From 7260b89c54536066bf97c17efd21fc525ee624e0 Mon Sep 17 00:00:00 2001 From: frei tycho Date: Mon, 6 May 2024 09:12:09 +0000 Subject: [PATCH 0001/2849] 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 f2737c7f6f2c2..ec37a3718d5e0 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 0a60adc333b0ba98afdc6c273fc3f13480b2e7a5 Mon Sep 17 00:00:00 2001 From: Jerzy Kasenberg Date: Wed, 17 Jan 2024 10:07:05 +0100 Subject: [PATCH 0002/2849] 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 50887e4b4531b..ad3db8f99525a 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 0398b2a3d95b4c907b90c083fb475921a87e0d09 Mon Sep 17 00:00:00 2001 From: Abderrahmane Jarmouni Date: Mon, 6 May 2024 09:32:52 +0200 Subject: [PATCH 0003/2849] 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 1051c8fc0d1da..00b433db20168 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 98342107fe33d3a864053b534cee7f4bbcc4910a Mon Sep 17 00:00:00 2001 From: Abderrahmane Jarmouni Date: Mon, 6 May 2024 09:43:32 +0200 Subject: [PATCH 0004/2849] 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 00b433db20168..cecd7ca9a25c8 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 3eec2a56d5a5a85bfff999033a9f4afac638722c Mon Sep 17 00:00:00 2001 From: Johann Fischer Date: Fri, 19 Apr 2024 10:18:58 +0200 Subject: [PATCH 0005/2849] 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 5f75fe97c4f92..325989dc7fdee 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 aeb4df1a3f09b..41c813a61b46d 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 69e3e3a90d67fc18793caa99fad1ef425fb1a254 Mon Sep 17 00:00:00 2001 From: Johann Fischer Date: Fri, 19 Apr 2024 15:05:05 +0200 Subject: [PATCH 0006/2849] 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 5100f1b90aefb..0277462b68d76 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 67db6f69f36e5538f212fb9bb2f86fa656b8464f Mon Sep 17 00:00:00 2001 From: Philippe Schumacher Date: Fri, 26 Apr 2024 11:23:23 +0200 Subject: [PATCH 0007/2849] 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 41bb3f0a5d4dd..20b64f91f4aba 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 dbb5a36855131..662329d168015 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 0d479a0091ca79394ab919dc3dbea37d3999d685 Mon Sep 17 00:00:00 2001 From: Nithin Ramesh Myliattil Date: Mon, 6 May 2024 08:23:05 +0200 Subject: [PATCH 0008/2849] 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 074af102863f0..ae6e3351e3079 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 d6db75640dd06031adf77b79b2852ce47620060a Mon Sep 17 00:00:00 2001 From: Chris Friedt Date: Sun, 5 May 2024 08:27:54 -0400 Subject: [PATCH 0009/2849] 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 2cc05b6df2585..7cd0f7e116092 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 2e36c898c9edf3fd708e2ae9815b033d4e8754a1 Mon Sep 17 00:00:00 2001 From: Fabio Baltieri Date: Fri, 26 Apr 2024 11:50:36 +0100 Subject: [PATCH 0010/2849] 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 5e62e6ee32e1a..53b0cd13233ee 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 d8476170bf542f615d670d9098819101fa971d32 Mon Sep 17 00:00:00 2001 From: Fabio Baltieri Date: Mon, 29 Apr 2024 10:48:46 +0100 Subject: [PATCH 0011/2849] 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 53b0cd13233ee..5681b33183322 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 61bb304c69b84b8cab0039db331546062e482f4f Mon Sep 17 00:00:00 2001 From: Abram Early Date: Thu, 4 Apr 2024 15:10:40 -0600 Subject: [PATCH 0012/2849] 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 a2e1803b13899..b46c709d8ef44 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 425dcc467868fce4f7cebcb8ad3c2506fdd564c1 Mon Sep 17 00:00:00 2001 From: Morten Priess Date: Fri, 23 Feb 2024 15:33:42 +0100 Subject: [PATCH 0013/2849] 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 129637fd6a820..7c8aadf5efa0d 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 c81d7d21e00e1..4038a04486ec6 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 aef8512e68e6f..fcc37fc52d873 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 807c2a7719561..bd312a5cf4b58 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 b8978e9efecd60ea2d3468c0e70ab4a0affacb0b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20S=C3=B8rensen?= Date: Tue, 5 Mar 2024 12:23:13 +0100 Subject: [PATCH 0014/2849] 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 9c131a6c9d46b..a4433e7e030cb 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 6ad1591bd4533..278f78530780a 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 98b996f6ec3433149269df57240b22946c475d32 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20S=C3=B8rensen?= Date: Tue, 5 Mar 2024 12:23:44 +0100 Subject: [PATCH 0015/2849] 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 0000000000000..2af48efc4d1d4 --- /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 9359fffcc2c7b9134da9a9fb1fbe93216776ac8b Mon Sep 17 00:00:00 2001 From: Emil Gydesen Date: Mon, 6 May 2024 12:01:05 +0200 Subject: [PATCH 0016/2849] 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 f1d8a75b0a7eb..147df7d96088d 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 05371a41f6e7d3b60850dd78321ded5bf4a35d88 Mon Sep 17 00:00:00 2001 From: Richard Wheatley Date: Tue, 7 May 2024 14:24:00 -0500 Subject: [PATCH 0017/2849] 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 a224512cd08dd..dc1cdda6a9be5 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 ff8a6d79e6013..3df717bf0e5ff 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 1caa52be5b43cc3f6b7c2224d415dc8cf5513a6e Mon Sep 17 00:00:00 2001 From: Richard Wheatley Date: Tue, 7 May 2024 14:24:45 -0500 Subject: [PATCH 0018/2849] 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 a3abd1093e936..68e692908f860 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 e9619c389892c8353b14d0bae9ee9b31f7f662f4 Mon Sep 17 00:00:00 2001 From: Richard Wheatley Date: Tue, 7 May 2024 14:25:03 -0500 Subject: [PATCH 0019/2849] 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 68e692908f860..aa95ff80c9adb 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 87070aae79ee648522321823b3dfc11833664717 Mon Sep 17 00:00:00 2001 From: Richard Wheatley Date: Tue, 7 May 2024 14:25:16 -0500 Subject: [PATCH 0020/2849] 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 19f7fa032af3a..5ff65e2ba351e 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 182adf42cd541..c8b0d5cbaf054 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 0000000000000..8fe8557ba7ed4 --- /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 32b69f53aa3af9a6efd366ac9dc0b1775609154d Mon Sep 17 00:00:00 2001 From: Richard Wheatley Date: Tue, 7 May 2024 14:25:52 -0500 Subject: [PATCH 0021/2849] 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 2d0efbe54242e..70a7507a4c175 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 0f835b51867f2d375c2cc4f189f31187dc6ed0af Mon Sep 17 00:00:00 2001 From: Henrik Brix Andersen Date: Tue, 30 Apr 2024 15:25:51 +0000 Subject: [PATCH 0022/2849] 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 d812e8933b1b7..cff8817c1eb91 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 5cbf7b1b9d13a39f36ad8dabfaeaec21d98cf5ff Mon Sep 17 00:00:00 2001 From: Alberto Escolar Piedras Date: Wed, 8 May 2024 09:00:58 +0200 Subject: [PATCH 0023/2849] 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 8f27eb0f8365d..a660f92af1772 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 30ce8b1b1854ce9ab9eb9eabfa80ecda6d37f5be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20Cab=C3=A9?= Date: Wed, 8 May 2024 09:59:43 +0200 Subject: [PATCH 0024/2849] 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 7c5f65bb74558..70cb0474a0274 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 5266680199f3f..7bfcccb492e81 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 e40e8fc8e3beb..0b6b6ab2e108a 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 1597f60e3b244..ff0a49549428d 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 fed776d365645..da76c4cc615a8 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 4029f1f2e85cb..752eb942fe41e 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 3d146de17f089..bc9ee006edc17 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 2c542982d9fb0..1e2e9ac4e111a 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 aa852d974bb1b..743e07689b6a5 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 506508bd90210..56a54f3005ab8 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 b81c942f2d63c..46c0bc0d9c548 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 8432e067adbf0..e102eec013b68 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 0785ba54abf0a..f93df2ef163ed 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 8c8fad5cdb44c..b56868ccdb7a1 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 a92743afdb536..df0eafe515813 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 56301a7beca2f..97c7cbefc35b0 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 997934cabb798..19adee0ebab2f 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 a9c290475deac..d171a4bdd6f9d 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 3bfb068b78656..b26614b75daaa 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 9a2d2377c6147..bf87ed50d23af 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 e5c505885bcf0..cf95a4317a03b 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 48e47a126212a..47bb84db553f2 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 528df6de763aa..2b66a42e5641d 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 68265dcabed1c..fca9bafdaffeb 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 555f11619b0ae..ce861f1d02df4 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 5d7216fc932761c26a404c2b45e86a4c91b743e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20Cab=C3=A9?= Date: Wed, 8 May 2024 10:00:02 +0200 Subject: [PATCH 0025/2849] 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 3fe44c92908f1..00fc9c41f11b3 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 e54a305e80f89..05d173826029b 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 c5b3c973b44e6..9718c20b39145 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 d23a1fdf1c1ef..90324568172c2 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 b70523cfadd37..bf1a77a2ac83d 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 e0fc28ff8be4e..cdb0999b23a96 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 378f6c0a8ecd1..731ebe828c3b4 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 2e4584d0a67dc..10e48a13348d0 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 2034ccd2c0fae..2dc1c7d0e891e 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 2537b7e09d7da..d8a064a179f5d 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 9072e80727b35..5fcbda2c8471e 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 b0605b6a7daf1dc2c21727927a89e665944860d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20Cab=C3=A9?= Date: Wed, 8 May 2024 10:00:15 +0200 Subject: [PATCH 0026/2849] 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 0af13d78c26c0..05820f8800f3f 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 d425f950a31ef..cfd0742469efc 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 de1fc9b8616fd..4d3b3b9cf31f9 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 0ea9be14f7a79..e3b57ae4f339f 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 a4c2b848c4899b984e95690f6ac85ccab87fa5b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20Cab=C3=A9?= Date: Wed, 8 May 2024 10:00:43 +0200 Subject: [PATCH 0027/2849] 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 b0c3b35c1aff0..e2011fd4cadd1 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 067e6168d9792..7db24bf51e2d7 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 bc1c4fb1d1c70..93859499e5977 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 dd42501a606d102c70a5092d0a4755fd31db87c1 Mon Sep 17 00:00:00 2001 From: Armando Visconti Date: Mon, 6 May 2024 14:47:39 +0200 Subject: [PATCH 0028/2849] 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 0a0f35258045e..a29b18e8fea17 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 da176f4f6923f..524cc6bd314c6 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 7602c4f386e5d0545e759821f3348da060345627 Mon Sep 17 00:00:00 2001 From: Nick Ward Date: Mon, 6 May 2024 18:02:15 +1000 Subject: [PATCH 0029/2849] 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 12caaac1378d2..45d0129841e30 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 48d7e95f7a752..7bb6b9c58cd86 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 3718b515bda0b3b173b59e30dea761b6fe690d81 Mon Sep 17 00:00:00 2001 From: Nick Ward Date: Mon, 6 May 2024 21:54:47 +1000 Subject: [PATCH 0030/2849] 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 9d38788118213..fcd94b1792bb7 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 5dea56e107a74..ac41a2ff2ee98 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 479e957b79c5d522a16844df51de8c81b556a025 Mon Sep 17 00:00:00 2001 From: Maciej Baczmanski Date: Wed, 24 Apr 2024 13:04:04 +0200 Subject: [PATCH 0031/2849] 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 ef71e411b4e1c..9673aa7702a08 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 e4ea597a778890c3f17de2c3612e8058e4a41e23 Mon Sep 17 00:00:00 2001 From: Rubin Gerritsen Date: Tue, 30 Apr 2024 13:12:55 +0200 Subject: [PATCH 0032/2849] 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 81bcd7ecc53de..4a966987bd1ba 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 dabc6c65cfef4..3074f9f35d1df 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 dabc6c65cfef4..3074f9f35d1df 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 a3660d178c5c95cdc3708e411b8efdd576ecfb3c Mon Sep 17 00:00:00 2001 From: Eran Gal Date: Thu, 25 Apr 2024 09:35:00 +0000 Subject: [PATCH 0033/2849] 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 4bbefcc5734e1..176a0d46c561d 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 35fc91c080dbaed2ae14f3df82aae09a37eee549 Mon Sep 17 00:00:00 2001 From: Aleksander Wasaznik Date: Thu, 18 Apr 2024 16:32:09 +0200 Subject: [PATCH 0034/2849] 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 b3da250ba1b02..59d232be3a4ca 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 0000000000000..71d844b76ee93 --- /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 0000000000000..555da337bf587 --- /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 ff0f485b17d58..06d5d718a9dca 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 0000000000000..d271c9c04fad3 --- /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 0000000000000..bc7928e349f52 --- /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 a55ebe13777769725d3c8d02d8b8d8a8f3a09fdf Mon Sep 17 00:00:00 2001 From: Rafael Laya Date: Thu, 4 Apr 2024 20:42:24 -0700 Subject: [PATCH 0035/2849] 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 73bb4b6cfe661..6bb2fc5c64df1 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 b064a2cfcc34327b1594e54811e7ba641253effd Mon Sep 17 00:00:00 2001 From: Peter Johanson Date: Fri, 1 Dec 2023 09:51:08 -0800 Subject: [PATCH 0036/2849] 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 5da08efd5b964..fd70895bc8040 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 0000000000000..14c8e5d043cb6 --- /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 d32a455570a3b5a36f1a467c5116c6b09c3d69c9 Mon Sep 17 00:00:00 2001 From: IBEN EL HADJ MESSAOUD Marwa Date: Mon, 6 May 2024 13:41:29 +0200 Subject: [PATCH 0037/2849] 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 5786fa21b0702..88c4ed94b282d 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 92e438d03a8cc..62b466defb4e4 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 ccf95e8773537ac2a807f5c01e2a5d05554cb558 Mon Sep 17 00:00:00 2001 From: Hake Huang Date: Fri, 29 Mar 2024 19:51:14 +0800 Subject: [PATCH 0038/2849] 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 85335491af693..5fd292fd4bc63 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 3d60d551c428906e2fd398aaff0089b8b69ccafb Mon Sep 17 00:00:00 2001 From: Stoyan Bogdanov Date: Wed, 28 Feb 2024 14:26:47 +0200 Subject: [PATCH 0039/2849] 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 0000000000000..02d1249cdd5aa --- /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 0000000000000..6188ce8c00447 --- /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 6f06b3c79450d082299e5fe5028b36d02b24a7a6 Mon Sep 17 00:00:00 2001 From: Stoyan Bogdanov Date: Wed, 28 Feb 2024 14:48:05 +0200 Subject: [PATCH 0040/2849] 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 0000000000000..a6696d780bfde --- /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 52c68f90c1897..a1b663867a5b1 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 1e6e6a228ff0ca635bf64067aab9001f4a3147c7 Mon Sep 17 00:00:00 2001 From: Kamil Piszczek Date: Mon, 29 Apr 2024 15:01:06 +0200 Subject: [PATCH 0041/2849] 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 02deaa7716124..3759402531326 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 37ac93b555d9b65f1166cc1f18936bc01dacc88d Mon Sep 17 00:00:00 2001 From: Pieter De Gendt Date: Wed, 8 May 2024 13:58:37 +0200 Subject: [PATCH 0042/2849] 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 95aeeb99e8933..5305f9cf873c2 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 5468569dabfcb4699374e0bb1224c4ff8ff1d478 Mon Sep 17 00:00:00 2001 From: Andrej Butok Date: Tue, 7 May 2024 14:40:10 +0200 Subject: [PATCH 0043/2849] 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 86cdff853d9b5..fa5862e5e008f 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 0ecfac663d4cb4593abee8e9353105f522ae49d2 Mon Sep 17 00:00:00 2001 From: Alberto Escolar Piedras Date: Mon, 6 May 2024 17:20:45 +0200 Subject: [PATCH 0044/2849] 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 8a961f34f8834..9f8395003a85c 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 75d112b85e2c8..4a4f78bc16612 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 76dc4903f5552..a15ead439534b 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 dede897035393d05dd1d14007a0af48114e2fa8d Mon Sep 17 00:00:00 2001 From: Alberto Escolar Piedras Date: Mon, 6 May 2024 17:27:39 +0200 Subject: [PATCH 0045/2849] 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 1fe3a98f8d754..4043d53e718a1 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 4ccfeb7669e08559e1477e20a73a48ff23571f42 Mon Sep 17 00:00:00 2001 From: Alberto Escolar Piedras Date: Tue, 7 May 2024 10:59:05 +0200 Subject: [PATCH 0046/2849] 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 4043d53e718a1..bd6af3c5d3c82 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 e2d9f09b70634e7cc222b6a6c3abdb7ef9f18ad6 Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Wed, 24 Apr 2024 16:09:42 +0000 Subject: [PATCH 0047/2849] 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 55911170d968f..7463cceefa3c4 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 32386d54274dc..07c96c55233ef 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 284147ba0006c..2b9a02845a7c5 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 d954060626ee4b5f7dcaaa1e684a4c6a8337768d Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Wed, 24 Apr 2024 16:10:51 +0000 Subject: [PATCH 0048/2849] 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 68efde1ab3026..025b0791010fe 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 37956465e18b9d9d1757282746c538502b6d6f48 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Thu, 2 May 2024 15:50:01 +0300 Subject: [PATCH 0049/2849] 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 35f1dcdc872f1..79a7989519bf8 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 c7dff045d7483..732b6a1160a8a 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 535d4b40a8e3462561b65757d6b710e0fe20125c Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Thu, 2 May 2024 17:25:16 +0300 Subject: [PATCH 0050/2849] 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 79a7989519bf8..17b354ca87807 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 4d4409b2ad731..b30d12b834eb7 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 61e8a36fa538a..de1c5ca4b9387 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 732b6a1160a8a..d735736589db8 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 0000000000000..f618b70e3b073 --- /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 adfcdc169d939..4a379cca1dd41 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 97caab6396393f4054e9e4ffaf0da004be0dca47 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Thu, 2 May 2024 17:52:56 +0300 Subject: [PATCH 0051/2849] 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 4a379cca1dd41..20f6ca6b1fe35 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 8960f13c4ff61e96c1e794d274ecc2ff85b6002e Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Fri, 3 May 2024 13:43:28 +0300 Subject: [PATCH 0052/2849] 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 1a0853891a020..33c300acaf04e 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 13118cf3c04ffcab248794ea86dedfa48cc18986 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Fri, 3 May 2024 13:45:36 +0300 Subject: [PATCH 0053/2849] 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 33c300acaf04e..dc0eaf36d185e 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 8f463285c2504..e29f2589bb744 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 dedd30e140b15ea44d83c794695a064546f2de3b Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Fri, 3 May 2024 13:47:11 +0300 Subject: [PATCH 0054/2849] 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 e29f2589bb744..83bd976d1cb28 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 3c9513e9ccdaa1646e99778161c7ebf1e9c55c6b Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Fri, 3 May 2024 13:49:40 +0300 Subject: [PATCH 0055/2849] 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 17b354ca87807..60cab000fe0e1 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 b78d8e93e3555..3df70b84a84a1 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 de1c5ca4b9387..557cc26d88333 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 a7f11b45b8ea0..e0402259faf42 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 d735736589db8..799485f537c25 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 b26139a79bb26..3948401057f78 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 f618b70e3b073..593a73526d7af 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 c9aac6efeb8e5f9b3d8f91ed57976b8d3cb084db Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Fri, 3 May 2024 13:52:52 +0300 Subject: [PATCH 0056/2849] 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 5b27e5ee7ca96..2a8d03ac9b28e 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 90104be01fa19..ca55f9692e34b 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 cc4cd1c548219..739635cf8a191 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 9e56f3332e7f2..3d13a55cbf29b 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 dac4499029d4d..be564ac4a541e 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 0000000000000..08cdfd1ee29f7 --- /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 85e9b0b274270b0547deeb55602b31808accdaef Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Fri, 3 May 2024 14:44:21 +0300 Subject: [PATCH 0057/2849] 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 83bd976d1cb28..9890571ff29ab 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 f9ac565f121a0a887befed8dc89462ec677c1178 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Fri, 3 May 2024 14:57:57 +0300 Subject: [PATCH 0058/2849] 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 56e705199e346..7e760024f7e13 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 ef7ddc07d3b5954817fdf0168fbb5ef0d3e1cf53 Mon Sep 17 00:00:00 2001 From: Morten Priess Date: Mon, 6 May 2024 12:50:11 +0200 Subject: [PATCH 0059/2849] 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 9613dc8ebb262..7828dfdf65abd 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 9f2fc3d0c95c0..653aa304b070b 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 b1a3798c1a191..094ba62f85305 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 f61b5b6b0fbae..c8f12876620f1 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 ef3950805b344..7383478d1763b 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 4d39057676388..25ca59bc44f68 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 a8498e3682cc1..36763a7c0f7f5 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 cecaefef333da..0917e594edfb8 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 bd312a5cf4b58..f6c68436b5eb0 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 ad2745471c8d63bed8da969925a24593e11a3c74 Mon Sep 17 00:00:00 2001 From: Chekhov Ma Date: Wed, 8 May 2024 15:55:52 +0800 Subject: [PATCH 0060/2849] 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 655de8340d79e..787a10d7dd5d4 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 45d0129841e30..9ce2b7f5859f9 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 0000000000000..d531f858f1d27 --- /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 0000000000000..0a1da5e63f4aa --- /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 bcd9b190e1563..fa6ab5ddceda0 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 b487c3556b00e..c384249daed3e 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 0000000000000..e08f119a72cbc --- /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 0000000000000..d57b82035dca4 --- /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 0192e62a3502b..defcb2dc32687 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 0000000000000..bb27d2facb61e --- /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 0000000000000..9d2456b6a83b5 --- /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 0000000000000..abac20bcd51b1 --- /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 bb0743def2ac45bfa60405984302de8a0fbb8020 Mon Sep 17 00:00:00 2001 From: Chekhov Ma Date: Mon, 22 Apr 2024 10:45:09 +0800 Subject: [PATCH 0061/2849] 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 6cd176d0ce358..40faba8411719 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 6551e6f5baea82cbf7f98cb5bbf5ca5c3c7a901f Mon Sep 17 00:00:00 2001 From: Robert Lubos Date: Mon, 15 May 2023 11:43:27 +0200 Subject: [PATCH 0062/2849] 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 17588b17fd1f3..e6fd07e47e28f 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 7c0a2ba74f256..85eafd0eedb33 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 f003087e38521cc51cce978ec4740ee03a858c0e Mon Sep 17 00:00:00 2001 From: Robert Lubos Date: Wed, 24 Apr 2024 13:48:51 +0200 Subject: [PATCH 0063/2849] 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 1ab45c3ef6dbd..90d38919cdad8 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 7e2f06cbc2ece100cc1d8d950da523a64832a23f Mon Sep 17 00:00:00 2001 From: Valerio Setti Date: Mon, 22 Apr 2024 11:57:08 +0200 Subject: [PATCH 0064/2849] 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 daaee438a38c7..dab5ef4215d99 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 0000000000000..35200a9d2f4f2 --- /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 18be5b4119ebb..d33b2de0e4b1a 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 34c4b544734950080dc2d849e5f870413e345ac0 Mon Sep 17 00:00:00 2001 From: Valerio Setti Date: Tue, 23 Apr 2024 07:24:55 +0200 Subject: [PATCH 0065/2849] 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 58ec0949d474f..760a3ce6757b2 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 2013c5d52fb78..c85b35452b809 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 2e2484b9df7c90cf8c97981d2ce748eb84453644 Mon Sep 17 00:00:00 2001 From: Valerio Setti Date: Mon, 6 May 2024 18:10:39 +0200 Subject: [PATCH 0066/2849] 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 042a59405a8e1..77e3ac8f28398 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 e6281c9d21dddca9bb1e698e1374e9927638708c Mon Sep 17 00:00:00 2001 From: Valerio Setti Date: Tue, 7 May 2024 13:19:49 +0200 Subject: [PATCH 0067/2849] 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 c85b35452b809..95c41984de2f5 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 b25f322b732809a6abb4b2119221226a1189f700 Mon Sep 17 00:00:00 2001 From: Valerio Setti Date: Mon, 22 Apr 2024 16:51:01 +0200 Subject: [PATCH 0068/2849] 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 8e5f7abf65222..3fedc2563504f 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 a364fc8a41d21595646e6fbd0b16e2e2fd4157b0 Mon Sep 17 00:00:00 2001 From: Valerio Setti Date: Wed, 24 Apr 2024 16:22:31 +0200 Subject: [PATCH 0069/2849] 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 d75abd64be2f0..b55111a5599c7 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 d33b2de0e4b1a..6febce2c60db0 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 28a6a40fdc545..78602e497e389 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 d068982005ff2e75a630ffd0a8077d6e27e9547a Mon Sep 17 00:00:00 2001 From: Valerio Setti Date: Mon, 22 Apr 2024 11:57:48 +0200 Subject: [PATCH 0070/2849] 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 e7d45f46c7a6c..9df87e31b6099 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 3fedc2563504f..0c747449f85ec 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 a58f8eb3edbd05f564c0d13aa8edd00e07faee20 Mon Sep 17 00:00:00 2001 From: Valerio Setti Date: Tue, 30 Apr 2024 16:14:23 +0200 Subject: [PATCH 0071/2849] 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 9b6af503e038e..dd5e629e16a40 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 9d5021befdbeffa040c878ffc962d9feee651355 Mon Sep 17 00:00:00 2001 From: Valerio Setti Date: Thu, 2 May 2024 12:56:12 +0200 Subject: [PATCH 0072/2849] 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 6febce2c60db0..383ab44f18b04 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 f539b661d6011f44297137a11a6fd2e1573bf8d2 Mon Sep 17 00:00:00 2001 From: Valerio Setti Date: Thu, 2 May 2024 15:54:56 +0200 Subject: [PATCH 0073/2849] 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 b55111a5599c7..5087213bb27ec 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 383ab44f18b04..92ab1f66edb76 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 a7ac8db8f2e14..f308a5aefaf5b 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 88fccf0961cf5..74e377569b338 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 012c9a28470fbf9b36fa6df21e02597f08c02553 Mon Sep 17 00:00:00 2001 From: David Schneider Date: Tue, 7 May 2024 15:14:31 +0200 Subject: [PATCH 0074/2849] 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 dc65b683118df..1dcc3dc729ac3 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 ed12a0cc35aaf30c1915526f23cbec3af86ff410 Mon Sep 17 00:00:00 2001 From: Hess Nathan Date: Tue, 7 May 2024 08:53:44 +0200 Subject: [PATCH 0075/2849] 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 0ffcdc875b4e3..2d739d7a233ed 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 736a9742af96b..a9ff5518b2fd3 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 e7e91fed93fd3..3bf6fca6c43b8 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 2fb0f141125b0..dde98c0b07fa8 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 fd56131d7dc1b..254d6d9dda341 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 cd4c8ccd7a07f..52ad585b79c13 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 1fe3417901ee9..9641ab250003c 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 751786d5a4c99..66a00a452a7ad 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 39d7cde6f8f52..b0fe24c6bf617 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 618aa6b2c20b1..968d2a436bc55 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 3807b3b103b2c..50b5dd58f5d72 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 5540cebce7061..8591e0a8ba445 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 29e336297717f..76036b32c705f 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 dc33d6fd5f050..d4da8366cf22f 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 ad36a22eb771e..8e3e02a67ced1 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 d7ff2f2cad2db..04aef8157558b 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 8704a23cd7fb95d7951b8c8f2d1bd4d8c13edb60 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Mon, 6 May 2024 17:40:40 +0200 Subject: [PATCH 0076/2849] 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 92ddab5258e8d..2a677470f6666 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 0000000000000..018c11af6faa0 --- /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 0000000000000..e9ed12997bc77 --- /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 2833caa2ad031..f5e608d891285 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 fae32ac0b8040649c77f8095de04b61d46ab6393 Mon Sep 17 00:00:00 2001 From: Ali Hozhabri Date: Mon, 6 May 2024 16:22:06 +0200 Subject: [PATCH 0077/2849] 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 8da9936888eef..d45dbb592a1e8 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 c09f1ec91ac2ee0533948c059f5725ad36c2a4d9 Mon Sep 17 00:00:00 2001 From: Abderrahmane Jarmouni Date: Fri, 3 May 2024 00:17:49 +0200 Subject: [PATCH 0078/2849] 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 128586a4a0a43..cab26b1eeeab8 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 6c244cf440bef54ef157b4bf65a328c9e34df843 Mon Sep 17 00:00:00 2001 From: "Mike J. Chen" Date: Fri, 26 Apr 2024 14:40:17 -0700 Subject: [PATCH 0079/2849] 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 f9d61431cc966..508a029790faa 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 f4c067c6bcf0fa63b2f52d3dfb4879d73815b9fc Mon Sep 17 00:00:00 2001 From: Sateesh Kotapati Date: Mon, 8 Apr 2024 17:46:41 +0530 Subject: [PATCH 0080/2849] 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 3617191ed5b2c..ffa883da6f9e6 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 2b803cca1abb0..522d945ce5afc 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 3df717bf0e5ff..94d555e9f169c 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 2f17c46fb11a17482c0c1cb6d5f59b6ec825f6ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20G=C5=82=C4=85b?= Date: Tue, 7 May 2024 12:49:27 +0200 Subject: [PATCH 0081/2849] 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 6ecde2cfdb103..107aa0be67f41 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 b199f65385f3f..32375faf481cf 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 2967fe8648901..61f42d8ff3167 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 57b4dba828c7f..706c2621bbb63 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 9d011019f4afe..1cfa3dddb553a 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 2a62845dc8917..e4a7469dac553 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 4a4f78bc16612..5671ac699a4cc 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 07c96c55233ef..549abb138fbec 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 2b9a02845a7c5..a54866252a5cc 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 db6c51568f42a..a6d730804b824 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 f9db3f4db1458..9dfd1e409c89e 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 48ee6fcae0571681ec5f892616e90679eae8c104 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20G=C5=82=C4=85b?= Date: Tue, 7 May 2024 13:28:29 +0200 Subject: [PATCH 0082/2849] 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 0000000000000..d540137dadb48 --- /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 0000000000000..7793fed2b8e96 --- /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 fc453ba3b321c..65569ad30a431 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 c408d2f8f1d2c..4fdbfaa1a4c2d 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 bb30a5d0846efdc259257b853b9fc5dd9d96b958 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20G=C5=82=C4=85b?= Date: Wed, 8 May 2024 09:46:37 +0200 Subject: [PATCH 0083/2849] 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 107aa0be67f41..198f4db403b38 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 32375faf481cf..68d169331ef83 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 fe4f101a99e7535eb3b378f876462f658c36d5c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C4=99drzej=20Ciupis?= Date: Tue, 7 May 2024 12:56:02 +0200 Subject: [PATCH 0084/2849] 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 b2629eef67b76..6df811f6badb6 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 d191c13f0d3fdc08e17ec51a57dd05c759de4b2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C4=99drzej=20Ciupis?= Date: Tue, 7 May 2024 13:04:51 +0200 Subject: [PATCH 0085/2849] 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 c4f3946731434..49c0e5a1c730e 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 3d08a5dd4cd6f..f9082e6ca4006 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 3b85d55dfd071..dadba8c0f54a8 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 491808f236a22..67059bd4ee895 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 cd8281cb2bf25..bf0626ce30b2e 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 64e335869fb59..9596b3453be20 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 ec4567274c40d..31b8bf5a75e5a 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 81e4b91bb533e6540c8227c437ce306942c85591 Mon Sep 17 00:00:00 2001 From: frei tycho Date: Mon, 6 May 2024 13:54:05 +0000 Subject: [PATCH 0086/2849] 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 f90a54ec3fb31..a3960064029b5 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 015a6ff50a26e..56d0701e79bb0 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 3769648793b82a7f18d3d652207d14e38cf63c41 Mon Sep 17 00:00:00 2001 From: Bjarki Arge Andreasen Date: Fri, 3 May 2024 10:33:18 +0200 Subject: [PATCH 0087/2849] 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 77631bcb9710a..05192ca5400eb 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 98602d4194997..94aaf7a02ba84 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 0000000000000..9ae9a40647284 --- /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 0000000000000..553736f0ba721 --- /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 0000000000000..eb7d9eec8acc3 --- /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 fdda93fd99dec507ed0ee2434fbe6738282ef46a Mon Sep 17 00:00:00 2001 From: Bjarki Arge Andreasen Date: Fri, 3 May 2024 09:49:48 +0200 Subject: [PATCH 0088/2849] 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 0000000000000..50762c4105938 --- /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 0000000000000..34238dcdf71cf --- /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 0000000000000..bfb63abec375d --- /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 0000000000000..246e94631a80f --- /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 0000000000000..35ceec38dc3bb --- /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 0000000000000..c07843b58f653 --- /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 0000000000000..15439f5d9f376 --- /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 0000000000000..7ce2c22de3efb --- /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 2d0b24bff27733c2c473c6401c9b2ea87bc3105f Mon Sep 17 00:00:00 2001 From: Bjarki Arge Andreasen Date: Fri, 3 May 2024 10:09:58 +0200 Subject: [PATCH 0089/2849] 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 0000000000000..58a3450defba7 --- /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 0000000000000..c81955df1acc9 --- /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 0000000000000..58a3450defba7 --- /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 0000000000000..c81955df1acc9 --- /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 0000000000000..58a3450defba7 --- /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 0000000000000..c81955df1acc9 --- /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 0000000000000..b1cf5b22cbef1 --- /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 0000000000000..c81955df1acc9 --- /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 d2e5eeb51d3364585c2fec13d5f44784e06da53e Mon Sep 17 00:00:00 2001 From: Robert Hancock Date: Wed, 7 Feb 2024 12:16:31 -0600 Subject: [PATCH 0090/2849] 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 e80317664b974..5384977b614fc 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 d1687a557cdc32176ff1368c9313906ee77f639c Mon Sep 17 00:00:00 2001 From: Mayank Mahajan Date: Thu, 2 May 2024 08:55:16 +0530 Subject: [PATCH 0091/2849] 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 6fae283ad4b67..4af7aa8996d06 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 d3b5569815911..02c5a6e9780fe 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 0000000000000..fd0e774e908e1 --- /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 0000000000000..f0e9cc75beeca --- /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 0000000000000..5f46b0322f064 --- /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 0000000000000..0752e2902d573 --- /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 0000000000000..9efd704eb9da4 --- /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 eb5a0e973789d..5de1f832802d5 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 68ea73aca2c0b245af808e5f92eff60d7919b4e6 Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Sat, 27 Apr 2024 21:56:17 -0700 Subject: [PATCH 0092/2849] 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 c3c8055d0de9d..52f1e0c1b0ab8 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 cbbb64a3aa299d241a7f82cb313348a6d65ba35e Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Fri, 26 Apr 2024 16:47:55 -0700 Subject: [PATCH 0093/2849] 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 24e3ba6514e9c..b4d384e6bb0ee 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 7a2a4ff6ec9e33325c37b724121990ad3080be5a Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Wed, 8 May 2024 21:02:19 +0200 Subject: [PATCH 0094/2849] 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 19baeade7dcd3..c6ece4e4b8ce0 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 8e63e0657b79640156c4a850e2b37f7add5a40a6 Mon Sep 17 00:00:00 2001 From: Grzegorz Swiderski Date: Tue, 16 Apr 2024 10:46:32 +0200 Subject: [PATCH 0095/2849] 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 3614d80870fa0..f1077dbc4f0e9 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 df72cdb977b09..1ba620473a08d 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 8212215779cbcceefd65312207a9d492e7c4a295 Mon Sep 17 00:00:00 2001 From: Grzegorz Swiderski Date: Tue, 16 Apr 2024 10:46:32 +0200 Subject: [PATCH 0096/2849] 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 1ba620473a08d..ce5af2e25af90 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 f7d6880fce0c86a32be5a1aa85fa626746ea81cc Mon Sep 17 00:00:00 2001 From: Grzegorz Swiderski Date: Tue, 16 Apr 2024 10:46:32 +0200 Subject: [PATCH 0097/2849] 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 9dfd1e409c89e..4fca3501e27a4 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 d33bf33b6661f20a06aef8d27f7c4ac277d82546 Mon Sep 17 00:00:00 2001 From: Dinesh Kumar K Date: Thu, 30 Mar 2023 15:16:07 +0530 Subject: [PATCH 0098/2849] 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 028b591940722..0715771916c3a 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 476a3982af04c31a4308aac36cb6520f85090f29 Mon Sep 17 00:00:00 2001 From: Dinesh Kumar K Date: Thu, 7 Sep 2023 15:30:42 +0530 Subject: [PATCH 0099/2849] 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 0715771916c3a..8a822c08da7ca 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 63c48bba91d92e6ab4c2465cf182595e600be600 Mon Sep 17 00:00:00 2001 From: Dinesh Kumar K Date: Thu, 7 Sep 2023 15:35:30 +0530 Subject: [PATCH 0100/2849] 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 8a822c08da7ca..5445c981b0808 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 378034c66a4883aea278a612ccc0ff26e024f4d5 Mon Sep 17 00:00:00 2001 From: Dinesh Kumar K Date: Fri, 15 Sep 2023 09:49:33 +0530 Subject: [PATCH 0101/2849] 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 5445c981b0808..0047f94da6a86 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 c8374fb17d3dd..f61e7edab071d 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 e57c6f9d2b0eae9c470a79eb5f5d18a6e637fe31 Mon Sep 17 00:00:00 2001 From: Dinesh Kumar K Date: Mon, 29 May 2023 00:38:23 +0530 Subject: [PATCH 0102/2849] 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 0047f94da6a86..69b66ee5cb801 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 f61e7edab071d..00044359a0bad 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 8b0db47188d35..fafcfd7855995 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 583d1ed3f6fad..573a03aa5fb71 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 3c8bd0bc2bd8198111956c9e52bfca22919ac81c Mon Sep 17 00:00:00 2001 From: Dinesh Kumar K Date: Fri, 7 Apr 2023 18:36:41 +0530 Subject: [PATCH 0103/2849] 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 69b66ee5cb801..5a8be3a7fca30 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 00044359a0bad..9e26f86360129 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 fafcfd7855995..37bbeb486b42c 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 2fa0bb3197f77..7add14e5350cb 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 0f507ebe69d09..360ccc6182a25 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 573a03aa5fb71..a11332b469eff 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 b63fe1c3687e397925e002462ede399a37ffb925 Mon Sep 17 00:00:00 2001 From: Dinesh Kumar K Date: Wed, 5 Apr 2023 21:10:33 +0530 Subject: [PATCH 0104/2849] 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 5a8be3a7fca30..caffa067ff892 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 9e26f86360129..78db4913fc129 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 7ae0158e3507bc24c7399f93f7bc220cf9690fe8 Mon Sep 17 00:00:00 2001 From: Dinesh Kumar K Date: Mon, 10 Apr 2023 14:50:55 +0530 Subject: [PATCH 0105/2849] 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 53c31f3c80407..35297b90b655f 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 caffa067ff892..a92477d2d98c5 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 78db4913fc129..72130525ce136 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 37bbeb486b42c..4a9cd7fc372d1 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 360ccc6182a25..5727d4c0ceb78 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 a11332b469eff..da8923e1fc27b 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 e08ce0ed7112bbaca5f4be33ec51fc5935a3b538 Mon Sep 17 00:00:00 2001 From: Dinesh Kumar K Date: Mon, 10 Apr 2023 22:57:41 +0530 Subject: [PATCH 0106/2849] 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 a92477d2d98c5..8bd073655bab0 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 72130525ce136..154693f5701bf 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 4a9cd7fc372d1..81ee68ca71464 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 6a746dc01294f3d4acd2b46c02fd36f92b59fe4a Mon Sep 17 00:00:00 2001 From: Dinesh Kumar K Date: Tue, 25 Apr 2023 15:20:58 +0530 Subject: [PATCH 0107/2849] 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 8bd073655bab0..15714314b95f4 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 5e60656aebc587f6410bb27be1384ab85d9ff2c5 Mon Sep 17 00:00:00 2001 From: Dinesh Kumar K Date: Wed, 1 May 2024 16:09:56 +0530 Subject: [PATCH 0108/2849] 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 032be38bfff67..06de5aabec575 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 a495fd9475e324b453a02b543d917e0816cfce3a Mon Sep 17 00:00:00 2001 From: Hao Luo Date: Thu, 9 May 2024 15:54:43 +0800 Subject: [PATCH 0109/2849] 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 147df7d96088d..0fdc29b6485d4 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 c81d95b9ae355ed16e69d134ec23d3c2de4d0a4f Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Thu, 9 May 2024 20:06:02 -0400 Subject: [PATCH 0110/2849] 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 55ab1a2e4a047..12bf20f5685b7 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 37c49f2af912c0f69bfaea26e25bc0b5e637b062 Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Wed, 8 May 2024 08:20:47 +0100 Subject: [PATCH 0111/2849] 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 25cee4381b72f..dd93a355e9333 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 274aaddf1ec66..c7abe79ffd428 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 c0813ef1f21d7a2370a722ba8c179f2d2d54de0d Mon Sep 17 00:00:00 2001 From: Jordan Yates Date: Wed, 8 May 2024 15:32:48 +1000 Subject: [PATCH 0112/2849] 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 556f5b359baa4..26ffefec997a8 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 796fc9d54fd857c84aa71b964e9036e934adbdf0 Mon Sep 17 00:00:00 2001 From: cyliang tw Date: Tue, 7 May 2024 20:14:13 +0800 Subject: [PATCH 0113/2849] 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 3a1c8ad8eeefd..c88e0d498ce5f 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 2ec7a46d0fb2730682ba25d5ca9d494000399ef8 Mon Sep 17 00:00:00 2001 From: Aleksander Wasaznik Date: Wed, 10 Apr 2024 21:37:51 +0200 Subject: [PATCH 0114/2849] 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 4659f946f92c8..9d83e1f92764b 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 cdc76933836e9b367cc51f6a9045bca00ffccdfa Mon Sep 17 00:00:00 2001 From: Luis Ubieda Date: Thu, 9 May 2024 15:43:08 -0400 Subject: [PATCH 0115/2849] 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 739e9809ff302..3992897d90f29 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 7f5a481ec742a439892a7eb0a12c5b10e2c3413d Mon Sep 17 00:00:00 2001 From: Konrad Derda Date: Wed, 8 May 2024 10:59:48 +0200 Subject: [PATCH 0116/2849] 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 25f7b42bdafb9..554e0103e02aa 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 9074c07ae73f6f45a0c821a6ae2df8f2ac0fbab3 Mon Sep 17 00:00:00 2001 From: Konrad Derda Date: Wed, 8 May 2024 10:44:18 +0200 Subject: [PATCH 0117/2849] 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 554e0103e02aa..75644c2ca5801 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 d2012a17b4c49..09f71c5b179bb 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 d397aae027f59f3335453115e28519e5e1aa2dc1 Mon Sep 17 00:00:00 2001 From: Konrad Derda Date: Wed, 8 May 2024 10:49:47 +0200 Subject: [PATCH 0118/2849] 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 c780d20d8e516..abfaca57a3072 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 7f82b6a2199f16892701f7df70130e3c6ea4b3a5 Mon Sep 17 00:00:00 2001 From: Morten Priess Date: Mon, 6 May 2024 16:08:42 +0200 Subject: [PATCH 0119/2849] 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 f4133b9af8de1..b5bbec9af84dd 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 7374678d5177fe222897dcb9d83ac60fd96b8fa8 Mon Sep 17 00:00:00 2001 From: Daniel DeGrasse Date: Fri, 26 Apr 2024 23:25:16 +0000 Subject: [PATCH 0120/2849] 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 ac50cfa8b76f3..e7ab7ce896b55 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 564164c5ae414..9c44e8d874e85 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 d371a0f9ad9426290617e106bf3754a8334b11f5 Mon Sep 17 00:00:00 2001 From: "Mike J. Chen" Date: Fri, 26 Apr 2024 14:28:58 -0700 Subject: [PATCH 0121/2849] 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 508a029790faa..ba0c29e34b803 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 8c5c6dad44c25e53d4e9fde06fcb3d172ae87cd5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Chru=C5=9Bci=C5=84ski?= Date: Thu, 18 Apr 2024 10:50:57 +0200 Subject: [PATCH 0122/2849] 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 0000000000000..d442c11226228 --- /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 0000000000000..f65b4dd3b0ba0 --- /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 0000000000000..88c288a452898 --- /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 b1020b0bc8b9588ebfb70bba4df4634a609ac828 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Chru=C5=9Bci=C5=84ski?= Date: Fri, 10 May 2024 10:34:43 +0200 Subject: [PATCH 0123/2849] 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 0000000000000..181611f712d29 --- /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 0000000000000..f65b4dd3b0ba0 --- /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 0000000000000..f7f44e2dc4363 --- /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 af78efaa4d2cccce81dd18f0bac651c642f1e615 Mon Sep 17 00:00:00 2001 From: Yong Cong Sin Date: Mon, 26 Feb 2024 21:27:10 +0800 Subject: [PATCH 0124/2849] 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 79e6c269c7ce6..e9b767f587720 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 7c7c8ee57a6ff..0000000000000 --- 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 1cfdde31e137d..0000000000000 --- 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 1cfdde31e137d..0000000000000 --- 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 1cfdde31e137d..0000000000000 --- 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 49281301178ac..0000000000000 --- 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 ff9e44d289f2b..0000000000000 --- 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 ff9e44d289f2b..0000000000000 --- 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 bb6a719084b57..0000000000000 --- 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 1cfdde31e137d..0000000000000 --- a/subsys/testsuite/ztest/include/zephyr/syscalls/sys_clock.h +++ /dev/null @@ -1,3 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - */ From 2e072ad017cf41673e7f5a7ff44aebb4624e4ee7 Mon Sep 17 00:00:00 2001 From: Yong Cong Sin Date: Thu, 11 Apr 2024 17:23:50 +0800 Subject: [PATCH 0125/2849] 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 e9b767f587720..892358999cfc4 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 e1e78a5f08a9219e59fda115d1fb30984ce8b877 Mon Sep 17 00:00:00 2001 From: Richard Wheatley Date: Thu, 9 May 2024 13:38:10 -0500 Subject: [PATCH 0126/2849] 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 1aa0fbf75d4b2..205da184346bf 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 2e7d91141be9c..60707d59a6199 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 703201410dec5..b3bab9c82afb0 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 0000000000000..80bcf62763ad5 --- /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 24aaf1189cd75..b329d117c8979 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 94d555e9f169c..55bfac7ae334c 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 6d4ed7e192dcba9ba704e589aeadc68bb8eac252 Mon Sep 17 00:00:00 2001 From: Aaron Ye Date: Thu, 1 Feb 2024 17:17:04 +0800 Subject: [PATCH 0127/2849] 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 cc84c0faf39f1..5ce028bba9664 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 fdc852c04ca8c..30ce852404510 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 e32c2ee2968599e893172a0221bab7d4bde3632b Mon Sep 17 00:00:00 2001 From: Aaron Ye Date: Wed, 8 May 2024 15:26:02 +0800 Subject: [PATCH 0128/2849] 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 181495a303825..78bba84b8524a 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 46894814dbe42..910fca95567f9 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 1f151efc9a1ab..f863ee14ba81c 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 a95b7e6945b35..988e5b48a7fa0 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 3997479b49dbdbd999f87c072cfbf8e039a44075 Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Wed, 8 May 2024 14:24:04 +0200 Subject: [PATCH 0129/2849] 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 7429547ee410d..b373ab5bd911c 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 f1ebf0c7d3eb7..cbcbf4ea503be 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 89955b7061487..68119724f1893 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 36e062a0ad915..4fecb50de1a00 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 20b73b5b1d670..a7251748cca3a 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 7f1e0d01f7056..ec0a5e8ceabbb 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 2c6306d09954de13f993ebc28e173246b9b6ef39 Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Mon, 6 May 2024 12:54:28 +0200 Subject: [PATCH 0130/2849] 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 c73ff9c3ea9b8..3711a34921368 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 0000000000000..320c5c352b116 --- /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 0cdbb7a501cd1..455ff8fcb0001 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 7fd4d377b1d76..27f7b9b80ea20 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 18606ee3a67f2..040e1db6b4f17 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 823343bc3f65d..3377273dd9ab6 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 22d7f2e726dbb..05645663bc442 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 c6e0172b69460..56e80860f326b 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 3272d896ca62c..b72aaa624f1a7 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 3774532c42415..8d6dbdd87b016 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 a5f8b3cc1c5bf..19264a9d041af 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 10fb481688c62..92bde54d7a0c7 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 c73ff9c3ea9b8..3711a34921368 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 3c7c698c48b8c..0000000000000 --- 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 57d674179ff93..0000000000000 --- 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 57d674179ff93..0000000000000 --- 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 3c7c698c48b8c..0000000000000 --- 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 57d674179ff93..0000000000000 --- 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 1c29b28e2ddaf..755e7fafa786f 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 3c7c698c48b8c..0000000000000 --- 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 1499e379d4e22..8c6d99253a6b8 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 68119724f1893..cce7208b48cf0 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 4a966987bd1ba..6d031c446224a 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 4fecb50de1a00..d051150a26b64 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 1eb2d86a1c3d1..15e4eacd966d8 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 1afbca08502e0..90e5924bf6cb5 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 d1a1b8cd16118..78ef925ce07c4 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 02e2f3168db97..afa1f5958614c 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 9cf785bc92595..2f0f9ccc86d33 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 a4d3c3e8c5f8e..c124cbd223eb9 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 d410216659ac4..5119ac0d3eddb 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 76559f27fd6e9219516c9ee7deebbdf5b3116105 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20Battrel?= Date: Tue, 7 May 2024 13:14:59 +0200 Subject: [PATCH 0131/2849] 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 d0737cd85fd4c..b0429fe3b6d64 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 69cdadd9c4d31..618dc6b758606 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 e518903cba2c3..f9f10d5ccabee 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 313f94e776281..35267739edd16 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 28bdcbd3c5e683e04b0ab4db0c3c29d71a16dcc2 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Mon, 6 May 2024 11:46:05 +0300 Subject: [PATCH 0132/2849] 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 cf9cc600d5cf5..e3e32eba4af1f 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 3502b71386fb2fe9a0e60684dcce46889c89aa5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mo=C5=84?= Date: Fri, 10 May 2024 12:10:29 +0200 Subject: [PATCH 0133/2849] 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 d4ffa23706447..a19d2d33f10f9 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 673b9cde818bb2eadffe27403421a361f83e102e Mon Sep 17 00:00:00 2001 From: Marcin Szymczyk Date: Fri, 10 May 2024 12:21:43 +0200 Subject: [PATCH 0134/2849] 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 0fdc29b6485d4..42e70bdb0b607 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 bcbe71362027a0168efccb0b1f002e3716645055 Mon Sep 17 00:00:00 2001 From: Reto Schneider Date: Wed, 1 May 2024 14:34:58 +0200 Subject: [PATCH 0135/2849] 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 c938ff18385a3..31cd058f60fbf 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 215cdb65dfb944a7fce0e7797cbc344a75e68505 Mon Sep 17 00:00:00 2001 From: Luis Ubieda Date: Thu, 9 May 2024 12:59:42 -0400 Subject: [PATCH 0136/2849] 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 0a43acc4f6242..7fd90c3b89da1 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 0ba6a208965cfaba67abdd5fe1daa0a616072b5b Mon Sep 17 00:00:00 2001 From: Robert Lubos Date: Wed, 8 May 2024 16:47:57 +0200 Subject: [PATCH 0137/2849] 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 8f7996a93bdb2..b93369e62ce33 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 8cc5193437ce4711ef40c25b26bc4f0aea451528 Mon Sep 17 00:00:00 2001 From: Robert Lubos Date: Tue, 7 May 2024 14:09:31 +0200 Subject: [PATCH 0138/2849] 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 efdd78edf6ee5..3e51539b4b7eb 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 60cab000fe0e1..9ebcb48404348 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 cb51bd007aca184226b4711864dca3ffee4294e8 Mon Sep 17 00:00:00 2001 From: Robert Lubos Date: Tue, 7 May 2024 14:33:38 +0200 Subject: [PATCH 0139/2849] 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 9ebcb48404348..5731ae622c7d1 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 811386ef3abfebaab52a3274edc7bcf5a2818874 Mon Sep 17 00:00:00 2001 From: Robert Lubos Date: Tue, 7 May 2024 14:13:37 +0200 Subject: [PATCH 0140/2849] 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 5731ae622c7d1..c11dc8b2caa43 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 2f17b5022f7cd..334444420b983 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 7b55805a3eff4b53f53234908bed763a1e6943af Mon Sep 17 00:00:00 2001 From: Robert Lubos Date: Tue, 7 May 2024 13:24:04 +0200 Subject: [PATCH 0141/2849] 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 d32748e77fae5..fa7876d841115 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 0000000000000..362d19ac37486 --- /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 aea485b74aa6d..57aeaae8d021a 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 fdcc73753a280..73876449c88fa 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 855c36d068a29..d360ae45edfae 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 739635cf8a191..8e6740a6348d7 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 1da6e57342785c87c686cd37575059725d8b9469 Mon Sep 17 00:00:00 2001 From: Dmitrii Golovanov Date: Wed, 8 May 2024 12:39:32 +0200 Subject: [PATCH 0142/2849] 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 e03d754ee8c29..254f2497d7434 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 e05c4a8786a041c4ebede9670288d697127e0b89 Mon Sep 17 00:00:00 2001 From: Hess Nathan Date: Tue, 7 May 2024 13:22:50 +0200 Subject: [PATCH 0143/2849] 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 6124ada5140f8..4b19d247c0099 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 590852e4e3706..4afb828f4a7fc 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 de5c6656165a6..7ef2c1fa02287 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 52f1e0c1b0ab8..0a8b861cfbec5 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 adebb2d68e80f..5ddc4178f89df 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 e11e53087d0dc..dfd5eb7bdd698 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 a60f2c76dad7d..fed8f3a983c5f 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 a26c50828d76c..da4053b4bdbda 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 a6ededcc9f93f28b59f0d0850b84f77a9baf7f47 Mon Sep 17 00:00:00 2001 From: Adam Matus Date: Fri, 10 May 2024 13:32:32 +0200 Subject: [PATCH 0144/2849] 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 3c39008965c47..61a49bde39af7 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 21392e734547c..a798edd853775 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 7958f80b37306..659107df16438 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 548a0a55f10f2..daf2cf21d01f1 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 684a28656e1ffb357547bc01bd1169aa27449840 Mon Sep 17 00:00:00 2001 From: Adam Matus Date: Fri, 10 May 2024 13:37:21 +0200 Subject: [PATCH 0145/2849] 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 a629048330090..21ce74bb33b7d 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 72d406e980296..1b97bdde7b92c 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 659107df16438..6b3fe458347db 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 3dc91dda7d75f80e91ff68ddd006dc5d05c7dad9 Mon Sep 17 00:00:00 2001 From: Luis Ubieda Date: Thu, 9 May 2024 00:11:28 -0400 Subject: [PATCH 0146/2849] 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 1fd4b67e457e8..3e2b49b112e8b 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 9020b9bf809e3..c7cc46d030737 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 5da3b122e335e..279a99cc99505 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 385c6874ef0c576ca0fae531985ac0d88d3024ff Mon Sep 17 00:00:00 2001 From: Declan Snyder Date: Wed, 8 May 2024 10:55:00 -0500 Subject: [PATCH 0147/2849] 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 5cf192a73c476..6640b1aa2f2ad 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 de58070fa4309573e47dae36bf0f364c20cc8f1f Mon Sep 17 00:00:00 2001 From: cyliang tw Date: Wed, 8 May 2024 09:35:08 +0800 Subject: [PATCH 0148/2849] 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 a443f705edf45..e29f214a1833a 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 4474f9b089faf..3ff6200ee3919 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 4c12b81c94bc8..53f07b526edb3 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 1e9448b404b75614bc11fb3affa15e048b69cdfe Mon Sep 17 00:00:00 2001 From: Phi Bang Nguyen Date: Tue, 30 Jan 2024 15:01:15 +0100 Subject: [PATCH 0149/2849] 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 279a99cc99505..0a1eecc2cc921 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 e1cde2e8d117d1bb9457009fc64ef2978ec58a86 Mon Sep 17 00:00:00 2001 From: Andrej Butok Date: Mon, 6 May 2024 13:41:24 +0200 Subject: [PATCH 0150/2849] 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 1d62840c2e207..9f15dac313535 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 16d709e54faec76ff19b5b05dada754a8427fd27 Mon Sep 17 00:00:00 2001 From: Hake Huang Date: Thu, 2 May 2024 15:26:47 +0000 Subject: [PATCH 0151/2849] 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 93a7915e6fd9c..8dbd8533c1c26 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 82e1548615918..1cd757e66d5be 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 ebd3af9f582a2..ff4a121772085 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 c2f35a416845764eaa48ecfb70389545c72623de Mon Sep 17 00:00:00 2001 From: Matthias Alleman Date: Tue, 30 Apr 2024 10:48:12 +0200 Subject: [PATCH 0152/2849] 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 ccd92ef7e50ef..8d308a27509f4 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 7d4c13f55f2564272216f2f8dc718535be91a45d Mon Sep 17 00:00:00 2001 From: Emil Gydesen Date: Fri, 26 Apr 2024 11:10:29 +0200 Subject: [PATCH 0153/2849] 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 ae6e3351e3079..54d2e7caf53a2 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 f621407d5061683dc8c72feaf71ebdfba7e32058 Mon Sep 17 00:00:00 2001 From: Phi Bang Nguyen Date: Wed, 10 Apr 2024 15:35:05 +0200 Subject: [PATCH 0154/2849] 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 18adaab4c50e3..0f1263f041c31 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 3f20250f58b0a..0700438661e67 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 51b894ae304fe..b91fbe0b3ec53 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 1a40d1fd5a9afb34de5e66aec9338178fc9759b6 Mon Sep 17 00:00:00 2001 From: Phi Bang Nguyen Date: Thu, 29 Feb 2024 16:42:31 +0100 Subject: [PATCH 0155/2849] 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 1e7117c4393e3..475d18eb1003e 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 46eb7e2b65f799f3b81e000657cf2eb08522b600 Mon Sep 17 00:00:00 2001 From: Phi Bang Nguyen Date: Wed, 10 Apr 2024 17:28:49 +0200 Subject: [PATCH 0156/2849] 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 475d18eb1003e..a67d1d2044f62 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 249159f531b6a4e80b9af0bbd0872b0100d45144 Mon Sep 17 00:00:00 2001 From: Phi Bang Nguyen Date: Tue, 30 Jan 2024 17:34:24 +0100 Subject: [PATCH 0157/2849] 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 a67d1d2044f62..d267ea7a5ad8f 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 69fa94f761023aa43d7b25016101b4c04ad8a500 Mon Sep 17 00:00:00 2001 From: Glenn Andrews Date: Sat, 30 Mar 2024 11:59:47 -0700 Subject: [PATCH 0158/2849] 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 0000000000000..86586364114e8 --- /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 0000000000000..0b79cbb540c2d --- /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 0000000000000..e2104b03a2762 --- /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 0000000000000..ae32b7594af96 --- /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 0000000000000..9e5e1ab82b7ec --- /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 0000000000000..4a1118754d88b --- /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 0000000000000..e22588dbd67c6 --- /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 0000000000000..0612e1803427c --- /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 0000000000000..bc48258b99f8f --- /dev/null +++ b/samples/subsys/smf/smf.rst @@ -0,0 +1,10 @@ +.. _smf-samples: + +State Machine Framework Samples +############################### + +.. toctree:: + :maxdepth: 1 + :glob: + + **/* From bfe8020c4c214f948d7ac955829f2c602d9b0b75 Mon Sep 17 00:00:00 2001 From: Keith Short Date: Fri, 10 May 2024 13:32:15 -0600 Subject: [PATCH 0159/2849] 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 5384977b614fc..e80317664b974 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 2d61db9a606d155c2c2b6d04f8f5db436cc33483 Mon Sep 17 00:00:00 2001 From: Tomi Fontanilles Date: Fri, 3 May 2024 11:40:01 +0300 Subject: [PATCH 0160/2849] 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 5087213bb27ec..d377bb46b8d1d 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 92ab1f66edb76..6a731d4f61ac7 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 9673aa7702a08..c75af2c5c255d 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 6002abe519731cde5759139541597e8a315a9031 Mon Sep 17 00:00:00 2001 From: Tomi Fontanilles Date: Thu, 25 Apr 2024 16:16:44 +0300 Subject: [PATCH 0161/2849] 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 07d2585fa1687..19f272214045a 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 95e8a1c265872..2bb7e74fb6309 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 118dc93f9edb8..5005067f38c16 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 42ce2e03c86e3..ed584f347629c 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 546b7f6128eae..53b017ba80a96 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 d8f44a443a1b0..bf9bb9763c24a 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 73da457dcaa9cf11fa2a73ddfad4ac594ee9c679 Mon Sep 17 00:00:00 2001 From: Tomi Fontanilles Date: Fri, 3 May 2024 14:44:01 +0300 Subject: [PATCH 0162/2849] 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 4f07ecf0211d1..fd0da3fd04799 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 7adc4b689bc712c43ca642b8cf3d159efb706d49 Mon Sep 17 00:00:00 2001 From: Peter van der Perk Date: Fri, 12 Apr 2024 13:37:58 +0200 Subject: [PATCH 0163/2849] 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 ea6b82ebc0e20..a3a46039bfc99 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 1b8f540072253..4e06853323b66 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 64a373f4ea29672a8979469a71a3d154e61329ef Mon Sep 17 00:00:00 2001 From: Ederson de Souza Date: Wed, 8 May 2024 16:49:40 -0700 Subject: [PATCH 0164/2849] 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 51b31de006f72..fcc2e6676501f 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 f76f2928f118847dbbd9d2221390ab133de5ae6b Mon Sep 17 00:00:00 2001 From: Dino Li Date: Fri, 3 May 2024 15:37:39 +0800 Subject: [PATCH 0165/2849] 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 e018f86951571..6c19eb2514c1e 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 bd0d83c02103e..f0510c7f1f586 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 71176c366d6f8..c585271542eab 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 be682e22e166c33a67c1db0755f8ca20c37b6576 Mon Sep 17 00:00:00 2001 From: Maciej Perkowski Date: Fri, 10 May 2024 12:36:23 +0200 Subject: [PATCH 0166/2849] 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 3073a7c4ca6fb..25037eb263245 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 e2a51fc2a09d1..592d2c6304208 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 a6fbfc0612e6b214eef8040336b5cdd744de481f Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Fri, 10 May 2024 21:34:16 +0200 Subject: [PATCH 0167/2849] 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 2213c0dccf409..b37f24a7cddf2 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 dc4bd6fc7507c57dcec11cf5c2d031184e7da9f5 Mon Sep 17 00:00:00 2001 From: Reto Schneider Date: Thu, 2 May 2024 10:42:11 +0200 Subject: [PATCH 0168/2849] 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 38205ef5df619..76481eb69adb5 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 202a9329e56baced87365288f01a6f87a54fb677 Mon Sep 17 00:00:00 2001 From: Jordan Yates Date: Sat, 11 May 2024 11:38:33 +1000 Subject: [PATCH 0169/2849] 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 0d5a61c49113c..0a90e444f728e 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 497423cd7a8c0e17f36b20d85aa5f615cc0f4d67 Mon Sep 17 00:00:00 2001 From: Hake Huang Date: Thu, 9 May 2024 07:52:39 +0000 Subject: [PATCH 0170/2849] 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 3514983420987..abb1d3a44b13d 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 854685dfbca93040a678c950420e6c0aaa1873ad Mon Sep 17 00:00:00 2001 From: Michael Stumpf Date: Thu, 9 May 2024 11:57:58 -0400 Subject: [PATCH 0171/2849] 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 f12ba05addaf3..845b03d15187d 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 817b45e228ca6cfb1e82f845ae7d456d36fecdfc Mon Sep 17 00:00:00 2001 From: Tomi Fontanilles Date: Wed, 8 May 2024 10:55:10 +0300 Subject: [PATCH 0172/2849] 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 19f272214045a..3471a1a9a9d2d 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 bc60d8f3d2c40..2659e53631038 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 2b53c8305825002a12537f8086eb9e4a6cbfbf24 Mon Sep 17 00:00:00 2001 From: Ederson de Souza Date: Tue, 7 May 2024 15:45:12 -0700 Subject: [PATCH 0173/2849] 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 35ab0e246b250..924417286ce3d 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 6d417d52c2d6d9d12625523b6fd12ccea904b0b4 Mon Sep 17 00:00:00 2001 From: Hess Nathan Date: Tue, 30 Apr 2024 13:26:35 +0200 Subject: [PATCH 0174/2849] 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 1354a6314e496..813ce0f62e3f0 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 058e44ebef3a9..a25755aac279b 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 fd29df2e92c0d..ccdd66907880c 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 5c41c1418fe00..16b337acf011d 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 7b62c96facc36..9482f0e88c50a 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 162e1c413e941..7b283733edd6b 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 7ef2c1fa02287..d91a4d6b7c1a5 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 b99bfb0174ab8..fcccde56f9310 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 32cdb5eff7e7e..bb9676b18320e 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 dfd5eb7bdd698..3b197743b09ac 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 8c727e204f91b..cf4a6d681d585 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 fed8f3a983c5f..6a77532f8aebc 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 1fb5cd6462fca393946955b5f5b2df9f462d9006 Mon Sep 17 00:00:00 2001 From: Hess Nathan Date: Tue, 30 Apr 2024 10:49:36 +0200 Subject: [PATCH 0175/2849] 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 d387962191778..09a19f1074388 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 56471770a7cdf..71277e0b86421 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 2ffc599aa40f4..e54903a0a1d14 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 ba29f7d9bec26..82d1986fe9bf1 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 f6f856c4ad46d..76e0fa19cb6ff 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 62c199bc488d9..796be1d43a214 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 8f1dcda0156a9..99da187f9e40f 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 b8c21d4898952727e4a815bf548533a02565ce8a Mon Sep 17 00:00:00 2001 From: Hess Nathan Date: Thu, 2 May 2024 13:44:35 +0200 Subject: [PATCH 0176/2849] 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 3054119ff660c..71d671b6222f8 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 39538f78cf2e7325b8f081dc88681f091d23ff40 Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Fri, 10 May 2024 12:00:28 -0700 Subject: [PATCH 0177/2849] 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 b1404fa4ac4c8..fde8f631ca2f9 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 095bfba1d77036d6d78b04769879cb523aafc688 Mon Sep 17 00:00:00 2001 From: Jerzy Kasenberg Date: Mon, 21 Aug 2023 10:13:56 +0200 Subject: [PATCH 0178/2849] 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 eed1abc33ee79..c78e8bb414bf0 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 e24c6ce721966cd8f792cfd2fea593b3d5540262 Mon Sep 17 00:00:00 2001 From: Andrzej Kaczmarek Date: Wed, 14 Jun 2023 00:20:57 +0200 Subject: [PATCH 0179/2849] 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 7d5ef34cc72db..e6f3e0d300f76 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 f10b77364a3eac1f95803b4d1bb745b071f2a632 Mon Sep 17 00:00:00 2001 From: Jerzy Kasenberg Date: Tue, 22 Aug 2023 15:15:31 +0200 Subject: [PATCH 0180/2849] 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 f83098f6f197c..f4a3d1d674ee4 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 5572b5ba18749..2ea73a37fa110 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 e6f3e0d300f76..66ec3e108f62b 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 4b2a2b973c2d9..9eaf48974e89a 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 961959fc5f2ba913a80af6e92ea493b373f90253 Mon Sep 17 00:00:00 2001 From: Jerzy Kasenberg Date: Tue, 22 Aug 2023 15:27:20 +0200 Subject: [PATCH 0181/2849] 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 66ec3e108f62b..8656ae8dc433d 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 9eaf48974e89a..428eb0ca76e3d 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 beb4d5690a3c52ec66c9127f5e5585ee081ffe71 Mon Sep 17 00:00:00 2001 From: Grzegorz Swiderski Date: Thu, 9 May 2024 12:31:22 +0200 Subject: [PATCH 0182/2849] 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 fafadb163b6b9..fcbb21e787594 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 97a83ef8a7112d1e5347fb0a0b84086638229542 Mon Sep 17 00:00:00 2001 From: Grzegorz Swiderski Date: Thu, 9 May 2024 12:31:22 +0200 Subject: [PATCH 0183/2849] 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 5671ac699a4cc..809dcd62ae426 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 0000000000000..a5fd23fd34b23 --- /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 0000000000000..080b4e048e22a --- /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 22fd74914a033f28c954312253a9cf49001d305f Mon Sep 17 00:00:00 2001 From: Grzegorz Swiderski Date: Thu, 9 May 2024 12:31:22 +0200 Subject: [PATCH 0184/2849] 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 d1ff4df9bcd62..1cd531b7f3c57 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 70edbd1cf5b51bf0b4a2135ab58c68a40969fb7b Mon Sep 17 00:00:00 2001 From: Grzegorz Swiderski Date: Thu, 9 May 2024 12:31:23 +0200 Subject: [PATCH 0185/2849] 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 9797d2e717a30..f1ad19476f099 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 0000000000000..98ffffe867031 --- /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 8d221a91d07ee0c80a2391447998d37482fdff96 Mon Sep 17 00:00:00 2001 From: Robert Lubos Date: Fri, 10 May 2024 09:40:28 +0200 Subject: [PATCH 0186/2849] 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 ffdd263e603fd..59f374024c02e 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 2da205527fc50ecf927cdf0441dbc422f6db0cd8 Mon Sep 17 00:00:00 2001 From: Abderrahmane Jarmouni Date: Thu, 25 Apr 2024 14:53:02 +0200 Subject: [PATCH 0187/2849] 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 dcfd2a49276b1..7cb3343269b2d 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 0c4548c13b68e81b1d16d4eae025e920b04acd2f Mon Sep 17 00:00:00 2001 From: Abderrahmane Jarmouni Date: Thu, 25 Apr 2024 14:55:40 +0200 Subject: [PATCH 0188/2849] 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 fd37b14b5f93b..39ea370bdfbfe 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 0371ac75ac6e1..ba44fb6246f95 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 9c91375691984..eeb1d8e028485 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 725ed0eacb622..c17eaa5d9d4fb 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 231c8b988f886..686b84e302c1a 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 600f959b4fd85..78b3ea42d5216 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 bfa023d027d3e..6e4c7992f12d6 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 1450efbee3835..cf9caddc327e9 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 cd19d329e60f4..13a11ea7ac9e5 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 f3a24e2718fc8..7e7db46ccf0d4 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 91d290d0d0807..ad01e09017338 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 1f6f0644819cc..ac1161a946234 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 7dcabdf877cd7..869652f886837 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 f9c37b33cd8c5..673019120f0d3 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 bd9bb445858d1..642431a52ecae 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 d76f2f243f743..0addc69cd095c 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 38a76023cfc43..05efb0a9431e1 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 5e69ef4f3b786..ac2098ca4c1e1 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 e2bd33bf6c1a917ec4df7f9ce18fbea99036e473 Mon Sep 17 00:00:00 2001 From: Abderrahmane Jarmouni Date: Thu, 2 May 2024 09:37:35 +0200 Subject: [PATCH 0189/2849] 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 7cb3343269b2d..d368410b6ee6e 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 ac00136dfd009ca26c65e8107fb894af88ea5aa6 Mon Sep 17 00:00:00 2001 From: Abderrahmane Jarmouni Date: Thu, 2 May 2024 10:52:46 +0200 Subject: [PATCH 0190/2849] 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 39ea370bdfbfe..f7e58c7b69919 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 ba44fb6246f95..5f25181e6578a 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 eeb1d8e028485..8af21aaa46804 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 c17eaa5d9d4fb..07ed6f9dc2606 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 686b84e302c1a..b69d32d6cf301 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 78b3ea42d5216..a20419f001d36 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 6e4c7992f12d6..89c6944e6a42f 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 cf9caddc327e9..8cba3a5802153 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 13a11ea7ac9e5..64a2ac37fee40 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 7e7db46ccf0d4..c9b8d5e4f968d 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 ad01e09017338..f515f9c3166bf 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 ac1161a946234..3816489f42ffc 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 869652f886837..e6e87879b95a4 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 673019120f0d3..d4f7a7f000b0a 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 0addc69cd095c..acd8d3c0fd89f 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 ac2098ca4c1e1..a6611b8ef1b22 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 c085177af5047ff3fd0489c588f11fd80aeb0184 Mon Sep 17 00:00:00 2001 From: Abderrahmane Jarmouni Date: Fri, 3 May 2024 17:43:48 +0200 Subject: [PATCH 0191/2849] 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 cecd7ca9a25c8..fee7ef1e61818 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 0000000000000..16f381081c174 --- /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 b1f878f7a5859617ff7581f4dac5648388ea8f24 Mon Sep 17 00:00:00 2001 From: Abderrahmane Jarmouni Date: Fri, 3 May 2024 18:09:23 +0200 Subject: [PATCH 0192/2849] 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 fee7ef1e61818..3ed8f9fdf9284 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 d4c0fda714bbd16366d91d94ab5382eb7788edd3 Mon Sep 17 00:00:00 2001 From: Abderrahmane Jarmouni Date: Thu, 25 Apr 2024 15:24:41 +0200 Subject: [PATCH 0193/2849] 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 7912aa33deb4b..97fe4e0be57b7 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 27ba601cae56d..ef3e9b0a210a1 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 166d2ac390736..0631b5b1ada94 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 ca90da9607a00..6600d0724a855 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 dc49d4fcb2d68..63ccdd9582eac 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 8ed5a7edfeae3..8f44ab9d3079b 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 c4766287cc564..7f311f93c489a 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 5e6544e9cfb76..e8d9f40a77b37 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 7cd2e3bd7b662..c504dad4de50c 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 60af06296a94e..5ed0d28dd3d54 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 eee47f79254e1..a83b00bd82a44 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 c19aa47d955b9..d0ac388b263a6 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 a801f0bc1e9a6..032cf2ab85944 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 f89510912be0f..aeb13880f84ad 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 bd806a6378ace..4b848eb10171e 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 ea1d89798c0c6..457c4295196ce 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 9e795649a4ebf..c15e524238b76 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 762ede6fb2c4b..f8c167bc5ef4d 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 f0c40595f3a41..83b5413040524 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 8a128e61e6e60..47bce02573291 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 94cdcb739143d..4286f55eca9a1 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 cc1ca6d95ed71..dcbff3ca0bc37 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 015b1e3e642f1..ce8b0322fcd3e 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 8500f7fd3f17a..5dec0099d905a 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 e3be20e378061..1ca2d19993fb7 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 9cc78b0f4c823..094666250f397 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 755196fec1697..8caf70832cded 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 9d23c072b7597..d826ce3718858 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 d473be929bfde..26c4254294ffe 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 0c24a47992095..93574531dae21 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 622c268eceafa..698fb32a091b9 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 d5d1ee596b62a..66e75e574bbcd 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 e67e8d0e54e7f..b283964820abf 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 4c4ca788ddd0b..991a3710d08d2 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 93571670b7dba..eefd8d428e7e2 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 f97973c48542d..2a2ffde92bd78 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 9d8e31a6a6e3a..e0e92e5c16843 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 cc550b993c9c5..2713e735fa5a3 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 f449c985a8360..5fd6156e1ba96 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 ee4115fc1e6d3..5be0e1f69bed5 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 88c4ed94b282d..d69bbe3f28d2a 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 62b466defb4e4..26069f4b73f54 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 0c65b8361ff6c..a8a38453cb6f3 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 521997ca26614..9245300e816ba 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 d0ba893c87300..14a5b1de80fe0 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 4d74f6a13b8b0..cd93708041410 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 04bdc9d45ec71..6be25936050be 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 f455356048c47..a2b42575b1b54 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 2423d6bc36a66..70b08b6b0566b 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 0f435e29c75e0..947549a697cf4 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 df32bbc07c071..50f7c63d9e02c 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 e83f45452ddd8..6e37b1c148533 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 b741d37280550..4eb53ef3324fb 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 8862d754fbbd1..d4a629a489592 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 1c87cb7fd36bf..ebdbe230d20dc 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 13e6b0bf1431f..bc17f1c2d684d 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 bdc29c5dc751f..72fba315ace50 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 ac963c5756f43..b2b3ae93b79a0 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 f295947a33445..e450488ed4d39 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 7cd328e90dbde..bb90724deadcb 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 126376b1464ed..ddca938bb51e6 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 29e4e02cdebd1..7e3d638fa3ead 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 66859c3daabcb..05bdfdd34ebf3 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 7205a3954d46c..792eda8a7b76f 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 16ea3a4f794681846461ea9d31432af585a8a28a Mon Sep 17 00:00:00 2001 From: Abderrahmane Jarmouni Date: Thu, 25 Apr 2024 15:30:43 +0200 Subject: [PATCH 0194/2849] 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 0000000000000..8c6c114ee41fa --- /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 0000000000000..bd861fccf4292 --- /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 0000000000000..8c6c114ee41fa --- /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 0000000000000..bd861fccf4292 --- /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 0000000000000..8c6c114ee41fa --- /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 0000000000000..bd861fccf4292 --- /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 0000000000000..8c6c114ee41fa --- /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 0000000000000..bd861fccf4292 --- /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 0000000000000..d8e316b0bf27f --- /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 0000000000000..bd861fccf4292 --- /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 0000000000000..8c6c114ee41fa --- /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 0000000000000..bd861fccf4292 --- /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 0000000000000..8c6c114ee41fa --- /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 0000000000000..bd861fccf4292 --- /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 0000000000000..8c6c114ee41fa --- /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 0000000000000..bd861fccf4292 --- /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 0000000000000..8c6c114ee41fa --- /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 0000000000000..bd861fccf4292 --- /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 0000000000000..8c6c114ee41fa --- /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 0000000000000..bd861fccf4292 --- /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 0000000000000..8c6c114ee41fa --- /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 0000000000000..bd861fccf4292 --- /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 0000000000000..8c6c114ee41fa --- /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 0000000000000..8c6c114ee41fa --- /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 0000000000000..bd861fccf4292 --- /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 0000000000000..8c6c114ee41fa --- /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 0000000000000..bd861fccf4292 --- /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 0000000000000..8c6c114ee41fa --- /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 0000000000000..bd861fccf4292 --- /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 0000000000000..d8e316b0bf27f --- /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 0000000000000..bd861fccf4292 --- /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 0000000000000..8c6c114ee41fa --- /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 0000000000000..bd861fccf4292 --- /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 0000000000000..8c6c114ee41fa --- /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 0000000000000..bd861fccf4292 --- /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 0000000000000..8c6c114ee41fa --- /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 0000000000000..bd861fccf4292 --- /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 0000000000000..8c6c114ee41fa --- /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 0000000000000..bd861fccf4292 --- /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 0000000000000..8c6c114ee41fa --- /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 0000000000000..bd861fccf4292 --- /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 0000000000000..8c6c114ee41fa --- /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 0000000000000..bd861fccf4292 --- /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 0000000000000..d8e316b0bf27f --- /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 0000000000000..bd861fccf4292 --- /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 0000000000000..8c6c114ee41fa --- /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 0000000000000..bd861fccf4292 --- /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 0000000000000..8c6c114ee41fa --- /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 0000000000000..bd861fccf4292 --- /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 0000000000000..8c6c114ee41fa --- /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 0000000000000..bd861fccf4292 --- /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 30c471ca1dd058047aff3df4a3fea22f8257cfdf Mon Sep 17 00:00:00 2001 From: Abderrahmane Jarmouni Date: Thu, 25 Apr 2024 15:32:59 +0200 Subject: [PATCH 0195/2849] 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 f65baf15877e9..5f81d05c87b42 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 9b51d889c0e8e..c73cbd5fbddf0 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 83b5d65d57297aff33a8c81158fecf586efaa64c Mon Sep 17 00:00:00 2001 From: Abderrahmane Jarmouni Date: Tue, 7 May 2024 09:09:12 +0200 Subject: [PATCH 0196/2849] 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 3ed8f9fdf9284..2d59137b25fc1 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 4682e10e2afd63a271fbc873f521f613efc8219f Mon Sep 17 00:00:00 2001 From: Abderrahmane Jarmouni Date: Tue, 7 May 2024 11:16:12 +0200 Subject: [PATCH 0197/2849] 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 2d59137b25fc1..cdc975c4f1fe1 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 e92efc4a030bbc5cfabafb9324d4abed42632216 Mon Sep 17 00:00:00 2001 From: Abderrahmane Jarmouni Date: Tue, 7 May 2024 11:26:59 +0200 Subject: [PATCH 0198/2849] 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 0ff1a60ef85f1..e2313c5e932fd 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 63d2199e4d03f..c6938020f99ef 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 e4a6686691374f6e03399e5251114d9146532714 Mon Sep 17 00:00:00 2001 From: Wojciech Sipak Date: Fri, 15 Mar 2024 13:38:41 +0100 Subject: [PATCH 0199/2849] 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 1f3d3d9e0c0d3..119745e52edeb 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 d8bce88855696..f017d9c6f3c35 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 46005a7da105c..0733824966130 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 e8d9256f3f0c9..a6a5ecc7738bb 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 311c88f58acbf..a8e935bd50ae9 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 c3bcfac49c518..27b02fa4bedba 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 ba22e8aa624b3..30708da7fa423 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 bd4a3affce9f2..c75724709788d 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 8c8e8ae15778e..0408282380163 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 bf130d7d3a8cd..a2089253a3c6b 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 1984dea8da3c2..7f2f067d72c67 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 d7d4958d2e73f..ca098c1ef773d 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 64f7ef2124f65..57971b3571c15 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 ecec50611c35b..d316dd1b8d029 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 a5a1c003ef35c..946166f95b49d 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 59363bb4ee92e..f2eafb526763f 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 373c6b0eae994..d838e27766ea2 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 f8571589d7a12..d516f1e1c5c89 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 a465da8f94dc9..d738477900dfb 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 af75ec0edbcf8..8a80a51872e17 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 51ac12191f6dd..325c3794c29da 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 05aac04c00fb8..ae7e008793e8b 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 cb2ac02717b5f..3a80a65a46a91 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 2a1bb02cc2f2c..6d564843a1c32 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 f1cd4d19d5a6b..7e160d6811716 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 a8efc9aad007d..30c20695c27e7 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 4be28b02f83eb..082aa4e569925 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 0a641e9ef1275..004ed974675bd 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 3012207d36de9..996732bc3dd00 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 8e5a51d07c7f0..a49668e954770 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 b5f7a37910dde..5a95351e16df3 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 eb4fcfcd02809..9443a7e09c65f 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 99e14f59b1976..746a5d2916e7c 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 e436849ced4d1..ac94218909779 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 ad8985b55db08..69741a72d8f51 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 20b765232869e..7613fabaed57c 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 d66078fde8bb5..52a05c854556b 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 1957bc3ad259b..0faa84b38c948 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 47842c49d46d8..9d9f07dc48b85 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 fd95098a77345..c8224cafae41c 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 29559d1e262dd..ead08879d1b7d 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 9e81868de2181..fa3b6417b90f1 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 f4929c52b4204..c897a54621493 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 0740dc17fafb3..543b58db8375e 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 8249d6f971992..3a7f4ad73082c 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 dc6361d4f5019..7112c3fde8e16 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 a9eb85aee47a2..e94bd6e2faa01 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 db494bd878cb8..b1aa3766f7728 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 37ed59788d9bb..851fb36a8b41a 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 5d66048e03880..53055263f3465 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 8a1ace79ba69a..d438611cb3373 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 498333044249e..29f4404ca9517 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 194e1b451993b..0cdc0e8ee9d2e 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 05f3c979f7f0c..480b81537b678 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 018b3c2b72732..20e2f1a74c6f8 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 b3fc0cdf97d1a..7e8e17cf71f08 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 e59db1ab804a308bca7f71df5536be480674d575 Mon Sep 17 00:00:00 2001 From: Helmut Lord Date: Thu, 7 Mar 2024 12:43:25 -0500 Subject: [PATCH 0200/2849] 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 0000000000000..b313c721fb6a7 --- /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 509d8f8aae9b95f9eab81588937e7739abfa2ae0 Mon Sep 17 00:00:00 2001 From: Pieter De Gendt Date: Tue, 7 May 2024 10:12:10 +0200 Subject: [PATCH 0201/2849] 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 dfd5ba8b9e348..af9715fe20b22 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 e791e7637f6435a513d0eea5197d8d4c59296767 Mon Sep 17 00:00:00 2001 From: Pieter De Gendt Date: Tue, 7 May 2024 09:17:51 +0200 Subject: [PATCH 0202/2849] 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 931f2635d600b..6946518b2bed0 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 7b6e9dc4b844b33f6b13413e585097871b8a9043 Mon Sep 17 00:00:00 2001 From: Pieter De Gendt Date: Mon, 6 May 2024 15:35:07 +0200 Subject: [PATCH 0203/2849] 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 af9715fe20b22..125d438b58b29 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 db1a4a61be6d7fc277f0ae519c0228af7d9d297b Mon Sep 17 00:00:00 2001 From: Pieter De Gendt Date: Mon, 6 May 2024 15:39:52 +0200 Subject: [PATCH 0204/2849] 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 17d207098254b..932e3cfdeebea 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 5df6f99c40f322ac626e29b8ed76833003737f55 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C4=99drzej=20Ciupis?= Date: Thu, 14 Mar 2024 12:51:06 +0100 Subject: [PATCH 0205/2849] 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 809dcd62ae426..7436f9b936db5 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 7a8c16c9376f785e92b00d4ddd7525039b05ffe1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C4=99drzej=20Ciupis?= Date: Thu, 14 Mar 2024 12:55:34 +0100 Subject: [PATCH 0206/2849] 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 fd838f3757df9..22877e4e8d324 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 ad08596f600aa..dba929c04cf1a 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 b45764542394cfa91b1293c48cc8f72fcb70c18b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C4=99drzej=20Ciupis?= Date: Thu, 14 Mar 2024 13:01:56 +0100 Subject: [PATCH 0207/2849] 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 9acb811e6b602..43217f8d37a3f 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 ba1102c97df59b91ddabcd2760cd6be5a81cd126 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C4=99drzej=20Ciupis?= Date: Fri, 12 Apr 2024 08:14:08 +0200 Subject: [PATCH 0208/2849] 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 593aff6fcc7a3..15a1f076063d2 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 6b048fdf71091871e412c4e508fddcc4a9166283 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C4=99drzej=20Ciupis?= Date: Mon, 15 Apr 2024 08:43:56 +0200 Subject: [PATCH 0209/2849] 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 22877e4e8d324..476c076fae115 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 dba929c04cf1a..20109b66180e6 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 ff58bd02047cc1207e37ca988eb1a0e03a98342e Mon Sep 17 00:00:00 2001 From: Pieter De Gendt Date: Wed, 8 May 2024 13:31:09 +0200 Subject: [PATCH 0210/2849] 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 eeba6274530c0..f193cdb6c5436 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 e7235f80ccfa56eb0931903723e57c64081cff3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Chru=C5=9Bci=C5=84ski?= Date: Fri, 10 May 2024 09:15:41 +0200 Subject: [PATCH 0211/2849] 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 fa68a195cd687..b985b7bc96309 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 dc44966f02acc426684c0fbfbfe28c508ed494d2 Mon Sep 17 00:00:00 2001 From: Tim Lin Date: Thu, 9 May 2024 15:40:19 +0800 Subject: [PATCH 0212/2849] 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 5043f1fa3b233..0e7e4751b5e23 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 91f992f076ef7..abbeecd53d6ab 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 85e1a212f6a1a..c6d9608490d39 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 f89934451f98bb287edbd35351916888cbad11be Mon Sep 17 00:00:00 2001 From: Tim Lin Date: Tue, 30 Apr 2024 10:58:47 +0800 Subject: [PATCH 0213/2849] 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 0000000000000..73f577d814a46 --- /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 0e7e4751b5e23..ad8a06a3d8e0d 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 0000000000000..48fed80f1c297 --- /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 2ff1bc17953fd..2f272533e9526 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 b462d75ecd360..dc0ab56669e11 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 682a4c936a35352ca397196d22ba9e4eb07e49aa Mon Sep 17 00:00:00 2001 From: Tim Lin Date: Tue, 30 Apr 2024 11:09:34 +0800 Subject: [PATCH 0214/2849] 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 0000000000000..73f577d814a46 --- /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 ad8a06a3d8e0d..089115dc4898f 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 0000000000000..d774e6a455b10 --- /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 2f272533e9526..0da984253c81e 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 dc0ab56669e11..ff1b221f2ad61 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 d371a89c3fce3cc82b05bd767c6d7fd2ef3cf394 Mon Sep 17 00:00:00 2001 From: Tim Lin Date: Tue, 30 Apr 2024 11:17:49 +0800 Subject: [PATCH 0215/2849] 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 089115dc4898f..38b92c9c6b8ed 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 0000000000000..6bd70e438f97a --- /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 0da984253c81e..96504021f2383 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 ff1b221f2ad61..b73270535f931 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 4d85967e09d0ab31cb76048d3370e2750d4ac354 Mon Sep 17 00:00:00 2001 From: Dmitrii Golovanov Date: Wed, 8 May 2024 22:10:18 +0200 Subject: [PATCH 0216/2849] 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 43c05750bf845..09ddaa973f818 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 5fd292fd4bc63..d27e7196843f0 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 600cde4c1a6db..7f93629922365 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 36d8583589905d9ad2f1060b2535280a58e03218 Mon Sep 17 00:00:00 2001 From: Piotr Dymacz Date: Wed, 8 May 2024 14:18:31 +0200 Subject: [PATCH 0217/2849] 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 88dd4083209f4..f956270a8529a 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 b501278237bf5294a3146a1bf7dce222ea84e80c Mon Sep 17 00:00:00 2001 From: Johann Fischer Date: Wed, 8 May 2024 15:28:55 +0200 Subject: [PATCH 0218/2849] 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 0c1463e979801..8f5547d36c79a 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 4c4f0bce589c9c3ea0324cb7f057ec43ee774ed4 Mon Sep 17 00:00:00 2001 From: Jordan Yates Date: Mon, 13 May 2024 16:16:26 +1000 Subject: [PATCH 0219/2849] 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 55bfac7ae334c..801f1fd6e6794 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 153255f15b3f76e57db5de77e5ebb2976506ed93 Mon Sep 17 00:00:00 2001 From: Jiafei Pan Date: Mon, 13 May 2024 10:47:49 +0800 Subject: [PATCH 0220/2849] 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 40faba8411719..cd025a547e717 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 2bb2dd6e82fd62ffa6673f7d36076d7da60ee7d4 Mon Sep 17 00:00:00 2001 From: Jordan Yates Date: Thu, 9 May 2024 21:08:56 +1000 Subject: [PATCH 0221/2849] 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 bbe0f8dabe103..60ce2f36e2187 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 4bdc61132cbaa9a6a56b9d2ac2f18743c4639fa9 Mon Sep 17 00:00:00 2001 From: Jordan Yates Date: Thu, 9 May 2024 21:40:35 +1000 Subject: [PATCH 0222/2849] 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 557418ace63e0fa6a73f581b796822aada485a56 Mon Sep 17 00:00:00 2001 From: Jordan Yates Date: Thu, 9 May 2024 21:35:47 +1000 Subject: [PATCH 0223/2849] 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 0000000000000..6f4d8151e3519 --- /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 0000000000000..8672ce0e8eb5a --- /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 0000000000000..4e78174c5c6ca --- /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 0000000000000..93c0b9c965401 --- /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 0000000000000..069bbac09c936 --- /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 31112619407316cd5f918ffd610042f73749ed12 Mon Sep 17 00:00:00 2001 From: Marcin Niestroj Date: Thu, 9 May 2024 13:18:20 +0200 Subject: [PATCH 0224/2849] 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 be49d3ec63e57..ab4d22ce51a24 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 60aeb4e6bc9a397cf79935ec2e2115b1155d5a1a Mon Sep 17 00:00:00 2001 From: Arkadiusz Cholewinski Date: Thu, 9 May 2024 10:16:26 +0200 Subject: [PATCH 0225/2849] 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 34ce99c98549e..1d446aded7881 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 265da0df86b171f559a2f10f7aa7043be910a590 Mon Sep 17 00:00:00 2001 From: Noah Pendleton Date: Wed, 8 May 2024 06:21:52 -0400 Subject: [PATCH 0226/2849] 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 8f654bf224b8d..ad65b6a1d1f8f 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 fd9076a38d94f..e44cd327cb5f0 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 4b48ffe005ad1..6fa63080dd921 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 8aac55b0400cd..f61860b31da55 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 3a3e04e4388c1..cd3d55342b5d8 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 294939a31ed82d320cb534e86bd73194c2dd7bc7 Mon Sep 17 00:00:00 2001 From: Pieter De Gendt Date: Tue, 7 May 2024 15:44:30 +0200 Subject: [PATCH 0227/2849] 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 ad65b6a1d1f8f..b589ac43159bb 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 9fc26804fb5cdd6c1826c4afc3af4eefce74c429 Mon Sep 17 00:00:00 2001 From: Daniel Apperloo Date: Fri, 3 May 2024 01:55:49 +0000 Subject: [PATCH 0228/2849] 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 b589ac43159bb..2fa2d371c4ab8 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 af51267edbf1f..767c04f94fe47 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 c96017c79c9f1..085ef77556959 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 c0869be56f69d50d9bca9ba4400cc7477ba0e70d Mon Sep 17 00:00:00 2001 From: IBEN EL HADJ MESSAOUD Marwa Date: Mon, 15 Apr 2024 10:08:08 +0200 Subject: [PATCH 0229/2849] 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 801f1fd6e6794..825f15f4c4d26 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 820cf4d639200946f4fc25434d0199f5b733624d Mon Sep 17 00:00:00 2001 From: IBEN EL HADJ MESSAOUD Marwa Date: Tue, 16 Apr 2024 09:31:37 +0200 Subject: [PATCH 0230/2849] 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 c8e44633ad5f9..8a589261aa3d2 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 1f16e9c44c64bb872f18b1b5719fc07a7272d45b Mon Sep 17 00:00:00 2001 From: IBEN EL HADJ MESSAOUD Marwa Date: Tue, 16 Apr 2024 09:39:47 +0200 Subject: [PATCH 0231/2849] 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 869b31a31f7a0..0a061d777a922 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 ccd1019f8092de78630b0696317a0d0dd577d2ff Mon Sep 17 00:00:00 2001 From: IBEN EL HADJ MESSAOUD Marwa Date: Tue, 16 Apr 2024 18:50:21 +0200 Subject: [PATCH 0232/2849] 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 f21cb07e1834c..553e09838d84d 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 bca6514190e64..d12a294eb7ff1 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 99fd91bf1c3958e4ac643cf1f3aeb6ed1cbe536b Mon Sep 17 00:00:00 2001 From: IBEN EL HADJ MESSAOUD Marwa Date: Fri, 19 Apr 2024 10:07:59 +0200 Subject: [PATCH 0233/2849] 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 8a589261aa3d2..70006e377b1b0 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 23a03b7a0a494e27316fdd7fdb453a0409b99aa9 Mon Sep 17 00:00:00 2001 From: IBEN EL HADJ MESSAOUD Marwa Date: Fri, 19 Apr 2024 10:09:14 +0200 Subject: [PATCH 0234/2849] 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 0a061d777a922..8f6b1ffd1f43a 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 423f18c4dde4a910671f6a5d023e9566f804fbb9 Mon Sep 17 00:00:00 2001 From: Henrik Brix Andersen Date: Mon, 13 May 2024 12:36:38 +0200 Subject: [PATCH 0235/2849] 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 7cc95c0ed179c..f85c50138bda5 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 b8fedfb6c16bd614b18d653a7f55db24eed4b78c Mon Sep 17 00:00:00 2001 From: Marek Pieta Date: Thu, 9 May 2024 15:26:11 +0200 Subject: [PATCH 0236/2849] 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 76686ce996569..8caebcc4c3c34 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 f63f508c21779b7e8936d724f0a7f9a5c39c9a10 Mon Sep 17 00:00:00 2001 From: Robert Lubos Date: Thu, 9 May 2024 15:37:14 +0200 Subject: [PATCH 0237/2849] 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 59bad541f1c5b..f532060f8f555 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 a85919141368b9a11b995f47d18bacfe209ed3e3 Mon Sep 17 00:00:00 2001 From: Mateusz Michalek Date: Thu, 9 May 2024 10:19:58 +0200 Subject: [PATCH 0238/2849] 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 025b0791010fe..a729b57bc288d 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 d9b3ffa5eafc1f7e6dad0e57f01d9e787cfd0fc5 Mon Sep 17 00:00:00 2001 From: Balaji Srinivasan Date: Wed, 8 May 2024 12:51:42 +0200 Subject: [PATCH 0239/2849] 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 1b854cbf83059..2ade708271adc 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 9bd0170aad49311e0dd5279b0a628b1ea1704698 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fin=20Maa=C3=9F?= Date: Mon, 13 May 2024 11:53:04 +0200 Subject: [PATCH 0240/2849] 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 e1ff3e63b9a86..6a95004001f42 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 3df70b84a84a1..9926b9b1d383a 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 54a83e2c17d94a7525ee07d299341da6b741a7fd Mon Sep 17 00:00:00 2001 From: Carles Cufi Date: Thu, 9 May 2024 13:40:50 +0200 Subject: [PATCH 0241/2849] 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 544f721994bf3..4310b11d5d8c3 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 cbf5ab49e6f2911e5b4bf3d95da53cbd52424f04 Mon Sep 17 00:00:00 2001 From: Carles Cufi Date: Thu, 9 May 2024 13:49:05 +0200 Subject: [PATCH 0242/2849] 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 3471a1a9a9d2d..73f3e5ccaf809 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 57305971d1182b6e41702ba1bb991ab1899a9e98 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Wed, 1 May 2024 18:28:20 -0400 Subject: [PATCH 0243/2849] 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 8591e0a8ba445..313afbb7922e1 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 d4da8366cf22f..0628879d93302 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 35dae90a2356d..343c10478b93c 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 4afb828f4a7fc..e1b8e3ed26c8b 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 7b283733edd6b..47a41f242666e 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 73f7617d792e1..3adcfbab33a26 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 9f100649d49d4..28fb66fec4b47 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 83c4a3b53d765..7429b4e3fdb4d 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 e9a47d932ce6e0d31168d3d8972689f5a928d6c1 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Wed, 1 May 2024 21:58:54 -0400 Subject: [PATCH 0244/2849] 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 13a04cd283327..e870c8740e251 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 e1b8e3ed26c8b..ddfbdd2e16e1d 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 47a41f242666e..f74b8c7cf4454 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 6c5eaacbb78034f97375e59a24b5e18fd15178a9 Mon Sep 17 00:00:00 2001 From: Dmitrii Golovanov Date: Fri, 3 May 2024 12:42:23 +0200 Subject: [PATCH 0245/2849] 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 becabeb25a98d..a1f5c737b7978 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 55ebc691cd610278d6ee3dcb70fc434fe281fc32 Mon Sep 17 00:00:00 2001 From: Dmitrii Golovanov Date: Fri, 3 May 2024 12:57:15 +0200 Subject: [PATCH 0246/2849] 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 a1f5c737b7978..eff3d49c59103 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 272731169ce9166d6df989c47e01060af4ab409a Mon Sep 17 00:00:00 2001 From: Dmitrii Golovanov Date: Fri, 3 May 2024 14:12:33 +0200 Subject: [PATCH 0247/2849] 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 eff3d49c59103..dc6791587ebb9 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 8e6a9211043bb7a966aca6a7ed2ae8e57e34abaf Mon Sep 17 00:00:00 2001 From: Dmitrii Golovanov Date: Fri, 3 May 2024 17:11:00 +0200 Subject: [PATCH 0248/2849] 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 dc6791587ebb9..a2e481f02f9bb 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 b438a74bd002bf93bf5ff0bbdcecc95c4768ec3f Mon Sep 17 00:00:00 2001 From: Dmitrii Golovanov Date: Fri, 3 May 2024 18:16:20 +0200 Subject: [PATCH 0249/2849] 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 a2e481f02f9bb..a8d671ef61985 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 2005deddb4e2992a00582a6415c64ca820a9acb8 Mon Sep 17 00:00:00 2001 From: Dmitrii Golovanov Date: Sat, 4 May 2024 16:22:55 +0200 Subject: [PATCH 0250/2849] 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 a8d671ef61985..414665c764172 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 af515ef87bf63d48d67fee8155f5d904baff9b84 Mon Sep 17 00:00:00 2001 From: Jordan Yates Date: Sat, 4 May 2024 14:58:43 +1000 Subject: [PATCH 0251/2849] 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 5bc51f3635b9f..4899a3435d960 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 24ce3f4182e8561adea4c285aa7602dccba102c9 Mon Sep 17 00:00:00 2001 From: Grzegorz Swiderski Date: Fri, 3 May 2024 09:21:43 +0200 Subject: [PATCH 0252/2849] 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 b8a62084ce5fb..71b25dbeba07f 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 549abb138fbec..10ecd585ef3f4 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 958a4505bd158a7bbb3390344e00e2ed743bef58 Mon Sep 17 00:00:00 2001 From: Hess Nathan Date: Tue, 30 Apr 2024 09:52:26 +0200 Subject: [PATCH 0253/2849] 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 0a98d8e8e069a..9acca131a98d2 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 9b98ce8c52ec1..a9515d8c7a5cf 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 59b0017375c3d..6b4035d976da6 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 2b9c5520503c6e016e9e9cac4daca2312fdc2f0b Mon Sep 17 00:00:00 2001 From: Corey Wharton Date: Mon, 15 Apr 2024 16:15:54 -0700 Subject: [PATCH 0254/2849] 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 0000000000000..6940a607ee5a0 --- /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 2542a4887dce7..3b02c29c3ffb7 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 c643740b1bae5..3fc9db4902a21 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 bf114c6b1a818a804114a81880b856c7e0f06325 Mon Sep 17 00:00:00 2001 From: Corey Wharton Date: Mon, 15 Apr 2024 16:22:28 -0700 Subject: [PATCH 0255/2849] 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 56b0458c2ecf1..eb8cb5606556e 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 c05858c1125f6..3e767092b762c 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 3b02c29c3ffb7..1af13cb562264 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 2d31d45429ddd0cc70bcdbdd0b7f7d132ab58870 Mon Sep 17 00:00:00 2001 From: Fredrik Gihl Date: Sat, 27 Apr 2024 12:51:40 +0200 Subject: [PATCH 0256/2849] 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 2659e53631038..0851c52b7cec1 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 ac7fe02ac4697..82f5160ff732e 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 15c7370b8e44a..35e9a82df0226 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 cf318cb9f9f20..a85e91c58ae5b 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 0000000000000..1e42cd80a9d05 --- /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 a7a6a554eb021..2566057e5f4f6 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 2803dcd5646ca1a6e62ffb5d86c7e99b03c302fe Mon Sep 17 00:00:00 2001 From: "Najumon B.A" Date: Mon, 10 Jul 2023 11:16:50 +0530 Subject: [PATCH 0257/2849] 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 913bb0e794d5e..2e6e7ebd00ab2 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 d1aedcd4deca6..8d68afa2a1913 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 d68e80c423f4d..68f89c90398f9 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 6cbf18a831d87..af3b0d1c8165e 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 7f16b7fb945b9985d810b8d18333971a0d512c77 Mon Sep 17 00:00:00 2001 From: "Najumon B.A" Date: Mon, 10 Jul 2023 11:21:25 +0530 Subject: [PATCH 0258/2849] 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 393d504c7dc6a..852e949c1150f 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 40a8ed84aaf0eb90c46c5c142b114cbcea54c74b Mon Sep 17 00:00:00 2001 From: Jason Murphy Date: Tue, 20 Feb 2024 17:35:56 +0000 Subject: [PATCH 0259/2849] 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 00f00777a2371..171e57963bcd8 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 467af2d6b87be93f17daed80adc576e0040ccf36 Mon Sep 17 00:00:00 2001 From: Jason Murphy Date: Wed, 21 Feb 2024 09:50:33 +0000 Subject: [PATCH 0260/2849] 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 5db24f04e80da..83a3343ca351d 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 8120bd751952221a07b9e3c553a4a0f43e6ca40d Mon Sep 17 00:00:00 2001 From: Gerard Marull-Paretas Date: Fri, 10 May 2024 09:59:01 +0200 Subject: [PATCH 0261/2849] 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 42e70bdb0b607..77f9820f681b6 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 bf4f9262749a2..91586470feabd 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 8581a330d40a8..0120c87769d7e 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 0000000000000..c959e82a3a3ba --- /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 785bc0d24004d..e1f456405a7cc 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 0630c5cfb52a0ba4e63deee03f1ea0504aa2857a Mon Sep 17 00:00:00 2001 From: Gerard Marull-Paretas Date: Fri, 1 Mar 2024 10:14:14 +0100 Subject: [PATCH 0262/2849] 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 0000000000000..f58082ab8dfd8 --- /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 0000000000000..edec01b94c98d --- /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 0000000000000..2cb0208205188 --- /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 0000000000000..046b18c7559ab --- /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 0000000000000..becd6a5481915 --- /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 0000000000000..62961aff1840b --- /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 0000000000000..becd6a5481915 --- /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 0000000000000..5add79c52ba82 --- /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 0000000000000..af5b6fd3dbe74 --- /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 0000000000000..b59062d881f17 --- /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 0000000000000..b8ae05d4ef6fa --- /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 0000000000000..f50bc8553a011 --- /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 0000000000000..270c92c09a4f3 --- /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 0000000000000..dd863e78d9933 --- /dev/null +++ b/samples/sysbuild/hello_world/sysbuild/nrf54h20dk_nrf54h20_cpurad.conf @@ -0,0 +1 @@ +SB_CONFIG_REMOTE_BOARD="nrf54h20dk/nrf54h20/cpurad" From e783aafdd05728a5e17fd42e43bcb886da0d74d4 Mon Sep 17 00:00:00 2001 From: Abderrahmane Jarmouni Date: Wed, 20 Mar 2024 15:25:14 +0100 Subject: [PATCH 0263/2849] 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 e79ba3bf0f3e9..f5a831f0d2b83 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 fdb34570584959c281c5beaa491dbec98db95388 Mon Sep 17 00:00:00 2001 From: Abderrahmane Jarmouni Date: Wed, 20 Mar 2024 15:34:45 +0100 Subject: [PATCH 0264/2849] 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 0000000000000..6883eb2350967 --- /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 26c8de398978b..15b4b6fba41a9 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 b903dff44fe12d91716c0bff024b8d25a6349c6e Mon Sep 17 00:00:00 2001 From: Abderrahmane Jarmouni Date: Wed, 20 Mar 2024 15:39:18 +0100 Subject: [PATCH 0265/2849] 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 0000000000000..2657a0bf45f42 --- /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 1eef7ad3ae93e..9ecaf11a0817a 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 0000000000000..fc9393dcf4247 --- /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 0000000000000..1d24d39f82436 --- /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 a3665f7c570c3..e7a970d4a58ab 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 cd6c94846542d559c36540b626a5f55aa44743fa Mon Sep 17 00:00:00 2001 From: Abderrahmane Jarmouni Date: Wed, 20 Mar 2024 15:54:00 +0100 Subject: [PATCH 0266/2849] 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 8bbeabfe48630..718b783f69df0 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 dcbff3ca0bc37..f06415451704e 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 b1913fb47e993ea9b2d8052cc9425b7e1ebbf072 Mon Sep 17 00:00:00 2001 From: Luis Ubieda Date: Mon, 29 Apr 2024 21:16:12 -0400 Subject: [PATCH 0267/2849] 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 ad450eea9aa23..a68f747f69f1a 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 413518e0c8e733b3ae0bf8cdefdc32aa48a37530 Mon Sep 17 00:00:00 2001 From: Luis Ubieda Date: Mon, 29 Apr 2024 21:45:06 -0400 Subject: [PATCH 0268/2849] 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 500613d6208e8..214109759ae0b 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 a68f747f69f1a..9e4a4de593006 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 9668b35ce7284500282ceeb40d5a78b26ea709b2 Mon Sep 17 00:00:00 2001 From: Daniel DeGrasse Date: Mon, 29 Apr 2024 18:52:53 -0500 Subject: [PATCH 0269/2849] 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 6c827e7ce7fa7..fdc50c2b3e69a 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 0000000000000..cd18246823c89 --- /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 b249dbb312bbc..ce96362b49d6b 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 97e2eba977a49..c26a16bc03229 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 84b8e92445f1a613286b476ca113bf99e49d65a7 Mon Sep 17 00:00:00 2001 From: Daniel DeGrasse Date: Mon, 29 Apr 2024 18:53:45 -0500 Subject: [PATCH 0270/2849] 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 70dd0b0d4ad28..888d4eb1bd9c6 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 b91fbe0b3ec53..aa5e5e705013a 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 c26a16bc03229..789f02099beca 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 4d9d0ee64c2e047a64879c6a67382b409302aae6 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Thu, 9 May 2024 14:31:47 +0300 Subject: [PATCH 0271/2849] 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 9890571ff29ab..d8c719483ac32 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 70ab0e65a587fba92e520ddf4cb87dd4cd9770ae Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Thu, 9 May 2024 14:33:04 +0300 Subject: [PATCH 0272/2849] 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 dc0eaf36d185e..606957e9fd57a 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 d8c719483ac32..c7b896ecb8a68 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 fb1ec14938a7d43c58b60e8b808e29884b952691 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Thu, 9 May 2024 14:35:39 +0300 Subject: [PATCH 0273/2849] 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 08cdfd1ee29f7..d62283b5bbc56 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 c354f7b00bec7cee5f199cdf5d5982c37ddc253a Mon Sep 17 00:00:00 2001 From: Jordan Yates Date: Fri, 10 May 2024 10:55:15 +1000 Subject: [PATCH 0274/2849] 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 796be1d43a214..caff1c1fa6478 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 aee130f8d7c6c7bae56b36307e1e7a46e018c1f5 Mon Sep 17 00:00:00 2001 From: Jordan Yates Date: Fri, 10 May 2024 10:59:50 +1000 Subject: [PATCH 0275/2849] 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 caff1c1fa6478..e088099ef9137 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 98deebd29bef2a991949cde158dc45800cb253de Mon Sep 17 00:00:00 2001 From: Jordan Yates Date: Fri, 10 May 2024 11:09:23 +1000 Subject: [PATCH 0276/2849] 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 0851c52b7cec1..c778f96d47986 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 71277e0b86421..32c554c159da6 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 23ca74b756d1fe8bc62892022509e64c8a1647db Mon Sep 17 00:00:00 2001 From: Jordan Yates Date: Fri, 10 May 2024 11:11:42 +1000 Subject: [PATCH 0277/2849] 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 3c91928396397..b0861bcbb2e69 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 a4532fdee14fe..c736a396deeed 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 9aef57181678c..e31eaa3bae1fe 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 b7f727ff4a449..55b9f7728cabd 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 30b3beaca6631..cdebef24532b9 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 f1557c9fcbae3..3534a0dec6b5f 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 cba18a5943412c801c2622985d9dd4cb19ed40ba Mon Sep 17 00:00:00 2001 From: Reto Schneider Date: Thu, 2 May 2024 15:52:25 +0200 Subject: [PATCH 0278/2849] 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 31cd058f60fbf..429c41f1e58a5 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 530b593275b46b9e6978c0c1509696f23912aebf Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Thu, 9 May 2024 11:10:51 -0400 Subject: [PATCH 0279/2849] 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 2a8ed28deae76..e9a3d523127a4 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 d796c117cebab17d3836581cc588e17a6f192a4b Mon Sep 17 00:00:00 2001 From: Samuel Kleiser Date: Wed, 8 May 2024 17:04:11 +0200 Subject: [PATCH 0280/2849] 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 fa9df2937e7b7..e2a22fba6cf6e 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 aaac4141455f0..b1666d67d91ec 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 01b4f9d263745e41aa0cca1ef71e2063c8224f3b Mon Sep 17 00:00:00 2001 From: Troels Nilsson Date: Tue, 7 May 2024 15:49:27 +0200 Subject: [PATCH 0281/2849] 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 2ca53aaf4c9d3..4c5265b799cff 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 f4a3771f8eda33e4f8229e487d2486089d3ff40d Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Wed, 17 Apr 2024 18:34:34 +0100 Subject: [PATCH 0282/2849] 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 0000000000000..f8ffb62e68314 --- /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 2da4f234e64fa..de66dd7d2af28 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 ff594a862cd64..6b8e59b7e9e7e 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 8ca399919b0c49acc3c2150725b89bd0c9108bfc Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Wed, 17 Apr 2024 19:51:55 +0100 Subject: [PATCH 0283/2849] 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 56a31b1310694..45827a7bcec82 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 b94b0e1ed7369..21fc54fb9e9a0 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 48bcacff102c6..245b2eb1aad23 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 b4be11a83a9e8..49bee930cca93 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 0a7fce2fe75ed..383637d77173d 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 cd6669e4516de..3f71e34d33b7a 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 4bea96b68b82b13495b8859e7a31711e39398017 Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Wed, 17 Apr 2024 19:10:22 +0100 Subject: [PATCH 0284/2849] 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 cea394d79018b..e6bb90fbb4d5a 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 a1fa90e6415c5..991e2e3fb57e9 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 06d36455d5806..da6bcddbbb461 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 bba534f1bbe7b..f53cbf1b3e23f 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 19baefff8e2bf..b9346a62b4411 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 5da5cc05f592a..a50a65a7552b7 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 44cfecebc9ea5..03172a47b8f65 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 0a6e6a00a0de4..2d3b7b665294e 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 6baca4898d68c..7a7dc8158c279 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 0a0f0e9f6ee74..971155b210d65 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 b9c7a81407baa..328859870d476 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 245163cb8721f8af981b9af23478134072d858ce Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Wed, 17 Apr 2024 19:13:22 +0100 Subject: [PATCH 0285/2849] 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 328859870d476..e57d8c810081c 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 50b7d61c915f58580db035dda5df8c0bc5367f97 Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Wed, 17 Apr 2024 19:18:00 +0100 Subject: [PATCH 0286/2849] 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 da6bcddbbb461..3a9a787fd7099 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 03172a47b8f65..65dd80a92f67d 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 e57d8c810081c..94afae1431ff8 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 7a4f4711af73c9bf5ce62595ae256e2d48e5d52c Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Wed, 17 Apr 2024 19:22:02 +0100 Subject: [PATCH 0287/2849] 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 e6bb90fbb4d5a..9f7de642358b7 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 3a9a787fd7099..ace45414fbf82 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 f53cbf1b3e23f..9c0d47d3afb0d 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 b9346a62b4411..b1b951216282a 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 a50a65a7552b7..45b19da8f8400 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 65dd80a92f67d..536da5463c9a0 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 94afae1431ff8..7c297cbc6cdc1 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 e911435d90d640f31301cede9962fe2d1063b0b6 Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Wed, 17 Apr 2024 20:00:06 +0100 Subject: [PATCH 0288/2849] 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 73f3e5ccaf809..19de22a992e8f 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 c778f96d47986..d73bd134332f3 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 92145a22d380eb8425ff028c4a2e34f4e34a567c Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Wed, 24 Apr 2024 20:49:28 +0100 Subject: [PATCH 0289/2849] 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 2931d4cc929b8..fdf12abde2446 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 a6b0032792634..27c211e24e403 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 49fc84a0a95fc..0232f7d97c347 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 9c347a3558884..0000000000000 --- 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 af9d53eddc073..0000000000000 --- 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 e4aff43aee811..a97acd9ffab89 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 af9d53eddc073..0000000000000 --- 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 d6dafcd68ea92..45e8fad35cd9d 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 36c1aeaf19e621eec87bb9435c0fbfaa33036af9 Mon Sep 17 00:00:00 2001 From: Emil Gydesen Date: Sat, 16 Mar 2024 11:02:35 +0100 Subject: [PATCH 0290/2849] 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 cb86f9042a672..d44f4e1841777 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 6aa4ee52dd506..8d537557dae96 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 1ed8f0480691d..0cc7d9b3d79ac 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 97c7309bca8fc..30afd5ae093c3 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 3d4c5e2dc8857c9aa4b28ff1071fb65327acdcb6 Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Mon, 13 May 2024 23:25:13 +0200 Subject: [PATCH 0291/2849] 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 a6611b8ef1b22..9ef2a41969a67 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 99adbadad5a2ccd70ed7e7a483b7615bd043d999 Mon Sep 17 00:00:00 2001 From: Jonathon Penix Date: Fri, 10 May 2024 11:16:26 -0700 Subject: [PATCH 0292/2849] 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 1886f50cfe51d..50293b2d61e1c 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 681e1d41e0d270d2eee4be147a20e681db6b197c Mon Sep 17 00:00:00 2001 From: Anas Nashif Date: Fri, 12 Apr 2024 07:01:55 -0400 Subject: [PATCH 0293/2849] 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 240727d9e2438..e9e892320c44f 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 f8b841ae30022..af67331aa2991 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 0cb828d44376a07e79f9bf969f354e0c72972d98 Mon Sep 17 00:00:00 2001 From: Emil Gydesen Date: Mon, 13 May 2024 10:40:48 +0200 Subject: [PATCH 0294/2849] 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 f7c05a4e55f5e..7a9c1663594d1 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 f5ce0476c5d009fbd5bfc4817cbba16efd6fa4ac Mon Sep 17 00:00:00 2001 From: Nikodem Kastelik Date: Fri, 10 May 2024 16:46:29 +0200 Subject: [PATCH 0295/2849] 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 825f15f4c4d26..0beadf4237d14 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 25229b2fce6607d0954839b86c3905fea4e82d05 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mo=C5=84?= Date: Wed, 8 May 2024 14:31:32 +0200 Subject: [PATCH 0296/2849] 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 8f5547d36c79a..ea9dc2da7a424 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 41b856f8dd1b3e45d678cc2b143261f1df61ff6f Mon Sep 17 00:00:00 2001 From: Marcin Szymczyk Date: Wed, 10 Apr 2024 12:34:07 +0200 Subject: [PATCH 0297/2849] 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 0000000000000..f146dac821e10 --- /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 0000000000000..84fbad22f26ef --- /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 0000000000000..03db1a5ad18e4 --- /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 7b82235e1e3773127aae787fb68c390d451fe539 Mon Sep 17 00:00:00 2001 From: Bartosz Miller Date: Mon, 13 May 2024 12:47:03 +0200 Subject: [PATCH 0298/2849] 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 df8c7b54b1020..da8fa4f6690ae 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 f84e082f73511789eab69577521a16040b8e1fce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20G=C5=82=C4=85b?= Date: Fri, 10 May 2024 12:46:15 +0200 Subject: [PATCH 0299/2849] 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 0000000000000..748e06aef8358 --- /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 8982dfccd33db..52e19e8bb1861 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 7c8d53898228d8583861f4ef8411d984d0adc949 Mon Sep 17 00:00:00 2001 From: Alberto Escolar Piedras Date: Fri, 10 May 2024 11:06:44 +0200 Subject: [PATCH 0300/2849] 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 2607ae2a4be85..56d3b4ae5430e 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 b5f8b4b6b7533bc253dad5cb3ff1ba470e8c3759 Mon Sep 17 00:00:00 2001 From: Jun Lin Date: Mon, 6 May 2024 15:42:54 +0800 Subject: [PATCH 0301/2849] 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 af45fa59ddb08..ec9979c707725 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 2b219c48edecb..35a40411835d4 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 2ba0b78fdda29..583b5352fad7d 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 71b71015a9a4860f4a8d8d9f9fcb985d443cdfc0 Mon Sep 17 00:00:00 2001 From: Jun Lin Date: Mon, 6 May 2024 15:43:09 +0800 Subject: [PATCH 0302/2849] 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 41810666604a6..51802586c8c9e 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 e71569fc00f9705a16805e3b8819373554f2ecdc Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Mon, 13 May 2024 09:09:35 +0300 Subject: [PATCH 0303/2849] 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 374b083ce091a..35bfa49189f13 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 c11dc8b2caa43..d493e5b3251eb 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 3d1b8c6116df715b64f64bccd031e4e628185505 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Fri, 10 May 2024 13:47:20 +0300 Subject: [PATCH 0304/2849] 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 5cfb5c269b44c..ea310b5fc71b1 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 0000000000000..72c7b61506fe3 --- /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 3a711143f40ece1fe43647cb678bf1f2a62a09cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20G=C5=82=C4=85b?= Date: Fri, 10 May 2024 14:06:04 +0200 Subject: [PATCH 0305/2849] 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 0000000000000..3746c13c741b0 --- /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 3ab57ee0923c4..e4a9e148c5a1d 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 3cb5e4ed54fa0b4034cf08d21417730f310264ce Mon Sep 17 00:00:00 2001 From: Trung Hieu Le Date: Thu, 25 Apr 2024 12:05:52 +0200 Subject: [PATCH 0306/2849] 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 c564e77e49273..e87e07401d077 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 25cd1b8155451..b42829869e4f6 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 ce96362b49d6b..2ab29a50ce61f 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 e46fa5789e340..b96e5e58b3f27 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 dffa4e2cb7d2a33a8b1062cb284ce5c10867670d Mon Sep 17 00:00:00 2001 From: Trung Hieu Le Date: Thu, 25 Apr 2024 15:56:22 +0200 Subject: [PATCH 0307/2849] 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 395d8351794c1..a54b1b8a145f8 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 dcaceda39b2169f2426ff2a664c6deacf339fa0a Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Tue, 9 Apr 2024 23:33:32 +0000 Subject: [PATCH 0308/2849] 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 0628879d93302..ceb840ba1ff91 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 eb7d60dd67093d2b41810976e03a4bfdb9249b68 Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Wed, 10 Apr 2024 07:48:41 +0000 Subject: [PATCH 0309/2849] 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 631760f03cb18..2fd69c198e0b2 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 e9fa729a6b34d6152193a6deec68623b288b4699 Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Wed, 10 Apr 2024 07:46:49 +0000 Subject: [PATCH 0310/2849] 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 2fd69c198e0b2..af3a28057f6b1 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 0012725d85d0658beaf6d09db6417f9851e2c887 Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Wed, 10 Apr 2024 07:42:23 +0000 Subject: [PATCH 0311/2849] 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 ceb840ba1ff91..1953a246124f9 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 af3a28057f6b1..608cbac9c4652 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 d6d3c1098d5a46edaaa1f1e42133e5bb10698765 Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Wed, 10 Apr 2024 07:59:17 +0000 Subject: [PATCH 0312/2849] 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 1953a246124f9..f44e17ad6a953 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 6c2e661da0e344cfd6379bc084292b9be9e99544 Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Fri, 10 May 2024 17:28:23 +0000 Subject: [PATCH 0313/2849] 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 f2dffe4fe097a..6b4b57ac2a0bb 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 f2dffe4fe097a..6b4b57ac2a0bb 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 011f919a56808..b18b8cfe36262 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 89ffe9f16ae8d..4c53a55d59104 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 c8faa1e3809854e83bc7abe9d33737a5047d9125 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Ju=C5=99ena?= Date: Thu, 9 May 2024 12:38:00 +0200 Subject: [PATCH 0314/2849] 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 0000000000000..b6242139bfdfe --- /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 0000000000000..7dacd75eb4bae --- /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 0000000000000..4ad2396a16210 --- /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 0000000000000..699e51ae5959f --- /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 0000000000000..e1da9c4b2f44e --- /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 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 + * 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 0000000000000..fe16637e5efc6 --- /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 0000000000000..c54a159929890 --- /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 0000000000000..03e689742d93b --- /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 0000000000000..2d46284294ea7 --- /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 0000000000000..4b261299fed1e --- /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 0000000000000..f3ba3ad3b2a93 --- /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 0000000000000..cd2f2e5753b93 --- /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 d8bffffda0417414396dd052da6ff88ff72a3a78 Mon Sep 17 00:00:00 2001 From: Bartosz Miller Date: Wed, 24 Apr 2024 13:12:03 +0200 Subject: [PATCH 0315/2849] 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 0000000000000..0e4b8e8a8b6a7 --- /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 0000000000000..b0ac29c8a9713 --- /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 0000000000000..4b19609ecfbd1 --- /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 0000000000000..7041e579c1304 --- /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 0000000000000..d351b31e7074b --- /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 0000000000000..cac5addb33e72 --- /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 0000000000000..e36d79089f9a0 --- /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 3ca157e76f3b13cb03515f39b35deb611e48afab Mon Sep 17 00:00:00 2001 From: Armin Brauns Date: Thu, 28 Mar 2024 13:03:30 +0000 Subject: [PATCH 0316/2849] 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 ad9c6ac520cab..fbc7ff07e71cf 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 1e75fe49d7097..e86893b1b18f8 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 74cc85c526dbe8bfe23a85da3ff0bcb381bdfbf0 Mon Sep 17 00:00:00 2001 From: Armin Brauns Date: Thu, 28 Mar 2024 13:39:53 +0000 Subject: [PATCH 0317/2849] 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 a20419f001d36..ea80dbe86afc5 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 08cd15d5b018455dfafeeaa35af222aa773641bf Mon Sep 17 00:00:00 2001 From: Armin Brauns Date: Thu, 28 Mar 2024 13:16:01 +0000 Subject: [PATCH 0318/2849] 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 feb0f2f11a285..22b981b50225a 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 f2e3d3f951112ffec7f3a1a40bcf0c187dcae40e Mon Sep 17 00:00:00 2001 From: Jerzy Kasenberg Date: Mon, 13 May 2024 10:09:45 +0200 Subject: [PATCH 0319/2849] 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 59c8b2f109f15..5e624cd30119a 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 142634ae5e81f..d8205ed4925df 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 0dcaed68f0284..c987b579c1032 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 ea3e87dd123a6159d4f254dd5c2180ce24c893bd Mon Sep 17 00:00:00 2001 From: Sylvio Alves Date: Mon, 13 May 2024 10:14:28 +0200 Subject: [PATCH 0320/2849] 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 bd677cef701c1..c42258133ae27 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 0f5aa8aa814916e47217ce58506d072f42b02476 Mon Sep 17 00:00:00 2001 From: Emil Gydesen Date: Tue, 14 May 2024 13:11:13 +0200 Subject: [PATCH 0321/2849] 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 bfc9e3f452aeb..e783677ad0fc5 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 c1a39f31b277edadcf712af772a708d8449d9c41 Mon Sep 17 00:00:00 2001 From: Alberto Escolar Piedras Date: Tue, 14 May 2024 10:17:01 +0200 Subject: [PATCH 0322/2849] 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 8eb51bff5b873..4f2acc50b340b 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 cb8e4162a662c..279ebca410005 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 97b0ad699e8eacb90aa0957f4a6961cb392f2d25 Mon Sep 17 00:00:00 2001 From: Phi Bang Nguyen Date: Thu, 1 Feb 2024 23:28:38 +0100 Subject: [PATCH 0323/2849] 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 26c910b55c52b..43b1642da96f9 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 a1d680a1e746d..e70890f911d4f 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 1d7970be045927a43bc3d7828c82a758cf4ec322 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Fri, 10 May 2024 20:29:50 +0300 Subject: [PATCH 0324/2849] 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 77d829a570fd6..20b85237aea27 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 1230640076eedb591696d8ee75d007dbeea3f930 Mon Sep 17 00:00:00 2001 From: Dmitrii Golovanov Date: Fri, 10 May 2024 17:27:59 +0200 Subject: [PATCH 0325/2849] 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 eaef473af71d7..c3fe7da2f56a0 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 c8aa437930049..061e19ec9b2b7 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 5be57e1deb69f..fb0fc1d909b48 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 7eddd016ca9af..7a3b56a130f51 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 3657163a7ba45..a01d313cb28ee 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 1b1c99a214358..4f820532aeaf7 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 11de74c11f6ccdea9875c54c722bc0c29e8023d5 Mon Sep 17 00:00:00 2001 From: Dmitrii Golovanov Date: Fri, 10 May 2024 18:18:40 +0200 Subject: [PATCH 0326/2849] 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 061e19ec9b2b7..6fd6dae73a899 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 ae9096fe62c4293b7e14463269381232e0615e95 Mon Sep 17 00:00:00 2001 From: Carles Cufi Date: Fri, 10 May 2024 15:08:31 +0200 Subject: [PATCH 0327/2849] 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 1bd39950ddefe..e82e7f95ac14b 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 d48da4cfd1d6cc2f2f41699e496f9b268fd50934 Mon Sep 17 00:00:00 2001 From: Robert Lubos Date: Fri, 10 May 2024 15:35:28 +0200 Subject: [PATCH 0328/2849] 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 7106c38e735a4..c59d3031f63b2 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 3e046626c13647907026b48d19ad62d6a3ba5f84 Mon Sep 17 00:00:00 2001 From: Robert Lubos Date: Fri, 10 May 2024 15:52:24 +0200 Subject: [PATCH 0329/2849] 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 c59d3031f63b2..2ff4a1017a602 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 50c523636ba0c52b02c95f7136bc89a040eb8bd6 Mon Sep 17 00:00:00 2001 From: Robert Lubos Date: Fri, 10 May 2024 16:19:11 +0200 Subject: [PATCH 0330/2849] 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 2ff4a1017a602..1dbc0fb46a6b8 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 fab2f973644f512a248932ba732ab9f458159d8b Mon Sep 17 00:00:00 2001 From: Robert Lubos Date: Mon, 13 May 2024 10:32:58 +0200 Subject: [PATCH 0331/2849] 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 ace0a0128c2ff..c5046a2746a21 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 18c23daee3317c8b4b9ed69f7d8c81112b5185f8 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Fri, 10 May 2024 15:37:11 +0300 Subject: [PATCH 0332/2849] 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 430b8a860f7df..a5fe2515b5034 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 36b722dbf3819..0000fc670f3ce 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 5679d2caff840..b99f7c57511eb 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 29aa7598ef81b..8e3f0bb167041 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 3f15027bb35d6..5dea5bc3a7418 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 a9feeb48cb00b..bb759ccfdf872 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 0fdf19b8cfce0..8c74fc50e3905 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 ec1228981f37a..2bfc0bd055c4d 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 6d031c446224a..962ce3b146c2e 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 981d1b8f1fc33..0613b66edbf7e 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 d051150a26b64..54417bdffd997 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 91e17c11fcbca..175b3725255d8 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 b0429fe3b6d64..9fb3903d0e4e2 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 eb6c58e5a34c5..8c5dcb6d31f4c 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 618dc6b758606..a72bc01038493 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 a92a542f6d7f0..ba2013915d179 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 53559510ac4dd..59314c494d7ea 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 f37e9c6f309c2..b65082eb70f6f 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 f2bf1f7ffd455..1b32cbf6dc99e 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 ba983f09a734e..47c4f3f70629d 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 19de37a5a84d7..a9dcf2327e05a 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 35897ee66c606f960ac145d8824adffeceba4e6c Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Fri, 10 May 2024 15:41:33 +0300 Subject: [PATCH 0333/2849] 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 2bfc0bd055c4d..d7d0d57960963 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 962ce3b146c2e..11dc46dcc838f 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 0613b66edbf7e..3f62ed8b4f1e8 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 54417bdffd997..5d1f051461cc1 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 175b3725255d8..328a4905976af 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 9fb3903d0e4e2..f02acf526513f 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 484fe3f06c44de897ec0271d8cf36d52300627d7 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Fri, 10 May 2024 15:57:50 +0300 Subject: [PATCH 0334/2849] 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 8611765c70699..08aacc853f36c 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 5d1f051461cc1..247a50959da9d 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 a72bc01038493..d6f23f2db6415 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 e2b63adfefedf..bc843b5d9cabd 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 3032321938f4c1817c75b1ea84931569bc0cdf47 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Fri, 10 May 2024 17:58:00 +0300 Subject: [PATCH 0335/2849] 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 19de22a992e8f..762e581dece58 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 13dfd866169ee6b0e95300f60f67ae65ef4d793d Mon Sep 17 00:00:00 2001 From: Ayush Kothari Date: Fri, 10 May 2024 21:00:06 +0530 Subject: [PATCH 0336/2849] 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 cb07de20adcb1..48f213c7394c9 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 313d9039a5b54..ab3b88df83f58 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 53ceae5f5841576493f1cdafee4706d18317d018 Mon Sep 17 00:00:00 2001 From: Daniel DeGrasse Date: Thu, 9 May 2024 15:04:30 +0000 Subject: [PATCH 0337/2849] 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 3876e1adbf427..3eb5640d82de2 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 481462d4a658d9b3faf860c4c4889f3514642046 Mon Sep 17 00:00:00 2001 From: Daniel DeGrasse Date: Thu, 9 May 2024 17:04:33 +0000 Subject: [PATCH 0338/2849] 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 707d9f088cc37..6863649bc94a5 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 ba98dfd976cc36089ba5e9bb7f94ea440b52ad98 Mon Sep 17 00:00:00 2001 From: Daniel DeGrasse Date: Thu, 9 May 2024 17:10:16 +0000 Subject: [PATCH 0339/2849] 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 951d3f99a1e94..99c524a29b21c 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 c4eac60982e4708ddb6d165bad76c2bae235f02c Mon Sep 17 00:00:00 2001 From: Daniel DeGrasse Date: Thu, 9 May 2024 17:14:19 +0000 Subject: [PATCH 0340/2849] 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 6d2f30933e96c..b0bfa04ac486f 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 99c524a29b21c..39faadcd534af 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 372cf92060b7eb4655b5f2fb7da8d7839371638a Mon Sep 17 00:00:00 2001 From: Daniel DeGrasse Date: Thu, 9 May 2024 17:15:49 +0000 Subject: [PATCH 0341/2849] 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 b0bfa04ac486f..dd6c2da48f443 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 39faadcd534af..c3ad20aab4b2d 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 ef8b8a298379f1631db8b2670c0d2b0e9d816d5b Mon Sep 17 00:00:00 2001 From: Daniel DeGrasse Date: Thu, 9 May 2024 17:18:35 +0000 Subject: [PATCH 0342/2849] 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 e3ba54f2a5d68..7ce698b3dd650 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 4f65595b24e31bf00f2703752f664c0662fb1cfe Mon Sep 17 00:00:00 2001 From: Daniel DeGrasse Date: Thu, 9 May 2024 17:22:49 +0000 Subject: [PATCH 0343/2849] 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 bfcef6daebd74..d072f25f9246c 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 33f90e1eabccd9c7653706391d33371ffac3266f Mon Sep 17 00:00:00 2001 From: Daniel DeGrasse Date: Thu, 9 May 2024 17:24:28 +0000 Subject: [PATCH 0344/2849] 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 60bfc1c626249..f76b8554671c6 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 d02a07662da1a..e32be713e3b88 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 558c2916b998216502dd59662b13aed7aa27d507 Mon Sep 17 00:00:00 2001 From: Daniel DeGrasse Date: Wed, 1 May 2024 15:44:03 +0000 Subject: [PATCH 0345/2849] 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 43f90374380a7..48c4857a8eb55 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 e4b45f89d40dd..4252a98e859c1 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 9b2ae5d02b255e9d8bc3d6feddcfceb2a561fb8f Mon Sep 17 00:00:00 2001 From: Daniel DeGrasse Date: Wed, 1 May 2024 15:52:24 +0000 Subject: [PATCH 0346/2849] 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 bfb4a84e341b0..1db4e04d7770b 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 9c441f051d10d..4bd6b5bb44116 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 75a3c5b848b6dd2fc2a4409c2ffa0d72b2369b11 Mon Sep 17 00:00:00 2001 From: Ioannis Karachalios Date: Wed, 1 May 2024 13:02:31 +0300 Subject: [PATCH 0347/2849] 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 39daff3ff162d..60d7fb98c56b8 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 c147201adc483..197882b5536f6 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 c09b48ac003a3..ab12cc23a0083 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 f7f80b6cd7ea174fa196b5c0c3d47fb2bb015f6d Mon Sep 17 00:00:00 2001 From: Declan Snyder Date: Fri, 26 Apr 2024 10:29:52 -0500 Subject: [PATCH 0348/2849] 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 0000000000000..e151d2fdbe3d5 --- /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 c767ed6e27e045381ce7e77a5cf1ebd461205388 Mon Sep 17 00:00:00 2001 From: Declan Snyder Date: Fri, 26 Apr 2024 10:30:36 -0500 Subject: [PATCH 0349/2849] 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 0000000000000..7f5c5767d78ab --- /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 0000000000000..712a342eedc7e --- /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 b9e89ef688c44d5be18ca79b1c374012253f7603 Mon Sep 17 00:00:00 2001 From: Declan Snyder Date: Wed, 20 Mar 2024 10:38:31 -0500 Subject: [PATCH 0350/2849] 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 ae0ebcb5b54cc..cd4006bccd77e 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 725ec32c2c892..a61e7068e886c 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 0000000000000..137c33feeaf47 --- /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 fa990a7639bade371d6f48628f40d7e63c178389 Mon Sep 17 00:00:00 2001 From: Declan Snyder Date: Wed, 20 Mar 2024 10:39:00 -0500 Subject: [PATCH 0351/2849] 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 50cd660ac524e..d6869cc234a1c 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 87869775d03c1..417e1b9be943a 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 0000000000000..ba4835b1c7046 --- /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 79025c5524a219e2fa3cd4a9b2d0ecef86eccb7b Mon Sep 17 00:00:00 2001 From: Declan Snyder Date: Wed, 20 Mar 2024 10:40:08 -0500 Subject: [PATCH 0352/2849] 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 d78879e107a4d..22e34b4777ac1 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 f20393ee6dc66..dcf52c8437785 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 00a205ffbacb1289e43e4f51af48b0c7de0ad6e8 Mon Sep 17 00:00:00 2001 From: Declan Snyder Date: Fri, 26 Apr 2024 10:32:19 -0500 Subject: [PATCH 0353/2849] 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 21872376294bf..6216d381d037a 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 14ef7d2d2155ef77099632a0a39c3cb85ce8f408 Mon Sep 17 00:00:00 2001 From: Declan Snyder Date: Fri, 26 Apr 2024 10:33:10 -0500 Subject: [PATCH 0354/2849] 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 db7445f1c9541..d821b46b45c31 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 0000000000000..32098b10883ce --- /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 a4d6c8f5fea03..2096ad78eb9b4 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 0000000000000..53596ab11c413 --- /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 595ee908ba10c23ba9bd163b2eb793993c2ff7fb Mon Sep 17 00:00:00 2001 From: Declan Snyder Date: Fri, 26 Apr 2024 10:33:58 -0500 Subject: [PATCH 0355/2849] 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 d821b46b45c31..919f10479ee43 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 0000000000000..55409f2be1867 --- /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 e83c20d5fc0ff..9c7a53beef1f3 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 a2c9c65bfa484ec91b72bddab7980f058df114f3 Mon Sep 17 00:00:00 2001 From: Johann Fischer Date: Mon, 20 Nov 2023 15:37:23 +0100 Subject: [PATCH 0356/2849] 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 8fc380b970e0b..f15d0526e4ac1 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 92fc5316a4a37221ffb06424a580a38025deada1 Mon Sep 17 00:00:00 2001 From: Johann Fischer Date: Thu, 17 Aug 2023 00:07:12 +0200 Subject: [PATCH 0357/2849] 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 cec26a508ec7f..755950cc6519f 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 c0e8f0d96b63aa3b1816a1da2044a7902c970554 Mon Sep 17 00:00:00 2001 From: Johann Fischer Date: Mon, 19 Dec 2022 13:55:58 +0100 Subject: [PATCH 0358/2849] 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 0000000000000..03887acb0d887 --- /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 0000000000000..5dd6d0dad2354 --- /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 281c228632814..0c6c9b2426950 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 19fe3cceb8c65..42e489e9f4db8 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 0000000000000..8e3133a1dde89 --- /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 0000000000000..befdc9db9ccc9 --- /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 0000000000000..17b0efc1fbbe9 --- /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 0000000000000..d049b0c22a357 --- /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 0000000000000..c00a18b227a09 --- /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 fce6b20f611fc9c426c192b368f691254f9530ce Mon Sep 17 00:00:00 2001 From: Johann Fischer Date: Fri, 10 Nov 2023 18:52:26 +0100 Subject: [PATCH 0359/2849] 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 d384859f9fce6..d2217c00a4727 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 0000000000000..96c5455894806 --- /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 f638fefc58c21..018c1a04b8021 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 6a297418b4cbb..c42a96ed47408 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 0000000000000..8b7b5c5182139 --- /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 0000000000000..9c8894b2126c6 --- /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 859cc2f1feec93132e06753278be02889418333f Mon Sep 17 00:00:00 2001 From: Johann Fischer Date: Mon, 4 Dec 2023 11:43:29 +0100 Subject: [PATCH 0360/2849] 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 0000000000000..76d18842cff3a --- /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 0000000000000..96c5455894806 --- /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 0000000000000..b1936b5558868 --- /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 0000000000000..6433abbe7061b --- /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 0000000000000..2eb82c5df619c --- /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 0000000000000..16b02a9efb059 --- /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 0000000000000..bcd776622e843 --- /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 0000000000000..04ce14ad588e1 --- /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 0000000000000..daf6703b81a5d --- /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 0000000000000..1a2a146a5a95c --- /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 99804c77c4d8e0f60f398718b0c78844d50f0470 Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Wed, 8 May 2024 16:52:07 +0200 Subject: [PATCH 0361/2849] 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 8379670fab380..84511c1a4ccc5 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 09fc2dab430a85bc8b98fd2837ef804c41e5b921 Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Wed, 8 May 2024 17:47:54 +0200 Subject: [PATCH 0362/2849] 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 3532d2aeddd76..14412a6579a62 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 eff80ae5bc588f9dc2bc1c818f7a170a569cdc18 Mon Sep 17 00:00:00 2001 From: Pisit Sawangvonganan Date: Sun, 12 May 2024 16:22:37 +0700 Subject: [PATCH 0363/2849] 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 7f646f4e78951..ca48f140b86c2 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 6d129b2a2df1493d6a4692394296cc6b930c22ba Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sun, 12 May 2024 11:57:04 +0300 Subject: [PATCH 0364/2849] 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 d493e5b3251eb..7bfb609384356 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 799485f537c25..d718c37bc3505 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 3948401057f78..b455340bf389e 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 aad76a941651a2a8703492556653f18f0acc0629 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sun, 12 May 2024 11:57:51 +0300 Subject: [PATCH 0365/2849] 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 be564ac4a541e..ff72f2ed5bbde 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 ba1565b46d18a99e8eb0518683da8222b06665f4 Mon Sep 17 00:00:00 2001 From: Phi Bang Nguyen Date: Tue, 30 Jan 2024 15:37:51 +0100 Subject: [PATCH 0366/2849] 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 b9994d1e8c115..e4212cd8294c6 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 c20be8ad6a892..387b116d60154 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 d267ea7a5ad8f..77022d037d898 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 d2553d6891184..bf7fd01eeaadd 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 bd17c8629971ac2854d794f01b1996e8c6208838 Mon Sep 17 00:00:00 2001 From: Daniel DeGrasse Date: Fri, 10 May 2024 21:58:16 +0000 Subject: [PATCH 0367/2849] 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 84f8f2aee3b0b..812305a713504 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 da9361e544a1f81ccabecc147b618f49cd71e7c8 Mon Sep 17 00:00:00 2001 From: Daniel DeGrasse Date: Fri, 10 May 2024 22:02:56 +0000 Subject: [PATCH 0368/2849] 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 812305a713504..2265a60202483 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 bf61a47887bae2d683f6b92bcb26f42c3dae598e Mon Sep 17 00:00:00 2001 From: Daniel DeGrasse Date: Fri, 10 May 2024 22:03:39 +0000 Subject: [PATCH 0369/2849] 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 2265a60202483..2909ea104b15d 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 3493d95ed0b8c7b7521fc3b9279d7c04685310bf Mon Sep 17 00:00:00 2001 From: Daniel DeGrasse Date: Fri, 10 May 2024 22:04:32 +0000 Subject: [PATCH 0370/2849] 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 ad7d25a8ec72b..2410a6377c792 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 f0af6aa8b296c3aae4105d333cc6d013a5b2fa6a Mon Sep 17 00:00:00 2001 From: Daniel DeGrasse Date: Fri, 10 May 2024 22:07:45 +0000 Subject: [PATCH 0371/2849] 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 72cc76170b974..461a4ed628642 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 29b4bbf846129..0481fafddf55e 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 cf63ab6abff72..9dd884e07283c 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 11bb253d66a98..4d3e977138298 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 e1543f19692a2..0634ddcae56ff 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 4865e16784ea8..462edb3332bc3 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 2e9c4f6c2830d..a1c2b1c2da128 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 d0ae1a8b1057c0a8b510860d1cbdbb1cb79f2411 Mon Sep 17 00:00:00 2001 From: Stephanos Ioannidis Date: Tue, 14 May 2024 23:54:35 +0900 Subject: [PATCH 0372/2849] 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 1c5ded582f0df..63812a85eb291 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 769409d41cbfcca7d04a50521c25baaf91dc8de2 Mon Sep 17 00:00:00 2001 From: Troels Nilsson Date: Wed, 8 May 2024 13:36:57 +0200 Subject: [PATCH 0373/2849] 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 a7251748cca3a..f174ca02c728c 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 48ad0835074dd..ff06068a8e602 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 61d3773c43d0a..0e50bea63be17 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 06407816c38e1..b7beb40f38a11 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 c9d698634abbe..77bd1d5421d4f 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 27c337828593c4eab3f4011254bcfed7c5846c2f Mon Sep 17 00:00:00 2001 From: Dawid Niedzwiecki Date: Mon, 13 May 2024 08:52:41 +0200 Subject: [PATCH 0374/2849] 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 1ba8c33a7ec62..4fd5bd4a3e2fe 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 c9649bdef8bb541732f8dcf496f7684b61782371 Mon Sep 17 00:00:00 2001 From: Dawid Niedzwiecki Date: Mon, 13 May 2024 08:59:38 +0200 Subject: [PATCH 0375/2849] 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 15aa2063b47d6..7f73471f71810 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 d4d0bf1c201e8..ea45ecb846333 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 fe13b3444fd4f..c65df8bdffbdc 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 daaf06db94a4b9b64bb45ead01fc07ccccc84831 Mon Sep 17 00:00:00 2001 From: Benjamin Perseghetti Date: Fri, 10 May 2024 19:12:15 -0400 Subject: [PATCH 0376/2849] 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 d753682f46e46..617ac3e4b7f7c 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 a411ae93b7c1a2ec6efe2f9932b88d509d40bb4c Mon Sep 17 00:00:00 2001 From: Kamil Paszkiet Date: Mon, 6 May 2024 15:17:54 +0200 Subject: [PATCH 0377/2849] 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 09ddaa973f818..ea1eb1856db17 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 254f2497d7434..c02bda79c4eaf 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 d27e7196843f0..83c5d6b06fdad 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 30656544b94fa..f61880c1b0528 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 85c6ce69ca746c0867e7296100d1fb8c2b7c516e Mon Sep 17 00:00:00 2001 From: Kamil Paszkiet Date: Tue, 7 May 2024 08:58:01 +0200 Subject: [PATCH 0378/2849] 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 7f93629922365..daa732db522a0 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 0000000000000..635c696edf9d5 --- /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 0000000000000..9467c2926896d --- /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 0000000000000..3c250486af659 --- /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 0000000000000..e42250e6b248c --- /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 0000000000000..635c696edf9d5 --- /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 0000000000000..9467c2926896d --- /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 0000000000000..d896f500c9e45 --- /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 0000000000000..b2813ad46e12c --- /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 0000000000000..635c696edf9d5 --- /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 0000000000000..9467c2926896d --- /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 0000000000000..04b4de0e0867e --- /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 0000000000000..c5c9486c735cb --- /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 0000000000000..635c696edf9d5 --- /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 0000000000000..9467c2926896d --- /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 0000000000000..04b4de0e0867e --- /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 0000000000000..a4957e6f5ebb3 --- /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 80f8f722a3eb2..e116bea3da1eb 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 3b87a0b939ffcb7abca2e3714d18b1cbd45b164c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fin=20Maa=C3=9F?= Date: Mon, 6 May 2024 16:32:36 +0200 Subject: [PATCH 0379/2849] 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 fdb78a2c6ed32..c6554afa53903 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 00b2ef87444e4c57df0f6e7c517a5b1c52f8d7e6 Mon Sep 17 00:00:00 2001 From: Filip Kokosinski Date: Thu, 25 Apr 2024 13:18:46 +0200 Subject: [PATCH 0380/2849] 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 6c820813021c6..2c38ca1da1d7c 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 6c820813021c6..2c38ca1da1d7c 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 7596ee0d6eb1d..403d75cb74206 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 fb96f6d3d38a0..673d46680192f 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 fb96f6d3d38a0..673d46680192f 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 0000000000000..c4c5a8b174eca --- /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 20873731c6e9d..8329a1ec62b8c 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 0000000000000..25d769d5183a9 --- /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 0000000000000..936f0a1881526 --- /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 99aa65c72532315a614871648034af83cd29e442 Mon Sep 17 00:00:00 2001 From: Filip Kokosinski Date: Fri, 10 May 2024 09:52:23 +0200 Subject: [PATCH 0381/2849] 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 316162ddc0c1a..1d52f93af73e2 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 9023c27913e97614529e43db8dc187fe07bc7fab Mon Sep 17 00:00:00 2001 From: Francois Ramu Date: Wed, 6 Mar 2024 12:14:59 +0100 Subject: [PATCH 0382/2849] 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 79a4bbedca3c0..87e4237d96136 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 93ee60fe87132543d2dd84bb360b52ce01b8492d Mon Sep 17 00:00:00 2001 From: Pisit Sawangvonganan Date: Sun, 18 Feb 2024 23:26:37 +0700 Subject: [PATCH 0383/2849] 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 e5a7a06f35b82..503ab57b2f579 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 557ad8e45c68c053b0fab8e6ac5e48a610903a60 Mon Sep 17 00:00:00 2001 From: Pisit Sawangvonganan Date: Mon, 19 Feb 2024 01:55:12 +0700 Subject: [PATCH 0384/2849] 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 4dfcc8b5f57b1..3ae474f4304fc 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 503ab57b2f579..8b649e8093b86 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 13aa26eac2f17d096a0f4d8b950f59b79f754a4a Mon Sep 17 00:00:00 2001 From: Rafal Dyla Date: Thu, 14 Mar 2024 19:42:21 +0100 Subject: [PATCH 0385/2849] 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 91899e2cf86b6..5ea59e9469713 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 476c076fae115..6e69419147796 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 20109b66180e6..f8aff548436c8 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 c4a7134935cdd..3ee6356cc97c7 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 c9cc93e93293c..a7d55e4620aa5 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 0000000000000..c601b8a4233c9 --- /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 0000000000000..b4f6715fdd2d8 --- /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 0000000000000..2dc97ea63ceb9 --- /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 0000000000000..172b5957b2392 --- /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 0000000000000..572c05e864c78 --- /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 0000000000000..4512a91b36aff --- /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 0000000000000..0a6078a0db04e --- /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 0000000000000..883161e9f9236 --- /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 0000000000000..947a9b5a1afd2 --- /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 0000000000000..20e879c4f737e --- /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 0000000000000..b15e630eb2c89 --- /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 0000000000000..20cf6cece0e3e --- /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 1be3e6bc40ea8..a7eb08d9c9fcf 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 41786a6477f6923a6949ffa4778c458f4fa6da34 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20G=C5=82=C4=85bek?= Date: Fri, 26 Apr 2024 12:55:21 +0200 Subject: [PATCH 0386/2849] 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 0169664e6aa0a..89265c0e59d3b 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 42678ed2fcc00..27f1cfedf59af 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 aa0e3d6fc0fdd..0000000000000 --- 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 d57e18cdf1b63..e3f81b50ac438 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 0000000000000..e32fb1b8fdd60 --- /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 0000000000000..015e05918f04d --- /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 0000000000000..2a77552b3bfef --- /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 7436f9b936db5..a4b70ddcb3c80 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 53c350e17bf09b2165318308e203f5d536f17fe7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20G=C5=82=C4=85bek?= Date: Fri, 26 Apr 2024 12:59:59 +0200 Subject: [PATCH 0387/2849] 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 0000000000000..6aed768ebdae1 --- /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 0000000000000..435e4f4a6ccf8 --- /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 0000000000000..371797173d979 --- /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 0000000000000..012c93a8fa81b --- /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 0000000000000..97305dd78ef97 --- /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 0000000000000..ba4da1f417398 --- /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 0000000000000..1a12dcb270d81 --- /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 e255444179a6eb5fb901a0edba044135a838e398 Mon Sep 17 00:00:00 2001 From: Francois Ramu Date: Thu, 14 Mar 2024 09:38:40 +0100 Subject: [PATCH 0388/2849] 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 0000000000000..f2ade8c7689c8 --- /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 0000000000000..388c3d20bca1c --- /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 0000000000000..3e0610e80905d --- /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 182c5475e24373bddf19d3e641146d2fbc70eeea Mon Sep 17 00:00:00 2001 From: Francois Ramu Date: Thu, 14 Mar 2024 10:14:33 +0100 Subject: [PATCH 0389/2849] 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 ac7564c4708ea..54b9178c09183 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 6a1f816aa55ac..441a79868786f 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 0000000000000..3bea03801f3e3 --- /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 0000000000000..ae08e1d07cdc1 --- /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 0000000000000..d940cc93343b3 --- /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 6de81b2b7db405bdd6c3c8f9f7a77a9395e693a8 Mon Sep 17 00:00:00 2001 From: Francois Ramu Date: Thu, 14 Mar 2024 12:48:09 +0100 Subject: [PATCH 0390/2849] 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 a4acfcb8ee9c0..0a52c12fc0e55 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 5dff83a8be0babbe4d7a4079f925080adfcc388e Mon Sep 17 00:00:00 2001 From: Francois Ramu Date: Thu, 14 Mar 2024 12:52:22 +0100 Subject: [PATCH 0391/2849] 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 e27445c2ac3bf..05f13c64f4602 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 0289105758805e78ed3b2f60073ff90fbbaac3c8 Mon Sep 17 00:00:00 2001 From: Francois Ramu Date: Thu, 14 Mar 2024 12:44:55 +0100 Subject: [PATCH 0392/2849] 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 4ab18259153c7..c2742a68d4644 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 92dd10208dd24..7450df86ed277 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 b3bec006e9cb0..b7c7a06924386 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 2faadd309c6e8..e456b51103090 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 ed53fdd431a38c0a69868d327c0552f976321448 Mon Sep 17 00:00:00 2001 From: Henrik Brix Andersen Date: Wed, 15 May 2024 08:13:22 +0000 Subject: [PATCH 0393/2849] 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 2d46284294ea7..227cb9ab8c266 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 b989920c1b4f44ee0d9dc7119c8dfa4de12cb153 Mon Sep 17 00:00:00 2001 From: Henrik Brix Andersen Date: Wed, 15 May 2024 08:15:56 +0000 Subject: [PATCH 0394/2849] 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 e6aaacc8c34eb..3f7bbca688f07 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 3a8c9b8ac3c90a369b9a335dbd4850b39eace533 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mo=C5=84?= Date: Tue, 14 May 2024 07:12:50 +0200 Subject: [PATCH 0395/2849] 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 ea9dc2da7a424..2f6825e52b709 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 59212c198cf60f5c1380bb4a21eb9ff059ed4f85 Mon Sep 17 00:00:00 2001 From: Grzegorz Chwierut Date: Mon, 29 Apr 2024 16:38:37 +0200 Subject: [PATCH 0396/2849] 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 c3fe7da2f56a0..5ef10906b4e54 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 7a3b56a130f51..b5012646eb904 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 dfae5ba7debfaf680514a09ac5405a38ecba1c3e Mon Sep 17 00:00:00 2001 From: Valerio Setti Date: Tue, 14 May 2024 16:15:45 +0200 Subject: [PATCH 0397/2849] 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 d377bb46b8d1d..eec38e05089fb 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 dd5e629e16a40..9f916487099c1 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 248b66dfe3b96ebecb9efb3da69d246e2c317f8a Mon Sep 17 00:00:00 2001 From: Hake Huang Date: Tue, 16 Apr 2024 17:34:33 +0800 Subject: [PATCH 0398/2849] 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 5ef10906b4e54..b8007849eb55b 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 d45dbc26f00789566cef8ae29173fa905ed3c732 Mon Sep 17 00:00:00 2001 From: Dmitrii Golovanov Date: Tue, 7 May 2024 09:11:47 +0200 Subject: [PATCH 0399/2849] 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 ea1eb1856db17..177cc4b3f931f 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 c02bda79c4eaf..48c9df082c486 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 f61880c1b0528..33b0569f330bc 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 aa075beb7a1fb..c6382f9a9e337 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 a6a14360a98e51f77f0c423f8e62c989bdc78edc Mon Sep 17 00:00:00 2001 From: Emil Gydesen Date: Thu, 9 May 2024 13:53:27 +0200 Subject: [PATCH 0400/2849] 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 d73bd134332f3..ce4215db4a37e 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 08a2a642eb029..cc96141213153 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 aef75d072e485..6013afbf81776 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 dfe868fac45a1..6f210a4ae5eb3 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 b278eb3255665..75b2ed716e86e 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 86f30cad9f4b1..58beed0f7bf89 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 7b2e20946d4bd2d6364d3323a74cd6c917f3c29d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20G=C5=82=C4=85b?= Date: Fri, 10 May 2024 13:30:41 +0200 Subject: [PATCH 0401/2849] 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 0000000000000..94e0d719af4ef --- /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 c41438c4969a718feed7ddbd5663d2d7fbffb205 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20G=C5=82=C4=85b?= Date: Fri, 10 May 2024 15:33:41 +0200 Subject: [PATCH 0402/2849] 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 6e69419147796..5cd3d5b78e825 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 d2e08319bd17d41ccaea9c86aff86ba8441dd13d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20G=C5=82=C4=85b?= Date: Fri, 10 May 2024 16:09:17 +0200 Subject: [PATCH 0403/2849] 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 68d169331ef83..53bbff4a46006 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 b3004be0a7e8e92ab840eaacca315889fbb82201 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20G=C5=82=C4=85b?= Date: Wed, 15 May 2024 11:00:43 +0200 Subject: [PATCH 0404/2849] 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 0000000000000..66157d79fb36f --- /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 0000000000000..66157d79fb36f --- /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 01b57b499979ccd93f6a38cf37da878a2069c48d Mon Sep 17 00:00:00 2001 From: Seppo Takalo Date: Fri, 10 May 2024 13:35:11 +0300 Subject: [PATCH 0405/2849] 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 762e581dece58..8eaed64cb5e0b 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 ce4215db4a37e..12c90c0298bb1 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 e68f5fb47ad4c..68a5ef9617ed5 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 dd6dcd8d59983..5ef2e1cf127c0 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 98055baa580cf..d4aa638889070 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 17814ae134cec..861074513440d 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 f679d7e4a606e..c44df2c54312a 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 1268b7da56d95..bfe713a1cbec6 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 96944e0c16ad5..9fae4cfeb2547 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 05a1afc9806e8..2b5381d564c9e 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 b2d147060a02e..85bb2335c2e91 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 55b9f7728cabd..883dece531d2b 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 3da496b2ca1a6..da1cf464d83fb 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 7dca2ed39560d..f6b59591d7d66 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 07782a86756cc..475363a75efaf 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 ba843db0ebdfb..6d258b9d5fbd0 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 833002e56c49a..cf4798d745657 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 ec1274d07fffb..87fb1b837613d 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 3596f432476f1..462ed32fafd6f 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 e5eb8c56efb1c..287be88f72645 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 cdebef24532b9..208423eb04a41 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 ad31316354808..1ba3789f1cf3d 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 106ef95165340..fb82fe6c3f5c4 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 a7d3e541bbec4..9c1dfc0ca1d6f 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 f1466be6c87e9..69dfd5c1f8cd3 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 e1eac08554ff5..c4c782d538f8d 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 3ead504bc9419..54bda0a0ca15a 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 4c193cfd50b38..b6178abb17f1d 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 a9e91af37547a4f11699c4ddf5f1ec54265fd624 Mon Sep 17 00:00:00 2001 From: Seppo Takalo Date: Fri, 10 May 2024 17:34:48 +0300 Subject: [PATCH 0406/2849] 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 d8e0b6fc61fb6..4fdd7228f707c 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 5f4d3e20269bf..153423f6402a1 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 6115e6f40e389..39d998db6f6f0 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 181f15ebf6138..198c3fc2880ed 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 0000000000000..27bece69f1e31 --- /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 0000000000000..7ed44093dbd58 --- /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 cb4ab22acd237..bc668c15c3cea 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 37f6803833b80a981fa7fdd21bd67c2450af2025 Mon Sep 17 00:00:00 2001 From: Seppo Takalo Date: Fri, 10 May 2024 17:41:01 +0300 Subject: [PATCH 0407/2849] 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 462ed32fafd6f..f7e79dc40aa7a 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 6257576ce6962e6ea74420c28e7ef5eb291c6286 Mon Sep 17 00:00:00 2001 From: Seppo Takalo Date: Fri, 10 May 2024 17:42:28 +0300 Subject: [PATCH 0408/2849] 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 39d998db6f6f0..e5de79a39d30f 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 15a1b6d5c2ec6ef76ebfaed86994cdeb2f82bea9 Mon Sep 17 00:00:00 2001 From: John Johnson Date: Mon, 13 May 2024 10:10:57 +0200 Subject: [PATCH 0409/2849] 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 2261a11f714a1..ff32e3884efa2 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 c5fc2e743c9ebf6aeb0a3f8c0b516e129bae7e43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fin=20Maa=C3=9F?= Date: Mon, 13 May 2024 10:55:34 +0200 Subject: [PATCH 0410/2849] 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 aa72793a2421e..82f7202048e08 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 8e13268439b2e9c6666c26b43b31462354b883ce Mon Sep 17 00:00:00 2001 From: Armando Visconti Date: Mon, 13 May 2024 14:07:22 +0200 Subject: [PATCH 0411/2849] 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 0ce9b8862a384..38291b114719e 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 2b496759eb0720fb1d8eaa60d2a85663fdb170b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fin=20Maa=C3=9F?= Date: Mon, 13 May 2024 15:57:55 +0200 Subject: [PATCH 0412/2849] 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 332ad5e657187..5fc2780fdae96 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 243f114d5158e2afe70b26577015816da08123a5 Mon Sep 17 00:00:00 2001 From: Piotr Kosycarz Date: Mon, 13 May 2024 15:05:20 +0200 Subject: [PATCH 0413/2849] 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 149dd1724838e..95c772d7d890d 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 faf6fd169c15b39c95315b014faaacb7ff57ea25 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20G=C5=82=C4=85b?= Date: Mon, 13 May 2024 10:44:29 +0200 Subject: [PATCH 0414/2849] 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 198f4db403b38..2f83ef80de610 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 53bbff4a46006..e36f2e21ffea6 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 a64b069785740c30d767f4ab33f1cafe8387102a Mon Sep 17 00:00:00 2001 From: Hao Luo Date: Wed, 20 Dec 2023 14:54:04 +0800 Subject: [PATCH 0415/2849] 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 78bba84b8524a..97021e84f2717 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 c76500facc455..1be99d9d92bdf 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 910fca95567f9..e510c52ad44b7 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 db00dbedcd647..fe17883861b22 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 e264a4096d8ce..0c0f1db458c52 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 f863ee14ba81c..5ae40c06790a2 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 988e5b48a7fa0..ac53b55883e2d 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 0beadf4237d14..40a896f65bc5a 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 6771e797298837ab3ee5820b2c24069c1d5cb613 Mon Sep 17 00:00:00 2001 From: Ioannis Karachalios Date: Wed, 1 May 2024 16:03:36 +0300 Subject: [PATCH 0416/2849] 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 34b4913118160..d487e093a080f 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 28b6f08e100bf..0b42f77f4f8fc 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 481bd6db8bb9718d390834870ced0aaf7017d2f0 Mon Sep 17 00:00:00 2001 From: Daniel Schultz Date: Fri, 26 Apr 2024 07:59:47 -0700 Subject: [PATCH 0417/2849] 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 0bde22965df24..bb484358db184 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 21920433fc7f1..93970fd70a79a 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 3ca3131a7dff77bbf7af6faee285bccd3160c427 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Karol=20Laso=C5=84czyk?= Date: Wed, 7 Feb 2024 14:19:30 +0100 Subject: [PATCH 0418/2849] 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 6d1973ca0aae9..e5e658c893aee 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 1dd537bbe47a356868e04a10d817ee5db8b85ee6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Karol=20Laso=C5=84czyk?= Date: Wed, 7 Feb 2024 14:21:59 +0100 Subject: [PATCH 0419/2849] 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 159bb224258c8..24b15763bdc8f 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 64d79ea45c79da3c6ce7fabbc06570f961ea7adc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Karol=20Laso=C5=84czyk?= Date: Wed, 7 Feb 2024 14:23:08 +0100 Subject: [PATCH 0420/2849] 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 0000000000000..f185624f9b933 --- /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 0000000000000..a0639a405c405 --- /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 00d2fc51355dce5f01ecc18ba573ed3bc4fa1fbb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Karol=20Laso=C5=84czyk?= Date: Wed, 7 Feb 2024 14:24:15 +0100 Subject: [PATCH 0421/2849] 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 0000000000000..e10ddc5432828 --- /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 394e0974a4ac42879c559128678577cbf7897b13 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Karol=20Laso=C5=84czyk?= Date: Wed, 8 May 2024 08:31:32 +0200 Subject: [PATCH 0422/2849] 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 057c3b3f390bb..fd563bc6c1e31 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 319a8867ef742cdd2b3f96615ea2b814099bf48a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20G=C5=82=C4=85b?= Date: Thu, 14 Mar 2024 12:21:59 +0100 Subject: [PATCH 0423/2849] 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 706c2621bbb63..1c23c9452b41a 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 4041a2507d6e6274e30f3328a579239356cb9d88 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20G=C5=82=C4=85b?= Date: Wed, 15 May 2024 13:16:55 +0200 Subject: [PATCH 0424/2849] 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 65569ad30a431..b16daccb2e37e 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 dd2132c3094e31d064ec3f0a8edc9944c757d058 Mon Sep 17 00:00:00 2001 From: Evgeniy Paltsev Date: Tue, 14 May 2024 23:36:10 +0100 Subject: [PATCH 0425/2849] 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 77f9820f681b6..9825f700e2b62 100644 --- a/MAINTAINERS.yml +++ b/MAINTAINERS.yml @@ -3150,7 +3150,6 @@ Synopsys Platforms: collaborators: - abrodkin - evgeniy-paltsev - - IRISZZW files: - soc/snps/ - boards/snps/ From 14e69c85fe20f90857163f21110274cb36c7db54 Mon Sep 17 00:00:00 2001 From: Evgeniy Paltsev Date: Tue, 14 May 2024 23:42:09 +0100 Subject: [PATCH 0426/2849] 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 9825f700e2b62..c31f7b35956f3 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 62e32fa7c21e16286c8783feaabe4c2ea13801d3 Mon Sep 17 00:00:00 2001 From: Evgeniy Paltsev Date: Tue, 14 May 2024 23:46:24 +0100 Subject: [PATCH 0427/2849] 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 c31f7b35956f3..2d464460eb59c 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 69c6732d23d185a382637202b1134d551ae111fc Mon Sep 17 00:00:00 2001 From: Mykola Kvach Date: Tue, 14 May 2024 20:47:08 +0300 Subject: [PATCH 0428/2849] 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 49d373897b38e..d888a5fd6dcc4 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 56882e2d913b17a7aa970c3854de3e041f3a2885 Mon Sep 17 00:00:00 2001 From: Ayush Singh Date: Mon, 13 May 2024 19:38:42 +0530 Subject: [PATCH 0429/2849] 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 1b97bdde7b92c..97d9e1e914084 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 f71a4184f3025ac77b6e17d0fa6d1386f20f23f3 Mon Sep 17 00:00:00 2001 From: Lukasz Mrugala Date: Mon, 13 May 2024 12:39:44 +0000 Subject: [PATCH 0430/2849] 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 c97e93204479b..554df8545fb2e 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 74402561fc190..565fa9dadd848 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 6d2df0dbf77dbb68d6a8836e74e5fa932056878e Mon Sep 17 00:00:00 2001 From: Daniel DeGrasse Date: Mon, 13 May 2024 10:10:58 -0500 Subject: [PATCH 0431/2849] 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 b4cf8b26bfbf1..266ff00218497 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 f3ef45a79062e..5442db5bb6737 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 b474319510dda..9415c4660d1c7 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 b2b3ae93b79a0..f6d5f12b17330 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 3544d15980c3b..15301e002c717 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 89ab98c92b108..81d844caf75df 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 dcbe7539d6482..c2acb4cb09823 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 c092f8da95d82..50d239c805beb 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 0ce1024b6d08b..b92c045ee2359 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 22fa0c08859d1893d8d212c10c0a6cf05a37e353 Mon Sep 17 00:00:00 2001 From: Daniel DeGrasse Date: Mon, 13 May 2024 10:12:12 -0500 Subject: [PATCH 0432/2849] 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 5ee0c79e91500..9fc566158bc28 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 5dde5416b3ea59bbc9ba6f29dd6079a3198c92f6 Mon Sep 17 00:00:00 2001 From: Zhaoxiang Jin Date: Fri, 10 May 2024 09:40:47 +0800 Subject: [PATCH 0433/2849] 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 3d2ba23010e31..e15488e721078 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 fd736c4f2d19c5ad817cb2ca627f1c33cf837166 Mon Sep 17 00:00:00 2001 From: Zhaoxiang Jin Date: Fri, 10 May 2024 09:46:11 +0800 Subject: [PATCH 0434/2849] 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 e15488e721078..d3aa0f48a1524 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 e3466ad29d5e0..8d5acb1f2bc25 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 23e37896d8f087451b3c525b2a401bb714fc8fd2 Mon Sep 17 00:00:00 2001 From: Zhaoxiang Jin Date: Sat, 20 Apr 2024 23:59:11 +0800 Subject: [PATCH 0435/2849] 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 8eaed64cb5e0b..0ba7d361c0328 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 db87c6c0ff86cbc77ff3a6b7d60d1fd7a1ccbb35 Mon Sep 17 00:00:00 2001 From: Zhaoxiang Jin Date: Fri, 26 Apr 2024 13:37:19 +0800 Subject: [PATCH 0436/2849] 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 1f47328496f7c..02c6e7ac648ee 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 f61c6fdf06fc1283ca9f8328982a51cc9f7239a6 Mon Sep 17 00:00:00 2001 From: Zhaoxiang Jin Date: Fri, 19 Apr 2024 08:51:20 +0800 Subject: [PATCH 0437/2849] 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 2410a6377c792..fc125774e62ef 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 71c60a84f1cd2351cc5c76f26c8ab141aeb97803 Mon Sep 17 00:00:00 2001 From: Zhaoxiang Jin Date: Thu, 18 Apr 2024 16:43:42 +0800 Subject: [PATCH 0438/2849] 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 fc125774e62ef..890e7d007dfd8 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 979d90bb9589276974ca61e7cf5eb8f2a37bde74 Mon Sep 17 00:00:00 2001 From: Zhaoxiang Jin Date: Fri, 19 Apr 2024 08:52:25 +0800 Subject: [PATCH 0439/2849] 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 0481fafddf55e..d8ed68f6d7ce1 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 9dd884e07283c..5fd4904e5bb71 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 462edb3332bc3..52d9bf8c0bb4b 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 a1c2b1c2da128..2f4ed54a7c72c 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 85087e2d5d2fee8e48a4ebacc254cbdf561b6191 Mon Sep 17 00:00:00 2001 From: Zhaoxiang Jin Date: Thu, 18 Apr 2024 16:45:52 +0800 Subject: [PATCH 0440/2849] 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 d8ed68f6d7ce1..b79265127b3c9 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 5fd4904e5bb71..b04849a61dc25 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 4d3e977138298..8bdc9e1c91fe7 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 0634ddcae56ff..e928f64ab33bc 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 52d9bf8c0bb4b..338e8e520ae7c 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 2f4ed54a7c72c..10127d1a6693c 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 a3bad6769650f5352f7b506350469ca0b43e494a Mon Sep 17 00:00:00 2001 From: Zhaoxiang Jin Date: Thu, 18 Apr 2024 16:47:16 +0800 Subject: [PATCH 0441/2849] 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 0000000000000..051e3c1a3a47f --- /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 3dc82a66067d5352b3d5f3606396af009b011e6e Mon Sep 17 00:00:00 2001 From: Zhaoxiang Jin Date: Thu, 18 Apr 2024 16:48:39 +0800 Subject: [PATCH 0442/2849] 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 0000000000000..99d447efc68ab --- /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 1805c4797f04773777e6025937216b5dabb0f9e2 Mon Sep 17 00:00:00 2001 From: Zhaoxiang Jin Date: Tue, 7 May 2024 10:15:23 +0800 Subject: [PATCH 0443/2849] 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 0000000000000..3dfb29da938a4 --- /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 d545c1f377eec19a11155f293ff61c4f9f2fc153 Mon Sep 17 00:00:00 2001 From: cyliang tw Date: Thu, 2 May 2024 17:56:58 +0800 Subject: [PATCH 0444/2849] 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 1ebbd9118a074..5a755676e8cc1 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 22d574cb3c4c839ed7014995bed81e36fb248096 Mon Sep 17 00:00:00 2001 From: Johann Fischer Date: Fri, 12 Apr 2024 10:55:09 +0200 Subject: [PATCH 0445/2849] 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 7d783422ec3d0..72d3a84e5b46d 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 b9afb534fa1d1..8bf3c7a43a4c3 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 693191467d28dadc97c440b5b443e31796c58b68 Mon Sep 17 00:00:00 2001 From: Johann Fischer Date: Fri, 12 Apr 2024 12:30:50 +0200 Subject: [PATCH 0446/2849] 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 f278ded3e7616..1a61c41523b07 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 00ef52a386566..a11cff7d1daff 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 41cc248aa6b3a..a9375fa3b7c88 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 8bf3c7a43a4c3..b70b85928f4c0 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 48f2a4bc1ad9ec33d0826cfac94c1cf6eca89aae Mon Sep 17 00:00:00 2001 From: Johann Fischer Date: Fri, 12 Apr 2024 13:16:49 +0200 Subject: [PATCH 0447/2849] 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 90a73d592307c..eeed077ebc47a 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 180d136b18611..40999b0f7e4fa 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 4c360f38d1f1421c40522ffb2f088944b52a37b6 Mon Sep 17 00:00:00 2001 From: Johann Fischer Date: Fri, 12 Apr 2024 13:40:46 +0200 Subject: [PATCH 0448/2849] 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 7e13d565a736a..2e4d4dbcf32cc 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 1a61c41523b07..ded72ebade979 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 f13c1266f53af..0f83839d20e06 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 ba2e257d06248600e8768cc64af0e05fe6c100f9 Mon Sep 17 00:00:00 2001 From: Johann Fischer Date: Fri, 12 Apr 2024 15:36:15 +0200 Subject: [PATCH 0449/2849] 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 d4ecc130587c4..f02dfcdc308b8 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 c3ec41bdf8e9c3e36966bffa92799d3f3f916687 Mon Sep 17 00:00:00 2001 From: Johann Fischer Date: Fri, 12 Apr 2024 17:50:22 +0200 Subject: [PATCH 0450/2849] 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 ded72ebade979..1797b54f6dc2f 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 31ac1a5f7a0a6..fa68313ce8db0 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 eb9b46c11822b83dd741a67718b0d7c10d0434af Mon Sep 17 00:00:00 2001 From: Johann Fischer Date: Fri, 10 May 2024 18:17:38 +0200 Subject: [PATCH 0451/2849] 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 0f83839d20e06..9057e439040b8 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 2c0187ae849f12a9996201cbd21158b84cc54e14 Mon Sep 17 00:00:00 2001 From: Johann Fischer Date: Fri, 12 Apr 2024 18:19:46 +0200 Subject: [PATCH 0452/2849] 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 a9375fa3b7c88..91f7a8db7f7af 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 bc183d12780fd51396b1edabb4948bca92789102 Mon Sep 17 00:00:00 2001 From: Johann Fischer Date: Fri, 12 Apr 2024 18:24:37 +0200 Subject: [PATCH 0453/2849] 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 c5147519f8704..f08928438b777 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 4efc03520966a96e1a5dcf5369f75503626c2b42 Mon Sep 17 00:00:00 2001 From: Dmitrii Golovanov Date: Wed, 15 May 2024 17:34:16 +0200 Subject: [PATCH 0454/2849] 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 177cc4b3f931f..dcd8fe9189cf8 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 84144c6833f2ee1dbf40ee836d0a03b332bb217c Mon Sep 17 00:00:00 2001 From: Lyle Zhu Date: Wed, 13 Mar 2024 09:44:14 +0800 Subject: [PATCH 0455/2849] 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 0000000000000..6e5173d9fa4c1 --- /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 6cd4006c91abc..ab28df1bcec32 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 328a4905976af..9c0e53e80e135 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 48b3935f86f04..039f961c78627 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 0000000000000..eaf06d088051f --- /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 0000000000000..82b3aa88131d1 --- /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 50c883fedec1b..116807187046e 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 514c78546c2bcb3d17e309c5beb16fe9474894aa Mon Sep 17 00:00:00 2001 From: Lyle Zhu Date: Wed, 13 Mar 2024 11:31:05 +0800 Subject: [PATCH 0456/2849] 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 cbcbf4ea503be..2e91eda5c13c8 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 4c7b19fa5ab5e116d734cc62ed19c9354161daf1 Mon Sep 17 00:00:00 2001 From: Lyle Zhu Date: Wed, 13 Mar 2024 14:43:45 +0800 Subject: [PATCH 0457/2849] 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 0000000000000..af90adf8b82e2 --- /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 0000000000000..f3a1edbcdc9b1 --- /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 0000000000000..9d2e2d9343aca --- /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 0000000000000..cd315ed26b8b7 --- /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 0000000000000..416834fc191e8 --- /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 0000000000000..03c76eb0805b5 --- /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 c3ac8574380a2a485d3c7a7ae674f0c3a454d8b7 Mon Sep 17 00:00:00 2001 From: Lyle Zhu Date: Thu, 14 Mar 2024 10:50:56 +0800 Subject: [PATCH 0458/2849] 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 d7d0d57960963..9ccd4e184f6f8 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 804dbdd43cdaea575d0f38a54df4a9aa2b7ef090 Mon Sep 17 00:00:00 2001 From: Lyle Zhu Date: Fri, 15 Mar 2024 14:58:14 +0800 Subject: [PATCH 0459/2849] 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 9c0e53e80e135..4005d7752df09 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 615fe2466beb7694e41d06bf4f3578c9ca8519d4 Mon Sep 17 00:00:00 2001 From: Lyle Zhu Date: Wed, 24 Apr 2024 16:05:57 +0800 Subject: [PATCH 0460/2849] 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 5664506931c82..3b4f7f44ddbfd 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 4005d7752df09..a5d16a986b7ef 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 5da8916ad54497830de09d75f51e736ce8e4b13c Mon Sep 17 00:00:00 2001 From: Lyle Zhu Date: Thu, 25 Apr 2024 15:25:27 +0800 Subject: [PATCH 0461/2849] 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 a5d16a986b7ef..f880ed805d99b 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 0000000000000..2869978f9c78c --- /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 fa6df6a51a781da3f512dbd571d99431ea06fc6b Mon Sep 17 00:00:00 2001 From: Lyle Zhu Date: Thu, 25 Apr 2024 14:41:37 +0800 Subject: [PATCH 0462/2849] 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 eaf06d088051f..034cd324b6ae2 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 8599c509b347a870e5d65e624a308e9d032be754 Mon Sep 17 00:00:00 2001 From: Phi Bang Nguyen Date: Wed, 10 Apr 2024 17:08:26 +0200 Subject: [PATCH 0463/2849] 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 40a896f65bc5a..4fd16a2f7d6f0 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 d9e83c90269dd7622e6fdc782ce3e09b7d8c31c5 Mon Sep 17 00:00:00 2001 From: Mahesh Mahadevan Date: Mon, 6 May 2024 12:02:25 -0500 Subject: [PATCH 0464/2849] 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 e36eba8918252..d62662063eec3 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 04ce8801d9cbdc4fc33b58cb88d817296445cbe1 Mon Sep 17 00:00:00 2001 From: Mahesh Mahadevan Date: Mon, 6 May 2024 10:56:21 -0500 Subject: [PATCH 0465/2849] 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 890e7d007dfd8..31e280e556e4e 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 c68a8818c418a52bfd6a943e0ece7aa3b0ef3772 Mon Sep 17 00:00:00 2001 From: Mahesh Mahadevan Date: Mon, 6 May 2024 11:04:09 -0500 Subject: [PATCH 0466/2849] 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 1f310d9fa566d..3bf1d3a881a48 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 a6b3b4bb96e86d12de90d7bd47be6470405d561f Mon Sep 17 00:00:00 2001 From: Mahesh Mahadevan Date: Mon, 6 May 2024 10:50:32 -0500 Subject: [PATCH 0467/2849] 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 b79265127b3c9..e6568204ce9f7 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 b04849a61dc25..a7724ad69ce04 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 338e8e520ae7c..e3d80335db2cc 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 10127d1a6693c..ef6ea7114dc96 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 2be937dca442f02c7ef8e944540af5de2681dbe5 Mon Sep 17 00:00:00 2001 From: Daniel DeGrasse Date: Fri, 10 May 2024 22:20:43 +0000 Subject: [PATCH 0468/2849] 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 1ee9b7a1ba915..205b367a74174 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 9a4698159d59517c1498122733a74b509254dd87 Mon Sep 17 00:00:00 2001 From: Yong Cong Sin Date: Mon, 13 May 2024 13:16:25 +0800 Subject: [PATCH 0469/2849] 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 7152da2066c72..05d7f4c99c3ed 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 8c8123466a4adb57e2c14f51a3ea782053b5befe Mon Sep 17 00:00:00 2001 From: Yong Cong Sin Date: Mon, 13 May 2024 15:48:46 +0800 Subject: [PATCH 0470/2849] 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 0000000000000..5348bd113709e --- /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 31d2f11f46f2b..8ac350b3c97ff 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 7d963bed29c8b..b935b5c596e1d 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 a82a54cd38c029b5462cc879e63b94fe4453010f Mon Sep 17 00:00:00 2001 From: Yong Cong Sin Date: Mon, 13 May 2024 17:44:03 +0800 Subject: [PATCH 0471/2849] 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 05d7f4c99c3ed..07809c488aaae 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 771451f6168736e40d6faa4e2c92fcafcd3a0102 Mon Sep 17 00:00:00 2001 From: Daniel DeGrasse Date: Mon, 13 May 2024 14:44:09 -0500 Subject: [PATCH 0472/2849] 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 ed61932e65516..f75f2b9e7eb42 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 06f35746850299d2ed94d06f8b17cc29fd5ab40f Mon Sep 17 00:00:00 2001 From: Daniel DeGrasse Date: Mon, 13 May 2024 14:48:56 -0500 Subject: [PATCH 0473/2849] 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 f75f2b9e7eb42..88de0153f3f8e 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 87030f4cbf7a937a5723b0a623a398a6d71efda1 Mon Sep 17 00:00:00 2001 From: Daniel DeGrasse Date: Mon, 13 May 2024 15:45:44 -0500 Subject: [PATCH 0474/2849] 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 88de0153f3f8e..4724eb2625345 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 82ce2b412d594c06f44b6075877816993db0ced0 Mon Sep 17 00:00:00 2001 From: Daniel DeGrasse Date: Mon, 13 May 2024 16:29:43 -0500 Subject: [PATCH 0475/2849] 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 4724eb2625345..7e08488805c55 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 5b9854cc95bfe..ed7acaf439bbc 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 ed64818565e8d9d34ee31a96afd3e18cfefe5dc1 Mon Sep 17 00:00:00 2001 From: Daniel DeGrasse Date: Mon, 13 May 2024 17:22:51 -0500 Subject: [PATCH 0476/2849] 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 64c813b1090b0..a81403c5f82c1 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 1a256c7c21e710dfe4ae469ae51ec69eb519969d Mon Sep 17 00:00:00 2001 From: Daniel DeGrasse Date: Mon, 13 May 2024 16:35:55 -0500 Subject: [PATCH 0477/2849] 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 84c07bb3998e3..1bae0941041e3 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 3b718bf1fe55c9c2c21f813c38152e9eee25e4c2 Mon Sep 17 00:00:00 2001 From: Daniel DeGrasse Date: Mon, 13 May 2024 16:45:15 -0500 Subject: [PATCH 0478/2849] 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 2e5d20ee86adf..8d637f0fd577e 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 6d7a6ea8a87d90158fbdcf72ca500b596689ddc0 Mon Sep 17 00:00:00 2001 From: Daniel DeGrasse Date: Tue, 14 May 2024 16:15:45 -0500 Subject: [PATCH 0479/2849] 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 7d4ebf11dd3c3..debf80f46551b 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 0887986b886d52db6d584271a134d9d12f8fb772 Mon Sep 17 00:00:00 2001 From: Dmitrii Golovanov Date: Wed, 15 May 2024 22:22:38 +0200 Subject: [PATCH 0480/2849] 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 b10aae71d438d..266b60d2bf2ec 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 0f7cd6128ecf0f1be2287e93ac9fdd1ab07ea2a0 Mon Sep 17 00:00:00 2001 From: Henrik Brix Andersen Date: Wed, 24 Apr 2024 11:09:15 +0200 Subject: [PATCH 0481/2849] 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 4f929ba32f83e..7f6b12453a2c5 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 adc738d7319f2..55322b50a21e9 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 46fab559d2a03..9efc7823f94fd 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 8a26b407ccbb0..3b0e323dff93e 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 c470e1f173216..60c3ebaa6dfe6 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 aed0fbf7741ec5b2b8daae359cbe73b14dc41a57 Mon Sep 17 00:00:00 2001 From: Henrik Brix Andersen Date: Wed, 24 Apr 2024 11:14:17 +0200 Subject: [PATCH 0482/2849] 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 4459780243b1b..0ffb4f75380fb 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 93dc9b1f35684..ded3866acfe67 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 9864c7ae50a1f..f6981455b5122 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 79ff5b90ecfd7..3827dc104d993 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 e636089ba03e3..f1d9481a8b757 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 253731fc7212b..4538c41fa5f79 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 e0d4461a33bc0..0cb8b962829a6 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 38d870a6fbb26..255fc34c051a9 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 df37b32e3c781..a7b50692c0752 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 2972e4725f1d2..bf83c33898c3d 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 efaded4d02d6f..849dd35bd6719 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 56353da3d8135..812c2aeaa86d8 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 aa4f2eab0c818..5ed512dd05e48 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 28db9b9265a11..69b0aa3fafc92 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 6fb7def19730b..4c42385a794ed 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 aa2373b829ccf..42849ac568bf1 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 1b68d976f3e8a..d081a79b96913 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 be2b16c27f750..42b48e8c203f4 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 472cd02630193..c2c90d8599683 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 43a440994307e..08eb8541432c4 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 73b9e9704050d..85a53c07f298a 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 387b116d60154..7351659dd87ff 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 9bdf8f088b1db..2f4e842873f08 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 d4400dea0f4ff..95eff6eb715f5 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 65f6c86d56942..ba74e255f625e 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 2399766c0c2f2..8d2b01c44ba13 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 297b4926d11e1..1270676c77a56 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 5bc591f0726c1..e0f3e1d242c0e 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 57ca5dd43b310..77b9523634386 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 9c44e8d874e85..c2ea2f474967b 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 11747f1a7b6e9..63070f08e1cd1 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 931012548fd6a..8c3a3b1491a10 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 866a8318f3e8f..776bf4a3827c5 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 6a76109ce8444..539f9838fbf4b 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 45a311c50307d..2d96ce6a4fbb3 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 4b676664956cc..63775c3d1c618 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 fbe6042c1781c..023c551eb47ac 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 a5a23e779d819..cadd4dc979974 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 ce5c046f54ad9..d0db253f12734 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 79577593ddbf5..bfd1fc3c30bdb 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 5cea1004af625..8475709095b16 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 99d7f0deb75fb..ae232f4d22810 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 8a9d719e641ab..9e86a3236d35a 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 e520218830ec5..290522d8c921f 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 e4136cf577bf3..d1f988f281ed7 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 43094d1d72ae7..522017c81eac6 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 d25d8ff0e6208..7aeb3022a9a2d 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 b7a94b29e9e83..b24435909182a 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 7259a9f34af0e..af1bea6d92ac7 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 6afc2996acc6c..3674692ec9763 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 d6c7dd4be456a..5eaad0ca83db5 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 47bce02573291..988a1204a9fdd 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 db57eb734dc20..90c4b4409a0eb 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 8ae863248f226..4125f4e6bde13 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 ec79bd3575d31..d86d7c6ae8eea 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 74b0308d706da..a91ec3ccb6034 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 fd1a5a8b29ff8..f410d6f956e9d 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 d8cc922acada2..e3b52c2b50cfe 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 370cfe3a0d87b..f6a3d56891399 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 3c58b14302df2..4e483b55f002b 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 3da0ae94b9993..8f0d76d9a8651 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 26069f4b73f54..bd8dc8453e091 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 14a5b1de80fe0..a08d7b47ce2a4 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 363e5a565c565..de73e11af6f99 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 f90c10cf71cc1..44a66f038be73 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 2847c2fcfdb15..163612aaf0759 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 05f13c64f4602..721cea3ab6aeb 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 4843e98a709d2..41e67e551c2c2 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 227cb9ab8c266..e140f6d22bc0d 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 1567585b2fd53..8868581770685 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 6d2e47595488c..72dd744c4c21b 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 7543e062ada3f..a2b7796ebfae5 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 e435076059475..168314547eff5 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 f55eb780c2d6e..ce65192812374 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 736382d68bd0e..045c09974fcdd 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 5c74989093ca0..75b115d697cee 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 c98aba18376d0..7a4ee3b7daf4e 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 5d9827e2f35dd..1de44e0e9c5ed 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 5ee7171d932f8..ee3bef5db4148 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 0a89ce0bf5194233790dc0e3dd264928aef0634f Mon Sep 17 00:00:00 2001 From: Emil Gydesen Date: Tue, 7 May 2024 15:48:54 +0200 Subject: [PATCH 0483/2849] 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 25ca59bc44f68..06f8f9f3bc520 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 c8cd57fe9ef4547b2d92d4733af57acdeb8e08e8 Mon Sep 17 00:00:00 2001 From: Francois Ramu Date: Mon, 6 May 2024 16:36:10 +0200 Subject: [PATCH 0484/2849] 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 326c1129a3638..8421d71f16ee7 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 83cd4d36ab52d200e9fe976d6af58f80006a0b76 Mon Sep 17 00:00:00 2001 From: Frederic Pillon Date: Thu, 4 Apr 2024 11:30:08 +0200 Subject: [PATCH 0485/2849] 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 0000000000000..f2a184ea87fe5 --- /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 0000000000000..be9fa9523a539 --- /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 0000000000000..aae01c61ac776 --- /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 0000000000000..1d98da4aba091 --- /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 0000000000000..7b41b6115ca78 --- /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 0000000000000..6431922325371 --- /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 zcmeFZcUTi$*DoAI1rbF$NEMLYLT>?)-lg{%S_mOP=v4(lsnR>BG${e;9aIEFdgxth zC<4+uoZwxb=e^(eeCPc0eb@CpJDF>Kv-VnR)>?bd&di>@ayfSS9dJ)sUP&H+g@pxB z#C!mka~#2PUJzRVKuL)mfC~TsZ~#PD*Z?dHy4vnz-T1Y)!eFZ3u>%IP{?2m^gMnDr z0CzBZSIowT!6cadQ_Kblz5Yu!9)t5R8|HMsj{n#zD5*W6=i>(Qa`W?IBzgG+#CWg1 z^gv!QUZ5C;hy}oU^Or3calkFW1>iTWSJnZre#2L4vHpgyVXVW(R8wH+*uPtP6LWm? zZ5P41*YKs`dt1!c2{m-I4>swG63A0H*s#>z{SDAxpfN{ z51-@?{_WfNltjb?BsBNwXld?KQ`0kXv(PheGE!5s3bS$Y0tEyF=vYKSB773u`~rMe zO0aI-x`lrmpW@CP3cd%_5BUC%%jHJ^A?}q;*jNmJYlK+Xgjknf0CX5TZ(v&bsn023+fYuB-F+_-)n!|ji$2V5t-LG%D9eUn(z5{JQsgzs6* zTU^G+WuHj327WT}Te&{Jg-1qCL3#fnGYcylyMUmOu!yLbjI5lzf})bLwvMizzJZ|; z*xJU{&K}}`aC7(Y^z!xz3Vsn1`tns+Y+QUoVp4KS>bvZm+`Rnv1%>4ml~vU>wRQEM zTfelmcYN*qh8i3i9vK}QpO~9pSX^30udJ?Z@9ggF9~>SXpIrHM<>w#eH^=_XFG7r8 z*REg3zK(O{7uGdT%!W;P{l){}O(JPc97`8s2EJ#wB#&d>mVLU#$glO2)XH@LkBmuR z?&0>8Yrj1Ef9BZp|0~b_bnGv`CII-@SeVAcCImmPP#ZojwM$rb`(5OQ(dif!hZiQ?7xj9+iVXLgA`XaT6Dg^zk1=qC*XPUS_Z=z zRIG$UnoM%iAohrvDA0AC-u7E&eQ^SH+qG=9xKyVI}H8W z!SorK+))07QNZ)idgst?XL9Pe2&)P>kHv>)d9|+@qPx#;xTKcUxfBwm*du-A3Apwz z0eGve-_fS4H7?2y9NOAO+fpg@v+5#dk)oG?@xb=F*Na51N)oX?sn-$@Na-W6%w=Q< z)PudPqQnxYYv?l{TR4l&7Z{mz;9nEQab94u6U=6~mg_R4i)Fixs-OEdoI+g|TS54c z$E_r%(Ap)csxXNdGM87CFmE}mp8zk+WJgxj8Iq3efjHz3NKzS@On__IO?J9%RpcK` zrE`gvqQesvLnq&i`A|OS;+YpKT{k}1>5zDAkYh+#&zBx#7RXg}gPe=Ye`+jK+0qczmBrxi&t(*W|$lICBIK`oW3v z+)1d!ryk$JK3`gsGFpf6aFxy(Zm>kzk68;i;+C=yhZd+T72P19i5#y z@DN@Cz6wgMzrT<#iPuJw^yii(*B|78U!T8Uq-R_-*WA#p>LXkm@v-W;F|LG5{X=_l zO4t1opv`j{bP0G&s_~^|=cdM+3*E*!ItbJq_lGr4RHLF>ik(=@E}7cf#`hGNrJTk?%Im<2g`Q!u95rJoF zZWn~xLS+T()gy;VAqH6iOFKh$c#10^Xpf`RNHo$T^V%gKCbjQkB5>tqMUgrlU-=6E zsQtUJozANfg4MwyA)0nS&B!R`WAt_*HErWa%$N)-wN^YR3i6^lI_)XQq4>ciK>d!b z!wh|pvRde24cDQScHhtmUgwB}I!RMWs*K1S`hxVtCw0lR+1Asww}bPCx8Uj=->S}G zp?w5eQ$d!wpxAWU+`EQ|LzIqvVM*gnu_&?DuGtz$UH$GB*K1hE8&apGSi_J}?LE<4 zLYFS$4RZzc1Q9touDjlBN;AvN35;siNcsmIGo5{czNA@sv7|$L-=FF4nhcZXblYv; zv0$$py#-^SWPmV=PJh^8Zxtrh`c8iBWznWclR}#(e*Y`km$_LEZRss$B1J?qa+cVA z?hI{2_!Yo*j`T*a4P9F+&G;qd{k|$!pQhoN{0Gn!(@_aF(Gz`UVM2Vq3QzyYVNy`I z4>|%pyg9)E>NmVAGM95GIWrtT5&QXDv9n^&6W7E|()frdTp9?f9!3>U?e=xmTv)Gi ztt(Y^EkZ{(rZ6?-)lg7^)Muaj8+)hEAB3HJGvu;~k)9=N_fK|%f6>43*1jg-K?~ty zyw6$dHXV3U1qY?_LjwEd17H=?ex^t4#D{4#y$T4k5l!}}pGlv4RaFyE;X_k{XD$-g z6^b4)X&fI_n`LdWn0HAj|8Uz-?s`%w?BPk+L-*(j8fO;O_|~z6xjM=tzEEuOy5>oi z`L`m$y&1YXl@-Ir1A4!pb9lww{c&@ST)oY>ij97qZSJ%3p@VQ)9wE#S9Qq|V(2l;3 zS@SGX<&9Zuf&IbZhv#HAojC77xMz2)p!!*kEv)&6E`Hflhk|o+-S;wn8tS8iQI*sZ=s}BgC0M6MLx3t!4=bbw-Tx^$s z^(tHAOF)s&;J;i0TBl~Y_sQti6-F8~umZpK*j)l(QhV4YrlBVT`^a;mO<$^7C$22( z!Y?;Jg5(Lz!J3+8T=<9V9N~k4)5;5S&{s~L%G^RX$Fd{tiun$;Od5rrodqt0Uyv^Q zGIP-QlP)zgZ3om@3UI*uKkx$r-9nGU_WZda+yX_0xiFLxQ3W-aDNHMGzU1>4qqh&N zI-2Zm;!KpTl@u-A6zL7jMfi-=*<>3hWqgW{$WeC1c!1Pb=Jtrt%i)(_-lP)u%$%1~ z9I}puz8sN|kt|VtviZE5F1vGokMu>c*Ne@sb&Wi%IENlT3oNqE1CcrvBV1eQOi+5i z??ojjDX|lLW}|`$cR@RewVE6?sI`)k96h`9qoPv8wEnL8ML`wpHRW;q7AWQy21iL^S0R zwrmMXoD7Z$XY7j8Hc!@EbFB4Han`#^WN+Nu?k2b19cB}hrus2>H_($2OdF}MH2)!X zNTW7*@HSR2t4HA$GyA&|+=VUfocemt*E>o89|Gks^-W%-5jXi1sJzxqC3Eu$IW%Cs z3yB(mng-;|-!tCLsGiO@n^T4$?;|_S&NbxI_jgP*I_ zP&k}Ojwp)6z0Xwxu_a$`w4hKM1xy-$%|TPurn$o=sJ6fUYLQTmOvM?;WVAs&RZAUo z_m+0Trt87zNp7=T)6{l>sEtfaR<1i48P5l^HU7%-g$L&EPE(U1dM5$gEUXVTV{zmz z0mO#<4sqsY#k|Z`ICbs*J?=Wl-VHT}LpxO~WDg^%Q5@M}H}{rW`)>?KJ)B z8f+JM^7k45er6N2d$Y>7cF~I=Wkx_`g8D_@cl+{i&7o3;>K7CyD(Q?^{fOC##>3!T z92PdF%o@j1sIOt>yVQe3W_{oI$@_Dp0q`XQpXI!hiXWBwHZ&sZCa{f=TszkT&wJmT zNM%TRT{1I7O43?grj1sAcDNnCj#XsYj8^_M$NNF~U17$-5X&oPz3LpWYLhAJWVqpN zekZQyfzk%^BTzRNc5u3WPAeQcHr0gOThl&Iaz)QP6HQpXoS?l{OtLDso8+kA`bWxU_ySZ|N5x)LXzteFl)5G zL45JZLu&t1V1gR_8Buo@<=U-0NRjJznz{*)21O}tV{Ph^O>~7GGeBxZQvZT( zDD!3~3`9tkn(I0yFWP4GdPF||0p2~@%E_g08)?&crrLl<61pB9PWb|d6h@AW-W=)o z=iX0Dt&N*FDQ+pG)U3*|X-SK|e+i+Ge_D}MkK>bEt=8e)ttfjVC5lu*3mVWqE%4rN z^(C~LqR%w5b>>ZZg_;|UoM_cOJ!xnUIO^pB;C*LIY+h4Rq92+O07Xe z6H(bKQh4M3bY_k96}4o1+_Sx2t4yBjQfXCo&v9w_Qg=`v(}uy8#11!2s`~Wy8~br%KBpzoW3R2_ zgTfK|w}Je$)(Q~Xi>{Md}N_?{d<(i_n?mldG`EohtthE?=)q1 zEvur~m&OPZ6#Oji1~k`}yd2WCHxqx;ny;Q6tueID#T6O#>N=4NXDRx_#mdGBmXem5 z%R!2fg)7zO!eEsGs@7k9&y|+<5)d68csSDJD|-oeO%r|YY`$d1Kd%zwT_6p=H+5mr z4k{Y2#QfBcT>?h0U+5H_;U*$l?#(Oh)mpx`F-$wrk5Gdm^1iBCG(I}mFzea|#N2pE zGmgmQ%qxIro@P@%4&6)yIXFoD>7490Bj+951?WVd=Flm!fvcxOg z>!SPWn>rusxXMhG`6Q;m!|8eD1~U7D+9D-O+*2Gq$)J8sYM0dytaObjN7xN?E9@wR z1B01)?|W0cORwf|-V{ZMHNC8=;V}6Id&c>xB;6tg1zh1EI?wEFHw?a~Mt%Bynklqf zkE4rZ?Ir;wjf20{H}551y~xI*aM$f`@4IE9oLvU<&Ac{NlOW&%!?EsIqi-z@w}pNJ zI<7m*`-@rCZX0wKv5OsE0+{6DOLE^TQz`9r)iT8`N6onk?TAHhBlklTKPGojv3{LE z2W9d;65TTL@vn|Mpz_S5c;e;4ZGoi^F!GfV7b$--XQOQH|+@PsxB6yrSsL zK%ONtn31}!=(uxXytihTv3-sDM`ZdJ>>Z-Jz^LW~4}a#(8NNeGT^uMWY%##_;H=GF zsl-e%>!ae=(iZ#U33QSImiHi$QT@n2R=J`f5+VQ#@Z{w{})R2BTV}`FH z!=8S5O;Dvm!rhfX73KVB{U|`^$ja{cTI{TEvlosOdLk!QsM?R8S;6GqN9w~*2m1vG zj~dPQ$P+TjZi^^pC2B?aLmX@f4Y1G5zp!Gm-NGwdlQO2JG5j$6?qXH}5?7;Z@%@Ay zy(pcV#liROy@SG@ojK*jL`U8gd6(7wf{6H#;m}nFV>2O?9Gt6ZNVSJOp&OQ^jmjdq z*Wn8n(4?dZ&?CArF}1*0eZ#zE5HI{y<4YtF@3qfVA^RPd00XOv`TCtXwhtA@&l1A@ zXYR^_j^5{!lP%%Yis!`wl!W0oki^YB%n5O5_IBmTVXFDXOisoowtY7{$R&b*KBD4rQouVeuv zlBV+a4cu?(Q!YT*-I#F9DPbzxJZOcBc~e2l+FG*jdhypZXM}ug#r#l za&2vWbB%S__b=hCBAQJtk~m8y!%b~H8T0KdiT0iCu&zyV zeUEuCPmJ&~`r(|H-93`Gs-)t7<5VDt2=>xCQ|Sl$(4evXNGqdT~n)jRB5Z2blhRM(>+vzEzp-R%@9}_j>`G!t8boS{R zkvKo2I>r&l!|yHXhB(PLfa)k5@f3>SJ@iv4qj{#v=9XHBfk0G%t*r&G)SD8tdX%Yh zt433BV6JiXXW<1G>U)9Ibmp0jXE57Yb`RBdeV=^9V~}GvJ!&&*;2vShge$N3T>?fb zA3J)yp|U~A$^1z(iZ>Ni+!hIQST(NFqN1Q^%q-ISlVO3EB|M2&^vbu+^AyEE(4ZdiN>F<{QXudevs zR*NOz2y7RX$^xLeJS~{&s;Xvz-iay-I*Y)ye2@bCb6sBZ(?-pox4V|+oSj8QCE`Y- zzm;%pB;k;ATMt)*alcY7xbnDt{ zr6(#O7PlN>*F9L`)(w8Pii@z_noK8S$%AU~5Kd1UHx#dwH6+o~Ke>ySDTW^+Fuvz| zDjpyCBS(pvD9xMYY=3{%sO`P9{Mt+t{)B6sHTk`gVfO7h+ld*)t7p<@i2cGvITB^V z2v_kNPh4GnE@&M)+-h1>BhOgS0#AB>Z+FBh#0hxaj;*x&+xS`sdK1xFzY^?354T zjT#nWS>KQlF^^jKK1V}WTk42?L|LNqx{x9}C4nkdRPt(Ar~QNG5t~q*M6jLD4B~6( zjfZBgA`6U@$EZl}UhXGG^ll4e@!>zuGa5T~gI>1pvEMQTtaq5D%)e`Fs)FCU!`F@z zlfh^Mn<}%6)$#G@s4;5bSapFMI2%eY7s{^8FNs==pH7P|W@fZ8$GHdQNJA|$W%wF! zmz>lo0EGnLemjW>?X%TK&CsLeF!Z|Kygbc^R(hYqydHF=}EXZ=M!Ss1uYg*C)zTd_#k99tRTq>;b+GBqH3`;&>;>aQN8O zKgwZbQJk2oaVffRX!N9FqBS^p@w|VE;9HGftU?zR-MiFpErV*^jo-h!QD^-u3eRUL z2tetH3hLLUsx+kVXR6T73`f)RIg|^ezasdmVL7H3QX~-mUa(f=nK}ugUuGo{1wDK1?9!omqR0Dg$!$+CK{lc&Wz&y6(eZ0qXPuByF@3{Zyzcky)!l%JxAgmeYf1LeBTRV z-wN922(meVa5M2k$~j%zn2;YncFR~If_4_&dKHU-A_1~FrtImx?Sn@lhL3jPOCFJa zpTnjU^BE!7L0?t3&ol-jnA5u;^Bm$2a!u51d^=M3+)VSY$91R@U+kXjj&kK?<Mw*!Ib74#QBrF!DaYi>oa z*t^w4=9-Ne*S_eo8s;LFUSD%I!2iC0YN9hCdp&&#us1iBmLS`v?x64F70E zPq`ep>*HuE;_MIH$UM{G4F^*3smF4QVm*^M)gA`h;S=|GKf6Vg(M_?vo{r8`5FAj> z$){5M_C(X?7Q)lTskr0R*!1y$a*G|s9ZCvGv|tYRyJ_;mb1}bev|X-R zij&rezIu?P>Lq~pz-hiI^pWV#gUrCyX{iJ+e>^^&SJJo0{S?{c%CbNCUAEqF|g@Ki{%fbcdklF{xg6iHl6NGkNA-ko^_MPX_cv5 zf2JVb^Hha2R_VbORHo$8y|V%i&t7(lkuPGw;Wb?!J90Ij-HvTb=Xqnrn$capP$$S3 zgHJ)Nx2>lqsPY)u-GF%R3{nz|@$?!=++wfk_0n8(m~LIFzF=85=`C`0a{7WBpmQ8Z zyIhlY;C#KL+jp!xaoI8UQ#q&uAy-C3e@Nha=y2G>b*G?h6C?#P@jWgGTP7#rAUGeH?K}k20qJB7O5w<&hDrwoi+}TkWQzRGjX`;K5lsKC0!dpJ1oDYSB>&h zfcO)s(R=VtU-OZl_M$_FB~%_~-m94DR+zD@m2Y|0yRg?L{V+F}C_EWWDE0!I)1aAP zoA_CD>s!Vqm-;wlc2vk&S$?5UX0-o27kO*UTWs#j zon75Am91zkWVKvk;?x|Yy|sWXS=XZ3T`6_!V4@pxoZF22JL@j%;TZaTX{hWhYgA7tO$6(0f z>NOE;w_9xfW1YihYMm%%M(K9eSMBCWJG!qC=m`PB=xWp+o)AgKgiGY5Sl*4Vwmpu~IFeKproa!sV&3pkmFd39n;m zc~karAs41UK2X1?vVFEm7;N^w=&gOy$@ymmk^mFJD9R&%@9Ag_#A5@RYh>IkEJyUV zL;Z&BO1-0z`*Zm>a7IojOhoQPzt5`dZslfAHYusKi#cJ-!c6P=!9_x+!eQTnDf|ok z=ztppIqf>--R!#@2~|=_D?ih5X5*v@HvG?`(i`t zZx{Lpso@I}g^N7%!T?qA<8~Elyq$b+`^bT!7l}a16?rxA%s3WZ z3=d(@X&vCSxnrUVIn)XaaV+vE+A)^j-k|4|teSqI74Q8jPDQ47lQXya^{ppAShh;( zqrs*up?-2u2$(s^@5Kg1MsA2R!4o-?G$lYy9HTse?ppp&LCw9&(B*ie8~bcw?re`s z8y<*E8w`b;{JaQvwESR5EjnGr=Y3LxD(sv;o&Q$d?~S+dbjOZ*`&>;=x3b#w)2P(m zXYN3L9XLx(Mm(qMk~)GB&9bVEPXv{nE!}&$80P6XLw1rd^>TNXpY=gw?I2)ib#6FS zL&zXgCOum0@uM^LmJqm;lauw!DVuxObVCq(dnGOG*>TZGOD*p7bdMUa;`>QitD4aH zd!#zSLec>Gj&&v45P9tGM>KKIPV^eOGom!An5^cX_!W6t`7VTY>Q^VRb|z~4R15NO@_BcFi2drX+@O8>x-}Sk_%P*TPz6WmY ztQ-_@y9C@T|ITlXd8vuCAvS7bU0J*1-PRT+PNdU*378?BUB%N@sL*niWxusQ-yBGY z%apDjY~|G_-#qf5(wH?kM96B~xwaPs&D6LBeNYZdYB{Si-!4^pR}v+OWM!4(V0fsc zG@a?!Og{X~ak5luZy>Ne(fsyW_c+=5B_NRe4BF3Hbb&&S2b%LqmJ;_#&5;ftEd1yi zyzt>U8nphI_n{-)W;J?0{6cW0Qu|`?ijnuEQ62k&Fw)povbW`MJFq=Fu5}^-nX}Uc z(0O8zvF3%nZWgLj6@7ed1~VN=exWm$tQ#K-!G22;{owDHnR3haj%3!Hruq5u$^8>W zKgG`U>L$$7McE~wF)*gMP7-5bqf~+ebas24?zH3heplRP%W3Pez7YRB_YIY-TFG~n z0tR}e%yhadb<>7(Gc@ebz9cFGW}2c!KSjQc$v2bx^HStMno@TAuS$~(Kt zPjrcmNu_JZT?Pz|rN2FT8gJ&Y#@mOCRUudQ>Nt zD|cWiteZUE%=GX)?e-KNsgjWPMVlbY=@O+$vMgs=58KNRqaUtUACiXc?Z2GVeA0+Q(d;$nF{kS$XlbnpFmT z(2x@?UhXeOV6;X=Q1RkaoMeLcrbA*htenxgbvb~1OfT1)v{1B54+_PZKxxEoatAgy z1)l7Wj@>Z6?HtO^NFg~^BJs5Ky0yM}{!@W%`5B>~Qnny(G%56-##0F90dtmv{` zN!TdoX66KM^&oNWp3Djq_`~U-<%AP6Q&J(Bu+K%B;W#klxpbx+DNe^~Vqiu>QJKCY zwUmOHn?m&$m&DE;8mqRjczrF+w=Z#zgv_*!9q0LqzeAG^x?ju{#G=qY9{FdQEM5Yz z4oY)aiwuKmK67g?i#nD>sNSfY4n(IQkCDtOxE3nj*AghH?)YwymL3$9o3y-4=l0^H z^(njU=<<}pVv%se2!`DTUH0Z_+{18zNM_(dlS>a#3c;VCE(qS)+Y6$dGHoy>t#)aH zMJ+MD=XZRTNZTZI@-};j%9g$!@)anAOO}v4SIE`JygZ*6UL+J{7r|2MEH!*rlF1+U zV@h3E(#2S%&W4AHXcJr))jCq`*2E1>8k)0%a!|o(RDR-j;Npe^-hMqt#sXC|yNqVpmtr{*_O}51yKEj(hsHZ4BVo%2L1k@@ zftxi;rm&}N!IT%@FLbTKQj`}kO_*~njP=d`TN}aU_~qOk6?-=~XE7cgCj_^pHQdUE z8w`i>cv(900J(X201{GO&X!=PjT^m{jUB`Z#IV)S!axtP1~KRhs`08h%h=dM6n$K6 zw0+cdz&=p0s5OI>B)x=}m>0|$X5(f_?*(&oLWp^R7=9@i!{9424+H%#7B?t}!2q)u zR|f8CLodKBz|G5rSrqKS$AHn{YHcf~B`g2C2FwwN;dfI#Jw3TS`MKe)c052)QBfXV zJ{~?kE(`}3!rRHs(u>Op!T5&;SsMh{72@m$fjiM(X|%M0ySsrHFz5fxFqpHN+MkO5 zF$OT$m9@XP5pHrG7~%gZVh9~?XB!?Z8wA|l6>KBtVdLb+_?Nhr&0k*peygaYy zW4=FRm7EZ6mQG-sKV%^oSzcjYOI{#9FP9)#n3qdHMA()~M37gIOHfF_TGWP5R2Xa} z_=miPD+JT;EFJ&J23sLvelS0n52MG5pG&~j#)eD8n%A0307JF1v<8b<3JWpNUjL^5ZelgfWZQyd|aaZyp~)7)&jg-mbQXmE>S^SYhh7-KCrEjz#sAmxUHL~rK^p! z9j1*jmSXzVuhsGNtiOW8_6MJ*z0H;9nC0?ZyjNeH-@L=rcxw^)F zbA{*Mz5Km1*| zLY6j`TzoySDH@jiA|fI}qF^qdh&8682w4hq zSy^Jb46hYGpRK5s5TA(E-^~Bpknx8{m~rR|{yD5k(*LLYCj$S8z<(m}p9uUX0{@A? z|NkQJ*MpIb6Xs^j6Z6<}Ie+bgl8lV`6D|0Vjw1|?~NlEhPaMNGlV(0xoRmq zrpM%{(c`ROatW_vG9E<%T$W&jv-FcEs()n4{n!1$$W_uG05HgPrR%@e|BsYA)|dw% zOokmjhU*d7+0_k$EihQf)6Mw`Cu1-P=AP0TgNrek(-mVN29I6Qt$xEluCU!Ne3fnrScg<+2F7~6i8D-ZE) zoOHD@dnU|A4Nw3m0n`9b0Q3MWfI9#Ja0IvkxG;Ms3aOYm*`ok}4klKrJpe#TDgeN2htX~F-}rr% zMf+#m{zsnQVgwa!GGul1Xv#2yf%vx`jtda1Wo5g7iKm1t|qN6)npH zDw>Bhumh3WX$Fe#T;k@&q}U&p$JNhHN&W8TNmuhKF9sKM-i%f`I?J)`j+_B{;g zzD)G@^S1a#m>9@snDIO-(+zfs0(m(n+PFzVsH_jA0&wn2abJ)4g# z?(55}9WP4G6KFE)g1n0pL6v$2UEkV+U3gCH!q;LtTb=(WwbaK(I|;y5bmVr_ltJ$x z1uQv|3b$~&Aa`MsYG!PbO4in^#LmQOgBtO?DZ&kk-=HtN;eEU+c>+)K@Y?`AZ;F7*8F=kAPM`Easmd2_hpFT#RF8j&{(SxCPARa#E;T zhj=u_=%emKIQJM|HH>{98)=cQ+M$y}Z)}m29M@c3-2YVY1pHb|ZANhY{feE%wzr~% z3v%z9x4<(7dim_cEYm64#}aGD`Aa4S)7%()e2o0Is8MQj6ATcGc{?&cv?N@-WGbPe z$Ct9GPN*MZzcIBt6EwM$I}~mfc4`*-&Bx4BVSu_fEA5TmqklL%mX@9b67M2XFr_p% z(&3~|t} zBhpU|n%l;FXI(!0{Z9INN!|o>O(1W&r)+gwd(lUoz&~xWj8I-Y)tKGKXwEz^aP>lI zAAY+;v(4h)&yQu4AGI3pE<8EfDx&5ilP0cbzYS7gF<4RxP-A`(4n*0_W}$MJY~#lx zzEEIeUoVR+<3mq;pUa!bNftj;3h{m&dU0r#;0gs4#u{H;W#tEFVwx$tPDu_!z+Q zAVy-^J11_hghm|=miFz}jZk(lFs1E7^%(}6*{uE|h7Y{JbfpkxM1+-&w|_H1M)i36 zjMLt6)0$#Yf3)mddoToKZfi6-E15538|pBkV;^}$lj^4!BsjpKbKH-gLf_YaeEyr{7<8K}a_JxlKe}}cy#N$?P zbPyU$AkbYt>E=Z*OA(VV+|A$~$_?h+Ns>bX3jO&xz2!=}P#;*788Vz|DU znYe8n4dupAX~) zGHMm<~*IvE3<$&88b z-utOJlN(A!Gj+;4*@x-rRSPqFB)~y4DYF;0#c303?UiG(Ed4u0(9Ra+%(RKBcVC*k zW{}9vZ~-4b<33dNZgY6&2HsPQA6Qz`w0RA5V8px{;#G$Gq_JR;?F)gyJ0Av3VDDU- zW9=xS?B{EVcoUOnZiy@9A{Bd#gvSCGL-k%xtZN2MT11T z)Z&D-zGhiZ^t_03@O%$srfjB~%V?=uEdZ4OSe1lY_!1YR3_d&S|6=JvEGL>#5 zLzU^UN@uMCPymdO$H&eUL-`_t>xUnnv>VH;n7ip=YCkwU~&I+~G8icoHAreKxHGC&+3N|Zeo!Qm z4Vz0a5$q|7O0*7Vv+7e#dy?x0Peo+}gi^)Ew5^DytUGk@l(i0!?W{nG>-K7^`eYm? z(=sc0k&FV>;EG!j#of})lX@fX$0isW%a*tE8q|m%OGa~K!A<*CezHNt8fTJpLCy=9 z`)*9xr8ak2067+=olp#*4=Yo?o5TjsmPy@y)0bPNwA-sElhr`Q?tNEXoUoDLRA ztlvQ9D?WS&yq8X#a(Z=-bFQ%k!p*PP!uriT5>k+cFiZ=UqD3YXZ2SJ%bH;iKDq%)2qeAZNw>?kc>Lx zJ@0~1@%3B;rz>h4Wnw2L6x&(28VAdcrJ57vqAUZF)_XDwts#m~6LJ~uCDIf70WuX` zHHP@(m0m0z>Y?}4{8_{eXLZfR@$|umSz_7fE*#d zsmGn#{p&k(eU56w4GCwMzaz-E6W?(}ZG0{!aWWF~^E0SK>;{C|;y+F(05|pJiom2D z=9Nd;e0G4%dK_CXGhDN8ufP8Cxo7+(*RbnGv7dTK%+y;u2X+7a?rDv8hR4xO?LLf@ zznmfbDltnnGql;&1{*-17~F?@m3D2eLw1FHOqv8%$9I#U>QnJ7eWDW^idfG?p8Io2 zu;m5iE3K;KCHDutrG`FC&5%^fNy)P#Ag$-9Iyp zL29$nm=Vk))KzhQs1cwZ{Vuz{kpvC&m?C4%v&BlnbkKNaWbAS$R@;F zkar~7uaS4Uj*N6d=0Bd%e(cSGFb|-uUGIT(j7sR2)nM)b$h~2m2ekSXosMRSpJR4? zyk2FqD6<=J!#Hhx4@AehRGRMI$Y2}oAUB#s3KJLPa#pSxHP#?^ohWblN0_dW|0&Xnft()9tmcaH47Mp)c8fwKKMTN>d?V4h8eagWCyHS1Y(RIp3emiH9= zotI>(a9}z0)kMy3g?&QR+YH{g?76gfP^aJDp(ohn*1b;Bkb2R#)g*JxB9{KoY|+H1N1ot#=|_ZDC_6KXP^7yRxcJ zvu8~evCBzi_i{0k&%00BV6^{;F7VR;vqfp+u-ut*?oPCVl3E+ioYtneHF|GW!<_ns0GA9*J3EM%p#Ut}?>}e5unAG+b4acm2X9 zZdIeTE~0WT{6&@e?O9u=GRqWGuj24UQ?{Ru ze}*b~<_5QITGXHw?dbo_M9~c3&jwHcX3;|z$+Y0}rZu6=si_Ebl02T#;~uZVo^u72 zR^KQu+vXot;Z(_Gdd9|SVf?!=_N6FOZ*uPC0dnDd?xE7+l86ThdIL~(kUx5$;}cqC zU~q8^g)lm+pG*M1&Cp%$-G(8As**jvcp{sQeQ3k_#F1T&@QCHO{{Fr6#3{tpUC_T2 zEOY=Ev+VBm>b)Mb4u9)h4=N2wQfbpibIQ+Mu4+KzKm8Z8t_~yuKZKZ5)!jX>ipi;e zi{4+~mla@6-Tvy%iWZlNpxGRKm6Vw|!NX-NcB1ad?i3uOW~?$K1zTr5oHdsJph3Ej)%`^(Z#j@Vi5p9OZ?3ry4WCF-U{t6sfz>Y7HQ|_XppH#x;7%9#CK0S-S}-C zRDGs~snUm>(< zb1~(f?MK%!~B|&(AZnap;OJGxvaQ$rlifQsYn!ZO0vQ z5tw!^W6HR|=Sx6?s$&r{`!@ZBYMn}&Nl5#-(W!zhTB@MU3E$&~kLdQomNp9W>)`9H zb+<#jVQJ5N)h*L>f9&a%d)|TKd*)fblnPFx+MwhRD z@Q2?U4@b+2{h(4>+1cnP=eJ?tr2`N-%K$PeL-Lh!TcEzcj=(v=wO#Xk6;Q34j{v8) zxIbaZ4D~Kx3j;kIUNwDMZM0AgNdNq3+rj^0@2rC22)j2=aF^h2 z!QCZD@Zdf;1ct%go!}0^-GdMA?t?>ccXtVHS-$VTH(Rwgd%y2RPtEj9RoB~ZpYA#5 zJin(s)*JrE|MBJj>zm!VTU+XEf6y0-|LgAm|Kb1R4E%=)$?<`Fgoge=Wx~OJynX-& zKa%xOFtAvk;V`i&aVV(RIjA|msfhi+<%0jhEuM$>k;F&*$nAfE`(TjWolTZ9pJ;xu zE3uYHPMRG{7J3p#Ju8Zs|DJ5FYX5vpDJ`QqCnEn{iZs2iXY1Y^%9Gk*p3r@o<2f79 z<0iVm(rT$6-Q1b%y6T&|#?lMfaLfYIbIri$wp6V}17$QTwfE`CTZ zLthtPz6$+=!hIi}uaLC9juq9Cjy&0Yll)c4Bw|tf6t@*l5V4;lhP3t%3Q@XU`+%`R z>MxK;aCk*KrTW>msZu^MZIRum#yHT*F@v;RF@a~f1d-V^x5Ng;?kn&v!l2CRqt|{9 zR7o|Ka}Q%=5$8`e>hH`(A*TJ~Y`zz`$Y)SLWQ!KJAU9fF^#SXXc~tt&F86#>9irUkxiYAY@^%kZ6GXd4rw~ziih6R>G!?FY^UpV!Udv_5 zoNGGD6SH{C5cT)Gwsw942;eb&3Tc4xMr&DCj?JM>+Qk% zU3rFZUxr>Eu>V1|#faTUzJQWetm4ue^9dHT!j~4zRn}hPVLy-TElZrGx1jcYEo|EU z6a-Z8t4s`c^ok(_zIfk!4jCTv3Da0~BMn|#!z9Hz^DX3u=x83~+vy3edUKvwS?^tk z3%hR=({fbcP2~gbED#v>OQjp^t+r;1kJmL4->Lv!bA%iBFmc1P>gv(EtFKxwBGYG} zEKP$bMMXvB_f<@?)yqz$+@Bgxp)2(jD)2jtWBcrhx9%%1RHXnz!Pm0rNH z`YFkyFg$hl`E53s6~*H5E}b?N7i9v_@UPd>0|I(l{OB`z--+MHIT}r=uwZMvI&Rtt zx`Z3M6S~h>I~nw|7CV!9Hq~Qy=NoPO{m_)LFnOZz_PJD;cM+-^s}}Y84=J#Ejl-Jj z92|sH+#QGYJ(k$4Y?O)aIaM#>h3095G5@wA$tfzCF~oprw(YgxX>A;pz?z4(c0^w3Z2;%`$z^Jz}|{#B`E& zodl7|uLJ%;4L%`3BLJRSKMBCRAqf&@%SfCw#ED~;Z%u6RlPaTT8%vjPXcJaPczqVz=fxwWr{;i7>G-kKAE)__rWV8FIjBABTZFB6 z@d#KVg>n=q&@LeWKB!p(DG@}@&_ko2>k8R$z@?h-@~LaR1C(@uQ8zZju1caG`u%2A z;%Kz4hq`c5v!T)BVU2%KPS2jCNB6YYNMUm&Br6)08tJ2Uc1~H_H4+Xvwo^Csd;Zwh zEbWfpL!P8T`xE8~&K9!5VP>z;kydQ6k)< zHxFnXMc(uM0BR>pQf1bXdNeEZ(3ZKR2)lPZJiuD&IiZOY9P&g1P06B=oe2=_1xu;N zUjI;FFKc`s#Z5)F{8#x#zF^9Fi-MFHjks3p1?EfjpN-*xnnhcHI;wMP7+_QSQ+2H` z^mJ6R8B3#fv(_u`kBZDW`AM2Q5}C{B$k|?f8>!^n^7>X+pE+MT2X2%mw;kf)L7#Hf zR+Q5nYd?v0@)DAlmoJm*4lkjNIUGVJpUS#k&byPmxmA0Fe`TYv?4w9MVE<`?H2i}~ zd?|gh3V#PiWq*;5vd5m=)#TBXggo^=-D^+(J` zeVw(GT64}HML&PRU#@tNub5UZHPIos(KcDh-23f#UGtSVc*tJ+A5?CQab{NW!MpFn zN07RQM8X-LMfXaj;Dy5NLp$Q;3NILGidD)3%hc7PP<;4ee=Hg-vce0ivtT(XiNih) zea55Yk(3DZ|$nzz+84*!DK5s(Ac=p zG&(sV)9m?-G%?a@+9|;?Y zKd~yDs*eF^4lyMDLFmI&1hr=_qo?!{IJ7iXQPw9cNEjd(+z1BaQm(+8MKJ5XDT+j z)I#f#gXWwJv4EUag&Ie+%}_fCSORP`Y!)oVYLd_6zuiWdG}mcwjvsC^W0`U-Ux0oT zPcj!5Me+(n*|7={l5e`V>Mjj)JXTmY%ZI|U*qL}BtI@juc%_Pb* zM6Q4tJX=K9oGJc-vF7PNqzbHIGA3A&w*xnF3qICas=Gt>FwZV;80N%w+MYc~yggQv znifHLj_o9i326CDRS>hL?s*YWTwmZkezBDQhcfS(vtkouK?MKq?EBN#U8I1rr99;G zsytEo7E8VQDk-e~iAO(^f2lY2+;70bV~Z~TbtMWvjb0AqP9PCy1?P$2wfsAs%@gWE zk+8^wX=qxUUP;8tnZDI!>f)}glj@0TjGlt7l;+#2@WRbXK2g9OZXP@N0fC?6rWbPP z418!&N(zr=kM?uMfx)0Wz;|9DI+N2Vf?Y1NO?R%F>ZV(g-Lh&tF?x>L;Ahwzg0YsZ z9g{|OYa(JKvb<+-&&aOr{1aoPM&%v4hhWoGx5ch;j5bF(l^@kIZk`3kjk4LxmlG`= zC-`<9V`oi$skl<#o=I9^vAVVxZY}pGFd!l!fK6g>&^t>-vGgZ2Q)$puv-S2j)i|w$ zQ56~hIad(IY}~tv$72$Urb{mM;%T^Udo||d98no$Kk@3I4QdVh_l(u(%hTO;ds8!6 zHbk6)#>C)LK=H>7(3`w=Os(xHci>f~VQF4-Kzjv^nZ}xs7lG`6Msv;XTgt4{0&By% zCa%6-uRYHoPy|iqk2(e^0)SFS{Fs^(il8vCqbpSK3<>R=@QGP$;)bEBmS^eDB7gND zG7Nt>GmbozwEq713sM zv_@Weg?A^7$UG9m9k68VOJg#@j^#t`IXpg|*E_buWx2^zp5bx6#rBTcU}Pp+F``Kg z_b(MptF|UBC-LDZD&UE6lZyD{c!OCP^&5t|wyXJ;M!YAhmnZFltK*XUZfXFLuwbwi z&7euke-44zCv2ZqQ`x?!t{f&JDh4=37K7H?an~Wh zN|!Qbjtwsy;#ry#&2;AW?7{n}c%A9da^E=XV}54#hY^Nn6Rp1y*Ha$A?@?V|fq;MB z8sHy0wPhgXUb)0O%^#Y%=qpo7aEF_-Ky$^7_URodCSEt*iR`d7S#$N8r8&LQMJOZZ z`x7~UrPoR1b7_<&*OZ)aYU5o#5Y&*|)E1T64-z3d9jePCs~}KW2A$R8CKR;g?l#&M z2r%EH@(HM|g>%K#4oErmz+$a5qiWEnJvBFd|wNY z-bLuLe{!+3$ZK|e(e7Y{v~Q>PRD~)0l;??8TfnBONa?VHUmF!toV{2ctr&8neqwB@ zCe3)L+6=l)<)ev0g!kyl;sN>rb(%lOFH9N>i<%kWT?13)PbO{lLG?o*8#;xN>kXxn z0rj!VchH-FLM?JFYK`~BFls#+E)@+po&^o&+otVy19T+GiOx}Nu$_t<<;H1+LF~`A zcM!mWs!Fx)up+9Uw8T;F@#L?AQJj;VaRsaVR8xR%5qcG#+BQ?sSaE|Z#T zywS6y&$RW?DnVx`XMAU%oFTBy+I&aO(=fB#z2A<-8P^;7#JcvCSa0g8DWswwh*dmP zzhsrjR=!ua#q<})W~`!w#|f-uEt1MQDO1un{CD~lq0&~b&3loX;KeBZ1dTZ_qEfOW zJOw@=PxM2fj+$9j{Uhxklm?UNg#Y(Vs^rsJN~y(6WS zabG9NVrryt2n74LtFstgIrMVdD8}$xJKhQ%rrFDh@TbB#fVWyYmLYuR)3|Zri|m?E zW0ivz#2cvTBWZ@%tZ&2aSZ3Q;<+p_AT`QD!LY^>h2B2wVnG4XB+y^?^##t{T{B+g_r_MF zEvGqk1~^$fOPeqL1TOaIPAv&5|E1`H7W9wQ5-#sK_D?VO>8p zE8qOSK)q;(g4sS#4zhhe|x6mKtSFSye=iL|=yP-QFrCm@IHe|5&hioP17CrRs z!f_3!F>zaaDxhK@>*}wwV=j&L;b@kk%W|@j;InIc+%G0Fhj~Mlu9Ci{OSS|bs|MDE zP4bx)CZorXO+WhCeI7`?fcGx6KM`0zFOWJPBW^E&z~mFcg}wa>1Q zUeHO^gC#Sge#~G|BGtPNZ}m*PcHy$^nzm)_#g+N^Xz&4AG=IkAf_~RmFGJ~}Yun=X zlr<*HEY0HKC$gI9qq&8G6-hllpSgwh4$sq2vXrEv9FbO3Sfyb>=6Sz9yiS&ZPmL*VFouRECmjkm!-F%akALg zLSVWqWzH#ju8cv~fPppE3bMb1t%~1h8##FwC@*M>i^}1U<-2r^)YGbtw zgF^XfO&FxO2?H98MeF#4x??lV0%>=|byu%^z#Aq%_;32v&s<(PB86d)6U`k*GtIGM zLqq6(-Gflouo=#ndjwuYJ}e5>Tg z@uZz~HtMKmh)4KRZ5aOf`}PSCSLqU|H)6#Do z*6@||O`5Fc?9r#wFOTMUh%UCX$|#8O`DQt~Og`I2AJ@97JYy=<#;4-cagm|_$~D@? z>zZw(B4mj-lS%X?jj6eW?Wkm@8xZBA)y8Ai25u*2gWq{0hr?Qe*Ha%fT_ZQhGT(8! zJ03D^DFX2Qx_NU__WB@k=o65B?%}LD_0j9N^{1S+(ev_NL=L61{%hrk9iC;@uJdR) zq{2pUe{<0X`0>C^n}@BJx>zg5yKTR|S!ic>m%wkZGdxvx3(pg?w`*WKj?$Ne{yNx- zXF!^B$N({2oIscvn^$!4AKj;E)js!LomF(%sbopaUwO5iO`=er9g+az+{+HWQPzVTDF4 z1D`GU^N9&@u6&r9QrXhI6f50elEa47mMu!Ltvi?TG8~-*dO1Zk*{dEFo#eF<5l9v+ zabp}7fmOU*dT>h9OM2h#{daA4LAH89Y^9Y)x|yISTg_Ioqp}ul;kffoXFAS`+>)6PDM$0z#$x&$bLRS)&P~+YdzXUzVPN;dR0N(CFka6DQfm$dm?sp_GW(1R6{2Giit)U*CSU^V3_k zPN21UeKpN7*uC2Ds~s3vbka!d_^UkAN$q$dBgZT2-ZvdW)H3mn4^F69Ns!@~P>gxF zG*oY*MRw3hygV+EwWJ-pgk~bbj|-k+PTWq*_>U%C$xda;-t1PFpQ4s92iV$X zLK{~oS^D!4n9gv>b>alY zPBHDyH1s&7z(*b?%0HDlo14~7N((^gKNm6&1TEAYPDL~xJRmI09Rph}3Z08~&p)94 zT}53{)>d}fU$O9yUA{iqD!JaCx^+F`F$3a3rp_hJPvD#4IV2~l&ht1(=R~iuwjB%S zQ&bzT77At*lD9Cr(h^RVQ!ayjMW<(DUtNA(>u$R(}|o>xdu&p*O?bI#(;H& z_VRrA@}zn8hM)1ORQ@=Q5^gvlo+lqJDrC@lr9pT0dFnL`KUBOImU=!=G;_aT528zE!D%jH-}Hw?22ei=C-qp=7#gY^r`Z_~=rgHP5V*Y`wQnOWdG< zgQ==E$;3@rsjy3qtMF*G;K@-D#*et1(!hGY1ekzlO5@NpKLY<%QZk3Ppbt!An5!VM zi+rTJ>y#nh`M})%I2&UUw3=KX#*rQ^Gag&>=jq3rma-9ZoZT#Rk%`C&pm5Sfj!{A?G#?XDYAIw!%YX+?$!(p> zH2o7|5@{R?*K_s5fu77ratA?jV{$pvjfZ{kq7>eTR^ZDY!D6U({iJ%wW2hvh&Zh@JhTh6 zdF++#1iDx5*6er(FG~SDTr1?v^U6XfB4j=SK_rNbV5RRh?F4H(W$s#A*k1y{1ik@l z@hH+j@-^eaGVQ&VT|oEw4UdIWWsad^3Q%W+H7Q4cd}aR+r=yNs9eGkrA7zok75A3p zbIBqXZ`>I#6+9|?R>nL94S(+!_z)>o9b^b26y$C4604`i`898|% zS3(!zY0)ttCb}cAS1giS*7G>4UpLyvVEl;Cr~E#KOk#hnYi*UoL;n&Du?O+okeem8 zwcliwu=Zdx^$pk2eRsw#+6BuoR_~vBWU<0*Zl#ALI1;t1&7bH)BR@4Jk23G;xTckO zv4{sFqn?v=@f^)Hx~G2 zW#H41TJGFewL4~+e?kxD>g%ZGkZO8IxL;ID$2E63WnW=R4(NSS@E`BvqJGbjcEap< z9^aCcOxpO zvd|x)-9Ir*NoDxR?RQ<2rSJ-&+yx-Z&_Bm@p*o=$4~;;MID!1-dNo$&xfUu)(2XX( zjg}$zio5p@M~TMqNSKost@TWqPwu0saq^#YsWQ~p(Kr$@H_r^KLE;>Zz3Hftk zYdhi7c!d*!qf{23oYBV|{iC$XG3+<{(w#>xaZAg8P^I9qv;4)fWpGxMQwb&v>z1^% z?inynD~$ZjzHE9QvN)~0TXQx6#cJI<>=`rr3h=M;Gn4W|X-UvJ6ReclL{ID__=D|2FX_E(bZvZ% zWf!Ru{L7M#F8c&Lx0*t@|3N7-ym~Hs)(sL8qa;bOP4h_>_58MvqS;B#bV~Ha3XBW= zZJi((gEgo8cb}0JQb|nEu-Ph#qjP3cE5$~tb)PhdCvA(B{cc)vot*A^i0h}85J}SP zG|Z{ELlS>_qnAH=v&TRjb_nOEmNNr*@`#YVw+T<}>82bFy~Gb?rhKyWm~`E0XOaix&vc&DhXLUE1LncS$pWa5Gs z-htB0)BN`9Snb?E8HulFNrn2Ds~1-4$5_;(g$>e938e!``Udi(_p&^%-|1^tT%>uJ zu)Af!M#;}uf4|#f>;$TdA$ufO%xvrD)q)YHQ5oDjD)X)!0>WA1|lbuF#4OI;k>rax(gaHCt14 z5E5GUj>BH0&63PH-&c~~>m65|JQp&d%Eb05EVaausRT(D`hxtFG-MOH_uO=EUD?{V z@0`CKDf>FGK;cP|U5eM@*|+}8DmzjtyC7;S8Z7Cd;;CXA={cFsLU|Om0y({4utAb6 z#vdDi*87Mm_+NjS|4I!!PqR>b@0G?YK=Rp=gq>kV^7-)>fC> zT&dGijAO9sug%)T_#sDl7n;;%uv@Kb`mMA^%z&XM6S`2OKtjQ?jVTTPP=P^)(>l4q z@hh6gxqZInf{r-m3t>8mG`46f)!9i^~O23C*U+OhC-ERy28m-ggFzyE`hUa)1t zi`guUS~|)~Mv9a^##yde;g4XxvimwEe)^HGS=P4XIxgsf`!!P4(B5JWU$3e`r+>z+N=*RGuUa+{|fQ*#mxlsA;gTSsa7DRkQ zs}#TJx_Lh?%wf9%2NOGwZ2_Qf3 z5`9p=DAEP-4#}rU}Mr+mHWfh2w8c&HEb; z0Z1r55KT>isal65y?}I5N|TSLkuOOw6s37 z5^RkDJEBni?kEu>S^qRy+Nu61q>;C80a8fn#p#&b1cfbP;;v?k=TB*ZMl4XJ)Rk@! z_uvOne0_|DSAIcY;@X-Vj4`9e;JF2(=}3t&Mw|HnIy=?vQb|d;M}~w0-O;5l*X?K* z?Jr8Gzr@G{kA!|!`OY7cI?u;hs!t4AAst|NjD+Hx8+}5}4^8B}9puj-zJ}(w=5X0C zYK$;JQrUY|GC>X_aO}99{^7$UY7luFQ9c+EpX^u2%zJtT>LYf2^0>|lEheFaMMU^f zP>7gmi~LSyOJMbrj7IJ;B4mIPBOHoE(O_;c_8k^_2RwWlV}1(0BpW?5Zy?w^QyJ(10=k!{fvi8DrK2S048f)Aqe6U9EyOG%BRj>Jc9h?rp* z`2&jjh2d!ZCY*_jnCF!KW;sfjFm?t`! zWI^4-hGtw12ZT=V#HrVNfn@WH8tvf$@Wq*}aq;Ra0_lb!Q*%NJFW!g6D`2s>@1<&k z%JNoWpLwkCp7RQO!9JS?qd2=vKr}Bvb_LjCnB2#!G$dwN5=MSJusapS^03|LVpd9 zyO=R9Ynbmuieogz3#*U9CiaN_J*bx1{;OvZwhsbF7XL3SU$L6t4;igb7Y9AA1& zYYXvhhhf$DSiUA!T(a!IvSNYYv1nGhtx5NE(QsULzGoB-jF@mO<*$=#wru?dA^cWZ;SOG_*|#z*#~APUnmIV&X|33TtnH?Q}CgPBzEi%&#$YUZqc*$ak=P z?iErMm!xsLbFKAT-Ra%tm&T*~;X_{)SrDn6xvhh7S15Vd-V0)kzO`htx?QWbeJ=RG z#y=sHL|B@c-}tR#gvS8uQApRc(9-#cb z!}nWDL9#kufm8%=Xdx)|4+@CI4iu6;k;N$>ss0D0Nf@xVX8x)WSNaCw-K@K8VBqcv z6@0dTgMbW8+L|%PqqqYa zHpQ#NuioZ#U{7S#w1b}lBjzAwaOr0FhgqvajLPK$#dKQi9sB`9S;^?6TL>KFn0bRs z)ypS%+Cor+q(2{_LE=~6%nPDyAX4;%T!DEfK0Dqtu4XG21)`b%7bU-QcWlJDddcz~ zD};23-YADNP+v%XA0s=yxR%4|0m;~o*MzXqNE)dVTE5_nh><+m-;xuo$5%ESVbE&MAj15x4uQMHP{#{oZwaIJdx5m9=~)*%-drC zgrvtOkmz!|;9G(?{t9bGrNe5$B4AT3x6YX(!XE#He^xLyF(-cCobKk|C)zOYJ*9t* z2!hx5WS#<;xwfpmuf?hcAsVsVN8`z4gyq%_7nLgVOW=cq9_Tg!%*n z4FeC21P%Mqar(j1_^-t^vCK^a@4hVK>P+Y& z+ZWym{MCZ~W0+5;Bl3vUPjYhoit=yCeY3VrJt_c34B-@VSv%}IIPNtP(Zu~h35{&u z*0s8}t_oa)Up3G2z~{gWJ9P4ql=hUaOOSVn@5fIljc-3X7t$DhU->7n*37<^xp(Rq zZkx@U*%h^1Yee8$_4H}z88eH8u~_aQVl-@Mwg3IK zLcX2pJLy8ngV9Cfz1uxI>ptt(oB1?m4N^Gc+ms#h@;m!(iNCMhcPB-wALa%6ln&q^ z@t^ljcDNzaLd`X5?MdxM#*_%?-jsa+M%KU@uWt}MncgEmcUJbA*=hNQQL;r@IFJo4 zS9wAap6YAa*Vbl(z4Kv*WbSBYp8DnqQE@2aYpMSi}FeE-Ge!*W#DALd$&#n=nq z%mifsh#W=FtqU5!4^la>%jHTXKtcNo$F@GlBGcws@gfFjnflNbk4AVj+lHz`&JztY zF1k5V$?F12r05LJ-L%ib^w!v$4PGun8{}gHJd*9z?>7eeI)V0k)l5uDd{SSD|03G1 zHQsk>|Mphf_jRWkl)gtc(f@r=dST5#Ze0=nH4M}=vO?{4fTxCjHw>WO;{*^HC9_WJ zt@_J8U~0}cJIubc7lgh|Y1;H3GkRW3v5W{Z+0>cw1w81hFN1)QqmbCs#};q6^u6>} zeTlQ`Y|~<8r#g;&f6Ul19`z?9tQS^%Cc(T{@RDKvR!x~Dtf%(@U2;g9i`v`p{VxE% zw>S=|^nSBnit9;`E`>KSQ<+oKuw8FNpXTqk6hH-3D|i6?G{Qn|8|7=hrSN>{fm>jw zUib~4y4zC>9?`P0q2b;9I!AWmF}_~CIjvGj6FUT7B9E~wwmx{?=B}#@>e=tnqJ1wn$ZVUvQ<16tSyfrLYVNSZ2}aTm#W>H*-{GYj zGi7!xsf#ziVfqI}n|Du$uucPk?pK;nyNk+|ia3yK(PzSzm9%Lp^k#_TtjF}}YlE!M zp5Na8!D-ioF;7_q|4g~p8ZE4f8qC4rr-*1(r;rgVx8a%53fmrH2f=qsnFZXhw+HS3 zkjFGJun8A=fce#XpaMpfG1cuI!zci*2KM#+W%p|SYMm1MRePv?79L?y%z4Qv8SN|ckV7|=fh*1dLS9A761P{y zZ-QG#;%sg)2GH?M(y?y~2##E99lU=RS0H=fQP0;f6pd`nCfU`9g-?7lgkGEhh;6AN z2DkwRfo*BDyr!+ldYR)qX1VPtX7D*PEgw}(6ArwbJ+?v zEe{B}Z1%2mOf0y)`U@f2Hg$>4m)d$w@Z|>0*yA?M@A3=ZyGq%c<3a%W>WIvOee)hv zzonM#EQBw!^nWC)MMXDnu`yb%&5~p?4SX7$z;c&4i&nSuUOFmzG|x)Xv#*hgE~b_d z7835Q#uM>|$s^cPf0P!b@uWA#(>NZ^=9U<&NV}^8ewiB_5v~!lG_+FJh0U=n&c3$3 zz<40#bA1@Li(I8_D|2fH4QtS1Oh=d{KB%Z5B{Td13h`#!vu6XcRp5X*u&iZ8J<`oe z#Ve9cMT7agzm2(VWZP4t(EDD0w_ZQP>LjAX7IJ!k|AqlZg7qkNwz&#ywk;2lk}<&c zpx8`NChW$wKBpK75OO?)qYMqJ>l4m%92YeT(Q1k2?=w-Y1dP%%NqSAj+?|dgQ#ejB zL2>&?(Ar!3^i$Yv1rr!&F57J^DYr(39c!LF72D@Lq`VGR@O)+zsSVSZ=T06}70c9z zYDQ?=pZ!AdAO!XP)gp!xog}=YT2EyMUb0n<8bv8F)V$4kxpV^SxfFu%qZ7Dxap=Sj zq@S$_^@?ZD;~ul)Jn({DFVWG~aq#RTV@6?!KcSY-gp*N ziUv!#Fd80zoz2%?lh2+5bC*32A+oWxWyEcFzzSPB#3+@WdBkz%$6A}GYp-i0Y{>DT ze8OYmW5T7;mS(fLSY>J2WK6ZJJB1S-dkYl$LLSm5KBzGz^`qU+BWV|NM%?+tU`WG@ ziU{9-+4Dc@gXUG+_<57`^QOHsH}WV=<~gP%XEpd#L^9UapCJ*UD>w|Xhii!I-J>)s zHf?#FYLcuk{OWempr{OG->4<_y z_xW6mk&JTHJAcQb(MI{XN0@3;)4~|#cc)DqOKTkRhz5(?vpk`e|scJ^)HWeo{|C;Xd+I1<5_MULlKgL^l~kGY{y#8@}%NnP0rM^r}|3fp~!o#u^=t8ex5bK z$#5p}h)X`X;(O7p7alU*HhO<>%$hpNIHIm>lAT87Zi%U7L;SUb|91&RaWVSP@i;^W z6@W4)sLUhOBv7c&P)j+Bo*V>Y#UcH9le#td$QQ!Mt1){AegjA#6inE@zMsPTqZphr zxV1YpD~^Atl0a4=X_eu04IWik@#~^Y3mjccsQf59O3tu#g&r=*Sv7iDANCI{_<f=ypMLPVeAif8O$3(}+t>x!8LqR3gx8kNje6Uyw{#@dwn$3yAB9s<1NGR63sPGW z4;vELhD$xVnvTN17zK~QNGu!g#Gv<`ae?@CF+k~uf7|TLOQ*d~eq!03;&M^1nTPy? zQZa08$-IMO=H#=j8@(6V7%NXT*pwS)kE8M5G*=uZ`cRa#^{wM1v(^|uXZBHasf1z5 zuxD7!b!-yHyR5yTpjmmE3~uA86v{TuuT2;KAy(G@gz}lVxEP<%kf|IPH~mRnJmVS2 zP>VP#+$Snu6-7FNXV-Y=%u}u{@b32AV1XnL63NTc!)?4=e4g>0WC1@+`4%?{9*d|2 z%vMQ?sw4T1ImwnsLu6my%8b74f26rUj#a<8##-wo&~uTMLUi79QBk_yG(}@?OJm~D z^$K@bCl`8LPbv?Uw_GAthcfO0fE(@MG4tPsp2n>8XvrN!s)XUPCDqMVz4{YFWyUS( z#D@Y?jYnT!5Lq24j&9i^)we%&gp;nbm1u#P!-NgGAF20a$`*cuUf76ox|F zieCqOiVypaoEcUBp(rU*D{O%qgXVYl;T^j)`4g4J-r(%izZ=?~6q7^v=ZR`0)e5!T zICRqGt8oB(*<&&q{%pgYVs9p5v`hy2-sQTPr>N_s=3_`)%XaB9vM4NYxj>&V1SaskETuBdQtLZKsykmtBBN_udisf7sG#e8!1af;x)zrjD3lz^?c z78|p-H8d-`L_{&qwggIjk?!Xol!; zB#QD_Bw9Jtlk9u*F1`lAB8bXh({uvTvn@v^!k{`bCd{ep8CCLl*1MyvRDmWIk=KVK z+82kkFaTdRm)++g6>Nrr?U51Gg>QY~Ir#js79F!SW<^2ps|z}BMNQgpZoOJ6yd#Es z9GWjYCjS4RCW=!Hu^ zAc|uD!lmUNZm^p34X#LNNS@|tkq2koH}{ildsKcFns#n2ot8p&5-DJ9NO>x^Cv-^8 zo#F7eP`WC?U|415gGat{^s4zIlQWL1&8RLI*g-B+v|S6-;o(Dpv$7*MJy@{AR@-sa zHX2^XfadU|mR%vm%!na(IqB1%o-jsp&Mim7va>Qg)-L1|j=#zb`FYKC|Dd37XMci6 z{@wm5Fy(-_X&K~AZi_~2T79pjed33c4e8Jh{@@!N9$*zuQ&^a*)bpBuTczGXWd>6t z?S)4L!@X`J^k@6(hxheB9R%z%VGc$Fy^CL?e53FKP?uXcpd}HjE{Pq)Meuv#4q(`> zt$O$~_S_>rx~u^!`9X0G(^M91Gw@(;TqdZpEt%PioO7#(JOs{*) z?2JUHE1X>uaUV`|&r{P!A?g_TMd89vt*BpTv64hu!rS^b?cgIdBCJsy9Qn?Wd|@_> z20qL6tG19;J1)Ad3MF@wtthQ2weDfDuA1dXB2k)R#!&OGWU6+!RNfnYUH?cXN>cvv zDqe`#6Fd1?(u?1>`9`gjU(=is>JqH&H(cL`-qg{@T{f;knct}j+;8DQtoyAILxVaH z)4T|L1rR=(XRugHC{uxl+Rv(k{mMyX0Y8>=3iZ~?gQlk<@2&oH531V;grW42tJ|o! z>O;laX^&8o3o+`l)DwFWYHx-#MduqQ62pYi#9@D{C`J5fKEavohRTLVSJeyn;v>5N zLljtO`pWjU7a%kaY5=8-f)2UPj zOSBfuEFT$*q%Qu0g0^LBM1)`5E4af*47Nci7?R&P3ek#nj4(lmH&ZVUQ%>MM@M2=Y zy#B_*%bEF2^;7Lwx}+Ch!JHcz2myjU?!xqSWn=#<%7lX8*5|UhD}${L2-k=@NUJuf z{OBMC*Ix2ABlf!NXv;)K)RvZFD*{Cb z&AII(qnD*@x@$Hci3&5Bn$vZCKYT2G>nKo@eua*a4cNfnP{5M0_IM;R@$XuOQy2IN_2mo6brL1RXy5lrHcVx3 z-?|fj&A)1iAd~u}Ax6!v_)*c@waZs4Us#U`5}JQBD!nlz>jbr-%x*h?|Or^Gag0Y}GK4eqY-jzol?&vDe-3OsKl>c8czkK>Cg z@C4$%eDMg956N2+Qf2Q{hcW+AzM)&jj*zZY`rN#4DnD6)jT!=i!^|+5*sCla?}<2V zPg@76)>gmZ{yh2zwYl*(>dxqapg8@7-XRX;n)FTEB3dT16?OqTq6%BsozCxQ*14|x zK{|K7#N|vfjg(udV5fKXbJ@4`xxajGi@{c{F~WF6nx-+%3Scp_?q!~uGx~Tfc06>( z^JI1eQ@t_GP#ff6V2dJ5L}-7hP-1CkQB?%?OL3~zYzR-uPF)8#g^6i-nn4(PAdjL0 zKTPF=bY`saVh&^hpP5~poAl~<`3L-j*l&|iX6Cve-#V8Y?I0@H&(H*VTm>1)O1ww& zpn>J1nhvq0L!`dbd|GW4u^LKT>iAsWfwj039Dr$DDRZoWCgeP$%2-0oyCdmYtY`B# zGxusR)fSi9MEkOgVr?_#JZH_XpwMLeaN^*v_XoKLn zL@265T~bW!xZfIOvCNCifSeEzMUIDi+kaD&c2%u#oH z_5Ah7wi2oFITmA;oCuPXZG^-m6x(I~ZT3aY+x6`qirEm4C{prv4UzTv6nCgLSj&tw zq6?~m#51(W%%nxU_;I-sK!^{9J&l4whjraEQ?uz{U~CCcw0YC6q0hg_t2}>mty%^j zlo8ZD(;e!MJQufZns?dPg~z75bBAhSx5RM!1Y@^4UFXiI;@FfgkOeWT#!M#zNvxBq zm$gXA(aL}@%orUV>Qz!s2?~yC&n%w=X~C^IuNGcz;0%nW6xnaa$}jAhrjyKm2W zcW%#{kNJIT<;su9qodRbg%pzZ*;|Nv9x6MX_Rz>M@a=JGG7<)zfy|_4gX37Fl1@D zDx8pLyfe(kg(<9t6>29F0`sJR;pIVW({9fn$d+Inx}h~SvD$;_7zd4b4;l+ase4@# zr*~uXesO?Y`L~wQ1J_l&hOc&F*^XrqJF@OKC7H=eQx(Adk!!qc$A>So8-)?RwCcCb zDfh5T=hNeU$%0`CId2(Qa=ECJKBDk2U45g5BB=f@lBqFo(^#5I-|)tKOYrEV-&7f2 zqG@O37O_|$>rRol>Na49 zbrXwd2n026S}4MIM1~KMrI`;*8Tt23*|t#}0W&Dg1Up5`GVSdO{Sk+b;rPgj*_lhC z`>HPB#JJe!rvF1xkM$3t)C9SQqXyODy~spg^sFDHL_%5;>$#aZ7ZPei`t2rQsLxetzDZUzG_F7va&72VvvSl+PH4js z+3W3KJm^Uq)cl83pqgY)Z|d~TzcZ|9&EWQ3a@P^+NqeFL)P{~u1KmyeYp5$1N7hqU zuZudk=uq#R09!I}hY@nw81^%P6i6qwU3UY*r>C8qsHNQWRZZR!N+D&NtG18dYkzHH zl@ZKYy=vuj)|JE-YXD#JF5OnpIkph#4^iWcL$nsOSP{< zY8h3&YF~5(Eql|~YS)^%Xpq+tO;2HccZiE1$e}&9A`lr;c1cYP@R?iOEDoVkajRwN zI(%nhtY%Hq(zVm9qi}8x)r}2ku{*u2Z5%)l6;G{}PhT+cMxWvJS?x`jv(Q>!{zIR3 zr-!keADRk`U?i?P^k33>P={A@Mbt`(cP6V?O`#jxwQAxHnLZ6K?)~v5nbE}HR_t~5 z8q}tL{(W>xy|3t~u1-S@v}%xJn)<1OhTChbHNWaHbmjx?bfIK9iT*%)7Xq6XH>&I! zv99&dt8tgNLLybkA!oky>z!y}(P#aSD3pey`zrK`bq6DcAr@-y1*O{)rh1v*lYZll zn^x(^vWzW}?c6CMrf=@H33A>q?n>SV75V;?S0!@1Z3rk)$FsgT*ZRQ zqw=Y|IT6!W4O=u;c8?mG1ip&>1(Es0|60&ae4U+zx}BW!nq}43{lZc=b=UtAxC|YN z?hFgy^*LxA6h2V$FY+%mav+YAw0+*dw2)b_ed3*@d|ltr9kWy_+jXl}i925wylKfh zrv^X%Z2kEbR%OY>=Q3MSEkAX|xxQ`sW0%*P@=0~((VuPrwOPr2ZDM78rGBqR?-6;E zeLf#?C|@t&^#XwiB{Z+_9YRldiz@wF>65#hfH&xwVA{sqFym&pp|>lRNU^}D4x}Ne ztJpb9G7&Zyk9v-mrGHP)Y*y&+(C$!jA2R2Oa24CQO7 zY4ZC+;n1oa^Lp)tmsm9WRu|NwwE+d zfAX6RzWJyv>2*@_Rx8*rmCA?ti$%l>$WBl_W2IkoKqv#FE#5=V-2%QdbPGg!tUE;| zPfSwH`&D5871djFiNK_3)j7y)I-_n!nB|2{oLuuQFW0kpem{}Ke1g2u6$@wq3%}J9Z^+)2xa$k4uRQ8@bq(9 zY$shrZ5;lER<**B)f!Brrd$&p)EpFLfzhZK%cTFkJdQYpqJ_^p{DY+-z7eOY zu3?(uO|??F)Qci7g+eG5VL+&iJF~A4ViK#&kbk&ZqN^}qOoCiNjcomcMA$kAppG9~ zmkcUdA(Q&DzHo+$lY~&2RziZRE4v{nr_eK8FT`7B94^7`QFj~#o&TT0lX90b;6$d!=0}W<8`;k`X!Xq2vEeG)B@nWH~@Z8`_ zYC~vA*gJzUy2nnv$iD}QH{R(o?kiHLDu-Q` zd132(Kcr)*+|3LfsHm)2pQmlA=mEc$a4JH=AJv4&B(`#3&4KoG1Rd#@ChQ8p@UZx^ zWq zsC|2a6T%Ec$WIuF+ez6+%`@{LAWYQ6pDaBV#UYOwG@_ZbZ3m5Ly2tI^+^u2wt}q{4 z6Thr~SCl1EH6aqJZ0x{;fqR{4ZWyfkaWv_lYI>|u;#PHzphToIRi0mzP(*^;hj%g@ zyqq6+;*5SehwTgBKtU>%=@=S~lFSo<{MfSxO&879n{><&=x@hg{_E75nuT+@t0@`9 z>G@(>^tc0$%SrOu==Yy2Cun++*J-T*#;?~V1JySDd!>7s@G7BPgOmhglx;7vhRX+X zUr@vNY{tVogY_2 z5k|~&%F@SRV;-h_n2M37lb-?FI!-(4Qx$)*tn}JD^Yrk|;4}*iC>)PU7MEers%t;p0lEnTd|Ad8*RD2MU18 z=qfo8UMzjg$fEmG1pQ2eVLHSYT&0$7> zw?ZegpRjW7c7Jo}u@Yne-%q;USy)+tv!et)FPQIj9h?L=6sd=`{@xR}JbHZ*q*}?3 zwBp2)sUL-hz4e35y$vCHh492c?o>FkNgVV1q3Zqxw4zTPt{-o}xu;d950PJiHi{TI zx+R0%=&pM{_uWEgf8ZzJGmwm#bGt=Qo>H|*gH~rDBpzHs+7TOLFUcjZzaYc4KdhR{ zjRXn+N=4LSutv~Miv*eU4+#8&2Tl(!r*sAS#iPhPpP80z^c@o#z2512VrbKI zcx`?pb5!#a-*}J?`+O4au23*39FNe~DvP^|vY;dL#+P`LXCI3Z@A-CLIT_866<=d_ zy;;d-U#b3xiPyUWw*8tQbmJ|C0V8?ss&L@u_mV9YSS~VhQtji86g4Z5>BT=J03s_H zRw(9d!8NK468DTG)QaxLe#CoVwYP2m`mjHQmHMgDCLx_g@}g6iu(4OqUjiWo&m`@8ErX9hg3|ej zNA{~1K#sZ=h;ey35AF29lO;oVP#|5=1w^rEvB@E99ACIb`t?Sj-=O0~6#3wbyy#1p z{=zipjuT=OxVqZzY#~|G$Wk}QH|AS7AK*L;wT^uurWm|y|6MBH5isAfjkU$>0Eze0 zbWe9ex2~sX>Up`HG)N~!tTfBR7)hf<$tCxATLAZWdV!xwDQCS@U(QH+2^I9PRe&}p z=mzGnQ3C-j2G&M8*XqS3j!E?R8+~q0vDM-n7qiwDU%h5x8UYkV6!8Nnw48U=o)wE( zd8_eRX)xX#Peq0~Tcio@0}Vq|r-uH*hj4?E41~9kYYC!)WKfjJTG3;u z+8>FZSu`?B_=u7wB5hu(Zw*SP%yo!dX1^iKWr*g1W_H3G7)bT+3D0C8!mVGW>jYXw zR!U~30?$qR45#+GNAjl`9j^UI4cdiyJTkhN-%TnW&CGF)%!LrW6f4rkifsEt6f_S!8DeEUF*VE5Q{gg=EhOGXhr(S$zv};yRGZSx3LnEmS8m zx_e`@y6XJcMvTtvqRSclM=Be{7qUV8rGjOlZN6+l4OwiHHcZ3zME>LKCOBh6l8Y>u z#Zdm>kq(Y|&3zpv7ec(~GaW&+dV9p;K*!k#uh&3MXp(sZUxW<?E^&oC>8zo+RE(&L=nD)-@>|TmAkLiFNA`N(t{EW%dbTcK!`Q!tj+JJd1A7`W9Nmu!P?ni* zc`=;D9|o8$1o4Vs_6g@VK4+KaF$bdwO36IHW|7nnwR~-vE)Xu>0C_~KxZv+0vHzs8 zNvAlUj4kkaS*7a77jJo|v1a1jgips=?}G>%2UZo0ESmPV*9bBHo^P*55rT5h3}(=- zSR4dz3*X`qiruYm+Zi#_Gmb`>LiO(2an`3b3a+V`CjJ67lV`mmG^@=UrhPMpW)RzX3=U&ac+T!tJt@FiMlG<_^a5&0%9Oz|{=!v+I4PGJboG$9 z!d!A{OvfKdy`W|2jPcCHg52fw-K!43_URJ{U7sbyd4M{aeKbm?yIu6>#U6uae(=>d zA1^OHDQHuhbd@;?oKAF$VTd|HDWZ=YlN8PT3j#>`S<^?^v-fce8h6ms#x-2hn$Hr6 zQ!6_oVD1s-a0|9ZGQ@)-&S01L(mH83ccfkxL-9BxH=5sWU$NrdY^TfQpgB z>`k|(RHK)F4f*tg2*5Ll2BI~P#ec+{sS$mt^hIYantB3=%Ro2irkLmQyJ;TbeGR%K z=yu*x2i(-e2pbI^sukX7DKP|bi3*3OKT!nqpsctP)_xFX~7++omUjsEc^Gw}j8G#p52x?uQ$#9$A zrc~68q)#i~Uz-f|5aCxr0g5PH&U!G3Ac$8k><95lf|>@vVLEVr!Imr0AUEnxlL0xl z^^}P zHq0!$xa{}#%&qM54T{yT0FpNFQ>;~~ZEx@isR@7HN*oTu<_<}7i{7PF2- z0}kUbM^*-4AVrW^MBFRxyg}4a%Z+G&jAC0|;GM+4ddpTQ!1j_hls?B(IK44!DOm=? zD+-c3$UIYdIUc#wnLpY;qTasWpS3vYeT4m4$~@||+dz{8AZswDcNnc(DBkFvoi=4o z>i+oRb5~zLSsgC(n(ILjUWZrxavN|%(w3tziy6lmF zj|eeGdm=sa8-o_4#^7u%BYJD6xfQ{8)UDYrwp11igsP331fgBSPW<3wmr^``vQt9S z6J+iwqLq$XurtI!UMth6bxY-#jY7`?M%*QpQ74Tjz{*_KyK`d@*H=4pxmF#h&7)-T zv$VqI$Sop8^VB2f8?KK8>YEn!3e&hKd>NZVEbYn%r7!23by8X@+dJ0Dqi>`u1p1|q$)xj z^{lz^X49~|tr#K`JsepST+G&cwRA8{v}3MV*Fku-V2!pj_goHU87Eku<2>X{gxmbqwGr#W~)X=4b{A5V`R%#bgMGb%H|vW=EGEw z0TcUjbrDCcQU=RvB1~s;V>jZ70nTh~h`ki*`7~PAYi9c>^sMKsgqYuSCCDNq?DJ>! zue01tiowqbIe18N@>02ey^35iYZj(`^uP;3%J*eWk-jmT+_2W*SUA5EtC!Ko!X6AQ z0ccsxDh`z|-lrRa!m|2BPFk3acBAfcoOsyG5RhPn1D=PWV%#z*^-nTvJjg!*+61^T zx_m%rOH5+g`22{n{EBd*VPUd%1!sKkVF<91F$#xUh7K2(OFGm*NSxuplL6QFsn=Hi zjY(~n%nC3T(OQiH&g8b;@zppxWD@+E8uZ@rT0AZr!Whzv?`*|p4(29v9qIYXQf{1W z<`u(tTa+3f$ikb*LDY~cr@vUogin9gi#8V1uQf_E%7 zDAlifc2qlztXi_2v<-6bCR@+Ur7B|chc1PS`+q@{!i*VGCmRd6Q+iP=4w%zV>svZI zC7uO{BRAbt@sb{=>oT3unJwLdpP$p+ek<7Z-Dzl~Igi(GSt}IWuBjsdZL()B8HIoG zON^~iQ?IWsLrG9UZd8WjFY@-|=}rn`<03WHHENU!naVAf?ZLtVW+u#d|v3RM2UA36!?*6~-jZo|*XDo(uW2wBJRlgiFAUTS~Hd3)W1V z_ZV*rdbBus>;}3sdzr43tB!sJBGi#t$VM}*u5ymWO=O`shLKU#ETreSro1J0+%{!g z{`c=w+N6Ah`mD5R$}{d1EJ(_DlL#BU0EbgXHZvTe!O+@2*uj^%J2f2vgtzt?GCa@- zgU&%^_zry@o+|N4oC*tz86>gw3x#_$n6MhE3QSEVlg#FM2}<5)!|tz0Cke6BIY2%3 zCW`9gI00g)%FENS;))Q(-id3dj9!9SQM3emAl{$M5NllPyPzs23{8@Xsdfu|qe&2L z@a_@d4)QDjo!-N^ep$6c9|^g8?KL8nUwoXKWFr~0H_UGF!Pn6KPOFkeK3y1N>pF%K zlXXM_<2jPC_{X+W+mvC{oS2@$HZ?;U(;yk+x7k>u=nxS3xnY`&XoAg59dDSlcBNCA z9H`+f`r5xB2SN&NID8N0Ikf3{FE1}C9fyyU6!j5N&hZ)XvEBUbCW`7*WXqs~Ip!va zI>hQHvgY=2!?M^&C;Dn)?AD*Nr6jFk97<2} zZxsElDAqJ`3dl8JR}YtelI@DAz(v%W)0#jCo2#A`#@*en}df zv$xzh!-$VXo2WXeJX@0~->0u>dA$i<-1uHUSK6vv_@m$#E=<47{9!}A!a49M$Z0`)+=_i2+nlj1udL?9FN|@ zH{r~@c=EelN#u}NTtmJ`jwtkyu&;if$2IKTvpfHJWfo~n=iUbhQU1&s(N>dt6r<}(>L3hk&_%6qe6&(aGiiHVbFGm1yNcuUa7LF2)`8cdHJ{K_Twl3Pd zOj6XP8gt(85{$seGIi1#7r|@I6HN}+Q~^5DkskCDajxJsg}is(o_{+D);=-7E^Eby zT%QIJV`kYXM-lb{CVFK25Oi1;j&);C;Tq7<8#{rj9HN8U66=;ON&#O(QU28NHR8_9 zYi$QV}8j%DUQuq>Hb zhv5DhNO12-=*Bk0DcOs^~nWNS6Xo zY5CTFAGF~zabQy}MN>nsTpz*r-Q#eX5tyPQGc>Q3p$}MN#U6hCyu~H{EmAjbfZ7AM zkicW7T}_|~QzyzK?Yh{%5iW|nnJFF(AV8P}`iI8xLI6Y_aEs+^8~PsC*yy=UD0+vG zDp+-m90wqVCljuTy6AyxpxOx3AuAZWtR41E29>2QMWcj>ljL|--2!*1`}wl>72eb2 z1_xv)Mka3(2l6ozTh5iCS&Yr17sRMzi*iXZ(+|1ph1rn&`puF{iwuP!v2u=ho+;n$ z8Mc3FJ-yDWK3ZHkl7i>)%I*Dh3Wx4BiPoZt8==Br)xYRXHoENU@jIxrwVoA^&C^tz zy3MD)c<0(C-ARvuWMv}SnxFHe)U{*eV4LCP8D>JD%zx6j$rqF|wF*rJ;FvB9&zBKn zGz_uXVP}|Um21gz2h;#jz;nr(TK4)}F!A?p1)lFg5YT1rHz9%*@dgbtK9Tx{m@uIU zk(*S{gA*c7X$&u6VN1P2(%0ySEq}`FFF4SSTPH#Z@Ju==0B#GRbtz0B-O}~TKo@Et zu?lpi#Pvd^IlPSif_$+_GB0x8&4b$l&wBkSH)EI!zJS*J_|hh7-wz>TsHrW_4;p515oh!RE}se?3IXJcvtpF*5H%5Tv`rC}dq{ zLn)2r>58dkz3B4_71@tWHzTr2%4{%mA+G7nzUr22J_0rDoqbod;4dULEju5&eF}uc z@D${Pqnv8fQUsSvy$a=ER`fay2P;g9AcMS+!(BjgS>B0}j=l9Wad=#WFeb&1VQ|}d zGeBc)XwceB8&L03dpA}w4E!M-c`A@65OTE41pO*7tDIfbYvox3K2&lh7M7a~Uga%# zhdw9175GU?D(iCcX}m;)CqdQL6@@Y$0mJEz(~fA~@lg5$+GWSnTju%(1u2g!Rc9>o zo)!U#2!(X6G&Bdh!`WF|pecAIqURp)HqA>+Q=a=t+2A8?*OnH+MOsMxrNyZ7McC#c zs2HS@ME&+FJ$h{5Ig17=FBLII661m#FlTH|t6_d)$Xf*Lg*i|WK~ibPU1 z`fz(Bwr2L8!}sl=tC-BLNE(iJXpnetCQi<~XAT3mL)(u`i|r=Jk9K5=q9ze6F|Nd0 zJ+!Ko`pJ#F%DMcoCkT5gKOTgz>s@YH{S+F2r=dKisePDTN-)|6OKUIpyWEXduSZ&4kvFG;7_&syP!pg(4w>=G%J~I{)nJuJ<#48 zc~6bqD00V%HhfVbHZIN3Kuw{Cr}%PpqHeA1Lb+|0O025&d)nt)S&-F)d3{dOC_h8_ zTn5?Tyg)_OBaE4H0hXHp#_a_(0z1%V8hjPjkhjJ&1b#|9l6LjCcIXRa#Sw_5#_WgM z(V9}(8Ot}u7@;TK^>ViP;`2+n!;!aEgEn4bpx(XdxtN|Q<;>`C3PRzXaPG%EmvdFC zof)J&2~xoU*JPKrMM%As*kNElKsCnIcxF($@ek9bWaw5b(Q`{*04=bul7P9a*Gquy zl2=8%x2cYqS?f0d^nvmb?YC5uY+6{v+N4z|1rwXt#_|Hel6i!{RR3 z9II}v{4hU*52JWR!?P#xCd7K_?tET}+nPmbIutv9iIR;D3Twsxmm4E=kg79?`NAnG zbFlGsZ-fE!0K_qPSEf?Hhc6$}tlq?7JDqIfFay{!jA}_GIIT%P z7UR9ZXg6ExVj$FjI`0-yjpH7KDwSZ3_SkM<9DgsU%lge3mt;33JDDy^HU<; z`k`Yp8TJ{}!2@gzk^A}A_VOeg-<{#}wB&%P=7mP~nY#osVa*%>fiEc!3WO0CeL_)w zL;L_RGxsqyojo1IrEOimg@VtCKYL0SroJK1YTtNCH5+pu13bB>CgqHCtJ4W&(a_br z#aqNaQ<&Gey9g^h`dh_#z_wYqORhgwz+t*at-P(sOSzy$=j!s* zxRRl{`CU|UX>GP4(>=`5$z6B_LqQGxzcurTAFfLDspO&3OiY3(TNm)V`IXlybb0XtdJIYpgyKhnzx>)icIkJj zWh>E`huxsC)~^GZMO~lO?de~ee3xCdRNToKzp+G3!%xF1AUQ zB1-KtR~jcf+EEvO(Le{Acu%q3r2AcHjjS=~+Eg>;mR4H*Vg^^ixe)YNrO0$}@7srr zd4!O0ikcB-qfgJ`5wcvJ=0$x`wFVMe}e~mmszro0?b0Mi;hRQXTC5%Uu~euLNn#Zw7%P;aQ}2~ zm#kXNGj@?}&ymL19_7@XIo=*c7*5PP;H@(TlUi`}r0B`u{t`o=bmd~Qxr0eS%5r2d zZ@vzk)>*k8%MoMC%WkpQ$?43IS}|xOZUMBk+QS_K$v_|-A3ypj&|WguIugtz>mZl5 z$AW3Ir}vifR>Ov;$9tN7x&ra{=6z_eW1~jr8&!8zV(J6!tz=Yy@!_b?#6#d1nQ282 zi4tV7KffHgV0h;vhk&?z;GHPI*61LNJcJXU`tUTr>y`B}{QSBwWD?9TR ztmCA6=U>F{c{^Xi;kp$XuX(nu{8g6=Ql(m0ZJ1tmAr@Awl`CmTn`dPOlyzStkBe0# z2=6O=#0OTx@s75-rr*W3C|dMGY9}th95g(&FP>;kd06BEJm#^1g%$*4j1-ry@E3#k zJuG@I_w1{6Naue+P<#0pyc};)9+7^jB|6zQL7<$)Z!*B;015&KMd1(6u5>4*3sY*E z<@k@;Zpm6-<=^?loCJ()aj9635j3%kL;04X5fXs2tIBYAm&h? zP*(;%MKKMY1R9SQhfh-Vjnyc9A>P^Wr=Fss*gEqYVCF$nyPavELz_?X-t5-fTiVkPvRqwxngq^>GjNaoj&CwOz zO5UNE#2B+uUQ)N919D(*88q)E61tWqbpn`FCUIx!PyN}9^8wrIlgxgo4pfEb#gT-! z3&1AM0Yc4(coZF7OCTBpb0=w^ka1d}VuXJ}G3P%Aa0!dzhz|)dv7A<#2?zaRqW=CT zwLB?@=KvYQdHhF8?m?;!8b!`>i7l89!Gg(VtfY|@&h(+7uZ#naGLWWwE+;{!L%iQx zzP~6VJ-#0~KcRp#=4z=}(am#%npD&IiQrLm{ruLO(-jpbl-W!mcQ@U!BPqmpgwq#9 zQAn#N{O}XxD=pX8xT7N>!}*I8nG^w&f?WIZA4BPbWg3SaQtgZG4eM z9xx@G#*hf*mPU`*cQ7dJ(DRsk8Zk_$wyS`;&^tm`kxTne}Cgxy~dnxL{3FHBe`?dN_4ex8AgzWHw>zZWv(k7O$m z^=2tsg0r>r)Nm(zd%Df+Ef>&7 zZJfNy1wJ|8;SpVX7%nVU2~SbkWPiIsSad`LaYNB&((fY)Rh~o?;apkKMSqw%&y;+b zQIjgY6Kt2?n%hTI|7u%d?&1*`N+UEqS#TV0kY0K24caVJ6=>sy@D zSF#VitiJRR&wj%QSmkXFfev1%uV_H**&X#q!(;76(VtT|q+bKCQhLlvxJ&^G&Y!Z6 z>?ZEBp-S+uVGQw)jyt+VadL+qX9PE$K2yc6mYlO;$eHX;{&vXMD&{p7JnZtL8Ph2J z_}(v-NX#`BnE{?(MC|e!J)7Z3$if{Oi!3^~2ju+0&-jxDTjeAa(p#=!x^GH=Xk^;e zU1QB>GC%a`Zssi-N+%eKbWh3B)|JAmC(|sNu2TXJ$&_M#K(&fpe=aFC>QGT3sE;SmMWCCR z#VFgZBUam+$}p2!!z!ixGGaV8W>s%#qZ+HA{+AY^d~>;fP-Z zTFbS%nVTgL(c@>_X}T z1Iso4L0g#s)l}^9ljfuSePnw#&@bVWq_C)Ub_1j2cL7n22jyRo81HE#Z^hQARgkKV6y=g0aR~)#*~Xu2+aJz^ z+A3qr2uAZvGB~Svqh;QS!pO5ZH1q9$U@|%vi8N&Kt}^bfgc`#T6D*Ohaz%lz;`b65J;fC2IYc9l%Ra6N3|@}# z6SmM=b*Fu1nY0%TLbot*`v)!tXKjlRx{GW;T-lS?kS-kFXle6=s_1g^x|A+QXY7wHz<)A6qzueu=%jXgXkkPZE1V5d`rraqzJado+ zpo1Hov#6Wu{&cPxL+t)%bFq^vHNZq4kp-aBYnthBn8_p2@ z(~Pg94q;aGp!;W!oPR-fr*6<{tq!=}uBWiH7oT|`doH`2_kVTODbQ9O7h&F4?eb4K zO{a=j!s12PBx+t*+Ywmbt)G4M|L)Nayaa6rw_@OG+88`|tyS-!vu56ZL4+9dD9sj}0k_1d__A z@z4M6QvddA(;ekFN**-$*h??_6S=>okfZ4j*UEnd`QJugUON?3=qSJvjzEr^h{VTb z-HoUml94 zrgfkWxb58fmy7@QJ?_ZKwA(dt^Yi0XYYjcXJMbg%>AxBLm*+7gw?h71YC;#?5J|$j zJ;NiLhyP^8JsXlm;Nej;_Rla(6+*oKKjZPQQcb;Gv}{XbX!dj!6+KPXW^zX-|yK~4@1@()Gie~{FD zWq$yKmA>*mj1(OM1HMu~{+ajjl^h}n_zRK-!<+aFe+B->E8MADQh%3yluN67)br7W zXcYU%J55N=_K)^%NGJiR%}WV1n3|1k+l2bE2lEAu(+A7@am4kDI8cEP(*S~dXJnoA z6xZnjqC92n(dsxu|8jdr$Odl$EhWVDhhOY10j^Z;WSxkhpQ3l>-lY%B^)Z6-GOpxO zvqky*9oIeav>mC#o751DrRLtEnec#n>;RB^4}qR`PG^=oBv3l&OE!F^ z=9*`kC#k2u2ugaVcLu#qIXSaAYIX`B2+7ODtG+fFz};8{*Q~;D!X62pYsRzaE*T># zCaiTe)>(N=^Ps_H-_nRAP1P1 zdXTT|N#L>d5auVl8#0sBK^Ve7kQI>DhAKS*}Tm}35dtk>Gs z5sZ!*!{wK-;{F9OZ0D20#zcH3UF!dmc6@&qjkwyzJ9?gzS^b4guKfYQeWPdi%>RNX zp=d-W-a~25>Tsm_Mt;P4q#xciSRcI-;W)oEAgP#@GZxZkK#c1f=Eyp_aiimN9X2zs z=Y#4<%5A5!I~1h*Eh+0vU!i!@85vfWAE-;O*L7-T&!N233xdR*xk|?2O#37@$SpAV ziwUt@*l5?=2E!Gt{sigSs}ft<6J(Lmyq70EAVSqX8>apY>@0;@6yy5-MY=FhnOg zhXyx8YL|rz;*7!L#2x#zL+LKxB!i2-XB-E3wlKD`PQ`&<&5Vbl{1Fepw&;~2%o(Y z{tgG;D7p*2v~E!iD|~glrBE!kd$s%HOOX!~a-^Np$j1I`XLFA}CwP*v5bb*lemg6D zCOv4($ME+;6XyAWvmGiZO{bTkz6uZ^BD4Up@&2$XnVm|Pk+XH1Y<)IP=y0MCr_^o` zdz7^V_PynHcAs|w*UuBotcQ+opS~>!7TlHRL%Ay|PK`IR(V>0O(o<(7kS>zoMw()$)k^TwL7JGYW*`bI6o70}H$4hnCA-;p2o%*r@ zB*4SGl=*mlUWB;_BFu+_y`z==@~%4i_q@X<2=22Pl<4LDXD_`pB#Eiupi4gVeIR4F zte|dw`L$CyawZ3XfU3ri4u)`s$*j;Bv?2jJtAmw2xg7@c&}_?%cnFlGkYm_z1K3`a z&~m3CdsEDi733}9t7lbSRv22b&rP5 zf)ZLle@ihaiB**U7Beibu)F7Gx3}IRSaw^1i*eXg$jGigbMr6y zzW57kUQDYowPKJ<%N_U|6r$@^1viMIGdKh(lBn{?;&IAYs`7J>aKc6VvC^=H1#RDr z{0_F9#@4CxLw_aWFpO>lLm!sh=w$%U2Yz~+Orn)UPht$Wt?&AfW11fX(LYkI5@mHG zx|{c8&nzNh2S*pbMmAYNL>Ohn{kVGJI=YAqUt|ZS;lxO* z5lm;uY;PYOe$0%{?Q}(>dNdd`_m0yz*+BV&rm?a*Cht>eJi<5=u+I7ujb-2;SSN=& z4m#wIm1S}rbanAO!WX}OEj-iyf_zOPbSVFvLcVBD|8I4R|4JbQI0oJ@f6X9s#6pS# zySD-VoJsz{{QfnQEbX*Yn!XnPA{&jbnW^7?d19&1M;O){;@ZGTVNxMeS==BJZTnQB zL%#I|37JjZQH^O6$1_WUHILZeMEBR)t3J3%`B}a?}|ABeR06;<&DQa{ZAa zk@pv*zqTaxTna}_R;e?4`=mY6DFq7*7eT599mQABJwJA^j1xxAM4-`=Aa`QmyZ=^k zVWwP&68HR=lGZhsUydR52w&;18EDp}z=1c-pBR}@<7RUmxj}Rmh&gYrADdF5mm4rX zAfy$I+<}g-k^0*U60fC@6+s4u6>9FdCn*AP1YZfOxjQn%Q6evyqEL@m5==@8L<>K3 zT(Ny z2l&oXqodp?6YOak4w)%A$82xGw5=dRZ|6ApiOnQmau;9YgIS_|kN11YOr{#CV$O}x zi;*0qh?gL1B`_Wxz#dj=AL24r*%OK%9p$#0@k>Nfk;nNA0gT0%!BqX4h%U^K(mo~l z^EOx)eV39lQ&O&)F~GNy2P72>Rz$LlSh%TX5Dt(V2gnVxljwbyMooicY)03!Xfd*^ zu25|gAm3AA#~CJ7r^p@AH&%*(%?Q^AN$@x)=pI5SWFu_bH|$}x!)f8>{6rBfa`UCk z)&Jpb=p}qjSmNgbV_S@$kUj{)5yAb0`KSQM$Iq=<|XbyghptVD)!1w$7ZOK7%ON5Yb4 zc(?#-$NC4f$vp+`hG{@_G#F$s_(*k;z+V_vjkx;--<$-LdCVQ&2G)q6()&Xqb6D+AHbw=BPyF^KT~IVHPm2QlajJ>ksRZj z*??v7!2AX?-f&6qA)Zy-f_2oJ*lar(`-h4ANRTUFXIh!V!=RsJhlwT2+z;Zw6}6nT zopd|u9c%j#iKCBe5{C*-{Tl=nzX!(fuR5uelrby~(78#W>1_byqEslTBjJV*pt(s; zs4FxpLWJmx!&exlOiadD3)P8r0?z)FaR}irNObovo%X;xK7bSY>g7XBnjwbcV+uv0 zdt*7E_YR~u0x~+#GwW_mI~Pe()1bqAa3RAeQGKlA@S>CZPb?<6FMi zxy)!mZ6}|xH2&~^kfONxW`N-GO!gxs{$wZf!J+%RT-uS)%&MBQl?7*GFU+IrG|$dFBIxt$DabY3&ev~xFxj54rU`>B zfugBY+dEAy2tgwUG9K31J3mEOPd2sL+2VzD{jR|yV=l^00RcK|#&K9ogHYd)3)Nr2 zfLIB%KJaL_k=ns2|iGN~be)O$<0%Wnijog_zd~joX)pGImGxtm~A9o4|v%+@J zCFRm85qw0Mq8OHNzuve?+!E!NOUA&4U!A zrOEU^=!c#7O6N2v>sbCT0Ifh$zZG0rfH0p)ax{dY+BkkY7KARN>0fGxU)TObb@QwE zm{Ih8cM)2*z*nHli!}4#46MV2rVBOcIC}eK7$pQq)GwKMtyW(QaKK$l;3BF32IVv} zDU@brW=5y1Y!}E)3G+YEFLTIFVEevtE&aV)6n&!8GZN#uZbLcTRHW}TB@1>(8rR=R zuFt=p(pD)~;VOc`XimhgF+iV|U+y}!cX1N5eM}K<{Rl;?UcY&YJL`x8BgvnCIh0RS z62Vb>NA1R&B~;;z!2x#4@GM6GD@*?XP}^{v;A;}hI%cBq;G%4{%(n~+*>)l-gRkNZ zfOa9Bmzy zo0Y7_cCXNY%@gY>*!f~|i{CPpA0%m12Y7)`$vfl&4G=n$04@#2G6W8+h zQAx2eZs61}Kh(LsA*XZ9vOFsoSu}B9-TwenJ*-uPRzJL49FeYMN*^d|z%9fG+bwUD9wF!c zK|ahHhG`ippXI@(fEWg9OTIax5Q{hA!)DUw=^)pICVL6{{X&58oGzpzmUVW4Nar} z0Ik3O!~iT10RRF50s#a81OfvA0RaF20RRypF+ovbae+^gR*zaae0lD;3p02t=e;fDa67x~lk z1OkL~pY_AY7NoW+;>KS?h~~F~+cJUd$`lk)3KZL*l(P16PGIg;6;aYOh2TA-?=t!k z$O`p}9I*Lt`pZG#fy)@J2L*+SyO$Fgm*}FPfdpzBZuJ-#84x_I z8p0)JhdM(TyPb9BQ3afz!7Ej7Iqk$vcgDv0%>6K1ANsbf#dwQaE>}L20Uf>n0LB|} zx`LC8K9SwKq(QWlOeeHeO<4QH9!%IHRCgQ42@?ND7+O zW;H2&9f78&AYi3xHla7K5w(ffU1-VxPAMg}8bW=L}++Rq9zGK!o z#hpVCq%kP1d6^Ibd5kWnrZY?Zm}7)z-aqv*2xiUtoXchmBadr~NaepuBpe zu?H$sj(J_NhcJQ<&|;w=#uafYS!kD-xq9B_RwCuY9o48UBo!F|PMLD6bm}x4(fb*O ziHgDYd4UjRRDDOIW+>0O1|b(qC#nAcNPa+CtpxDhM&C#lBgt&ADF7T1WnbtJMM~~5 zj9jY5A)KeC3iU5D4U-RWmvZh>+zl|qq{ZS|e!2rdM}`4z{W^he=*aeAVHPU~*_7E} z6frmh2+;L8fG!2Mq3VCpSD3VN`b2kILvPkQw(Ei}BEY}Y0$1pfB1DOB9K=9%043B( zf(lar_R}m?E2Eeuka$SL*i z8+bC*eZS~L0bUEQSnyGJ;PDcufq18?av_iAfA(0gajEYcDtL7J%)$i1+&5-5B|Emdu| zD4p_TmgyE`9*oA>E>Jyrf!lK_Pq+KvL;%XXLD!-F5t&W3T(H3fbJVcp!z{x+ zeJSb_V*$`Z-z$vaNUP!uL-eoJB1D)A6Lt-`Jd(U;B}14kBJXM?+Jdg`6!JmfeaxH$ zJg?>eoFU2RibX9}<^gp(A(pK;C3)OlV+hhwd6dfQWc8Y-?z(wCV#eJ7H7v_4R8K}@ zaMy`EJi{bAfBv8D!zU@`UKO=Q{ZjNPk#QUtmOmt=iBc`Ja~22{l=Sl(MbqX17O{C) zKs=I$CulQYrN{MVBNR2E*F;2zoG-F7b_J8_hf4q#B{Zyaf~`eB32Jds0~!ZDo+1=g zcJnesnv?{rJrH?^1sG#c5Nc6^D5DUha}`#^4;G)6WvINyo{m z6**e=cmCn|X~5<6j~UQ3CS$v6h_(6`>9P`*WcrArm+u$ASC}fuKpRGL6$4$6Qi;hg zAM-&j7)wjIms*wLGhDOOOLSPdb5Vz)ueQ3G=6Trv0D6OWx!cSD#0@d1>zLsnb~6G~ z#^>b5V{;ouS+&qIu81C9+TAhi1K#DHqPr#dc(}gu`J9QwM`q_AnDNPU{_(i3GhqAb zYg!c_W;-uLH`nrl0)%oWKkYPTXrA5AM{K$x+MUX4@7z@unLWdtC}6$LPIItfmyv|B!TW%CZ9(mdwDXoFA&%#o$k z@=q-D!_?b=+Vnyq5`ydfmB+4zhPCO~B^Tu;QE+ybn#QSnTuLF9Ej0vLVqWgG=>jRt zVAWOc6IdAHm`zs0q%k8BZeez4`G2W|D>%yd`=WiANL$?`iPoJw^vk zrWYj8OGqi}h3D=k$vjM%9;D1(V-o|ZLKFJe)eE$F+)mW6;xmEyn#J(%^30jSF9RPI3=wC1d1wgpV28p2U zQkeT3i^rFr>O`VnnS@F0y-G{6>1Cf)#-9uY-Hng4uec2$_e_Gi5BGqAlab6ELe130 zIo7zAty^XO!mo>0k6bsx<pHU9uFr~r>wpfCCm#A{PQDw}v6zL7x*yt#qI z4Fq89Sj(2bq#z%p=M-v`)F2{|5!l9s>9PH_42QfS{{R*-WyTp+mAwN007cB9#HI`w zthS?$wAWAr^90i_cPy&$5CEJkf4kxu%X609ukFM4pskhnO6TtPxzls=;n&ULIxQOQ8<@Of}z5{nbl`H)Vg+5sQ=L*dU__?EJv3;lFSr!}xJ`dhl#`4wnRxx&c z1LlZ@`mgH%Qn>#B&_n`ezvHD^IFe+TO08=hi_kT--2-yDs#fug!SjElE9}w4-()apl z0T|#$Rs+`K0IfF6rY4b4t3j4t7^=Mg08ZfM91eWFzGfhC4$M2l^cl&xbm(p*cNve4 zX&n@}C}4p&>R5|itU=St)Bw|Ed0~zmF2i@CKKpGyH3npT{@60l!po=M?GWX!fUm(e zt#d~unK14KU(VB|_8ihjG>SBuNX*yy0zoN!0ShF#Uatqk>!sM5N{U!!j0e08&Mp1YX__=%? z(T}zyVqd?VZS|KS4o*5r`CtV=_s(A2XNK#L}=E@buFPa^X1e zoIm3NAO=<91g#w&lCUD$S!D&yrC;+4V6N1ka`y|-OYk`#>dmkY`->pI$w zap(zAVLVI!09Y6>e@kQ!PX7QQ_<%fE*d3p<1mJ9WJ0Cyd8sOSB6L!2g^}uTcS;{7+ zBW&{khdw%ZhZ9XFR{_+|3vswPlXn{Rq)x=W9XBw?H9J`qt+(DNV4Z{bEL|xf0#A3!QUgDjfq%ztHW)eVsW!44q zPCCF`+co5&m|1*dk5b>IFK~=#Ch0}C6FCrwT4~~Dzd8uwuts5_$8*q~M0Q{~Y8L=k zX0h8GFfPQ~zfPqD-rvp$SXG#32;=Tqqf{cL6;aJLJcIz0YUH~V*xb6ZtbupUHH_SH zSciNCta)8xk2s>S1Z6W#FWMjqIs*H~2GTVxC=1LKxPUKC*cH=7g^z@_wsx={54yQT z&)awh7{_bbZ zLSmy>h5$ov5ib26(E|D%#zm(RT1+K0Ym*a%mDwLI(@%(q?0}1V zyh{bc0nA2CxJ?oDR4Gb_9WoS0bv5p9nMR~YsRUX-59~}exqCApR zd27+KtBrY%&}<&2etOwgEgf6LN5!Z(^7MMe_kdi8GgENexHrb*MhLWMJAEKpT)m(r zuMQFcR%%pluKxgecI;#*eXLAgR@@W2X0=oRr@Nx%;EPLgzuqRQ1``h-QKNq1j~J?8 zXuzV-EIm_Ci=51B*YU({HZxGYYKnR4TRep#VHm7qqlN0@<{ejwUM4hOEO-&; zsd|Pr{sOZ=tKf~JmX3%h<&;~9v0$wfGipq> zK)n&xX!69u?%)8>xrU>-#o%Y5k5vGQ&C(Ih-9ui5eBv8|ZhSl+8=NA83*u4(Ta;{5 zEHmIC_4*M8in8CI)ndjhWBM!>Cg`@u5uEM<%S5I#QsZ^vKM8!Y!JH8XV(_ODpo%R~ zxSyQ1mS`pJwe=8yAZp{RXGZoCCnI|7gcTem{v0@kQTEIn#v_iuL{$xYK!FQvRjQKh+7us^;{6u-NS>HguzF; z;ss0vDlq9B6oY!WE++v$xAvDu^bTF(C6qJ)YjJ0rht!1}>>_)dV;gHg2j-ceRl!~CYtt)=eYGYlGEFaB^tKweDbQUk%LJL&$PRGF( zBh)OdZVIQ=GSw*XE`C|}f51@MMttMhuKDe4)Qq%z!MdO+YM4Fq9q!ATY)5^M<2 z*%d+HKO|=%;sR+oRRTkyx-$s|x_>Y#x#o}FH!AY3AZoWDq6`%~Xp|HOdM6nD7{8+* z(5gI29HO=a(m4G$B^_=h#0aM)Yf^bc83n`L$wgD#tT2V%MQ$bZ%14TAzaOm0Kyj)^IDsf{<4H--` zIQoSmvO}_3)65F}0yY5?Y$Jxo@hE=bv|hsWnb$FwY}!y{ZjQbtSSDo^GAu9$=DC#_ z0PqEob)}h0g(eZ%9g$1nD?ZBv$Et#WWtO&#J?09Z8j3*y0MIkm;GUFNU6Ue>dO^cb zupDIr_ahmVWq3=oL5#i5QSvY~hfGXEFqy}QI!DpwBrveL`F-Ky2oZ0ms{a50p*cSU zbWX;hhL~{cN<=jbz{xdAsKos&(mewKXRjs87*qp~lsBn0d_f!*?(%>@ z1EOE*{)}T6=yaH@R{sD%75Wss#t2qUBI&4Ee^YsXMZhDZ&m!>-72C?h$lz#*?DQN( z9D^#s{oiTvHq{!Ij{?w=lx<;VF6H#xQrPn=APfmxZ^j~YRj8#_>;MCKrp{w&h#(X& ztIKtFw|ruUV6IR?t608s8(oZxgRsj;bs5k&Chm$gOP1Q)CHhKKb_%mkyJ;JN!tJma z3@-DIF$Ay`jXp{$E;;?-FMI}AQG$s_#(9`{*m9s2_O+H<86jpa&J0rNn%EX9$T&<# zE@3TrUTgSfQ#`@EJU9tVhC6C;KTzf#*|a@ZTrA;es#Tm;><(!@LIcn3Cb z1=y+6060>v#o8f*il*jS?OqYsx)TIaYPDIa78cQ+->gPSpn}+j6gqD2sM5hk$*ykD z@IBbp-i&=kydd<%rTS)9aUiclZ7b);nBarjgtD}^K6sCuOrh2DiC~AcC4HO#_#=({ zz&_)0vBDnjiDb|tNV|Dr@Kwv9g1mb?mpkziIvX!V$u*d+YULoB)zEu=%=+9{P@8RB z4~l{a0k(N;e(-ASprq+P{iwc7;Sx1TRK+RlraH?|!E7f`LIMP-U!_Ww`qZgVKT{v0 z`Z0`H#V#+>+Ac9N{T>li!gUhvQFEvTvA!WP(cBsdu}fi~o-iiStRqC($12*!c^?dH z@@^Xnw;;Mdb`C!qfTQd)HliE@j^ZeGObx@lTmyCC7^roPgQr{HIjLXRrg0NsUHrux z8YYWuaY?0Q&k2z_+dw^oP@uaask^@x_CjAE3mV>fr}p=_Cde%Ts&{G; zR$ObGB4n|U*9gRYi#oX3#laJf{{U~|9!+&H7ThQ><^tsSW=Uo*!1~P*nr#l3UeWyk zY{$dE>dj_18VWU0RJx|hu2HKbtLYqX5#GsCD}`IX%qb$KGz&t7w=Sj50IeJ}9Fo%Q zuOY|1%5CXO2nB zaNWc(AWD@g62D4^{6qAw)}tTL#T^k?%oJMilvI4on82H@N;!1JD0SHvmr0T85d<6% zc!0nVk*Fnb&X+`@HnOd(BwWQ+5#ZmXK!H^h`h0nSI_Q(&azJH8PKXUa@O8E{M&l>B z$%nXY6r(2x{%hHbx;2ia6LuQ*g{3CMOYrj-To6+&vny0we*V zn8JmUua=HT=neQnAP&jon+QTwsZk-RQl)>un*BJ8a~S@GFqmpNMWWd$qqweALztjm z;goo8FD=mvPC0ED0k01?`1WQPhr3GNSdo z-mP$rNIJYTe@p{%7K2uGaJrMxrHGB=_LzMPA;fUFD*J(b!&^g-9eIc>PFLg))Gpqy zC-6Su8>@6BIqevsGAfAz9W4P%D+FaxlSR{<`$~dS)-Bo+R=vjlnU#rjqcdDR#VAN zku!(}%^iit0J>K#VsK8lhIgabgLGOsKF(cuYCZ5Vy0;vKU)SDBhBS?K)4Xh0fG)%0PPb2zB8 z2exb8C>uRnbr0>-OFJkO9lp`naMmX$<{}LjjCM9SOPkVgD@l;50~)J_gn+o4X{WY0 zm1PTWnl<98Jb5pBbf7@>aWI_d7D^3+4w}!IeV=5`vL#{NR;3gWaN$ctP?l2Cdci;# zK$D7TorCaPqE1S^4R{vyRZ6AYI}sfGc(R(YcV zo{va+va3C^eTU2b1DjTsy+5?O)2HXj;e^n_Y<5Cb#sD#k8}SebR8E!qNnRbl+MGua zoxm7>O}7nBU`z$;GNnp^{{RM5V;QVeqn2XLe@KvVA2EzKwV;54-(ZA*&*Ee@4&}c? zObzL^<%0~Dh2~bobpHUC$BtkY#FbotH0@)gL0b|x28CDk{K0ml?okQl@qITbl|%P! zH%*Ru?g~Ytp=<+mZ;~H7Lrp{+lxd+i#Gpb|@)m=1Y2sPx1T|X&S{@jvico~Yj*3!a z7ZMC}Q@+|Ux1M7*4cH%%uobx3_zXhJ$SwQl?mr3=$d2%PCz_6U)hS@F2KNj`dl*NoQ$;!$Tsqhk$x+fPaNSI7BqL__+@@t?rS@@ z)OQh_qLd2ClfFi(1HLfg`(RBzrVEzwLV zyv3^v;^0t%P_2xsK@};$y>Q2oLu6mBw0eKQ210m8;QT~l^^(0q$qH560}%j09!Nwc zNK<)5(6I3yppvrhKF@hyFMN+_Uof_UU3aNil?oEE8aB$6`ah*cBy|{_NAxV_NVxqM zS~!|xnc*~BbP=p8G(nIVjfSA+TeKPo8Xf%+H`ek@RFt6M<0PxBeZ?!pT@w&tfz7c4 zOn@zSLSY6`xlka$0|g1iVxfem09DRSd56-*j%W@y)L<4DO)`)!7c-UX6=DhGAPnZ) zu7IagBwr%=Mf-(S?w!NMan#p|c+Zc^6rYEerq8!iTpt7K?l84aXFlD)2Ac@q=2%cC zBA1h&h?Qns4lU#O_lvIEp`w7`o|=lCKpb}aoIA#d2EpX6Wj*4Jiai*!-13$-s;tjl zZ!(WVapjg6&hL=oCt#}?mr*%Obl(!JI{*x(O}$dkN+W@Do1R`>H9vQhOyH5C%nrExtfyGOP-hVfKeMBNw9*LlI~W8 zqy)hh{X&jdDOwEM7E}!fF!F&jr7X!bt>y}%VT3TiDS02h!BXDC?g89 zWWH}Oro<+#oalFODr&aYk1%g!%5?@cuP{YsR!)c()eEAax zgcs;TDJkAoVnSlD(-tig%2X6m$BA?)A{I-rTr=ZSH>7N7$lDB_fuLfZ!>FFA8$OxyO0u;!e zfWh!QC^?{^sZa$G8WHaW!bS_s8wB2KgSl&ULg9L=ua9_r2B5SGIo0RlS`=DHuFH9< zYt{>^vb_%vocqM6EytJpUlArK^K$9-9K)M#GW(}n+J$Q&J>6Z2h zRdl?;o8Tq5b4L}s<|Q@`H5iR4znX=1DB6v*bZwW!HdC5bsC)j@0qwT<4gUZh@Y1my znw7?g6|2}%QFn~)8#1$lU$IjLSW{G$jW?KAh9Ff_^8|!-@E0(4a!;uPnD*;)H&L$QSv;KE?p2Q#y2k#Y20#WoBS{V7F^)q{yrjM zu2m5`a?xD%kMJCj6orWZ+ht#miT?o9@B|5Cr(p!QXX!%|0hr~D#zGYkqw!wdN<+%o z_U==N4&dqk04m4n>-q)w7@?0*^#YD1*e+nBULh9gC6(r12AaRQx|FXZm)xVg{Xi&k z2mtw5s6b_7Wn#G$bH&K2!~ZW)fL=2)EULUT?a2r+|c{6r@hK>96; z6&yeE*Ww=LqS}WGtl19N^es>aLv05NZYI;vU&+Cs_LOw3njIim6`;L07-24}@_5Mm z$2n;|xb|%Li2*=7rXP%ZMm5LecK9kgNFZqHhni*0%y^z_h(KcT9a3hWsf7eu+;f@< ze@>L)9@hQ9v>TRJ)mX36q$%wbMOhtb1Qp;b?k)p(04Yp(gfmZh;}8w;}I2wCN$ zm?Jy%f_WQ^nqQf1+#mt1k0x*P6G_1+IZIR0Un*j$`n6ZQQJJq!Fv<|og%>q=M(&S@ zPfFYX&eqOJ_`Jff4i5JGzuS1W5y>M7$CDJ3Hk_# zhKmyogwc^D89n?x)G zHT$BaR#kX~MQd+T{{U9GPGugR`;W{UScwzkxk0N!hoYWIz;eWvH80b*%v9+tVURJu zX2>$r&jvDA4VvN%lHFshV2ahCD$VO6!1GLYLDt|JPYGW!0Vq%kgXSe@EhXMnL~j?| z5DYLQR5oD{k9j%R!sx7Dx@9m{5y}N-v45Fj3U1v!zTIq;oK)e?A8_(Y45~M`UQ5gvgwbDiB=KgLXx)7L#KMC@aBx5_)rs7i*2*udfaR?f!4g> z3S3?0SOb=|2{Vo0gsQ22V{D_6TBvrgEnP+mvsI;9K>clD@g4cR*uiZ4P4%P4M;b;sR4`CgW^AB33XT zAko%py&%;GC^uIAVAm&F;1>l@t(_69Wc-2q30}`~;u?p7oy{(ke_=kzEMp$KpJzWX z0R&4EpYW-I6OHe4=)==L8-T!kt$c9|(bJ>pE>**5Sqf83b!>z%g5+ahy|2juowSVe z!sQJA0L6s7SEDJ&mfi~jfI97BD=xW2oGx-xI91R?1Gkrg5cjmktsj&oLH9DH1_Dy8 zdYE!ds$W;Z+aB3Mnz#YM5>%?ztMVqp+dk6HOCDGF7t#VZ5VFK~ei=(r2qwfwB*&|W zh=E0!F7)ss_&}vfE0FtI5t|XT#1~mW`h!vfr9gOvQ@isM>Hq?goY>{*vQU9Res;x1 zVOWE)1f*X``n4JR-cPxB0ORr)B_hA{zxsuiN2LC8!N=h z1S#RTy8YqYWQe;sHw79O7l?+#WI#r9nnv(?KO`?nLStRda{WM=CiYHLy?{5euT6R4 zJfWbX^K=KEVZeH=`#vTG81lG<23d;tpkU8BmVjXnv!n$>Z8C$J_KkyWU13*k>AF4R zRw}ECJ2Tn%gUM(@b`7;H`g6eI3U=>v>KRv|{-~buN)FvKA(U(P3sGtJa zFh94%#!=;4)_((^Miy=qTb>V%e1C|X^3#?Wv27at?mxJLtQiZ*=`jOIwX$5?OcFBW zDe55-U5e!4m4227vQ> z^xqk@ABQ9?~$iuX=`fX=*sL(+t7z1!Az(=g`gx1-x%6C-vo zd{tV?mIPaC1J#HkWyyyrSwFo_>S*@K?C0OaFX%198!iVB8DUy$#g*#~IGo0LY_{9r zjsltOTY>df83!TX<}^}-!}ma}168~n*`1Bq)W$LoH(_TPrG!;n0m95)O_Ud?he1FE zT+rU@jK!$hhh)X!vB>sDt&89eJso?%Sqe2Nr2g&=)6K~L0Ek5Xhhyz7Gi7(_Jb!Z- zxRh%B9%DbyIh7=zq6}yjd5d87h@ufHABz6~$y_(}DduFS3>4f6xns;>x=6F;vJ+VHg@rJdMM}sHI}tLs>RJy0l%wuO5~63WZeHr;;KhB7~GvT$#qR zDd=ajvB{2$`4a=9to|T2V9i7ZI3Dkge~f6A{}R9)nJ@d>7)s-=GCd_oD;dTo03f{qs=-*+iQ9TiZs_K-f; z2_9HDm_yeZ9C-oPd<$IT)*}P=T7uMhk7J zXcSfMdl4XRlddXK85&5|-SO=O0%q%O>ri`?tQx}4cxsnRW+Rt4M>~cfj4l(0{{T3c zDApC}+gGo0QicwOp)6;*(Dfh0s6%Q1?M9ux?{KZG9=?-3bDofDR-G<-{{Y<2sLoEy zockS^M#PlmZNaXL147)!;OvRQ4T_VX|2`jyR@b`ihF4*`@ zOOH?z;14mzV`GA7m1~FHO$^_uXjaQ)E|)COWzkwZ5G;qOmgQ*p0ZV-R1R+NcKCwZ7 zZ^WYpJivegv0dg~1y}{r9y~&A-LW|Kg-yC-CcKS8uU;PoJsS2*hDZiGEqyhLsPm$j zO&kPmZs_VMC^fb_>^gXTWyT7+I-I|J0IqNhY~S3TlmZS@Od+)MJD!$E#- zknEh)v|y)So>cf!T8hVfs!vDirWj1Wyi6#>z1oEud5uFG?6R^ItUIkh+T0ICxb4cc z_?SH#B(~HPYmR3SdZM(al?A>$!x(%)hE>wt9BPhD9yD-MHNoJh-`@n7i zd2`e>46<aKuu2!qHR*X`yD2my^)sae5zVDXk_j%9Ibd1ca*rN-73g5FSF+3m{t zUT=)NSy?2u&GvIJv&>ebGG{n?xYB!eO^C?8yiF^BW9JaEBb|U(-+u6`vZ~=60Ns^o zA4Y|P$#+j?W0i32Z1OyO{$p8XM0TdNL+L19HA^(N3jFQ~l?_W^<^sNtD94Sp?=4YK z0;__~q7z{jP*+B81Y)MMHf#kfH{4u-QC}qcKGNm@08lTHr=i?HMLZzzKlb(b(1cn1Zx11fk!##qLxd%SBl^S0)ZF z13o&a>gZ2LLmBx%p&%h+SncW{N=y1c02Rv~HEbz6E-Gb2stEp`J|X08+sFRTu>Sxd z5QtJH8D{S&{Cs{qPyT|1BK=kJY=T<#I+utB3W+T69_FxSE!rMPqXKy%SQFB35#|vr zhlo`s`XC=Tj_K#h1sgFi3YTL}2P~m7i?vX`?l=~yEl&-J8YM#q3(FOnsabzY^~6v}|dv z6@BhfxrT)WE#xp>sQA!qaaEnqJzAIrbga1=BR+6jw-xO%DNdozUDgtt&8Wchd;aqE z>u)2-di{rTjufC*VSEF8p0LnRAR__iF`;USvCwxYr42YGgyn112RbX;X%W6dIQfFG zuoH2F)^*|YEPI=8bhIxGC&z?Hu0?Si3i{ygFirCqnD8ce$>Lq9K=j6P6b~m1GAeeM zjRJ>jY(OlMr*?^+F&NXy+XwRrK=@$1!K5jkDkpL%Pe&% z#r@=r3??58Y2XPDmFFAWQDvES?kGU0VTTa-FhO}6E;AKrw$408CrU%8ER+t$HxTsi zXY}NQ?a804HoF8~*_0U^|q_>i+x0BeXkQLobG?LeQQg%tS;>#9v}();$?X zf$=CBl|yPPK(3;mc8sxtt%?V4L=4v~qMzb)MV=a%*`I+CxG*8s5Xmh770=did zFSSAHbx^Gw8KrlNj!!vyxO1nX4|hzekU=4Kcr5yh(X#B9lP#a;?u3O#-cAc~rg#jzhB67%EGKlHv<|uZnCmlaOnOkQ4u!*PP`Ioy+fe#C6 z#_@S=*w>Oh zh6CArdP1Vbz`;z+?gv*ejvjtv3Pnc1;9g_te{!0pMX@cRru@ZXKFkXMr2R*{;qY zmJOYstq};3F@g+6c!OB*WnudaGI5uFc)zqqAd{iDqpt}SZH7D>*%izw#vev6W~ZbQ zI1Rx{7WIO80X8m7ZWsjTaZmvr5bAA9wczsHRI153;yuOp6GY7+vNwBcLW4Iz05;n} zhoR!kMGRW(1`omk>h2?(mrmHhde5}XL-G>93}c2U^-UDhDpOrlU(!*8mxbAF#-WUb z)g@tK35dYp8^P)dxqPfqMFkZWwOJ4tM!k_GN_O* zA_uIgrb{I^VIxEPaZ$ShtESg(V6c{~gctHJ;voto0JlaZaII@b7XGIP@l7sRtG^xi zjOPPsK#iF$-kFFle(Dx_wC|r=lsHqngM9+Ju~29njx>=_0NC1Hju6MRR`;lJb(icS z&=t9LnEW;E2N0VD6+Igc8RQSISf5fECG4 zPw(b1SgmGJ27`<+FG;0Y+!W&qgmxxz2Fb@vQE6sdRaf(Cifex8M}RX#Go*}Z&BQTw zl=3!rD8V7CnR70Z#a8ZMZrIjI?9Z|*Yu~HJnj1vc7^@>O3CPZ~mR42QQ8;>nT{*g8 zHi6(gfTN1RhHHX?2%slQ3i+>C5MqcXW~g;*pXk_BU8bt;~Y!z1I<#J?XMzg<62QiI4N@h%uN87H76Kyhqr`C<2}Ax!gH;~pX1 z&wS#>fsQpT7z$zXRhC8u5k~BR5yF?dva&aRxPw={vQd|-ZK*&S7l?(Ea4d}{uoi`l z_Xi7rTYLm#6-$e{G5n>~Rzc$J`WSPbktx}?;r?rqCJJHzHA;XYy7U&ZAG3+AulROi2-Tu|l9{bqjWv(&HE=k*IqBS`F(9Tbm{zA@@E z3caJuQ>{PpMNcYTp#w7du1F4q^&)@;wOV>bz%IFFjw%~%8H#VdBQq&l`y75>esKmUpBhtg%h?0jMemq5XePF1)oywm9 z6(r?R=vu#U7`X#?;LpqH1rA5G{Av(1-#tVG+D2Z_q{7xLLV7rclIt9N5VUFJiDHWP z#1f7CK|%nS6mguU8wV@TgK@&N%5vqH^@r6v{fEDBk*8~wU};1>kMvaNlo~($Ij2}{ zGJPs5XOIlzM)?;FsjK!g)OZ-7s zaVAH{l0BAk0Le?BwP$chi$hYc3!M#Q*K8lsTr>q^tZme6RDd((dBX<)dY^?6ts=Vq z2)j*9rLVgf0V|Lhj&U2ccGp81&l2hw670i)4|ly>HfU;)yLoHth&j8*QLd%47xNvZ zd$$Xq7+OhTEIcaW@w1;g8Wj$i^s_N38sa*j55>%?wo8RzK|sI3UnHCjJI@F)(gN2e*gG+qM zsQWmn;Vg#4PS=Q#L<=>s-hZZM4eL$$Yizv|=`7f;eCvpi7&c#VO}HLSzS(i*+@Pj~ zTSZ)Lh3+q`{9~jL?aE?28jd?6$PSY-d_!mpS{&uYvq&9{`oCz#u)+TTk^A;JcKaWn z^_B?mm6&};GKGrkk*oBW-bu7DT_b0#QGVk7)G!M~+$zc!%Sjidu)|c&@eu8c^%AFF zB2mfKCKiRK8u#yb8|AA@TUhbTR4e0eE5grg9fUblm!yewUN&G zapo(9Yzn;Z#4xf~Y*$}%?1Y+#uEnn>3CN@)p2P%{Y*NAFAq?&%syuV_^@j>uXz@n< z?pzitcEFQR6rv?k5a1%M$d57fbh`AhjMz1>9wj9M%Fl&`Y`7HesQZ}XeC3MK#!*+|HwxUg=!%}$N7{ZUM6Y8`4gIp1 zZ(p)UDElN#C|qu!K)$JSS7kWy1F_05yZ3K3EW3Sj#;*l%?=5 z0@ss`tJW7<(`P6!{+vMomnDOh?=7c|`;0fD831U|Te;QlD6A?h5rxQE$fZ#yf-}l7ZyI<}6fnw)_y`Fm+*> zN!}v9;_A8uDL7U7TpyRcL?eso{HB<{2*?(C++v=mQOE+-X#W6Q1RT4@Z<|f$mxBC#>nXy$lup3G(wDEYC zdo0jqlx%GDNPOmN-M8un_qBg*eMCoC7ytzY9wt)w8Tl$?0CA$$v2VO-;i*ms;bvhW zqRy326DhJLG9hh-@x@m1W`Wd6V?hcp3x5Wv;sGlGV_PaxuE6U!mRdCAg~)E4pKi!V z6bZPkc;Q}bzDW6v-j6Puhz`7}jN}}6_3kg8z<^a!-F-?C9J4QY8=_je8C@Q;0pMNd z5LI07DPmgoCAe1$xT{j|YFnG_Ttz`%i9>|*{E=FZ8HyTPX%DD+^a1%|Gy}?3@;n-i z3s02ECzd|a!EE=qW6sN&^kYE1pqENf0P}|b0N8cx^8&d2pK?)N{{Tjj0PlZDy2JBx z6GIHs7hPlBznGTJ&_0OV{=(Z()1%n>EAtf4>VW&)6Y|V*$I=;w0(LnV=<<|WE^>jg zyhDxZo&hE^2pqoORK`jxOYR@ebbvH{p|4h^m#^}~kf9O+ap zF+)t!&%`Fx#;)~fJ;iQ?_I9D?!Y2m?b~Fzro2nPWnQBl)DerBI?+q$p%P-CAc$Pp8 zRtZbG&H9O6UOI@!3eT|!QwszL*%4bx`Icrp24e36%B>%Y6u7 ziRUwM9t;qvlKE|wbbW*B5t>|n;|~URcj8>;dNmca^*0f)45O%Z9cKkur@2t`12K$f zj&+rW-i-SH0I7qe=ybyif|r`WcOh3x3SCaif4 zmF5qKsA*|#GuuR^DCSj0V0MF@hF#^02}dKn9;@yIgmAXiTxI~Yox-T!jL!h_{{V=^ z6g*KH1MOOaNc3V{E{GHuBm7d~1tZY-h~f|EH7V(Mphl4TBvXCnXod!lwZJu82jGcP z*Q9*0{pHR4M87#l)N?O>cPirZ1firAgfEiZrH!xQU$oG0v8FV##H_N0fVbNV&d8(;lNP%i4M_4oJnEZ0v$}RvbM*4#RKm<9x@yK`Lo5&DL1#sG<6}iK&(p zs8X8`6zA4FDZ9}0X#0hW2IaNN`C?SK>_9te4bH`Ek1^CD@{8QP3;N1euQss?RRctn z*{)P;K9O56c`8~dw#%h!V1xCTDFq3knC0%X7Z&s=m};B>m|w(Jh&LB}7crOS z$`|y+Q94vDZ9rX^uukJtW0c%1TzvFpzeLG{674eSq5{{XQR zy3Y`qlF$XPu0>tFdLRG+LC5Q%9-lz|226QCf=?3V+ZJqW_^nL2wS zEuDRyvZhE!!@4k4^|yu#%G_>_3`2#tnZt_P8PVl3LgUCY*A%N$w{1SUnpM8RYV)TG%g zP9jjA@DC`XhLZAU?=Sb4*+|RR{{Ui|E6_msk9b9Leh{`~npsz*L1=$vAKE6iv?~Zx z^8k#UZ{+9wr?a?PZWgtIH%|Q>%!R~P)R>ehzPQPxmuWufR#jZHHOJ$%LT1NaQa18UKcU-Eax92ui7|;%3l}% z0LiDZxdA$R#|2WKmSp41S%9fq>ED!o^1XBv_g}q#w#5+K988~FJ&}-+w>lwDFc*j> z;ouMS2AC-7ZT+6*Gam_tGeON{eWs^&R*w5M--uh4>trhC@G`_}bPwKEhszAIx8s-I zV;pxP&y38lFdXiPBC(|{e8U1>O_2Cgk()rGzd(#)=A%MjxZ~11+yas9m}{|)8n0wU zk%}n85{Yk#goMK{Z~YJbjy4HjnQ*TBABZJ;0xi%x*!JoJmtA!p^3J|a8Kvoc68zN9 zb!F*G{{U@Y<%Z$P`69V_+e1kJ@9J|QxgrB!qe!!_5zCARC!;K$lw3P+1^Wg$S6m+v z?|;OmSHVy50OWeoZDG=?7v6oOu+t9Z_Zkat5%mVb<*^aN6_Uq(ARo&i zXlWr6czxwnRbQ_E0BD19ssR_5dgErw|NMQDViIJmd_=p#} zl;}70FAIiIIr~!o0NXzBf;}%o`Sq1vCNkFtxTu$GOn#@AFdV%~f;lHhF?tuc{owNV zyFtC)mK8?p7t~wo3fyZWhAerO+;eK>my4Fy&1OBET+~R)Bc}Z)N%In`uSl!B!0TEC ztW;a@KL}?vGiFAA#Og_Wp^C^IRVnO6@zCUl0c?%zBycp}l$ zr^yP;M#peLRz|DzNQ#1`Dm7ABd5VW@4H`f87$!8gck6PtqqqoXP%SOltwwp&t*yUk zh@GOlQ#N@Wg?&miOTzl^>RLNx{{XhX5CI9xqwG-+j5rU&{{X~CF=*AFVWwGy8NxLh zu)B}w+`1hzd^fmCk6};A9PilG_Z0;L))GKpX++zwfrZlo9Chl$2nqv1{@mOf-EfZy z5Q`15>Cu{uW7JCW{0w66^f`6MW$`Ix_KGsK`Ae4Kh@PkO7G-B_E!n>rfT`K0Pnky6 z@g9Jvj;0X@sDBJ_{wCe0lpf_?7Qs7xr=W4;knK>;C}QX__c#enTF_0ngJ2 z@j~$~QLp3-9_(`PIwhVi*qD3`jy0Z1MB_C(~O`xNTQ27 z5$k^s%vV87BgoCOsY{gU%;KlYfjD}_82O<`51Dyq=44kv8n=OeBmBjJhF)tD?XA$S z%sW-viouSGOCqD_&8NgXp$Odw^i%gGCqiFu$^H%1p8GmaBbc6ognU!NW*RAcABR6s zqp^NLufzb(IsJl(P;W$kzoybx+&ua?fDzKvhhh^rL`~?jNmZ- zVPJaTAbj1-@xh7s&3z)C0*aA1NUW^k97U|p+GFJpMIXeaHX=YlU_Ryl0M@{y9&WF4 z&v{1?IdxyO0CQnJASFwFRzDEwp{sMsyq~6l1e7CQr2IrSpOD<5iV}|3?cn{TCf=rM zycf1VZ~EXoqXB~7MZJ<{Mws&xYbaN#kJ=@`d&jCiap@dCm@oh`qP~d!WojgAFPE4G zR1x~g18dS`xN0gPfkM_h!2&mHFWdhBTn+}2myhE<(u>(+Haz{z{_&xuhJkQfSv?tr z0Y2&ppgXH&@P0Pl#Jnr=mG#wLJyFw4I{{X44|Jj6XB|`uJ 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 0000000000000..367de5d437348 --- /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 0000000000000..d84b9fae9cda4 --- /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 0000000000000..12715712a0bb8 --- /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 0000000000000..c432b5184df15 --- /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 0000000000000..31f15356db715 --- /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 d725666b2ce6ce4eee84d503ab39b290dc7d33ab Mon Sep 17 00:00:00 2001 From: Jordan Yates Date: Tue, 14 May 2024 20:40:01 +1000 Subject: [PATCH 0486/2849] 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 472b611acea8e..47f90e9fcb4c5 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 62ea9bc0d1280..b167221256da5 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 9b618984d88b4..33a9b7f9b2729 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 f3804f3323fbd..9563bdd7b3aa6 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 8f1c7e03875ac..2638269224dcc 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 192cd3fd922e6..3e76dcd4f79d5 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 19027aa93615e..b89510c2b72b1 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 cf8a756e67b1d6b46509f6405dde725502529d71 Mon Sep 17 00:00:00 2001 From: Chris Friedt Date: Mon, 13 May 2024 13:36:56 -0400 Subject: [PATCH 0487/2849] 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 5ed512dd05e48..87d6297f7491d 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 b1810ef26991c..fc2b09cd8390e 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 ed501d788b406e93e38c65e72adde18261b1baf5 Mon Sep 17 00:00:00 2001 From: Chris Friedt Date: Sat, 11 May 2024 19:38:27 -0400 Subject: [PATCH 0488/2849] 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 ff8bde4e57162..baa2046f07c8e 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 7a538c88cd1f2d813221a867422cd6812ef60315 Mon Sep 17 00:00:00 2001 From: Fabio Baltieri Date: Wed, 20 Mar 2024 19:51:21 +0000 Subject: [PATCH 0489/2849] 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 7fca24a55ed42..fa27ca5bd6440 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 7d3dc4e7e377746ce752390082e634120b7edb8e Mon Sep 17 00:00:00 2001 From: Maciej Perkowski Date: Thu, 16 May 2024 12:57:07 +0200 Subject: [PATCH 0490/2849] 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 b8007849eb55b..16cec58be2f8f 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 ba1855632fb4c64d52ee8e98aab0495dc94cbfd9 Mon Sep 17 00:00:00 2001 From: Alberto Escolar Piedras Date: Thu, 16 May 2024 13:17:36 +0200 Subject: [PATCH 0491/2849] 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 a31e8b21d14bd..9249cb3622c0b 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 d651be5d70322e24b8940ae0c3a68a7d552cce38 Mon Sep 17 00:00:00 2001 From: Grzegorz Swiderski Date: Fri, 3 May 2024 10:07:30 +0200 Subject: [PATCH 0492/2849] 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 5ea59e9469713..f67ddfb80bf48 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 39971ad447ea794a9e8132e9a992eda5f31f48d1 Mon Sep 17 00:00:00 2001 From: Evgeniy Paltsev Date: Wed, 15 May 2024 22:02:30 +0100 Subject: [PATCH 0493/2849] 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 9d7ac1d7f4cfd..69b0b578afa08 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 f573c3eb01937c63465b64b3604e61e6bddf47b2 Mon Sep 17 00:00:00 2001 From: Emil Gydesen Date: Tue, 14 May 2024 13:31:25 +0200 Subject: [PATCH 0494/2849] 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 0cc7d9b3d79ac..4ffa953994032 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 849817b36acb2..607737479e2e5 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 8d48d5e1c2072..607737479e2e5 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 ef1a0b39b2248..3ddde520a861f 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 73528a326e076e7bb7b48df4e11b7c3a126069bd Mon Sep 17 00:00:00 2001 From: Emil Gydesen Date: Tue, 14 May 2024 13:35:16 +0200 Subject: [PATCH 0495/2849] 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 a2ab2f4e87a5f..80cbf6267972d 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 a2ab2f4e87a5f..80cbf6267972d 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 607737479e2e5..68e0a8a7e50f8 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 607737479e2e5..68e0a8a7e50f8 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 cb7ed8d97d5a9513f3f195d0239de3abbf4f39d9 Mon Sep 17 00:00:00 2001 From: Francois Ramu Date: Wed, 2 Aug 2023 16:57:22 +0200 Subject: [PATCH 0496/2849] 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 4fd5bd4a3e2fe..72481c5ae6ed9 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 846007676ae3db11072b07d7d8ca28555e83fa36 Mon Sep 17 00:00:00 2001 From: Armin Brauns Date: Thu, 2 May 2024 11:32:55 +0000 Subject: [PATCH 0497/2849] 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 8421d71f16ee7..adec32e8e4e6f 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 344dbe12b42dc4a5c28f662212eda250e2b222a2 Mon Sep 17 00:00:00 2001 From: Armin Brauns Date: Fri, 3 May 2024 14:08:06 +0000 Subject: [PATCH 0498/2849] 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 22b981b50225a..1d81dbf805a7e 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 83a1c9b28e15e35a9d31258d72fb712b7e7a8655 Mon Sep 17 00:00:00 2001 From: Armin Brauns Date: Fri, 3 May 2024 14:10:40 +0000 Subject: [PATCH 0499/2849] 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 1c964a0e64384..8896666bc6d22 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 0023986bb2615e5794a18ff8d6010041fabcd27c Mon Sep 17 00:00:00 2001 From: Armin Brauns Date: Fri, 3 May 2024 15:09:58 +0000 Subject: [PATCH 0500/2849] 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 1d81dbf805a7e..03ff90c729baa 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 ea80dbe86afc5..439bc560a7d5e 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 e7a53cf03bbd6d33ee572a33ab2d72b67715bdc5 Mon Sep 17 00:00:00 2001 From: Armin Brauns Date: Fri, 3 May 2024 15:11:58 +0000 Subject: [PATCH 0501/2849] 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 f8ac178a7e94d..2e0f49f520f83 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 0000000000000..eac2504a7850e --- /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 7ead7f6bae483..4bf540a721100 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 b9415221e2468..a583ea3b44f0f 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 8ef8e8b4974ea08688265c2fbeb6da146a3265ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20LOCHE=20-=20MAKEEN=20Energy?= Date: Tue, 30 Apr 2024 08:34:50 +0200 Subject: [PATCH 0502/2849] 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 3f5f3075777fc..bf68ec6faae69 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 6d5ba15ee6e82..88598cf5790eb 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 724be849572ae2c423eb1a7422bbf7de157339c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20LOCHE=20-=20MAKEEN=20Energy?= Date: Tue, 30 Apr 2024 08:39:43 +0200 Subject: [PATCH 0503/2849] 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 4a6d606c25374..ce34a247b80e0 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 9b7ed2aed5acc..b127c8eda4f5b 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 9a925ade2f6a6..73f11971d6c8f 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 2e9d5e71d9d9b..041da088770cc 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 7e95816baf20d7dbf07054d23eca6f31a404f426 Mon Sep 17 00:00:00 2001 From: Grzegorz Swiderski Date: Fri, 3 May 2024 09:20:27 +0200 Subject: [PATCH 0504/2849] 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 1a5611b5258e4..f2ccbdb3c412c 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 60308af7173a4..1d9486de8b3ee 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 0303d255c5472..8696279859db1 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 7ab8e395195367d1ca23ce5e29e79318d82e011c Mon Sep 17 00:00:00 2001 From: Alberto Escolar Piedras Date: Mon, 6 May 2024 13:06:06 +0200 Subject: [PATCH 0505/2849] 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 0063021c3e3c8..cd3b17f28affe 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 c9753f5cf6f2a7ba121f8528ed16fd97e4e1558b Mon Sep 17 00:00:00 2001 From: Alberto Escolar Piedras Date: Thu, 18 Apr 2024 15:21:05 +0200 Subject: [PATCH 0506/2849] 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 7463cceefa3c4..e46e458ccab84 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 042925f8e6821c1a21c6241e536d7ca497952368 Mon Sep 17 00:00:00 2001 From: Alberto Escolar Piedras Date: Tue, 14 May 2024 13:06:53 +0200 Subject: [PATCH 0507/2849] 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 4fd16a2f7d6f0..05d9717db8355 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 0b173b100c87d1c5d4bb03e7c14055f24cf81d50 Mon Sep 17 00:00:00 2001 From: Alberto Escolar Piedras Date: Mon, 6 May 2024 13:07:31 +0200 Subject: [PATCH 0508/2849] 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 6165f76a438dc..7fef9d1b5228b 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 caed5baf8b6a9..0273667c4152a 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 f0d1dde660b9a..81f90836b543b 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 0000000000000..d3ef1f5ffa2bf --- /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 874c661c380a1..ba14ed8aef6f6 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 d75a187aa6109..e0b1cb60a594a 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 0000000000000..8440d76384d0b --- /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 0000000000000..4a80be6b7ca80 --- /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 0000000000000..acdf8e2a467e8 --- /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 0000000000000..0fde4e01b5838 --- /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 d599e2b6705eb3f3cc26fc5c02f0636660da3e62 Mon Sep 17 00:00:00 2001 From: Alberto Escolar Piedras Date: Mon, 6 May 2024 11:48:52 +0200 Subject: [PATCH 0509/2849] 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 98faa4e231cc1..a5c41a63ab97c 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 13a553683822587401818032f58a75c27c5e2d96 Mon Sep 17 00:00:00 2001 From: Alberto Escolar Piedras Date: Tue, 7 May 2024 11:09:52 +0200 Subject: [PATCH 0510/2849] 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 acdf8e2a467e8..cbdd257334f44 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 0000000000000..b1942e1f84f8f --- /dev/null +++ b/tests/drivers/counter/counter_basic_api/boards/nrf54l15bsim_nrf54l15_cpuapp.overlay @@ -0,0 +1 @@ +#include "nrf54l15pdk_nrf54l15_cpuapp.overlay" From ced0676911b6755061b30d72a8b961c45db0eb36 Mon Sep 17 00:00:00 2001 From: Alberto Escolar Piedras Date: Tue, 14 May 2024 13:21:15 +0200 Subject: [PATCH 0511/2849] 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 a4329cd888007..d55a52e1a5311 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 0dda0d1cca9a7efced43333598c4181c39b4f9a8 Mon Sep 17 00:00:00 2001 From: Alberto Escolar Piedras Date: Tue, 14 May 2024 13:21:36 +0200 Subject: [PATCH 0512/2849] 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 4a80be6b7ca80..994af625bcbba 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 c542b06df117b27199efc2b0001f9cc63b76762f Mon Sep 17 00:00:00 2001 From: Alberto Escolar Piedras Date: Tue, 14 May 2024 12:35:16 +0200 Subject: [PATCH 0513/2849] 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 d2f98295dc76a..0bdc7d0fecc19 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 ccdd829aef55b5e76320075f123eb3004e0053a0 Mon Sep 17 00:00:00 2001 From: Alberto Escolar Piedras Date: Tue, 14 May 2024 12:36:54 +0200 Subject: [PATCH 0514/2849] 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 12c90c0298bb1..47aee8764a590 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 5919163b48a629efd0d86a36967aca265cb89d0b Mon Sep 17 00:00:00 2001 From: Mateusz Michalek Date: Fri, 10 May 2024 16:16:01 +0200 Subject: [PATCH 0515/2849] 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 37b7c7f322331..b03628afc93ec 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 dc59cb56ed7f92abac16f588bfe06b194ab9da13 Mon Sep 17 00:00:00 2001 From: Mateusz Michalek Date: Tue, 14 May 2024 13:55:57 +0200 Subject: [PATCH 0516/2849] 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 07430fc766e58..e66f6ac7e0f13 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 014e879e6fe9c9be11831d6cc884f74c3995dce2 Mon Sep 17 00:00:00 2001 From: Ryan McClelland Date: Mon, 22 Apr 2024 12:59:07 -0700 Subject: [PATCH 0517/2849] 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 efe65e6756e14..748d25e4b9ebd 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 da094d4d3cd0ff2aa9456f511db54f217f9fe6cb Mon Sep 17 00:00:00 2001 From: Ryan McClelland Date: Mon, 22 Apr 2024 13:06:05 -0700 Subject: [PATCH 0518/2849] 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 116750bcac59b..9846efce0a171 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 9640905a71f7c2e80f21469c770af203831aa5e4 Mon Sep 17 00:00:00 2001 From: Ryan McClelland Date: Fri, 19 Apr 2024 16:24:21 -0700 Subject: [PATCH 0519/2849] 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 748d25e4b9ebd..7b03b5b9f429f 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 b5411dcd9a309..7233143fc705d 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 9846efce0a171..767d922086c2d 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 e59d65536d8e4e3d0e61ed3354210c18786e9b95 Mon Sep 17 00:00:00 2001 From: Ryan McClelland Date: Wed, 24 Apr 2024 22:01:47 -0700 Subject: [PATCH 0520/2849] 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 93b30388da1a5..f58521bd483d9 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 328b03f56eeb18bb6b64c34822918ec05a0b6b11 Mon Sep 17 00:00:00 2001 From: Ryan McClelland Date: Mon, 22 Apr 2024 13:28:48 -0700 Subject: [PATCH 0521/2849] 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 d4f3269dff095..9bfc72f954803 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 bb66b7b8706e7b418220d61274fdd49cdb8d5609 Mon Sep 17 00:00:00 2001 From: Ryan McClelland Date: Mon, 22 Apr 2024 16:18:34 -0700 Subject: [PATCH 0522/2849] 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 9bfc72f954803..8cd2c2b57e58b 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 c75783219f4addd32a6ee699a9b03f98c0cd3ac4 Mon Sep 17 00:00:00 2001 From: Ryan McClelland Date: Mon, 22 Apr 2024 16:20:39 -0700 Subject: [PATCH 0523/2849] 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 ef361523e4e22..fab1df7f4abe4 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 4c4ff203837bd17ffbcd5e5dc8bd90818dda74b4 Mon Sep 17 00:00:00 2001 From: Johann Fischer Date: Fri, 3 May 2024 09:59:31 +0200 Subject: [PATCH 0524/2849] 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 b0be2cc6636d2..838550f18dd71 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 c98c388da6ec041f924ccf46bbf8597dfebff53e Mon Sep 17 00:00:00 2001 From: Jason Yu Date: Thu, 18 Apr 2024 12:14:06 +0900 Subject: [PATCH 0525/2849] 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 e928f64ab33bc..37e15451bc9f4 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 325994c937a371a5639b720747425a63e35af2b2 Mon Sep 17 00:00:00 2001 From: Evgeniy Paltsev Date: Thu, 16 May 2024 15:14:40 +0100 Subject: [PATCH 0526/2849] 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 2d464460eb59c..821497ff6c0d6 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 6b27f4893823bc039bec265e1062aa3a9a8c28ea Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Tue, 14 May 2024 13:06:39 -0700 Subject: [PATCH 0527/2849] 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 47aee8764a590..d4c2352b0755b 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 cec23830e4e1e0e16a4b989e0e5adc1e013528dc Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Tue, 14 May 2024 13:09:34 -0700 Subject: [PATCH 0528/2849] 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 468098fa0cc06..33ebd3f3d9b79 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 c63cef98fc13c7b3665e2d80045b1280c5d847e6 Mon Sep 17 00:00:00 2001 From: Declan Snyder Date: Thu, 1 Dec 2022 09:38:07 -0600 Subject: [PATCH 0529/2849] 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 22e34b4777ac1..b846950bc7b88 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 1192c9be6b06eb84e3df7575d9cca7efe9eed91b Mon Sep 17 00:00:00 2001 From: Mahesh Mahadevan Date: Tue, 14 May 2024 11:07:03 -0500 Subject: [PATCH 0530/2849] 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 38bb0df74b7bc..aa62fea1460a9 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 dcf52c8437785..536d79b67ec6a 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 a9a28b3ab6e8e..780bd9b66aad8 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 8d214448f18b68def963614d65c773e48492552f Mon Sep 17 00:00:00 2001 From: Mahesh Mahadevan Date: Mon, 13 May 2024 17:36:21 -0500 Subject: [PATCH 0531/2849] 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 6216d381d037a..3310e80660892 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 648bc402dc36d024ffb84507fc167848aaca016f Mon Sep 17 00:00:00 2001 From: Mahesh Mahadevan Date: Mon, 13 May 2024 15:31:22 -0500 Subject: [PATCH 0532/2849] 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 b846950bc7b88..ae4361e0d0dd4 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 8824fa8bdd477058cc49e1971327e93cb1d2a28d Mon Sep 17 00:00:00 2001 From: Mahesh Mahadevan Date: Mon, 13 May 2024 16:09:25 -0500 Subject: [PATCH 0533/2849] 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 d4c7cd7af4d33..ace3c53eda847 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 5951cf59ab257..a072151a05c60 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 0000000000000..69e9901f0d20b --- /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 161978d398f0af23960ec6b9dfe4ec9d00758cb8 Mon Sep 17 00:00:00 2001 From: Mahesh Mahadevan Date: Tue, 14 May 2024 14:55:26 -0500 Subject: [PATCH 0534/2849] 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 dae43dd8aea77..42783abb9bbd8 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 d44a414574fa296709d4ae3b48a8301274603bf2 Mon Sep 17 00:00:00 2001 From: Mahesh Mahadevan Date: Tue, 14 May 2024 15:09:34 -0500 Subject: [PATCH 0535/2849] 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 021a3416b9b5e..203e44fbef117 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 05c84ccb2d7a7cb39e49d769503ac22edffeb6f7 Mon Sep 17 00:00:00 2001 From: Daniel DeGrasse Date: Tue, 14 May 2024 11:05:58 -0500 Subject: [PATCH 0536/2849] 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 debf80f46551b..54f5b1a360f14 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 bda05fb51a74b2acc70476d6d688529f646b31b7 Mon Sep 17 00:00:00 2001 From: Sylvio Alves Date: Mon, 13 May 2024 13:11:24 +0200 Subject: [PATCH 0537/2849] 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 2efbbba1ce551..7760668b0bd21 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 43039afbdfe697351ce0ab0d4c033ab7035dbb3f Mon Sep 17 00:00:00 2001 From: Frederic Pillon Date: Tue, 14 May 2024 16:44:48 +0200 Subject: [PATCH 0538/2849] 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 b66edf23be48d..c19d0abe3da6e 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 97bd924f59cf39170328e2689891e4835555aff5 Mon Sep 17 00:00:00 2001 From: Ioannis Karachalios Date: Tue, 14 May 2024 16:57:49 +0300 Subject: [PATCH 0539/2849] 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 0b42f77f4f8fc..80f9ef1510c5d 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 7ddbe9d4bd34622d79ee0fb6e2b6f9c5f79e2ed1 Mon Sep 17 00:00:00 2001 From: Jordan Yates Date: Tue, 14 May 2024 20:53:02 +1000 Subject: [PATCH 0540/2849] 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 ef2b34c74b316..47569b005d58d 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 a1576af7af8400817b596547a262a3664e3eb55e Mon Sep 17 00:00:00 2001 From: Alberto Escolar Piedras Date: Tue, 7 May 2024 17:07:49 +0200 Subject: [PATCH 0541/2849] 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 58836c2ba9b98..ba9a76d4085a1 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 1de7574d3aeaa358e0717d4e7fff4896031d778e Mon Sep 17 00:00:00 2001 From: Daniel DeGrasse Date: Wed, 1 May 2024 19:34:42 +0000 Subject: [PATCH 0542/2849] 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 d072f25f9246c..175e75554f24a 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 af1b627065848a64e3aba6752aa0c363bab06b99 Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Tue, 30 Apr 2024 12:27:23 +0100 Subject: [PATCH 0543/2849] 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 05d9717db8355..6673d1f65f72c 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 c9f53d337408ed14142cb59c3d7ce9c3005c8a72 Mon Sep 17 00:00:00 2001 From: Jeppe Odgaard Date: Tue, 19 Mar 2024 13:44:04 +0100 Subject: [PATCH 0544/2849] 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 2a952bb2614ed..0c1ec766321d4 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 3636641cb7a97..5f264cc05c129 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 0000000000000..968d4cfe796bd --- /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 0000000000000..761eae1d96363 --- /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 0000000000000..5470394a49ff9 --- /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 0000000000000..d6ee88b8079b7 --- /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 93970fd70a79a..a6121e34194f6 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 332d3625954f3838decfca30ede7a453179d9832 Mon Sep 17 00:00:00 2001 From: Jeppe Odgaard Date: Fri, 22 Mar 2024 13:11:55 +0100 Subject: [PATCH 0545/2849] 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 aec784c26888e..ebfa224848a32 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 fe677345578bf..2fb7bedcac8d6 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 0000000000000..e1b1ec978a986 --- /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 68029a63099382bb894eacd49af3a965a78f77dc Mon Sep 17 00:00:00 2001 From: Andrzej Kaczmarek Date: Tue, 23 Apr 2024 14:44:11 +0200 Subject: [PATCH 0546/2849] 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 6673d1f65f72c..091f6ac35a47b 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 6306596b27e02919c6747635ee7f927aa529e501 Mon Sep 17 00:00:00 2001 From: Andrzej Kaczmarek Date: Mon, 16 Jan 2023 22:36:00 +0100 Subject: [PATCH 0547/2849] 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 adda6ea0e2ab0..ab1df047ce11d 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 ad1d9da2df2a6..1b4bc9fdb25d0 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 0000000000000..8935244472a95 --- /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 dd395e72f7c731bfcf5b0e94be15a62649562859 Mon Sep 17 00:00:00 2001 From: Andrzej Kaczmarek Date: Tue, 23 Apr 2024 17:57:05 +0200 Subject: [PATCH 0548/2849] 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 d487e093a080f..c20c21658d06f 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 84332680432852efaebf2ac00b07f158ed00b945 Mon Sep 17 00:00:00 2001 From: Luis Ubieda Date: Thu, 16 May 2024 11:42:18 -0400 Subject: [PATCH 0549/2849] 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 821497ff6c0d6..ed368a990e9b2 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 caf332e745f15b628cc37e116407fa6c004ece7c Mon Sep 17 00:00:00 2001 From: frei tycho Date: Thu, 16 May 2024 14:21:16 +0000 Subject: [PATCH 0550/2849] 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 b9ad0b70bbfa5..6089e453405d6 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 32c04c6b25200a4eea37f7807f153d989194d62d Mon Sep 17 00:00:00 2001 From: Abderrahmane Jarmouni Date: Thu, 16 May 2024 14:07:14 +0200 Subject: [PATCH 0551/2849] 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 6e8631d7d6d3b..b4110208b3fe9 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 82ca880fb9e17c0dcdeef259f6b99f29334d67e1 Mon Sep 17 00:00:00 2001 From: Jerzy Kasenberg Date: Wed, 17 Jan 2024 10:13:43 +0100 Subject: [PATCH 0552/2849] 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 60c98f8668a0f..1ba24850f2d98 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 c987b579c1032..b07c4274ad693 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 4e91d8e7c3392478843bdc91ec9e301bc443eb10 Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Tue, 14 May 2024 15:43:35 -0700 Subject: [PATCH 0553/2849] 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 fee5a18b44916..b590470ff70ea 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 f4aefc281bd5102086d88151b6c1b33f06bd99ad Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Tue, 14 May 2024 15:36:42 -0700 Subject: [PATCH 0554/2849] 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 9acca131a98d2..734ffbd67e4b7 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 ff3cb07806402..fd75adaa57ac0 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 8cd1ab8896551387d9bdd67deea2cba16410321f Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Tue, 14 May 2024 15:38:45 -0700 Subject: [PATCH 0555/2849] 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 734ffbd67e4b7..c2261af5de4e7 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 fd75adaa57ac0..cb55dffd5b8ca 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 696a1a0a13022d8308a3c3eb717fd92a1a5be49f Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Tue, 14 May 2024 15:52:50 -0700 Subject: [PATCH 0556/2849] 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 d4c2352b0755b..bada622428003 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 cb9d8bac5410c460e9d2bf4588f51d83fed1f3d7 Mon Sep 17 00:00:00 2001 From: Daniel DeGrasse Date: Tue, 14 May 2024 10:29:44 -0500 Subject: [PATCH 0557/2849] 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 7462e711dcd40..234fb99743a88 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 a2087bed16aee8e749014d2a076957431cb73e90 Mon Sep 17 00:00:00 2001 From: Daniel DeGrasse Date: Tue, 14 May 2024 11:34:03 -0500 Subject: [PATCH 0558/2849] 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 234fb99743a88..7e7e22b9f17ac 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 b24953509331590cd91c2c2923282bcb89127995 Mon Sep 17 00:00:00 2001 From: Tom Burdick Date: Sat, 6 Apr 2024 09:29:28 -0500 Subject: [PATCH 0559/2849] 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 f33e5cd9134f8..08ef4026ccf5b 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 9bd6b312b7a0e..9f13cc4b31d16 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 db541b8b4fb4b..5dce0d0d82716 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 9d8656d67aa80..db717cc0c04e0 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 efc4012e29c56..ec5f069da536e 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 38c74a98813d1..9fc33b48b6aa9 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 c21736f792aa2..dec4faacc3b73 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 7e906af5f04d7..fe1dbc5d3452f 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 758e658816a94..84d11f152c23a 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 3dc556ac61c7c..b71d06b7f3a6d 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 499cf3d080155..9eadcbcecad57 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 5bf60aa4fd12c..41b6b11ea5f24 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 ccb9532ee45a2..ad00fd7abf25a 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 9bbbd8d30525a..265505d5e5aca 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 f110a47989648..2bd6b5c5b892d 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 2d5e0c1df86a9..30d4d72f5676d 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 a97be2cb7840b..3f36744e3d1f8 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 adeb19b30cbfb3552cb2d19c6c6676a872afe6c0 Mon Sep 17 00:00:00 2001 From: Andrei Emeltchenko Date: Thu, 16 Nov 2023 13:57:55 +0200 Subject: [PATCH 0560/2849] 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 6b4035d976da6..3c6ab1e0a6dff 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 90b654ee86bcdddd95f98951b289a05351a27cc8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Chru=C5=9Bci=C5=84ski?= Date: Fri, 10 May 2024 08:08:46 +0200 Subject: [PATCH 0561/2849] 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 0000000000000..c102d617f900d --- /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 0000000000000..c6ff4eb77af37 --- /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 0000000000000..2bde29c9fc51e --- /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 7736e085f3429..8be2429492e91 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 f04f8b242285dcd56b9e458de8ea233a14237b9b Mon Sep 17 00:00:00 2001 From: Pete Skeggs Date: Wed, 24 Apr 2024 16:19:21 -0700 Subject: [PATCH 0562/2849] 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 819559e9d936f..3997a394f5809 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 33b66acf7dce9..f80c440a839ff 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 29f81872ce2751bf2a6f69dda1428e65a0366763 Mon Sep 17 00:00:00 2001 From: Chaitanya Tata Date: Thu, 9 May 2024 17:58:34 +0530 Subject: [PATCH 0563/2849] 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 0000000000000..d03419690bdf6 --- /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 a3f2b5f4b31540a2390388e9943bf8635736635f Mon Sep 17 00:00:00 2001 From: Marcin Niestroj Date: Fri, 3 May 2024 10:13:57 +0200 Subject: [PATCH 0564/2849] 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 1ba4584a4a6c7..bafb40542e040 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 86aaa743681db..104aa392fa826 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 0000000000000..dbc14997559c0 --- /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 c177342599549..24d686f536a1b 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 cd2c425efe49de54918cf7d1ea16ade2952a63c4 Mon Sep 17 00:00:00 2001 From: Marcin Niestroj Date: Mon, 6 May 2024 09:48:31 +0200 Subject: [PATCH 0565/2849] 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 104aa392fa826..d3f787762c468 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 dbc14997559c0..10db34cdcf11e 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 24d686f536a1b..5dd528e91013c 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 736fe29349fc9075cbdfbddfa3b3689ed9bbd407 Mon Sep 17 00:00:00 2001 From: Marcin Niestroj Date: Mon, 6 May 2024 08:36:38 +0200 Subject: [PATCH 0566/2849] 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 bafb40542e040..911e49dff2c3e 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 d3f787762c468..7e3363c73f840 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 5dd528e91013c..df6f97e8745c6 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 d47ec4f75dfb221d7eb404d5072c5949da12074c Mon Sep 17 00:00:00 2001 From: Marcin Niestroj Date: Mon, 6 May 2024 09:52:51 +0200 Subject: [PATCH 0567/2849] 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 7e3363c73f840..9e1a3dd062b4e 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 10db34cdcf11e..f63b8b3004932 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 df6f97e8745c6..40cb6a62f90d1 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 87a6df2a9b70182045e4d29f3ac7d77327f81385 Mon Sep 17 00:00:00 2001 From: Marcin Niestroj Date: Mon, 6 May 2024 09:53:13 +0200 Subject: [PATCH 0568/2849] 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 9e1a3dd062b4e..a9b5fb1b33fb0 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 f63b8b3004932..66f54130d175d 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 40cb6a62f90d1..54b1af8b24613 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 3a9ae1878f238fd001a13b9fbc4db61f56636f98 Mon Sep 17 00:00:00 2001 From: Marcin Niestroj Date: Fri, 3 May 2024 11:29:00 +0200 Subject: [PATCH 0569/2849] 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 f13a8e3c9829e..3d27e4121a5d2 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 a15cc704e0bbc68743c5b77bce4bfba297e759d7 Mon Sep 17 00:00:00 2001 From: Marcin Niestroj Date: Mon, 6 May 2024 09:41:12 +0200 Subject: [PATCH 0570/2849] 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 3df5ceaec9a76..c9d5cc68ebd29 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 6707410381fa5..3afe29301514d 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 b0394425e1fd0e1515f5999cfe1c90706b6d4e96 Mon Sep 17 00:00:00 2001 From: Yong Cong Sin Date: Fri, 17 May 2024 14:02:28 +0800 Subject: [PATCH 0571/2849] 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 2638269224dcc..f5430c91a6b74 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 84511c1a4ccc5..352c5a22920cd 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 ae082064ffa5746ed4ca9139420199afaaa2e362 Mon Sep 17 00:00:00 2001 From: Laurentiu Mihalcea Date: Tue, 14 May 2024 17:02:11 +0300 Subject: [PATCH 0572/2849] 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 c61e6115a807b..8deb17e06a19b 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 0af51b072c7bbdb152580a874acb6259ccd64905 Mon Sep 17 00:00:00 2001 From: Evgeniy Paltsev Date: Tue, 14 May 2024 16:39:02 +0100 Subject: [PATCH 0573/2849] 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 656d41618a64a..cc44390e279f6 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 ca07b5d1640cb..275674902829a 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 47b334c619ac4a7696c141a02816989d50ad966c Mon Sep 17 00:00:00 2001 From: Evgeniy Paltsev Date: Thu, 16 May 2024 00:07:09 +0100 Subject: [PATCH 0574/2849] 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 a187cdad03e6f..323593fc1d829 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 a2ebe49259d12c7c3375669f65ed5703ddd7f33a Mon Sep 17 00:00:00 2001 From: Jens Rehhoff Thomsen Date: Wed, 6 Mar 2024 10:40:16 +0100 Subject: [PATCH 0575/2849] 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 ae55ca13b128e..860434d428af4 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 c547079cc2552f2974fa3e50e1d6717b11733481 Mon Sep 17 00:00:00 2001 From: Emil Gydesen Date: Fri, 10 May 2024 11:56:30 +0200 Subject: [PATCH 0576/2849] 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 dbaf7383e652c..55f2eab2f931a 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 9c785b87e9843..a6cfcb418d6ea 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 a302a69886729..1981a23458fee 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 46be03e72ef2e..0e5c165290215 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 f67eb76831810..14dba82922530 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 b234131281e4d..7d9491944ef27 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 34e3e7126f699..0e236a1fd4a07 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 27359ca7ffa5d..500eb2048395f 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 acc53adb5ad5d..71d7d107b4e9c 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 15d91fae330e2..1128bf18d1e4b 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 d34e6bcd16e9d..8b6a51d8d64b4 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 b60475c02e266..f8e7769df349f 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 570fcbf58d4a6..b39c4027e81c0 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 a6771fc712eed..93ab96f6279c2 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 2a130f53d9a61..5ba8a9bf2f035 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 878962feb410f..ca72550843af8 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 a9bd3024aa366..bcf72962427c4 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 a66831d1eb7c1..f0d89d7b585b1 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 d0b139e90b19d..ccd3d55cdacdf 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 cb14218068cf2..ed632848d23a2 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 15b8191d2f8b7..ef4f8928650fa 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 2e7fcb384200a..69efefe5b91cd 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 cb24845b202b7..3a0e7ed2c73e9 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 a2bc94d6fb942..aa5dd7e727c66 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 ed227defc1b12..084f1397d0c37 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 2b1e4362b13e4..d582b2aaab4a9 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 24082d582faede181d9a375b8dc33083420296e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Chru=C5=9Bci=C5=84ski?= Date: Mon, 12 Feb 2024 11:56:20 +0100 Subject: [PATCH 0577/2849] 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 aa715c8bbb90d..1e5bca04fe294 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 7b499278dd277..2657d48dc32a1 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 16443f2d105fd..451794a53a246 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 621a5407ac6ce..eda7569c917a3 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 5f1e1c7b34ae115ee43cdd1a21a30ddfb34fcb86 Mon Sep 17 00:00:00 2001 From: Yong Cong Sin Date: Fri, 17 May 2024 18:36:32 +0800 Subject: [PATCH 0578/2849] 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 84d11f152c23a..8b26b1fed8d85 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 67cdccc1c23cece11724becd5b071e3f9ec8eb79 Mon Sep 17 00:00:00 2001 From: Johann Fischer Date: Mon, 13 May 2024 11:55:58 +0200 Subject: [PATCH 0579/2849] 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 2f6825e52b709..dba38aa651093 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 efb286dfdfa760a958b1d1b40f3df3a6da24f007 Mon Sep 17 00:00:00 2001 From: Johann Fischer Date: Tue, 14 May 2024 14:10:30 +0200 Subject: [PATCH 0580/2849] 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 dba38aa651093..0f744ca439785 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 11d8178c135b0..37c9a1eca3893 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 104cb5cb8474f..f96ad9312533c 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 6d06a8cea96de70f08ee4d66735886403921897e Mon Sep 17 00:00:00 2001 From: Johann Fischer Date: Tue, 14 May 2024 12:22:06 +0200 Subject: [PATCH 0581/2849] 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 0f744ca439785..f533490da259d 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 37c9a1eca3893..b54cb82fd2a71 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 7e1f37267d5ce..ad36609bfa1b2 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 8af55448780f8..d5b0167f26b32 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 8cd2525699c39..d1e6b29edbd3c 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 ff51b08078efc..2e954626ded21 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 b117155320921988c2ddfdc5e701d180bb6eb6af Mon Sep 17 00:00:00 2001 From: Johann Fischer Date: Tue, 14 May 2024 13:21:19 +0200 Subject: [PATCH 0582/2849] 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 c05aed352665b..a1a1c9d22cece 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 f96ad9312533c..c06a41572b3bd 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 acd2fa797240c28381ff6cd62e9d770a60f9c1d5 Mon Sep 17 00:00:00 2001 From: Johann Fischer Date: Thu, 16 May 2024 11:43:42 +0200 Subject: [PATCH 0583/2849] 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 f533490da259d..e18aa6b96f6e7 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 715e4ce6f3b628e0ba0a206a8b0eadacfcb077e4 Mon Sep 17 00:00:00 2001 From: Johann Fischer Date: Wed, 15 May 2024 18:15:51 +0200 Subject: [PATCH 0584/2849] 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 c06a41572b3bd..2311dd803086a 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 c00071574a3db48924eec4241b16f557272c9403 Mon Sep 17 00:00:00 2001 From: Johann Fischer Date: Tue, 14 May 2024 11:36:00 +0200 Subject: [PATCH 0585/2849] 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 a4b70ddcb3c80..010819d0b6f09 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 53adf6f490b693d4a1d5f54b43ec03f84aa912cb Mon Sep 17 00:00:00 2001 From: Johann Fischer Date: Tue, 14 May 2024 11:40:21 +0200 Subject: [PATCH 0586/2849] 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 5cd3d5b78e825..374a62724529e 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 2f83ef80de610..713f7c3c27347 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 619dd3022dff42a897a052061ecdc078ae914ea2 Mon Sep 17 00:00:00 2001 From: Johann Fischer Date: Fri, 17 May 2024 12:30:57 +0200 Subject: [PATCH 0587/2849] 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 85dc6b7af2764..82365c1f24598 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 daf6703b81a5d..726608009bad3 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 018c1a04b8021..d7d79f83ec3bf 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 d7c2c32bc5933..f2459019ce7fe 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 834044da3df5f..246b6133a02a0 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 19df415f91f6d4f2109d281adedf590466d5f083 Mon Sep 17 00:00:00 2001 From: Alberto Escolar Piedras Date: Thu, 16 May 2024 11:49:25 +0200 Subject: [PATCH 0588/2849] 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 c276b6b55f1d3..39ad4f088091d 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 35c08ea63664e1cb606d689ee3efb1f88ff9d2b6 Mon Sep 17 00:00:00 2001 From: Piotr Dymacz Date: Wed, 8 May 2024 15:30:16 +0200 Subject: [PATCH 0589/2849] 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 f956270a8529a..0c22bf3796d20 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 bf8f1747cffc6..5976dfdbc7600 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 5409c7c13041f4ed4fed0f212c4125f1e52aeca8 Mon Sep 17 00:00:00 2001 From: Piotr Dymacz Date: Tue, 7 May 2024 15:45:25 +0200 Subject: [PATCH 0590/2849] 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 0c22bf3796d20..f3ba9c494e29a 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 9cba85bb8d248428a7d4c5cdc5d99f46b6daf075 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Ku=C5=BAnia?= Date: Thu, 9 May 2024 08:37:29 +0200 Subject: [PATCH 0591/2849] 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 ad06920c15ce8..b09b24e5e7040 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 d156a03074af3764f134f608ff8493daa8dda3a8 Mon Sep 17 00:00:00 2001 From: Ederson de Souza Date: Thu, 18 Jan 2024 20:28:46 -0800 Subject: [PATCH 0592/2849] 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 2fa2d371c4ab8..22b60009baca0 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 77a718cc7259f..7675e7cb6d51c 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 0000000000000..7c8cf4201f546 --- /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 2f4b0b76ddd3b..8ff24025954a1 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 085ef77556959..792ce4b2da5cd 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 967168a536386c2e7c827484498efb569355bcdf Mon Sep 17 00:00:00 2001 From: Ederson de Souza Date: Tue, 27 Feb 2024 15:05:47 -0800 Subject: [PATCH 0593/2849] 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 22b60009baca0..e1d88a2fca409 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 7c8cf4201f546..dce42e32090d6 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 8755f3c649aac..b6e332d45caef 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 792ce4b2da5cd..c0dc5e5e881f9 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 2f41060fbd327cdd44c521639f0e307bccd5c05d Mon Sep 17 00:00:00 2001 From: Ederson de Souza Date: Wed, 28 Feb 2024 14:45:32 -0800 Subject: [PATCH 0594/2849] 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 dce42e32090d6..2136e7f3fba2c 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 dc8d7ada199aac3d204d35a3805c17beb721a5ac Mon Sep 17 00:00:00 2001 From: Ederson de Souza Date: Sat, 13 Apr 2024 16:00:59 -0700 Subject: [PATCH 0595/2849] 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 924417286ce3d..158321bf4a3f7 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 cd535b75aa267ff6abf42c78ff07d64e21313f67 Mon Sep 17 00:00:00 2001 From: Ederson de Souza Date: Sat, 13 Apr 2024 16:03:10 -0700 Subject: [PATCH 0596/2849] 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 e1d88a2fca409..401060f989cce 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 7675e7cb6d51c..78e5fc9455034 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 2136e7f3fba2c..c62aec4b03005 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 4e9a2a7c33a7dc9c9b6e49a9aeba9bacf3c6df52 Mon Sep 17 00:00:00 2001 From: Ederson de Souza Date: Sat, 13 Apr 2024 16:04:01 -0700 Subject: [PATCH 0597/2849] 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 c62aec4b03005..9501133f3ab38 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 a0ee472a6f9271d38b2174a85e259612df47a86d Mon Sep 17 00:00:00 2001 From: Ederson de Souza Date: Fri, 1 Mar 2024 17:34:25 -0800 Subject: [PATCH 0598/2849] 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 41e36b99a27ab..9bc1d46505749 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 0000000000000..4fee915a57fcf --- /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 0000000000000..1b1a9142ee48a --- /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 0000000000000..c4843bee333fb --- /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 0000000000000..5270bca687359 --- /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 0000000000000..a479f3a569cd6 --- /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 0000000000000..d85a138d48b17 --- /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 0000000000000..190dac2bea692 --- /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 0000000000000..a5e7ab2e1980f --- /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 0000000000000..81f7ce0bd567c --- /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 972eecfc1799a06160a4b138ca6bfc95643fa029 Mon Sep 17 00:00:00 2001 From: Ederson de Souza Date: Mon, 4 Mar 2024 13:43:38 -0800 Subject: [PATCH 0599/2849] 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 0000000000000..22e678c314d22 --- /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 0000000000000..1afc133186e91 --- /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 0000000000000..bc6cb49dca85e --- /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 0000000000000..c9c758f676736 --- /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 0000000000000..1bcfe288e4dd0 --- /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 0000000000000..502901d59bdd0 --- /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 0000000000000..fa7641be4616c --- /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 0000000000000..cfb254797655d --- /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 0000000000000..d7f9c6aa71b3f --- /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 0000000000000..c511cc4a6a067 --- /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 0000000000000..70ea00f0b6120 --- /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 0000000000000..38a054a5ccb19 --- /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 0000000000000..c511cc4a6a067 --- /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 0000000000000..8f95956a25577 --- /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 0000000000000..19aff8352d967 --- /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 0000000000000..c511cc4a6a067 --- /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 0000000000000..b1f4aae47e84d --- /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 0000000000000..34dedc6372820 --- /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 0000000000000..c511cc4a6a067 --- /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 2df070adb466295c1764d6f775e63065fd49b09e Mon Sep 17 00:00:00 2001 From: Evgeniy Paltsev Date: Wed, 15 May 2024 01:25:08 +0100 Subject: [PATCH 0600/2849] 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 711d759a8fd78..bc0a91f60beca 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 d0e0e8ff36b69cf2d646a4fe8267154d15226996 Mon Sep 17 00:00:00 2001 From: Scott Worley Date: Wed, 15 May 2024 09:31:42 -0400 Subject: [PATCH 0601/2849] 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 091f6ac35a47b..11cc8064bb0b7 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 f1107660725e69518ef025f63974a3b8c803f2d3 Mon Sep 17 00:00:00 2001 From: Johann Fischer Date: Fri, 28 Jul 2023 18:05:03 +0200 Subject: [PATCH 0602/2849] 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 1797b54f6dc2f..340cdf9f82be0 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 7cbbc8d433e57..7b3305bf34385 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 b5d086d542463..1d91c188d42cc 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 2f31ee63b5c5956e2288bfda18daec13c3bff50b Mon Sep 17 00:00:00 2001 From: Johann Fischer Date: Fri, 26 Apr 2024 17:56:47 +0200 Subject: [PATCH 0603/2849] 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 755950cc6519f..da80e778533af 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 1d91c188d42cc..70cfdec24565a 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 0b3702206d244..623e92e90c4a3 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 48ca72326b77c30a52fa682108835cd40d3b5f36 Mon Sep 17 00:00:00 2001 From: Johann Fischer Date: Mon, 29 Apr 2024 11:33:55 +0200 Subject: [PATCH 0604/2849] 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 340cdf9f82be0..04001ad427676 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 da80e778533af..1092cf9ac2312 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 70cfdec24565a..4d4114bda9d58 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 9b8796400a7a5e440ce2f90ab3d0aff51c0f8f9e Mon Sep 17 00:00:00 2001 From: Johann Fischer Date: Mon, 29 Apr 2024 16:27:12 +0200 Subject: [PATCH 0605/2849] 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 72d3a84e5b46d..a38823db71add 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 1092cf9ac2312..57a946e7b7729 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 4d4114bda9d58..acf3cc3c1f82c 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 4f17bc605119b862ed5fc579b8530dab10f7280c Mon Sep 17 00:00:00 2001 From: Johann Fischer Date: Mon, 29 Apr 2024 19:10:00 +0200 Subject: [PATCH 0606/2849] 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 04001ad427676..9c272cdeaddfb 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 19023e3212fdf..585e3cfdcf03e 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 57a946e7b7729..aa6e3851312e2 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 acf3cc3c1f82c..efc9c217dbe80 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 9f0a3e6721894..86e571177d7f5 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 29003ff264c0a9fe68d545463329ba4078eeefe0 Mon Sep 17 00:00:00 2001 From: Johann Fischer Date: Tue, 30 Apr 2024 10:08:26 +0200 Subject: [PATCH 0607/2849] 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 b7a0ef08339fe..f73e7c06678ea 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 0de535365ee17..59c3db1cb5905 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 57abfff9cacc9..4b7feb2251330 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 0000000000000..711b1a78ebdaf --- /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 41c813a61b46d..a3670a16804b7 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 1bd4d9f46cb95..e9452d86fc301 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 b0d7d70834ab13e0ae9115436ead908545b2b410 Mon Sep 17 00:00:00 2001 From: Johann Fischer Date: Tue, 30 Apr 2024 18:24:40 +0200 Subject: [PATCH 0608/2849] 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 9c272cdeaddfb..6d697c88869f9 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 aa6e3851312e2..8e7db0b756e77 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 efc9c217dbe80..ecc8e57259a46 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 73286907990883fa69880414995b2639f761b443 Mon Sep 17 00:00:00 2001 From: Johann Fischer Date: Tue, 30 Apr 2024 18:25:04 +0200 Subject: [PATCH 0609/2849] 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 1d330c2ad0874..765fc69bf2172 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 585e3cfdcf03e..1a712819c5711 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 64894e8798d41bf2b6c8c3e36def394ba0a7bd82 Mon Sep 17 00:00:00 2001 From: Johann Fischer Date: Fri, 17 May 2024 00:38:58 +0200 Subject: [PATCH 0610/2849] 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 d7d79f83ec3bf..77ede76aeb42d 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 bdfb6afe70b02e7eaf2546b22d7475e3836204ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20Cab=C3=A9?= Date: Fri, 17 May 2024 15:27:06 +0200 Subject: [PATCH 0611/2849] 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 8e6740a6348d7..4d802ae1a35c4 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 18fd294b5c98e471470d04f2c4cf97f16006a102 Mon Sep 17 00:00:00 2001 From: frei tycho Date: Fri, 17 May 2024 12:36:35 +0000 Subject: [PATCH 0612/2849] 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 f7e75b3aab615..d58411bb1b507 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 89fcb5a9b471d2938044c768f465e72ed32b9a83 Mon Sep 17 00:00:00 2001 From: Karthikeyan Krishnasamy Date: Fri, 17 May 2024 16:28:59 +0530 Subject: [PATCH 0613/2849] 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 c639ec8b30537..6fd249e01c4ee 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 5e7d74bd23d6a4b35ef53683c46424d00eb0e88b Mon Sep 17 00:00:00 2001 From: Karthikeyan Krishnasamy Date: Fri, 17 May 2024 17:10:24 +0530 Subject: [PATCH 0614/2849] 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 4209320fcff3f..8ec74170f94eb 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 409d3bada63f0..692d2a5749b07 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 fa86c518f6704c9d782cf2bbce4808cc6ee01a77 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20G=C5=82=C4=85bek?= Date: Fri, 17 May 2024 12:53:19 +0200 Subject: [PATCH 0615/2849] 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 010819d0b6f09..4e71c0be76945 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 99097bdddb3cf8e9dd5ad5e40ed83d9b5c6bea1d Mon Sep 17 00:00:00 2001 From: Torsten Rasmussen Date: Thu, 22 Feb 2024 20:51:37 +0100 Subject: [PATCH 0616/2849] 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 e6453a5ba48ac..91dc8b6ef38fd 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 0000000000000..5f97065734b36 --- /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 b8836ab94a5a34c02f9bbf2ede317b54a4a5afe8 Mon Sep 17 00:00:00 2001 From: Ioannis Karachalios Date: Wed, 15 May 2024 21:39:03 +0300 Subject: [PATCH 0617/2849] 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 034831075b2e8..480ee2158b206 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 6f0476eb774223ec19a138bcbd9a97b5f36beb43 Mon Sep 17 00:00:00 2001 From: Ioannis Karachalios Date: Wed, 15 May 2024 20:06:52 +0300 Subject: [PATCH 0618/2849] 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 bfac974e874c0..7aa0d461d2733 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 d9a49cb761a5ce5443991bb7ec95fe8d18a32a1f Mon Sep 17 00:00:00 2001 From: Ioannis Karachalios Date: Wed, 15 May 2024 20:22:58 +0300 Subject: [PATCH 0619/2849] 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 0000000000000..c4d616ff25d68 --- /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 0000000000000..4f795b02288ad --- /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 4d038fb523a816d3429a41df58b4ab3219d08e14 Mon Sep 17 00:00:00 2001 From: Abderrahmane Jarmouni Date: Wed, 15 May 2024 15:28:28 +0200 Subject: [PATCH 0620/2849] 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 cdc975c4f1fe1..2cdda0158f3e8 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 cda52f80b5098afeee96a61c612ea264a87c5a4c Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Fri, 23 Jun 2023 20:04:44 +0000 Subject: [PATCH 0621/2849] 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 a67db362366aa..c899e31a3fb9b 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 e987321b250f866ede0da1e0b9a244f43e66c4af Mon Sep 17 00:00:00 2001 From: Phi Bang Nguyen Date: Thu, 29 Feb 2024 16:34:39 +0100 Subject: [PATCH 0622/2849] 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 0000000000000..eecb0e3d3192b --- /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 95657e331268e0f00c6fac4cb1b6721d0d447edd Mon Sep 17 00:00:00 2001 From: Phi Bang Nguyen Date: Thu, 29 Feb 2024 16:33:55 +0100 Subject: [PATCH 0623/2849] 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 0b279de38134f..b93c5bb2f66c6 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 8a489cc4be6bd..9f44944150fc9 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 0000000000000..950079dd35507 --- /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 0000000000000..7c76c7b88c93c --- /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 04293dcfaca39ec33f33634791e52709d377047c Mon Sep 17 00:00:00 2001 From: Phi Bang Nguyen Date: Mon, 4 Mar 2024 15:55:57 +0100 Subject: [PATCH 0624/2849] 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 a38cfdd0e133c..e06d2940817a9 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 08dd430da7314..2acb801b9c643 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 fa912f4389df59861cdcb7c6895064d7092a5e48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mo=C5=84?= Date: Tue, 14 May 2024 07:38:48 +0200 Subject: [PATCH 0625/2849] 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 f216a423968d5..b137a526ede0f 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 00e2b867081b12549ba0ba2f91a7c85a0ae0d349 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mo=C5=84?= Date: Thu, 16 May 2024 10:39:15 +0200 Subject: [PATCH 0626/2849] 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 e18aa6b96f6e7..b344ff0d7d632 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 f4e95ccd48e51c6f8ea351de1fd2e32955d4ce99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mo=C5=84?= Date: Fri, 10 May 2024 14:47:01 +0200 Subject: [PATCH 0627/2849] 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 b344ff0d7d632..2f43eb00a506f 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 938050c7ce206d63ecdf5c709d1a92f650b6dda7 Mon Sep 17 00:00:00 2001 From: Declan Snyder Date: Fri, 17 May 2024 10:24:53 -0500 Subject: [PATCH 0628/2849] 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 a3a46039bfc99..359944f477f8b 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 a20e962340557d6a6dc565c17e6a40cb076d6376 Mon Sep 17 00:00:00 2001 From: Taras Zaporozhets Date: Fri, 17 May 2024 16:56:08 +0200 Subject: [PATCH 0629/2849] 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 1dbc0fb46a6b8..dc115aaf2c329 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 cc1894b8449c4a6934d139177703576dc04d0593 Mon Sep 17 00:00:00 2001 From: Yong Cong Sin Date: Fri, 17 May 2024 15:34:29 +0800 Subject: [PATCH 0630/2849] 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 536d79b67ec6a..f319328bd37e8 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 f58ac3476fac566335622778c396202138e42b32 Mon Sep 17 00:00:00 2001 From: Emil Gydesen Date: Wed, 15 May 2024 14:08:48 +0200 Subject: [PATCH 0631/2849] 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 0ba7d361c0328..3222d6ad9c04a 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 a6cfcb418d6ea..6bf5e1b018e12 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 dc7e54c439da4..fd20fadaa7105 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 7a9c1663594d1..80fd66c103afc 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 ea45041159992..cd4ee8639f0d9 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 cd57f97e11ccd..3f750e9516f36 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 a2605e4b0c77c..ad94a97a96573 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 082a96d2f1b5f..86dcdcc016165 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 b59587ebdfc7f..fb68aa2ee9ed7 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 1042f3530a236..16a6d5ce7f84c 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 54d2e7caf53a2..d5b7496eb19d0 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 1e56aca693073..6133ce2ae6416 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 4305f8e1b8ee2..c652de7946cef 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 c8ddf116b0eac..58d34bd06511a 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 9271a6a12dee5..8d100ebb82667 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 3ae18ced886b8..0a4daa04ca11e 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 3048dfa89995f..1d686a31016e5 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 2ad265cb75abe12ff1daf397f3ec087fbcfce63c Mon Sep 17 00:00:00 2001 From: Daniel Leung Date: Tue, 14 May 2024 16:16:10 -0700 Subject: [PATCH 0632/2849] 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 6a77532f8aebc..664971e2727e2 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 3ccbef2d55d6be76cba4afaa0a7e862281b2cf7c Mon Sep 17 00:00:00 2001 From: Nikolay Agishev Date: Mon, 13 May 2024 22:34:30 +0300 Subject: [PATCH 0633/2849] 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 0000000000000..78164376629e6 --- /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 c40856e5aabb9b96a72af80a799e41cd5c15fb3c Mon Sep 17 00:00:00 2001 From: Emil Gydesen Date: Mon, 13 May 2024 15:57:00 +0200 Subject: [PATCH 0634/2849] 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 1466d46814810..5bdbc947b64fc 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 f02acf526513f..1c4a5ca67e146 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 ec0a5e8ceabbb..6df42691a288f 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 78ef925ce07c4..134cd4beed5c0 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 2cae15e78621f..9c85946c1a218 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 0000000000000..dfd2d8d11e224 --- /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 fcf089574dc7d99959b474ab41b8258779c3d197 Mon Sep 17 00:00:00 2001 From: Emil Gydesen Date: Tue, 14 May 2024 14:53:22 +0200 Subject: [PATCH 0635/2849] 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 f7bb3900e7649..c7ff859472f60 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 4a977463122e5fb25b034bcffd3dfdab6925638a Mon Sep 17 00:00:00 2001 From: Emil Gydesen Date: Tue, 14 May 2024 14:54:04 +0200 Subject: [PATCH 0636/2849] 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 8caebcc4c3c34..018329969695c 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 c476456c5909084f010375dea2f312b43bb15af3 Mon Sep 17 00:00:00 2001 From: Emil Gydesen Date: Wed, 15 May 2024 14:55:30 +0200 Subject: [PATCH 0637/2849] 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 cc0d49ea360fa..265bb6fae39f4 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 0000000000000..89a3d5cf313d5 --- /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 0000000000000..e1e57deda07de --- /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 0000000000000..165b6add6838c --- /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 0000000000000..6d1ec087b23fd --- /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 0000000000000..f644f9181c2b7 --- /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 0000000000000..60a191e388381 --- /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 0000000000000..3bfdb37533447 --- /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 0000000000000..e717a4b2bbef0 --- /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 0000000000000..18c76e299e37e --- /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 0000000000000..980af68ee6f04 --- /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 7c96743fae28d881956260c11f6d3a02f6854417 Mon Sep 17 00:00:00 2001 From: Emil Gydesen Date: Mon, 13 May 2024 10:25:24 +0200 Subject: [PATCH 0638/2849] 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 c7ff859472f60..a8166a5605132 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 cce7208b48cf0..9fdde1da86734 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 63c8b950e5d05a8d4d9fc5563718eafdc74754f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Stenberg?= Date: Fri, 15 Mar 2024 09:44:35 +0100 Subject: [PATCH 0639/2849] 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 47569b005d58d..f10a6596222aa 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 b6cc70e438bdaa006760441c1781cb41b60b7024 Mon Sep 17 00:00:00 2001 From: Jeppe Odgaard Date: Fri, 9 Feb 2024 10:53:31 +0100 Subject: [PATCH 0640/2849] 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 a6121e34194f6..4cc0cae7e82f7 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 5e4d55246abbbafdd75d6191b2bca08a7c5c67cf Mon Sep 17 00:00:00 2001 From: Jeppe Odgaard Date: Fri, 9 Feb 2024 12:03:47 +0100 Subject: [PATCH 0641/2849] 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 0000000000000..38529ab240d29 --- /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 0b94ab77049187d7afc6fccc69fe30d04422d785 Mon Sep 17 00:00:00 2001 From: Jeppe Odgaard Date: Wed, 14 Feb 2024 15:48:10 +0100 Subject: [PATCH 0642/2849] 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 0c1ec766321d4..76a8cff9b96bb 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 5f264cc05c129..85589a541c959 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 0000000000000..07db16869425c --- /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 0000000000000..143618c6838aa --- /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 0000000000000..c5935942069e7 --- /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 0000000000000..de08f07aedccd --- /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 69065fa3170fe66c036c0f9a7814ffb6578a2005 Mon Sep 17 00:00:00 2001 From: Jeppe Odgaard Date: Wed, 14 Feb 2024 16:05:30 +0100 Subject: [PATCH 0643/2849] 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 0000000000000..e43b188ab7d9c --- /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 0000000000000..7eca02930fd6b --- /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 0000000000000..09d85eacacfab --- /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 0000000000000..10b9676ac80be --- /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 0000000000000..e0bc48f5dfef2 --- /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 0000000000000..2039dd9e7ed1a --- /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 0000000000000..db00cda87159b --- /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 7046c9030e7020f6ce416e7061bd1fd7f9b553b8 Mon Sep 17 00:00:00 2001 From: Bartosz Bilas Date: Wed, 24 Jan 2024 21:34:54 +0100 Subject: [PATCH 0644/2849] 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 bada622428003..548b723bdd962 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 067d3419de5ab..be4e983990b4d 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 0ca7ef78bc50bfce622a801a599e40ae0960b9ee Mon Sep 17 00:00:00 2001 From: Kai Vehmanen Date: Wed, 15 May 2024 13:40:57 +0300 Subject: [PATCH 0645/2849] 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 9dd184b9685fd..5424e2a68ae81 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 97ce913437910..3b82d5bf33648 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 723a8fcf364e57decdde906cf1af62b08b76e5d5 Mon Sep 17 00:00:00 2001 From: Benjamin Gwin Date: Thu, 11 Aug 2022 15:42:15 -0700 Subject: [PATCH 0646/2849] 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 16cec58be2f8f..970e6b2717efe 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 25037eb263245..7251f3f733ceb 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 34c84eccec0508b16f5001b20fa369f387d856df Mon Sep 17 00:00:00 2001 From: Lyle Zhu Date: Thu, 16 May 2024 16:28:09 +0800 Subject: [PATCH 0647/2849] 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 548b723bdd962..b2b72c14c7969 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 edef1b7cf45ab8b67ff09ff38cc71f0b922d9a6f Mon Sep 17 00:00:00 2001 From: Erik Brockhoff Date: Wed, 15 May 2024 13:54:05 +0200 Subject: [PATCH 0648/2849] 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 db9bfab8f76bf..951b5754bc6e3 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 aea6c72a7b608..10b4547698a2c 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 982fbff1f320b..eb1f692e55f27 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 4ce49c68ea0fc..cc112b11d3ab8 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 faaa660bb75a9..5744f9c57232e 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 793e33934bce0..f2a21b2f4f8b6 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 f20155bfa3426..e4f2fc2f83cfd 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 2263cd1b23d85..d939abe2d3268 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 806a4fcf92ae882c299d23de9d219b8f887e6619 Mon Sep 17 00:00:00 2001 From: Erik Brockhoff Date: Wed, 15 May 2024 13:56:02 +0200 Subject: [PATCH 0649/2849] 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 f2a21b2f4f8b6..249943b10b2af 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 d939abe2d3268..66476aae6dd51 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 9d8059b6e5541f7f6b4eb1697dccd475f2c1b39b Mon Sep 17 00:00:00 2001 From: Erik Brockhoff Date: Wed, 15 May 2024 13:57:40 +0200 Subject: [PATCH 0650/2849] 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 951b5754bc6e3..4dc525adf904e 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 e4f2fc2f83cfd..006938d9b2fc2 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 d477c6690964fba8a05eef67f4aac102620e211e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Ju=C5=99ena?= Date: Wed, 15 May 2024 20:40:02 +0200 Subject: [PATCH 0651/2849] 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 e140f6d22bc0d..eb33539d8799c 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 4b261299fed1e..ba7f0e8d9400a 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 2fe8e9853b8dbc5148bd5c470202303738918238 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Ju=C5=99ena?= Date: Fri, 17 May 2024 11:01:58 +0200 Subject: [PATCH 0652/2849] 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 0000000000000..7b071f3a54f51 --- /dev/null +++ b/tests/drivers/can/timing/boards/stm32h745i_disco_stm32h745xx_m7.conf @@ -0,0 +1 @@ +CONFIG_TEST_ALL_BITRATES=y From 9a40066b4fc0345faf740f776de11018f8bc2462 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Tue, 14 May 2024 17:19:30 +0300 Subject: [PATCH 0653/2849] 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 46e5ad8e4df06..b0d1fc7dcc9a4 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 7dfa893477473..54e534caf080b 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 0000000000000..97e03804311ab --- /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 4503c3e8dc813..45a9ff16f284d 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 4e723944800e0..3e7a22923bc3c 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 fb3750e110ab1..f16bfc8e96231 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 ad5c07de60146..f8398e95df1dc 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 db691377acd44..c28f0a14eac19 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 5551a41cfbaae..21b33cba4caad 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 a14a8f6fe7de4..b86087552b53a 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 a69ee4ccb73bb..d1129ca8b424b 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 c43911ac3cd2d..4bc1b8706cec9 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 cc56a7821a2e7..3d3bdcf9cf5f1 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 5b7b40cc2773b..b0734b4d17591 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 22a6d33255802..bfdc751ed7c17 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 3d7bb63370356..14822401179c2 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 7b5eac449d559..a155461514f55 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 56ac475d13e1f..9d08909605e97 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 a59dd1a956058..5e0b95aa8272e 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 177d9c991c4aa..fd15cb5309d88 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 bb906c29d0c42..133f2801b9594 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 a4295b74f1deb..5ac3599ca1b20 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 94433b9ce2e7f462f2107a676dc511d559ee469e Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Wed, 15 May 2024 10:36:44 +0300 Subject: [PATCH 0654/2849] 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 45a9ff16f284d..a334b17c8e5bc 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 e10f40d1194e9..e92db7dd57b45 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 31b7a6699a151..e70482c027c0e 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 f7c6945827c09..6d4db394c8db5 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 ae9f6d9dbf2ca..aabe426bdd059 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 d5cd41a0fe5e7e4b4e6275adae059355f829b0b2 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Wed, 15 May 2024 14:03:49 +0300 Subject: [PATCH 0655/2849] 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 db58992f3f8e0..644067671b4f3 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 a334b17c8e5bc..9b15408177e74 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 b2881e7829cdb..deb9802c2a6e6 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 3f1bd6b29e37b478062d001f9f94fc6a39f06a1b Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Tue, 14 May 2024 17:17:12 +0300 Subject: [PATCH 0656/2849] 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 1a027e2c83daf..e75c0b0203fa7 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 b56297bf161e739cd53eb7783f1e0bd5d8ead2b1 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Fri, 17 May 2024 11:14:22 +0300 Subject: [PATCH 0657/2849] 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 f8398e95df1dc..6e034d57ea5b6 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 07d64352fe1383a07388e2fb10bff378a22da537 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Thu, 16 May 2024 09:18:02 +0300 Subject: [PATCH 0658/2849] 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 e3b57ae4f339f..98a20203bdf23 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 e670637f4223720c5436b17499b92f38d5aae3aa Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Thu, 16 May 2024 13:20:28 +0300 Subject: [PATCH 0659/2849] 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 46ee6c66820b2..841c1fb7ebe0f 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 9343b3b408e13..59bc9be99f91e 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 d3df57afd46506ed983a0c45ccda3789b6b09200 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Fri, 17 May 2024 07:41:02 +0300 Subject: [PATCH 0660/2849] 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 cee7218f84738..f3884110630ac 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 7bfbc937e6c41451d1e00c389ec9164a4cd4e02d Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Fri, 17 May 2024 15:56:41 +0300 Subject: [PATCH 0661/2849] 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 c019aa9a8c54e..163024d86b72b 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 3770b07a0eb9343255f164f015f9b2287b35043a Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Fri, 17 May 2024 08:02:08 +0300 Subject: [PATCH 0662/2849] 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 ff8027b0982a6..118d8be120912 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 f6df1a267f918..d1dbe939b1589 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 6924b0d49a968ccc2ed484ce44ed42698e2cce77 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Fri, 17 May 2024 18:22:00 +0300 Subject: [PATCH 0663/2849] 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 512d4dc159bb6..68d6c54271bcc 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 78be3c872afd7..efc60810da269 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 9edc6b2502e96..2e60ca44fe006 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 b042c5796a7bead345d8863097d9e1e42fbd7e25 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Fri, 17 May 2024 08:58:14 +0300 Subject: [PATCH 0664/2849] 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 0f15770cd4676..3f49e0a40881c 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 62a55d03af18084de82398404da4c847d4cad477 Mon Sep 17 00:00:00 2001 From: Robert Lubos Date: Fri, 17 May 2024 10:35:29 +0200 Subject: [PATCH 0665/2849] 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 21b7aad397b8d..aa1f215b1ff3d 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 e6a4a365e2bc1..b2b2f0886733b 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 68dfaee894422e823beb65f7040f193b248428cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20S=C3=B8rensen?= Date: Wed, 15 May 2024 16:23:01 +0200 Subject: [PATCH 0666/2849] 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 278f78530780a..8504e23ed7e50 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 0874f609f1c90d0df20cf664cc24174b245b64e6 Mon Sep 17 00:00:00 2001 From: Robert Lubos Date: Wed, 15 May 2024 17:09:42 +0200 Subject: [PATCH 0667/2849] 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 d1f1d176350f0..9d094c9c4c9f8 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 adc8fd8bbcff2e071ed979e3a9c1d7da41400caf Mon Sep 17 00:00:00 2001 From: Robert Lubos Date: Mon, 13 May 2024 15:16:32 +0200 Subject: [PATCH 0668/2849] 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 a0e0020d729ef..8030ffb791052 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 abfaca57a3072..e1bcce056cfaf 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 1d7239d00ad29a53a59893e76cff1eda77ca6ddd Mon Sep 17 00:00:00 2001 From: Robert Lubos Date: Tue, 14 May 2024 12:19:35 +0200 Subject: [PATCH 0669/2849] 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 59f374024c02e..9ce127bf9feb5 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 f33a183936a943fa87834118d9fb4bf27cd159d6 Mon Sep 17 00:00:00 2001 From: Robert Lubos Date: Wed, 15 May 2024 11:55:09 +0200 Subject: [PATCH 0670/2849] 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 9ce127bf9feb5..c1cafe6f3704c 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 b9f7ffe79d26accf356377b07e844f23aad4d5c8 Mon Sep 17 00:00:00 2001 From: Robert Lubos Date: Wed, 15 May 2024 12:22:36 +0200 Subject: [PATCH 0671/2849] 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 c1cafe6f3704c..8c1f32940d08d 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 9c8ed2dca79e8262984f32cac07123fed80c2b74 Mon Sep 17 00:00:00 2001 From: Robert Lubos Date: Tue, 14 May 2024 10:05:55 +0200 Subject: [PATCH 0672/2849] 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 8c1f32940d08d..02df9ac650c6c 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 5d737e2ab428dfa02b151dafcde1bac5de8713a7 Mon Sep 17 00:00:00 2001 From: Chauncy Liu Date: Sun, 19 May 2024 12:04:11 -0400 Subject: [PATCH 0673/2849] 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 3af2782a442e7..c50e5e592451b 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 7c0de1eccd662..34dffdfe73729 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 cf5bc56f1da43..4c9acb85ac76e 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 f8bbf753fca5752683b7bb72907b28249b3c4853 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Anders=20Storr=C3=B8?= Date: Thu, 16 May 2024 13:29:13 +0200 Subject: [PATCH 0674/2849] 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 558836504d67b..da04b15db73b2 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 aba5580af3de4a3f8405c36c6666ad0996bd544d Mon Sep 17 00:00:00 2001 From: Bjarki Arge Andreasen Date: Fri, 10 May 2024 14:16:31 +0200 Subject: [PATCH 0675/2849] 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 0000000000000..23fb3eac50bc8 --- /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 a19916a0dd3f2..b366b73ce21ff 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 a71542a706a34..7dfdcbfe635ca 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 0000000000000..2ab90d3be6ee4 --- /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 beeb769bb1aa4711491497ccd033b559907a3228 Mon Sep 17 00:00:00 2001 From: Bjarki Arge Andreasen Date: Fri, 10 May 2024 14:21:46 +0200 Subject: [PATCH 0676/2849] 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 0280494e3502e..f68f411c6e222 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 c67c8f7644e40..ea8d99d603268 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 9f451022991c48b4dff18b22ae622102395b45c1 Mon Sep 17 00:00:00 2001 From: Bjarki Arge Andreasen Date: Fri, 10 May 2024 14:22:49 +0200 Subject: [PATCH 0677/2849] 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 c7d4b6297e677..184f83a8e461d 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 b6363276015652f0fcfe7947a0795814e258be34 Mon Sep 17 00:00:00 2001 From: Bjarki Arge Andreasen Date: Fri, 10 May 2024 14:23:38 +0200 Subject: [PATCH 0678/2849] 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 57ee6a8505b8a..2e6990f5aa06d 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 3fcca3d6068af..f4e2280dccbeb 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 88bb45082a8849294313a5f764016bf3bf2713de Mon Sep 17 00:00:00 2001 From: Bjarki Arge Andreasen Date: Mon, 13 May 2024 19:13:03 +0200 Subject: [PATCH 0679/2849] 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 c0eca885fcdc3..799aac60b0b13 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 91085317d99f2..17e3081f55ab6 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 5e193edbc3d3c14b1bd202e4daafbabce7660070 Mon Sep 17 00:00:00 2001 From: Bjarki Arge Andreasen Date: Tue, 14 May 2024 13:27:13 +0200 Subject: [PATCH 0680/2849] 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 afb57c912fc2f..a30a7191ba967 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 51d1cf2e9b60d..b13334d145ba6 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 84e9f52fc475fc13cc00f3a12f27c0dcf906bc44 Mon Sep 17 00:00:00 2001 From: Bjarki Arge Andreasen Date: Fri, 10 May 2024 14:25:33 +0200 Subject: [PATCH 0681/2849] 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 345d49bf463fd..4656fe52d651b 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 b876bd26fd7aacbca07041451408425b338e50f2 Mon Sep 17 00:00:00 2001 From: Joel Guittet Date: Fri, 17 May 2024 10:31:49 +0200 Subject: [PATCH 0682/2849] 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 01a7ed09c28ea..30ddce44eb176 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 442f208cb3222e4be6cc54eb665f3772ee73258e Mon Sep 17 00:00:00 2001 From: Aleksander Wasaznik Date: Thu, 16 May 2024 15:21:09 +0200 Subject: [PATCH 0683/2849] 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 364514fc343cd..59689974b8763 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 85a4b22c3f35a68f4e4a6df2736463f43a29ef16 Mon Sep 17 00:00:00 2001 From: frei tycho Date: Thu, 16 May 2024 13:17:29 +0000 Subject: [PATCH 0684/2849] 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 3a0bc7465e1ff..53fb8af7e3ac1 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 274507fc52a31eb0d43f585ea1d3382f03508590 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Thu, 16 May 2024 14:53:50 +0300 Subject: [PATCH 0685/2849] 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 42008750d6db0..a2fb0d22508b2 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 11dc46dcc838f..dc7143bc7f52d 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 939f1c97e7104..38c6d4b301988 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 52284f57ce69620e6753159a2946e9f8a3f3f11a Mon Sep 17 00:00:00 2001 From: Kevin Wang Date: Thu, 16 May 2024 13:26:21 +0800 Subject: [PATCH 0686/2849] 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 5252c2c56cb3a..3fc69215f60cc 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 44f5a5d5d4d29f7db8df8ed3193f43046829e7ff Mon Sep 17 00:00:00 2001 From: Jordan Yates Date: Sat, 11 May 2024 15:31:46 +1000 Subject: [PATCH 0687/2849] 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 970e6b2717efe..414f89f207ace 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 759dcfe18fcb2b5989fa73a07fa58da1c698dbff Mon Sep 17 00:00:00 2001 From: Patryk Duda Date: Tue, 30 Apr 2024 14:41:09 +0200 Subject: [PATCH 0688/2849] 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 8a78d4e840486..a77e82a45e2b8 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 904f0b49b2560..80a2ff1ab2929 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 1f4e911d687142caea6947fed0ee78b59271f704 Mon Sep 17 00:00:00 2001 From: Patryk Duda Date: Thu, 2 May 2024 10:39:40 +0200 Subject: [PATCH 0689/2849] 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 a77e82a45e2b8..fb203f5becd08 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 0079ab1cb36c3904d2f6e6d0882eed83cebec65d Mon Sep 17 00:00:00 2001 From: Patryk Duda Date: Tue, 30 Apr 2024 15:36:06 +0200 Subject: [PATCH 0690/2849] 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 fb203f5becd08..d2bc4aeac34f2 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 72b20315ea7812edab1841400987debd4cac78ab Mon Sep 17 00:00:00 2001 From: Juliane Schulze Date: Mon, 8 Apr 2024 15:46:21 +0200 Subject: [PATCH 0691/2849] 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 6afa8af839b1f..16b0ea52fb850 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 1988a7c1deb5e..e4c41f586d513 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 a697f34cc8024..ff13d13a321b5 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 861235a9bc7ef178bf199b5279591ed6ff1add94 Mon Sep 17 00:00:00 2001 From: Hess Nathan Date: Thu, 2 May 2024 14:29:03 +0200 Subject: [PATCH 0692/2849] 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 313afbb7922e1..7bfa2088a418e 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 105fc792675c052d71f5911ac071555d1a3f747e Mon Sep 17 00:00:00 2001 From: Stephanos Ioannidis Date: Wed, 15 May 2024 21:39:34 +0900 Subject: [PATCH 0693/2849] 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 63812a85eb291..0e16d6b6ab82f 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 12b96dc324fc641add4ab002b9db96f2571702cd Mon Sep 17 00:00:00 2001 From: Anas Nashif Date: Thu, 16 May 2024 10:58:16 -0400 Subject: [PATCH 0694/2849] 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 ed368a990e9b2..a95e3b9b37eb8 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 1e196f0f752b528db24655f0d44e13c2c025ade5 Mon Sep 17 00:00:00 2001 From: Yong Cong Sin Date: Thu, 16 May 2024 13:44:43 +0800 Subject: [PATCH 0695/2849] 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 8b26b1fed8d85..972f62c7fe3fe 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 d462ed4d95c53cd3fece60dec960a12b95536603 Mon Sep 17 00:00:00 2001 From: Yong Cong Sin Date: Thu, 16 May 2024 12:28:43 +0800 Subject: [PATCH 0696/2849] 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 1f13027d26b90..597957beb61c0 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 354385ee6cadc..38fcdfa7eb6eb 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 db9e3e2061f3b..d3146e5201dd3 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 0000000000000..79d50cb6b2b59 --- /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 0000000000000..50c32f17dbac2 --- /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 0000000000000..212ef5e056556 --- /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 46ed467339c9338945358bec794e80fffec2535c Mon Sep 17 00:00:00 2001 From: Yong Cong Sin Date: Thu, 16 May 2024 13:04:02 +0800 Subject: [PATCH 0697/2849] 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 0000000000000..c13f888a28507 --- /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 d89dfebc21aae..51f57b10f6c0c 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 52935edc5c211d987ec7f2f7ead9778ad4032377 Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Sat, 18 May 2024 22:10:10 +0200 Subject: [PATCH 0698/2849] 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 5e594b0fe0ce2..fedd111af0403 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 97ed2a8f036c2f251e5ece51ec10d301695d5df3 Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Tue, 14 May 2024 15:20:56 -0700 Subject: [PATCH 0699/2849] 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 0b29df511b7fa..b5638870b4ac6 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 938ab7b2303c2..3df8639ac737a 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 b8d40c790d4b0ca30fd2441253184ae4061e388f Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Tue, 14 May 2024 15:27:04 -0700 Subject: [PATCH 0700/2849] 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 d58411bb1b507..61036288671c8 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 8e85ccaea111f..e39e6c0cd6565 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 9a951a0150f08..66c312e48e242 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 9faaf0f8ce608c723ae43ffdc267205a183ed113 Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Tue, 14 May 2024 15:30:17 -0700 Subject: [PATCH 0701/2849] 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 ece13e3bdc29e..8fe75eb33d931 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 b4a1ac5ac691405c586e4ee93a7ad22379853b95 Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Thu, 16 May 2024 12:52:31 -0700 Subject: [PATCH 0702/2849] 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 564355dfefa72..75a47955bc632 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 7c06739829c206de8105672f4daba1594351dde3 Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Thu, 16 May 2024 12:54:41 -0700 Subject: [PATCH 0703/2849] 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 654df3874599f..55f99ad3e28bc 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 ddc1d8706e48f210770e5848bdde1329117f8db2 Mon Sep 17 00:00:00 2001 From: Helmut Lord Date: Thu, 16 May 2024 15:24:50 -0400 Subject: [PATCH 0704/2849] 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 0000000000000..68a1f1baf5a03 --- /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 0000000000000..3453f62ca38ea --- /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 0000000000000..c773063490c04 --- /dev/null +++ b/snippets/rtt-console/snippet.yml @@ -0,0 +1,3 @@ +name: rtt-console +append: + EXTRA_CONF_FILE: rtt-console.conf From 35aae8b5c11136e384c3ddca08a24827a3020f62 Mon Sep 17 00:00:00 2001 From: Hao Luo Date: Thu, 21 Dec 2023 16:17:19 +0800 Subject: [PATCH 0705/2849] 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 97021e84f2717..fd961a550bef8 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 1be99d9d92bdf..a85086461c3ee 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 e510c52ad44b7..2bccb1746d84f 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 fe17883861b22..d789a2519bcc0 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 5e3cf663b8e18..91929c91e20ff 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 6ab7735774d0f4db3661b54d631ebd45fad141f5 Mon Sep 17 00:00:00 2001 From: Andy Ross Date: Mon, 31 Jul 2023 08:34:28 -0700 Subject: [PATCH 0706/2849] 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 8aa3d0fa96cc6..82a44f820c58a 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 fab15a803dad8..40906a0a3262b 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 b8dca1c19679c..ee0ec0fe9395d 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 03cafbdaefeeddec0f0bd3ab61360ae6bf87d3dd Mon Sep 17 00:00:00 2001 From: Andy Ross Date: Mon, 13 May 2024 17:38:53 -0700 Subject: [PATCH 0707/2849] 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 ee0ec0fe9395d..f0b0a9175ff2c 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 bcf6b27c6bd16f2b12b25d6865bb459666f4b96b Mon Sep 17 00:00:00 2001 From: Andy Ross Date: Thu, 3 Aug 2023 20:57:52 -0700 Subject: [PATCH 0708/2849] 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 6a7935d409cfd..2770cb4662c8a 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 14721951971a0f7ae2f7b0c28a6fefc5312faace Mon Sep 17 00:00:00 2001 From: Andy Ross Date: Tue, 14 May 2024 13:15:45 -0700 Subject: [PATCH 0709/2849] 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 c872936a0448a..ff74226cce16f 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 96bdf2146f862..0000000000000 --- 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 10a807537bea1041e5332353b3d41f027ee53eb3 Mon Sep 17 00:00:00 2001 From: Yong Cong Sin Date: Mon, 13 May 2024 15:55:24 +0800 Subject: [PATCH 0710/2849] 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 77d1c7aa53adc..965ff4e3f8d3c 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 07809c488aaae..47abb7c097701 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 b935b5c596e1d..9f29790f95cdf 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 8c6da49f735686d040057c2a7a0bd043009cf63e Mon Sep 17 00:00:00 2001 From: Yong Cong Sin Date: Thu, 16 May 2024 17:45:47 +0800 Subject: [PATCH 0711/2849] 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 1d8daac060c26..7ffcffd65c83f 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 47abb7c097701..8efffd3737193 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 0000000000000..a85dcfbd82d84 --- /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 fe138fc2467c50319cc3fc03f7a1ee0fb02b3dd7 Mon Sep 17 00:00:00 2001 From: Tom Chang Date: Mon, 22 Apr 2024 18:18:24 +0800 Subject: [PATCH 0712/2849] 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 d7cece4eb07d5..05d7b60e2eafd 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 722b26730e8cd..c1760f7adf987 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 a8755e080f759..90b98cbb62d31 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 3f8fe6b4b5f99f07fdf8f3303b3dfd8dde6d0724 Mon Sep 17 00:00:00 2001 From: Tom Chang Date: Wed, 24 Apr 2024 11:25:15 +0800 Subject: [PATCH 0713/2849] 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 0d0d1202f8e89..884b5cdd4d9a1 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 a46fb055bc1e1f9a19560b56155c0ceeb16f840e Mon Sep 17 00:00:00 2001 From: Hake Huang Date: Thu, 9 May 2024 10:05:47 +0000 Subject: [PATCH 0714/2849] 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 e9c7d7ea8c7e5..08c159f552a89 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 de526632ae7a58eb323e68b7f44c76bd6a79c627 Mon Sep 17 00:00:00 2001 From: Hake Huang Date: Fri, 10 May 2024 03:56:47 +0000 Subject: [PATCH 0715/2849] 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 861f0a3098a46..44362f44e204b 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 b3ffe0aede6db181e118eb95db84ad7537bed0b2 Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Tue, 21 May 2024 07:37:49 +0100 Subject: [PATCH 0716/2849] 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 7daedb861c3e3..4e47ac8ab117b 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 c864024c326d7180e3d0c528fee5526c6c26ebfa Mon Sep 17 00:00:00 2001 From: Jun Lin Date: Thu, 9 May 2024 16:52:00 +0800 Subject: [PATCH 0717/2849] 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 8d25067be8c22..864208b49fe08 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 482bbd1c7334b..31aadd86345a1 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 2ec8f442a505954a8c91fa8aeba77fa807681271 Mon Sep 17 00:00:00 2001 From: Jun Lin Date: Mon, 13 May 2024 13:30:35 +0800 Subject: [PATCH 0718/2849] 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 3222d6ad9c04a..280f28370c210 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 b2b72c14c7969..b460b1c13bd6d 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 6ad6d59c4d9394a054bb34c1eecfec7afcb2d5ea Mon Sep 17 00:00:00 2001 From: Nazar Palamar Date: Fri, 22 Mar 2024 01:06:57 +0200 Subject: [PATCH 0719/2849] 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 c4221dc1ad0bb..7a9d44ab17e95 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 c2693b610095b..35e866413c610 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 0000000000000..aa1cd9a0c93f7 --- /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 242f1f6b78e38ca1bb896d0e34bce5a84622f7d4 Mon Sep 17 00:00:00 2001 From: Nazar Palamar Date: Sun, 24 Mar 2024 19:51:51 +0200 Subject: [PATCH 0720/2849] 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 4506e0c995fc9..d5eb1ba0039f9 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 d368e397ea3c3..ff64b9bd9c19d 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 e6bab488049d0..b40ba24a8a5c7 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 ad8e1ea641357..7a1d6f4db6e69 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 879c10d8182ac5a3caee1d83bd193cc335644d47 Mon Sep 17 00:00:00 2001 From: Nazar Palamar Date: Sun, 24 Mar 2024 19:53:18 +0200 Subject: [PATCH 0721/2849] 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 a95e3b9b37eb8..e905666fb6933 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 b3bab9c82afb0..0d3f6b991f986 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 99d925b1396a0..c6d9d95aa246e 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 723579c5d5b92..fb1431faed20b 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 c94bd1db60c34..e3d468cd76412 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 f71e0b2b3a952..f7461673961f8 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 e55e313974031..0000000000000 --- 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 8c645cb1d7bb6..0000000000000 --- 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 1e382579c5f5f..0000000000000 --- 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 140274c4e2609..0000000000000 --- 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 f7a4bd016ad9b..0000000000000 --- 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 78c412cc3ef75..0000000000000 --- 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 a5995c61a0c44..0000000000000 --- 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 b644b123a073d..0000000000000 --- 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 df5e232dc0f0f..0000000000000 --- 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 975ea4fa7fb61..0000000000000 --- 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 aad2f32b66684..0000000000000 --- 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 0000000000000..c08c13ac0cc9e --- /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 0000000000000..f7e3e0b49b477 --- /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 0000000000000..57e358eff8bc4 --- /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 0000000000000..a70e341dd410a --- /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 3120bfdded237..aec3e32650c80 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 0000000000000..3380db75d79d6 --- /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 b50a91cff1efe..65c86f0b831b6 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 0000000000000..1a3d7e054673e --- /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 0000000000000..9986f512d3ea8 --- /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 0000000000000..1863a4fd22988 --- /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 30908b188a729..77de960a053b6 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 0000000000000..b70ed63313cb5 --- /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 0000000000000..c6da791fa963f --- /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 0000000000000..7cb8f8acde994 --- /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 fe5e982cde156..8bd23b04ec2ae 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 c973ed24b9412..a7d58a4a99240 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 9aed50a0fd86e..6c98bdb988075 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 769b6d5d15b6ac82ff8066476afa1fcc27e0c3e2 Mon Sep 17 00:00:00 2001 From: Nazar Palamar Date: Sun, 24 Mar 2024 19:57:46 +0200 Subject: [PATCH 0722/2849] 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 b35cb08ec2fcf..6ef5bd8e9d7b8 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 e918f547bd26f..0f96ff07a774f 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 1aaef3040d38e..db4f1ec95b001 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 281a037b709dd25935448fca2ea6309d1485a8d3 Mon Sep 17 00:00:00 2001 From: Nazar Palamar Date: Sun, 24 Mar 2024 20:02:23 +0200 Subject: [PATCH 0723/2849] 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 adb45b87c0795..c460d9f050396 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 6695a24a4b88b..457878a62b7a7 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 aaa7d0c830551..4ab5c7580ecdd 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 92a9c9a16a599167ee1b70d0fb9240bef5ef3889 Mon Sep 17 00:00:00 2001 From: Nazar Palamar Date: Sun, 24 Mar 2024 20:04:41 +0200 Subject: [PATCH 0724/2849] 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 575dbf8341487..f89df6ee65e02 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 726b1c9894e9b..7997344dd540a 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 8300a160c5a98..113c686db0371 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 279a048a255422dfd8662ed19f7b1a8512817788 Mon Sep 17 00:00:00 2001 From: Nazar Palamar Date: Sun, 24 Mar 2024 20:05:54 +0200 Subject: [PATCH 0725/2849] 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 8f5176e2623d2..0fae593a8794a 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 8288742042241..e232445e811a6 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 2f6fb18cf3c91a40da0d115ee9612771a900190b Mon Sep 17 00:00:00 2001 From: Nazar Palamar Date: Sun, 24 Mar 2024 20:06:51 +0200 Subject: [PATCH 0726/2849] 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 fff6d89ea5d01..18fe196201b2f 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 e192f94580d8e..7cd87ba86342f 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 a82ac8aeb8a426d7ebf33f93dddf6e9052d8de33 Mon Sep 17 00:00:00 2001 From: Nazar Palamar Date: Sun, 24 Mar 2024 20:07:42 +0200 Subject: [PATCH 0727/2849] 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 936733ea02a83..b8bb7b42a8c0c 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 6b1519a455383..feb0a8e5aba64 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 72fcbcbde043032dfb22b20a91b16eb2b96e98e3 Mon Sep 17 00:00:00 2001 From: Nazar Palamar Date: Sun, 24 Mar 2024 20:08:11 +0200 Subject: [PATCH 0728/2849] 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 e6688a7ebb247..75b35c388b77a 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 a7b50692c0752..ec8879bcb4008 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 d308265f5fc7a19c6192e5cf3b63031a66dbc99c Mon Sep 17 00:00:00 2001 From: Ioannis Damigos Date: Fri, 17 May 2024 16:00:14 +0300 Subject: [PATCH 0729/2849] 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 11cc8064bb0b7..4c9c58021947f 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 8716b6a9004ab01b68b993be0b33c66ef6e473ef Mon Sep 17 00:00:00 2001 From: Ioannis Damigos Date: Fri, 17 May 2024 16:01:27 +0300 Subject: [PATCH 0730/2849] 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 28a21d3aa8f3f..a6626aa9598af 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 261b358dc3183fb6b825a96aa80bb35eeaf3d6ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Anders=20Storr=C3=B8?= Date: Tue, 7 May 2024 12:11:21 +0200 Subject: [PATCH 0731/2849] 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 4b3d49702822c..81c9d557c5d23 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 93d0eac8345a60497abf0c89b5f26c41a59ea251 Mon Sep 17 00:00:00 2001 From: Aleksander Wasaznik Date: Fri, 10 May 2024 13:40:43 +0200 Subject: [PATCH 0732/2849] 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 018329969695c..244658e6c74f7 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 f0f04ab796fd8..df312f5dd0346 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 1ee4a8b52cf9638891218afa571c9b230bd2303b Mon Sep 17 00:00:00 2001 From: Robert Lubos Date: Fri, 17 May 2024 10:33:31 +0200 Subject: [PATCH 0733/2849] 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 1e9e27b074ea1..0000000000000 --- 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 dc256b47832a2..944da5cca684c 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 6e53b0f188172..fd4b2f2d0c0e9 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 ec0e2d6308680203bb58275062b79105016ea1b1 Mon Sep 17 00:00:00 2001 From: Robert Lubos Date: Mon, 20 May 2024 15:14:59 +0200 Subject: [PATCH 0734/2849] 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 11d720068cc56..8b89a10da9733 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 2c75b4f1ca18b..615b4264685b2 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 d5683174bcd04..80d6c7e2651b0 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 96c1cfcfb083205de67ffbd699b731f23058ff1e Mon Sep 17 00:00:00 2001 From: Emil Gydesen Date: Tue, 21 May 2024 10:17:46 +0200 Subject: [PATCH 0735/2849] 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 c6e910e8c0bee..4fcf5b2950456 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 14762736b168bc7d1d308d75b8751ad201783f9a Mon Sep 17 00:00:00 2001 From: Andrej Butok Date: Tue, 21 May 2024 10:20:56 +0200 Subject: [PATCH 0736/2849] 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 31e280e556e4e..1912d3cc26b64 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 369ee6d130c42287068b41153e286824b02d5428 Mon Sep 17 00:00:00 2001 From: Hake Huang Date: Tue, 21 May 2024 04:53:01 +0000 Subject: [PATCH 0737/2849] 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 44362f44e204b..deaac1c22ece0 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 30f72eb0a3803318af561242623260a7f8aaa989 Mon Sep 17 00:00:00 2001 From: Charlie Gilliland Date: Sun, 19 May 2024 18:24:53 -0400 Subject: [PATCH 0738/2849] 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 4a11796dc8815..6bd0c65f9b91e 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 369a3a16758407bc1a7243568309be257543c5d0 Mon Sep 17 00:00:00 2001 From: Adrian Warecki Date: Thu, 16 May 2024 17:26:45 +0200 Subject: [PATCH 0739/2849] 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 b9a548d77c145..a860d74422693 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 ad6fa8baac689..d0e7662195e1f 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 4e58ec32021feb462d8e4e9a0cffa96626e034c2 Mon Sep 17 00:00:00 2001 From: Ioannis Damigos Date: Fri, 17 May 2024 14:55:05 +0300 Subject: [PATCH 0740/2849] 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 1ba24850f2d98..e00999ec490a0 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 ffa5b30c33173e0d383e7575f9ead7ea73e50eb8 Mon Sep 17 00:00:00 2001 From: Ioannis Damigos Date: Fri, 17 May 2024 17:29:21 +0300 Subject: [PATCH 0741/2849] 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 d20907c60018c..49ac7c7c660fa 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 e00999ec490a0..39ab44f7d0cd2 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 c78e8bb414bf0..a1539c7887e99 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 0aa82f773e5f2..45c3c56e47277 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 b21b50b02b653925248af072f5f50588a10a99b4 Mon Sep 17 00:00:00 2001 From: Ioannis Damigos Date: Fri, 17 May 2024 17:47:00 +0300 Subject: [PATCH 0742/2849] 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 39ab44f7d0cd2..27290f62c53bf 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 0a49b788a4254b5fcad08ae1758741694927cd06 Mon Sep 17 00:00:00 2001 From: Henrik Brix Andersen Date: Tue, 21 May 2024 15:32:33 +0000 Subject: [PATCH 0743/2849] 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 63c91cde176c8..10436fda53a3d 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 59402fd82ef07634e580b2e85f600b2f4897235a Mon Sep 17 00:00:00 2001 From: Henrik Brix Andersen Date: Tue, 21 May 2024 15:35:03 +0000 Subject: [PATCH 0744/2849] 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 b72b5eece6ca4..7f5beda55ebad 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 85755dd83a93a1f29ddb01aefcf0093af7318243 Mon Sep 17 00:00:00 2001 From: Andrej Butok Date: Tue, 21 May 2024 11:00:36 +0200 Subject: [PATCH 0745/2849] 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 e905666fb6933..8134b0da73953 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 ed025b2f04c34adfdcbb95846c58f8a378d3e7bd Mon Sep 17 00:00:00 2001 From: Benjamin Lindqvist Date: Fri, 17 May 2024 16:02:24 +0200 Subject: [PATCH 0746/2849] 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 3997a394f5809..7779b22fca960 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 f80c440a839ff..96d1584ccb031 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 852f452b03c6b74384b0a55364a7d69192b25360 Mon Sep 17 00:00:00 2001 From: Bartosz Sokolski Date: Tue, 21 May 2024 02:16:37 +0200 Subject: [PATCH 0747/2849] 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 6f1cfb2289332..e692040f7bd72 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 e1931726e7162..028bcfccd54b1 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 282adfd6b1d69..bfe673ec966e5 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 a37482f7d1642..1ca5cadaff999 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 a19bc8fdc8b2b..0000000000000 --- 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 a37482f7d1642..1ca5cadaff999 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 0000000000000..1ca5cadaff999 --- /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 65703a80af836c979007c93cf2524ed1e4e5d9c5 Mon Sep 17 00:00:00 2001 From: Piotr Kosycarz Date: Fri, 17 May 2024 13:50:49 +0200 Subject: [PATCH 0748/2849] 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 26787496a7ccc..3483aab58aecf 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 a7cb8659bd9940c31d6f3e251352bbe39f6ff93b Mon Sep 17 00:00:00 2001 From: Piotr Kosycarz Date: Fri, 17 May 2024 20:11:48 +0200 Subject: [PATCH 0749/2849] 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 3483aab58aecf..1bbfd331debd0 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 60ccb8e4251a53dbd639f91428fed3e0bde0582a Mon Sep 17 00:00:00 2001 From: cyliang tw Date: Tue, 14 May 2024 17:28:35 +0800 Subject: [PATCH 0750/2849] 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 5a755676e8cc1..3485ea22b9591 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 07e2e87fdea5c9a198bbd1036834092cd32b972a Mon Sep 17 00:00:00 2001 From: cyliang tw Date: Tue, 14 May 2024 17:32:17 +0800 Subject: [PATCH 0751/2849] 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 0000000000000..9fb2581d7f4a2 --- /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 0000000000000..8d4f3c66d4351 --- /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 10f0859967579f5d275b731052af9cc7a219d2c9 Mon Sep 17 00:00:00 2001 From: cyliang tw Date: Thu, 16 May 2024 09:38:25 +0800 Subject: [PATCH 0752/2849] 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 2803a4289a291..3f28f49a4a251 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 4d40a96362cce15e3807007db5d4854dadecb9cb Mon Sep 17 00:00:00 2001 From: Ben Lauret Date: Fri, 17 May 2024 13:34:19 +0200 Subject: [PATCH 0753/2849] 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 8134b0da73953..fabae903e97eb 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 e36caec3bae1a2edcfa41baff1952720a52082a2 Mon Sep 17 00:00:00 2001 From: Arkadiusz Cholewinski Date: Fri, 17 May 2024 14:18:58 +0200 Subject: [PATCH 0754/2849] 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 0e16d6b6ab82f..19c50aba9b4b9 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 c5e5686805bea47b8c2d3cea456792ca09ecb04a Mon Sep 17 00:00:00 2001 From: Lucas Romero Date: Thu, 16 May 2024 10:21:07 +0200 Subject: [PATCH 0755/2849] 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 90d1f59345bb5..6ca166f6b21cc 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 7213ae201f54e..6e8c92f118bdc 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 05dd12c534390..dbd43ed201f0f 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 752d3c529e7baa9923c38aa3d2bc43f7ed732a21 Mon Sep 17 00:00:00 2001 From: Lucas Romero Date: Thu, 16 May 2024 13:43:07 +0200 Subject: [PATCH 0756/2849] 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 6ca166f6b21cc..edf67d980fac7 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 6e8c92f118bdc..2642d45e385c7 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 dbd43ed201f0f..9381bbe299b9f 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 3f50197a90369728efa14e33f4848960d8955473 Mon Sep 17 00:00:00 2001 From: Lucas Romero Date: Thu, 16 May 2024 21:07:09 +0200 Subject: [PATCH 0757/2849] 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 edf67d980fac7..ebd18081cc53c 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 2642d45e385c7..509fa5f199f6d 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 9381bbe299b9f..a7a7be02a017f 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 0707a6f302c5bb1b8683845d34c19c7fdac955b0 Mon Sep 17 00:00:00 2001 From: Daniel DeGrasse Date: Thu, 16 May 2024 19:44:40 +0000 Subject: [PATCH 0758/2849] 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 713d8594e886a..376f96da2b332 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 0000000000000..8b9dbe924911f --- /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 c6e3bc3252928a6ea06ce1e19f2891f5476a4390 Mon Sep 17 00:00:00 2001 From: Scott Worley Date: Thu, 16 May 2024 08:44:08 -0400 Subject: [PATCH 0759/2849] 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 8c30ae6087d42..7497d99ead0a5 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 1b5ccda45e05c..8f0b84b4b4abf 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 0fe0c9f3d8ba5..0669a09cbe295 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 0000000000000..62cd150861f1d --- /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 0000000000000..807d8f67b0936 --- /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 0000000000000..6d2a447f7293f --- /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 0000000000000..52eb412941a89 --- /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 0000000000000..9f52e8bad9a7a --- /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 0000000000000..b75177ea75700 --- /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 0000000000000..75a55c393566b --- /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 0000000000000..e815797d8f432 --- /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 0000000000000..6d7a502b08241 --- /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 0000000000000..b0a2a46eef83a --- /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 0000000000000..6d2a447f7293f --- /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 0000000000000..1cce7ce0e2b6a --- /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 0000000000000..268b482b3c043 --- /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 0000000000000..b75177ea75700 --- /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 0000000000000..9d8cdf99040a6 --- /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 0000000000000..39fe541636f85 --- /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 0000000000000..6d7a502b08241 --- /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 0000000000000..b0a2a46eef83a --- /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 0000000000000..6d2a447f7293f --- /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 0000000000000..0bc04fbed20bd --- /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 0000000000000..fe25daf3a93b4 --- /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 0000000000000..b13f40a231f3b --- /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 0000000000000..5bbc8bb5df15c --- /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 0000000000000..3e3a210cf6cd0 --- /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 0000000000000..6d7a502b08241 --- /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 0000000000000..b0a2a46eef83a --- /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 6c20b24ff9ffb..b3c68a80ed069 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 a530010fe2d6d0279a0379692767bfa3dd429d29 Mon Sep 17 00:00:00 2001 From: Aleksander Wasaznik Date: Thu, 16 May 2024 14:03:11 +0200 Subject: [PATCH 0760/2849] 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 280f28370c210..a89e3150d1b9c 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 02bb706f87068..4ba0610b77dd7 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 b93361e89c10e09562314810595c68aa0fa708a8 Mon Sep 17 00:00:00 2001 From: Henrik Brix Andersen Date: Tue, 14 May 2024 10:25:49 +0200 Subject: [PATCH 0761/2849] 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 f7a605f4d7fc8..0fda9745579e9 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 7aadd19d383237e67a4351fcfd18c60530048b01 Mon Sep 17 00:00:00 2001 From: Henrik Brix Andersen Date: Tue, 14 May 2024 10:27:01 +0200 Subject: [PATCH 0762/2849] 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 cff8817c1eb91..68684c0a397e7 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 a6a3891691dd0d28ef9a1922d9e391c702a4b935 Mon Sep 17 00:00:00 2001 From: Henrik Brix Andersen Date: Tue, 14 May 2024 10:28:38 +0200 Subject: [PATCH 0763/2849] 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 0000000000000..dfbf2580eb40c --- /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 f3e4c9685ca1456b43d94313966c2973d87296c1 Mon Sep 17 00:00:00 2001 From: Henrik Brix Andersen Date: Tue, 14 May 2024 10:32:52 +0200 Subject: [PATCH 0764/2849] 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 803d2b7b2d1a9..6cd0c511fb3bc 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 0000000000000..c091646039536 --- /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 888900f9794aaa9d92d80a08260623d67382d890 Mon Sep 17 00:00:00 2001 From: Henrik Brix Andersen Date: Tue, 14 May 2024 10:34:50 +0200 Subject: [PATCH 0765/2849] 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 68684c0a397e7..a4128ac227ba0 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 5197660073895f072b5d8217963f5b240c96c53e Mon Sep 17 00:00:00 2001 From: Henrik Brix Andersen Date: Tue, 14 May 2024 10:35:41 +0200 Subject: [PATCH 0766/2849] 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 0fda9745579e9..56c463d0e4c26 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 be14f9802a386d54bc6cd3ee3876e990ea08dcbf Mon Sep 17 00:00:00 2001 From: Henrik Brix Andersen Date: Tue, 14 May 2024 10:42:32 +0200 Subject: [PATCH 0767/2849] 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 a4128ac227ba0..3a528cded68a7 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 519813b3ce469200d99ea8f2537a7ff7d3a8e6c7 Mon Sep 17 00:00:00 2001 From: Henrik Brix Andersen Date: Tue, 14 May 2024 19:59:17 +0000 Subject: [PATCH 0768/2849] 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 56c463d0e4c26..c137d1a95d2bf 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 64531e8213eb2dcf51d03e34253944b192547599 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Tue, 14 May 2024 10:47:09 +0300 Subject: [PATCH 0769/2849] 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 4c9c58021947f..1fae14d6373ed 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 34e1333a43e995052d268bd8ccdb9cb454a64089 Mon Sep 17 00:00:00 2001 From: Luis Ubieda Date: Thu, 9 May 2024 16:45:14 -0400 Subject: [PATCH 0770/2849] 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 0000000000000..d2b49977fdccf --- /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 7d5265f6105052dcd38bdd564819233c31791f30 Mon Sep 17 00:00:00 2001 From: Luis Ubieda Date: Sun, 5 May 2024 23:17:11 -0400 Subject: [PATCH 0771/2849] 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 13878b66d3b3f..22c5dc252e6d3 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 6898d6e42a93e..3c0596fc5b9b9 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 0000000000000..0d8bda63425f7 --- /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 0000000000000..a8925d3f75b16 --- /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 0000000000000..cf2e4c06312d9 --- /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 788b9855097a79de7dc7af90b51f0466a1fe1427 Mon Sep 17 00:00:00 2001 From: Luis Ubieda Date: Thu, 16 May 2024 20:16:07 -0400 Subject: [PATCH 0772/2849] 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 22c5dc252e6d3..cb180ef24e3cd 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 8af5fe4ddeeca..56d3727e125ef 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 488760638dbca8e4fe552d21a41ef6f9d4cbcb16 Mon Sep 17 00:00:00 2001 From: Declan Snyder Date: Tue, 14 May 2024 12:56:12 -0500 Subject: [PATCH 0773/2849] 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 ace3c53eda847..3790d07afd87a 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 0000000000000..b5c7db0da7298 --- /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 0ae759cb9614093de7c357cb01829447db4afc23 Mon Sep 17 00:00:00 2001 From: Declan Snyder Date: Wed, 24 Apr 2024 13:08:20 -0500 Subject: [PATCH 0774/2849] 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 0000000000000..a2a0b1227353d --- /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 0000000000000..53ccaf667f3a2 --- /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 0000000000000..cecf36ad9a275 --- /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 0000000000000..c7b1d7d51d4a3 --- /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 0000000000000..e52333358c468 --- /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 0000000000000..caefff181f0fd --- /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 0000000000000..c9b0bcb8984a1 --- /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 0000000000000..ad7237fb6583e --- /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 0000000000000..cbb95c517163b --- /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 0000000000000..b987fa24dc09b --- /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 0000000000000..2c56668e4355a --- /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 299b52d1a7089f409f93a83ce5d256cc95237baa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Chru=C5=9Bci=C5=84ski?= Date: Tue, 30 Apr 2024 11:34:37 +0200 Subject: [PATCH 0775/2849] 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 0000000000000..85b08af6419c4 --- /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 a6e59d5432539..d9cbc68b975b8 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 1f14b80b47cac..5fd5d9bfd5d2c 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 0000000000000..39aacbdd4d766 --- /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 a5931c716f6b517d59533c173e09c6fea4de738a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Chru=C5=9Bci=C5=84ski?= Date: Tue, 30 Apr 2024 11:38:45 +0200 Subject: [PATCH 0776/2849] 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 0000000000000..4b55d300ab929 --- /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 0000000000000..c4e9984fc5887 --- /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 0000000000000..10d6c08c2c283 --- /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 0000000000000..ecf519de4aa51 --- /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 0000000000000..85d342cd60c55 --- /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 29fd12818d41aade9f180ab620d51a9afa476e18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Chru=C5=9Bci=C5=84ski?= Date: Mon, 20 May 2024 11:25:56 +0200 Subject: [PATCH 0777/2849] 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 c1a455f5b1cae..259fd894ac4d8 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 0000000000000..dfba9c7e99b1b --- /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 c2cd0fe3ed000049370baeaba840dc27a5e61b9c Mon Sep 17 00:00:00 2001 From: Jean-Nicolas Graux Date: Thu, 4 Apr 2024 18:58:22 +0200 Subject: [PATCH 0778/2849] 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 fd0c62182a483..1c4cf53f899be 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 d56b679ab7ae5..da25e358af645 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 cec4818fde217374dd6d9d145eedf3a3a5249005 Mon Sep 17 00:00:00 2001 From: Jean-Nicolas Graux Date: Thu, 4 Apr 2024 19:57:37 +0200 Subject: [PATCH 0779/2849] 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 2e460ce0303dd..4d09a38fe1d67 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 64aa577c920dbb29da06a8074094c826d217ebeb Mon Sep 17 00:00:00 2001 From: Jean-Nicolas Graux Date: Thu, 4 Apr 2024 20:37:26 +0200 Subject: [PATCH 0780/2849] 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 4d09a38fe1d67..bb5a36cf16b07 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 c2f65cddfc0031a4713ff068fa2cfa7cf1781482 Mon Sep 17 00:00:00 2001 From: Jean-Nicolas Graux Date: Fri, 5 Apr 2024 13:47:36 +0200 Subject: [PATCH 0781/2849] 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 da25e358af645..7fe558d8a2ca7 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 ef5a620b5ab908b068a922174bbf86b872d8bd53 Mon Sep 17 00:00:00 2001 From: Anas Nashif Date: Thu, 25 Apr 2024 07:17:04 -0400 Subject: [PATCH 0782/2849] 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 1fae14d6373ed..4349b0d9d41ce 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 eb866a345de100fbd8bcf9c348179022647d2fec Mon Sep 17 00:00:00 2001 From: Declan Snyder Date: Tue, 30 Apr 2024 11:04:59 -0500 Subject: [PATCH 0783/2849] 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 eddf52c376ada..6a2cf5e10d3d6 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 1db901e2c9927fdbd8f548d591c421ef88fcef63 Mon Sep 17 00:00:00 2001 From: Declan Snyder Date: Tue, 30 Apr 2024 11:07:49 -0500 Subject: [PATCH 0784/2849] 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 0000000000000..df4e01c2a2e63 --- /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 0000000000000..04a1a48d043b6 --- /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 0000000000000..9888572325a0f --- /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 1a7d95e26ce2741285aa516562e775d789b0d922 Mon Sep 17 00:00:00 2001 From: Declan Snyder Date: Tue, 30 Apr 2024 11:08:59 -0500 Subject: [PATCH 0785/2849] 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 f27f31f683c11..8b33eaa86a72d 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 1d361aa8e243d..ccd28e954d0b6 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 0000000000000..cfa6bcdd55857 --- /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 0000000000000..9effda6651898 --- /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 399193f54eba14d0a4b9b7f33e55e6d3a90c57c6 Mon Sep 17 00:00:00 2001 From: Declan Snyder Date: Wed, 1 May 2024 12:09:15 -0500 Subject: [PATCH 0786/2849] 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 8b33eaa86a72d..84f0443cabb5f 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 ccd28e954d0b6..87ba9c7576cac 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 0000000000000..6e604b9664345 --- /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 0000000000000..22d7cfa065088 --- /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 e7d0f3feaf3b58bbe1d6f47c6140a1dd1f402b2c Mon Sep 17 00:00:00 2001 From: Declan Snyder Date: Tue, 30 Apr 2024 19:11:53 -0500 Subject: [PATCH 0787/2849] 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 4e601ea8f9d47..c892b53007672 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 565a62065b7af6522c2ed8d593275aaa1688d67b Mon Sep 17 00:00:00 2001 From: Declan Snyder Date: Tue, 30 Apr 2024 17:36:48 -0500 Subject: [PATCH 0788/2849] 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 fabae903e97eb..62b4cf8d46182 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 7a17e141cc7a40dedeb9a79ee6b6de0558e4a893 Mon Sep 17 00:00:00 2001 From: Declan Snyder Date: Mon, 6 May 2024 12:20:56 -0500 Subject: [PATCH 0789/2849] 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 ffc27753c3dce..57121b489ae25 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 48aef0031396c..bd735c88561e6 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 e9e05b6c5b5b0..18e4543cfe3db 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 12f99a8338667..14e96d7e0db21 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 c2901c3bb6d4cebd5536de6f4c02b5ed6ee09534 Mon Sep 17 00:00:00 2001 From: Declan Snyder Date: Mon, 6 May 2024 12:22:25 -0500 Subject: [PATCH 0790/2849] 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 964e863485ba9..3c69de8dd4ac6 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 a5befec1257f0..78ffb203a84ff 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 c2f8295e57578..4ffb014f2814d 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 05ad85196be8f..c9b4b3ddb8978 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 5a5e435083309..a751693e201a9 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 311ad16e3ace2..6a5621d19b7bd 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 3178e05a54eb1..22ca5d6b0ec28 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 fc6714b951e0c..fc24a062e8a2a 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 800d61bd13855..4b7b1524a0b22 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 ae4361e0d0dd4..6770d6455967d 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 eeb3e808f5e5956305b1992756c34868f230bd62 Mon Sep 17 00:00:00 2001 From: Declan Snyder Date: Mon, 6 May 2024 12:23:58 -0500 Subject: [PATCH 0791/2849] 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 e995a19ab6f1a..a0e3e00fddab0 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 2ca5d3e02771d..5a984279ae554 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 6bd8c6dcd024e..cf3bb84558f19 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 209d0314b3e14..2ad62385d8e37 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 744f5025eb066..f91876390147b 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 eeb77cb68e115..f75c65650ec07 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 67fbc370ac860..743c7d9c6a55d 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 2365f58aacc29..e323dc9ec786e 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 ff07a5ec03887..68ef16aa3e814 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 cb20fcea6e3be..411244c21a9aa 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 5edaa5e276d2ca841dfb08cb080b4d39d3b7cb00 Mon Sep 17 00:00:00 2001 From: Declan Snyder Date: Mon, 6 May 2024 12:24:54 -0500 Subject: [PATCH 0792/2849] 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 4b420ea46d483..9f29550b576ff 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 de658a285be9f..bb6ea26ac45b7 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 e09800ce872f4..c4b7b58131abd 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 20f2022cd56b5..f5a353d2ad343 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 a26aae34d9b76..5072fd8266b54 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 f319328bd37e8..a18aff5cf8a0c 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 9b9a4eb0273f6899334ec61cceaacb674c5ec06e Mon Sep 17 00:00:00 2001 From: Declan Snyder Date: Tue, 30 Apr 2024 19:13:19 -0500 Subject: [PATCH 0793/2849] 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 fc24a062e8a2a..95af8ca31770a 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 4b7b1524a0b22..47d4258ee8e24 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 6770d6455967d..b02f5fe281405 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 b8049b41ae3725bf2e3845b1cdd2e0123f010ddb Mon Sep 17 00:00:00 2001 From: Daniel DeGrasse Date: Tue, 30 Apr 2024 10:58:02 -0500 Subject: [PATCH 0794/2849] 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 0314fe5c31f13..e2b3aefe53bf6 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 13ae32e1c23cfe5b3f1ceebc5e9a6112fe2116d7 Mon Sep 17 00:00:00 2001 From: Daniel DeGrasse Date: Thu, 21 Mar 2024 14:26:28 -0500 Subject: [PATCH 0795/2849] 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 42d7cd890603d..d769b9a1a4dd5 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 6d272ddd53d4f..c5e9202e94f25 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 94153eca5859b..387665ace45bb 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 88c282d89f88e..1626cb5204b23 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 90ead2b8731d8..bc94281e82923 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 6347aa74c42135017cb3dc28fb89cabc38093e79 Mon Sep 17 00:00:00 2001 From: Daniel DeGrasse Date: Thu, 21 Mar 2024 14:33:47 -0500 Subject: [PATCH 0796/2849] 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 3f71e34d33b7a..86554578ff937 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 1ed9ef465bc45d69b661f526c12af612c8a46127 Mon Sep 17 00:00:00 2001 From: Daniel DeGrasse Date: Thu, 21 Mar 2024 18:34:24 -0500 Subject: [PATCH 0797/2849] 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 a89e3150d1b9c..4c1fccd2e3a32 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 9d15f6623aef6dfcdea06cc5b5133f7dd0283bac Mon Sep 17 00:00:00 2001 From: Javad Rahimipetroudi Date: Tue, 6 Feb 2024 10:41:53 +0100 Subject: [PATCH 0798/2849] 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 aa4e95722a716..b293782e620fb 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 269657dd0b8a0..3be80de47298c 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 0000000000000..3857c08dc5f0d --- /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 0000000000000..c8501156e8143 --- /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 0000000000000..596bee98d165d --- /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 c46466e48a67db2fa111bc89f98517b98b8f86ad Mon Sep 17 00:00:00 2001 From: Javad Rahimipetroudi Date: Tue, 6 Feb 2024 10:44:04 +0100 Subject: [PATCH 0799/2849] 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 a149ea79a3679..51bde0110c55d 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 4f4fb99cea013..6e48823ae242e 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 fd157a81be1c95c6e5702a88140d6a53914d107e Mon Sep 17 00:00:00 2001 From: Phi Bang Nguyen Date: Thu, 29 Feb 2024 11:21:30 +0100 Subject: [PATCH 0800/2849] 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 0000000000000..1726d63b3299e --- /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 f1846eca0206701f378fa9ad085b6dc0747aa1ff Mon Sep 17 00:00:00 2001 From: Phi Bang Nguyen Date: Thu, 29 Feb 2024 11:10:33 +0100 Subject: [PATCH 0801/2849] 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 b93c5bb2f66c6..19ad0e2bc797e 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 9f44944150fc9..787311622e0cc 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 0000000000000..f9bf2f19f1efe --- /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 0000000000000..6d9dc5729edc3 --- /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 61a16be840e1a20b784ccae30debbc42ce0aed93 Mon Sep 17 00:00:00 2001 From: Phi Bang Nguyen Date: Tue, 30 Jan 2024 18:19:24 +0100 Subject: [PATCH 0802/2849] 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 0a1eecc2cc921..642708af9871d 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 ae8115275ce48c0d0fd5d0f4bde7a5fd89be4ca3 Mon Sep 17 00:00:00 2001 From: Phi Bang Nguyen Date: Tue, 30 Jan 2024 18:13:35 +0100 Subject: [PATCH 0803/2849] 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 03611213830ae..fc0a169080010 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 9e03d5ada3f7ce5d50ed4e67237dd644e1df4b1f Mon Sep 17 00:00:00 2001 From: Phi Bang Nguyen Date: Sat, 11 May 2024 19:34:35 +0200 Subject: [PATCH 0804/2849] 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 0000000000000..99542ad4c7825 --- /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 2acb801b9c643..49acda27c13ef 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 492cf3c250952335b09b318489943b4d77668e32 Mon Sep 17 00:00:00 2001 From: Erwan Gouriou Date: Tue, 21 May 2024 15:57:17 +0200 Subject: [PATCH 0805/2849] 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 12715712a0bb8..a12712dda8a1e 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 fb64753c289da51099d7488a9cfd4d4bf9582f4d Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Mon, 20 May 2024 09:18:55 +0300 Subject: [PATCH 0806/2849] 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 c50e5e592451b..2855017b28243 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 0a49160d1ea6960ce4906edc812a031268ce6f96 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Mon, 20 May 2024 09:20:39 +0300 Subject: [PATCH 0807/2849] 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 da5b6a3e067bf..1d7056a72ead7 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 b99497006894f5052c41c09df3f00aab5459364e Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Fri, 17 May 2024 18:37:56 +0300 Subject: [PATCH 0808/2849] 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 bd47f92106ef1..c6714ee9dcb5a 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 7779b22fca960..a3576a244c521 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 cabfb9ff859d9..7c7c3c5f2f378 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 f19eec6eb4b43..a52293a926583 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 931dffd75502f213970aa6fe8acacb2171de127f Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Fri, 17 May 2024 18:40:05 +0300 Subject: [PATCH 0809/2849] 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 d083509b437bc..048f40124de8a 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 bacff7fd285ff841c72990470afd4ac1b4b9c130 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Fri, 17 May 2024 18:42:12 +0300 Subject: [PATCH 0810/2849] 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 94c50d90f1911..16a873b7b2f1d 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 03e9b3f320827d68abef58a9edd2c68b4102abaf Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Fri, 17 May 2024 18:45:12 +0300 Subject: [PATCH 0811/2849] 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 b06a7cb0320a5..c31d5f9141782 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 86537ca4693ecae02c8954b3b81500d7c86d345f Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Mon, 20 May 2024 07:14:32 +0300 Subject: [PATCH 0812/2849] 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 b0d1fc7dcc9a4..fff5d4ad867d8 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 ee26be4113d0d95cc2aff117719cad48da6fd934 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Mon, 20 May 2024 07:16:06 +0300 Subject: [PATCH 0813/2849] 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 479690509a3f2..1aed17e11baad 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 ce3512bfaf9b2ffbf8b20f5b41d09ce2599f0b62 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sat, 18 May 2024 09:07:56 +0300 Subject: [PATCH 0814/2849] 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 bcf250a341cb9..4c5fe0312349b 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 f1852b4a1d8ed833679414982ce58448192a056d Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sat, 18 May 2024 09:37:25 +0300 Subject: [PATCH 0815/2849] 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 9ecc7340d03e7..30fbb200bce44 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 9ec0f6ec4f081cd0a36fccffe185ed3fda18096f Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sat, 18 May 2024 09:39:35 +0300 Subject: [PATCH 0816/2849] 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 aa86f63a5616b..fa2ca54698335 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 fb4dda2605fa0a9d8eed8a7884e7475477c95b8e Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sat, 18 May 2024 09:42:30 +0300 Subject: [PATCH 0817/2849] 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 049a94ec99e80..488583e4d533b 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 d206c5931a70c01bf913e1a9100462979b44cb46 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sat, 18 May 2024 09:47:11 +0300 Subject: [PATCH 0818/2849] 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 d9bac4393c287..4e801ffbda5c5 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 de2cdd538b39e1f5ee7e2fc6d0fdb0aeab6ddd46 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Mon, 20 May 2024 09:57:36 +0300 Subject: [PATCH 0819/2849] 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 6a95004001f42..71eb1b32f336f 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 b0fa4140391c40e055347f2cb467a76da34cbb6b Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Mon, 20 May 2024 10:04:19 +0300 Subject: [PATCH 0820/2849] 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 3e51539b4b7eb..02d063c68660b 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 639fa20d081ca3d9962fab03d93ef3b6cbcd5d91 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Mon, 20 May 2024 10:05:59 +0300 Subject: [PATCH 0821/2849] 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 35bfa49189f13..0a85cf7c8adca 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 5119235a006ae75b77bf8885aecc69c83817abd6 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Mon, 20 May 2024 10:07:46 +0300 Subject: [PATCH 0822/2849] 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 b27e3144b236b..30f4aaeeaca7c 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 5b7b378dfe1f010e2385218219f349558cadf128 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Mon, 20 May 2024 10:11:31 +0300 Subject: [PATCH 0823/2849] 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 7bfb609384356..3e5223427dc7d 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 3a555048f491d086fb65eee73ffc8db557884461 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Mon, 20 May 2024 10:13:51 +0300 Subject: [PATCH 0824/2849] 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 334444420b983..e541c768f5636 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 8eb91fa11eacd1eaefb23c707b45df45275c6bbb Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sat, 18 May 2024 10:10:06 +0300 Subject: [PATCH 0825/2849] 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 a5b9f6b2455c4..6d6a6b2c867dd 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 effb78d03af95d12c3097b6cda325d6b8dd08a72 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Mon, 20 May 2024 07:25:13 +0300 Subject: [PATCH 0826/2849] 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 927a9036db3e3..b60aa7071f390 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 78aaaba2cd53840e090373bd1a3a44c103619840 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sat, 18 May 2024 10:31:17 +0300 Subject: [PATCH 0827/2849] 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 0be4c1576e5c0..a2378a38efa84 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 b3bbc8f763e466742c6e8ea9f3c1abe2e8acd29f Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sat, 18 May 2024 10:35:11 +0300 Subject: [PATCH 0828/2849] 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 1f08c0b73c063..5937242355878 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 04d12cc699a1f0221d5f8b2315d9b0a436b5b978 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sat, 18 May 2024 10:41:28 +0300 Subject: [PATCH 0829/2849] 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 9912132918b55..028a2d1ea1b49 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 f5ae486c0ef4e881202b1b083f0b1fd384a3baaa Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Mon, 20 May 2024 07:32:35 +0300 Subject: [PATCH 0830/2849] 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 f6f9949d328fe..e45bbc6b85b4c 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 4d46300be4eddd4c8ae66c3b710b3e4ea62dda87 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sat, 18 May 2024 10:43:16 +0300 Subject: [PATCH 0831/2849] 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 ed39a31359f2b..7dbfd78e1d8da 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 a28949b4518f0cb15b3ea7e3a1caaf0165882934 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sat, 18 May 2024 10:44:56 +0300 Subject: [PATCH 0832/2849] 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 5fec5eb6637db..3b686faffca5a 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 055665238d289e3dbd0093a24f0957568112419c Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Mon, 20 May 2024 07:39:34 +0300 Subject: [PATCH 0833/2849] 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 68a5ef9617ed5..0ae5314e3d0bc 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 136637144264930124c248d4b501fce0acf39dad Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Mon, 20 May 2024 07:41:15 +0300 Subject: [PATCH 0834/2849] 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 cd42c4942dad4..ad012c8aba865 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 fe2bc1703de2f5db3f9de25406d99b1d5d28f344 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Mon, 20 May 2024 07:43:18 +0300 Subject: [PATCH 0835/2849] 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 8d1998f7cec93..6ed13c1a6fd38 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 b711f5ac94b08bf967247926fb67c2483435c9b8 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Mon, 20 May 2024 07:46:52 +0300 Subject: [PATCH 0836/2849] 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 fc2a65bc306b4..371f19665c22a 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 aa59ac9de13aab0df3bae6531019f1abafb39cac Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Mon, 20 May 2024 07:50:46 +0300 Subject: [PATCH 0837/2849] 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 5bbc9f794834f..2514fc709c2c6 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 8825075438e9a4e86e11421e8301e42e177ed2a9 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Mon, 20 May 2024 07:52:00 +0300 Subject: [PATCH 0838/2849] 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 cb1a6d3373123..102cb5e692a7a 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 06abfee94bbc15fa0b2b1de6531e29f0bc780d04 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Mon, 20 May 2024 07:58:18 +0300 Subject: [PATCH 0839/2849] 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 34dffdfe73729..8e85af1fde97a 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 f1d1603eda248fc4df27ce40668848bce3a21ca8 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Tue, 19 Mar 2024 17:42:36 +0200 Subject: [PATCH 0840/2849] 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 3d2be01fd9002..b149934f8bcac 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 3f24da5761f871f863157c4adac3ad914f2604e7 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Mon, 20 May 2024 08:52:53 +0300 Subject: [PATCH 0841/2849] 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 9c27e08d2c26a..b1a2ca8925a13 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 03e471683068dbb43581718f5db8e649d050cd1d Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sat, 18 May 2024 11:21:32 +0300 Subject: [PATCH 0842/2849] 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 4c9acb85ac76e..413d3efb09449 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 b330357fdc61456d121f29826ebc63b3af4743b9 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sun, 19 May 2024 10:22:41 +0300 Subject: [PATCH 0843/2849] 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 f90bc8e183646..55c65b122ec24 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 f1f77046fb6bae86b14764b57587eec974d31e99 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sun, 19 May 2024 11:13:21 +0300 Subject: [PATCH 0844/2849] 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 18eba376fe725..4c5b592fde4ab 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 d08c93bbc9ebabb1cbae13f2d665f216876d726b Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sun, 19 May 2024 11:17:28 +0300 Subject: [PATCH 0845/2849] 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 aa1ad89b0e619..753ca347eb45c 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 2a28a13a6de7fbf61ff64074c508fb8477b8c673 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sun, 19 May 2024 12:11:22 +0300 Subject: [PATCH 0846/2849] 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 f5a567fcdbc41..5a2ac84eaa216 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 5c917939116e5029b45fbff5ed5fd0e2f5fa8204 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sun, 19 May 2024 12:13:20 +0300 Subject: [PATCH 0847/2849] 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 fb40ec9361601..87d312648f48e 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 8fed255da5615166b844bec44ab4d36c03ff7323 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sun, 19 May 2024 12:15:07 +0300 Subject: [PATCH 0848/2849] 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 ce90cf77bf375..009a0666515e0 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 c168ef39c03d2d9f33d6ede1ea2c57397417cc81 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Mon, 20 May 2024 08:56:34 +0300 Subject: [PATCH 0849/2849] 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 81c2629d6c025..0d933df460f77 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 35c64657a1ad665387a0c98291740c1a4deb6d5e Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sun, 19 May 2024 12:20:09 +0300 Subject: [PATCH 0850/2849] 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 38c6d1f5bbe71..160b31df23797 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 bd0816afea3e95c2ed28f356136c9737a6a0267e Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sun, 19 May 2024 12:32:26 +0300 Subject: [PATCH 0851/2849] 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 36c6bf64eebf3..da31eca01a18c 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 6a766416199fb06ad6120da303ad9b28aa501488 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sun, 19 May 2024 12:36:46 +0300 Subject: [PATCH 0852/2849] 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 99c5037e7ba0b..269325cdde19d 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 8b031c7952afc4a0734fac2d42218df4000e8fcd Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sun, 19 May 2024 12:40:08 +0300 Subject: [PATCH 0853/2849] 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 a1c8a59e0e856..68a733d355d50 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 b38132113a7a858dc1f1e59d0cb8854e05533db0 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sun, 19 May 2024 12:42:04 +0300 Subject: [PATCH 0854/2849] 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 54e534caf080b..1ec1a9a12dfb4 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 f8a3c95132fde7b362c0bfd709986faf04e87cc2 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sun, 19 May 2024 12:43:52 +0300 Subject: [PATCH 0855/2849] 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 c2c07a93b15c1..3c173f96a6f6c 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 77a8f1b105fde2d3d431a35a088d79f78b466d6d Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sun, 19 May 2024 12:46:32 +0300 Subject: [PATCH 0856/2849] 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 d0f2d29cfe402..988d0fb686b34 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 b1956dfa0832c98165fa0f623e451ecf6b768a48 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sun, 19 May 2024 12:48:39 +0300 Subject: [PATCH 0857/2849] 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 1e7507711a118..d4cfef32cbcd9 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 d433c9cc17362313055807b25e8ccccf7c455797 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Mon, 20 May 2024 09:03:19 +0300 Subject: [PATCH 0858/2849] 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 a4e21f00a3335..b1037bf07c3c3 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 97979604de43089ed6f0edfdc0e1737148783337 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sun, 19 May 2024 12:50:49 +0300 Subject: [PATCH 0859/2849] 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 6195315e51aca..0727dd77bdf31 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 a0b51ebc6fa150c0035a2e9f61b7306c830d48ab Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sun, 19 May 2024 12:58:09 +0300 Subject: [PATCH 0860/2849] 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 c4916487d9971..dd2a7049288d7 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 478f4d1f6d11ff99a44f48978aed51fa64729007 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sun, 19 May 2024 12:59:28 +0300 Subject: [PATCH 0861/2849] 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 7a7b862a7a707..b118f7531d9ce 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 c32492af5400bf629b1866f2ae3c6abe4a93153f Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Mon, 20 May 2024 09:04:35 +0300 Subject: [PATCH 0862/2849] 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 61db441e54843..eb3df0cc0c1d2 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 a485eb0ddf8117a6842fd3f584bae399f0aa9278 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sun, 19 May 2024 13:02:15 +0300 Subject: [PATCH 0863/2849] 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 fb6ee8f74be88..9d46ffa0b91ff 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 d44d814bb5d8f656e3c6dcdf05c7c00222ab60fa Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Mon, 20 May 2024 09:06:04 +0300 Subject: [PATCH 0864/2849] 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 d64bab155772b..806665296f925 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 e86719d8ccc6b0580a9ae29dd9c49c87acf3b59f Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Mon, 20 May 2024 09:09:09 +0300 Subject: [PATCH 0865/2849] 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 606957e9fd57a..3b2d9dddd678b 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 4a7e6ffde505118ee718cb9fc642cdae4a8d606d Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sun, 19 May 2024 13:11:52 +0300 Subject: [PATCH 0866/2849] 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 ebfc76d2192d1..5f47209b83fc6 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 3b56c7baf8372ea5b21c486188dd0bca5db8f3d9 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sun, 19 May 2024 13:34:59 +0300 Subject: [PATCH 0867/2849] 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 70fd5978fba67..0442a91c2f2fb 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 0870af5f9fcba665c59dec655dde8590a1961ddf Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sun, 19 May 2024 13:36:21 +0300 Subject: [PATCH 0868/2849] 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 dd97fcdd8b616..615d49157572a 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 457877fc34773160738a1491c3d3c9658eab6926 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sun, 19 May 2024 13:37:58 +0300 Subject: [PATCH 0869/2849] 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 537db78764828..511d203353228 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 356c650ccf0a6da6143a15ac7a89f1e730ceda63 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Sun, 19 May 2024 13:41:54 +0300 Subject: [PATCH 0870/2849] 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 21ce74bb33b7d..c97c9d014395b 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 17a5beb34124b66f54da4e9d2051ccccdf30311b Mon Sep 17 00:00:00 2001 From: Andy Ross Date: Sat, 5 Aug 2023 08:54:31 -0700 Subject: [PATCH 0871/2849] 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 eaffb6ce763b3..00765f5483a89 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 169bc07e83f93187b4a191490b54cf366f0657d5 Mon Sep 17 00:00:00 2001 From: Daniel Leung Date: Thu, 25 Apr 2024 10:57:17 -0700 Subject: [PATCH 0872/2849] 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 767c04f94fe47..c65ec351fcb3e 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 0000000000000..9f94f4cdcbd61 --- /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 e6abc035c8fad57c29cf23e72e520347b2a26357 Mon Sep 17 00:00:00 2001 From: Daniel Leung Date: Thu, 25 Apr 2024 11:35:35 -0700 Subject: [PATCH 0873/2849] 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 a1ddcd395e98a..f830cc981b91b 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 9f94f4cdcbd61..28f3d003639d2 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 8426a05e0e5fbd176711dc719f95958efdc1df10 Mon Sep 17 00:00:00 2001 From: Daniel Leung Date: Thu, 25 Apr 2024 12:05:52 -0700 Subject: [PATCH 0874/2849] 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 cd66c06ab7a1a..d2b5842ee97ea 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 7289dcdcda50b783c84fc19cf264baa4d6334f01 Mon Sep 17 00:00:00 2001 From: Daniel Leung Date: Thu, 25 Apr 2024 11:59:02 -0700 Subject: [PATCH 0875/2849] 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 dc540038e2b2c..c6d1bdc7da05a 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 27b0651f7acda8736373c881d8b783767c1952bc Mon Sep 17 00:00:00 2001 From: Daniel Leung Date: Thu, 25 Apr 2024 12:10:03 -0700 Subject: [PATCH 0876/2849] 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 965ff4e3f8d3c..1c4d547b29c64 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 219433143152251b24ccc8e36c34a1dbad41679f Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Sun, 19 May 2024 12:22:11 +0200 Subject: [PATCH 0877/2849] 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 fedd111af0403..48abc493718a4 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 352c5a22920cd..87942f4bfd205 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 14412a6579a62..5db5a857167e9 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 ee91493e64ba933528ec0dbe12e6725881d6ba5a Mon Sep 17 00:00:00 2001 From: Hake Huang Date: Sat, 18 May 2024 16:31:16 +0000 Subject: [PATCH 0878/2849] 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 612aa824ec0be..b7315b180d4f3 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 35e266d2c1218e2d625dc27622bc3ee7e2f3dee0 Mon Sep 17 00:00:00 2001 From: Hake Huang Date: Sat, 18 May 2024 16:41:11 +0000 Subject: [PATCH 0879/2849] 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 b7315b180d4f3..e38f1ef1273dc 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 d2c060d1ef8c407dbe3d4a4d108ecbafad45dc0c Mon Sep 17 00:00:00 2001 From: Marcio Ribeiro Date: Mon, 20 May 2024 06:58:43 -0300 Subject: [PATCH 0880/2849] 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 25b1c599c571f..f8282767d22d7 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 e38f1ef1273dc..b63410ef53c01 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 027e00955d0b88bab80931b676c266b9714aef77 Mon Sep 17 00:00:00 2001 From: Paul He Date: Sat, 18 May 2024 23:14:55 +0800 Subject: [PATCH 0881/2849] 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 009cd2de966ec..cfffd813a8bc2 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 20020563ca164..0000000000000 --- 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 ea288283a327e9767ff4a7da508563956222489d Mon Sep 17 00:00:00 2001 From: Dong Wang Date: Fri, 17 May 2024 15:11:35 +0800 Subject: [PATCH 0882/2849] 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 85fbfdb35b6e5..cd8e898a354ba 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 c12f0507b6e5c7228794480bc4ca96ab78b5b5d6 Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Fri, 17 May 2024 14:57:55 -0700 Subject: [PATCH 0883/2849] 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 d03e36693468b..89f80933dd0f1 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 95dde52b1e85b64bcb1d9ebb8c92dddb5bdc93e1 Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Fri, 17 May 2024 14:54:59 -0700 Subject: [PATCH 0884/2849] 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 bb15d824d81bc..a833197d36126 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 c8ae26549d0cdb2fbc98c45d885f1516837ebf09 Mon Sep 17 00:00:00 2001 From: Hao Luo Date: Wed, 10 Jan 2024 15:15:29 +0800 Subject: [PATCH 0885/2849] 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 fd961a550bef8..9f1cac0b30980 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 a85086461c3ee..f55c135f1d4af 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 2bccb1746d84f..02acc1bed5705 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 d789a2519bcc0..0ed3fe2929df0 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 040a93866e978..04a80848d9f4b 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 e8b62fb2c45a7..f3c5b90e90031 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 5ae40c06790a2..0005102b69727 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 ac53b55883e2d..dc578356bf143 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 c211cb347e0af0a4931e0e7af3d93577bcc7af8f Mon Sep 17 00:00:00 2001 From: Yong Cong Sin Date: Fri, 17 May 2024 12:45:57 +0800 Subject: [PATCH 0886/2849] 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 dec4faacc3b73..c95dcedfe8795 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 00e3ea89ddef322d4931991f7fe301a23a0d7009 Mon Sep 17 00:00:00 2001 From: Shawn Nematbakhsh Date: Thu, 14 Mar 2024 12:07:01 -0700 Subject: [PATCH 0887/2849] 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 62b4cf8d46182..09ed1022e2882 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 31c048f4e365330c464967dc5421f8fb39719eb6 Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Mon, 29 Apr 2024 12:32:38 +0200 Subject: [PATCH 0888/2849] 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 7828dfdf65abd..8e1bc6d615cf6 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 1b7fe792e0c52635f371df9c2e14d1f4ce8fcacc Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Thu, 14 Mar 2024 21:04:04 +0100 Subject: [PATCH 0889/2849] 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 a2fb0d22508b2..a9761dc217d0e 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 8e1bc6d615cf6..e4428929e3585 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 32bc8f2221b0fdad8f152ed306ceb361fa24eecc Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Mon, 29 Apr 2024 14:04:27 +0200 Subject: [PATCH 0890/2849] 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 59314c494d7ea..372d4a2901029 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 b65082eb70f6f..920a9f088609e 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 1b32cbf6dc99e..386e81a33f919 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 bd3a2f5bd15ad8e713c572c79bf281af941ef7ef Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Tue, 19 Mar 2024 09:28:18 +0100 Subject: [PATCH 0891/2849] 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 3377273dd9ab6..8fbd3d3af2dcc 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 6a8fcdaf21fb756f4f0b496b575a98f2ac526c50 Mon Sep 17 00:00:00 2001 From: Wilfried Chauveau Date: Wed, 1 May 2024 14:14:50 +0100 Subject: [PATCH 0892/2849] 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 f7753bc5099b1..8f5b70f5f330d 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 18541b631fba62a3f4a2cce51241204500fbd5a7 Mon Sep 17 00:00:00 2001 From: Conor Paxton Date: Fri, 10 May 2024 19:02:04 +0100 Subject: [PATCH 0893/2849] 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 a4976aa909b42..f97e2409c14cd 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 7a599081793c4..203745dc4eeb3 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 0000000000000..6d122ed5d97b7 --- /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 0000000000000..2f7983ca09292 --- /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 0000000000000..529171d1c46da --- /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 3aeefd225078ba92234c0364982260ced68bede4 Mon Sep 17 00:00:00 2001 From: Andy Ross Date: Mon, 31 Jul 2023 12:32:45 -0700 Subject: [PATCH 0894/2849] 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 40906a0a3262b..4c2ce8173ca59 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 0000000000000..e9e60e30fe529 --- /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 7dd4c4d312b572533fbe23169a8144f119ff42d7 Mon Sep 17 00:00:00 2001 From: Andy Ross Date: Tue, 14 May 2024 13:41:49 -0700 Subject: [PATCH 0895/2849] 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 b77effc032bd3..87ad18b54246c 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 f9770ba0c1431804684acdcf685905d41921d695 Mon Sep 17 00:00:00 2001 From: Alberto Escolar Piedras Date: Thu, 16 May 2024 16:06:52 +0200 Subject: [PATCH 0896/2849] 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 4349b0d9d41ce..601719200b031 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 0ec5c9c27bda84e351674480e666e6c4a0695caa Mon Sep 17 00:00:00 2001 From: Alberto Escolar Piedras Date: Thu, 16 May 2024 15:50:45 +0200 Subject: [PATCH 0897/2849] 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 b8ab3afa8feb2..9e5e652ca5ed5 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 7f907ec2f2527700ab0bed7aa34320d0d5fe41aa Mon Sep 17 00:00:00 2001 From: Alberto Escolar Piedras Date: Thu, 16 May 2024 14:55:10 +0200 Subject: [PATCH 0898/2849] 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 994af625bcbba..ff4aef337f25d 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 cb7f20f4364917debf269164d26e70457644e095 Mon Sep 17 00:00:00 2001 From: Alberto Escolar Piedras Date: Thu, 16 May 2024 14:56:17 +0200 Subject: [PATCH 0899/2849] 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 8440d76384d0b..702ff50f85170 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 1c70e8704715cec27a26e85511eb6f18c788a236 Mon Sep 17 00:00:00 2001 From: Jens Rehhoff Thomsen Date: Fri, 17 May 2024 09:41:28 +0200 Subject: [PATCH 0900/2849] 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 dee7de02a8a32..e6f2c85b8b496 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 02d988e784f03a2dbfb3d672399821db350709d0 Mon Sep 17 00:00:00 2001 From: Alberto Escolar Piedras Date: Fri, 17 May 2024 09:59:50 +0200 Subject: [PATCH 0901/2849] 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 305fdfff5f8dc..4648743bbafa7 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 79f1b23cdbecd6a60c97123c292875eec8cf2c74 Mon Sep 17 00:00:00 2001 From: Declan Snyder Date: Fri, 17 May 2024 12:08:15 -0500 Subject: [PATCH 0902/2849] 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 f42f483887749..88ed70f2ba950 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 d8c89f2b08bec4c9d0767b20750f2764529996db Mon Sep 17 00:00:00 2001 From: Ravi Dondaputi Date: Mon, 20 May 2024 12:23:16 +0530 Subject: [PATCH 0903/2849] 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 a25a4b37e505b..ab2637a1271a3 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 2f1a07f3158f0c1f52da2a2d6fc9ccf8b969f20d Mon Sep 17 00:00:00 2001 From: Jerzy Kasenberg Date: Mon, 20 May 2024 13:27:53 +0200 Subject: [PATCH 0904/2849] 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 60d7fb98c56b8..0a90af9a63cf4 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 3666b46b2e557dd56db28bd9358fcde62c63a88d Mon Sep 17 00:00:00 2001 From: Marcin Niestroj Date: Thu, 9 May 2024 13:08:46 +0200 Subject: [PATCH 0905/2849] 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 a9b5fb1b33fb0..af9acd1e40e7e 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 7cf49cc6f750bc12c20fcdf35a09aa0434a349a5 Mon Sep 17 00:00:00 2001 From: Marcin Niestroj Date: Tue, 7 May 2024 14:55:40 +0200 Subject: [PATCH 0906/2849] 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 54b1af8b24613..d8382df4bc779 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 ea13a70274ff345788005945c5e2d2ff04e76e80 Mon Sep 17 00:00:00 2001 From: Marcin Niestroj Date: Tue, 7 May 2024 15:07:38 +0200 Subject: [PATCH 0907/2849] 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 d8382df4bc779..7050c962a14c2 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 7aa8e2f5215727043b1935e708d21321bc80a0c7 Mon Sep 17 00:00:00 2001 From: Marcin Niestroj Date: Mon, 20 May 2024 13:48:08 +0200 Subject: [PATCH 0908/2849] 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 7050c962a14c2..1c7df2af830d9 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 ed19ce0ab0e66951b1dffb1e7633b05ad0b7ea71 Mon Sep 17 00:00:00 2001 From: Emilio Benavente Date: Mon, 15 Apr 2024 15:49:33 +0000 Subject: [PATCH 0909/2849] 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 601719200b031..c6ff13bd6bf9f 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 14158d7bf996d533bf337a4ce48ee314327b7fe0 Mon Sep 17 00:00:00 2001 From: Emilio Benavente Date: Thu, 28 Mar 2024 23:46:08 +0000 Subject: [PATCH 0910/2849] 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 0000000000000..5f6b08f5dc078 --- /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 0000000000000..73f5de72ea2cd --- /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 24c1d3ed70ae4b444986866c668bf9811aa9a510 Mon Sep 17 00:00:00 2001 From: Emilio Benavente Date: Thu, 16 May 2024 00:46:23 +0000 Subject: [PATCH 0911/2849] 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 8fa48abc8c675..f7d15e3cf0cba 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 552008cf42004dd5efa4762c1339c6345c821e3a Mon Sep 17 00:00:00 2001 From: Emilio Benavente Date: Thu, 28 Mar 2024 04:41:52 +0000 Subject: [PATCH 0912/2849] 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 d3a2ee0c02d02..9caa7610b7211 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 0000000000000..116e67f67510a --- /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 0000000000000..9e01b9ec4eba6 --- /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 0000000000000..3077b6e873176 --- /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 0000000000000..e0059ac98b1b9 --- /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 0000000000000..3aeb5db419efb --- /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 0000000000000..ac805348a55d2 --- /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 c2b27eb9841cd..887c6d6980b22 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 1cc1f248a0a8e706b02adefe742d14f7aae9b6ca Mon Sep 17 00:00:00 2001 From: Emilio Benavente Date: Thu, 28 Mar 2024 05:20:54 +0000 Subject: [PATCH 0913/2849] 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 0000000000000..32c3589c59119 --- /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 0000000000000..d14370f54fa7a --- /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 0000000000000..c637334b8b83e --- /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 0000000000000..fd1dec9bc67f6 --- /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 0000000000000..b004d91e60c04 --- /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 0000000000000..0a1c341b0008d --- /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 0000000000000..9a2a7ac4b272b --- /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 0000000000000..69a85bdc43dda --- /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 690c133dd16a8..526bb06bc7d5f 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 f966353b09da04d672d229a1d03a9282e5ad0ea2 Mon Sep 17 00:00:00 2001 From: Emilio Benavente Date: Thu, 2 May 2024 21:58:56 +0000 Subject: [PATCH 0914/2849] 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 0000000000000..68c941f0cd5dc --- /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 7ded97ee85efff82391007fd6cc462feba6b9636 Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Tue, 14 May 2024 13:44:39 -0700 Subject: [PATCH 0915/2849] 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 8cd648a06e3d4..a66ce9d00256a 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 d0ee2b08722ff..10746b49021c2 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 6569ae1798b2e135eb1fe35446269bd90d403661 Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Thu, 16 May 2024 15:01:37 -0700 Subject: [PATCH 0916/2849] 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 51cdd74e4a493..d574f0356c9bf 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 3fb4e703063d84e1994cc7e51d882983f7b28f75 Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Thu, 16 May 2024 14:13:30 -0700 Subject: [PATCH 0917/2849] 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 74f46eaf75536..ba4482ac8f300 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 0f56974c9d61bafcbfae813fa17919d5e40f8cac Mon Sep 17 00:00:00 2001 From: Jordan Yates Date: Wed, 22 May 2024 15:15:09 +1000 Subject: [PATCH 0918/2849] 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 e1db51ebfcd06..d0ea25edc4943 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 d082cd29afb3f34f760cb2d5dccdae7eae82bafb Mon Sep 17 00:00:00 2001 From: Peter Mitsis Date: Tue, 21 May 2024 10:39:22 -0400 Subject: [PATCH 0919/2849] 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 704bfcd9caa9b..a56595252789a 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 7eaca455faf6ff8d9a92c4392da281dab08d0c2b Mon Sep 17 00:00:00 2001 From: Mike Szczys Date: Sun, 19 May 2024 22:28:15 -0500 Subject: [PATCH 0920/2849] 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 b5560650c1b6c..3f73045f899fe 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 34a09aa38f536..60537608357a1 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 ece190c630f88..6ab26c3e8f416 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 dcd8fe9189cf8..85b7cdb371e10 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 6fd6dae73a899..b0925c0fce096 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 5f203922d8c6c4ca54372d32c06c3d2a43991ad6 Mon Sep 17 00:00:00 2001 From: Hake Huang Date: Mon, 20 May 2024 11:08:25 +0000 Subject: [PATCH 0921/2849] 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 d482b24e322a4..ec24e040231d3 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 49d0dd810dc2a990617044b145d6e5c1d6b4d7e2 Mon Sep 17 00:00:00 2001 From: Hake Huang Date: Mon, 20 May 2024 12:38:17 +0000 Subject: [PATCH 0922/2849] 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 f830b49aab547..438b038baea32 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 531c457550ca4792b82f21dc1ceb3aaee23bde60 Mon Sep 17 00:00:00 2001 From: Glenn Andrews Date: Sat, 20 Apr 2024 20:43:43 -0700 Subject: [PATCH 0923/2849] 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 4c1fccd2e3a32..cc9a8b1bce7a5 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 b460b1c13bd6d..aff99963d7888 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 169ee507ec4b4..9b5ee62af7642 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 ba0191272648b..5b5f303630da8 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 ecc107407440a..fb0c95c574f23 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 08844e75aa62b..3e793f984426c 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 2e00dc2d553d9..c78e6fa04a522 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 6296352fb73e8..032dec06f79aa 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 672dab0566288eb9e3383bcf4950523be434bc61 Mon Sep 17 00:00:00 2001 From: Lucas Romero Date: Wed, 22 May 2024 22:59:02 +0200 Subject: [PATCH 0924/2849] 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 ebd18081cc53c..35ee721ddf799 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 1bedf6209b98e680c01bac40937613a3983affc0 Mon Sep 17 00:00:00 2001 From: Reto Schneider Date: Wed, 22 May 2024 15:50:31 +0200 Subject: [PATCH 0925/2849] 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 73e20fba51af3..7dd3f8fd71659 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 f9ee925bb7dacf56e34d68e7e3934d6de0a206b7 Mon Sep 17 00:00:00 2001 From: Piotr Kosycarz Date: Wed, 22 May 2024 15:29:39 +0200 Subject: [PATCH 0926/2849] 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 07e75ec8dd654..e28d55efb3317 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 0268b9358f68b10f8bba33f1d42d170120aa925f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20G=C5=82=C4=85bek?= Date: Wed, 22 May 2024 14:49:39 +0200 Subject: [PATCH 0927/2849] 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 f9f657b4fbb00..5f6436c076d69 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 48230f21c915ec24aa6c81e630525d7068014f68 Mon Sep 17 00:00:00 2001 From: Robert Lubos Date: Wed, 22 May 2024 11:59:17 +0200 Subject: [PATCH 0928/2849] 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 7b98922798d17..986f25150343a 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 1e3f14476b03b92be7afe01ed821824c691a2f14 Mon Sep 17 00:00:00 2001 From: Robert Lubos Date: Tue, 21 May 2024 15:29:01 +0200 Subject: [PATCH 0929/2849] 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 95c41984de2f5..6752f8dd506d8 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 aef0eb275d6fe7440418ac8c65450319b544d5ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Karol=20Laso=C5=84czyk?= Date: Tue, 21 May 2024 13:14:31 +0200 Subject: [PATCH 0930/2849] 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 0000000000000..435e4f4a6ccf8 --- /dev/null +++ b/tests/drivers/sensor/temp_sensor/boards/nrf54l15pdk_nrf54l15_cpuapp.overlay @@ -0,0 +1,3 @@ +temp_sensor: &temp { + status = "okay"; +}; From 49998d93ac78419c8f5d4de33cd065dd0791431b Mon Sep 17 00:00:00 2001 From: Filip Kokosinski Date: Tue, 21 May 2024 08:49:44 +0200 Subject: [PATCH 0931/2849] 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 b96ff81fe8339..f05bf210213cc 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 22a3788b1b80a..bc86125f5d585 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 4cc7753cadef9b3e2874c6bc9476de9b559268af Mon Sep 17 00:00:00 2001 From: Pieter De Gendt Date: Tue, 21 May 2024 08:22:16 +0200 Subject: [PATCH 0932/2849] 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 158321bf4a3f7..315890732c321 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 e17618c00ceee0199b90c0294b7a3be55f14f4b5 Mon Sep 17 00:00:00 2001 From: Dong Wang Date: Mon, 20 May 2024 14:24:16 +0800 Subject: [PATCH 0933/2849] 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 a0e2f5c6732eb..0d1e67147c49a 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 63eccd3b78b62d3f3dd5d697f098647f32b54df6 Mon Sep 17 00:00:00 2001 From: Ioannis Karachalios Date: Sun, 19 May 2024 21:52:43 +0300 Subject: [PATCH 0934/2849] 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 5b003875b93f2..9a9d1edeff995 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 858e8c51f1f42abb0afe62a4d701e69b7a6bd2b1 Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Mon, 13 May 2024 22:09:05 +0200 Subject: [PATCH 0935/2849] 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 39ee5c2451ec6..7b557ebd07b5c 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 fac04490a4b4f4791632c521c9ac2dcb20b43f70 Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Sat, 18 May 2024 08:28:24 +0200 Subject: [PATCH 0936/2849] 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 77c66858a2f77..bab4e3dbca24a 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 55d6e4cb107275e2a9783bc1e94ebcd08ceff146 Mon Sep 17 00:00:00 2001 From: Jason Murphy Date: Sat, 30 Mar 2024 17:13:12 +0000 Subject: [PATCH 0937/2849] 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 0000000000000..af4feece2dc50 --- /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 0000000000000..19d15187acf26 --- /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 0000000000000..b2ff6a1573c14 --- /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 0000000000000..8182bb8b230a0 --- /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 0000000000000..33655bfe4e10b --- /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 0000000000000..69737f64078f8 --- /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 0000000000000..b87eaa2c348f5 --- /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 0000000000000..44b9a4d7d2a3a --- /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 0000000000000..7ac800e43e20c --- /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 0000000000000..ad09b9d3efa90 --- /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 0000000000000..64993139e9007 --- /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 0000000000000..3fdb6f3abf479 --- /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 0000000000000..d78c2b05d342a --- /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 0000000000000..e044f465b9e05 --- /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 02e739873edd240ca2a72aabd18d1fe35ccc2d44 Mon Sep 17 00:00:00 2001 From: Ioannis Karachalios Date: Tue, 23 Jan 2024 22:13:59 +0200 Subject: [PATCH 0938/2849] 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 2e020548610bd..1648343c18f00 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 f64165573556c..afab61994af1a 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 0000000000000..32cb8c94f467e --- /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 0000000000000..37584f99dcc9b --- /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 0000000000000..f55e064683bde --- /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 e1772409ce1037ed5d9dd3dc01a84b8c13b10cba Mon Sep 17 00:00:00 2001 From: Ioannis Karachalios Date: Tue, 23 Jan 2024 22:28:16 +0200 Subject: [PATCH 0939/2849] 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 27290f62c53bf..6da9c88b9a5a9 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 4e2ef1f525cceab3212c109815a1f814fdd2f89b Mon Sep 17 00:00:00 2001 From: Ioannis Karachalios Date: Tue, 23 Jan 2024 22:17:41 +0200 Subject: [PATCH 0940/2849] 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 eb29fd6c55907..942bfe3e07e5f 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 a1539c7887e99..fe589f52fb1cb 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 b820cc2932955231f600d048a6b9feb4b57224b5 Mon Sep 17 00:00:00 2001 From: Ioannis Karachalios Date: Tue, 30 Apr 2024 00:42:29 +0300 Subject: [PATCH 0941/2849] 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 0000000000000..5707f111d97ff --- /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 db67eaa346a8a7ceac9bb45cab08a7b9c2744084 Mon Sep 17 00:00:00 2001 From: Ioannis Karachalios Date: Tue, 23 Jan 2024 22:19:10 +0200 Subject: [PATCH 0942/2849] 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 1347cce2b12b2..901eb064fb128 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 5c1e7d94ac6335260b6ff239b5d947521318dc0c Mon Sep 17 00:00:00 2001 From: Ioannis Karachalios Date: Tue, 30 Jan 2024 12:20:32 +0200 Subject: [PATCH 0943/2849] 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 49ce816d4877e..c8de856aa46f2 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 39f99d84d2fb80d0cabf759cb34b0f36f2d25687 Mon Sep 17 00:00:00 2001 From: Rick Bruyninckx Date: Fri, 19 Apr 2024 14:13:45 +0200 Subject: [PATCH 0944/2849] 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 b8b386d968ac0..7534b3674f69d 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 e3ad40f883557ac99ab0a93834df657ce11322d8 Mon Sep 17 00:00:00 2001 From: Phi Bang Nguyen Date: Sat, 11 May 2024 21:07:24 +0200 Subject: [PATCH 0945/2849] 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 85f08920119fa..84b5558390e85 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 ea02b93eea35afef32ebb31f49f8e79932e7deee Mon Sep 17 00:00:00 2001 From: Phi Bang Nguyen Date: Sat, 11 May 2024 21:08:41 +0200 Subject: [PATCH 0946/2849] 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 77022d037d898..2e8e4d505084a 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 e79f7135af386c3d02619a43cd5f35f74d3a4cff Mon Sep 17 00:00:00 2001 From: Roger Wang Date: Thu, 23 May 2024 11:21:56 +0800 Subject: [PATCH 0947/2849] 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 0cb3e29df1a0a..ffc72bcb863cf 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 d830446c91b1c819fa58b5ecb6fc5f31e8064f85 Mon Sep 17 00:00:00 2001 From: Tomi Fontanilles Date: Wed, 22 May 2024 15:41:00 +0300 Subject: [PATCH 0948/2849] 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 d75b34a810988..c351f97f906a5 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 5bb8cb5bd94ae..67ee755c25eca 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 ced9fba95c9d68e7354bd9c589ac81844784abd8 Mon Sep 17 00:00:00 2001 From: Ali Hozhabri Date: Fri, 17 May 2024 10:53:20 +0200 Subject: [PATCH 0949/2849] 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 be9fa9523a539..f10fea5e293b8 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 d84b9fae9cda4..23eda67338aec 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 a12712dda8a1e..f08afe0d21d13 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 ee669d084f6f675c54fad210d6630eca2a242eba Mon Sep 17 00:00:00 2001 From: Simon Hein Date: Thu, 23 May 2024 10:03:11 +0200 Subject: [PATCH 0950/2849] 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 09ed1022e2882..fe4526c16f331 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 991b3623b014408bd5c3f63b3ee492c33103810a Mon Sep 17 00:00:00 2001 From: Kai Vehmanen Date: Wed, 22 May 2024 13:14:50 +0300 Subject: [PATCH 0951/2849] 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 04503ca35e8f2..d1a315e5f1c38 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 765b244c27d642f06c9c813737a22e1a8e0ddfcb Mon Sep 17 00:00:00 2001 From: Aleksander Wasaznik Date: Tue, 21 May 2024 16:34:44 +0200 Subject: [PATCH 0952/2849] 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 209292320dea8..487f5c644b850 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 56cb28e109322..f2aa8a3b4a804 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 79962c3168911..0394282164070 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 6149378ecb616..9f1ff58904e6d 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 c266b4739a4c5..e41d568dff818 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 551a41ebaadd3..40d776ba4cb2d 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 3083eb767d64c..05ccb6f39457e 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 b856e60fcf348..2e8e50c8f7fd6 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 a07ffbb6efb95..3dc53ba0d29eb 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 dbee4d4f3c3e3..7cdb32b9cd223 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 60ed49eb229ca..e421812d60e17 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 df5f4c1bffdd7..13637090788f5 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 03d706b6214c9..ab5a13bcf294e 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 78c6674ff11d4..af4a62820e716 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 7bf1c2b09e860..1b4b23f71b728 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 7fd32dccfca98..824b5eab8fa34 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 1dc6ec5f96ef2..12ab2f875814b 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 65762a174c2fa..81042fb740b82 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 2d054ed903179..80583e565dc44 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 1461ab69a9c4a..b351f8b3a800c 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 146195a647aec90de596b42780db2d7d4d090d87 Mon Sep 17 00:00:00 2001 From: Piotr Kosycarz Date: Tue, 21 May 2024 14:15:59 +0200 Subject: [PATCH 0953/2849] 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 d3400f78468bb..8ce0e32cea71f 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 0af906a533e36a69938567d6294c559366c5684e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20LOCHE=20-=20MAKEEN=20Energy?= Date: Tue, 14 May 2024 10:59:47 +0200 Subject: [PATCH 0954/2849] 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 68caf1786da87..91159c918c7d1 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 e1ce0aefff75a1d20703b5971d840d97344c5036 Mon Sep 17 00:00:00 2001 From: Yong Cong Sin Date: Sat, 18 May 2024 16:45:44 +0800 Subject: [PATCH 0955/2849] 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 401060f989cce..0e9fc7280a9e6 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 aff99963d7888..2ca4126c6cb2a 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 0000000000000..a8685cf4ddd93 --- /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 0000000000000..a2c767c44613f --- /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 d9cbc68b975b8..200e3bcb38662 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 5fd5d9bfd5d2c..3721261e3d62e 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 0000000000000..5e128c8bc3abe --- /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 0000000000000..98b865a440344 --- /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 0000000000000..a99b85e7aa521 --- /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 c1a925de985fe78587015116d0fee672586d4c7d Mon Sep 17 00:00:00 2001 From: Yong Cong Sin Date: Sat, 18 May 2024 16:49:42 +0800 Subject: [PATCH 0956/2849] 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 a85dcfbd82d84..1f3676252c66f 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 2ca4126c6cb2a..d30186c7c7307 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 3721261e3d62e..819d70343530f 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 9f29790f95cdf..84e00ecbf5910 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 eafc4eff04a56f2d6a9de028b8214815979625e9 Mon Sep 17 00:00:00 2001 From: Yong Cong Sin Date: Tue, 21 May 2024 16:06:07 +0800 Subject: [PATCH 0957/2849] 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 8efffd3737193..31ead071eb9c2 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 2a3d9d0d9078136912ffeef4a9f125a8206ab6f9 Mon Sep 17 00:00:00 2001 From: Yong Cong Sin Date: Sat, 18 May 2024 17:36:43 +0800 Subject: [PATCH 0958/2849] 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 84ff767508ed1..92ef0d8a3da8b 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 d30186c7c7307..334d12ed0535f 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 84e00ecbf5910..f57e8b41048b4 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 c118cd5a1342865715009c7b6e5e08f28a694153 Mon Sep 17 00:00:00 2001 From: Yong Cong Sin Date: Tue, 21 May 2024 12:07:39 +0800 Subject: [PATCH 0959/2849] 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 1f3676252c66f..e0c97b642ba3d 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 370386d4af96b..a2aea6574987e 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 819d70343530f..00243f49be967 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 48a4269800d69885de174bed4a66e240c89d8a14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fin=20Maa=C3=9F?= Date: Thu, 16 May 2024 13:15:44 +0200 Subject: [PATCH 0960/2849] 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 fe4526c16f331..a980ed92529dc 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 d7afd88e71c2d0487efbf3cfefa84610e11f0f95 Mon Sep 17 00:00:00 2001 From: Hao Luo Date: Fri, 22 Dec 2023 18:47:22 +0800 Subject: [PATCH 0961/2849] 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 9f1cac0b30980..c6a0f70f90741 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 f55c135f1d4af..09275d9e5f82b 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 02acc1bed5705..902a909cc9f2c 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 0ed3fe2929df0..275c1efb6ef4c 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 67df6c5647f69..2036102138dd1 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 0005102b69727..5935352068da8 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 dc578356bf143..d4063fb98cf85 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 7ae915c4d2155..63399c06cae7c 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 266fb4c73a293b637b368ea3faf7d6afed337024 Mon Sep 17 00:00:00 2001 From: Hao Luo Date: Thu, 16 May 2024 11:59:35 +0800 Subject: [PATCH 0962/2849] 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 aa95ff80c9adb..b7ce6461e359e 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 dfc2f59de3d70..7f4d7145877fb 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 e58ebe12f473b1b1293fce6c4962bceed1bb7b52 Mon Sep 17 00:00:00 2001 From: Valerio Setti Date: Fri, 3 May 2024 06:00:05 +0200 Subject: [PATCH 0963/2849] 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 35200a9d2f4f2..e6121ed9173b1 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 0000000000000..e0278f761b889 --- /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 6a731d4f61ac7..2750bab09bc15 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 e82e7f95ac14b..090559e204923 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 c4e1b56ef9746da4da4526729a526c0d031416b7 Mon Sep 17 00:00:00 2001 From: Valerio Setti Date: Mon, 6 May 2024 10:41:16 +0200 Subject: [PATCH 0964/2849] 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 0000000000000..fd5d21c9ad945 --- /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 2adb4cac173292ded6a148af046583847bd6c0f8 Mon Sep 17 00:00:00 2001 From: Valerio Setti Date: Mon, 13 May 2024 10:16:42 +0200 Subject: [PATCH 0965/2849] 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 eec38e05089fb..6117424f8a4c9 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 2750bab09bc15..dc94e3d75f3d7 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 f308a5aefaf5b..a7ac8db8f2e14 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 74e377569b338..88fccf0961cf5 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 12ff947568679765f1b84cca4c2967bc67f4bd07 Mon Sep 17 00:00:00 2001 From: Valerio Setti Date: Mon, 13 May 2024 14:35:37 +0200 Subject: [PATCH 0966/2849] 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 e6121ed9173b1..7562032bf3d4e 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 6117424f8a4c9..b3e620d94b933 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 fd5d21c9ad945..fe6d0b79b4655 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 1c11a997cf7ff..e8f860fa2f646 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 a1a7c9081a8bddab31346cac4ec091ba43d23819 Mon Sep 17 00:00:00 2001 From: Valerio Setti Date: Tue, 14 May 2024 11:58:48 +0200 Subject: [PATCH 0967/2849] 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 30ddce44eb176..b5eececbc9e36 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 210e08be5d423099f3fbbb855e77cded1d742913 Mon Sep 17 00:00:00 2001 From: Valerio Setti Date: Wed, 15 May 2024 08:28:24 +0200 Subject: [PATCH 0968/2849] 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 b3e620d94b933..b692c18e32359 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 88fccf0961cf5..796982280a882 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 ffe79b552255cc6258dad702b86ee58120e45dee Mon Sep 17 00:00:00 2001 From: Valerio Setti Date: Thu, 16 May 2024 11:06:08 +0200 Subject: [PATCH 0969/2849] 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 1bbd6b6ddd7d8..7ebdc9d76a9ae 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 06870146e66e24425f1bd3a8da50d15b24744e0e Mon Sep 17 00:00:00 2001 From: Morten Priess Date: Mon, 11 Mar 2024 14:41:21 +0100 Subject: [PATCH 0970/2849] 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 4038a04486ec6..8db6c3a31a482 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 fcc37fc52d873..96b932403aa14 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 f6c68436b5eb0..41a6d0a303704 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 38a92f40c9ec2..b4ecfd52ca27b 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 3656c1b14c1eccc95386f8bb94661cc5ce25c020 Mon Sep 17 00:00:00 2001 From: "Mike J. Chen" Date: Thu, 29 Feb 2024 17:46:56 -0800 Subject: [PATCH 0971/2849] 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 ccf492f0255c3..f0b4df33590f4 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 85bc3e64619deec688529ac52d46772db75cd511 Mon Sep 17 00:00:00 2001 From: Jeppe Odgaard Date: Fri, 17 May 2024 19:35:03 +0200 Subject: [PATCH 0972/2849] 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 60ce1a2533a62..d1940b8d606ca 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 11920e35a00e30ea42bc24d05b253dc5433cedca Mon Sep 17 00:00:00 2001 From: Valerio Setti Date: Tue, 21 May 2024 10:29:01 +0200 Subject: [PATCH 0973/2849] 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 dc94e3d75f3d7..45bc81f35f20c 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 8c8e2f6243f147953ce3fadb999c4e2a5faf4f5e Mon Sep 17 00:00:00 2001 From: Stephanos Ioannidis Date: Thu, 23 May 2024 22:08:03 +0900 Subject: [PATCH 0974/2849] 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 bb12e241930e5..55cf8de629759 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 e0c955eba36683139a49276507870a993507fa9e Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Thu, 23 May 2024 14:43:34 -0700 Subject: [PATCH 0975/2849] 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 0282e87b3bb7f..af103ceb24f75 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 d3c0dfbf3699fc98e01909ecf9a2ee834d7f4d41 Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Mon, 20 May 2024 12:13:00 +0200 Subject: [PATCH 0976/2849] 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 6b0186e55d859..4954b75fd9b07 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 98c121d2623e16717dc8e162f7ab748473430289 Mon Sep 17 00:00:00 2001 From: Luis Ubieda Date: Wed, 22 May 2024 16:52:13 -0400 Subject: [PATCH 0977/2849] 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 cf2e4c06312d9..96977c134b700 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 4ae093eaf01d727fae59a5d8f075bc232810cc89 Mon Sep 17 00:00:00 2001 From: Luis Ubieda Date: Thu, 23 May 2024 07:26:16 -0400 Subject: [PATCH 0978/2849] 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 96977c134b700..7f5d5becf0472 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 04e38ae176d8aab88c6b41b81959762a3a2ca573 Mon Sep 17 00:00:00 2001 From: Emil Gydesen Date: Wed, 22 May 2024 13:03:33 +0200 Subject: [PATCH 0979/2849] 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 860434d428af4..38f9f54607837 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 e6f2c85b8b496..dbaffb0c2ffec 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 8da6984ee55d6..f2e7127b406bd 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 be51694fd1ad2..efb8dbc3e1fde 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 205feceb0b849..586ed60046919 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 e0ff7dd306e08..85460d10fdd5c 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 1040f0cd21483..94f334ff54d84 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 9b584966ce77f..a927c82e16c2b 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 63818ddbeea5b..1bfcc55977af0 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 6764b023a5ad2..b88c724a2225a 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 5ffb94d785f0d..f4dab65bbb291 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 2c0019e234c21..3cce613dd9863 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 db2a76fbab60f..6a39afb6879a7 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 cc602a694140e772e5f5c0b4a21c6dabba25605a Mon Sep 17 00:00:00 2001 From: Emil Gydesen Date: Wed, 22 May 2024 13:03:49 +0200 Subject: [PATCH 0980/2849] 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 782195e3bce2c..468946f5a5b4f 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 7919b4afcc954..cabd365ab5d00 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 cc0f0a5fc1bc9..6aa261cb3307c 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 90e201b135263..57dc3ac2dbc0a 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 34b172ad8ab93..215c3a41a4c01 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 1d686a31016e5..b2ca57556ce2a 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 fb5cf85e6b6bc..b445d8d99faee 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 165b6add6838c..e54412c55b0ca 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 2e8f104425ff7524c230d62f0923329f700a6f2a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20G=C5=82=C4=85bek?= Date: Wed, 22 May 2024 11:23:06 +0200 Subject: [PATCH 0981/2849] 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 15a1f076063d2..6b470c77733ce 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 e9256135d6747221bbc3d15bf81d7aa9ebc7aead Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20G=C5=82=C4=85bek?= Date: Wed, 22 May 2024 11:29:56 +0200 Subject: [PATCH 0982/2849] 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 b19abb3dfbb31..b40e14f516f85 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 9d5357fba8b27..4988276ffc91d 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 fc355af1edca6..fbc79906a2c40 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 baf57d4665381..a09056ae2d3d3 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 0000000000000..1403921ac22c5 --- /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 f38f88dc658dc..b9ada56b5ab2f 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 a2ce85d5f9b2f..1976df32233c7 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 0000000000000..ec3c11fea1b36 --- /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 6aec56a0ab4a6..5ed02f4051ff0 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 af3c8b973ede41f34bef107a71c3bc9de676b20c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Chru=C5=9Bci=C5=84ski?= Date: Wed, 22 May 2024 07:39:21 +0200 Subject: [PATCH 0983/2849] 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 a5c41a63ab97c..a12bf607555d4 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 b34e94f36295fe77000315f2f3f7320d540491a1 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Tue, 21 May 2024 21:47:52 -0400 Subject: [PATCH 0984/2849] 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 18944dc78a06c..9860070542edf 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 44f86dd67d168f3ddbb9c41670d7d9a96859a6c0 Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Tue, 21 May 2024 20:51:02 +0200 Subject: [PATCH 0985/2849] 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 db1706de1d68b..0847e9b2454b1 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 c6fd2a1ddfa5d689e28bb7887c970d47a6e6a9d0 Mon Sep 17 00:00:00 2001 From: Marcin Niestroj Date: Tue, 21 May 2024 18:53:58 +0200 Subject: [PATCH 0986/2849] 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 3e7a22923bc3c..85bbf9a6feba0 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 33665348c2085eefda2dfecf1f80e49b488dda87 Mon Sep 17 00:00:00 2001 From: Gerard Marull-Paretas Date: Wed, 15 May 2024 12:49:43 +0200 Subject: [PATCH 0987/2849] 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 a50233ab38c7f..cbd92c734604b 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 2958f691bb508e642a41b731f7df9d31ee8500e0 Mon Sep 17 00:00:00 2001 From: Ioannis Karachalios Date: Tue, 21 May 2024 19:25:47 +0300 Subject: [PATCH 0988/2849] 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 480ee2158b206..da0e5e154cec1 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 71a5f1b9fdcd14c2b766d758031d25e127e939a0 Mon Sep 17 00:00:00 2001 From: Ioannis Karachalios Date: Tue, 21 May 2024 19:30:40 +0300 Subject: [PATCH 0989/2849] 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 ab12cc23a0083..2467810861735 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 62f8f160ada4a3239217ff9ea00dfb489623fdaf Mon Sep 17 00:00:00 2001 From: Ioannis Karachalios Date: Tue, 21 May 2024 19:31:24 +0300 Subject: [PATCH 0990/2849] 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 80f9ef1510c5d..fecb7b07491e2 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 26f3073b9a30c8916d97c9667daff34e1f500be4 Mon Sep 17 00:00:00 2001 From: Aleksander Wasaznik Date: Thu, 16 May 2024 15:16:05 +0200 Subject: [PATCH 0991/2849] 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 776fe9ff4b38c..13123a2306ca4 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 9a11cee54ff3b..38a8bde83f599 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 0faa6713d59b0..1223a6797e0ba 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 0833c4e2f8b3f..6a458dc0d0fc6 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 2171b6c1aff61..60854912903de 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 949192c407019..8cf802455f781 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 72daba4465b76..32eb09f4b1bce 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 b94f2cf96e020..424c7e17d44b2 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 cf8ce038c6b95..2f06d5833e8b2 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 ca95b727cb670..713e89afe3de3 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 c60562bcd512b..d04269b391339 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 b2a6e34fc0034..1fc34b8f09c7c 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 23f02909a8ad8..82570b59e4128 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 e879cd050297a928c2902e9af00e1f8d54302468 Mon Sep 17 00:00:00 2001 From: Yong Cong Sin Date: Wed, 15 May 2024 22:56:31 +0800 Subject: [PATCH 0992/2849] 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 972f62c7fe3fe..7f9c9b3e50c57 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 eb37b8620b1c872b0cdc6dc4829c8b89abb39698 Mon Sep 17 00:00:00 2001 From: Yong Cong Sin Date: Wed, 15 May 2024 23:36:52 +0800 Subject: [PATCH 0993/2849] 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 7f9c9b3e50c57..0000040f18afa 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 c13105750d007e7e75a4ab6d385df7a3b6be1b9c Mon Sep 17 00:00:00 2001 From: Yong Cong Sin Date: Fri, 17 May 2024 11:18:14 +0800 Subject: [PATCH 0994/2849] 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 c13f888a28507..9cbca8ea36f38 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 4e7168028beeb380c36c579901094cc253f35dec Mon Sep 17 00:00:00 2001 From: Yong Cong Sin Date: Thu, 23 May 2024 10:54:36 +0800 Subject: [PATCH 0995/2849] 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 0000040f18afa..e175d6d05fa51 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 e993e994ea5966863746a27a85af3e2e2e75ef91 Mon Sep 17 00:00:00 2001 From: Yong Cong Sin Date: Thu, 23 May 2024 10:58:01 +0800 Subject: [PATCH 0996/2849] 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 c95dcedfe8795..c6b45e3e173a6 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 e175d6d05fa51..7edefe69ea110 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 2bd6b5c5b892d..b227fd72002f8 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 dd7f1f39c6d18..e1a2bc5c3e401 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 9cbca8ea36f38..7a01bec9978c7 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 212ef5e056556..2d6df21251a83 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 7d23bd2859ab91889d74213ad10bfaaf51546cd1 Mon Sep 17 00:00:00 2001 From: Tomasz Chyrowicz Date: Wed, 15 May 2024 15:19:01 +0200 Subject: [PATCH 0997/2849] 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 4e71c0be76945..0e429ab3a9dd2 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 8ba222c56a424fe051da3ea42f8d592af64279a7 Mon Sep 17 00:00:00 2001 From: Piotr Kosycarz Date: Tue, 14 May 2024 11:53:46 +0200 Subject: [PATCH 0998/2849] 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 401bbf517357f..c9ebfbadde1d3 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 18c73de93d53b1c7f81a6c9d5b1a1353cb917423 Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Mon, 13 May 2024 22:09:05 +0200 Subject: [PATCH 0999/2849] 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 7b557ebd07b5c..1fa3ea167d738 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 deabfa3c3a215bb89f81fa279e42c05efed3d52c Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Mon, 6 May 2024 22:05:22 +0200 Subject: [PATCH 1000/2849] 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 f0b4df33590f4..79d6410f99439 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 a655deb04618342dec9fc28b1e9232518f0d357a Mon Sep 17 00:00:00 2001 From: Alex Bellon Date: Wed, 1 May 2024 18:50:00 +0000 Subject: [PATCH 1001/2849] 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 33ebd3f3d9b79..77f39e79ea1f2 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 c026b55fe5699f37d652d7c10eecb492a4d66150 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Chru=C5=9Bci=C5=84ski?= Date: Fri, 12 Apr 2024 11:59:18 +0200 Subject: [PATCH 1002/2849] 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 f1b1e52c7c51e..b2524e9440916 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 1af474b575afbd05c390e025035c2a4d44027f9a Mon Sep 17 00:00:00 2001 From: Robert Hancock Date: Mon, 5 Feb 2024 16:51:15 -0600 Subject: [PATCH 1003/2849] 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 79d6410f99439..1c46a9103ef57 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 4c5eb92650df3b86c888162ae596270ea62c5318 Mon Sep 17 00:00:00 2001 From: Andrew Davis Date: Mon, 11 Mar 2024 11:37:14 -0500 Subject: [PATCH 1004/2849] 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 2d58beb4b9289..8229a213ed563 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 ba3b57e7ad824..f3254ebb676a7 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 39863b66bdfb0843544440cb1feebd5b3b223e62 Mon Sep 17 00:00:00 2001 From: Andrew Davis Date: Mon, 11 Mar 2024 12:21:46 -0500 Subject: [PATCH 1005/2849] 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 8229a213ed563..53e38f185f0a3 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 f3254ebb676a7..dc577fafa7edc 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 8bc1a475d081b..c8d12092ace05 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 051dc14bb6576d78432b007dcfdd764e6d8ad373 Mon Sep 17 00:00:00 2001 From: Celina Sophie Kalus Date: Fri, 1 Mar 2024 11:06:22 +0100 Subject: [PATCH 1006/2849] 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 1d5c65cded770..ce0cbbc6e9c5c 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 7f00324ba474a..ba72f0e894f58 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 0000000000000..586061bccbc69 --- /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 0000000000000..a1e9ca92607f0 --- /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 e1ec8f588492e1e848a66b2ad854ae53121ac416 Mon Sep 17 00:00:00 2001 From: Celina Sophie Kalus Date: Fri, 1 Mar 2024 11:10:42 +0100 Subject: [PATCH 1007/2849] 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 0000000000000..50226f3118242 --- /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 e178d21b96ece9d92b4bcc10f0170543ba471938 Mon Sep 17 00:00:00 2001 From: Celina Sophie Kalus Date: Thu, 2 May 2024 16:09:01 +0200 Subject: [PATCH 1008/2849] 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 813ca865f97b3..c8df24f2572cf 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 9e0d4ef88fb45a96bdc90771c5dfba9df6917e18 Mon Sep 17 00:00:00 2001 From: Celina Sophie Kalus Date: Thu, 2 May 2024 14:28:03 +0200 Subject: [PATCH 1009/2849] 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 d10fa6c8bf6bb..4556b7687f33c 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 7da8ca3113e479afd597becb163dc17ad130c8cd Mon Sep 17 00:00:00 2001 From: Celina Sophie Kalus Date: Thu, 2 May 2024 14:30:17 +0200 Subject: [PATCH 1010/2849] 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 4556b7687f33c..6d2d2216a3f9e 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 3290da8f1d0b4dc4f804c8ca55940e0b260397c5 Mon Sep 17 00:00:00 2001 From: Celina Sophie Kalus Date: Thu, 2 May 2024 14:35:18 +0200 Subject: [PATCH 1011/2849] 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 ca0ce8a8cff85..43effdcf6ff5e 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 d0849e37ddef1..2de1b5072e1c3 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 0000000000000..acba758575a87 --- /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 0000000000000..52a2facb9bf3a --- /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 0000000000000..110236f8fbde8 --- /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 0000000000000..4b8d6f59f4f53 --- /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 6d2d2216a3f9e..d3a7e695b9125 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 d0d79b8f24084..b1f0947aff7c4 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 59bfe591eff4fcd44306e6936b58a8c7ba7c3938 Mon Sep 17 00:00:00 2001 From: Celina Sophie Kalus Date: Thu, 2 May 2024 14:50:41 +0200 Subject: [PATCH 1012/2849] 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 d279843dacd24..3ca0508ab8c64 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 b8d7e17c29a36..c89a6f7b3f78b 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 0000000000000..acba758575a87 --- /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 0000000000000..d86cbbc2d42ea --- /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 9c19a0e8b4695..9bc1c67a61c08 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 0000000000000..110236f8fbde8 --- /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 0000000000000..c39e05aeb9c8d --- /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 bbbb2865c3f7186d88f956fb3a40a571d6edb801 Mon Sep 17 00:00:00 2001 From: Celina Sophie Kalus Date: Thu, 2 May 2024 14:53:11 +0200 Subject: [PATCH 1013/2849] 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 591d68b791630..1ba052502ac15 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 bd6bb64d8add362cc7ea460afdbc25c34c67b838 Mon Sep 17 00:00:00 2001 From: Jerzy Kasenberg Date: Wed, 22 May 2024 13:31:35 +0200 Subject: [PATCH 1014/2849] 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 4ab03f5d956e0..9726b6d9b9af7 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 1339ce4bf0350667b8749416258d400cc8257a3b Mon Sep 17 00:00:00 2001 From: Ping Wang Date: Tue, 7 May 2024 14:04:19 +0200 Subject: [PATCH 1015/2849] 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 cc96141213153..4e67d59487785 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 e3f044cacb6fd..6ac3fd8c5f527 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 cc42d16b1c6bb26dcabe754a485a7b2d0ca8ac02 Mon Sep 17 00:00:00 2001 From: Kapil Bhatt Date: Wed, 22 May 2024 14:45:28 +0530 Subject: [PATCH 1016/2849] 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 0442a91c2f2fb..8c2b61fa93640 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 1ed18ad5b2a50a5dee7245832bf0245512de6201 Mon Sep 17 00:00:00 2001 From: Alexander Sarmanow Date: Fri, 5 Apr 2024 11:15:03 +0200 Subject: [PATCH 1017/2849] 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 cdda1ac13f729..fa37e5f76de31 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 cdda1ac13f729..fa37e5f76de31 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 84898f62a3f4a6169bcec94a8977bbc422a51303 Mon Sep 17 00:00:00 2001 From: Nikolay Agishev Date: Thu, 18 Jan 2024 15:11:56 +0300 Subject: [PATCH 1018/2849] 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 24d5d53dc1b22..f41976c8c9800 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 ccedcd1ac04c8e6436b764a6f411e4590ee35e5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20G=C5=82=C4=85bek?= Date: Fri, 5 Apr 2024 15:39:30 +0200 Subject: [PATCH 1019/2849] 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 9415149c89f99..77a8e81fe0cff 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 418210dbf3573bd26b76be9b77d2b1146bb7859c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20G=C5=82=C4=85bek?= Date: Fri, 5 Apr 2024 16:01:15 +0200 Subject: [PATCH 1020/2849] 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 77a8e81fe0cff..a92e54edb2766 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 48665f2636208e71892f5203f39d427f74d19901 Mon Sep 17 00:00:00 2001 From: Maciej Perkowski Date: Tue, 19 Dec 2023 15:28:24 +0100 Subject: [PATCH 1021/2849] 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 1bbfd331debd0..edbbbf2d923be 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 301055dec086a6519e4f7028ec806eb12f6054ea Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Mon, 19 Feb 2024 15:10:42 -0800 Subject: [PATCH 1022/2849] 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 d9595311a974a..15b7128aea5ed 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 2e260eb2f9cf7..0f3cf6a3815bd 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 e728adffd276028934f008ec890ff0c19c32aeb2 Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Tue, 19 Mar 2024 21:31:41 +0000 Subject: [PATCH 1023/2849] 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 0f3cf6a3815bd..70a519f24ba32 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 c335cb542c242a3671dede827b7c4f95a10993b6 Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Mon, 19 Feb 2024 23:23:48 -0800 Subject: [PATCH 1024/2849] 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 70a519f24ba32..9fd884904d9c4 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 b496d0e52d3c0292f969909a58c038c1524114b9 Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Tue, 19 Mar 2024 21:38:26 +0000 Subject: [PATCH 1025/2849] 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 9fd884904d9c4..08f416e0326a3 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 693b65583c88a15891c9ca6e573c34f62d588926 Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Tue, 19 Mar 2024 21:40:52 +0000 Subject: [PATCH 1026/2849] 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 3f816c6914657..50b4582507ac0 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 f54232e9124dd1318190fdf7c4897d4d33deca66 Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Tue, 19 Mar 2024 21:42:46 +0000 Subject: [PATCH 1027/2849] 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 08f416e0326a3..4dadb89378af6 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: Sat, 18 May 2024 22:31:43 +0200 Subject: [PATCH 1028/2849] 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 1a5dc09125b60..6d0ef856a66f0 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 b0dceffacc1f3917ce46803bc7e4cf8f423a6a1b Mon Sep 17 00:00:00 2001 From: Babak Arisian Date: Wed, 15 May 2024 15:11:11 +0200 Subject: [PATCH 1029/2849] 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 4274279890039..a7d248026a18f 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 38f9f54607837..b08c4f96c9afb 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 164a52afa5ee1..619f52c7abc2e 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 8d537557dae96..1a73258d2e8a3 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 4ffa953994032..b045ecbcda4c6 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 30afd5ae093c3..cd597c65de162 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 cabd365ab5d00..04fe1ce07a670 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 362588037efcbbb50557e5e3cb19d799165bf5c6 Mon Sep 17 00:00:00 2001 From: Francois Ramu Date: Tue, 14 May 2024 16:32:08 +0200 Subject: [PATCH 1030/2849] 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 7da5c991a49a8..415818b7db301 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 2499a4b226f3dfb78cd2dc1e73f7da6d13453e6a Mon Sep 17 00:00:00 2001 From: Francois Ramu Date: Wed, 15 May 2024 17:34:46 +0200 Subject: [PATCH 1031/2849] 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 2cdda0158f3e8..1dd6002c3b2e2 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 6db2c2c2c1d1d971dc420baa4184e4d981f46bca Mon Sep 17 00:00:00 2001 From: Francois Ramu Date: Tue, 21 May 2024 16:07:43 +0200 Subject: [PATCH 1032/2849] 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 1dd6002c3b2e2..024669a1a9498 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 ab50b375e5a347de5ccaf3191764709c25479130 Mon Sep 17 00:00:00 2001 From: Alberto Escolar Piedras Date: Fri, 17 May 2024 10:02:45 +0200 Subject: [PATCH 1033/2849] 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 7389f7de33e70..7529d301e2ed1 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 9c874f0b93f70bbe296716a50d952189b5526324 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20G=C5=82=C4=85bek?= Date: Wed, 22 May 2024 16:08:34 +0200 Subject: [PATCH 1034/2849] 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 d187d4a5f99d2..4bbf47524a804 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 ca6f2d6ba5965130a0168e8487da430f314f867e Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Thu, 23 May 2024 15:13:23 -0700 Subject: [PATCH 1035/2849] 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 a980ed92529dc..ad197d1cf376d 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 2654fdc6bacb74225098bf5e565b719e1978c020 Mon Sep 17 00:00:00 2001 From: Ederson de Souza Date: Wed, 22 May 2024 13:18:35 -0700 Subject: [PATCH 1036/2849] 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 d742f198530d3..899936cda61ab 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 a6e17b34f689f7925f1e68cd86059932af337a8f Mon Sep 17 00:00:00 2001 From: Andrzej Kaczmarek Date: Wed, 22 May 2024 20:24:39 +0200 Subject: [PATCH 1037/2849] 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 1b325c47eb809..80a497acff542 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 9ef16f55cdc8254ca3490ffac83f6b31aef5a781 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20B=C3=B8e?= Date: Wed, 22 May 2024 15:11:33 +0200 Subject: [PATCH 1038/2849] 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 028bcfccd54b1..75dbe78409793 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 66157d79fb36f..5c765a8a89633 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 66157d79fb36f..5c765a8a89633 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 66157d79fb36f..5c765a8a89633 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 aa2789dd45e87..8d3dce3b38005 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 afbaaf241d87262136c367e1df54241468bb6d70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20B=C3=B8e?= Date: Fri, 24 May 2024 11:43:08 +0200 Subject: [PATCH 1039/2849] 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 0000000000000..94e0d719af4ef --- /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 0000000000000..5c765a8a89633 --- /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 0000000000000..5c765a8a89633 --- /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 50aaaa30c28c49fb5b79ff7236989992ebc484b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20B=C3=B8e?= Date: Wed, 22 May 2024 15:12:17 +0200 Subject: [PATCH 1040/2849] 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 a15ead439534b..b3c44f4c6b732 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 2c19d3ea9240a3508b63424f1aad28521c5c67ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20B=C3=B8e?= Date: Wed, 22 May 2024 15:12:57 +0200 Subject: [PATCH 1041/2849] 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 b3c44f4c6b732..93bfaa5db53d7 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 90332b9a0b3d800c2fe28ab7672e36598e204113 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20B=C3=B8e?= Date: Wed, 22 May 2024 15:13:58 +0200 Subject: [PATCH 1042/2849] 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 93bfaa5db53d7..0b8eb1c549a87 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 80209e4fd0b217d8587704cab7ed82999f6549ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20B=C3=B8e?= Date: Wed, 22 May 2024 15:14:35 +0200 Subject: [PATCH 1043/2849] 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 0000000000000..2fa2ec36428da --- /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 24b15763bdc8f..831479ea95037 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 5ead91d0991bc26b3b95a3bb3b924f76a82716b4 Mon Sep 17 00:00:00 2001 From: Andrzej Kaczmarek Date: Wed, 22 May 2024 11:18:54 +0200 Subject: [PATCH 1044/2849] 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 6da9c88b9a5a9..30f9820f2b004 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 d65d298280f9d75e6259dd24146297476804b135 Mon Sep 17 00:00:00 2001 From: Swift Tian Date: Tue, 21 May 2024 18:30:35 +0800 Subject: [PATCH 1045/2849] 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 9132dd9c14d48..6db6f0aee1b5a 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 e154d43a52531..02d6b1d646599 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 cf5a273aa502b99de3d742818c5dc98cdb613eb5 Mon Sep 17 00:00:00 2001 From: Swift Tian Date: Wed, 22 May 2024 14:09:35 +0800 Subject: [PATCH 1046/2849] 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 81a9aca7dbd98..66ef801fe376c 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 5df8ca2965a9de03032d15039e4daadf8f8a2351 Mon Sep 17 00:00:00 2001 From: Swift Tian Date: Wed, 22 May 2024 14:12:29 +0800 Subject: [PATCH 1047/2849] 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 2fb7bedcac8d6..156aa046560ec 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 2a639c91483e7cdda05a88d7846ef0f6fad69546 Mon Sep 17 00:00:00 2001 From: Swift Tian Date: Wed, 22 May 2024 14:13:55 +0800 Subject: [PATCH 1048/2849] 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 b5a8eb94dc8e3..a8d13b8a03580 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 12180d6082d1ee3566b317a81776eb2c38ad8465 Mon Sep 17 00:00:00 2001 From: Swift Tian Date: Thu, 23 May 2024 16:43:10 +0800 Subject: [PATCH 1049/2849] 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 a5d6e2e831e7f..4930ab3bc2f6f 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 e29baf5da3a7724a3f11cb4c4eb64488a30b1492 Mon Sep 17 00:00:00 2001 From: Swift Tian Date: Fri, 24 May 2024 15:58:16 +0800 Subject: [PATCH 1050/2849] 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 cc9a8b1bce7a5..5dc2312a57d9a 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 f9819dc010153ea611ae9e30c6a68ddb2ae3ab45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fin=20Maa=C3=9F?= Date: Wed, 8 May 2024 09:59:01 +0200 Subject: [PATCH 1051/2849] 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 e2011fd4cadd1..6b806f28a8091 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 854500850b6e2..6b42cbf78feda 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 207da52e8e7ef1eaff295f7280d6941b3e09050c Mon Sep 17 00:00:00 2001 From: Torsten Rasmussen Date: Thu, 2 May 2024 14:23:44 +0200 Subject: [PATCH 1052/2849] 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 6fc765f8f58f8..2464bb1517cb3 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 33db820400c3a231dd11cd91ec4582bda2d4bc30 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Chru=C5=9Bci=C5=84ski?= Date: Thu, 4 Apr 2024 10:24:12 +0200 Subject: [PATCH 1053/2849] 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 0000000000000..9aa338deaad71 --- /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 0000000000000..be5897fd0516f --- /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 0000000000000..beca628a2f080 --- /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 f96e6ccbc065eef90852ec730bf2b3d440907298 Mon Sep 17 00:00:00 2001 From: Sreeram Tatapudi Date: Thu, 9 May 2024 14:07:58 -0700 Subject: [PATCH 1054/2849] 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 0000000000000..1565606bbbe28 --- /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 0000000000000..9fa085b7448b3 --- /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 0000000000000..e25e3922b5359 --- /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 0000000000000..d795ccce728be --- /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 0000000000000..fb6b4571ff5d0 --- /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 0000000000000..c96208e5a3ac2 --- /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 0000000000000..590385dc4ec7a --- /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 0000000000000..a59cfbf692a1d --- /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 0000000000000..ac92f59d12a90 --- /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 0000000000000..419ffc13abc1a --- /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 0000000000000..f702d5409dc0b --- /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 7e17b94951434..4d8f4603b44e3 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 5d1851ef9e4c4..f97b6f446c733 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 0000000000000..26921d08235d8 --- /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 0000000000000..aff1340f79712 --- /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 0000000000000..a94c9744b9e9d --- /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 0000000000000..6975188c56167 --- /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 0000000000000..a0653ea6ba30f --- /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 0000000000000..b40054d67a36a --- /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 0000000000000..d1fc0a7c02689 --- /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 0000000000000..05ea3e26ed06f --- /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 0000000000000..d1fc0a7c02689 --- /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 0000000000000..d3ba211c22435 --- /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 0000000000000..d1fc0a7c02689 --- /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 0000000000000..363ad188050f2 --- /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 0000000000000..d1fc0a7c02689 --- /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 e3d468cd76412..2d7641f59b641 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 f7461673961f8..3d264fd5ee5bc 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 896156527fa8b..8e7df38166db8 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 0000000000000..936ff2b9d6799 --- /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 0000000000000..020436ead22cf --- /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 0000000000000..72ad49d573713 --- /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 0000000000000..602dfc1a00c39 --- /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 0000000000000..eff44801d0c36 --- /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 0000000000000..7832c1b39de37 --- /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 0000000000000..1605a4aaea4e3 --- /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 0000000000000..f00be4ba1b811 --- /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 0000000000000..2096df8420f8e --- /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 0000000000000..7737a29232145 --- /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 0000000000000..9d64178b1e23f --- /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 0000000000000..da007baa74912 --- /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 0000000000000..11b36b5117054 --- /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 0000000000000..3199a1ac8945b --- /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 0000000000000..e13fc0739e62e --- /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 0000000000000..af1e937afee03 --- /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 bbab3d69400cf57f5f30b3fa340eebf1ca738123 Mon Sep 17 00:00:00 2001 From: Yasushi SHOJI Date: Tue, 6 Feb 2024 14:22:34 +0900 Subject: [PATCH 1055/2849] 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 bfb2eb3edb75c..9d10a8f55d567 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 2e2aeb13ed911f435e2a63a6a3c1b9cd71dcfd60 Mon Sep 17 00:00:00 2001 From: Andrzej Kaczmarek Date: Wed, 22 May 2024 20:17:43 +0200 Subject: [PATCH 1056/2849] 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 8935244472a95..c97b83f3b35cf 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 39e126d6b31f1f396b0305b3af647805fed20d1e Mon Sep 17 00:00:00 2001 From: Yassine EL -AISSAOUI Date: Fri, 25 Aug 2023 14:29:55 +0200 Subject: [PATCH 1057/2849] 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 0000000000000..7620ec8eb6988 --- /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 ee03123dd1cd3c9b12c1644ef9a8a8d7392e8e02 Mon Sep 17 00:00:00 2001 From: Axel Le Bourhis Date: Fri, 25 Aug 2023 14:29:39 +0200 Subject: [PATCH 1058/2849] 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 ab1df047ce11d..ca3f62f9e59bd 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 1b4bc9fdb25d0..7a2f79fd85a86 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 0000000000000..a5eb8648c8ad5 --- /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 0000000000000..78016a794b5fd --- /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 c6ff13bd6bf9f..177d1715856e8 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 6ffbcd4990da76f38380015d02e3f693094521eb Mon Sep 17 00:00:00 2001 From: Axel Le Bourhis Date: Fri, 25 Aug 2023 09:54:09 +0200 Subject: [PATCH 1059/2849] 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 0700438661e67..5d30250079fc6 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 63791f2817548b5f0749f35c619043e0c7ca8efb Mon Sep 17 00:00:00 2001 From: Yassine El Aissaoui Date: Tue, 23 Apr 2024 15:30:43 +0200 Subject: [PATCH 1060/2849] 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 b02f5fe281405..60c3dc9d2d542 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 3790d07afd87a..64b8bd4803ab0 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 aa62fea1460a9..7f1ee72b9cf31 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 0000000000000..2fe41f042bd7e --- /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 780bd9b66aad8..13f451493e91e 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 f062d8bf32d2ca03e11f40b2bea39023e7586843 Mon Sep 17 00:00:00 2001 From: Yassine El Aissaoui Date: Tue, 23 Apr 2024 16:03:20 +0200 Subject: [PATCH 1061/2849] 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 db565403583f1..31a3303d5d6fe 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 3310e80660892..1fa058bfb1313 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 4a755a3157be8672203f8fc738ae9ff4adbae95b Mon Sep 17 00:00:00 2001 From: Yassine El Aissaoui Date: Wed, 15 May 2024 13:54:00 +0200 Subject: [PATCH 1062/2849] 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 f41b228970576..f59d207a59fed 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 4ff509843e064..4243914b57178 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 0000000000000..b25149c8ec46a --- /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 0000000000000..b78c0344f1eb0 --- /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 0000000000000..b78c0344f1eb0 --- /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 0000000000000..ba1ae16dc7c0b --- /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 0000000000000..4d4b5710e424c --- /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 7721cabf15318..43fa984a2ced9 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 0000000000000..b78c0344f1eb0 --- /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 0000000000000..b78c0344f1eb0 --- /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 0000000000000..b78c0344f1eb0 --- /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 0000000000000..b78c0344f1eb0 --- /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 0000000000000..b78c0344f1eb0 --- /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 0000000000000..b78c0344f1eb0 --- /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 0000000000000..b78c0344f1eb0 --- /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 0000000000000..b78c0344f1eb0 --- /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 0000000000000..b78c0344f1eb0 --- /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 c57f9f12a24a7e9772f12469a8b00ad49fdbd2a3 Mon Sep 17 00:00:00 2001 From: Yong Cong Sin Date: Tue, 21 May 2024 21:01:40 +0800 Subject: [PATCH 1063/2849] 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 fff8d1dffadeb..db7fe0b6b0d56 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 84da6c8e6ce8456fac1cfd843049f3716dc49102 Mon Sep 17 00:00:00 2001 From: Yong Cong Sin Date: Tue, 21 May 2024 21:03:14 +0800 Subject: [PATCH 1064/2849] 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 1b06037c78071..bb8c8a1dde772 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 c5f5b964c1529e11181221ec27fdbcdcea71e26c Mon Sep 17 00:00:00 2001 From: Yong Cong Sin Date: Wed, 20 Dec 2023 21:06:14 +0800 Subject: [PATCH 1065/2849] 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 78fc6396ed63a..407d028cffa77 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 aabc599a4d58a..d53eb393b2757 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 53f8e03a4d849..25972d41da164 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 0000000000000..dd4fe68b5ac45 --- /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 125d438b58b29..a902a24f3c0e0 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 f5f762e4aba9d..6f959b25cd4bf 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 0000000000000..a9c4e864ae198 --- /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 25daa0302495c..dda2ff2b46b0b 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 8f9c89ebdd0c6..7653c1843d1f5 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 0000000000000..9ee9dace34188 --- /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 7b1bfddb2cbda..ea708cba4f7d3 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 2f6476a1f344a..95a8940d25cdd 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 2300f8a445e16b233765f78dbe2ebb99e5d58c29 Mon Sep 17 00:00:00 2001 From: Yong Cong Sin Date: Wed, 24 Jan 2024 15:04:15 +0800 Subject: [PATCH 1066/2849] 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 5dc2312a57d9a..27834decc3fb1 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 8f9ebb652f8d56bae9c453f6f505ace4500be1c2 Mon Sep 17 00:00:00 2001 From: Yong Cong Sin Date: Wed, 3 Jan 2024 23:43:55 +0800 Subject: [PATCH 1067/2849] 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 6f959b25cd4bf..144e448a04d4a 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 dcaf2173368e4afde5d97840017531afccc97c47 Mon Sep 17 00:00:00 2001 From: Yong Cong Sin Date: Fri, 26 Jan 2024 12:45:40 +0800 Subject: [PATCH 1068/2849] 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 dda2ff2b46b0b..b500559f1c722 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 95a8940d25cdd..b71b47dafbca0 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 e2bcedc3ad1a4da675c54a3c470f3b6a26e4bb73 Mon Sep 17 00:00:00 2001 From: Yong Cong Sin Date: Fri, 26 Jan 2024 12:47:54 +0800 Subject: [PATCH 1069/2849] 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 25972d41da164..be2e8892e1f27 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 5d9e266d1336f51989767892477141deade3c5b7 Mon Sep 17 00:00:00 2001 From: Yong Cong Sin Date: Fri, 2 Feb 2024 13:13:06 +0800 Subject: [PATCH 1070/2849] 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 d53eb393b2757..2df4d3a8e8b19 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 cd06b23854acf..41157f08cde04 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 a512f68f14e0bc110e67e139a08cc6acb7200961 Mon Sep 17 00:00:00 2001 From: Yong Cong Sin Date: Tue, 20 Feb 2024 12:05:18 +0800 Subject: [PATCH 1071/2849] 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 9bda4bddcfa4b..300ee3a10be65 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 7248efcd5964abe0ca5e2625d21c0a47e7ad199f Mon Sep 17 00:00:00 2001 From: Yong Cong Sin Date: Tue, 20 Feb 2024 12:07:54 +0800 Subject: [PATCH 1072/2849] 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 2df4d3a8e8b19..ba74cf6dda75a 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 47e4940e13977..38e22c233e817 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 3d221b50370ca..1abee2e514eaf 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 300ee3a10be65..40f61a69e4e6a 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 b9b10c042112e..f5af9f70e7ebc 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 cd0ef1ad27950b7a855baf4056a3f3b6ebb9b078 Mon Sep 17 00:00:00 2001 From: Yong Cong Sin Date: Tue, 20 Feb 2024 12:17:05 +0800 Subject: [PATCH 1073/2849] 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 0000000000000..213deed619daf --- /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 0000000000000..d8e1b2f7fe148 --- /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 0000000000000..9da8bafefc1a7 --- /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 0000000000000..e0594ff091ac2 --- /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 0000000000000..4fac64b8a333a --- /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 0000000000000..689c8bf6b53f0 --- /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 0000000000000..98b9d2ac1d840 --- /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 4a49a88348b6c39dbc17e16701eed711bec62aca Mon Sep 17 00:00:00 2001 From: Yong Cong Sin Date: Wed, 28 Feb 2024 16:32:45 +0800 Subject: [PATCH 1074/2849] 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 0000000000000..9333affd47960 --- /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 0000000000000..31c67ccc7d47b --- /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 0000000000000..407b7b6612110 --- /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 0000000000000..7aba6aebef419 --- /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 0000000000000..5f41f8ff071fa --- /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 68bd4da4c64ca0c19cee0334bee6496ec8cde2b9 Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Wed, 22 May 2024 09:27:10 +0200 Subject: [PATCH 1075/2849] 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 9f2aad6f3637a..245a83aa0d96a 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 ef8a5b72755f2a29891eac7c18c4c83b66cdafa0 Mon Sep 17 00:00:00 2001 From: Marco Widmer Date: Wed, 22 May 2024 15:57:58 +0200 Subject: [PATCH 1076/2849] debug: coredump: fix multiple definitions When compiling with CONFIG_DEBUG_COREDUMP=n and including from any file, linking fails with a multiple definitions error. Define the functions in the header file as static inline. Signed-off-by: Marco Widmer --- include/zephyr/debug/coredump.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/include/zephyr/debug/coredump.h b/include/zephyr/debug/coredump.h index 740ef4776b8d5..135c05472edc9 100644 --- a/include/zephyr/debug/coredump.h +++ b/include/zephyr/debug/coredump.h @@ -229,34 +229,34 @@ int coredump_cmd(enum coredump_cmd_id cmd_id, void *arg); #else -void coredump(unsigned int reason, const z_arch_esf_t *esf, - struct k_thread *thread) +static inline void coredump(unsigned int reason, const z_arch_esf_t *esf, + struct k_thread *thread) { ARG_UNUSED(reason); ARG_UNUSED(esf); ARG_UNUSED(thread); } -void coredump_memory_dump(uintptr_t start_addr, uintptr_t end_addr) +static inline void coredump_memory_dump(uintptr_t start_addr, uintptr_t end_addr) { ARG_UNUSED(start_addr); ARG_UNUSED(end_addr); } -void coredump_buffer_output(uint8_t *buf, size_t buflen) +static inline void coredump_buffer_output(uint8_t *buf, size_t buflen) { ARG_UNUSED(buf); ARG_UNUSED(buflen); } -int coredump_query(enum coredump_query_id query_id, void *arg) +static inline int coredump_query(enum coredump_query_id query_id, void *arg) { ARG_UNUSED(query_id); ARG_UNUSED(arg); return -ENOTSUP; } -int coredump_cmd(enum coredump_cmd_id query_id, void *arg) +static inline int coredump_cmd(enum coredump_cmd_id query_id, void *arg) { ARG_UNUSED(query_id); ARG_UNUSED(arg); From 2d665c1c14f181521d47a1286a061678edb4637f Mon Sep 17 00:00:00 2001 From: Lyle Zhu Date: Wed, 22 May 2024 21:02:58 +0800 Subject: [PATCH 1077/2849] bluetooth: keys_br: Improve bt_foreach_bond The BR Keys cannot be scanned by function bt_foreach_bond. Add function bt_foreach_bond_br for br. The function bt_foreach_bond_br will be called by bt_foreach_bond if the BR is enabled. Signed-off-by: Lyle Zhu --- subsys/bluetooth/host/classic/keys_br.c | 18 ++++++++++++++++++ subsys/bluetooth/host/keys.c | 4 ++++ subsys/bluetooth/host/keys.h | 3 ++- 3 files changed, 24 insertions(+), 1 deletion(-) diff --git a/subsys/bluetooth/host/classic/keys_br.c b/subsys/bluetooth/host/classic/keys_br.c index 2ce745de678d5..3c9536fe1121e 100644 --- a/subsys/bluetooth/host/classic/keys_br.c +++ b/subsys/bluetooth/host/classic/keys_br.c @@ -146,6 +146,24 @@ void bt_keys_link_key_store(struct bt_keys_link_key *link_key) } } +void bt_foreach_bond_br(void (*func)(const struct bt_bond_info *info, void *user_data), + void *user_data) +{ + __ASSERT_NO_MSG(func != NULL); + + for (size_t i = 0; i < ARRAY_SIZE(key_pool); i++) { + const struct bt_keys_link_key *key = &key_pool[i]; + + if (!bt_addr_eq(&key->addr, BT_ADDR_ANY)) { + struct bt_bond_info info; + + info.addr.type = BT_ADDR_LE_PUBLIC; + bt_addr_copy(&info.addr.a, &key->addr); + func(&info, user_data); + } + } +} + #if defined(CONFIG_BT_SETTINGS) static int link_key_set(const char *name, size_t len_rd, diff --git a/subsys/bluetooth/host/keys.c b/subsys/bluetooth/host/keys.c index 7b0b13b6493bb..c8184d7cbb47d 100644 --- a/subsys/bluetooth/host/keys.c +++ b/subsys/bluetooth/host/keys.c @@ -169,6 +169,10 @@ void bt_foreach_bond(uint8_t id, void (*func)(const struct bt_bond_info *info, func(&info, user_data); } } + + if (IS_ENABLED(CONFIG_BT_CLASSIC)) { + bt_foreach_bond_br(func, user_data); + } } void bt_keys_foreach_type(enum bt_keys_type type, void (*func)(struct bt_keys *keys, void *data), diff --git a/subsys/bluetooth/host/keys.h b/subsys/bluetooth/host/keys.h index 408c48b2fcff3..198b6991ca912 100644 --- a/subsys/bluetooth/host/keys.h +++ b/subsys/bluetooth/host/keys.h @@ -215,7 +215,8 @@ struct bt_keys_link_key *bt_keys_find_link_key(const bt_addr_t *addr); void bt_keys_link_key_clear(struct bt_keys_link_key *link_key); void bt_keys_link_key_clear_addr(const bt_addr_t *addr); void bt_keys_link_key_store(struct bt_keys_link_key *link_key); - +void bt_foreach_bond_br(void (*func)(const struct bt_bond_info *info, void *user_data), + void *user_data); /* This function is used to signal that the key has been used for paring */ /* It updates the aging counter and saves it to flash if configuration option */ From ea29ef36bbedeacd171199d6feea5e699fa64447 Mon Sep 17 00:00:00 2001 From: Younghyun Park Date: Mon, 13 May 2024 15:04:34 -0700 Subject: [PATCH 1078/2849] debug: coredump: Move COREDUMP_*_STR strings to the public header This allows a customized coredump_backend_other API to re-use the COREDUMP_*_STR without re-defining the same strings. Signed-off-by: Younghyun Park --- include/zephyr/debug/coredump.h | 13 +++++++++++++ subsys/debug/coredump/coredump_internal.h | 10 ---------- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/include/zephyr/debug/coredump.h b/include/zephyr/debug/coredump.h index 135c05472edc9..9d4f37a4f870f 100644 --- a/include/zephyr/debug/coredump.h +++ b/include/zephyr/debug/coredump.h @@ -11,6 +11,19 @@ #include #include +/* + * Define COREDUMP_*_STR as public to allow coredump_backend_other to re-use + * these strings if necessary + */ +#define COREDUMP_BEGIN_STR "BEGIN#" +#define COREDUMP_END_STR "END#" +#define COREDUMP_ERROR_STR "ERROR CANNOT DUMP#" + +/* + * Need to prefix coredump strings to make it easier to parse + * as log module adds its own prefixes. + */ +#define COREDUMP_PREFIX_STR "#CD:" /** * @file diff --git a/subsys/debug/coredump/coredump_internal.h b/subsys/debug/coredump/coredump_internal.h index 0d9fa3b886153..6a2286ff8c151 100644 --- a/subsys/debug/coredump/coredump_internal.h +++ b/subsys/debug/coredump/coredump_internal.h @@ -16,16 +16,6 @@ * public documentation. */ -#define COREDUMP_BEGIN_STR "BEGIN#" -#define COREDUMP_END_STR "END#" -#define COREDUMP_ERROR_STR "ERROR CANNOT DUMP#" - -/* - * Need to prefix coredump strings to make it easier to parse - * as log module adds its own prefixes. - */ -#define COREDUMP_PREFIX_STR "#CD:" - struct z_coredump_memory_region_t { uintptr_t start; uintptr_t end; From 3a3f25c9a683562dcf09232eb754fa544affac3b Mon Sep 17 00:00:00 2001 From: Maciej Perkowski Date: Wed, 22 May 2024 13:38:01 +0200 Subject: [PATCH 1079/2849] requirements: Set min version of pylint to 3 PR #72592 made pylint to use json2 output format. However, this format is introduced in pylint v3. This commit adds an appropriate setting in the requirements file. Signed-off-by: Maciej Perkowski --- scripts/requirements-compliance.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/requirements-compliance.txt b/scripts/requirements-compliance.txt index 31c395ac4f050..68469fc80ea07 100644 --- a/scripts/requirements-compliance.txt +++ b/scripts/requirements-compliance.txt @@ -5,5 +5,5 @@ python-magic python-magic-bin; sys_platform == "win32" lxml junitparser>=2 -pylint +pylint>=3 yamllint From 7180c515c4272b460584e1d01fcf24a50696acf1 Mon Sep 17 00:00:00 2001 From: Nikolay Agishev Date: Wed, 22 May 2024 16:48:23 +0300 Subject: [PATCH 1080/2849] ARC: MPU: Add thread stack isolation configs Regarding recent changes in general MPU configuration (https://github.com/zephyrproject-rtos/zephyr/pull/71969), add appropriate configs for isolating thread stacks into ARC MPU. Signed-off-by: Nikolay Agishev --- arch/arc/core/mpu/Kconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arc/core/mpu/Kconfig b/arch/arc/core/mpu/Kconfig index 7078d88d534ae..2f288de25c7d5 100644 --- a/arch/arc/core/mpu/Kconfig +++ b/arch/arc/core/mpu/Kconfig @@ -35,5 +35,7 @@ config ARC_MPU select GEN_PRIV_STACKS if !(ARC_MPU_VER = 4 || ARC_MPU_VER = 8) select MPU_REQUIRES_POWER_OF_TWO_ALIGNMENT if !(ARC_MPU_VER = 4 || ARC_MPU_VER = 8) select MPU_REQUIRES_NON_OVERLAPPING_REGIONS if (ARC_MPU_VER = 4 || ARC_MPU_VER = 8) + select ARCH_MEM_DOMAIN_SUPPORTS_ISOLATED_STACKS + select MEM_DOMAIN_ISOLATED_STACKS help Target has ARC MPU From fb4f67b77503ad143d98cc1b2c73ca448850900e Mon Sep 17 00:00:00 2001 From: Henrik Brix Andersen Date: Sun, 26 May 2024 19:23:40 +0000 Subject: [PATCH 1081/2849] drivers: can: shell: fully initialize frame before sending Zerorise the CAN frame before filling in data to ensure all data bytes are initialized. Fixes: #73309 Signed-off-by: Henrik Brix Andersen --- drivers/can/can_shell.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/can/can_shell.c b/drivers/can/can_shell.c index 6c0744879aef0..3348d5774e09b 100644 --- a/drivers/can/can_shell.c +++ b/drivers/can/can_shell.c @@ -674,7 +674,7 @@ static int cmd_can_send(const struct shell *sh, size_t argc, char **argv) const struct device *dev = device_get_binding(argv[1]); static unsigned int frame_counter; unsigned int frame_no; - struct can_frame frame; + struct can_frame frame = { 0 }; uint32_t id_mask; int argidx = 2; uint32_t val; From 6a070ee165fe39b2fcbfd365102165ab362dce2f Mon Sep 17 00:00:00 2001 From: Henrik Brix Andersen Date: Sun, 26 May 2024 19:34:26 +0000 Subject: [PATCH 1082/2849] drivers: can: shell: print raw DLC when sending frame, not bytes Print the raw DLC when enqueuing a CAN frame for sending, not the corresponding number of bytes. Fixes: #73309 Signed-off-by: Henrik Brix Andersen --- drivers/can/can_shell.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/can/can_shell.c b/drivers/can/can_shell.c index 3348d5774e09b..d7c9fd4076dc8 100644 --- a/drivers/can/can_shell.c +++ b/drivers/can/can_shell.c @@ -779,7 +779,7 @@ static int cmd_can_send(const struct shell *sh, size_t argc, char **argv) (frame.flags & CAN_FRAME_RTR) != 0 ? 1 : 0, (frame.flags & CAN_FRAME_FDF) != 0 ? 1 : 0, (frame.flags & CAN_FRAME_BRS) != 0 ? 1 : 0, - can_dlc_to_bytes(frame.dlc)); + frame.dlc); err = can_send(dev, &frame, K_NO_WAIT, can_shell_tx_callback, UINT_TO_POINTER(frame_no)); if (err != 0) { From 76c0e2cf51c7f26661c7e0b5167c445c931d04a1 Mon Sep 17 00:00:00 2001 From: Francois Ramu Date: Mon, 5 Feb 2024 16:43:01 +0100 Subject: [PATCH 1083/2849] scripts: west flash with stm32CubeProgrammer error line Correct the error "F541 f-string is missing placeholders" when ruuning Flake Signed-off-by: Francois Ramu --- scripts/west_commands/runners/stm32cubeprogrammer.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/west_commands/runners/stm32cubeprogrammer.py b/scripts/west_commands/runners/stm32cubeprogrammer.py index 026e53274d5bc..b57864ace837a 100644 --- a/scripts/west_commands/runners/stm32cubeprogrammer.py +++ b/scripts/west_commands/runners/stm32cubeprogrammer.py @@ -200,7 +200,7 @@ def flash(self, **kwargs) -> None: # flash image and run application dl_file = self.cfg.elf_file if self._use_elf else self.cfg.hex_file if dl_file is None: - raise RuntimeError(f'cannot flash; no download file was specified') + raise RuntimeError('cannot flash; no download file was specified') elif not os.path.isfile(dl_file): raise RuntimeError(f'download file {dl_file} does not exist') self.check_call(cmd + ["--download", dl_file, "--start"]) From 94d93af91ff6f697a6a36c311bd38cc409dc3d24 Mon Sep 17 00:00:00 2001 From: Francois Ramu Date: Wed, 31 Jan 2024 17:48:08 +0100 Subject: [PATCH 1084/2849] scripts: west flash with stm32CubeProgrammer and ext-loader Add the option to support an external loader for flashing hex file to internal and external NOR flash using the STM32CubProgrammer CLI with a board_runner_args "--extload=MX25LM51245G_STM32U585I-IOT02A.stldr" The absolute path of the stldr file is added to the stm32CubeProgrammer command. Signed-off-by: Francois Ramu --- scripts/west_commands/runners/core.py | 20 +++++++++++++++++++ .../runners/stm32cubeprogrammer.py | 17 +++++++++++++++- 2 files changed, 36 insertions(+), 1 deletion(-) diff --git a/scripts/west_commands/runners/core.py b/scripts/west_commands/runners/core.py index 21a60edc1a06f..fdc38013a9ddb 100644 --- a/scripts/west_commands/runners/core.py +++ b/scripts/west_commands/runners/core.py @@ -236,6 +236,10 @@ class RunnerCaps: - reset: whether the runner supports a --reset option, which resets the device after a flash operation is complete. + - extload: whether the runner supports a --extload option, which + must be given one time and is passed on to the underlying tool + that the runner wraps. + - tool_opt: whether the runner supports a --tool-opt (-O) option, which can be given multiple times and is passed on to the underlying tool that the runner wraps. @@ -250,6 +254,7 @@ class RunnerCaps: flash_addr: bool = False erase: bool = False reset: bool = False + extload: bool = False tool_opt: bool = False file: bool = False @@ -531,6 +536,10 @@ def add_parser(cls, parser): "Default action depends on each specific runner." if caps.reset else argparse.SUPPRESS)) + parser.add_argument('--extload', dest='extload', + help=(cls.extload_help() if caps.extload + else argparse.SUPPRESS)) + parser.add_argument('-O', '--tool-opt', dest='tool_opt', default=[], action='append', help=(cls.tool_opt_help() if caps.tool_opt @@ -561,6 +570,8 @@ def create(cls, cfg: RunnerConfig, _missing_cap(cls, '--erase') if args.reset and not caps.reset: _missing_cap(cls, '--reset') + if args.extload and not caps.extload: + _missing_cap(cls, '--extload') if args.tool_opt and not caps.tool_opt: _missing_cap(cls, '--tool-opt') if args.file and not caps.file: @@ -649,6 +660,15 @@ def dev_id_help(cls) -> str: target when multiple ones are available or connected.''' + @classmethod + def extload_help(cls) -> str: + ''' Get the ArgParse help text for the --extload option.''' + return '''External loader to be used by stm32cubeprogrammer + to program the targeted external memory. + The runner requires the external loader (*.stldr) filename. + This external loader (*.stldr) must be located within + STM32CubeProgrammer/bin/ExternalLoader directory.''' + @classmethod def tool_opt_help(cls) -> str: ''' Get the ArgParse help text for the --tool-opt option.''' diff --git a/scripts/west_commands/runners/stm32cubeprogrammer.py b/scripts/west_commands/runners/stm32cubeprogrammer.py index b57864ace837a..43d9a19adfa1a 100644 --- a/scripts/west_commands/runners/stm32cubeprogrammer.py +++ b/scripts/west_commands/runners/stm32cubeprogrammer.py @@ -37,6 +37,7 @@ def __init__( cli: Optional[Path], use_elf: bool, erase: bool, + extload: Optional[str], tool_opt: List[str], ) -> None: super().__init__(cfg) @@ -51,6 +52,12 @@ def __init__( self._use_elf = use_elf self._erase = erase + if extload: + p = STM32CubeProgrammerBinaryRunner._get_stm32cubeprogrammer_path().parent.resolve() / 'ExternalLoader' + self._extload = ['-el', str(p / extload)] + else: + self._extload = [] + self._tool_opt: List[str] = list() for opts in [shlex.split(opt) for opt in tool_opt]: self._tool_opt += opts @@ -112,7 +119,7 @@ def name(cls): @classmethod def capabilities(cls): - return RunnerCaps(commands={"flash"}, erase=True, tool_opt=True) + return RunnerCaps(commands={"flash"}, erase=True, extload=True, tool_opt=True) @classmethod def do_add_parser(cls, parser): @@ -151,6 +158,10 @@ def do_add_parser(cls, parser): help="Use ELF file when flashing instead of HEX file", ) + @classmethod + def extload_help(cls) -> str: + return "External Loader for STM32_Programmer_CLI" + @classmethod def tool_opt_help(cls) -> str: return "Additional options for STM32_Programmer_CLI" @@ -168,6 +179,7 @@ def do_create( cli=args.cli, use_elf=args.use_elf, erase=args.erase, + extload=args.extload, tool_opt=args.tool_opt, ) @@ -192,6 +204,9 @@ def flash(self, **kwargs) -> None: cmd += ["--connect", connect_opts] cmd += self._tool_opt + if self._extload: + # external loader to come after the tool option in STM32CubeProgrammer + cmd += self._extload # erase first if requested if self._erase: From d490616d08c1799f7e314a2663da19180f6b6123 Mon Sep 17 00:00:00 2001 From: Francois Ramu Date: Tue, 20 Feb 2024 10:54:01 +0100 Subject: [PATCH 1085/2849] scripts: west flash with stm32CubeProgrammer testing Add the option "--extload" for the "extload" argument. Signed-off-by: Francois Ramu --- .../tests/test_stm32cubeprogrammer.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/scripts/west_commands/tests/test_stm32cubeprogrammer.py b/scripts/west_commands/tests/test_stm32cubeprogrammer.py index 096a3b2bb4aae..82d6dcd5450f7 100644 --- a/scripts/west_commands/tests/test_stm32cubeprogrammer.py +++ b/scripts/west_commands/tests/test_stm32cubeprogrammer.py @@ -68,6 +68,7 @@ "cli": CLI_PATH, "use_elf": False, "erase": False, + "extload": None, "tool_opt": [], "system": "", "cli_path": str(CLI_PATH), @@ -90,6 +91,7 @@ "cli": CLI_PATH, "use_elf": False, "erase": False, + "extload": None, "tool_opt": [], "system": "", "cli_path": str(CLI_PATH), @@ -112,6 +114,7 @@ "cli": CLI_PATH, "use_elf": False, "erase": False, + "extload": None, "tool_opt": [], "system": "", "cli_path": str(CLI_PATH), @@ -134,6 +137,7 @@ "cli": CLI_PATH, "use_elf": False, "erase": False, + "extload": None, "tool_opt": [], "system": "", "cli_path": str(CLI_PATH), @@ -156,6 +160,7 @@ "cli": CLI_PATH, "use_elf": False, "erase": False, + "extload": None, "tool_opt": [], "system": "", "cli_path": str(CLI_PATH), @@ -178,6 +183,7 @@ "cli": CLI_PATH, "use_elf": False, "erase": False, + "extload": None, "tool_opt": [], "system": "", "cli_path": str(CLI_PATH), @@ -200,6 +206,7 @@ "cli": CLI_PATH, "use_elf": True, "erase": False, + "extload": None, "tool_opt": [], "system": "", "cli_path": str(CLI_PATH), @@ -222,6 +229,7 @@ "cli": CLI_PATH, "use_elf": False, "erase": True, + "extload": None, "tool_opt": [], "system": "", "cli_path": str(CLI_PATH), @@ -245,6 +253,7 @@ "cli": CLI_PATH, "use_elf": False, "erase": False, + "extload": None, "tool_opt": ["--skipErase"], "system": "", "cli_path": str(CLI_PATH), @@ -268,6 +277,7 @@ "cli": None, "use_elf": False, "erase": False, + "extload": None, "tool_opt": [], "system": "Linux", "cli_path": str(LINUX_CLI_PATH), @@ -290,6 +300,7 @@ "cli": None, "use_elf": False, "erase": False, + "extload": None, "tool_opt": [], "system": "Darwin", "cli_path": str(MACOS_CLI_PATH), @@ -312,6 +323,7 @@ "cli": None, "use_elf": False, "erase": False, + "extload": None, "tool_opt": [], "system": "Windows", "cli_path": str(WINDOWS_CLI_PATH), @@ -355,6 +367,7 @@ def test_stm32cubeprogrammer_init( cli=tc["cli"], use_elf=tc["use_elf"], erase=tc["erase"], + extload=tc["extload"], tool_opt=tc["tool_opt"], ) @@ -393,6 +406,8 @@ def test_stm32cubeprogrammer_create( args.extend(["--use-elf"]) if tc["erase"]: args.append("--erase") + if tc["extload"]: + args.extend(["--extload", tc["extload"]]) if tc["tool_opt"]: args.extend(["--tool-opt", " " + tc["tool_opt"][0]]) From a8dddabdb882020537672792ccdc829b6c84f580 Mon Sep 17 00:00:00 2001 From: Lucas Tamborrino Date: Thu, 25 Apr 2024 21:33:34 -0300 Subject: [PATCH 1086/2849] manifest: update hal espressif Add changes to comply with rtc refactor. Signed-off-by: Lucas Tamborrino --- west.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/west.yml b/west.yml index 177d1715856e8..f49dd745e7a1f 100644 --- a/west.yml +++ b/west.yml @@ -152,7 +152,7 @@ manifest: groups: - hal - name: hal_espressif - revision: c49581173bab8625d1f08d5c41d5a186afc240b3 + revision: b5f5fa6d08780c0077407150c6685d6c9d70262c path: modules/hal/espressif west-commands: west/west-commands.yml groups: From e282b0ea8424a6ada37632bcea0646a7c069ec42 Mon Sep 17 00:00:00 2001 From: Lucas Tamborrino Date: Thu, 2 May 2024 16:39:17 -0300 Subject: [PATCH 1087/2849] soc: esp32xx: refactor clock and RTC subsystems The RTC subsystem in espressif's SOCs, among other tasks is responsible for clock selection for CPU and for low power domain clocks such as RTC_SLOW and RTC_FAST. This commit allows for proper clock source and rate selection for CPU, using the espressif,riscv and espressif,xtensa-lx6/7 bindings. It also enables clock selection for RTC_FAST and RTC_SLOW, that impacts some peripherals, such as rtc_timer. Signed-off-by: Lucas Tamborrino --- .../esp32_devkitc_wroom_appcpu.dts | 8 - .../esp32_devkitc_wroom_procpu.dts | 9 - .../esp32_devkitc_wrover_appcpu.dts | 8 - .../esp32_devkitc_wrover_procpu.dts | 8 - .../esp32_ethernet_kit_appcpu.dts | 8 - .../esp32_ethernet_kit_procpu.dts | 8 - .../esp32c3_devkitm/esp32c3_devkitm.dts | 6 +- .../esp32s2_devkitc/esp32s2_devkitc.dts | 4 - .../espressif/esp32s2_saola/esp32s2_saola.dts | 4 - .../esp32s3_devkitc_appcpu.dts | 8 - .../esp32s3_devkitc_procpu.dts | 8 - .../esp32s3_devkitm_appcpu.dts | 8 - .../esp32s3_devkitm_procpu.dts | 8 - .../esp_wrover_kit/esp_wrover_kit_appcpu.dts | 8 - .../esp_wrover_kit/esp_wrover_kit_procpu.dts | 8 - .../esp32s2_franzininho.dts | 4 - .../hardkernel/odroid_go/odroid_go_appcpu.dts | 8 - .../hardkernel/odroid_go/odroid_go_procpu.dts | 8 - .../heltec_wifi_lora32_v2_appcpu.dts | 8 - .../heltec_wifi_lora32_v2_procpu.dts | 8 - .../heltec_wireless_stick_lite_v3_appcpu.dts | 8 - .../heltec_wireless_stick_lite_v3_procpu.dts | 8 - .../kincony_kc868_a32_appcpu.dts | 8 - .../kincony_kc868_a32_procpu.dts | 9 - .../esp32c3_luatos_core.dtsi | 4 - .../esp32s3_luatos_core.dtsi | 8 - .../esp32s3_luatos_core_appcpu.dts | 8 - .../esp32s3_luatos_core_appcpu_usb.dts | 8 - .../m5stack_atom_lite_appcpu.dts | 8 - .../m5stack_atom_lite_procpu.dts | 8 - .../m5stack_atoms3/m5stack_atoms3_appcpu.dts | 8 - .../m5stack_atoms3/m5stack_atoms3_procpu.dts | 8 - .../m5stack_atoms3_lite_appcpu.dts | 8 - .../m5stack_atoms3_lite_procpu.dts | 8 - .../m5stack_core2/m5stack_core2_appcpu.dts | 8 - .../m5stack_core2/m5stack_core2_procpu.dts | 8 - .../m5stack_stamps3_appcpu.dts | 8 - .../m5stack_stamps3_procpu.dts | 8 - .../m5stickc_plus/m5stickc_plus_appcpu.dts | 8 - .../m5stickc_plus/m5stickc_plus_procpu.dts | 8 - boards/m5stack/stamp_c3/stamp_c3.dts | 4 - .../olimex_esp32_evb_appcpu.dts | 8 - .../olimex_esp32_evb_procpu.dts | 8 - boards/others/icev_wireless/icev_wireless.dts | 4 - boards/seeed/xiao_esp32c3/xiao_esp32c3.dts | 4 - .../xiao_esp32s3/xiao_esp32s3_appcpu.dts | 8 - .../xiao_esp32s3/xiao_esp32s3_procpu.dts | 8 - boards/vcc-gnd/yd_esp32/yd_esp32_appcpu.dts | 8 - boards/vcc-gnd/yd_esp32/yd_esp32_procpu.dts | 9 - .../esp32s3_touch_lcd_1_28_esp32s3_appcpu.dts | 8 - .../esp32s3_touch_lcd_1_28_esp32s3_procpu.dts | 8 - .../esp32s2_lolin_mini/esp32s2_lolin_mini.dts | 5 - drivers/clock_control/clock_control_esp32.c | 330 ++++++++++++------ drivers/counter/Kconfig.esp32_tmr | 8 + drivers/counter/counter_esp32_rtc.c | 70 ++-- drivers/timer/esp32_sys_timer.c | 2 +- dts/bindings/clock/espressif,esp32-rtc.yaml | 28 +- .../counter/espressif,esp32-rtc-timer.yaml | 7 - dts/bindings/cpu/espressif,riscv.yaml | 21 +- dts/bindings/cpu/espressif,xtensa-lx6.yaml | 34 ++ dts/bindings/cpu/espressif,xtensa-lx7.yaml | 34 ++ .../espressif/esp32c3/esp32c3_common.dtsi | 22 +- dts/xtensa/espressif/esp32/esp32_common.dtsi | 30 +- .../espressif/esp32s2/esp32s2_common.dtsi | 25 +- .../espressif/esp32s3/esp32s3_common.dtsi | 30 +- .../clock_control/esp32_clock_control.h | 40 +++ .../zephyr/dt-bindings/clock/esp32_clock.h | 49 +-- .../zephyr/dt-bindings/clock/esp32c3_clock.h | 42 ++- .../zephyr/dt-bindings/clock/esp32s2_clock.h | 45 +-- .../zephyr/dt-bindings/clock/esp32s3_clock.h | 45 +-- soc/espressif/Kconfig | 26 +- soc/espressif/esp32/Kconfig.rtc | 94 ----- soc/espressif/esp32/soc.c | 7 - soc/espressif/esp32c3/Kconfig.rtc | 67 ---- soc/espressif/esp32c3/soc.c | 5 - soc/espressif/esp32s2/Kconfig.rtc | 93 ----- soc/espressif/esp32s2/soc.c | 4 - soc/espressif/esp32s3/Kconfig.rtc | 63 ---- soc/espressif/esp32s3/soc.c | 2 - 79 files changed, 621 insertions(+), 988 deletions(-) create mode 100644 dts/bindings/cpu/espressif,xtensa-lx6.yaml create mode 100644 dts/bindings/cpu/espressif,xtensa-lx7.yaml create mode 100644 include/zephyr/drivers/clock_control/esp32_clock_control.h delete mode 100644 soc/espressif/esp32/Kconfig.rtc delete mode 100644 soc/espressif/esp32c3/Kconfig.rtc delete mode 100644 soc/espressif/esp32s2/Kconfig.rtc delete mode 100644 soc/espressif/esp32s3/Kconfig.rtc diff --git a/boards/espressif/esp32_devkitc_wroom/esp32_devkitc_wroom_appcpu.dts b/boards/espressif/esp32_devkitc_wroom/esp32_devkitc_wroom_appcpu.dts index c52b029ea552a..ae7a2e1e7f653 100644 --- a/boards/espressif/esp32_devkitc_wroom/esp32_devkitc_wroom_appcpu.dts +++ b/boards/espressif/esp32_devkitc_wroom/esp32_devkitc_wroom_appcpu.dts @@ -18,14 +18,6 @@ }; }; -&cpu0 { - clock-frequency = ; -}; - -&cpu1 { - clock-frequency = ; -}; - &ipm0 { status = "okay"; }; diff --git a/boards/espressif/esp32_devkitc_wroom/esp32_devkitc_wroom_procpu.dts b/boards/espressif/esp32_devkitc_wroom/esp32_devkitc_wroom_procpu.dts index 1708a7badf987..6ba26177f5250 100644 --- a/boards/espressif/esp32_devkitc_wroom/esp32_devkitc_wroom_procpu.dts +++ b/boards/espressif/esp32_devkitc_wroom/esp32_devkitc_wroom_procpu.dts @@ -39,15 +39,6 @@ }; }; -&cpu0 { - clock-frequency = ; - cpu-power-states = <&light_sleep &deep_sleep>; -}; - -&cpu1 { - clock-frequency = ; -}; - &uart0 { status = "okay"; current-speed = <115200>; diff --git a/boards/espressif/esp32_devkitc_wrover/esp32_devkitc_wrover_appcpu.dts b/boards/espressif/esp32_devkitc_wrover/esp32_devkitc_wrover_appcpu.dts index 7298148a2c34d..42c30a1079c4d 100644 --- a/boards/espressif/esp32_devkitc_wrover/esp32_devkitc_wrover_appcpu.dts +++ b/boards/espressif/esp32_devkitc_wrover/esp32_devkitc_wrover_appcpu.dts @@ -18,14 +18,6 @@ }; }; -&cpu0 { - clock-frequency = ; -}; - -&cpu1 { - clock-frequency = ; -}; - &ipm0 { status = "okay"; }; diff --git a/boards/espressif/esp32_devkitc_wrover/esp32_devkitc_wrover_procpu.dts b/boards/espressif/esp32_devkitc_wrover/esp32_devkitc_wrover_procpu.dts index 60a063bc87561..8d414b1e8903f 100644 --- a/boards/espressif/esp32_devkitc_wrover/esp32_devkitc_wrover_procpu.dts +++ b/boards/espressif/esp32_devkitc_wrover/esp32_devkitc_wrover_procpu.dts @@ -39,14 +39,6 @@ }; }; -&cpu0 { - clock-frequency = ; -}; - -&cpu1 { - clock-frequency = ; -}; - &uart0 { status = "okay"; current-speed = <115200>; diff --git a/boards/espressif/esp32_ethernet_kit/esp32_ethernet_kit_appcpu.dts b/boards/espressif/esp32_ethernet_kit/esp32_ethernet_kit_appcpu.dts index c5e1217b25c56..eb613c2cc0683 100644 --- a/boards/espressif/esp32_ethernet_kit/esp32_ethernet_kit_appcpu.dts +++ b/boards/espressif/esp32_ethernet_kit/esp32_ethernet_kit_appcpu.dts @@ -18,14 +18,6 @@ }; }; -&cpu0 { - clock-frequency = ; -}; - -&cpu1 { - clock-frequency = ; -}; - &ipm0 { status = "okay"; }; diff --git a/boards/espressif/esp32_ethernet_kit/esp32_ethernet_kit_procpu.dts b/boards/espressif/esp32_ethernet_kit/esp32_ethernet_kit_procpu.dts index 7e8310c9605b4..7c6c32970b745 100644 --- a/boards/espressif/esp32_ethernet_kit/esp32_ethernet_kit_procpu.dts +++ b/boards/espressif/esp32_ethernet_kit/esp32_ethernet_kit_procpu.dts @@ -26,14 +26,6 @@ }; }; -&cpu0 { - clock-frequency = ; -}; - -&cpu1 { - clock-frequency = ; -}; - &uart0 { status = "okay"; current-speed = <115200>; diff --git a/boards/espressif/esp32c3_devkitm/esp32c3_devkitm.dts b/boards/espressif/esp32c3_devkitm/esp32c3_devkitm.dts index f1d9481a8b757..039e72b48935c 100644 --- a/boards/espressif/esp32c3_devkitm/esp32c3_devkitm.dts +++ b/boards/espressif/esp32c3_devkitm/esp32c3_devkitm.dts @@ -11,7 +11,7 @@ #include / { - model = "Espressif ESP32-DevkitM"; + model = "Espressif ESP32C3-DevkitM"; compatible = "espressif,esp32c3"; chosen { @@ -38,10 +38,6 @@ }; }; -&cpu0 { - clock-frequency = ; -}; - &uart0 { status = "okay"; current-speed = <115200>; diff --git a/boards/espressif/esp32s2_devkitc/esp32s2_devkitc.dts b/boards/espressif/esp32s2_devkitc/esp32s2_devkitc.dts index f8282767d22d7..f2c9d8cd3c92f 100644 --- a/boards/espressif/esp32s2_devkitc/esp32s2_devkitc.dts +++ b/boards/espressif/esp32s2_devkitc/esp32s2_devkitc.dts @@ -39,10 +39,6 @@ }; }; -&cpu0 { - clock-frequency = ; -}; - &uart0 { status = "okay"; current-speed = <115200>; diff --git a/boards/espressif/esp32s2_saola/esp32s2_saola.dts b/boards/espressif/esp32s2_saola/esp32s2_saola.dts index f7e73bb8f2755..b204efab94bac 100644 --- a/boards/espressif/esp32s2_saola/esp32s2_saola.dts +++ b/boards/espressif/esp32s2_saola/esp32s2_saola.dts @@ -39,10 +39,6 @@ }; }; -&cpu0 { - clock-frequency = ; -}; - &uart0 { status = "okay"; current-speed = <115200>; diff --git a/boards/espressif/esp32s3_devkitc/esp32s3_devkitc_appcpu.dts b/boards/espressif/esp32s3_devkitc/esp32s3_devkitc_appcpu.dts index 5e5a1e2be4821..886aae0527009 100644 --- a/boards/espressif/esp32s3_devkitc/esp32s3_devkitc_appcpu.dts +++ b/boards/espressif/esp32s3_devkitc/esp32s3_devkitc_appcpu.dts @@ -17,14 +17,6 @@ }; }; -&cpu0 { - clock-frequency = ; -}; - -&cpu1 { - clock-frequency = ; -}; - &trng0 { status = "okay"; }; diff --git a/boards/espressif/esp32s3_devkitc/esp32s3_devkitc_procpu.dts b/boards/espressif/esp32s3_devkitc/esp32s3_devkitc_procpu.dts index 4538c41fa5f79..8894649a1bcc2 100644 --- a/boards/espressif/esp32s3_devkitc/esp32s3_devkitc_procpu.dts +++ b/boards/espressif/esp32s3_devkitc/esp32s3_devkitc_procpu.dts @@ -42,14 +42,6 @@ }; }; -&cpu0 { - clock-frequency = ; -}; - -&cpu1 { - clock-frequency = ; -}; - &usb_serial { status = "disabled"; }; diff --git a/boards/espressif/esp32s3_devkitm/esp32s3_devkitm_appcpu.dts b/boards/espressif/esp32s3_devkitm/esp32s3_devkitm_appcpu.dts index 3815ebdacf9b8..8a259eb99be50 100644 --- a/boards/espressif/esp32s3_devkitm/esp32s3_devkitm_appcpu.dts +++ b/boards/espressif/esp32s3_devkitm/esp32s3_devkitm_appcpu.dts @@ -17,14 +17,6 @@ }; }; -&cpu0 { - clock-frequency = ; -}; - -&cpu1 { - clock-frequency = ; -}; - &trng0 { status = "okay"; }; diff --git a/boards/espressif/esp32s3_devkitm/esp32s3_devkitm_procpu.dts b/boards/espressif/esp32s3_devkitm/esp32s3_devkitm_procpu.dts index 0cb8b962829a6..3ee4131ab33c6 100644 --- a/boards/espressif/esp32s3_devkitm/esp32s3_devkitm_procpu.dts +++ b/boards/espressif/esp32s3_devkitm/esp32s3_devkitm_procpu.dts @@ -42,14 +42,6 @@ }; }; -&cpu0 { - clock-frequency = ; -}; - -&cpu1 { - clock-frequency = ; -}; - &usb_serial { status = "okay"; }; diff --git a/boards/espressif/esp_wrover_kit/esp_wrover_kit_appcpu.dts b/boards/espressif/esp_wrover_kit/esp_wrover_kit_appcpu.dts index f0a046705ee00..ee3321726f2aa 100644 --- a/boards/espressif/esp_wrover_kit/esp_wrover_kit_appcpu.dts +++ b/boards/espressif/esp_wrover_kit/esp_wrover_kit_appcpu.dts @@ -18,14 +18,6 @@ }; }; -&cpu0 { - clock-frequency = ; -}; - -&cpu1 { - clock-frequency = ; -}; - &ipm0 { status = "okay"; }; diff --git a/boards/espressif/esp_wrover_kit/esp_wrover_kit_procpu.dts b/boards/espressif/esp_wrover_kit/esp_wrover_kit_procpu.dts index ac0bacd604ceb..ad900df0e46d4 100644 --- a/boards/espressif/esp_wrover_kit/esp_wrover_kit_procpu.dts +++ b/boards/espressif/esp_wrover_kit/esp_wrover_kit_procpu.dts @@ -94,14 +94,6 @@ }; }; -&cpu0 { - clock-frequency = ; -}; - -&cpu1 { - clock-frequency = ; -}; - &uart0 { status = "okay"; current-speed = <115200>; diff --git a/boards/franzininho/esp32s2_franzininho/esp32s2_franzininho.dts b/boards/franzininho/esp32s2_franzininho/esp32s2_franzininho.dts index d8a6f1c70706b..74d5f7610a94e 100644 --- a/boards/franzininho/esp32s2_franzininho/esp32s2_franzininho.dts +++ b/boards/franzininho/esp32s2_franzininho/esp32s2_franzininho.dts @@ -43,10 +43,6 @@ }; }; -&cpu0 { - clock-frequency = ; -}; - &uart0 { status = "okay"; current-speed = <115200>; diff --git a/boards/hardkernel/odroid_go/odroid_go_appcpu.dts b/boards/hardkernel/odroid_go/odroid_go_appcpu.dts index 6b59353de6d78..1733da93f7464 100644 --- a/boards/hardkernel/odroid_go/odroid_go_appcpu.dts +++ b/boards/hardkernel/odroid_go/odroid_go_appcpu.dts @@ -18,14 +18,6 @@ }; }; -&cpu0 { - clock-frequency = ; -}; - -&cpu1 { - clock-frequency = ; -}; - &ipm0 { status = "okay"; }; diff --git a/boards/hardkernel/odroid_go/odroid_go_procpu.dts b/boards/hardkernel/odroid_go/odroid_go_procpu.dts index c17c25823e216..0d150d08f1603 100644 --- a/boards/hardkernel/odroid_go/odroid_go_procpu.dts +++ b/boards/hardkernel/odroid_go/odroid_go_procpu.dts @@ -99,14 +99,6 @@ }; }; -&cpu0 { - clock-frequency = ; -}; - -&cpu1 { - clock-frequency = ; -}; - &uart0 { status = "okay"; current-speed = <115200>; diff --git a/boards/heltec/heltec_wifi_lora32_v2/heltec_wifi_lora32_v2_appcpu.dts b/boards/heltec/heltec_wifi_lora32_v2/heltec_wifi_lora32_v2_appcpu.dts index 4cf9e26b89d45..1b9f7dff7006d 100644 --- a/boards/heltec/heltec_wifi_lora32_v2/heltec_wifi_lora32_v2_appcpu.dts +++ b/boards/heltec/heltec_wifi_lora32_v2/heltec_wifi_lora32_v2_appcpu.dts @@ -18,14 +18,6 @@ }; }; -&cpu0 { - clock-frequency = ; -}; - -&cpu1 { - clock-frequency = ; -}; - &ipm0 { status = "okay"; }; diff --git a/boards/heltec/heltec_wifi_lora32_v2/heltec_wifi_lora32_v2_procpu.dts b/boards/heltec/heltec_wifi_lora32_v2/heltec_wifi_lora32_v2_procpu.dts index 5e1c8c6c6ff12..5fdec28fe3389 100644 --- a/boards/heltec/heltec_wifi_lora32_v2/heltec_wifi_lora32_v2_procpu.dts +++ b/boards/heltec/heltec_wifi_lora32_v2/heltec_wifi_lora32_v2_procpu.dts @@ -58,14 +58,6 @@ }; }; -&cpu0 { - clock-frequency = ; -}; - -&cpu1 { - clock-frequency = ; -}; - &uart0 { status = "okay"; current-speed = <115200>; diff --git a/boards/heltec/heltec_wireless_stick_lite_v3/heltec_wireless_stick_lite_v3_appcpu.dts b/boards/heltec/heltec_wireless_stick_lite_v3/heltec_wireless_stick_lite_v3_appcpu.dts index 6c49e64e8d1c9..92bde107bc3a8 100644 --- a/boards/heltec/heltec_wireless_stick_lite_v3/heltec_wireless_stick_lite_v3_appcpu.dts +++ b/boards/heltec/heltec_wireless_stick_lite_v3/heltec_wireless_stick_lite_v3_appcpu.dts @@ -17,14 +17,6 @@ }; }; -&cpu0 { - clock-frequency = ; -}; - -&cpu1 { - clock-frequency = ; -}; - &trng0 { status = "okay"; }; 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 255fc34c051a9..ca455d9d78025 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 @@ -75,14 +75,6 @@ }; }; -&cpu0 { - clock-frequency = ; -}; - -&cpu1 { - clock-frequency = ; -}; - &adc1 { status ="okay"; }; diff --git a/boards/kincony/kincony_kc868_a32/kincony_kc868_a32_appcpu.dts b/boards/kincony/kincony_kc868_a32/kincony_kc868_a32_appcpu.dts index 7940256ff2969..4717ca7fa628b 100644 --- a/boards/kincony/kincony_kc868_a32/kincony_kc868_a32_appcpu.dts +++ b/boards/kincony/kincony_kc868_a32/kincony_kc868_a32_appcpu.dts @@ -18,14 +18,6 @@ }; }; -&cpu0 { - clock-frequency = ; -}; - -&cpu1 { - clock-frequency = ; -}; - &ipm0 { status = "okay"; }; diff --git a/boards/kincony/kincony_kc868_a32/kincony_kc868_a32_procpu.dts b/boards/kincony/kincony_kc868_a32/kincony_kc868_a32_procpu.dts index 0f459d7f7c5c5..5b60336d1bb2e 100644 --- a/boards/kincony/kincony_kc868_a32/kincony_kc868_a32_procpu.dts +++ b/boards/kincony/kincony_kc868_a32/kincony_kc868_a32_procpu.dts @@ -26,15 +26,6 @@ }; }; -&cpu0 { - clock-frequency = ; - cpu-power-states = <&light_sleep &deep_sleep>; -}; - -&cpu1 { - clock-frequency = ; -}; - &gpio0 { status = "okay"; }; diff --git a/boards/luatos/esp32c3_luatos_core/esp32c3_luatos_core.dtsi b/boards/luatos/esp32c3_luatos_core/esp32c3_luatos_core.dtsi index bf83c33898c3d..904668716f6ef 100644 --- a/boards/luatos/esp32c3_luatos_core/esp32c3_luatos_core.dtsi +++ b/boards/luatos/esp32c3_luatos_core/esp32c3_luatos_core.dtsi @@ -43,10 +43,6 @@ }; }; -&cpu0 { - clock-frequency = ; -}; - &uart0 { status = "okay"; current-speed = <115200>; diff --git a/boards/luatos/esp32s3_luatos_core/esp32s3_luatos_core.dtsi b/boards/luatos/esp32s3_luatos_core/esp32s3_luatos_core.dtsi index 849dd35bd6719..883280c7b3172 100644 --- a/boards/luatos/esp32s3_luatos_core/esp32s3_luatos_core.dtsi +++ b/boards/luatos/esp32s3_luatos_core/esp32s3_luatos_core.dtsi @@ -31,14 +31,6 @@ }; }; -&cpu0 { - clock-frequency = ; -}; - -&cpu1 { - clock-frequency = ; -}; - &uart0 { status = "okay"; current-speed = <115200>; diff --git a/boards/luatos/esp32s3_luatos_core/esp32s3_luatos_core_appcpu.dts b/boards/luatos/esp32s3_luatos_core/esp32s3_luatos_core_appcpu.dts index e33c7f43401af..510e587925ea7 100644 --- a/boards/luatos/esp32s3_luatos_core/esp32s3_luatos_core_appcpu.dts +++ b/boards/luatos/esp32s3_luatos_core/esp32s3_luatos_core_appcpu.dts @@ -17,14 +17,6 @@ }; }; -&cpu0 { - clock-frequency = ; -}; - -&cpu1 { - clock-frequency = ; -}; - &trng0 { status = "okay"; }; diff --git a/boards/luatos/esp32s3_luatos_core/esp32s3_luatos_core_appcpu_usb.dts b/boards/luatos/esp32s3_luatos_core/esp32s3_luatos_core_appcpu_usb.dts index 7a251b40e04f1..b36963af0134b 100644 --- a/boards/luatos/esp32s3_luatos_core/esp32s3_luatos_core_appcpu_usb.dts +++ b/boards/luatos/esp32s3_luatos_core/esp32s3_luatos_core_appcpu_usb.dts @@ -17,14 +17,6 @@ }; }; -&cpu0 { - clock-frequency = ; -}; - -&cpu1 { - clock-frequency = ; -}; - &trng0 { status = "okay"; }; diff --git a/boards/m5stack/m5stack_atom_lite/m5stack_atom_lite_appcpu.dts b/boards/m5stack/m5stack_atom_lite/m5stack_atom_lite_appcpu.dts index 59a908a3feff8..f5db6e76116e0 100644 --- a/boards/m5stack/m5stack_atom_lite/m5stack_atom_lite_appcpu.dts +++ b/boards/m5stack/m5stack_atom_lite/m5stack_atom_lite_appcpu.dts @@ -18,14 +18,6 @@ }; }; -&cpu0 { - clock-frequency = ; -}; - -&cpu1 { - clock-frequency = ; -}; - &ipm0 { status = "okay"; }; diff --git a/boards/m5stack/m5stack_atom_lite/m5stack_atom_lite_procpu.dts b/boards/m5stack/m5stack_atom_lite/m5stack_atom_lite_procpu.dts index 53f6175e4d1ef..e4fae9d25434d 100644 --- a/boards/m5stack/m5stack_atom_lite/m5stack_atom_lite_procpu.dts +++ b/boards/m5stack/m5stack_atom_lite/m5stack_atom_lite_procpu.dts @@ -53,14 +53,6 @@ }; }; -&cpu0 { - clock-frequency = ; -}; - -&cpu1 { - clock-frequency = ; -}; - &uart0 { status = "okay"; current-speed = <115200>; diff --git a/boards/m5stack/m5stack_atoms3/m5stack_atoms3_appcpu.dts b/boards/m5stack/m5stack_atoms3/m5stack_atoms3_appcpu.dts index 91bcff6c0079d..a117ee02922fb 100644 --- a/boards/m5stack/m5stack_atoms3/m5stack_atoms3_appcpu.dts +++ b/boards/m5stack/m5stack_atoms3/m5stack_atoms3_appcpu.dts @@ -17,14 +17,6 @@ }; }; -&cpu0 { - clock-frequency = ; -}; - -&cpu1 { - clock-frequency = ; -}; - &trng0 { status = "okay"; }; diff --git a/boards/m5stack/m5stack_atoms3/m5stack_atoms3_procpu.dts b/boards/m5stack/m5stack_atoms3/m5stack_atoms3_procpu.dts index 1b5a5da32da10..aa80e0b835673 100644 --- a/boards/m5stack/m5stack_atoms3/m5stack_atoms3_procpu.dts +++ b/boards/m5stack/m5stack_atoms3/m5stack_atoms3_procpu.dts @@ -50,14 +50,6 @@ }; -&cpu0 { - clock-frequency = ; -}; - -&cpu1 { - clock-frequency = ; -}; - &usb_serial { status = "okay"; }; diff --git a/boards/m5stack/m5stack_atoms3_lite/m5stack_atoms3_lite_appcpu.dts b/boards/m5stack/m5stack_atoms3_lite/m5stack_atoms3_lite_appcpu.dts index 994c9b9a3b2b2..2323548e7fcd9 100644 --- a/boards/m5stack/m5stack_atoms3_lite/m5stack_atoms3_lite_appcpu.dts +++ b/boards/m5stack/m5stack_atoms3_lite/m5stack_atoms3_lite_appcpu.dts @@ -17,14 +17,6 @@ }; }; -&cpu0 { - clock-frequency = ; -}; - -&cpu1 { - clock-frequency = ; -}; - &trng0 { status = "okay"; }; diff --git a/boards/m5stack/m5stack_atoms3_lite/m5stack_atoms3_lite_procpu.dts b/boards/m5stack/m5stack_atoms3_lite/m5stack_atoms3_lite_procpu.dts index 430de46a5548c..9f2cc84555858 100644 --- a/boards/m5stack/m5stack_atoms3_lite/m5stack_atoms3_lite_procpu.dts +++ b/boards/m5stack/m5stack_atoms3_lite/m5stack_atoms3_lite_procpu.dts @@ -42,14 +42,6 @@ }; }; -&cpu0 { - clock-frequency = ; -}; - -&cpu1 { - clock-frequency = ; -}; - &usb_serial { status = "okay"; }; diff --git a/boards/m5stack/m5stack_core2/m5stack_core2_appcpu.dts b/boards/m5stack/m5stack_core2/m5stack_core2_appcpu.dts index cd5cf5d0bf228..875d0eaea2ad0 100644 --- a/boards/m5stack/m5stack_core2/m5stack_core2_appcpu.dts +++ b/boards/m5stack/m5stack_core2/m5stack_core2_appcpu.dts @@ -18,14 +18,6 @@ }; }; -&cpu0 { - clock-frequency = ; -}; - -&cpu1 { - clock-frequency = ; -}; - &ipm0 { status = "okay"; }; diff --git a/boards/m5stack/m5stack_core2/m5stack_core2_procpu.dts b/boards/m5stack/m5stack_core2/m5stack_core2_procpu.dts index 7cd5bc187c9a4..fec843884ca83 100644 --- a/boards/m5stack/m5stack_core2/m5stack_core2_procpu.dts +++ b/boards/m5stack/m5stack_core2/m5stack_core2_procpu.dts @@ -73,14 +73,6 @@ }; }; -&cpu0 { - clock-frequency = ; -}; - -&cpu1 { - clock-frequency = ; -}; - &psram0 { reg = <0x3f800000 DT_SIZE_M(8)>; status = "disabled"; diff --git a/boards/m5stack/m5stack_stamps3/m5stack_stamps3_appcpu.dts b/boards/m5stack/m5stack_stamps3/m5stack_stamps3_appcpu.dts index a9e590b9bbf8b..ce947b579724c 100644 --- a/boards/m5stack/m5stack_stamps3/m5stack_stamps3_appcpu.dts +++ b/boards/m5stack/m5stack_stamps3/m5stack_stamps3_appcpu.dts @@ -17,14 +17,6 @@ }; }; -&cpu0 { - clock-frequency = ; -}; - -&cpu1 { - clock-frequency = ; -}; - &trng0 { status = "okay"; }; diff --git a/boards/m5stack/m5stack_stamps3/m5stack_stamps3_procpu.dts b/boards/m5stack/m5stack_stamps3/m5stack_stamps3_procpu.dts index f832f4618ba4b..522518f7e077c 100644 --- a/boards/m5stack/m5stack_stamps3/m5stack_stamps3_procpu.dts +++ b/boards/m5stack/m5stack_stamps3/m5stack_stamps3_procpu.dts @@ -45,14 +45,6 @@ }; }; -&cpu0 { - clock-frequency = ; -}; - -&cpu1 { - clock-frequency = ; -}; - &usb_serial { status = "okay"; }; diff --git a/boards/m5stack/m5stickc_plus/m5stickc_plus_appcpu.dts b/boards/m5stack/m5stickc_plus/m5stickc_plus_appcpu.dts index 8b7e74fdd988c..1911e4fe56d55 100644 --- a/boards/m5stack/m5stickc_plus/m5stickc_plus_appcpu.dts +++ b/boards/m5stack/m5stickc_plus/m5stickc_plus_appcpu.dts @@ -18,14 +18,6 @@ }; }; -&cpu0 { - clock-frequency = ; -}; - -&cpu1 { - clock-frequency = ; -}; - &ipm0 { status = "okay"; }; diff --git a/boards/m5stack/m5stickc_plus/m5stickc_plus_procpu.dts b/boards/m5stack/m5stickc_plus/m5stickc_plus_procpu.dts index c1418ed51c335..b397c7d5b05fd 100644 --- a/boards/m5stack/m5stickc_plus/m5stickc_plus_procpu.dts +++ b/boards/m5stack/m5stickc_plus/m5stickc_plus_procpu.dts @@ -60,14 +60,6 @@ }; }; -&cpu0 { - clock-frequency = ; -}; - -&cpu1 { - clock-frequency = ; -}; - &uart0 { status = "okay"; current-speed = <115200>; diff --git a/boards/m5stack/stamp_c3/stamp_c3.dts b/boards/m5stack/stamp_c3/stamp_c3.dts index 812c2aeaa86d8..e9d519a2a5f8f 100644 --- a/boards/m5stack/stamp_c3/stamp_c3.dts +++ b/boards/m5stack/stamp_c3/stamp_c3.dts @@ -38,10 +38,6 @@ }; }; -&cpu0 { - clock-frequency = ; -}; - &uart0 { status = "okay"; current-speed = <115200>; diff --git a/boards/olimex/olimex_esp32_evb/olimex_esp32_evb_appcpu.dts b/boards/olimex/olimex_esp32_evb/olimex_esp32_evb_appcpu.dts index c52b029ea552a..ae7a2e1e7f653 100644 --- a/boards/olimex/olimex_esp32_evb/olimex_esp32_evb_appcpu.dts +++ b/boards/olimex/olimex_esp32_evb/olimex_esp32_evb_appcpu.dts @@ -18,14 +18,6 @@ }; }; -&cpu0 { - clock-frequency = ; -}; - -&cpu1 { - clock-frequency = ; -}; - &ipm0 { status = "okay"; }; 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 63070f08e1cd1..e092f9766b594 100644 --- a/boards/olimex/olimex_esp32_evb/olimex_esp32_evb_procpu.dts +++ b/boards/olimex/olimex_esp32_evb/olimex_esp32_evb_procpu.dts @@ -53,14 +53,6 @@ }; }; -&cpu0 { - clock-frequency = ; -}; - -&cpu1 { - clock-frequency = ; -}; - uext_serial: &uart1 {}; uext_i2c: &i2c0 {}; uext_spi: &spi2 {}; diff --git a/boards/others/icev_wireless/icev_wireless.dts b/boards/others/icev_wireless/icev_wireless.dts index 8ed474200e0bc..6015780833554 100644 --- a/boards/others/icev_wireless/icev_wireless.dts +++ b/boards/others/icev_wireless/icev_wireless.dts @@ -47,10 +47,6 @@ }; }; -&cpu0 { - clock-frequency = ; -}; - &uart0 { current-speed = <115200>; pinctrl-0 = <&uart0_default>; diff --git a/boards/seeed/xiao_esp32c3/xiao_esp32c3.dts b/boards/seeed/xiao_esp32c3/xiao_esp32c3.dts index 8475709095b16..943cda08b7dbf 100644 --- a/boards/seeed/xiao_esp32c3/xiao_esp32c3.dts +++ b/boards/seeed/xiao_esp32c3/xiao_esp32c3.dts @@ -29,10 +29,6 @@ }; }; -&cpu0 { - clock-frequency = ; -}; - &uart0 { status = "okay"; current-speed = <115200>; diff --git a/boards/seeed/xiao_esp32s3/xiao_esp32s3_appcpu.dts b/boards/seeed/xiao_esp32s3/xiao_esp32s3_appcpu.dts index 672c52a5cbac5..f2cf95742ac14 100644 --- a/boards/seeed/xiao_esp32s3/xiao_esp32s3_appcpu.dts +++ b/boards/seeed/xiao_esp32s3/xiao_esp32s3_appcpu.dts @@ -17,14 +17,6 @@ }; }; -&cpu0 { - clock-frequency = ; -}; - -&cpu1 { - clock-frequency = ; -}; - &trng0 { status = "okay"; }; diff --git a/boards/seeed/xiao_esp32s3/xiao_esp32s3_procpu.dts b/boards/seeed/xiao_esp32s3/xiao_esp32s3_procpu.dts index ae232f4d22810..17c2ca3eeec43 100644 --- a/boards/seeed/xiao_esp32s3/xiao_esp32s3_procpu.dts +++ b/boards/seeed/xiao_esp32s3/xiao_esp32s3_procpu.dts @@ -38,14 +38,6 @@ }; -&cpu0 { - clock-frequency = ; -}; - -&cpu1 { - clock-frequency = ; -}; - &usb_serial { status = "okay"; }; diff --git a/boards/vcc-gnd/yd_esp32/yd_esp32_appcpu.dts b/boards/vcc-gnd/yd_esp32/yd_esp32_appcpu.dts index 6bed6d3840294..8501714220d48 100644 --- a/boards/vcc-gnd/yd_esp32/yd_esp32_appcpu.dts +++ b/boards/vcc-gnd/yd_esp32/yd_esp32_appcpu.dts @@ -18,14 +18,6 @@ }; }; -&cpu0 { - clock-frequency = ; -}; - -&cpu1 { - clock-frequency = ; -}; - &ipm0 { status = "okay"; }; diff --git a/boards/vcc-gnd/yd_esp32/yd_esp32_procpu.dts b/boards/vcc-gnd/yd_esp32/yd_esp32_procpu.dts index 2e748af71b98d..62b657c44d077 100644 --- a/boards/vcc-gnd/yd_esp32/yd_esp32_procpu.dts +++ b/boards/vcc-gnd/yd_esp32/yd_esp32_procpu.dts @@ -47,15 +47,6 @@ }; }; -&cpu0 { - clock-frequency = ; - cpu-power-states = <&light_sleep &deep_sleep>; -}; - -&cpu1 { - clock-frequency = ; -}; - &uart0 { status = "okay"; current-speed = <115200>; diff --git a/boards/waveshare/esp32s3_touch_lcd_1_28/esp32s3_touch_lcd_1_28_esp32s3_appcpu.dts b/boards/waveshare/esp32s3_touch_lcd_1_28/esp32s3_touch_lcd_1_28_esp32s3_appcpu.dts index 50301f22c2088..9b345338aa41c 100644 --- a/boards/waveshare/esp32s3_touch_lcd_1_28/esp32s3_touch_lcd_1_28_esp32s3_appcpu.dts +++ b/boards/waveshare/esp32s3_touch_lcd_1_28/esp32s3_touch_lcd_1_28_esp32s3_appcpu.dts @@ -15,14 +15,6 @@ }; }; -&cpu0 { - clock-frequency = ; -}; - -&cpu1 { - clock-frequency = ; -}; - &flash0 { status = "okay"; reg = <0x0 DT_SIZE_M(16)>; diff --git a/boards/waveshare/esp32s3_touch_lcd_1_28/esp32s3_touch_lcd_1_28_esp32s3_procpu.dts b/boards/waveshare/esp32s3_touch_lcd_1_28/esp32s3_touch_lcd_1_28_esp32s3_procpu.dts index 346c522142f66..c00b23ba14786 100644 --- a/boards/waveshare/esp32s3_touch_lcd_1_28/esp32s3_touch_lcd_1_28_esp32s3_procpu.dts +++ b/boards/waveshare/esp32s3_touch_lcd_1_28/esp32s3_touch_lcd_1_28_esp32s3_procpu.dts @@ -57,14 +57,6 @@ }; }; -&cpu0 { - clock-frequency = ; -}; - -&cpu1 { - clock-frequency = ; -}; - &flash0 { status = "okay"; reg = <0x0 DT_SIZE_M(16)>; diff --git a/boards/wemos/esp32s2_lolin_mini/esp32s2_lolin_mini.dts b/boards/wemos/esp32s2_lolin_mini/esp32s2_lolin_mini.dts index 53a598ad0ded6..14d6fd4b1d807 100644 --- a/boards/wemos/esp32s2_lolin_mini/esp32s2_lolin_mini.dts +++ b/boards/wemos/esp32s2_lolin_mini/esp32s2_lolin_mini.dts @@ -46,11 +46,6 @@ }; }; -&cpu0 { - clock-frequency = ; - cpu-power-states = <&deep_sleep &light_sleep>; -}; - &uart0 { status = "okay"; current-speed = <115200>; diff --git a/drivers/clock_control/clock_control_esp32.c b/drivers/clock_control/clock_control_esp32.c index 7aec123785d35..594763846decf 100644 --- a/drivers/clock_control/clock_control_esp32.c +++ b/drivers/clock_control/clock_control_esp32.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2020 Mohamed ElShahawi. - * Copyright (c) 2021 Espressif Systems (Shanghai) Co., Ltd. + * Copyright (c) 2021-2024 Espressif Systems (Shanghai) Co., Ltd. * * SPDX-License-Identifier: Apache-2.0 */ @@ -10,19 +10,21 @@ #define CPU_RESET_REASON RTC_SW_CPU_RESET #if defined(CONFIG_SOC_SERIES_ESP32) -#define DT_CPU_COMPAT cdns_tensilica_xtensa_lx6 +#define DT_CPU_COMPAT espressif_xtensa_lx6 #undef CPU_RESET_REASON #define CPU_RESET_REASON SW_CPU_RESET #include #include #include +#include #elif defined(CONFIG_SOC_SERIES_ESP32S2) -#define DT_CPU_COMPAT cdns_tensilica_xtensa_lx7 +#define DT_CPU_COMPAT espressif_xtensa_lx7 #include #include #include +#include #elif defined(CONFIG_SOC_SERIES_ESP32S3) -#define DT_CPU_COMPAT cdns_tensilica_xtensa_lx7 +#define DT_CPU_COMPAT espressif_xtensa_lx7 #include #include #include @@ -30,67 +32,33 @@ #define DT_CPU_COMPAT espressif_riscv #include #include -#include -#include -#include #endif /* CONFIG_SOC_SERIES_ESP32xx */ +#include +#include + #include #include #include +#include #include -#include -#include -#include #include -#include -#include #include #include #include -#include - -struct esp32_clock_config { - int clk_src_sel; - uint32_t cpu_freq; - uint32_t xtal_freq_sel; - int xtal_div; -}; - -static int clock_control_esp32_on(const struct device *dev, - clock_control_subsys_t sys) -{ - ARG_UNUSED(dev); - periph_module_enable((periph_module_t)sys); - return 0; -} +#include +#include +#include -static int clock_control_esp32_off(const struct device *dev, - clock_control_subsys_t sys) -{ - ARG_UNUSED(dev); - periph_module_disable((periph_module_t)sys); - return 0; -} - -static int clock_control_esp32_async_on(const struct device *dev, - clock_control_subsys_t sys, - clock_control_cb_t cb, - void *user_data) -{ - ARG_UNUSED(dev); - ARG_UNUSED(sys); - ARG_UNUSED(cb); - ARG_UNUSED(user_data); - return -ENOTSUP; -} +#include +LOG_MODULE_REGISTER(clock_control, CONFIG_CLOCK_CONTROL_LOG_LEVEL); static enum clock_control_status clock_control_esp32_get_status(const struct device *dev, clock_control_subsys_t sys) { ARG_UNUSED(dev); uint32_t clk_en_reg = periph_ll_get_clk_en_reg((periph_module_t)sys); - uint32_t clk_en_mask = periph_ll_get_clk_en_mask((periph_module_t)sys); + uint32_t clk_en_mask = periph_ll_get_clk_en_mask((periph_module_t)sys); if (DPORT_GET_PERI_REG_MASK(clk_en_reg, clk_en_mask)) { return CLOCK_CONTROL_STATUS_ON; @@ -98,17 +66,45 @@ static enum clock_control_status clock_control_esp32_get_status(const struct dev return CLOCK_CONTROL_STATUS_OFF; } -static int clock_control_esp32_get_rate(const struct device *dev, - clock_control_subsys_t sub_system, - uint32_t *rate) +static int clock_control_esp32_on(const struct device *dev, clock_control_subsys_t sys) { - ARG_UNUSED(sub_system); + enum clock_control_status status = clock_control_esp32_get_status(dev, sys); - rtc_cpu_freq_config_t config; + if (status == CLOCK_CONTROL_STATUS_ON) { + return -EALREADY; + } - rtc_clk_cpu_freq_get_config(&config); + periph_module_enable((periph_module_t)sys); - *rate = config.freq_mhz; + return 0; +} + +static int clock_control_esp32_off(const struct device *dev, clock_control_subsys_t sys) +{ + enum clock_control_status status = clock_control_esp32_get_status(dev, sys); + + if (status == CLOCK_CONTROL_STATUS_ON) { + periph_module_disable((periph_module_t)sys); + } + + return 0; +} + +static int clock_control_esp32_get_rate(const struct device *dev, clock_control_subsys_t sys, + uint32_t *rate) +{ + ARG_UNUSED(dev); + + switch ((int)sys) { + case ESP32_CLOCK_CONTROL_SUBSYS_RTC_FAST: + *rate = esp_clk_tree_lp_fast_get_freq_hz(ESP_CLK_TREE_SRC_FREQ_PRECISION_APPROX); + break; + case ESP32_CLOCK_CONTROL_SUBSYS_RTC_SLOW: + *rate = clk_hal_lp_slow_get_freq_hz(); + break; + default: + *rate = clk_hal_cpu_get_freq_hz(); + } return 0; } @@ -512,88 +508,218 @@ static void esp32_clock_perip_init(void) } #endif /* CONFIG_SOC_SERIES_ESP32C3 */ -static int clock_control_esp32_init(const struct device *dev) +static int esp32_select_rtc_slow_clk(uint8_t slow_clk) +{ + soc_rtc_slow_clk_src_t rtc_slow_clk_src = slow_clk & RTC_CNTL_ANA_CLK_RTC_SEL_V; + uint32_t cal_val = 0; + /* number of times to repeat 32k XTAL calibration + * before giving up and switching to the internal RC + */ + int retry_32k_xtal = 3; + + do { + if (rtc_slow_clk_src == ESP32_RTC_SLOW_CLK_SRC_XTAL32K) { + /* 32k XTAL oscillator needs to be enabled and running before it can + * be used. Hardware doesn't have a direct way of checking if the + * oscillator is running. Here we use rtc_clk_cal function to count + * the number of main XTAL cycles in the given number of 32k XTAL + * oscillator cycles. If the 32k XTAL has not started up, calibration + * will time out, returning 0. + */ + LOG_DBG("waiting for 32k oscillator to start up"); + if (slow_clk == ESP32_RTC_SLOW_CLK_SRC_XTAL32K) { + rtc_clk_32k_enable(true); + } else if (slow_clk == ESP32_RTC_SLOW_CLK_32K_EXT_OSC) { + rtc_clk_32k_enable_external(); + } + /* When CONFIG_RTC_CLK_CAL_CYCLES is set to 0, clock calibration will not be + * performed at startup. + */ + if (CONFIG_RTC_CLK_CAL_CYCLES > 0) { + cal_val = rtc_clk_cal(RTC_CAL_32K_XTAL, CONFIG_RTC_CLK_CAL_CYCLES); + if (cal_val == 0) { + if (retry_32k_xtal-- > 0) { + continue; + } + LOG_ERR("32 kHz XTAL not found"); + return -ENODEV; + } + } + } else if (rtc_slow_clk_src == SOC_RTC_SLOW_CLK_SRC_RC_FAST_D256) { + rtc_clk_8m_enable(true, true); + } + rtc_clk_slow_src_set(rtc_slow_clk_src); + + if (CONFIG_RTC_CLK_CAL_CYCLES > 0) { + cal_val = rtc_clk_cal(RTC_CAL_RTC_MUX, CONFIG_RTC_CLK_CAL_CYCLES); + } else { + const uint64_t cal_dividend = (1ULL << RTC_CLK_CAL_FRACT) * 1000000ULL; + + cal_val = (uint32_t)(cal_dividend / rtc_clk_slow_freq_get_hz()); + } + } while (cal_val == 0); + + LOG_DBG("RTC_SLOW_CLK calibration value: %d", cal_val); + + esp_clk_slowclk_cal_set(cal_val); + + return 0; +} + +static int esp32_cpu_clock_configure(const struct esp32_cpu_clock_config *cpu_cfg) { - const struct esp32_clock_config *cfg = dev->config; rtc_cpu_freq_config_t old_config; rtc_cpu_freq_config_t new_config; - bool res; + rtc_clk_config_t rtc_clk_cfg = RTC_CLK_CONFIG_DEFAULT(); + uint32_t uart_clock_src_hz; + bool ret; + + rtc_clk_cfg.xtal_freq = cpu_cfg->xtal_freq; + rtc_clk_cfg.cpu_freq_mhz = cpu_cfg->cpu_freq; - /* wait uart output to be cleared */ esp_rom_uart_tx_wait_idle(ESP_CONSOLE_UART_NUM); - /* reset default config to use dts config */ - if (rtc_clk_apb_freq_get() < APB_CLK_FREQ || rtc_get_reset_reason(0) != CPU_RESET_REASON) { - rtc_clk_config_t clk_cfg = RTC_CLK_CONFIG_DEFAULT(); + REG_SET_FIELD(RTC_CNTL_REG, RTC_CNTL_SCK_DCAP, rtc_clk_cfg.slow_clk_dcap); + REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_CK8M_DFREQ, rtc_clk_cfg.clk_8m_dfreq); - clk_cfg.xtal_freq = cfg->xtal_freq_sel; - clk_cfg.cpu_freq_mhz = cfg->cpu_freq; - clk_cfg.slow_clk_src = rtc_clk_slow_freq_get(); - clk_cfg.fast_clk_src = rtc_clk_fast_freq_get(); - rtc_clk_init(clk_cfg); - } +#if !defined(CONFIG_SOC_SERIES_ESP32) + /* Configure 150k clock division */ + rtc_clk_divider_set(rtc_clk_cfg.clk_rtc_clk_div); - rtc_clk_fast_freq_set(RTC_FAST_FREQ_8M); + /* Configure 8M clock division */ + rtc_clk_8m_divider_set(rtc_clk_cfg.clk_8m_clk_div); +#else + REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_CK8M_DIV_SEL, rtc_clk_cfg.clk_8m_div - 1); +#endif + /* Reset (disable) i2c internal bus for all regi2c registers */ + regi2c_ctrl_ll_i2c_reset(); + /* Enable the internal bus used to configure BBPLL */ + regi2c_ctrl_ll_i2c_bbpll_enable(); +#if defined(CONFIG_SOC_SERIES_ESP32S2) || defined(CONFIG_SOC_SERIES_ESP32) + regi2c_ctrl_ll_i2c_apll_enable(); +#endif + +#if !defined(CONFIG_SOC_SERIES_ESP32S2) + rtc_clk_xtal_freq_update(rtc_clk_cfg.xtal_freq); +#endif + rtc_clk_apb_freq_update(rtc_clk_cfg.xtal_freq * MHZ(1)); + /* Set CPU frequency */ rtc_clk_cpu_freq_get_config(&old_config); - const uint32_t old_freq_mhz = old_config.freq_mhz; - const uint32_t new_freq_mhz = cfg->cpu_freq; + ret = rtc_clk_cpu_freq_mhz_to_config(rtc_clk_cfg.cpu_freq_mhz, &new_config); + if (!ret || (new_config.source != cpu_cfg->clk_src)) { + LOG_ERR("invalid CPU frequency value"); + return -EINVAL; + } + + rtc_clk_cpu_freq_set_config(&new_config); + + /* Re-calculate the ccount to make time calculation correct. */ + esp_cpu_set_cycle_count((uint64_t)esp_cpu_get_cycle_count() * rtc_clk_cfg.cpu_freq_mhz / + old_config.freq_mhz); + + uart_clock_src_hz = esp_clk_apb_freq(); + +#if !defined(ESP_CONSOLE_UART_NONE) + esp_rom_uart_set_clock_baudrate(ESP_CONSOLE_UART_NUM, uart_clock_src_hz, + ESP_CONSOLE_UART_BAUDRATE); +#endif + return 0; +} + +static int clock_control_esp32_configure(const struct device *dev, clock_control_subsys_t sys, + void *data) +{ - res = rtc_clk_cpu_freq_mhz_to_config(cfg->cpu_freq, &new_config); - if (!res) { - return -ENOTSUP; + const struct esp32_clock_config *cfg = dev->config; + struct esp32_clock_config *new_cfg = data; + int ret = 0; + + switch ((int)sys) { + case ESP32_CLOCK_CONTROL_SUBSYS_RTC_FAST: + rtc_clk_fast_src_set(new_cfg->rtc.rtc_fast_clock_src); + break; + case ESP32_CLOCK_CONTROL_SUBSYS_RTC_SLOW: + ret = esp32_select_rtc_slow_clk(new_cfg->rtc.rtc_slow_clock_src); + break; + case ESP32_CLOCK_CONTROL_SUBSYS_CPU: + /* Normalize frequency */ + new_cfg->cpu.xtal_freq = new_cfg->cpu.xtal_freq > MHZ(1) + ? new_cfg->cpu.xtal_freq / MHZ(1) + : new_cfg->cpu.xtal_freq; + new_cfg->cpu.cpu_freq = new_cfg->cpu.cpu_freq > MHZ(1) + ? new_cfg->cpu.cpu_freq / MHZ(1) + : new_cfg->cpu.cpu_freq; + ret = esp32_cpu_clock_configure(&new_cfg->cpu); + break; + default: + LOG_ERR("Unsupported subsystem %d", (int)sys); + return -EINVAL; } + return ret; +} - if (cfg->xtal_div >= 0) { - new_config.div = cfg->xtal_div; +static int clock_control_esp32_init(const struct device *dev) +{ + const struct esp32_clock_config *cfg = dev->config; + soc_reset_reason_t rst_reas; + rtc_config_t rtc_cfg = RTC_CONFIG_DEFAULT(); + bool ret; + + rst_reas = esp_rom_get_reset_reason(0); +#if !defined(CONFIG_SOC_SERIES_ESP32) + if (rst_reas == RESET_REASON_CHIP_POWER_ON +#if SOC_EFUSE_HAS_EFUSE_RST_BUG + || rst_reas == RESET_REASON_CORE_EFUSE_CRC +#endif + ) { + rtc_cfg.cali_ocode = 1; } +#endif + rtc_init(rtc_cfg); - if (cfg->clk_src_sel >= 0) { - new_config.source = cfg->clk_src_sel; + ret = esp32_cpu_clock_configure(&cfg->cpu); + if (ret) { + LOG_ERR("Failed to configure CPU clock"); + return ret; } - /* set new configuration */ - rtc_clk_cpu_freq_set_config(&new_config); + rtc_clk_fast_src_set(cfg->rtc.rtc_fast_clock_src); - /* Re-calculate the ccount to make time calculation correct */ - esp_cpu_set_cycle_count((uint64_t)esp_cpu_get_cycle_count() * new_freq_mhz / old_freq_mhz); + ret = esp32_select_rtc_slow_clk(cfg->rtc.rtc_slow_clock_src); + if (ret) { + LOG_ERR("Failed to configure RTC clock"); + return ret; + } esp32_clock_perip_init(); - uint32_t clock_hz = esp_clk_apb_freq(); -#if ESP_ROM_UART_CLK_IS_XTAL - clock_hz = esp_clk_xtal_freq(); -#endif - -#if !defined(ESP_CONSOLE_UART_NONE) - esp_rom_uart_set_clock_baudrate(ESP_CONSOLE_UART_NUM, - clock_hz, ESP_CONSOLE_UART_BAUDRATE); -#endif return 0; } static const struct clock_control_driver_api clock_control_esp32_api = { .on = clock_control_esp32_on, .off = clock_control_esp32_off, - .async_on = clock_control_esp32_async_on, .get_rate = clock_control_esp32_get_rate, .get_status = clock_control_esp32_get_status, + .configure = clock_control_esp32_configure, }; -#define ESP32_CLOCK_SOURCE \ - COND_CODE_1(DT_NODE_HAS_PROP(DT_INST(0, DT_CPU_COMPAT), clock_source), \ - (DT_PROP(DT_INST(0, DT_CPU_COMPAT), clock_source)), (-1)) +static const struct esp32_cpu_clock_config esp32_cpu_clock_config0 = { + .clk_src = DT_PROP(DT_INST(0, DT_CPU_COMPAT), clock_source), + .cpu_freq = (DT_PROP(DT_INST(0, DT_CPU_COMPAT), clock_frequency) / MHZ(1)), + .xtal_freq = ((DT_PROP(DT_INST(0, DT_CPU_COMPAT), xtal_freq)) / MHZ(1)), +}; -#define ESP32_CLOCK_XTAL_DIV \ - COND_CODE_1(DT_NODE_HAS_PROP(0, xtal_div), \ - (DT_INST_PROP(0, xtal_div)), (-1)) +static const struct esp32_rtc_clock_config esp32_rtc_clock_config0 = { + .rtc_fast_clock_src = DT_PROP(DT_INST(0, espressif_esp32_rtc), fast_clk_src), + .rtc_slow_clock_src = DT_PROP(DT_INST(0, espressif_esp32_rtc), slow_clk_src) +}; static const struct esp32_clock_config esp32_clock_config0 = { - .clk_src_sel = ESP32_CLOCK_SOURCE, - .cpu_freq = DT_PROP(DT_INST(0, DT_CPU_COMPAT), clock_frequency) / 1000000, - .xtal_freq_sel = DT_INST_PROP(0, xtal_freq), - .xtal_div = ESP32_CLOCK_XTAL_DIV + .cpu = esp32_cpu_clock_config0, + .rtc = esp32_rtc_clock_config0 }; DEVICE_DT_DEFINE(DT_NODELABEL(rtc), diff --git a/drivers/counter/Kconfig.esp32_tmr b/drivers/counter/Kconfig.esp32_tmr index 52f1c55c695bb..93f6e2503e2c3 100644 --- a/drivers/counter/Kconfig.esp32_tmr +++ b/drivers/counter/Kconfig.esp32_tmr @@ -10,3 +10,11 @@ config COUNTER_TMR_ESP32 help Enables the Counter driver API based on Espressif's General Purpose Timers for ESP32 series devices. + +config COUNTER_TMR_RTC_ESP32 + bool "ESP32 Counter Driver based on GP-Timers" + default y + depends on DT_HAS_ESPRESSIF_ESP32_RTC_TIMER_ENABLED + help + Enables the Counter driver API based on Espressif's General + Purpose Timers for ESP32 series devices. diff --git a/drivers/counter/counter_esp32_rtc.c b/drivers/counter/counter_esp32_rtc.c index 0b7e8bbbb27cc..379a9f0e57b29 100644 --- a/drivers/counter/counter_esp32_rtc.c +++ b/drivers/counter/counter_esp32_rtc.c @@ -12,11 +12,15 @@ */ #include "soc/rtc_cntl_reg.h" #include "soc/rtc.h" +#include +#include #include #include #include #include +#include +#include #if defined(CONFIG_SOC_SERIES_ESP32C3) #include @@ -38,21 +42,25 @@ static void counter_esp32_isr(void *arg); struct counter_esp32_config { struct counter_config_info counter_info; int irq_source; + const struct device *clock_dev; }; struct counter_esp32_data { struct counter_alarm_cfg alarm_cfg; uint32_t ticks; + uint32_t clk_src_freq; }; static int counter_esp32_init(const struct device *dev) { const struct counter_esp32_config *cfg = dev->config; + struct counter_esp32_data *data = dev->data; - /* SLOW_CK is the default clk source */ - if (cfg->counter_info.freq != rtc_clk_slow_freq_get_hz()) { - return -EINVAL; - } + + /* RTC_SLOW_CLK is the default clk source */ + clock_control_get_rate(cfg->clock_dev, + (clock_control_subsys_t)ESP32_CLOCK_CONTROL_SUBSYS_RTC_SLOW, + &data->clk_src_freq); esp_intr_alloc(cfg->irq_source, 0, @@ -80,22 +88,14 @@ static int counter_esp32_stop(const struct device *dev) * reset, will not stop or reset the RTC timer * ESP32 TRM v4.6 sec. 31.3.11 */ - return -ENOTSUP; + return 0; } static int counter_esp32_get_value(const struct device *dev, uint32_t *ticks) { ARG_UNUSED(dev); - SET_PERI_REG_MASK(RTC_CNTL_TIME_UPDATE_REG, RTC_CNTL_TIME_UPDATE); -#if defined(CONFIG_SOC_SERIES_ESP32) - while (GET_PERI_REG_MASK(RTC_CNTL_TIME_UPDATE_REG, RTC_CNTL_TIME_VALID) == 0) { - /* might take 1 RTC slowclk period, don't flood RTC bus */ - k_sleep(K_USEC(1)); - } - SET_PERI_REG_MASK(RTC_CNTL_INT_CLR_REG, RTC_CNTL_TIME_VALID_INT_CLR); -#endif - *ticks = (uint32_t) READ_PERI_REG(RTC_CNTL_TIME0_REG); + *ticks = (uint32_t) rtc_cntl_ll_get_rtc_time(); return 0; } @@ -106,26 +106,32 @@ static int counter_esp32_set_alarm(const struct device *dev, uint8_t chan_id, ARG_UNUSED(chan_id); struct counter_esp32_data *data = dev->data; uint32_t now; + uint32_t ticks = 0; + +#if defined(CONFIG_SOC_SERIES_ESP32) || defined(CONFIG_SOC_SERIES_ESP32C3) + /* In ESP32/C3 Series the min possible value is 30 us*/ + if (counter_ticks_to_us(dev, alarm_cfg->ticks) < 30) { + return -EINVAL; + } +#endif + data->alarm_cfg.callback = alarm_cfg->callback; + data->alarm_cfg.user_data = alarm_cfg->user_data; counter_esp32_get_value(dev, &now); - if ((alarm_cfg->flags & COUNTER_ALARM_CFG_ABSOLUTE) == 0) { - WRITE_PERI_REG(RTC_CNTL_SLP_TIMER0_REG, (now + alarm_cfg->ticks)); - } else { - WRITE_PERI_REG(RTC_CNTL_SLP_TIMER0_REG, alarm_cfg->ticks); - } + ticks = (alarm_cfg->flags & COUNTER_ALARM_CFG_ABSOLUTE) ? alarm_cfg->ticks + : now + alarm_cfg->ticks; + + rtc_cntl_ll_set_wakeup_timer(ticks); /* RTC main timer set alarm value */ CLEAR_PERI_REG_MASK(RTC_CNTL_SLP_TIMER1_REG, 0xffffffff); - /* RTC main timer interrupt enable */ - SET_PERI_REG_MASK(RTC_CNTL_INT_ENA_REG, RTC_CNTL_MAIN_TIMER_INT_ENA); - /* RTC main timer set alarm enable */ SET_PERI_REG_MASK(RTC_CNTL_SLP_TIMER1_REG, RTC_CNTL_MAIN_TIMER_ALARM_EN); - data->alarm_cfg.callback = alarm_cfg->callback; - data->alarm_cfg.user_data = alarm_cfg->user_data; + /* RTC main timer interrupt enable */ + SET_PERI_REG_MASK(RTC_CNTL_INT_ENA_REG, RTC_CNTL_MAIN_TIMER_INT_ENA); return 0; } @@ -172,9 +178,16 @@ static uint32_t counter_esp32_get_pending_int(const struct device *dev) */ static uint32_t counter_esp32_get_top_value(const struct device *dev) { - const struct counter_config_info *info = dev->config; + const struct counter_esp32_config *cfg = dev->config; + + return cfg->counter_info.max_top_value; +} + +static uint32_t counter_esp32_get_freq(const struct device *dev) +{ + struct counter_esp32_data *data = dev->data; - return info->max_top_value; + return data->clk_src_freq; } static struct counter_esp32_data counter_data; @@ -182,10 +195,10 @@ static struct counter_esp32_data counter_data; static const struct counter_esp32_config counter_config = { .counter_info = { .max_top_value = UINT32_MAX, - .freq = DT_INST_PROP(0, slow_clk_freq), .flags = COUNTER_CONFIG_INFO_COUNT_UP, .channels = 1 }, + .clock_dev = DEVICE_DT_GET(DT_INST_CLOCKS_CTLR(0)), .irq_source = DT_INST_IRQN(0), }; @@ -198,6 +211,7 @@ static const struct counter_driver_api rtc_timer_esp32_api = { .set_top_value = counter_esp32_set_top_value, .get_pending_int = counter_esp32_get_pending_int, .get_top_value = counter_esp32_get_top_value, + .get_freq = counter_esp32_get_freq, }; static void counter_esp32_isr(void *arg) @@ -222,6 +236,6 @@ DEVICE_DT_INST_DEFINE(0, NULL, &counter_data, &counter_config, - PRE_KERNEL_1, + POST_KERNEL, CONFIG_COUNTER_INIT_PRIORITY, &rtc_timer_esp32_api); diff --git a/drivers/timer/esp32_sys_timer.c b/drivers/timer/esp32_sys_timer.c index 040807299116e..0fa888f674580 100644 --- a/drivers/timer/esp32_sys_timer.c +++ b/drivers/timer/esp32_sys_timer.c @@ -156,5 +156,5 @@ static int sys_clock_driver_init(void) return 0; } -SYS_INIT(sys_clock_driver_init, PRE_KERNEL_2, +SYS_INIT(sys_clock_driver_init, PRE_KERNEL_1, CONFIG_SYSTEM_CLOCK_INIT_PRIORITY); diff --git a/dts/bindings/clock/espressif,esp32-rtc.yaml b/dts/bindings/clock/espressif,esp32-rtc.yaml index e30b027a46660..c5ba502398327 100644 --- a/dts/bindings/clock/espressif,esp32-rtc.yaml +++ b/dts/bindings/clock/espressif,esp32-rtc.yaml @@ -11,14 +11,32 @@ properties: reg: required: true - xtal-freq: + fast-clk-src: type: int required: true - description: Value of the external XTAL connected to ESP32. - - xtal-div: + description: | + RTC fast clock source. + - 0: ESP32_RTC_FAST_CLK_SRC_XTAL_D2 - Main XTAL divided by 2 (C3/S3) + ESP32_RTC_FAST_CLK_SRC_XTAL_D4 Main XTAL divided by 4 (ESP32/S2) + - 1: ESP32_RTC_FAST_CLK_SRC_RC_FAST - 8 MHz + enum: + - 0 + - 1 + + slow-clk-src: type: int - description: Divisor value for XTAL Clock, CPU_CLK = XTAL_FREQ / xtal-div + required: true + description: | + RTC slow clock source. Default to + - 0: ESP32_RTC_SLOW_CLK_SRC_RC_SLOW - 136 KHz (C3/S3) - 90 kHz (S2) - 150 kHz (ESP32) + - 1: ESP32_RTC_SLOW_CLK_SRC_XTAL32K - 32,768U KHz + - 2: ESP32_RTC_SLOW_CLK_SRC_RC_FAST_D256 - 17,5 MHz + - 9: ESP32_RTC_SLOW_CLK_32K_EXT_OSC - External 32k oscillator connected to 32K_XP pin + enum: + - 0 + - 1 + - 2 + - 9 "#clock-cells": const: 1 diff --git a/dts/bindings/counter/espressif,esp32-rtc-timer.yaml b/dts/bindings/counter/espressif,esp32-rtc-timer.yaml index 86d5cd6887630..a8bc1c1165f01 100644 --- a/dts/bindings/counter/espressif,esp32-rtc-timer.yaml +++ b/dts/bindings/counter/espressif,esp32-rtc-timer.yaml @@ -15,11 +15,4 @@ description: | include: base.yaml -properties: - slow-clk-freq: - description: | - The slow clock input frequency for the RTC Timer. - type: int - required: true - compatible: "espressif,esp32-rtc-timer" diff --git a/dts/bindings/cpu/espressif,riscv.yaml b/dts/bindings/cpu/espressif,riscv.yaml index a93894cd946ff..374d51c6a2fd6 100644 --- a/dts/bindings/cpu/espressif,riscv.yaml +++ b/dts/bindings/cpu/espressif,riscv.yaml @@ -9,5 +9,24 @@ include: riscv,cpus.yaml properties: clock-source: + required: true type: int - description: cpu clock source + description: | + Defines the CPU clock source, each corresponding to different frequencies: + - 0: ESP32_CPU_CLK_SRC_XTAL - Uses the external crystal clock typically at 40 MHz. + - 1: ESP32_CPU_CLK_SRC_PLL - Utilizes an internal PLL which operates at either + 320 MHz or 480 MHz. + - 2: ESP32_CPU_CLK_SRC_RC_FAST - Employs an internal fast RC oscillator with + frequency of 17.5 MHz. + enum: + - 0 + - 1 + - 2 + + xtal-freq: + required: true + type: int + description: Value of the external XTAL connected to ESP32. This is typically 40 MHz. + enum: + - 40000000 + - 32000000 diff --git a/dts/bindings/cpu/espressif,xtensa-lx6.yaml b/dts/bindings/cpu/espressif,xtensa-lx6.yaml new file mode 100644 index 0000000000000..24dd830cb010d --- /dev/null +++ b/dts/bindings/cpu/espressif,xtensa-lx6.yaml @@ -0,0 +1,34 @@ +# Copyright (c) 2024 Espressif Systems (Shanghai) Co., Ltd. +# SPDX-License-Identifier: Apache-2.0 + +description: Espressif Xtensa CPU + +compatible: "espressif,xtensa-lx6" + +include: cdns,tensilica-xtensa-lx6.yaml + +properties: + clock-source: + required: true + type: int + description: | + Defines the CPU clock source, each corresponding to different frequencies: + - 0: ESP32_CPU_CLK_SRC_XTAL - Uses the external crystal clock typically at 40 MHz. + - 1: ESP32_CPU_CLK_SRC_PLL - Utilizes an internal PLL which operates at either + 320 MHz or 480 MHz. + - 2: ESP32_CPU_CLK_SRC_RC_FAST - Employs an internal fast RC oscillator with + frequency of 17.5 MHz. 8 MHz for ESP32S2. + - 3: APLL_CLK - 16 Mhz ~ 128 MHz + enum: + - 0 + - 1 + - 2 + - 3 + + xtal-freq: + type: int + required: true + description: Value of the external XTAL connected to ESP32. + enum: + - 40000000 + - 32000000 diff --git a/dts/bindings/cpu/espressif,xtensa-lx7.yaml b/dts/bindings/cpu/espressif,xtensa-lx7.yaml new file mode 100644 index 0000000000000..33c6503122bb8 --- /dev/null +++ b/dts/bindings/cpu/espressif,xtensa-lx7.yaml @@ -0,0 +1,34 @@ +# Copyright (c) 2024 Espressif Systems (Shanghai) Co., Ltd. +# SPDX-License-Identifier: Apache-2.0 + +description: Espressif Xtensa CPU + +compatible: "espressif,xtensa-lx7" + +include: cdns,tensilica-xtensa-lx7.yaml + +properties: + clock-source: + type: int + required: true + description: | + Defines the CPU clock source, each corresponding to different frequencies: + - 0: ESP32_CPU_CLK_SRC_XTAL - Uses the external crystal clock typically at 40 MHz. + - 1: ESP32_CPU_CLK_SRC_PLL - Utilizes an internal PLL which operates at either + 320 MHz or 480 MHz. + - 2: ESP32_CPU_CLK_SRC_RC_FAST - Employs an internal fast RC oscillator with + frequency of 17.5 MHz. 8 MHz for ESP32S2. + - 3: APLL_CLK - 16 Mhz ~ 128 MHz (ESP32S2 Only) + enum: + - 0 + - 1 + - 2 + - 3 + + xtal-freq: + type: int + required: true + description: Value of the external XTAL connected to ESP32. + enum: + - 40000000 + - 32000000 diff --git a/dts/riscv/espressif/esp32c3/esp32c3_common.dtsi b/dts/riscv/espressif/esp32c3/esp32c3_common.dtsi index 6ad2f61286692..7c0962bec7a19 100644 --- a/dts/riscv/espressif/esp32c3/esp32c3_common.dtsi +++ b/dts/riscv/espressif/esp32c3/esp32c3_common.dtsi @@ -4,6 +4,7 @@ * SPDX-License-Identifier: Apache-2.0 */ #include +#include #include #include #include @@ -35,6 +36,9 @@ riscv,isa = "rv32imc_zicsr"; reg = <0>; cpu-power-states = <&light_sleep &deep_sleep>; + clock-source = ; + clock-frequency = ; + xtal-freq = ; }; power-states { @@ -95,17 +99,19 @@ rtc: rtc@60008000 { compatible = "espressif,esp32-rtc"; reg = <0x60008000 0x1000>; - xtal-freq = ; + fast-clk-src = ; + slow-clk-src = ; #clock-cells = <1>; status = "okay"; + }; - rtc_timer: rtc_timer { - compatible = "espressif,esp32-rtc-timer"; - slow-clk-freq = ; - interrupts = ; - interrupt-parent = <&intc>; - status = "okay"; - }; + rtc_timer: rtc_timer@60008004 { + reg = <0x60008004 0xC>; + compatible = "espressif,esp32-rtc-timer"; + clocks = <&rtc ESP32_MODULE_MAX>; + interrupts = ; + interrupt-parent = <&intc>; + status = "okay"; }; flash: flash-controller@60002000 { diff --git a/dts/xtensa/espressif/esp32/esp32_common.dtsi b/dts/xtensa/espressif/esp32/esp32_common.dtsi index 82a92ed00a878..d721dd08a2c9e 100644 --- a/dts/xtensa/espressif/esp32/esp32_common.dtsi +++ b/dts/xtensa/espressif/esp32/esp32_common.dtsi @@ -4,6 +4,7 @@ * SPDX-License-Identifier: Apache-2.0 */ #include +#include #include #include #include @@ -26,15 +27,21 @@ cpu0: cpu@0 { device_type = "cpu"; - compatible = "cdns,tensilica-xtensa-lx6"; + compatible = "espressif,xtensa-lx6"; reg = <0>; cpu-power-states = <&light_sleep &deep_sleep>; + clock-source = ; + clock-frequency = ; + xtal-freq = ; }; cpu1: cpu@1 { device_type = "cpu"; - compatible = "cdns,tensilica-xtensa-lx6"; + compatible = "espressif,xtensa-lx6"; reg = <1>; + clock-source = ; + clock-frequency = ; + xtal-freq = ; }; power-states { @@ -107,17 +114,20 @@ rtc: rtc@3ff48000 { compatible = "espressif,esp32-rtc"; reg = <0x3ff48000 0x0D8>; - xtal-freq = ; + fast-clk-src = ; + slow-clk-src = ; #clock-cells = <1>; status = "okay"; - rtc_timer: rtc_timer { - compatible = "espressif,esp32-rtc-timer"; - slow-clk-freq = ; - interrupts = ; - interrupt-parent = <&intc>; - status = "okay"; - }; + }; + + rtc_timer: rtc_timer@3ff48004 { + reg = <0x3ff48004 0xC>; + compatible = "espressif,esp32-rtc-timer"; + clocks = <&rtc ESP32_MODULE_MAX>; + interrupts = ; + interrupt-parent = <&intc>; + status = "okay"; }; flash: flash-controller@3ff42000 { diff --git a/dts/xtensa/espressif/esp32s2/esp32s2_common.dtsi b/dts/xtensa/espressif/esp32s2/esp32s2_common.dtsi index 1bb8c000ed59f..e8491c338e79b 100644 --- a/dts/xtensa/espressif/esp32s2/esp32s2_common.dtsi +++ b/dts/xtensa/espressif/esp32s2/esp32s2_common.dtsi @@ -4,6 +4,7 @@ * SPDX-License-Identifier: Apache-2.0 */ #include +#include #include #include #include @@ -32,9 +33,12 @@ cpu0: cpu@0 { device_type = "cpu"; - compatible = "cdns,tensilica-xtensa-lx7"; + compatible = "espressif,xtensa-lx7"; reg = <0>; cpu-power-states = <&light_sleep &deep_sleep>; + clock-source = ; + clock-frequency = ; + xtal-freq = ; }; power-states { @@ -86,17 +90,20 @@ rtc: rtc@3f408000 { compatible = "espressif,esp32-rtc"; reg = <0x3f408000 0x0D8>; - xtal-freq = ; + fast-clk-src = ; + slow-clk-src = ; #clock-cells = <1>; status = "okay"; - rtc_timer: rtc_timer { - compatible = "espressif,esp32-rtc-timer"; - slow-clk-freq = ; - interrupts = ; - interrupt-parent = <&intc>; - status = "okay"; - }; + }; + + rtc_timer: rtc_timer@3f408004 { + reg = <0x3f408004 0xC>; + compatible = "espressif,esp32-rtc-timer"; + clocks = <&rtc ESP32_MODULE_MAX>; + interrupts = ; + interrupt-parent = <&intc>; + status = "okay"; }; flash: flash-controller@3f402000 { diff --git a/dts/xtensa/espressif/esp32s3/esp32s3_common.dtsi b/dts/xtensa/espressif/esp32s3/esp32s3_common.dtsi index b02d38410ada1..62135a34ac3fa 100644 --- a/dts/xtensa/espressif/esp32s3/esp32s3_common.dtsi +++ b/dts/xtensa/espressif/esp32s3/esp32s3_common.dtsi @@ -4,6 +4,7 @@ * SPDX-License-Identifier: Apache-2.0 */ #include +#include #include #include #include @@ -30,15 +31,21 @@ cpu0: cpu@0 { device_type = "cpu"; - compatible = "cdns,tensilica-xtensa-lx7"; + compatible = "espressif,xtensa-lx7"; reg = <0>; cpu-power-states = <&light_sleep &deep_sleep>; + clock-source = ; + clock-frequency = ; + xtal-freq = ; }; cpu1: cpu@1 { device_type = "cpu"; - compatible = "cdns,tensilica-xtensa-lx7"; + compatible = "espressif,xtensa-lx7"; reg = <1>; + clock-source = ; + clock-frequency = ; + xtal-freq = ; }; power-states { @@ -100,17 +107,20 @@ rtc: rtc@60021000 { compatible = "espressif,esp32-rtc"; reg = <0x60021000 0x2000>; - xtal-freq = ; + fast-clk-src = ; + slow-clk-src = ; #clock-cells = <1>; status = "okay"; - rtc_timer: rtc_timer { - compatible = "espressif,esp32-rtc-timer"; - slow-clk-freq = ; - interrupts = ; - interrupt-parent = <&intc>; - status = "okay"; - }; + }; + + rtc_timer: rtc_timer@60008004 { + reg = <0x60008004 0xC>; + compatible = "espressif,esp32-rtc-timer"; + clocks = <&rtc ESP32_MODULE_MAX>; + interrupts = ; + interrupt-parent = <&intc>; + status = "okay"; }; flash: flash-controller@60002000 { diff --git a/include/zephyr/drivers/clock_control/esp32_clock_control.h b/include/zephyr/drivers/clock_control/esp32_clock_control.h new file mode 100644 index 0000000000000..d74b2c0aeff28 --- /dev/null +++ b/include/zephyr/drivers/clock_control/esp32_clock_control.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2024 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_DRIVERS_CLOCK_CONTROL_ESP32_CLOCK_CONTROL_H_ +#define ZEPHYR_INCLUDE_DRIVERS_CLOCK_CONTROL_ESP32_CLOCK_CONTROL_H_ + +#if defined(CONFIG_SOC_SERIES_ESP32) +#include +#elif defined(CONFIG_SOC_SERIES_ESP32S2) +#include +#elif defined(CONFIG_SOC_SERIES_ESP32S3) +#include +#elif defined(CONFIG_SOC_SERIES_ESP32C3) +#include +#endif /* CONFIG_SOC_SERIES_ESP32xx */ + +#define ESP32_CLOCK_CONTROL_SUBSYS_CPU 50 +#define ESP32_CLOCK_CONTROL_SUBSYS_RTC_FAST 51 +#define ESP32_CLOCK_CONTROL_SUBSYS_RTC_SLOW 52 + +struct esp32_cpu_clock_config { + int clk_src; + uint32_t cpu_freq; + uint32_t xtal_freq; +}; + +struct esp32_rtc_clock_config { + uint32_t rtc_fast_clock_src; + uint32_t rtc_slow_clock_src; +}; + +struct esp32_clock_config { + struct esp32_cpu_clock_config cpu; + struct esp32_rtc_clock_config rtc; +}; + +#endif /* ZEPHYR_INCLUDE_DRIVERS_CLOCK_CONTROL_ESP32_CLOCK_CONTROL_H_ */ diff --git a/include/zephyr/dt-bindings/clock/esp32_clock.h b/include/zephyr/dt-bindings/clock/esp32_clock.h index 99ab3c7004b2a..db4abbf02f7aa 100644 --- a/include/zephyr/dt-bindings/clock/esp32_clock.h +++ b/include/zephyr/dt-bindings/clock/esp32_clock.h @@ -8,32 +8,37 @@ #ifndef ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_ESP32_H_ #define ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_ESP32_H_ -/* System Clock Source */ -#define ESP32_CLK_SRC_XTAL 0U -#define ESP32_CLK_SRC_PLL 1U -#define ESP32_CLK_SRC_RTC8M 2U -#define ESP32_CLK_SRC_APLL 3U +/* Supported CPU clock Sources */ +#define ESP32_CPU_CLK_SRC_XTAL 0U +#define ESP32_CPU_CLK_SRC_PLL 1U +#define ESP32_CLK_SRC_RC_FAST 2U +#define ESP32_CLK_SRC_APLL_CLK 3U -/* Supported CPU Frequencies */ -#define ESP32_CLK_CPU_26M 26000000 -#define ESP32_CLK_CPU_40M 40000000 -#define ESP32_CLK_CPU_80M 80000000 -#define ESP32_CLK_CPU_160M 160000000 -#define ESP32_CLK_CPU_240M 240000000 +/* Supported PLL CPU frequencies */ +#define ESP32_CLK_CPU_PLL_80M 80000000 +#define ESP32_CLK_CPU_PLL_160M 160000000 +#define ESP32_CLK_CPU_PLL_240M 240000000 +#define ESP32_CLK_CPU_RC_FAST_FREQ 1062500 -/* Supported XTAL Frequencies */ -#define ESP32_CLK_XTAL_24M 24 -#define ESP32_CLK_XTAL_26M 26 -#define ESP32_CLK_XTAL_40M 40 -#define ESP32_CLK_XTAL_AUTO 0 +/* Supported XTAL frequencies */ +#define ESP32_CLK_XTAL_24M 24000000 +#define ESP32_CLK_XTAL_26M 26000000 +#define ESP32_CLK_XTAL_40M 40000000 -/* Supported RTC fast clock frequencies */ -#define ESP32_RTC_FAST_CLK_FREQ_8M 8500000U +/* Supported RTC fast clock sources */ +#define ESP32_RTC_FAST_CLK_SRC_XTAL_D4 0 +#define ESP32_RTC_FAST_CLK_SRC_RC_FAST 1 -/* Supported RTC slow clock frequencies */ -#define ESP32_RTC_SLOW_CLK_FREQ_150K 150000U -#define ESP32_RTC_SLOW_CLK_FREQ_32K 32000U -#define ESP32_RTC_SLOW_CLK_FREQ_8MD256 (ESP32_RTC_FAST_CLK_FREQ_8M / 256) +/* Supported RTC slow clock sources */ +#define ESP32_RTC_SLOW_CLK_SRC_RC_SLOW 0 +#define ESP32_RTC_SLOW_CLK_SRC_XTAL32K 1 +#define ESP32_RTC_SLOW_CLK_SRC_RC_FAST_D256 2 +#define ESP32_RTC_SLOW_CLK_32K_EXT_OSC 9 + +/* RTC slow clock frequencies */ +#define ESP32_RTC_SLOW_CLK_SRC_RC_SLOW_FREQ 150000 +#define ESP32_RTC_SLOW_CLK_SRC_XTAL32K_FREQ 32768 +#define ESP32_RTC_SLOW_CLK_SRC_RC_FAST_D256_FREQ 33203 /* Modules IDs * These IDs are actually offsets in CLK and RST Control registers. diff --git a/include/zephyr/dt-bindings/clock/esp32c3_clock.h b/include/zephyr/dt-bindings/clock/esp32c3_clock.h index 6b5b3de12279c..d0a266e424f15 100644 --- a/include/zephyr/dt-bindings/clock/esp32c3_clock.h +++ b/include/zephyr/dt-bindings/clock/esp32c3_clock.h @@ -7,28 +7,34 @@ #ifndef ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_ESP32C3_H_ #define ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_ESP32C3_H_ -/* System Clock Source */ -#define ESP32_CLK_SRC_XTAL 0U -#define ESP32_CLK_SRC_PLL 1U -#define ESP32_CLK_SRC_RTC8M 2U -#define ESP32_CLK_SRC_APLL 3U +/* Supported CPU clock Sources */ +#define ESP32_CPU_CLK_SRC_XTAL 0U +#define ESP32_CPU_CLK_SRC_PLL 1U +#define ESP32_CLK_SRC_RC_FAST 2U -/* Supported CPU Frequencies */ -#define ESP32_CLK_CPU_80M 80000000 -#define ESP32_CLK_CPU_160M 160000000 +/* Supported CPU frequencies */ +#define ESP32_CLK_CPU_PLL_80M 80000000 +#define ESP32_CLK_CPU_PLL_160M 160000000 +#define ESP32_CLK_CPU_RC_FAST_FREQ 17500000 -/* Supported XTAL Frequencies */ -#define ESP32_CLK_XTAL_32M 32 -#define ESP32_CLK_XTAL_40M 40 +/* Supported XTAL frequencies */ +#define ESP32_CLK_XTAL_32M 32000000 +#define ESP32_CLK_XTAL_40M 40000000 -/* Supported RTC fast clock frequencies */ -#define ESP32_RTC_FAST_CLK_FREQ_8M 8500000U -#define ESP32_RTC_FAST_CLK_FREQ_APPROX ESP32_RTC_FAST_CLK_FREQ_8M +/* Supported RTC fast clock sources */ +#define ESP32_RTC_FAST_CLK_SRC_XTAL_D2 0 +#define ESP32_RTC_FAST_CLK_SRC_RC_FAST 1 -/* Supported RTC slow clock frequencies */ -#define ESP32_RTC_SLOW_CLK_FREQ_90K 90000U -#define ESP32_RTC_SLOW_CLK_FREQ_8MD256 (ESP32_RTC_FAST_CLK_FREQ_APPROX / 256) -#define ESP32_RTC_SLOW_CLK_FREQ_32K 32768U +/* Supported RTC slow clock sources */ +#define ESP32_RTC_SLOW_CLK_SRC_RC_SLOW 0 +#define ESP32_RTC_SLOW_CLK_SRC_XTAL32K 1 +#define ESP32_RTC_SLOW_CLK_SRC_RC_FAST_D256 2 +#define ESP32_RTC_SLOW_CLK_32K_EXT_OSC 9 + +/* RTC slow clock frequencies */ +#define ESP32_RTC_SLOW_CLK_SRC_RC_SLOW_FREQ 136000 +#define ESP32_RTC_SLOW_CLK_SRC_XTAL32K_FREQ 32768 +#define ESP32_RTC_SLOW_CLK_SRC_RC_FAST_D256_FREQ 68359 /* Modules IDs * These IDs are actually offsets in CLK and RST Control registers. diff --git a/include/zephyr/dt-bindings/clock/esp32s2_clock.h b/include/zephyr/dt-bindings/clock/esp32s2_clock.h index aa9eb90de628b..5fc57c65d7049 100644 --- a/include/zephyr/dt-bindings/clock/esp32s2_clock.h +++ b/include/zephyr/dt-bindings/clock/esp32s2_clock.h @@ -7,30 +7,35 @@ #ifndef ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_ESP32S2_H_ #define ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_ESP32S2_H_ -/* System Clock Source */ -#define ESP32_CLK_SRC_XTAL 0U -#define ESP32_CLK_SRC_PLL 1U -#define ESP32_CLK_SRC_RTC8M 2U -#define ESP32_CLK_SRC_APLL 3U +/* Supported CPU clock Sources */ +#define ESP32_CPU_CLK_SRC_XTAL 0U +#define ESP32_CPU_CLK_SRC_PLL 1U +#define ESP32_CLK_SRC_RC_FAST 2U +#define ESP32_CLK_SRC_APLL_CLK 3U -/* Supported CPU Frequencies */ -#define ESP32_CLK_CPU_26M 26000000 -#define ESP32_CLK_CPU_40M 40000000 -#define ESP32_CLK_CPU_80M 80000000 -#define ESP32_CLK_CPU_160M 160000000 -#define ESP32_CLK_CPU_240M 240000000 +/* Supported PLL CPU frequencies */ +#define ESP32_CLK_CPU_PLL_80M 80000000 +#define ESP32_CLK_CPU_PLL_160M 160000000 +#define ESP32_CLK_CPU_PLL_240M 240000000 +#define ESP32_CLK_CPU_RC_FAST_FREQ 8500000 -/* Supported XTAL Frequencies */ -#define ESP32_CLK_XTAL_40M 40 +/* Supported XTAL frequencies */ +#define ESP32_CLK_XTAL_40M 40000000 -/* Supported RTC fast clock frequencies */ -#define ESP32_RTC_FAST_CLK_FREQ_8M 8500000U -#define ESP32_RTC_FAST_CLK_FREQ_APPROX ESP32_RTC_FAST_CLK_FREQ_8M +/* Supported RTC fast clock sources */ +#define ESP32_RTC_FAST_CLK_SRC_XTAL_D4 0 +#define ESP32_RTC_FAST_CLK_SRC_RC_FAST 1 -/* Supported RTC slow clock frequencies */ -#define ESP32_RTC_SLOW_CLK_FREQ_90K 90000U -#define ESP32_RTC_SLOW_CLK_FREQ_8MD256 (ESP32_RTC_FAST_CLK_FREQ_APPROX / 256) -#define ESP32_RTC_SLOW_CLK_FREQ_32K 32768U +/* Supported RTC slow clock sources */ +#define ESP32_RTC_SLOW_CLK_SRC_RC_SLOW 0 +#define ESP32_RTC_SLOW_CLK_SRC_XTAL32K 1 +#define ESP32_RTC_SLOW_CLK_SRC_RC_FAST_D256 2 +#define ESP32_RTC_SLOW_CLK_32K_EXT_OSC 9 + +/* RTC slow clock frequencies */ +#define ESP32_RTC_SLOW_CLK_SRC_RC_SLOW_FREQ 90000 +#define ESP32_RTC_SLOW_CLK_SRC_XTAL32K_FREQ 32768 +#define ESP32_RTC_SLOW_CLK_SRC_RC_FAST_D256_FREQ 33203 /* Modules IDs * These IDs are actually offsets in CLK and RST Control registers. diff --git a/include/zephyr/dt-bindings/clock/esp32s3_clock.h b/include/zephyr/dt-bindings/clock/esp32s3_clock.h index 68980d0c8bfe3..9c4bb8364ec78 100644 --- a/include/zephyr/dt-bindings/clock/esp32s3_clock.h +++ b/include/zephyr/dt-bindings/clock/esp32s3_clock.h @@ -7,30 +7,35 @@ #ifndef ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_ESP32S3_H_ #define ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_ESP32S3_H_ -/* System Clock Source */ -#define ESP32_CLK_SRC_XTAL 0U -#define ESP32_CLK_SRC_PLL 1U -#define ESP32_CLK_SRC_RTC8M 2U -#define ESP32_CLK_SRC_APLL 3U +/* Supported CPU clock Sources */ +#define ESP32_CPU_CLK_SRC_XTAL 0U +#define ESP32_CPU_CLK_SRC_PLL 1U +#define ESP32_CLK_SRC_RC_FAST 2U -/* Supported CPU Frequencies */ -#define ESP32_CLK_CPU_26M 26000000 -#define ESP32_CLK_CPU_40M 40000000 -#define ESP32_CLK_CPU_80M 80000000 -#define ESP32_CLK_CPU_160M 160000000 -#define ESP32_CLK_CPU_240M 240000000 +/* Supported PLL CPU frequencies */ +#define ESP32_CLK_CPU_PLL_80M 80000000 +#define ESP32_CLK_CPU_PLL_160M 160000000 +#define ESP32_CLK_CPU_PLL_240M 240000000 +#define ESP32_CLK_CPU_RC_FAST_FREQ 17500000 -/* Supported XTAL Frequencies */ -#define ESP32_CLK_XTAL_32M 32 -#define ESP32_CLK_XTAL_40M 40 +/* Supported XTAL frequencies */ +#define ESP32_CLK_XTAL_32M 32000000 +#define ESP32_CLK_XTAL_40M 40000000 -/* Supported RTC fast clock frequencies */ -#define ESP32_RTC_FAST_CLK_FREQ_8M 8500000U +/* Supported RTC fast clock sources */ +#define ESP32_RTC_FAST_CLK_SRC_XTAL_D2 0 +#define ESP32_RTC_FAST_CLK_SRC_RC_FAST 1 -/* Supported RTC slow clock frequencies */ -#define ESP32_RTC_SLOW_CLK_FREQ_150K 150000U -#define ESP32_RTC_SLOW_CLK_FREQ_32K 32000U -#define ESP32_RTC_SLOW_CLK_FREQ_8MD256 (ESP32_RTC_FAST_CLK_FREQ_8M / 256) +/* Supported RTC slow clock sources */ +#define ESP32_RTC_SLOW_CLK_SRC_RC_SLOW 0 +#define ESP32_RTC_SLOW_CLK_SRC_XTAL32K 1 +#define ESP32_RTC_SLOW_CLK_SRC_RC_FAST_D256 2 +#define ESP32_RTC_SLOW_CLK_32K_EXT_OSC 9 + +/* RTC slow clock frequencies */ +#define ESP32_RTC_SLOW_CLK_SRC_RC_SLOW_FREQ 136000 +#define ESP32_RTC_SLOW_CLK_SRC_XTAL32K_FREQ 32768 +#define ESP32_RTC_SLOW_CLK_SRC_RC_FAST_D256_FREQ 68359 /* Modules IDs * These IDs are actually offsets in CLK and RST Control registers. diff --git a/soc/espressif/Kconfig b/soc/espressif/Kconfig index 1917c3b432b1d..1efa0169ee6e6 100644 --- a/soc/espressif/Kconfig +++ b/soc/espressif/Kconfig @@ -35,13 +35,25 @@ endmenu menu "RTC Clock Config" -config ESP_SYSTEM_RTC_EXT_XTAL - bool - -config ESP_SYSTEM_RTC_EXT_OSC - bool - -rsource "*/Kconfig.rtc" +config RTC_CLK_CAL_CYCLES + int "Number of cycles for RTC_SLOW_CLK calibration" + default 3000 + range 0 32766 + help + When the startup code initializes RTC_SLOW_CLK, it can perform + calibration by comparing the RTC_SLOW_CLK frequency with main XTAL + frequency. This option sets the number of RTC_SLOW_CLK cycles measured + by the calibration routine. Higher numbers increase calibration + precision, which may be important for applications which spend a lot of + time in deep sleep. Lower numbers reduce startup time. + + When this option is set to 0, clock calibration will not be performed at + startup, and approximate clock frequencies will be assumed: + + - 150000 Hz if internal RC oscillator is used as clock source. For this use value 1024. + - 32768 Hz if the 32k crystal oscillator is used. For this use value 3000 or more. + 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. endmenu endif # SOC_FAMILY_ESPRESSIF_ESP32 diff --git a/soc/espressif/esp32/Kconfig.rtc b/soc/espressif/esp32/Kconfig.rtc deleted file mode 100644 index ea14eeaf098ae..0000000000000 --- a/soc/espressif/esp32/Kconfig.rtc +++ /dev/null @@ -1,94 +0,0 @@ -# Copyright (c) 2024 Espressif Systems (Shanghai) Co., Ltd. -# SPDX-License-Identifier: Apache-2.0 - -if SOC_SERIES_ESP32 - -choice RTC_CLK_SRC - prompt "RTC clock source" - default RTC_CLK_SRC_INT_RC - help - Choose which clock is used as RTC clock source. - - - "Internal 150kHz oscillator" option provides lowest deep sleep current - consumption, and does not require extra external components. However - frequency stability with respect to temperature is poor, so time may - drift in deep/light sleep modes. - - "External 32kHz crystal" provides better frequency stability, at the - expense of slightly higher (1uA) deep sleep current consumption. - - "External 32kHz oscillator" allows using 32kHz clock generated by an - external circuit. In this case, external clock signal must be connected - to 32K_XN pin. Amplitude should be <1.2V in case of sine wave signal, - and <1V in case of square wave signal. Common mode voltage should be - 0.1 < Vcm < 0.5Vamp, where Vamp is the signal amplitude. - Additionally, 1nF capacitor must be connected between 32K_XP pin and - ground. 32K_XP pin can not be used as a GPIO in this case. - - "Internal 8.5MHz oscillator divided by 256" option results in higher - deep sleep current (by 5uA) but has better frequency stability than - the internal 150kHz oscillator. It does not require external components. - -config RTC_CLK_SRC_INT_RC - bool "Internal 150kHz RC oscillator" - -config RTC_CLK_SRC_EXT_CRYS - bool "External 32kHz crystal" - select ESP_SYSTEM_RTC_EXT_XTAL - -config RTC_CLK_SRC_EXT_OSC - bool "External 32kHz oscillator at 32K_XN pin" - select ESP_SYSTEM_RTC_EXT_OSC - -config RTC_CLK_SRC_INT_8MD256 - bool "Internal 8.5MHz oscillator, divided by 256 (~33kHz)" - -endchoice # RTC_CLK_SRC - -config RTC_CLK_CAL_CYCLES - int "Number of cycles for RTC_SLOW_CLK calibration" - default 3000 if RTC_CLK_SRC_EXT_CRYS || RTC_CLK_SRC_EXT_OSC || RTC_CLK_SRC_INT_8MD256 - default 1024 if RTC_CLK_SRC_INT_RC - range 0 27000 if RTC_CLK_SRC_EXT_CRYS || RTC_CLK_SRC_EXT_OSC || RTC_CLK_SRC_INT_8MD256 - range 0 32766 if RTC_CLK_SRC_INT_RC - help - When the startup code initializes RTC_SLOW_CLK, it can perform - calibration by comparing the RTC_SLOW_CLK frequency with main XTAL - frequency. This option sets the number of RTC_SLOW_CLK cycles measured - by the calibration routine. Higher numbers increase calibration - precision, which may be important for applications which spend a lot of - time in deep sleep. Lower numbers reduce startup time. - - When this option is set to 0, clock calibration will not be performed at - startup, and approximate clock frequencies will be assumed: - - - 150000 Hz if internal RC oscillator is used as clock source. For this use value 1024. - - 32768 Hz if the 32k crystal oscillator is used. For this use value 3000 or more. - 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 RTC_XTAL_CAL_RETRY - int "Number of attempts to repeat 32k XTAL calibration" - default 1 - depends on RTC_CLK_SRC_EXT_CRYS - help - Number of attempts to repeat 32k XTAL calibration - before giving up and switching to the internal RC. - 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/esp32/soc.c b/soc/espressif/esp32/soc.c index 1c6e0eaa7db53..bec3413ba42a3 100644 --- a/soc/espressif/esp32/soc.c +++ b/soc/espressif/esp32/soc.c @@ -137,13 +137,6 @@ void IRAM_ATTR __esp_platform_start(void) wdt_hal_disable(&rtc_wdt_ctx); wdt_hal_write_protect_enable(&rtc_wdt_ctx); -#ifndef CONFIG_SOC_ENABLE_APPCPU - /* Configures the CPU clock, RTC slow and fast clocks, and performs - * RTC slow clock calibration. - */ - esp_clk_init(); -#endif - esp_timer_early_init(); #if CONFIG_SOC_ENABLE_APPCPU diff --git a/soc/espressif/esp32c3/Kconfig.rtc b/soc/espressif/esp32c3/Kconfig.rtc deleted file mode 100644 index b0f2e47f56579..0000000000000 --- a/soc/espressif/esp32c3/Kconfig.rtc +++ /dev/null @@ -1,67 +0,0 @@ -# Copyright (c) 2024 Espressif Systems (Shanghai) Co., Ltd. -# SPDX-License-Identifier: Apache-2.0 - -if SOC_SERIES_ESP32C3 - -choice RTC_CLK_SRC - prompt "RTC clock source" - default RTC_CLK_SRC_INT_RC - help - Choose which clock is used as RTC clock source. - -config RTC_CLK_SRC_INT_RC - bool "Internal 136kHz RC oscillator" - -config RTC_CLK_SRC_EXT_CRYS - bool "External 32kHz crystal" - select ESP_SYSTEM_RTC_EXT_XTAL - -config RTC_CLK_SRC_EXT_OSC - bool "External 32kHz oscillator at 32K_XP pin" - select ESP_SYSTEM_RTC_EXT_OSC - -config RTC_CLK_SRC_INT_8MD256 - bool "Internal 17.5MHz oscillator, divided by 256" - -endchoice # ESP32C3_RTC_CLK_SRC - -config RTC_CLK_CAL_CYCLES - int "Number of cycles for RTC_SLOW_CLK calibration" - default 3000 if RTC_CLK_SRC_EXT_CRYS || RTC_CLK_SRC_EXT_OSC || RTC_CLK_SRC_INT_8MD256 - default 1024 if RTC_CLK_SRC_INT_RC - range 0 27000 if RTC_CLK_SRC_EXT_CRYS || RTC_CLK_SRC_EXT_OSC || RTC_CLK_SRC_INT_8MD256 - range 0 32766 if RTC_CLK_SRC_INT_RC - help - When the startup code initializes RTC_SLOW_CLK, it can perform - calibration by comparing the RTC_SLOW_CLK frequency with main XTAL - frequency. This option sets the number of RTC_SLOW_CLK cycles measured - by the calibration routine. Higher numbers increase calibration - precision, which may be important for applications which spend a lot of - time in deep sleep. Lower numbers reduce startup time. - - When this option is set to 0, clock calibration will not be performed at - startup, and approximate clock frequencies will be assumed: - - - 150000 Hz if internal RC oscillator is used as clock source. For this use value 1024. - - 32768 Hz if the 32k crystal oscillator is used. For this use value 3000 or more. - 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/esp32c3/soc.c b/soc/espressif/esp32c3/soc.c index 2e39e10870578..61a4cb4c83ff7 100644 --- a/soc/espressif/esp32c3/soc.c +++ b/soc/espressif/esp32c3/soc.c @@ -82,11 +82,6 @@ void __attribute__((section(".iram1"))) __esp_platform_start(void) #endif /*CONFIG_SOC_FLASH_ESP32*/ - /* Configures the CPU clock, RTC slow and fast clocks, and performs - * RTC slow clock calibration. - */ - esp_clk_init(); - esp_timer_early_init(); #if CONFIG_SOC_FLASH_ESP32 diff --git a/soc/espressif/esp32s2/Kconfig.rtc b/soc/espressif/esp32s2/Kconfig.rtc deleted file mode 100644 index 61ca8d3a9df9b..0000000000000 --- a/soc/espressif/esp32s2/Kconfig.rtc +++ /dev/null @@ -1,93 +0,0 @@ -# Copyright (c) 2024 Espressif Systems (Shanghai) Co., Ltd. -# SPDX-License-Identifier: Apache-2.0 - -if SOC_SERIES_ESP32S2 - -choice RTC_CLK_SRC - prompt "RTC clock source" - default RTC_CLK_SRC_INT_RC - help - Choose which clock is used as RTC clock source. - - - "Internal 90kHz oscillator" option provides lowest deep sleep current - consumption, and does not require extra external components. However - frequency stability with respect to temperature is poor, so time may - drift in deep/light sleep modes. - - "External 32kHz crystal" provides better frequency stability, at the - expense of slightly higher (1uA) deep sleep current consumption. - - "External 32kHz oscillator" allows using 32kHz clock generated by an - external circuit. In this case, external clock signal must be connected - to 32K_XN pin. Amplitude should be <1.2V in case of sine wave signal, - and <1V in case of square wave signal. Common mode voltage should be - 0.1 < Vcm < 0.5Vamp, where Vamp is the signal amplitude. - Additionally, 1nF capacitor must be connected between 32K_XP pin and - ground. 32K_XP pin can not be used as a GPIO in this case. - - "Internal 8MHz oscillator divided by 256" option results in higher - deep sleep current (by 5uA) but has better frequency stability than - the internal 90kHz oscillator. It does not require external components. - -config RTC_CLK_SRC_INT_RC - bool "Internal 90kHz RC oscillator" - -config RTC_CLK_SRC_EXT_CRYS - bool "External 32kHz crystal" - select ESP_SYSTEM_RTC_EXT_XTAL - -config RTC_CLK_SRC_EXT_OSC - bool "External 32kHz oscillator at 32K_XN pin" - select ESP_SYSTEM_RTC_EXT_OSC - -config RTC_CLK_SRC_INT_8MD256 - bool "Internal 8MHz oscillator, divided by 256 (~32kHz)" - -endchoice - -config RTC_CLK_CAL_CYCLES - int "Number of cycles for RTC_SLOW_CLK calibration" - default 3000 if RTC_CLK_SRC_EXT_CRYS || RTC_CLK_SRC_EXT_OSC || RTC_CLK_SRC_INT_8MD256 - default 576 if RTC_CLK_SRC_INT_RC - range 0 125000 - help - When the startup code initializes RTC_SLOW_CLK, it can perform - calibration by comparing the RTC_SLOW_CLK frequency with main XTAL - frequency. This option sets the number of RTC_SLOW_CLK cycles measured - by the calibration routine. Higher numbers increase calibration - precision, which may be important for applications which spend a lot of - time in deep sleep. Lower numbers reduce startup time. - - When this option is set to 0, clock calibration will not be performed at - startup, and approximate clock frequencies will be assumed: - - - 90000 Hz if internal RC oscillator is used as clock source. For this use value 1024. - - 32768 Hz if the 32k crystal oscillator is used. For this use value 3000 or more. - 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 RTC_XTAL_CAL_RETRY - int "Number of attempts to repeat 32k XTAL calibration" - default 3 - depends on RTC_CLK_SRC_EXT_CRYS - help - Number of attempts to repeat 32k XTAL calibration - before giving up and switching to the internal RC. - 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/esp32s2/soc.c b/soc/espressif/esp32s2/soc.c index a0558bd8ea33d..05913df81cfc4 100644 --- a/soc/espressif/esp32s2/soc.c +++ b/soc/espressif/esp32s2/soc.c @@ -129,10 +129,6 @@ void __attribute__((section(".iram1"))) __esp_platform_start(void) #endif /* CONFIG_ESP_SPIRAM */ - /* Configures the CPU clock, RTC slow and fast clocks, and performs - * RTC slow clock calibration. - */ - esp_clk_init(); esp_timer_early_init(); /* Scheduler is not started at this point. Hence, guard functions diff --git a/soc/espressif/esp32s3/Kconfig.rtc b/soc/espressif/esp32s3/Kconfig.rtc deleted file mode 100644 index 9c5d7d834baa8..0000000000000 --- a/soc/espressif/esp32s3/Kconfig.rtc +++ /dev/null @@ -1,63 +0,0 @@ -# Copyright (c) 2024 Espressif Systems (Shanghai) Co., Ltd. -# SPDX-License-Identifier: Apache-2.0 - -if SOC_SERIES_ESP32S3 - -choice RTC_CLK_SRC - prompt "RTC clock source" - default RTC_CLK_SRC_INT_RC - help - Choose which clock is used as RTC clock source. - - config RTC_CLK_SRC_INT_RC - bool "Internal 136kHz RC oscillator" - config RTC_CLK_SRC_EXT_CRYS - bool "External 32kHz crystal" - select ESP_SYSTEM_RTC_EXT_XTAL - config RTC_CLK_SRC_EXT_OSC - bool "External 32kHz oscillator at 32K_XP pin" - select ESP_SYSTEM_RTC_EXT_OSC - config RTC_CLK_SRC_INT_8MD256 - bool "Internal 17.5MHz oscillator, divided by 256" -endchoice - -config RTC_CLK_CAL_CYCLES - int "Number of cycles for RTC_SLOW_CLK calibration" - default 3000 if RTC_CLK_SRC_EXT_CRYS || RTC_CLK_SRC_EXT_OSC || RTC_CLK_SRC_INT_8MD256 - default 1024 if RTC_CLK_SRC_INT_RC - range 0 27000 if RTC_CLK_SRC_EXT_CRYS || RTC_CLK_SRC_EXT_OSC || RTC_CLK_SRC_INT_8MD256 - range 0 32766 if RTC_CLK_SRC_INT_RC - help - When the startup code initializes RTC_SLOW_CLK, it can perform - calibration by comparing the RTC_SLOW_CLK frequency with main XTAL - frequency. This option sets the number of RTC_SLOW_CLK cycles measured - by the calibration routine. Higher numbers increase calibration - precision, which may be important for applications which spend a lot of - time in deep sleep. Lower numbers reduce startup time. - - When this option is set to 0, clock calibration will not be performed at - startup, and approximate clock frequencies will be assumed: - - - 150000 Hz if internal RC oscillator is used as clock source. For this use value 1024. - - 32768 Hz if the 32k crystal oscillator is used. For this use value 3000 or more. - 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 diff --git a/soc/espressif/esp32s3/soc.c b/soc/espressif/esp32s3/soc.c index d8791cf6cc83b..ec9d603d6cd76 100644 --- a/soc/espressif/esp32s3/soc.c +++ b/soc/espressif/esp32s3/soc.c @@ -197,8 +197,6 @@ void IRAM_ATTR __esp_platform_start(void) esp_reset_reason_init(); - esp_clk_init(); - esp_timer_early_init(); #if CONFIG_SOC_ENABLE_APPCPU From 9808aa9f9e99df88b441bb51a99ff4ba17f9b011 Mon Sep 17 00:00:00 2001 From: Lucas Tamborrino Date: Thu, 2 May 2024 16:43:07 -0300 Subject: [PATCH 1088/2849] tests: drivers: clock control api: Make test generic Changes for making the clock control api tests generic for any board. All the device subsys definitions were moved to its own folder according to the clock compatible. Also if the clock's async feature is not supported by the target, the test is skipped instead of failed. Signed-off-by: Lucas Tamborrino --- .../clock_control_api/src/device_subsys.h | 18 +++++++ .../src/esp32_device_subsys.h | 27 ++++++++++ .../clock_control_api/src/nrf_device_subsys.h | 36 +++++++++++++ .../src/test_clock_control.c | 54 +++---------------- .../clock_control_api/testcase.yaml | 17 +++--- 5 files changed, 100 insertions(+), 52 deletions(-) create mode 100644 tests/drivers/clock_control/clock_control_api/src/device_subsys.h create mode 100644 tests/drivers/clock_control/clock_control_api/src/esp32_device_subsys.h create mode 100644 tests/drivers/clock_control/clock_control_api/src/nrf_device_subsys.h diff --git a/tests/drivers/clock_control/clock_control_api/src/device_subsys.h b/tests/drivers/clock_control/clock_control_api/src/device_subsys.h new file mode 100644 index 0000000000000..fdb4e2b04384c --- /dev/null +++ b/tests/drivers/clock_control/clock_control_api/src/device_subsys.h @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2024 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +struct device_subsys_data { + clock_control_subsys_t subsys; + uint32_t startup_us; +}; + +struct device_data { + const struct device *dev; + const struct device_subsys_data *subsys_data; + uint32_t subsys_cnt; +}; diff --git a/tests/drivers/clock_control/clock_control_api/src/esp32_device_subsys.h b/tests/drivers/clock_control/clock_control_api/src/esp32_device_subsys.h new file mode 100644 index 0000000000000..425511766b2f8 --- /dev/null +++ b/tests/drivers/clock_control/clock_control_api/src/esp32_device_subsys.h @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2024 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "device_subsys.h" +#include + +/* Test common modules among espressif SOCs*/ +static const struct device_subsys_data subsys_data[] = { + {.subsys = (void *) ESP32_LEDC_MODULE}, + {.subsys = (void *) ESP32_UART1_MODULE}, + {.subsys = (void *) ESP32_I2C0_MODULE}, + {.subsys = (void *) ESP32_UHCI0_MODULE}, + {.subsys = (void *) ESP32_RMT_MODULE}, + {.subsys = (void *) ESP32_TWAI_MODULE}, + {.subsys = (void *) ESP32_RNG_MODULE}, +}; + +static const struct device_data devices[] = { + { + .dev = DEVICE_DT_GET_ONE(espressif_esp32_rtc), + .subsys_data = subsys_data, + .subsys_cnt = ARRAY_SIZE(subsys_data) + } +}; diff --git a/tests/drivers/clock_control/clock_control_api/src/nrf_device_subsys.h b/tests/drivers/clock_control/clock_control_api/src/nrf_device_subsys.h new file mode 100644 index 0000000000000..6d660bda94737 --- /dev/null +++ b/tests/drivers/clock_control/clock_control_api/src/nrf_device_subsys.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2019, Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "device_subsys.h" +#include + +static const struct device_subsys_data subsys_data[] = { + { + .subsys = CLOCK_CONTROL_NRF_SUBSYS_HF, + .startup_us = + IS_ENABLED(CONFIG_SOC_SERIES_NRF91X) ? + 3000 : 500 + }, +#ifndef CONFIG_SOC_NRF52832 + /* On nrf52832 LF clock cannot be stopped because it leads + * to RTC COUNTER register reset and that is unexpected by + * system clock which is disrupted and may hang in the test. + */ + { + .subsys = CLOCK_CONTROL_NRF_SUBSYS_LF, + .startup_us = (CLOCK_CONTROL_NRF_K32SRC == + NRF_CLOCK_LFCLK_RC) ? 1000 : 500000 + } +#endif /* !CONFIG_SOC_NRF52832 */ +}; + +static const struct device_data devices[] = { + { + .dev = DEVICE_DT_GET_ONE(nordic_nrf_clock), + .subsys_data = subsys_data, + .subsys_cnt = ARRAY_SIZE(subsys_data) + } +}; diff --git a/tests/drivers/clock_control/clock_control_api/src/test_clock_control.c b/tests/drivers/clock_control/clock_control_api/src/test_clock_control.c index a5d114192644d..1623335618d6a 100644 --- a/tests/drivers/clock_control/clock_control_api/src/test_clock_control.c +++ b/tests/drivers/clock_control/clock_control_api/src/test_clock_control.c @@ -9,53 +9,13 @@ LOG_MODULE_REGISTER(test); #if DT_HAS_COMPAT_STATUS_OKAY(nordic_nrf_clock) -#include +#include "nrf_device_subsys.h" +#elif DT_HAS_COMPAT_STATUS_OKAY(espressif_esp32_rtc) +#include "esp32_device_subsys.h" +#else +#error "Unsupported board" #endif -struct device_subsys_data { - clock_control_subsys_t subsys; - uint32_t startup_us; -}; - -struct device_data { - const struct device *dev; - const struct device_subsys_data *subsys_data; - uint32_t subsys_cnt; -}; - -#if DT_HAS_COMPAT_STATUS_OKAY(nordic_nrf_clock) -static const struct device_subsys_data subsys_data[] = { - { - .subsys = CLOCK_CONTROL_NRF_SUBSYS_HF, - .startup_us = - IS_ENABLED(CONFIG_SOC_SERIES_NRF91X) ? - 3000 : 500 - }, -#ifndef CONFIG_SOC_NRF52832 - /* On nrf52832 LF clock cannot be stopped because it leads - * to RTC COUNTER register reset and that is unexpected by - * system clock which is disrupted and may hang in the test. - */ - { - .subsys = CLOCK_CONTROL_NRF_SUBSYS_LF, - .startup_us = (CLOCK_CONTROL_NRF_K32SRC == - NRF_CLOCK_LFCLK_RC) ? 1000 : 500000 - } -#endif /* !CONFIG_SOC_NRF52832 */ -}; -#endif /* DT_HAS_COMPAT_STATUS_OKAY(nordic_nrf_clock) */ - -static const struct device_data devices[] = { -#if DT_HAS_COMPAT_STATUS_OKAY(nordic_nrf_clock) - { - .dev = DEVICE_DT_GET_ONE(nordic_nrf_clock), - .subsys_data = subsys_data, - .subsys_cnt = ARRAY_SIZE(subsys_data) - } -#endif -}; - - typedef void (*test_func_t)(const struct device *dev, clock_control_subsys_t subsys, uint32_t startup_us); @@ -194,7 +154,9 @@ static bool async_capable(const struct device *dev, clock_control_subsys_t subsy int err; err = clock_control_async_on(dev, subsys, async_capable_callback, NULL); - if (err < 0) { + if (err == -ENOSYS) { + ztest_test_skip(); + } else if (err < 0) { printk("failed %d", err); return false; } diff --git a/tests/drivers/clock_control/clock_control_api/testcase.yaml b/tests/drivers/clock_control/clock_control_api/testcase.yaml index 356893f400f84..f14e57971ab10 100644 --- a/tests/drivers/clock_control/clock_control_api/testcase.yaml +++ b/tests/drivers/clock_control/clock_control_api/testcase.yaml @@ -1,8 +1,16 @@ +common: + tags: + - drivers + - clock_control tests: + drivers.clock.clock_control_api_default: + platform_allow: + - esp32_devkitc_wroom/esp32/procpu + - esp32_devkitc_wrover/esp32/procpu + - esp32c3_devkitm + - esp32s2_saola + - esp32s3_devkitm/esp32s3/procpu drivers.clock.clock_control_nrf5: - tags: - - drivers - - clock_control platform_allow: - nrf51dk/nrf51822 - nrf52dk/nrf52832 @@ -12,9 +20,6 @@ tests: integration_platforms: - nrf51dk/nrf51822 drivers.clock.clock_control_nrf5_lfclk_rc: - tags: - - drivers - - clock_control platform_allow: - nrf51dk/nrf51822 - nrf52dk/nrf52832 From 0b72ded05710307883bf960480dfebe397bc1d77 Mon Sep 17 00:00:00 2001 From: Lucas Tamborrino Date: Thu, 2 May 2024 16:45:29 -0300 Subject: [PATCH 1089/2849] tests: drivers: counter: support rtc timer Add support for rtc timer node in the test. Signed-off-by: Lucas Tamborrino --- tests/drivers/counter/counter_basic_api/src/test_counter.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/drivers/counter/counter_basic_api/src/test_counter.c b/tests/drivers/counter/counter_basic_api/src/test_counter.c index c9c8418b00f5d..b83d1a5160271 100644 --- a/tests/drivers/counter/counter_basic_api/src/test_counter.c +++ b/tests/drivers/counter/counter_basic_api/src/test_counter.c @@ -97,6 +97,9 @@ static const struct device *const devices[] = { #ifdef CONFIG_COUNTER_TMR_ESP32 DEVS_FOR_DT_COMPAT(espressif_esp32_timer) #endif +#ifdef CONFIG_COUNTER_TMR_RTC_ESP32 + DEVS_FOR_DT_COMPAT(espressif_esp32_rtc_timer) +#endif #ifdef CONFIG_COUNTER_NXP_S32_SYS_TIMER DEVS_FOR_DT_COMPAT(nxp_s32_sys_timer) #endif From 4684b192bc37a0c1580c6cbba43264bc6c90218e Mon Sep 17 00:00:00 2001 From: Lucas Tamborrino Date: Wed, 1 May 2024 07:25:37 -0300 Subject: [PATCH 1090/2849] tests: boards: espressif: Add RTC CLK test Add tests for the rtc clk subsystem. Signed-off-by: Lucas Tamborrino --- .../espressif_esp32/rtc_clk/CMakeLists.txt | 8 + tests/boards/espressif_esp32/rtc_clk/Kconfig | 10 + .../boards/espressif_esp32/rtc_clk/README.rst | 85 ++++++++ tests/boards/espressif_esp32/rtc_clk/prj.conf | 1 + .../rtc_clk/src/rtc_clk_test.c | 199 ++++++++++++++++++ .../espressif_esp32/rtc_clk/testcase.yaml | 17 ++ 6 files changed, 320 insertions(+) create mode 100644 tests/boards/espressif_esp32/rtc_clk/CMakeLists.txt create mode 100644 tests/boards/espressif_esp32/rtc_clk/Kconfig create mode 100644 tests/boards/espressif_esp32/rtc_clk/README.rst create mode 100644 tests/boards/espressif_esp32/rtc_clk/prj.conf create mode 100644 tests/boards/espressif_esp32/rtc_clk/src/rtc_clk_test.c create mode 100644 tests/boards/espressif_esp32/rtc_clk/testcase.yaml diff --git a/tests/boards/espressif_esp32/rtc_clk/CMakeLists.txt b/tests/boards/espressif_esp32/rtc_clk/CMakeLists.txt new file mode 100644 index 0000000000000..c22ee7652d8b5 --- /dev/null +++ b/tests/boards/espressif_esp32/rtc_clk/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(rtc_clk_test) + +target_sources(app PRIVATE src/rtc_clk_test.c) diff --git a/tests/boards/espressif_esp32/rtc_clk/Kconfig b/tests/boards/espressif_esp32/rtc_clk/Kconfig new file mode 100644 index 0000000000000..5a4705655f333 --- /dev/null +++ b/tests/boards/espressif_esp32/rtc_clk/Kconfig @@ -0,0 +1,10 @@ +# Copyright (c) 2024 Espressif Systems (Shanghai) Co., Ltd. +# SPDX-License-Identifier: Apache-2.0 + +mainmenu "RTC CLK Test Configuration" + +source "Kconfig.zephyr" + +config FIXTURE_XTAL + bool "Selected when external crystal is present" + default n diff --git a/tests/boards/espressif_esp32/rtc_clk/README.rst b/tests/boards/espressif_esp32/rtc_clk/README.rst new file mode 100644 index 0000000000000..caeb6d027c69c --- /dev/null +++ b/tests/boards/espressif_esp32/rtc_clk/README.rst @@ -0,0 +1,85 @@ +.. _rtc_clk_test: + +Espressif's RTC Clock test +########################## + +Overview +******** + +This test iterates through all the clock sources and checks if the expected frequency is being set. +Espressif SOCs have 3 main clock subsystems: CPU, RTC_FAST and RTC_SLOW. Each of these subsystems have their own clock sources and possible rates. + + +Supported Boards +**************** +- esp32_devkitc_wrover/esp32/procpu +- esp32c3_devkitm +- esp32s2_saola +- esp32s3_devkitm/esp32s3/procpu + +Building and Running +******************** + +Make sure you have the target connected over USB port. + +.. code-block:: console + + west build -b tests/boards/espressif_esp32/rtc_clk + west flash && west espressif monitor + +To run the test with twister, use the following command: + +.. code-block:: console + + west twister -p --device-testing --device-serial=/dev/ttyUSB0 -vv --flash-before -T tests/boards/espressif_esp32/rtc_clk + +If the external 32K crystal is connect to pins 32K_XP and 32K_XN, the test can be run with `external_xtal` fixture enabled: + +.. code-block:: console + + west twister -p esp32c3_devkitm --device-testing --device-serial=/dev/ttyUSB0 -vv --flash-before -T tests/boards/espressif_esp32/rtc_clk -X external_xtal + +Sample Output +============= + +.. code-block:: console + + *** Booting Zephyr OS build v3.6.0-3162-g529005998ea6 *** + Running TESTSUITE rtc_clk + =================================================================== + CPU frequency: 240000000 + RTC_FAST frequency: 17500000 + RTC_SLOW frequency: 136000 + START - test_cpu_pll_src + Testing CPU frequency: 80 MHz + Testing CPU frequency: 160 MHz + Testing CPU frequency: 240 MHz + PASS - test_cpu_pll_src in 0.020 seconds + =================================================================== + START - test_cpu_xtal_src + Testing CPU frequency: 40 MHz + Testing CPU frequency: 20 MHz + Testing CPU frequency: 10 MHz + Testing CPU frequency: 5 MHz + PASS - test_cpu_xtal_src in 17.645 seconds + =================================================================== + START - test_rtc_fast_src + Testing RTC FAST CLK freq: 20000000 MHz + Testing RTC FAST CLK freq: 17500000 MHz + PASS - test_rtc_fast_src in 0.001 seconds + =================================================================== + START - test_rtc_slow_src + Testing RTC SLOW CLK freq: 136000 MHz + Testing RTC SLOW CLK freq: 68359 MHz + PASS - test_rtc_slow_src in 0.002 seconds + =================================================================== + TESTSUITE rtc_clk succeeded + ------ TESTSUITE SUMMARY START ------ + SUITE PASS - 100.00% [rtc_clk]: pass = 4, fail = 0, skip = 0, total = 4 duration = 17.668 seconds + - PASS - [rtc_clk.test_cpu_pll_src] duration = 0.020 seconds + - PASS - [rtc_clk.test_cpu_xtal_src] duration = 17.645 seconds + - PASS - [rtc_clk.test_rtc_fast_src] duration = 0.001 seconds + - PASS - [rtc_clk.test_rtc_slow_src] duration = 0.002 seconds + ------ TESTSUITE SUMMARY END ------ + =================================================================== + PROJECT EXECUTION SUCCESSFUL diff --git a/tests/boards/espressif_esp32/rtc_clk/prj.conf b/tests/boards/espressif_esp32/rtc_clk/prj.conf new file mode 100644 index 0000000000000..9467c2926896d --- /dev/null +++ b/tests/boards/espressif_esp32/rtc_clk/prj.conf @@ -0,0 +1 @@ +CONFIG_ZTEST=y diff --git a/tests/boards/espressif_esp32/rtc_clk/src/rtc_clk_test.c b/tests/boards/espressif_esp32/rtc_clk/src/rtc_clk_test.c new file mode 100644 index 0000000000000..2b621d0e715ae --- /dev/null +++ b/tests/boards/espressif_esp32/rtc_clk/src/rtc_clk_test.c @@ -0,0 +1,199 @@ +/* + * Copyright (c) 2024 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include + +#if defined(CONFIG_SOC_SERIES_ESP32) +#define DT_CPU_COMPAT espressif_xtensa_lx6 +#elif defined(CONFIG_SOC_SERIES_ESP32S2) || defined(CONFIG_SOC_SERIES_ESP32S3) +#define DT_CPU_COMPAT espressif_xtensa_lx7 +#elif CONFIG_SOC_SERIES_ESP32C3 +#define DT_CPU_COMPAT espressif_riscv +#endif + +static const struct device *const clk_dev = DEVICE_DT_GET_ONE(espressif_esp32_rtc); + +static void *rtc_clk_setup(void) +{ + zassert_true(device_is_ready(clk_dev), "CLK device is not ready"); + uint32_t rate = 0; + int ret = 0; + + ret = clock_control_get_rate(clk_dev, + (clock_control_subsys_t)ESP32_CLOCK_CONTROL_SUBSYS_CPU, &rate); + zassert_false(ret, "Failed to get CPU clock rate"); + TC_PRINT("CPU frequency: %d\n", rate); + + ret = clock_control_get_rate( + clk_dev, (clock_control_subsys_t)ESP32_CLOCK_CONTROL_SUBSYS_RTC_FAST, &rate); + zassert_false(ret, "Failed to get RTC_FAST clock rate"); + TC_PRINT("RTC_FAST frequency: %d\n", rate); + + ret = clock_control_get_rate( + clk_dev, (clock_control_subsys_t)ESP32_CLOCK_CONTROL_SUBSYS_RTC_SLOW, &rate); + zassert_false(ret, "Failed to get RTC_SLOW clock rate"); + TC_PRINT("RTC_SLOW frequency: %d\n", rate); + + return NULL; +} + +ZTEST(rtc_clk, test_cpu_xtal_src) +{ + struct esp32_clock_config clk_cfg = {0}; + int ret = 0; + uint32_t cpu_rate = 0; + + clk_cfg.cpu.clk_src = ESP32_CPU_CLK_SRC_XTAL; + clk_cfg.cpu.xtal_freq = (DT_PROP(DT_INST(0, DT_CPU_COMPAT), xtal_freq) / MHZ(1)); + + for (uint8_t i = 0; i < 4; i++) { + clk_cfg.cpu.cpu_freq = clk_cfg.cpu.xtal_freq >> i; + + TC_PRINT("Testing CPU frequency: %d MHz\n", clk_cfg.cpu.cpu_freq); + + ret = clock_control_configure( + clk_dev, (clock_control_subsys_t)ESP32_CLOCK_CONTROL_SUBSYS_CPU, &clk_cfg); + zassert_false(ret, "Failed to set CPU clock source"); + + ret = clock_control_get_rate( + clk_dev, (clock_control_subsys_t)ESP32_CLOCK_CONTROL_SUBSYS_CPU, &cpu_rate); + zassert_false(ret, "Failed to get CPU clock rate"); + zassert_equal(cpu_rate, clk_cfg.cpu.cpu_freq * MHZ(1), + "CPU clock rate is not equal to XTAL frequency (%d != %d)", cpu_rate, + clk_cfg.cpu.cpu_freq); + } +} + +uint32_t rtc_pll_src_freq_mhz[] = { + ESP32_CLK_CPU_PLL_80M, + ESP32_CLK_CPU_PLL_160M, +#if !defined(CONFIG_SOC_SERIES_ESP32C3) + ESP32_CLK_CPU_PLL_240M, +#endif +}; + +ZTEST(rtc_clk, test_cpu_pll_src) +{ + struct esp32_clock_config clk_cfg = {0}; + int ret = 0; + uint32_t cpu_rate = 0; + + clk_cfg.cpu.clk_src = ESP32_CPU_CLK_SRC_PLL; + clk_cfg.cpu.xtal_freq = (DT_PROP(DT_INST(0, DT_CPU_COMPAT), xtal_freq) / MHZ(1)); + + for (uint8_t i = 0; i < ARRAY_SIZE(rtc_pll_src_freq_mhz); i++) { + clk_cfg.cpu.cpu_freq = rtc_pll_src_freq_mhz[i] / MHZ(1); + + TC_PRINT("Testing CPU frequency: %d MHz\n", clk_cfg.cpu.cpu_freq); + + ret = clock_control_configure( + clk_dev, (clock_control_subsys_t)ESP32_CLOCK_CONTROL_SUBSYS_CPU, &clk_cfg); + zassert_false(ret, "Failed to set CPU clock source"); + + ret = clock_control_get_rate( + clk_dev, (clock_control_subsys_t)ESP32_CLOCK_CONTROL_SUBSYS_CPU, &cpu_rate); + zassert_false(ret, "Failed to get CPU clock rate"); + zassert_equal(cpu_rate, clk_cfg.cpu.cpu_freq * MHZ(1), + "CPU clock rate is not equal to configured frequency (%d != %d)", + cpu_rate, clk_cfg.cpu.cpu_freq); + } +} + +uint32_t rtc_rtc_fast_clk_src[] = { +#if defined(CONFIG_SOC_SERIES_ESP32) || defined(CONFIG_SOC_SERIES_ESP32S2) + ESP32_RTC_FAST_CLK_SRC_XTAL_D4, +#else + ESP32_RTC_FAST_CLK_SRC_XTAL_D2, +#endif + ESP32_RTC_FAST_CLK_SRC_RC_FAST}; + +uint32_t rtc_rtc_fast_clk_src_freq_mhz[] = { +#if defined(CONFIG_SOC_SERIES_ESP32) || defined(CONFIG_SOC_SERIES_ESP32S2) + DT_PROP(DT_INST(0, DT_CPU_COMPAT), xtal_freq) / 4, +#else + DT_PROP(DT_INST(0, DT_CPU_COMPAT), xtal_freq) / 2, +#endif + ESP32_CLK_CPU_RC_FAST_FREQ +}; + +ZTEST(rtc_clk, test_rtc_fast_src) +{ + struct esp32_clock_config clk_cfg = {0}; + int ret = 0; + uint32_t cpu_rate = 0; + + clk_cfg.cpu.xtal_freq = (DT_PROP(DT_INST(0, DT_CPU_COMPAT), xtal_freq) / MHZ(1)); + + for (uint8_t i = 0; i < ARRAY_SIZE(rtc_rtc_fast_clk_src); i++) { + clk_cfg.rtc.rtc_fast_clock_src = rtc_rtc_fast_clk_src[i]; + + TC_PRINT("Testing RTC FAST CLK freq: %d MHz\n", rtc_rtc_fast_clk_src_freq_mhz[i]); + + ret = clock_control_configure( + clk_dev, (clock_control_subsys_t)ESP32_CLOCK_CONTROL_SUBSYS_RTC_FAST, + &clk_cfg); + zassert_false(ret, "Failed to set CPU clock source"); + + ret = clock_control_get_rate( + clk_dev, (clock_control_subsys_t)ESP32_CLOCK_CONTROL_SUBSYS_RTC_FAST, + &cpu_rate); + zassert_false(ret, "Failed to get RTC_FAST clock rate"); + zassert_equal(cpu_rate, rtc_rtc_fast_clk_src_freq_mhz[i], + "CPU clock rate is not equal to configured frequency (%d != %d)", + cpu_rate, rtc_rtc_fast_clk_src_freq_mhz[i]); + } +} + +uint32_t rtc_rtc_slow_clk_src[] = { + ESP32_RTC_SLOW_CLK_SRC_RC_SLOW, + ESP32_RTC_SLOW_CLK_SRC_RC_FAST_D256, +#if CONFIG_FIXTURE_XTAL + ESP32_RTC_SLOW_CLK_SRC_XTAL32K, +#endif +}; + +uint32_t rtc_rtc_slow_clk_src_freq[] = { + ESP32_RTC_SLOW_CLK_SRC_RC_SLOW_FREQ, + ESP32_RTC_SLOW_CLK_SRC_RC_FAST_D256_FREQ, +#if CONFIG_FIXTURE_XTAL + ESP32_RTC_SLOW_CLK_SRC_XTAL32K_FREQ, +#endif +}; + +ZTEST(rtc_clk, test_rtc_slow_src) +{ + struct esp32_clock_config clk_cfg = {0}; + int ret = 0; + uint32_t cpu_rate = 0; + + clk_cfg.cpu.xtal_freq = (DT_PROP(DT_INST(0, DT_CPU_COMPAT), xtal_freq) / MHZ(1)); + + for (uint8_t i = 0; i < ARRAY_SIZE(rtc_rtc_slow_clk_src); i++) { + clk_cfg.rtc.rtc_slow_clock_src = rtc_rtc_slow_clk_src[i]; + + TC_PRINT("Testing RTC SLOW CLK freq: %d MHz\n", rtc_rtc_slow_clk_src_freq[i]); + + ret = clock_control_configure( + clk_dev, (clock_control_subsys_t)ESP32_CLOCK_CONTROL_SUBSYS_RTC_SLOW, + &clk_cfg); + zassert_false(ret, "Failed to set CPU clock source"); + + ret = clock_control_get_rate( + clk_dev, (clock_control_subsys_t)ESP32_CLOCK_CONTROL_SUBSYS_RTC_SLOW, + &cpu_rate); + zassert_false(ret, "Failed to get RTC_SLOW clock rate"); + zassert_equal(cpu_rate, rtc_rtc_slow_clk_src_freq[i], + "CPU clock rate is not equal to configured frequency (%d != %d)", + cpu_rate, rtc_rtc_slow_clk_src_freq[i]); + } +} + +ZTEST_SUITE(rtc_clk, NULL, rtc_clk_setup, NULL, NULL, NULL); diff --git a/tests/boards/espressif_esp32/rtc_clk/testcase.yaml b/tests/boards/espressif_esp32/rtc_clk/testcase.yaml new file mode 100644 index 0000000000000..c968be3850ccc --- /dev/null +++ b/tests/boards/espressif_esp32/rtc_clk/testcase.yaml @@ -0,0 +1,17 @@ +tests: + boards.esp32.rtc_clk: + platform_allow: + - esp32_devkitc_wrover/esp32/procpu + - esp32c3_devkitm + - esp32s2_saola + - esp32s3_devkitm/esp32s3/procpu + boards.esp32.rtc_clk.xtal: + platform_allow: + - esp32_devkitc_wrover/esp32/procpu + - esp32c3_devkitm + - esp32s2_saola + - esp32s3_devkitm/esp32s3/procpu + harness_config: + fixture: external_xtal + extra_configs: + - CONFIG_FIXTURE_XTAL=y From 59415697c4a98a231217120af87b017fe7ec3f14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Chru=C5=9Bci=C5=84ski?= Date: Fri, 24 May 2024 10:54:50 +0200 Subject: [PATCH 1091/2849] modules: hal_nordic: nrfx: nrfx_config: Fix SPIS137 config MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixing a bug where wrong instance was enabled when SPIS137 was supposed to be used. Signed-off-by: Krzysztof Chruściński --- modules/hal_nordic/nrfx/nrfx_config.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/hal_nordic/nrfx/nrfx_config.h b/modules/hal_nordic/nrfx/nrfx_config.h index a54866252a5cc..397d7b2a32093 100644 --- a/modules/hal_nordic/nrfx/nrfx_config.h +++ b/modules/hal_nordic/nrfx/nrfx_config.h @@ -495,7 +495,7 @@ #define NRFX_SPIS136_ENABLED 1 #endif #ifdef CONFIG_NRFX_SPIS137 -#define NRFX_SPIS130_ENABLED 1 +#define NRFX_SPIS137_ENABLED 1 #endif #ifdef CONFIG_NRFX_SYSTICK From f7437ac3b1a35fae56b810bbaf0bca06e4a91e18 Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Mon, 29 Apr 2024 10:49:22 -0700 Subject: [PATCH 1092/2849] pm: Move z_pm_save_idle_exit to pm subsys There is no need to this function be defined inside the kernel since all places using it are protecting the call under ifdef PM guards. This way we can also remove the ifdef condition inside the implementation. Signed-off-by: Flavio Ceolin --- include/zephyr/pm/pm.h | 9 +++++++-- kernel/idle.c | 15 --------------- subsys/pm/pm.c | 13 +++++++++++++ 3 files changed, 20 insertions(+), 17 deletions(-) diff --git a/include/zephyr/pm/pm.h b/include/zephyr/pm/pm.h index 09138bf1871f1..5c55294722176 100644 --- a/include/zephyr/pm/pm.h +++ b/include/zephyr/pm/pm.h @@ -116,6 +116,10 @@ int pm_notifier_unregister(struct pm_notifier *notifier); */ const struct pm_state_info *pm_state_next_get(uint8_t cpu); +/** @cond INTERNAL_HIDDEN */ +void z_pm_save_idle_exit(void); +/** @endcond */ + /** * @} */ @@ -175,10 +179,11 @@ static inline const struct pm_state_info *pm_state_next_get(uint8_t cpu) return NULL; } +static inline void z_pm_save_idle_exit(void) +{ +} #endif /* CONFIG_PM */ -void z_pm_save_idle_exit(void); - #ifdef __cplusplus } #endif diff --git a/kernel/idle.c b/kernel/idle.c index bef193aa8e86d..62ff84e4c88dc 100644 --- a/kernel/idle.c +++ b/kernel/idle.c @@ -18,21 +18,6 @@ LOG_MODULE_DECLARE(os, CONFIG_KERNEL_LOG_LEVEL); -void z_pm_save_idle_exit(void) -{ -#ifdef CONFIG_PM - /* Some CPU low power states require notification at the ISR - * to allow any operations that needs to be done before kernel - * switches task or processes nested interrupts. - * This can be simply ignored if not required. - */ - pm_system_resume(); -#endif /* CONFIG_PM */ -#ifdef CONFIG_SYS_CLOCK_EXISTS - sys_clock_idle_exit(); -#endif /* CONFIG_SYS_CLOCK_EXISTS */ -} - void idle(void *unused1, void *unused2, void *unused3) { ARG_UNUSED(unused1); diff --git a/subsys/pm/pm.c b/subsys/pm/pm.c index bb586073fcbf3..7389f963db692 100644 --- a/subsys/pm/pm.c +++ b/subsys/pm/pm.c @@ -280,3 +280,16 @@ const struct pm_state_info *pm_state_next_get(uint8_t cpu) { return &z_cpus_pm_state[cpu]; } + +void z_pm_save_idle_exit(void) +{ + /* Some CPU low power states require notification at the ISR + * to allow any operations that needs to be done before kernel + * switches task or processes nested interrupts. + * This can be simply ignored if not required. + */ + pm_system_resume(); +#ifdef CONFIG_SYS_CLOCK_EXISTS + sys_clock_idle_exit(); +#endif /* CONFIG_SYS_CLOCK_EXISTS */ +} From 1860dd9153c7f64d2939af768165fb9e5986c422 Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Mon, 29 Apr 2024 14:55:34 -0700 Subject: [PATCH 1093/2849] pm: system: Resume devices in pm_system_resume pm_system_resume() can be called directly from ISR and because of this devices should be resumed before calling pm_state_exit_post_ops(). Signed-off-by: Flavio Ceolin --- subsys/pm/pm.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/subsys/pm/pm.c b/subsys/pm/pm.c index 7389f963db692..92a63147236b7 100644 --- a/subsys/pm/pm.c +++ b/subsys/pm/pm.c @@ -144,6 +144,11 @@ void pm_system_resume(void) * and it may schedule another thread. */ if (atomic_test_and_clear_bit(z_post_ops_required, id)) { +#if defined(CONFIG_PM_DEVICE) && !defined(CONFIG_PM_DEVICE_RUNTIME_EXCLUSIVE) + if (atomic_add(&_cpus_active, 1) == 0) { + pm_resume_devices(); + } +#endif pm_state_exit_post_ops(z_cpus_pm_state[id].state, z_cpus_pm_state[id].substate_id); pm_state_notify(false); z_cpus_pm_state[id] = (struct pm_state_info){PM_STATE_ACTIVE, @@ -240,11 +245,6 @@ bool pm_system_suspend(int32_t ticks) pm_stats_stop(); /* Wake up sequence starts here */ -#if defined(CONFIG_PM_DEVICE) && !defined(CONFIG_PM_DEVICE_RUNTIME_EXCLUSIVE) - if (atomic_add(&_cpus_active, 1) == 0) { - pm_resume_devices(); - } -#endif pm_stats_update(z_cpus_pm_state[id].state); pm_system_resume(); k_sched_unlock(); From 4c5ee9b2dbc515bafd20957f41e734e59ff2c052 Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Mon, 29 Apr 2024 14:57:55 -0700 Subject: [PATCH 1094/2849] pm: system: Restore clock after sleep sys_clock_idle_exits was being called *only* when the system was resumed from interruption. Signed-off-by: Flavio Ceolin --- subsys/pm/pm.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/subsys/pm/pm.c b/subsys/pm/pm.c index 92a63147236b7..96ca35cdbe9d5 100644 --- a/subsys/pm/pm.c +++ b/subsys/pm/pm.c @@ -151,6 +151,9 @@ void pm_system_resume(void) #endif pm_state_exit_post_ops(z_cpus_pm_state[id].state, z_cpus_pm_state[id].substate_id); pm_state_notify(false); +#ifdef CONFIG_SYS_CLOCK_EXISTS + sys_clock_idle_exit(); +#endif /* CONFIG_SYS_CLOCK_EXISTS */ z_cpus_pm_state[id] = (struct pm_state_info){PM_STATE_ACTIVE, 0, 0}; } @@ -289,7 +292,4 @@ void z_pm_save_idle_exit(void) * This can be simply ignored if not required. */ pm_system_resume(); -#ifdef CONFIG_SYS_CLOCK_EXISTS - sys_clock_idle_exit(); -#endif /* CONFIG_SYS_CLOCK_EXISTS */ } From 5ca3bc92c8e00def6b071cc0f1cd6b831f362b38 Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Tue, 30 Apr 2024 15:50:40 -0700 Subject: [PATCH 1095/2849] intel_adsp: power: SoC restores the clock The SoC restores the clock only when leaving soft-off only. Signed-off-by: Flavio Ceolin --- drivers/timer/intel_adsp_timer.c | 10 +++------- .../intel_adsp/ace/include/ace15_mtpm/adsp_power.h | 6 ++++++ .../intel_adsp/ace/include/ace20_lnl/adsp_power.h | 6 ++++++ soc/intel/intel_adsp/ace/power.c | 2 +- 4 files changed, 16 insertions(+), 8 deletions(-) diff --git a/drivers/timer/intel_adsp_timer.c b/drivers/timer/intel_adsp_timer.c index d1f37b123c2c2..2636e506bfe0a 100644 --- a/drivers/timer/intel_adsp_timer.c +++ b/drivers/timer/intel_adsp_timer.c @@ -212,7 +212,6 @@ void smp_timer_init(void) { } -/* Runs on core 0 only */ static int sys_clock_driver_init(void) { uint64_t curr = count(); @@ -224,14 +223,11 @@ static int sys_clock_driver_init(void) return 0; } -#ifdef CONFIG_PM - -void sys_clock_idle_exit(void) +/* Runs on core 0 only */ +void intel_adsp_clock_soft_off_exit(void) { - sys_clock_driver_init(); + (void)sys_clock_driver_init(); } -#endif - SYS_INIT(sys_clock_driver_init, PRE_KERNEL_2, CONFIG_SYSTEM_CLOCK_INIT_PRIORITY); diff --git a/soc/intel/intel_adsp/ace/include/ace15_mtpm/adsp_power.h b/soc/intel/intel_adsp/ace/include/ace15_mtpm/adsp_power.h index 4da0e07508c1a..b52ba820fd2b9 100644 --- a/soc/intel/intel_adsp/ace/include/ace15_mtpm/adsp_power.h +++ b/soc/intel/intel_adsp/ace/include/ace15_mtpm/adsp_power.h @@ -88,6 +88,12 @@ static ALWAYS_INLINE bool soc_cpu_is_powered(int cpu_num) return (ACE_PWRSTS->dsphpxpgs & BIT(cpu_num)) == BIT(cpu_num); } +/** + * @brief Restore timer after leaving soft-off. + * + */ +void intel_adsp_clock_soft_off_exit(void); + /** * @brief Retrieve node identifier for Intel ADSP HOST power domain. */ diff --git a/soc/intel/intel_adsp/ace/include/ace20_lnl/adsp_power.h b/soc/intel/intel_adsp/ace/include/ace20_lnl/adsp_power.h index d25ffba2ae341..7ad97c4c7d8f5 100644 --- a/soc/intel/intel_adsp/ace/include/ace20_lnl/adsp_power.h +++ b/soc/intel/intel_adsp/ace/include/ace20_lnl/adsp_power.h @@ -89,6 +89,12 @@ static ALWAYS_INLINE bool soc_cpu_is_powered(int cpu_num) return (ACE_PWRSTS->dsphpxpgs & BIT(cpu_num)) == BIT(cpu_num); } +/** + * @brief Restore timer after leaving soft-off. + * + */ +void intel_adsp_clock_soft_off_exit(void); + /** * @brief Retrieve node identifier for Intel ADSP HOST power domain. */ diff --git a/soc/intel/intel_adsp/ace/power.c b/soc/intel/intel_adsp/ace/power.c index 4dadb89378af6..afc270f9afa07 100644 --- a/soc/intel/intel_adsp/ace/power.c +++ b/soc/intel/intel_adsp/ace/power.c @@ -388,7 +388,7 @@ void pm_state_exit_post_ops(enum pm_state state, uint8_t substate_id) imr_layout->imr_state.header.adsp_imr_magic = 0; imr_layout->imr_state.header.imr_restore_vector = NULL; imr_layout->imr_state.header.imr_ram_storage = NULL; - sys_clock_idle_exit(); + intel_adsp_clock_soft_off_exit(); mem_window_idle_exit(); soc_mp_on_d3_exit(); } From e1685bb4219d2529e428e13df9c224c58a515233 Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Tue, 30 Apr 2024 16:06:00 -0700 Subject: [PATCH 1096/2849] stm32: power: SoC restores the clock Clock must be restored as soon as the SoC leaves standby. Keep the logic inside the SoC instead of delegate it to the pm subsystem. Signed-off-by: Flavio Ceolin --- drivers/clock_control/clock_stm32_ll_common.h | 3 ++- drivers/timer/stm32_lptim_timer.c | 11 +++++++++-- soc/st/stm32/stm32wbax/power.c | 2 +- 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/drivers/clock_control/clock_stm32_ll_common.h b/drivers/clock_control/clock_stm32_ll_common.h index 5bab50d2e0dfa..7fd5e5386aeb2 100644 --- a/drivers/clock_control/clock_stm32_ll_common.h +++ b/drivers/clock_control/clock_stm32_ll_common.h @@ -50,8 +50,9 @@ void config_plli2s(void); #endif void config_enable_default_clocks(void); -/* function exported to the soc power.c */ +/* functions exported to the soc power.c */ int stm32_clock_control_init(const struct device *dev); +void stm32_clock_control_standby_exit(void); #ifdef __cplusplus } diff --git a/drivers/timer/stm32_lptim_timer.c b/drivers/timer/stm32_lptim_timer.c index c94be66b80e11..90c75fb709ce9 100644 --- a/drivers/timer/stm32_lptim_timer.c +++ b/drivers/timer/stm32_lptim_timer.c @@ -550,14 +550,21 @@ static int sys_clock_driver_init(void) return 0; } -void sys_clock_idle_exit(void) +void stm32_clock_control_standby_exit(void) { #ifdef CONFIG_STM32_LPTIM_STDBY_TIMER if (clock_control_get_status(clk_ctrl, (clock_control_subsys_t) &lptim_clk[0]) != CLOCK_CONTROL_STATUS_ON) { sys_clock_driver_init(); - } else if (timeout_stdby) { + } +#endif /* CONFIG_STM32_LPTIM_STDBY_TIMER */ +} + +void sys_clock_idle_exit(void) +{ +#ifdef CONFIG_STM32_LPTIM_STDBY_TIMER + if (timeout_stdby) { cycle_t missed_lptim_cnt; uint32_t stdby_timer_diff, stdby_timer_post, dticks; uint64_t stdby_timer_us; diff --git a/soc/st/stm32/stm32wbax/power.c b/soc/st/stm32/stm32wbax/power.c index 1565c59cfc6ca..ebb6d779a7bb5 100644 --- a/soc/st/stm32/stm32wbax/power.c +++ b/soc/st/stm32/stm32wbax/power.c @@ -118,7 +118,7 @@ static void set_mode_suspend_to_ram(void) /* Execution is restored at this point after wake up */ /* Restore system clock as soon as we exit standby mode */ - sys_clock_idle_exit(); + stm32_clock_control_standby_exit(); } #endif From 4d85f3d91cb9e37d52e770fbf266e110aa90c296 Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Tue, 30 Apr 2024 16:45:49 -0700 Subject: [PATCH 1097/2849] pm: Deprecate z_pm_save_idle_exit Deprecate z_pm_save_idle_exit and promote pm_system_resume. Signed-off-by: Flavio Ceolin --- arch/arm/core/cortex_a_r/irq_manage.c | 2 +- arch/arm/core/cortex_m/irq_manage.c | 2 +- arch/arm/core/cortex_m/isr_wrapper.c | 4 ++-- arch/posix/core/swap.c | 2 +- include/zephyr/arch/x86/ia32/arch.h | 2 +- include/zephyr/pm/pm.h | 27 ++++++++++++++++++++++++++- kernel/include/kernel_internal.h | 20 -------------------- 7 files changed, 32 insertions(+), 27 deletions(-) diff --git a/arch/arm/core/cortex_a_r/irq_manage.c b/arch/arm/core/cortex_a_r/irq_manage.c index a381fad2a4871..1dca75e297ab0 100644 --- a/arch/arm/core/cortex_a_r/irq_manage.c +++ b/arch/arm/core/cortex_a_r/irq_manage.c @@ -98,7 +98,7 @@ void _arch_isr_direct_pm(void) if (_kernel.idle) { _kernel.idle = 0; - z_pm_save_idle_exit(); + pm_system_resume(); } irq_unlock(key); diff --git a/arch/arm/core/cortex_m/irq_manage.c b/arch/arm/core/cortex_m/irq_manage.c index 3940d5246d4b5..b72332b32e81a 100644 --- a/arch/arm/core/cortex_m/irq_manage.c +++ b/arch/arm/core/cortex_m/irq_manage.c @@ -131,7 +131,7 @@ void _arch_isr_direct_pm(void) if (_kernel.idle) { _kernel.idle = 0; - z_pm_save_idle_exit(); + pm_system_resume(); } #if defined(CONFIG_ARMV6_M_ARMV8_M_BASELINE) diff --git a/arch/arm/core/cortex_m/isr_wrapper.c b/arch/arm/core/cortex_m/isr_wrapper.c index 6e6016508c6a4..46aac160c3bf9 100644 --- a/arch/arm/core/cortex_m/isr_wrapper.c +++ b/arch/arm/core/cortex_m/isr_wrapper.c @@ -42,7 +42,7 @@ void _isr_wrapper(void) * idle, this ensures that the calculation and programming of the * device for the next timer deadline is not interrupted. For * non-tickless idle, this ensures that the clearing of the kernel idle - * state is not interrupted. In each case, z_pm_save_idle_exit + * state is not interrupted. In each case, pm_system_resume * is called with interrupts disabled. */ @@ -59,7 +59,7 @@ void _isr_wrapper(void) if (_kernel.idle != 0) { /* clear kernel idle state */ _kernel.idle = 0; - z_pm_save_idle_exit(); + pm_system_resume(); } /* re-enable interrupts */ __enable_irq(); diff --git a/arch/posix/core/swap.c b/arch/posix/core/swap.c index 67ca4c5bb9bbf..d4ec5e50b5ea6 100644 --- a/arch/posix/core/swap.c +++ b/arch/posix/core/swap.c @@ -112,7 +112,7 @@ void posix_irq_check_idle_exit(void) { if (_kernel.idle) { _kernel.idle = 0; - z_pm_save_idle_exit(); + pm_system_resume(); } } #endif diff --git a/include/zephyr/arch/x86/ia32/arch.h b/include/zephyr/arch/x86/ia32/arch.h index e39e6c0cd6565..490dfdb40f334 100644 --- a/include/zephyr/arch/x86/ia32/arch.h +++ b/include/zephyr/arch/x86/ia32/arch.h @@ -250,7 +250,7 @@ static inline void arch_irq_direct_pm(void) { if (_kernel.idle) { _kernel.idle = 0; - z_pm_save_idle_exit(); + pm_system_resume(); } } diff --git a/include/zephyr/pm/pm.h b/include/zephyr/pm/pm.h index 5c55294722176..e1fb695415c16 100644 --- a/include/zephyr/pm/pm.h +++ b/include/zephyr/pm/pm.h @@ -116,8 +116,28 @@ int pm_notifier_unregister(struct pm_notifier *notifier); */ const struct pm_state_info *pm_state_next_get(uint8_t cpu); +/** + * @brief Notify exit from kernel sleep. + * + * This function would notify exit from kernel idling if a corresponding + * pm_system_suspend() notification was handled and did not return + * PM_STATE_ACTIVE. + * + * This function should be called from the ISR context of the event + * that caused the exit from kernel idling. + * + * This is required for cpu power states that would require + * interrupts to be enabled while entering low power states. e.g. C1 in x86. In + * those cases, the ISR would be invoked immediately after the event wakes up + * the CPU, before code following the CPU wait, gets a chance to execute. This + * can be ignored if no operation needs to be done at the wake event + * notification. + */ +void pm_system_resume(void); + + /** @cond INTERNAL_HIDDEN */ -void z_pm_save_idle_exit(void); +__deprecated void z_pm_save_idle_exit(void); /** @endcond */ /** @@ -182,6 +202,11 @@ static inline const struct pm_state_info *pm_state_next_get(uint8_t cpu) static inline void z_pm_save_idle_exit(void) { } + +static inline void pm_system_resume(void) +{ +} + #endif /* CONFIG_PM */ #ifdef __cplusplus diff --git a/kernel/include/kernel_internal.h b/kernel/include/kernel_internal.h index b2e1ccf706823..bb9ee4b01f1e6 100644 --- a/kernel/include/kernel_internal.h +++ b/kernel/include/kernel_internal.h @@ -243,26 +243,6 @@ void z_handle_obj_poll_events(sys_dlist_t *events, uint32_t state); */ bool pm_system_suspend(int32_t ticks); -/** - * Notify exit from kernel idling after PM operations - * - * This function would notify exit from kernel idling if a corresponding - * pm_system_suspend() notification was handled and did not return - * PM_STATE_ACTIVE. - * - * This function would be called from the ISR context of the event - * that caused the exit from kernel idling. This will be called immediately - * after interrupts are enabled. This is called to give a chance to do - * any operations before the kernel would switch tasks or processes nested - * interrupts. This is required for cpu low power states that would require - * interrupts to be enabled while entering low power states. e.g. C1 in x86. In - * those cases, the ISR would be invoked immediately after the event wakes up - * the CPU, before code following the CPU wait, gets a chance to execute. This - * can be ignored if no operation needs to be done at the wake event - * notification. - */ -void pm_system_resume(void); - #endif /* CONFIG_PM */ #ifdef CONFIG_DEMAND_PAGING_TIMING_HISTOGRAM From 5a35037af37d7af3e98d5da1fc2e7d22421f5065 Mon Sep 17 00:00:00 2001 From: Yong Cong Sin Date: Sun, 26 May 2024 01:55:10 +0800 Subject: [PATCH 1098/2849] arch: riscv: check esf before calling z_riscv_unwind_stack Make sure that esf is not NULL before calling z_riscv_unwind_stack to prevent NULL pointer dereferencing. Signed-off-by: Yong Cong Sin --- arch/riscv/core/fatal.c | 2 +- arch/riscv/core/stacktrace.c | 8 -------- 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/arch/riscv/core/fatal.c b/arch/riscv/core/fatal.c index 31ead071eb9c2..2624edbec9093 100644 --- a/arch/riscv/core/fatal.c +++ b/arch/riscv/core/fatal.c @@ -107,7 +107,7 @@ FUNC_NORETURN void z_riscv_fatal_error_csf(unsigned int reason, const z_arch_esf LOG_ERR(""); } - if (IS_ENABLED(CONFIG_RISCV_EXCEPTION_STACK_TRACE)) { + if (IS_ENABLED(CONFIG_RISCV_EXCEPTION_STACK_TRACE) && (esf != NULL)) { z_riscv_unwind_stack(esf); } diff --git a/arch/riscv/core/stacktrace.c b/arch/riscv/core/stacktrace.c index e0c97b642ba3d..9c6c013efaecc 100644 --- a/arch/riscv/core/stacktrace.c +++ b/arch/riscv/core/stacktrace.c @@ -88,10 +88,6 @@ void z_riscv_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(fp);) { @@ -121,10 +117,6 @@ void z_riscv_unwind_stack(const z_arch_esf_t *esf) uintptr_t ra; uintptr_t *ksp = (uintptr_t *)sp; - if (esf == NULL) { - return; - } - LOG_ERR("call trace:"); for (int i = 0; From d084d83baf920944aa2413f72e7d38bf81e3f890 Mon Sep 17 00:00:00 2001 From: Yong Cong Sin Date: Sun, 26 May 2024 14:20:24 +0800 Subject: [PATCH 1099/2849] userspace: fix minor typo in `k_is_in_user_syscall` 'generasted' should have been 'generated' fix it. Signed-off-by: Yong Cong Sin --- include/zephyr/internal/syscall_handler.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/zephyr/internal/syscall_handler.h b/include/zephyr/internal/syscall_handler.h index 09a19f1074388..091a60615f60f 100644 --- a/include/zephyr/internal/syscall_handler.h +++ b/include/zephyr/internal/syscall_handler.h @@ -56,7 +56,7 @@ enum _obj_init_check { */ static inline bool k_is_in_user_syscall(void) { - /* This gets set on entry to the syscall's generasted z_mrsh + /* This gets set on entry to the syscall's generated z_mrsh * function and then cleared on exit. This code path is only * encountered when a syscall is made from user mode, system * calls from supervisor mode bypass everything directly to From 85bd8520504f3551512739255c95a92febef6ecb Mon Sep 17 00:00:00 2001 From: Johann Fischer Date: Thu, 23 May 2024 11:49:16 +0200 Subject: [PATCH 1100/2849] samples: sensor: remove fxos8700-hid This sample uses the FXOS8700 compatible accelerometer to emulate relative mouse movement. While this is an interesting example, it does not provide anything unique in terms of sensor drivers or USB device support. The example has no documentation and unsafe report buffer handling. The example would need to be completely rewritten to make it generic and use any accelerometer, e.g. with an accel0 alias. From a USB perspective, there is no interest in maintaining this sample or porting it to the new device support and new HID device API. Signed-off-by: Johann Fischer --- samples/sensor/fxos8700-hid/CMakeLists.txt | 8 - samples/sensor/fxos8700-hid/prj.conf | 17 -- samples/sensor/fxos8700-hid/sample.yaml | 10 - samples/sensor/fxos8700-hid/src/main.c | 251 --------------------- 4 files changed, 286 deletions(-) delete mode 100644 samples/sensor/fxos8700-hid/CMakeLists.txt delete mode 100644 samples/sensor/fxos8700-hid/prj.conf delete mode 100644 samples/sensor/fxos8700-hid/sample.yaml delete mode 100644 samples/sensor/fxos8700-hid/src/main.c diff --git a/samples/sensor/fxos8700-hid/CMakeLists.txt b/samples/sensor/fxos8700-hid/CMakeLists.txt deleted file mode 100644 index e9d8e00fa5907..0000000000000 --- a/samples/sensor/fxos8700-hid/CMakeLists.txt +++ /dev/null @@ -1,8 +0,0 @@ -# SPDX-License-Identifier: Apache-2.0 - -cmake_minimum_required(VERSION 3.20.0) -find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) -project(fxos8700-hid) - -FILE(GLOB app_sources src/*.c) -target_sources(app PRIVATE ${app_sources}) diff --git a/samples/sensor/fxos8700-hid/prj.conf b/samples/sensor/fxos8700-hid/prj.conf deleted file mode 100644 index 6650650f119af..0000000000000 --- a/samples/sensor/fxos8700-hid/prj.conf +++ /dev/null @@ -1,17 +0,0 @@ -CONFIG_LOG=y -CONFIG_USB_DEVICE_STACK=y -CONFIG_USB_DEVICE_HID=y -CONFIG_USB_DEVICE_PRODUCT="Zephyr HID accelerometer mouse sample" -CONFIG_USB_DRIVER_LOG_LEVEL_ERR=y -CONFIG_USB_DEVICE_LOG_LEVEL_ERR=y -CONFIG_USB_DEVICE_INITIALIZE_AT_BOOT=n - -CONFIG_STDOUT_CONSOLE=y -CONFIG_I2C=y -CONFIG_SENSOR=y -CONFIG_FXOS8700_MODE_ACCEL=y -CONFIG_FXOS8700_TRIGGER_OWN_THREAD=y -CONFIG_SENSOR_LOG_LEVEL_DBG=y - -CONFIG_GPIO=y -CONFIG_CBPRINTF_FP_SUPPORT=y diff --git a/samples/sensor/fxos8700-hid/sample.yaml b/samples/sensor/fxos8700-hid/sample.yaml deleted file mode 100644 index b35bac5f4ef67..0000000000000 --- a/samples/sensor/fxos8700-hid/sample.yaml +++ /dev/null @@ -1,10 +0,0 @@ -sample: - name: USB HID accelerometer mouse sample -tests: - sample.sensor.usb.fxos8700-hid: - depends_on: usb_device - platform_allow: frdm_k64f - harness: usb - tags: - - usb - - sensors diff --git a/samples/sensor/fxos8700-hid/src/main.c b/samples/sensor/fxos8700-hid/src/main.c deleted file mode 100644 index 8932e992d9593..0000000000000 --- a/samples/sensor/fxos8700-hid/src/main.c +++ /dev/null @@ -1,251 +0,0 @@ -/* - * Copyright (c) 2018 qianfan Zhao - * Copyright (c) 2018 Nordic Semiconductor ASA - * Copyright (c) 2019 Intel Corp - * - * SPDX-License-Identifier: Apache-2.0 - */ -#include -#include -#include -#include - -#include -#include - -#define LOG_LEVEL LOG_LEVEL_DBG -LOG_MODULE_REGISTER(main); - -#define SW0_NODE DT_ALIAS(sw0) -#define SW1_NODE DT_ALIAS(sw1) - -#if DT_NODE_HAS_STATUS(SW0_NODE, okay) -static const struct gpio_dt_spec sw0_gpio = GPIO_DT_SPEC_GET(SW0_NODE, gpios); -#endif - -/* If second button exists, use it as right-click. */ -#if DT_NODE_HAS_STATUS(SW1_NODE, okay) -static const struct gpio_dt_spec sw1_gpio = GPIO_DT_SPEC_GET(SW1_NODE, gpios); -#endif - -static const struct gpio_dt_spec led_gpio = GPIO_DT_SPEC_GET(DT_ALIAS(led0), gpios); - - -static const uint8_t hid_report_desc[] = HID_MOUSE_REPORT_DESC(2); - -static uint32_t def_val[4]; -static volatile uint8_t status[4]; -static K_SEM_DEFINE(sem, 0, 1); /* starts off "not available" */ -static struct gpio_callback gpio_callbacks[4]; - -#define MOUSE_BTN_REPORT_POS 0 -#define MOUSE_X_REPORT_POS 1 -#define MOUSE_Y_REPORT_POS 2 - -#define MOUSE_BTN_LEFT BIT(0) -#define MOUSE_BTN_RIGHT BIT(1) -#define MOUSE_BTN_MIDDLE BIT(2) - - -static void left_button(const struct device *gpio, struct gpio_callback *cb, - uint32_t pins) -{ - uint32_t cur_val; - uint8_t state = status[MOUSE_BTN_REPORT_POS]; - - cur_val = gpio_pin_get(gpio, pins); - if (def_val[0] != cur_val) { - state |= MOUSE_BTN_LEFT; - } else { - state &= ~MOUSE_BTN_LEFT; - } - - if (status[MOUSE_BTN_REPORT_POS] != state) { - status[MOUSE_BTN_REPORT_POS] = state; - k_sem_give(&sem); - } -} - -#if DT_NODE_HAS_STATUS(SW1_NODE, okay) -static void right_button(const struct device *gpio, struct gpio_callback *cb, - uint32_t pins) - -{ - uint32_t cur_val; - uint8_t state = status[MOUSE_BTN_REPORT_POS]; - - cur_val = gpio_pin_get(gpio, pins); - if (def_val[0] != cur_val) { - state |= MOUSE_BTN_RIGHT; - } else { - state &= ~MOUSE_BTN_RIGHT; - } - - if (status[MOUSE_BTN_REPORT_POS] != state) { - status[MOUSE_BTN_REPORT_POS] = state; - k_sem_give(&sem); - } -} -#endif - -int callbacks_configure(const struct gpio_dt_spec *gpio, - gpio_callback_handler_t handler, - struct gpio_callback *callback, uint32_t *val) -{ - int ret; - - if (!device_is_ready(gpio->port)) { - LOG_ERR("%s: device not ready.", gpio->port->name); - return -ENODEV; - } - - gpio_pin_configure_dt(gpio, GPIO_INPUT); - - ret = gpio_pin_get_dt(gpio); - if (ret < 0) { - return ret; - } - - *val = (uint32_t)ret; - - gpio_init_callback(callback, handler, BIT(gpio->pin)); - gpio_add_callback(gpio->port, callback); - gpio_pin_interrupt_configure_dt(gpio, GPIO_INT_EDGE_TO_ACTIVE); - - return 0; -} - -static bool read_accel(const struct device *dev) -{ - struct sensor_value val[3]; - int ret; - - ret = sensor_channel_get(dev, SENSOR_CHAN_ACCEL_XYZ, val); - if (ret < 0) { - LOG_ERR("Cannot read sensor channels"); - return false; - } - - /* For printing double we need to use printf with - * printf("%10.6f\n", sensor_value_to_double(x)); - */ - LOG_DBG("int parts: X %d Y %d", val[0].val1, val[1].val1); - - /* TODO: Add proper calculations */ - - if (val[0].val1 != 0) { - status[MOUSE_X_REPORT_POS] = val[0].val1 * 4; - } - - if (val[1].val1 != 0) { - status[MOUSE_Y_REPORT_POS] = val[1].val1 * 4; - } - - if (val[0].val1 != 0 || val[1].val1 != 0) { - return true; - } else { - return false; - } -} - -static void trigger_handler(const struct device *dev, - const struct sensor_trigger *tr) -{ - ARG_UNUSED(tr); - - /* Always fetch the sample to clear the data ready interrupt in the - * sensor. - */ - if (sensor_sample_fetch(dev)) { - LOG_ERR("sensor_sample_fetch failed"); - return; - } - - if (read_accel(dev)) { - k_sem_give(&sem); - } -} - -int main(void) -{ - int ret; - uint8_t report[4] = { 0x00 }; - const struct device *accel_dev, *hid_dev; - - if (!gpio_is_ready_dt(&led_gpio)) { - LOG_ERR("%s: device not ready.", led_gpio.port->name); - return 0; - } - - hid_dev = device_get_binding("HID_0"); - if (hid_dev == NULL) { - LOG_ERR("Cannot get USB HID Device"); - return 0; - } - - gpio_pin_configure_dt(&led_gpio, GPIO_OUTPUT); - - if (callbacks_configure(&sw0_gpio, &left_button, &gpio_callbacks[0], &def_val[0])) { - LOG_ERR("Failed configuring left button callback."); - return 0; - } - -#if DT_NODE_HAS_STATUS(SW1_NODE, okay) - if (callbacks_configure(&sw1_gpio, &right_button, &gpio_callbacks[1], &def_val[1])) { - LOG_ERR("Failed configuring right button callback."); - return 0; - } -#endif - - accel_dev = DEVICE_DT_GET_ONE(nxp_fxos8700); - if (!device_is_ready(accel_dev)) { - LOG_ERR("%s: device not ready.", accel_dev->name); - return 0; - } - - struct sensor_value attr = { - .val1 = 6, - .val2 = 250000, - }; - - if (sensor_attr_set(accel_dev, SENSOR_CHAN_ALL, - SENSOR_ATTR_SAMPLING_FREQUENCY, &attr)) { - LOG_ERR("Could not set sampling frequency"); - return 0; - } - - struct sensor_trigger trig = { - .type = SENSOR_TRIG_DATA_READY, - .chan = SENSOR_CHAN_ACCEL_XYZ, - }; - - if (sensor_trigger_set(accel_dev, &trig, trigger_handler)) { - LOG_ERR("Could not set trigger"); - return 0; - } - - usb_hid_register_device(hid_dev, hid_report_desc, - sizeof(hid_report_desc), NULL); - - ret = usb_enable(NULL); - if (ret != 0) { - LOG_ERR("Failed to enable USB"); - return 0; - } - - usb_hid_init(hid_dev); - - while (true) { - k_sem_take(&sem, K_FOREVER); - - report[MOUSE_BTN_REPORT_POS] = status[MOUSE_BTN_REPORT_POS]; - report[MOUSE_X_REPORT_POS] = status[MOUSE_X_REPORT_POS]; - status[MOUSE_X_REPORT_POS] = 0U; - report[MOUSE_Y_REPORT_POS] = status[MOUSE_Y_REPORT_POS]; - status[MOUSE_Y_REPORT_POS] = 0U; - hid_int_ep_write(hid_dev, report, sizeof(report), NULL); - - /* Toggle LED on sent report */ - gpio_pin_toggle_dt(&led_gpio); - } -} From f5fd2cf49ee9c83499eb1ca5d978c208bf65f330 Mon Sep 17 00:00:00 2001 From: Emil Gydesen Date: Thu, 23 May 2024 11:50:16 +0200 Subject: [PATCH 1101/2849] Bluetooth: ISO: Avoid bt_iso_chan_disconnected in bt_iso_reset The bt_iso_chan_disconnected function will attempt to remote ISO data paths as the central. Signed-off-by: Emil Gydesen --- subsys/bluetooth/host/iso.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/subsys/bluetooth/host/iso.c b/subsys/bluetooth/host/iso.c index 6df42691a288f..e4dab861c2dc6 100644 --- a/subsys/bluetooth/host/iso.c +++ b/subsys/bluetooth/host/iso.c @@ -3290,12 +3290,20 @@ 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; + struct bt_iso_chan *cis; - /* Call the disconnected callback for each CIS that is no idle */ - SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&cig->cis_channels, cis, tmp, node) { + /* Disconnect any connected CIS and call the callback + * We cannot use bt_iso_chan_disconnected directly here, as that + * attempts to also remove the ISO data path, which we shouldn't attempt to + * during the reset, as that sends HCI commands. + */ + SYS_SLIST_FOR_EACH_CONTAINER(&cig->cis_channels, cis, node) { if (cis->state != BT_ISO_STATE_DISCONNECTED) { - bt_iso_chan_disconnected(cis, BT_HCI_ERR_UNSPECIFIED); + bt_iso_chan_set_state(cis, BT_ISO_STATE_DISCONNECTED); + bt_iso_cleanup_acl(cis->iso); + if (cis->ops != NULL && cis->ops->disconnected != NULL) { + cis->ops->disconnected(cis, BT_HCI_ERR_UNSPECIFIED); + } } } From d84874309ef71db2afc91afa10857b85c04f6778 Mon Sep 17 00:00:00 2001 From: Aaron Ye Date: Thu, 16 May 2024 16:27:51 +0800 Subject: [PATCH 1102/2849] drivers: spi: create Ambiq SPI BLEIF driver Some Ambiq Apollox Blue SOC (e.g. Apollo3 Blue) uses internal designed BLEIF module which is different from the general IOM module for SPI transceiver. The called HAL API will also be independent. This driver is implemented for the BLEIF module usage scenarios. Signed-off-by: Aaron Ye --- drivers/spi/CMakeLists.txt | 1 + drivers/spi/Kconfig.ambiq | 26 ++++ drivers/spi/spi_ambiq_bleif.c | 215 ++++++++++++++++++++++++++ dts/bindings/spi/ambiq,spi-bleif.yaml | 18 +++ modules/hal_ambiq/Kconfig | 5 + west.yml | 2 +- 6 files changed, 266 insertions(+), 1 deletion(-) create mode 100644 drivers/spi/spi_ambiq_bleif.c create mode 100644 dts/bindings/spi/ambiq,spi-bleif.yaml diff --git a/drivers/spi/CMakeLists.txt b/drivers/spi/CMakeLists.txt index 840c9dcdc5f6d..f7c8cc6fc791c 100644 --- a/drivers/spi/CMakeLists.txt +++ b/drivers/spi/CMakeLists.txt @@ -45,6 +45,7 @@ zephyr_library_sources_ifdef(CONFIG_SPI_SMARTBOND spi_smartbond.c) zephyr_library_sources_ifdef(CONFIG_SPI_OPENTITAN spi_opentitan.c) zephyr_library_sources_ifdef(CONFIG_SPI_NUMAKER spi_numaker.c) zephyr_library_sources_ifdef(CONFIG_SPI_AMBIQ spi_ambiq.c) +zephyr_library_sources_ifdef(CONFIG_SPI_AMBIQ_BLEIF spi_ambiq_bleif.c) zephyr_library_sources_ifdef(CONFIG_SPI_RPI_PICO_PIO spi_rpi_pico_pio.c) zephyr_library_sources_ifdef(CONFIG_MSPI_AMBIQ mspi_ambiq.c) zephyr_library_sources_ifdef(CONFIG_SPI_MCHP_MSS spi_mchp_mss.c) diff --git a/drivers/spi/Kconfig.ambiq b/drivers/spi/Kconfig.ambiq index 15eaf7463a46b..04113482f1be6 100644 --- a/drivers/spi/Kconfig.ambiq +++ b/drivers/spi/Kconfig.ambiq @@ -1,6 +1,7 @@ # Ambiq SDK SPI # # Copyright (c) 2023 Antmicro +# Copyright (c) 2024 Ambiq Micro Inc. # # SPDX-License-Identifier: Apache-2.0 # @@ -22,3 +23,28 @@ config MSPI_AMBIQ select AMBIQ_HAL_USE_MSPI help Enable driver for Ambiq MSPI. + +config SPI_AMBIQ_BLEIF + bool "AMBIQ SPI-BLEIF driver" + default y + depends on DT_HAS_AMBIQ_SPI_BLEIF_ENABLED + select AMBIQ_HAL + select AMBIQ_HAL_USE_BLEIF + help + Enable driver for Ambiq Apollox Blue SOC (e.g. Apollo3 Blue) + which uses internal designed BLEIF module (different from the + general IOM module) for SPI transceiver. It is always used for + the Bluetooth HCI communication. + +if SPI_AMBIQ_BLEIF + +config SPI_AMBIQ_BLEIF_TIMING_TRACE + bool "Ambiq SPI-BLEIF timing trace" + help + The pins for the SPI transceiver are not exposed from the chips + and no need for user to confiugre them. But the chips design the + configurable BLEIF timing observation functions on other exposed + pins. The user can enable it to configure the pins for timing + trace purpose. + +endif # SPI_AMBIQ_BLEIF diff --git a/drivers/spi/spi_ambiq_bleif.c b/drivers/spi/spi_ambiq_bleif.c new file mode 100644 index 0000000000000..ceaf598455ded --- /dev/null +++ b/drivers/spi/spi_ambiq_bleif.c @@ -0,0 +1,215 @@ +/* + * Copyright (c) 2024 Ambiq Micro Inc. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Some Ambiq Apollox Blue SOC (e.g. Apollo3 Blue) uses internal designed BLEIF module which is + * different from the general IOM module for SPI transceiver. The called HAL API will also be + * independent. This driver is implemented for the BLEIF module usage scenarios. + */ + +#define DT_DRV_COMPAT ambiq_spi_bleif + +#include +LOG_MODULE_REGISTER(spi_ambiq_bleif); + +#include +#include +#include +#include +#include +#include +#include "spi_context.h" +#include + +#define PWRCTRL_MAX_WAIT_US 5 + +typedef int (*ambiq_spi_pwr_func_t)(void); + +struct spi_ambiq_config { + uint32_t base; + int size; + const struct pinctrl_dev_config *pcfg; + ambiq_spi_pwr_func_t pwr_func; +}; + +struct spi_ambiq_data { + struct spi_context ctx; + am_hal_ble_config_t ble_cfg; + void *BLEhandle; +}; + +#define SPI_BASE (((const struct spi_ambiq_config *)(dev)->config)->base) +#define REG_STAT 0x268 +#define SPI_STAT(dev) (SPI_BASE + REG_STAT) +#define SPI_WORD_SIZE 8 + +static int spi_config(const struct device *dev, const struct spi_config *config) +{ + struct spi_ambiq_data *data = dev->data; + struct spi_context *ctx = &(data->ctx); + + int ret = 0; + + if (spi_context_configured(ctx, config)) { + /* Already configured. No need to do it again. */ + return 0; + } + + if (SPI_WORD_SIZE_GET(config->operation) != SPI_WORD_SIZE) { + LOG_ERR("Word size must be %d", SPI_WORD_SIZE); + return -ENOTSUP; + } + + if ((config->operation & SPI_LINES_MASK) != SPI_LINES_SINGLE) { + LOG_ERR("Only supports single mode"); + return -ENOTSUP; + } + + if (config->operation & SPI_LOCK_ON) { + LOG_ERR("Lock On not supported"); + return -ENOTSUP; + } + + if (config->operation & SPI_TRANSFER_LSB) { + LOG_ERR("LSB first not supported"); + return -ENOTSUP; + } + + if (config->operation & SPI_OP_MODE_SLAVE) { + LOG_ERR("Slave mode not supported"); + return -ENOTSUP; + } + if (config->operation & SPI_MODE_LOOP) { + LOG_ERR("Loopback mode not supported"); + return -ENOTSUP; + } + + /* We consider only the default configuration defined in HAL is tested and stable. */ + data->ble_cfg = am_hal_ble_default_config; + + ctx->config = config; + + ret = am_hal_ble_config(data->BLEhandle, &data->ble_cfg); + + return ret; +} + +static int spi_ambiq_xfer(const struct device *dev, const struct spi_config *config) +{ + struct spi_ambiq_data *data = dev->data; + struct spi_context *ctx = &data->ctx; + int ret = 0; + + am_hal_ble_transfer_t trans = {0}; + + if (ctx->tx_len) { + trans.ui8Command = AM_HAL_BLE_WRITE; + trans.pui32Data = (uint32_t *)ctx->tx_buf; + trans.ui16Length = ctx->tx_len; + trans.bContinue = false; + } else { + trans.ui8Command = AM_HAL_BLE_READ; + trans.pui32Data = (uint32_t *)ctx->rx_buf; + trans.ui16Length = ctx->rx_len; + trans.bContinue = false; + } + + ret = am_hal_ble_blocking_transfer(data->BLEhandle, &trans); + spi_context_complete(ctx, dev, 0); + + return ret; +} + +static int spi_ambiq_transceive(const struct device *dev, const struct spi_config *config, + const struct spi_buf_set *tx_bufs, + const struct spi_buf_set *rx_bufs) +{ + struct spi_ambiq_data *data = dev->data; + int ret; + + ret = spi_config(dev, config); + + if (ret) { + return ret; + } + + if (!tx_bufs && !rx_bufs) { + return 0; + } + + spi_context_buffers_setup(&data->ctx, tx_bufs, rx_bufs, 1); + + ret = spi_ambiq_xfer(dev, config); + + return ret; +} + +static int spi_ambiq_release(const struct device *dev, const struct spi_config *config) +{ + struct spi_ambiq_data *data = dev->data; + + if (!sys_read32(SPI_STAT(dev))) { + return -EBUSY; + } + + spi_context_unlock_unconditionally(&data->ctx); + + return 0; +} + +static struct spi_driver_api spi_ambiq_driver_api = { + .transceive = spi_ambiq_transceive, + .release = spi_ambiq_release, +}; + +static int spi_ambiq_init(const struct device *dev) +{ + struct spi_ambiq_data *data = dev->data; + const struct spi_ambiq_config *cfg = dev->config; + int ret; + +#if defined(CONFIG_SPI_AMBIQ_BLEIF_TIMING_TRACE) + ret = pinctrl_apply_state(cfg->pcfg, PINCTRL_STATE_DEFAULT); + if (ret) { + return ret; + } +#endif /* CONFIG_SPI_AMBIQ_BLEIF_TIMING_TRACE */ + + ret = am_hal_ble_initialize((cfg->base - REG_BLEIF_BASEADDR) / cfg->size, &data->BLEhandle); + if (ret) { + return ret; + } + + ret = am_hal_ble_power_control(data->BLEhandle, AM_HAL_BLE_POWER_ACTIVE); + if (ret) { + return ret; + } + + ret = cfg->pwr_func(); + + return ret; +} + +#define AMBIQ_SPI_BLEIF_INIT(n) \ + PINCTRL_DT_INST_DEFINE(n); \ + static int pwr_on_ambiq_spi_##n(void) \ + { \ + uint32_t addr = DT_REG_ADDR(DT_INST_PHANDLE(n, ambiq_pwrcfg)) + \ + DT_INST_PHA(n, ambiq_pwrcfg, offset); \ + sys_write32((sys_read32(addr) | DT_INST_PHA(n, ambiq_pwrcfg, mask)), addr); \ + k_busy_wait(PWRCTRL_MAX_WAIT_US); \ + return 0; \ + } \ + static struct spi_ambiq_data spi_ambiq_data##n = { \ + SPI_CONTEXT_INIT_LOCK(spi_ambiq_data##n, ctx), \ + SPI_CONTEXT_INIT_SYNC(spi_ambiq_data##n, ctx)}; \ + static const struct spi_ambiq_config spi_ambiq_config##n = { \ + .base = DT_INST_REG_ADDR(n), \ + .size = DT_INST_REG_SIZE(n), \ + .pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n), \ + .pwr_func = pwr_on_ambiq_spi_##n}; \ + DEVICE_DT_INST_DEFINE(n, spi_ambiq_init, NULL, &spi_ambiq_data##n, &spi_ambiq_config##n, \ + POST_KERNEL, CONFIG_SPI_INIT_PRIORITY, &spi_ambiq_driver_api); + +DT_INST_FOREACH_STATUS_OKAY(AMBIQ_SPI_BLEIF_INIT) diff --git a/dts/bindings/spi/ambiq,spi-bleif.yaml b/dts/bindings/spi/ambiq,spi-bleif.yaml new file mode 100644 index 0000000000000..2be2ee1b9f8a2 --- /dev/null +++ b/dts/bindings/spi/ambiq,spi-bleif.yaml @@ -0,0 +1,18 @@ +# Copyright (c) 2024 Ambiq Micro Inc. +# SPDX-License-Identifier: Apache-2.0 + +description: | + This binding gives a representation of SPI controller in some Ambiq + Apollox Blue SOC (e.g. Apollo3 Blue) which uses BLEIF module for SPI + transceiver. + +compatible: "ambiq,spi-bleif" + +include: [spi-controller.yaml, pinctrl-device.yaml, ambiq-pwrcfg.yaml] + +properties: + reg: + required: true + + ambiq,pwrcfg: + required: true diff --git a/modules/hal_ambiq/Kconfig b/modules/hal_ambiq/Kconfig index b329d117c8979..10d3f785ce647 100644 --- a/modules/hal_ambiq/Kconfig +++ b/modules/hal_ambiq/Kconfig @@ -50,4 +50,9 @@ config AMBIQ_HAL_USE_HWINFO help Use the HWINFO driver from Ambiq HAL +config AMBIQ_HAL_USE_BLEIF + bool + help + Use the BLEIF driver from Ambiq HAL + endif # AMBIQ_HAL diff --git a/west.yml b/west.yml index f49dd745e7a1f..a89b3c29c826d 100644 --- a/west.yml +++ b/west.yml @@ -142,7 +142,7 @@ manifest: groups: - hal - name: hal_ambiq - revision: 94dd874cd726ba8185a301e78337c5c39685123f + revision: fcbbd99e20db1432196f4aec92678bd1f5b19c96 path: modules/hal/ambiq groups: - hal From 9684b957bcb90b8de834d93891e1fd07735d6512 Mon Sep 17 00:00:00 2001 From: Aaron Ye Date: Thu, 16 May 2024 16:28:08 +0800 Subject: [PATCH 1103/2849] boards: arm: apollo3p_evb: create BLEIF instance This commits add the BLEIF instance which is compatible with "ambiq,spi-bleif" on Ambiq apollo3p_evb and apollo3_evb. Also creates the default pinctrl for the defined instance. Signed-off-by: Aaron Ye --- boards/ambiq/apollo3_evb/apollo3_evb-pinctrl.dtsi | 11 +++++++++++ boards/ambiq/apollo3_evb/apollo3_evb.dts | 6 ++++++ boards/ambiq/apollo3p_evb/apollo3p_evb-pinctrl.dtsi | 11 +++++++++++ boards/ambiq/apollo3p_evb/apollo3p_evb.dts | 6 ++++++ dts/arm/ambiq/ambiq_apollo3_blue.dtsi | 10 ++++++++++ dts/arm/ambiq/ambiq_apollo3p_blue.dtsi | 10 ++++++++++ 6 files changed, 54 insertions(+) diff --git a/boards/ambiq/apollo3_evb/apollo3_evb-pinctrl.dtsi b/boards/ambiq/apollo3_evb/apollo3_evb-pinctrl.dtsi index cfba01ba4dea6..25fda178797bf 100644 --- a/boards/ambiq/apollo3_evb/apollo3_evb-pinctrl.dtsi +++ b/boards/ambiq/apollo3_evb/apollo3_evb-pinctrl.dtsi @@ -148,4 +148,15 @@ ambiq,iom-num = <6>; }; }; + + bleif_default: bleif_default{ + group1 { + pinmux = , + , + , + , + , + ; + }; + }; }; diff --git a/boards/ambiq/apollo3_evb/apollo3_evb.dts b/boards/ambiq/apollo3_evb/apollo3_evb.dts index c6a0f70f90741..c7856793e6795 100644 --- a/boards/ambiq/apollo3_evb/apollo3_evb.dts +++ b/boards/ambiq/apollo3_evb/apollo3_evb.dts @@ -84,6 +84,12 @@ }; }; +&bleif { + pinctrl-0 = <&bleif_default>; + pinctrl-names = "default"; + status = "okay"; +}; + &uart0 { current-speed = <115200>; pinctrl-0 = <&uart0_default>; diff --git a/boards/ambiq/apollo3p_evb/apollo3p_evb-pinctrl.dtsi b/boards/ambiq/apollo3p_evb/apollo3p_evb-pinctrl.dtsi index 5619b134ee9ea..2f0b4acd54240 100644 --- a/boards/ambiq/apollo3p_evb/apollo3p_evb-pinctrl.dtsi +++ b/boards/ambiq/apollo3p_evb/apollo3p_evb-pinctrl.dtsi @@ -193,4 +193,15 @@ ambiq,iom-num = <2>; }; }; + + bleif_default: bleif_default{ + group1 { + pinmux = , + , + , + , + , + ; + }; + }; }; diff --git a/boards/ambiq/apollo3p_evb/apollo3p_evb.dts b/boards/ambiq/apollo3p_evb/apollo3p_evb.dts index 902a909cc9f2c..bce6963242f75 100644 --- a/boards/ambiq/apollo3p_evb/apollo3p_evb.dts +++ b/boards/ambiq/apollo3p_evb/apollo3p_evb.dts @@ -84,6 +84,12 @@ }; }; +&bleif { + pinctrl-0 = <&bleif_default>; + pinctrl-names = "default"; + status = "okay"; +}; + &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 5935352068da8..3fb242aae5b9e 100644 --- a/dts/arm/ambiq/ambiq_apollo3_blue.dtsi +++ b/dts/arm/ambiq/ambiq_apollo3_blue.dtsi @@ -224,6 +224,16 @@ ambiq,pwrcfg = <&pwrcfg 0x8 0x800>; }; + bleif: bleif@5000c000 { + compatible = "ambiq,spi-bleif"; + reg = <0x5000c000 0x414>; + interrupts = <12 1>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + ambiq,pwrcfg = <&pwrcfg 0x8 0x8000>; + }; + pinctrl: pin-controller@40010000 { compatible = "ambiq,apollo3-pinctrl"; reg = <0x40010000 0x800>; diff --git a/dts/arm/ambiq/ambiq_apollo3p_blue.dtsi b/dts/arm/ambiq/ambiq_apollo3p_blue.dtsi index d4063fb98cf85..426bd4c01cfd0 100644 --- a/dts/arm/ambiq/ambiq_apollo3p_blue.dtsi +++ b/dts/arm/ambiq/ambiq_apollo3p_blue.dtsi @@ -244,6 +244,16 @@ ambiq,pwrcfg = <&pwrcfg 0x8 0x2000>; }; + bleif: bleif@5000c000 { + compatible = "ambiq,spi-bleif"; + reg = <0x5000c000 0x414>; + interrupts = <12 1>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + ambiq,pwrcfg = <&pwrcfg 0x8 0x8000>; + }; + pinctrl: pin-controller@40010000 { compatible = "ambiq,apollo3-pinctrl"; reg = <0x40010000 0x800>; From af54a388273468d5077685cb23109a18bef37b50 Mon Sep 17 00:00:00 2001 From: Aaron Ye Date: Thu, 16 May 2024 16:28:09 +0800 Subject: [PATCH 1104/2849] drivers: bluetooth: hci: add Ambiq Apollo3 Blue SOC support This commit add the SPI-based HCI support for the Ambiq Apollo3 Blue SOC (e.g. Apollo3 Blue Plus, Apollo3 Blue) support. Also correct the dependency of necessary peripheral. Signed-off-by: Aaron Ye --- drivers/bluetooth/hci/Kconfig | 4 +- drivers/bluetooth/hci/apollox_blue.c | 80 +++++++++++++++++++++++++--- drivers/bluetooth/hci/apollox_blue.h | 6 +++ drivers/bluetooth/hci/hci_ambiq.c | 1 + 4 files changed, 82 insertions(+), 9 deletions(-) diff --git a/drivers/bluetooth/hci/Kconfig b/drivers/bluetooth/hci/Kconfig index 7a2f79fd85a86..a6e53508bc44f 100644 --- a/drivers/bluetooth/hci/Kconfig +++ b/drivers/bluetooth/hci/Kconfig @@ -130,8 +130,8 @@ config BT_NO_DRIVER config BT_AMBIQ_HCI bool "AMBIQ BT HCI driver" select SPI - select GPIO - select CLOCK_CONTROL + select GPIO if SOC_SERIES_APOLLO4X + select CLOCK_CONTROL if SOC_SERIES_APOLLO4X select BT_HCI_SETUP help Supports Ambiq Bluetooth SoC using SPI as the communication protocol. diff --git a/drivers/bluetooth/hci/apollox_blue.c b/drivers/bluetooth/hci/apollox_blue.c index eff8d8fbd8125..a25af495bf6e1 100644 --- a/drivers/bluetooth/hci/apollox_blue.c +++ b/drivers/bluetooth/hci/apollox_blue.c @@ -25,8 +25,13 @@ LOG_MODULE_REGISTER(bt_apollox_driver); #include #include +#include #include "apollox_blue.h" +#if (CONFIG_SOC_SERIES_APOLLO4X) #include "am_devices_cooper.h" +#elif (CONFIG_SOC_SERIES_APOLLO3X) +#include "am_apollo3_bt_support.h" +#endif /* CONFIG_SOC_SERIES_APOLLO4X */ #define HCI_SPI_NODE DT_COMPAT_GET_ANY_STATUS_OKAY(ambiq_bt_hci_spi) #define SPI_DEV_NODE DT_BUS(HCI_SPI_NODE) @@ -44,6 +49,7 @@ LOG_MODULE_REGISTER(bt_apollox_driver); #define SPI_MAX_RX_MSG_LEN 258 +#if (CONFIG_SOC_SERIES_APOLLO4X) static const struct gpio_dt_spec irq_gpio = GPIO_DT_SPEC_GET(HCI_SPI_NODE, irq_gpios); static const struct gpio_dt_spec rst_gpio = GPIO_DT_SPEC_GET(HCI_SPI_NODE, reset_gpios); static const struct gpio_dt_spec cs_gpio = GPIO_DT_SPEC_GET(SPI_DEV_NODE, cs_gpios); @@ -54,10 +60,19 @@ static struct gpio_callback clkreq_gpio_cb; static const struct device *clk32m_dev = DEVICE_DT_GET(CLK_32M_NODE); static const struct device *clk32k_dev = DEVICE_DT_GET(CLK_32K_NODE); +#endif /* CONFIG_SOC_SERIES_APOLLO4X */ extern void bt_packet_irq_isr(const struct device *unused1, struct gpio_callback *unused2, uint32_t unused3); +void bt_apollo_rcv_isr_preprocess(void) +{ +#if (CONFIG_SOC_SERIES_APOLLO3X) + am_apollo3_bt_isr_pre(); +#endif /* CONFIG_SOC_SERIES_APOLLO3X */ +} + +#if (CONFIG_SOC_SERIES_APOLLO4X) static bool irq_pin_state(void) { int pin_state; @@ -117,10 +132,13 @@ static void bt_apollo_controller_reset(void) /* Give the controller some time to boot */ k_sleep(K_MSEC(500)); } +#endif /* CONFIG_SOC_SERIES_APOLLO4X */ int bt_apollo_spi_send(uint8_t *data, uint16_t len, bt_spi_transceive_fun transceive) { - int ret; + int ret = -ENOTSUP; + +#if (CONFIG_SOC_SERIES_APOLLO4X) uint8_t command[1] = {SPI_WRITE}; uint8_t response[2] = {0, 0}; uint16_t fail_count = 0; @@ -139,18 +157,24 @@ int bt_apollo_spi_send(uint8_t *data, uint16_t len, bt_spi_transceive_fun transc break; } } while (fail_count++ < SPI_WRITE_TIMEOUT); +#elif (CONFIG_SOC_SERIES_APOLLO3X) + ret = transceive(data, len, NULL, 0); + if ((ret) && (ret != AM_HAL_BLE_STATUS_SPI_NOT_READY)) { + LOG_ERR("SPI write error %d", ret); + } +#endif /* CONFIG_SOC_SERIES_APOLLO4X */ return ret; } int bt_apollo_spi_rcv(uint8_t *data, uint16_t *len, bt_spi_transceive_fun transceive) { - int ret; - uint8_t command[1] = {SPI_READ}; + int ret = -ENOTSUP; uint8_t response[2] = {0, 0}; uint16_t read_size = 0; do { +#if (CONFIG_SOC_SERIES_APOLLO4X) /* Skip if the IRQ pin is not in high state */ if (!irq_pin_state()) { ret = -1; @@ -158,10 +182,26 @@ int bt_apollo_spi_rcv(uint8_t *data, uint16_t *len, bt_spi_transceive_fun transc } /* Check the available packet bytes */ + uint8_t command[1] = {SPI_READ}; ret = transceive(command, 1, response, 2); if (ret) { break; } +#elif (CONFIG_SOC_SERIES_APOLLO3X) + /* Skip if the IRQ bit is not set */ + if (!BLEIFn(0)->BSTATUS_b.BLEIRQ) { + ret = -1; + break; + } + + /* Check the available packet bytes */ + ret = transceive(NULL, 0, response, 2); + if (ret) { + break; + } +#else + break; +#endif /* CONFIG_SOC_SERIES_APOLLO4X */ /* Check if the read size is acceptable */ read_size = (uint16_t)(response[0] | response[1] << 8); @@ -186,6 +226,7 @@ int bt_apollo_spi_rcv(uint8_t *data, uint16_t *len, bt_spi_transceive_fun transc bool bt_apollo_vnd_rcv_ongoing(uint8_t *data, uint16_t len) { +#if (CONFIG_SOC_SERIES_APOLLO4X) /* The vendor specific handshake command/response is incompatible with * standard Bluetooth HCI format, need to handle the received packets * specifically. @@ -196,14 +237,18 @@ bool bt_apollo_vnd_rcv_ongoing(uint8_t *data, uint16_t len) } else { return false; } +#else + return false; +#endif /* CONFIG_SOC_SERIES_APOLLO4X */ } int bt_hci_transport_setup(const struct device *dev) { ARG_UNUSED(dev); - int ret; + int ret = 0; +#if (CONFIG_SOC_SERIES_APOLLO4X) /* Configure the XO32MHz and XO32kHz clocks.*/ clock_control_configure(clk32k_dev, NULL, NULL); clock_control_configure(clk32m_dev, NULL, NULL); @@ -256,13 +301,18 @@ int bt_hci_transport_setup(const struct device *dev) /* Configure the interrupt edge for IRQ pin */ gpio_pin_interrupt_configure_dt(&irq_gpio, GPIO_INT_EDGE_RISING); +#elif (CONFIG_SOC_SERIES_APOLLO3X) + IRQ_CONNECT(DT_IRQN(SPI_DEV_NODE), DT_IRQ(SPI_DEV_NODE, priority), bt_packet_irq_isr, 0, 0); +#endif /* CONFIG_SOC_SERIES_APOLLO4X */ - return 0; + return ret; } int bt_apollo_controller_init(spi_transmit_fun transmit) { - int ret; + int ret = 0; + +#if (CONFIG_SOC_SERIES_APOLLO4X) am_devices_cooper_callback_t cb = { .write = transmit, .reset = bt_apollo_controller_reset, @@ -277,10 +327,21 @@ int bt_apollo_controller_init(spi_transmit_fun transmit) am_devices_cooper_set_initialize_state(AM_DEVICES_COOPER_STATE_INITIALIZE_FAIL); LOG_ERR("BT controller initialization fail"); } +#elif (CONFIG_SOC_SERIES_APOLLO3X) + ret = am_apollo3_bt_controller_init(); + if (ret == AM_HAL_STATUS_SUCCESS) { + LOG_INF("BT controller initialized"); + } else { + LOG_ERR("BT controller initialization fail"); + } + + irq_enable(DT_IRQN(SPI_DEV_NODE)); +#endif /* CONFIG_SOC_SERIES_APOLLO4X */ return ret; } +#if (CONFIG_SOC_SERIES_APOLLO4X) static int bt_apollo_set_nvds(void) { int ret; @@ -334,19 +395,23 @@ static int bt_apollo_set_nvds(void) return ret; } +#endif /* CONFIG_SOC_SERIES_APOLLO4X */ int bt_apollo_vnd_setup(void) { - int ret; + int ret = 0; +#if (CONFIG_SOC_SERIES_APOLLO4X) /* Set the NVDS parameters to BLE controller */ ret = bt_apollo_set_nvds(); +#endif /* CONFIG_SOC_SERIES_APOLLO4X */ return ret; } int bt_apollo_dev_init(void) { +#if (CONFIG_SOC_SERIES_APOLLO4X) if (!gpio_is_ready_dt(&irq_gpio)) { LOG_ERR("IRQ GPIO device not ready"); return -ENODEV; @@ -361,6 +426,7 @@ int bt_apollo_dev_init(void) LOG_ERR("CLKREQ GPIO device not ready"); return -ENODEV; } +#endif /* CONFIG_SOC_SERIES_APOLLO4X */ return 0; } diff --git a/drivers/bluetooth/hci/apollox_blue.h b/drivers/bluetooth/hci/apollox_blue.h index a05238657e5a5..85e586d790856 100644 --- a/drivers/bluetooth/hci/apollox_blue.h +++ b/drivers/bluetooth/hci/apollox_blue.h @@ -98,6 +98,12 @@ int bt_apollo_vnd_setup(void); */ bool bt_apollo_vnd_rcv_ongoing(uint8_t *data, uint16_t len); +/** + * @brief Do the specific preprocessing in HCI packet receiving ISR if needed, + * for example, clear the interrupt status. + */ +void bt_apollo_rcv_isr_preprocess(void); + #ifdef __cplusplus } #endif diff --git a/drivers/bluetooth/hci/hci_ambiq.c b/drivers/bluetooth/hci/hci_ambiq.c index ec3a0b944fe46..48ea28235e24a 100644 --- a/drivers/bluetooth/hci/hci_ambiq.c +++ b/drivers/bluetooth/hci/hci_ambiq.c @@ -67,6 +67,7 @@ static K_SEM_DEFINE(sem_spi_available, 1, 1); void bt_packet_irq_isr(const struct device *unused1, struct gpio_callback *unused2, uint32_t unused3) { + bt_apollo_rcv_isr_preprocess(); k_sem_give(&sem_irq); } From 47ce99f7b02ea5e695f91466e32d12c908e7c271 Mon Sep 17 00:00:00 2001 From: Aaron Ye Date: Thu, 16 May 2024 16:28:09 +0800 Subject: [PATCH 1105/2849] drivers: bluetooth: hci: correct the Ambiq Apollox support BT feature The BLE controller of some Ambiq Apollox Blue SOC may have issue to report the expected supported features bitmask successfully, thought the features are actually supportive. Need to correct them before going to the host stack. Signed-off-by: Aaron Ye --- drivers/bluetooth/hci/hci_ambiq.c | 32 +++++++++++++++++++++++-------- 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/drivers/bluetooth/hci/hci_ambiq.c b/drivers/bluetooth/hci/hci_ambiq.c index 48ea28235e24a..6af3d13e2c0da 100644 --- a/drivers/bluetooth/hci/hci_ambiq.c +++ b/drivers/bluetooth/hci/hci_ambiq.c @@ -29,17 +29,18 @@ LOG_MODULE_REGISTER(bt_hci_driver); #define PACKET_TYPE 0 #define PACKET_TYPE_SIZE 1 #define EVT_HEADER_TYPE 0 -#define EVT_HEADER_EVENT 1 -#define EVT_HEADER_SIZE 2 -#define EVT_VENDOR_CODE_LSB 3 -#define EVT_VENDOR_CODE_MSB 4 -#define CMD_OGF 1 -#define CMD_OCF 2 +#define EVT_CMD_COMP_OP_LSB 3 +#define EVT_CMD_COMP_OP_MSB 4 +#define EVT_CMD_COMP_DATA 5 #define EVT_OK 0 #define EVT_DISCARD 1 #define EVT_NOP 2 +#define BT_FEAT_SET_BIT(feat, octet, bit) (feat[octet] |= BIT(bit)) +#define BT_FEAT_SET_NO_BREDR(feat) BT_FEAT_SET_BIT(feat, 4, 5) +#define BT_FEAT_SET_LE(feat) BT_FEAT_SET_BIT(feat, 4, 6) + /* Max SPI buffer length for transceive operations. * The maximum TX packet number is 512 bytes data + 12 bytes header. * The maximum RX packet number is 255 bytes data + 3 header. @@ -114,7 +115,7 @@ static int spi_receive_packet(uint8_t *data, uint16_t *len) static int hci_event_filter(const uint8_t *evt_data) { - uint8_t evt_type = evt_data[0]; + uint8_t evt_type = evt_data[EVT_HEADER_TYPE]; switch (evt_type) { case BT_HCI_EVT_LE_META_EVENT: { @@ -128,11 +129,26 @@ static int hci_event_filter(const uint8_t *evt_data) } } case BT_HCI_EVT_CMD_COMPLETE: { - uint16_t opcode = (uint16_t)(evt_data[3] + (evt_data[4] << 8)); + uint16_t opcode = (uint16_t)(evt_data[EVT_CMD_COMP_OP_LSB] + + (evt_data[EVT_CMD_COMP_OP_MSB] << 8)); switch (opcode) { case BT_OP_NOP: return EVT_NOP; + case BT_HCI_OP_READ_LOCAL_FEATURES: { + /* The BLE controller of some Ambiq Apollox Blue SOC may have issue to + * report the expected supported features bitmask successfully, thought the + * features are actually supportive. Need to correct them before going to + * the host stack. + */ + struct bt_hci_rp_read_local_features *rp = + (void *)&evt_data[EVT_CMD_COMP_DATA]; + if (rp->status == 0) { + BT_FEAT_SET_NO_BREDR(rp->features); + BT_FEAT_SET_LE(rp->features); + } + return EVT_OK; + } default: return EVT_OK; } From 3f56baa2955c9d9e0dc5cbfd573d4b0bc829b460 Mon Sep 17 00:00:00 2001 From: Aaron Ye Date: Thu, 16 May 2024 16:28:10 +0800 Subject: [PATCH 1106/2849] drivers: bluetooth: hci: add retry mechanism for Apollo SPI busy scenario The controller may be unavailable to receive packets because it is busy on processing something or have packets to send to host. Need to free the SPI bus and wait some moment to try again. Signed-off-by: Aaron Ye --- drivers/bluetooth/hci/hci_ambiq.c | 31 +++++++++++++++++++++++++------ 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/drivers/bluetooth/hci/hci_ambiq.c b/drivers/bluetooth/hci/hci_ambiq.c index 6af3d13e2c0da..9428594980d66 100644 --- a/drivers/bluetooth/hci/hci_ambiq.c +++ b/drivers/bluetooth/hci/hci_ambiq.c @@ -48,6 +48,13 @@ LOG_MODULE_REGISTER(bt_hci_driver); #define SPI_MAX_TX_MSG_LEN 524 #define SPI_MAX_RX_MSG_LEN 258 +/* The controller may be unavailable to receive packets because it is busy + * on processing something or have packets to send to host. Need to free the + * SPI bus and wait some moment to try again. + */ +#define SPI_BUSY_WAIT_INTERVAL_MS 25 +#define SPI_BUSY_TX_ATTEMPTS 200 + static uint8_t __noinit rxmsg[SPI_MAX_RX_MSG_LEN]; static const struct device *spi_dev = DEVICE_DT_GET(SPI_DEV_NODE); static struct spi_config spi_cfg = { @@ -84,15 +91,27 @@ static inline int bt_spi_transceive(void *tx, uint32_t tx_len, void *rx, uint32_ static int spi_send_packet(uint8_t *data, uint16_t len) { int ret; + uint16_t fail_count = 0; - /* Wait for SPI bus to be available */ - k_sem_take(&sem_spi_available, K_FOREVER); + do { + /* Wait for SPI bus to be available */ + k_sem_take(&sem_spi_available, K_FOREVER); - /* Send the SPI packet to controller */ - ret = bt_apollo_spi_send(data, len, bt_spi_transceive); + /* Send the SPI packet to controller */ + ret = bt_apollo_spi_send(data, len, bt_spi_transceive); - /* Free the SPI bus */ - k_sem_give(&sem_spi_available); + /* Free the SPI bus */ + k_sem_give(&sem_spi_available); + + if (ret) { + /* Give some chance to controller to complete the processing or + * packets sending. + */ + k_sleep(K_MSEC(SPI_BUSY_WAIT_INTERVAL_MS)); + } else { + break; + } + } while (fail_count++ < SPI_BUSY_TX_ATTEMPTS); return ret; } From 69d790b293316ae3651f244f2452705ee65c1f4b Mon Sep 17 00:00:00 2001 From: Aaron Ye Date: Thu, 16 May 2024 16:31:57 +0800 Subject: [PATCH 1107/2849] dts: arm: ambiq: add bt-hci subnode for Apollo3 Blue SOC This commit defines the bt-hci subnode under the bleif node on Ambiq Apollo3 Blue and Apollo3 Blue Plus SOC. Also add the default configurations for Bluetooth feature on Ambiq apollo3_evb and apollo3p_evb. Signed-off-by: Aaron Ye --- dts/arm/ambiq/ambiq_apollo3_blue.dtsi | 5 +++ dts/arm/ambiq/ambiq_apollo3p_blue.dtsi | 5 +++ .../apollo3x/Kconfig.defconfig.apollo3_blue | 34 +++++++++++++++++++ .../apollo3x/Kconfig.defconfig.apollo3p_blue | 34 +++++++++++++++++++ 4 files changed, 78 insertions(+) diff --git a/dts/arm/ambiq/ambiq_apollo3_blue.dtsi b/dts/arm/ambiq/ambiq_apollo3_blue.dtsi index 3fb242aae5b9e..07aa609e9423d 100644 --- a/dts/arm/ambiq/ambiq_apollo3_blue.dtsi +++ b/dts/arm/ambiq/ambiq_apollo3_blue.dtsi @@ -232,6 +232,11 @@ #size-cells = <0>; status = "disabled"; ambiq,pwrcfg = <&pwrcfg 0x8 0x8000>; + + bt-hci@0 { + compatible = "ambiq,bt-hci-spi"; + reg = <0>; + }; }; pinctrl: pin-controller@40010000 { diff --git a/dts/arm/ambiq/ambiq_apollo3p_blue.dtsi b/dts/arm/ambiq/ambiq_apollo3p_blue.dtsi index 426bd4c01cfd0..9fcfbd2b5e018 100644 --- a/dts/arm/ambiq/ambiq_apollo3p_blue.dtsi +++ b/dts/arm/ambiq/ambiq_apollo3p_blue.dtsi @@ -252,6 +252,11 @@ #size-cells = <0>; status = "disabled"; ambiq,pwrcfg = <&pwrcfg 0x8 0x8000>; + + bt-hci@0 { + compatible = "ambiq,bt-hci-spi"; + reg = <0>; + }; }; pinctrl: pin-controller@40010000 { diff --git a/soc/ambiq/apollo3x/Kconfig.defconfig.apollo3_blue b/soc/ambiq/apollo3x/Kconfig.defconfig.apollo3_blue index c6c07932856c4..370ec60873453 100644 --- a/soc/ambiq/apollo3x/Kconfig.defconfig.apollo3_blue +++ b/soc/ambiq/apollo3x/Kconfig.defconfig.apollo3_blue @@ -7,4 +7,38 @@ if SOC_APOLLO3_BLUE config NUM_IRQS default 31 +config MAIN_STACK_SIZE + default 2048 if BT + +if BT + +choice BT_HCI_BUS_TYPE + default BT_AMBIQ_HCI +endchoice + +config BT_BUF_ACL_TX_COUNT + default 4 + +config BT_BUF_CMD_TX_SIZE + default 255 + +config BT_BUF_EVT_RX_SIZE + default 255 + +config BT_BUF_ACL_TX_SIZE + default 251 + +config BT_BUF_ACL_RX_SIZE + default 251 + +# L2CAP SDU/PDU TX MTU +# BT_L2CAP_RX_MTU = CONFIG_BT_BUF_ACL_RX_SIZE - BT_L2CAP_HDR_SIZE +config BT_L2CAP_TX_MTU + default 247 + +config BT_HCI_ACL_FLOW_CONTROL + default n + +endif # BT + endif # SOC_APOLLO3_BLUE diff --git a/soc/ambiq/apollo3x/Kconfig.defconfig.apollo3p_blue b/soc/ambiq/apollo3x/Kconfig.defconfig.apollo3p_blue index 8484dfad34752..930c8bc15f5da 100644 --- a/soc/ambiq/apollo3x/Kconfig.defconfig.apollo3p_blue +++ b/soc/ambiq/apollo3x/Kconfig.defconfig.apollo3p_blue @@ -7,4 +7,38 @@ if SOC_APOLLO3P_BLUE config NUM_IRQS default 33 +config MAIN_STACK_SIZE + default 2048 if BT + +if BT + +choice BT_HCI_BUS_TYPE + default BT_AMBIQ_HCI +endchoice + +config BT_BUF_ACL_TX_COUNT + default 4 + +config BT_BUF_CMD_TX_SIZE + default 255 + +config BT_BUF_EVT_RX_SIZE + default 255 + +config BT_BUF_ACL_TX_SIZE + default 251 + +config BT_BUF_ACL_RX_SIZE + default 251 + +# L2CAP SDU/PDU TX MTU +# BT_L2CAP_RX_MTU = CONFIG_BT_BUF_ACL_RX_SIZE - BT_L2CAP_HDR_SIZE +config BT_L2CAP_TX_MTU + default 247 + +config BT_HCI_ACL_FLOW_CONTROL + default n + +endif # BT + endif # SOC_APOLLO3P_BLUE From 1b4844aad0e0e49422b7f0a0ce92001113431319 Mon Sep 17 00:00:00 2001 From: Jonathan Rico Date: Fri, 24 May 2024 08:16:47 +0200 Subject: [PATCH 1108/2849] tests: bsim: Enable asserts by default Asserts should always be enabled in test builds. Signed-off-by: Jonathan Rico --- tests/bsim/compile.source | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/bsim/compile.source b/tests/bsim/compile.source index 784c8dc06e156..71aa19ff97cf6 100644 --- a/tests/bsim/compile.source +++ b/tests/bsim/compile.source @@ -23,7 +23,7 @@ function _compile(){ local conf_overlay="${conf_overlay:-""}" default_cmake_args=(-DCONFIG_COVERAGE=y -DCMAKE_EXPORT_COMPILE_COMMANDS=ON \ - -DCONFIG_COMPILER_WARNINGS_AS_ERRORS=y) + -DCONFIG_COMPILER_WARNINGS_AS_ERRORS=y -DCONFIG_ASSERT=y) local cmake_args=(${cmake_args:-"${default_cmake_args[@]}"}) local cmake_extra_args="${cmake_extra_args:-""}" local ninja_args="${ninja_args:-""}" From ea41a24d3adaeeeffe9dac4413e937da611f02c1 Mon Sep 17 00:00:00 2001 From: Jonathan Rico Date: Sat, 25 May 2024 22:31:00 +0200 Subject: [PATCH 1109/2849] Bluetooth: tests: fix double-registering of callbacks This was the source of assert failures. If only they were enabled in the first place... The issue is that in order to save on build time, these two tests build only one image, from which two devices are instantiated (`gatt_client_test.c` and `gatt_server_test.c`). The double-registration happens as `BT_CONN_CB_DEFINE()` is build-time, and is included in two files of the same image. Then _both_ images will end up with both `connected()` `disconnected()` etc callbacks, which have logic specific to their respective images/devices. The patch uses runtime registration instead so each device only ever registers its own callbacks and not the other device's too. Signed-off-by: Jonathan Rico --- .../bluetooth/host/gatt/authorization/src/gatt_client_test.c | 4 +++- .../bluetooth/host/gatt/authorization/src/gatt_server_test.c | 4 +++- tests/bsim/bluetooth/host/gatt/general/src/gatt_client_test.c | 4 +++- tests/bsim/bluetooth/host/gatt/general/src/gatt_server_test.c | 4 +++- 4 files changed, 12 insertions(+), 4 deletions(-) diff --git a/tests/bsim/bluetooth/host/gatt/authorization/src/gatt_client_test.c b/tests/bsim/bluetooth/host/gatt/authorization/src/gatt_client_test.c index 9c60c5b57b2d4..d276bfcedc3b9 100644 --- a/tests/bsim/bluetooth/host/gatt/authorization/src/gatt_client_test.c +++ b/tests/bsim/bluetooth/host/gatt/authorization/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, }; @@ -297,6 +297,8 @@ static void test_main(void) { int err; + bt_conn_cb_register(&conn_callbacks); + err = bt_enable(NULL); if (err != 0) { FAIL("Bluetooth discover failed (err %d)\n", err); 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 0394282164070..a09b94367fb8d 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 @@ -45,7 +45,7 @@ static void disconnected(struct bt_conn *conn, uint8_t reason) g_conn = NULL; } -BT_CONN_CB_DEFINE(conn_callbacks) = { +static struct bt_conn_cb conn_callbacks = { .connected = connected, .disconnected = disconnected, }; @@ -331,6 +331,8 @@ static void test_main(void) return; } + bt_conn_cb_register(&conn_callbacks); + err = bt_enable(NULL); if (err != 0) { FAIL("Bluetooth init failed (err %d)\n", err); diff --git a/tests/bsim/bluetooth/host/gatt/general/src/gatt_client_test.c b/tests/bsim/bluetooth/host/gatt/general/src/gatt_client_test.c index 0ae87791f817f..cc233510b0ba2 100644 --- a/tests/bsim/bluetooth/host/gatt/general/src/gatt_client_test.c +++ b/tests/bsim/bluetooth/host/gatt/general/src/gatt_client_test.c @@ -74,7 +74,7 @@ static void security_changed(struct bt_conn *conn, bt_security_t level, enum bt_ } } -BT_CONN_CB_DEFINE(conn_callbacks) = { +static struct bt_conn_cb conn_callbacks = { .connected = connected, .disconnected = disconnected, .security_changed = security_changed, @@ -351,6 +351,8 @@ static void test_main(void) { int err; + bt_conn_cb_register(&conn_callbacks); + err = bt_enable(NULL); if (err != 0) { FAIL("Bluetooth discover failed (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 e41d568dff818..c77fe39c000f0 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 @@ -47,7 +47,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, }; @@ -151,6 +151,8 @@ static void test_main(void) BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)) }; + bt_conn_cb_register(&conn_callbacks); + err = bt_enable(NULL); if (err != 0) { FAIL("Bluetooth init failed (err %d)\n", err); From 8d446d345ba78cad03ccb4a04d41a72883b16b90 Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Wed, 8 Mar 2023 21:43:44 -0800 Subject: [PATCH 1110/2849] doc: security: Add ETSI 303 645 standard Add a new section for standards with ETSI 303-645 in the security related documentation. Signed-off-by: Flavio Ceolin --- doc/security/index.rst | 1 + doc/security/standards/etsi-303645.rst | 731 +++++++++++++++++++++++++ doc/security/standards/index.rst | 22 + 3 files changed, 754 insertions(+) create mode 100644 doc/security/standards/etsi-303645.rst create mode 100644 doc/security/standards/index.rst diff --git a/doc/security/index.rst b/doc/security/index.rst index 2ae92f7f57224..f05691c014e7e 100644 --- a/doc/security/index.rst +++ b/doc/security/index.rst @@ -16,3 +16,4 @@ for ensuring security is addressed within the Zephyr project. sensor-threat.rst hardening-tool.rst vulnerabilities.rst + standards/index.rst diff --git a/doc/security/standards/etsi-303645.rst b/doc/security/standards/etsi-303645.rst new file mode 100644 index 0000000000000..903998d86ede9 --- /dev/null +++ b/doc/security/standards/etsi-303645.rst @@ -0,0 +1,731 @@ +.. _etsi_303645: + +ETSI 303-645 +############ + + +`ETSI EN 303 645`, also known as "Cyber Security for Consumer Internet +of Things: Baseline Requirements," is a standard developed by the +European Telecommunications Standards Institute (ETSI). + +The standard includes provisions for secure software updates, data +protection, secure communication, and the minimization of exposed +attack surfaces, among other things. It is part of a broader effort to +address the challenges and risks associated with IoT devices. + +Full version of the standard can be found `here `_. + + +Terminology +*********** + +.. list-table:: ETSI 303645 terminology + :widths: 17 43 + + * - administrator + - user who has the highest-privilege level possible for a user of the device, + which can mean they are able to change any configuration related to the intended + functionality. + + * - associated services + - digital services that, together with the device, are part of the overall consumer + IoT product and that are typically required to provide the product's intended + functionality. + + * - authentication mechanism + - method used to prove the authenticity of an entity. + + * - authentication value + - individual value of an attribute used by an authentication mechanism. + + * - best practice cryptography + - cryptography that is suitable for the corresponding use case and has no + indications of a feasible attack with current readily available techniques. + + * - constrained device + - device which has physical limitations in either the ability to process data, the + ability to communicate data, the ability to store data or the ability to interact + with the user, due to restrictions that arise from its intended use. + + * - consumer + - natural person who is acting for purposes that are outside her/his trade, + business, craft or profession. + + * - consumer IoT device + - network-connected (and network-connectable) device that has relationships to + associated services and are used by the consumer typically in the home or as + electronic wearables. + + * - critical security parameter + - security-related secret information whose disclosure or modification can compromise + the security of a security module. + + * - debug interface + - physical interface used by the manufacturer to communicate with the device during + development or to perform triage of issues with the device and that is not used as part + of the consumer-facing functionality + + * - defined support period + - minimum length of time, expressed as a period or by an end-date, for which a + manufacturer will provide security updates. + + * - device manufacturer + - entity that creates an assembled final consumer IoT product, which is likely to contain + the products and components of many other suppliers. + + * - factory default + - state of the device after factory reset or after final production/assembly. + + * - initialization + - process that activates the network connectivity of the device for operation and + optionally sets authentication features for a user or for network access. + + * - initialized state + - state of the device after initialization. + + * - IoT product + - consumer IoT device and its associated services. + + * - isolable + - able to be removed from the network it is connected to, where any functionality loss + caused is related only to that connectivity and not to its main function; alternatively, + able to be placed in a self-contained environment with other devices if and only if the + integrity of devices within that environment can be ensured + + * - logical interface + - software implementation that utilizes a network interface to communicate over the network + via channels or ports. + + * - manufacturer + - relevant economic operator in the supply chain (including the device manufacturer). + + * - network interface + - physical interface that can be used to access the functionality of consumer IoT via a network. + + * - owner + - user who owns or who purchased the device. + + * - personal data + - Any information relating to an identified or identifiable natural person. + + * - physical interface + - physical port or air interface (such as radio, audio or optical) used to communicate with the + device at the physical layer. + + * - public security parameter + - security related public information whose modification can compromise the security of a + security module. + + * - remotely accessible + - intended to be accessible from outside the local network. + + * - security module + - set of hardware, software, and/or firmware that implements security functions. + + * - security update + - software update that addresses security vulnerabilities either discovered by or reported + to the manufacturer. + + * - sensitive security parameters + - critical security parameters and public security parameters. + + * - software service + - software component of a device that is used to support functionality. + + * - telemetry + - data from a device that can provide information to help the manufacturer identify issues + or information related to device usage. + + * - unique per device + - unique for each individual device of a given product class or type. + + * - user + - natural person or organization. + +Provisions Assessment +********************* + + The following table is a self-assessment using Table B.1 from ETSI EN + 303 645, specifically focusing on the Zephyr RTOS as a component + within IoT products. + + According with ETSI 303 645, table B.1 provides a mechanism to give information + about the implementation of the provisions presented in the standard. Zephyr has + adopted the following notations used in the standard: + +.. list-table:: ETSI 303645 Table B.1 notations + :widths: 17 43 + + * - M + - the provision is a mandatory requirement + + * - R + - the provision is a recommendation + + * - M C + - the provision is a mandatory requirement and conditional + + * - R C + - the provision is a recommendation and conditional + + * - Y + - The provision is supported by Zephyr + + * - N + - The provision is not supported by Zephyr + + * - N/A + - The provision is not applicable to Zephyr or it is product makers responsibility + +.. list-table:: ETSI 303645 provisions assessment using table B.1 + :header-rows: 1 + :widths: 17 63 17 63 63 + + * - Provision + - Description + - Status + - Support + - Detail + + .. _ETSI_Provision_5_1_1: + * - Provision 5.1-1 + - Where passwords are used and in any state other than the + factory default, all consumer IoT device passwords shall be + unique per device or defined by the user. + - M C + - + - + + .. _ETSI_Provision_5_1_2: + * - Provision 5.1-2 + - Where pre-installed unique per device passwords are used, + these shall be generated with a mechanism that reduces the + risk of automated attacks against a class or type of device. + - M C + - + - + + .. _ETSI_Provision_5_1_3: + * - Provision 5.1-3 + - Authentication mechanisms used to authenticate users against a + device shall use best practice cryptography, appropriate to + the properties of the technology, risk and usage. + - M + - + - + + .. _ETSI_Provision_5_1_4: + * - Provision 5.1-4 + - Where a user can authenticate against a device, the device + shall provide to the user or an administrator a simple + mechanism to change the authentication value used. + - M C + - + - + + .. _ETSI_Provision_5_1_5: + * - Provision 5.1-5 + - When the device is not a constrained device, it shall have a + mechanism available which makes brute-force attacks on + authentication mechanisms via network interfaces + impracticable. + - M C + - + - + + .. _ETSI_Provision_5_2_1: + * - Provision 5.2-1 + - The manufacture shall make a vulnerability disclosure policy publicly + available. + - M + - + - + + .. _ETSI_Provision_5_2_2: + * - Provision 5.2-2 + - Disclosed vulnerabilities should be acted on in a timely manner. + - R + - + - + + .. _ETSI_Provision_5_2_3: + * - Provision 5.2-3 + - Manufacturers should continually monitor for, identify and rectify security + vulnerabilities within products and services they sell, produce, have produced + and services they operate during the defined support period. + - R + - + - + + .. _ETSI_Provision_5_3_1: + * - Provision 5.3-1 + - All software components in consumer IoT devices should be securely updatable. + - R + - + - + + .. _ETSI_Provision_5_3_2: + * - Provision 5.3-2 + - When the device is not a constrained device, it shall have an update mechanism + for the secure installation of updates. + - M C + - + - + + .. _ETSI_Provision_5_3_3: + * - Provision 5.3-3 + - An update shall be simple for the user to apply. + - M C + - + - + + .. _ETSI_Provision_5_3_4: + * - Provision 5.3-4 + - Automatic mechanisms should be used for software updates. + - R C + - + - + + .. _ETSI_Provision_5_3_5: + * - Provision 5.3-5 + - The device should check after initialization, and then periodically, whether + security updates are available. + - R C + - + - + + .. _ETSI_Provision_5_3_6: + * - Provision 5.3-6 + - If the device supports automatic updates and/or update notifications, these + should be enabled in the initialized state and configurable so that the user + can enable, disable, or postpone installation of security updates and/or + update notifications. + - R C + - + - + + .. _ETSI_Provision_5_3_7: + * - Provision 5.3-7 + - The device shall use best practice cryptography to facilitate secure update mechanisms. + - M C + - + - + + .. _ETSI_Provision_5_3_8: + * - Provision 5.3-8 + - Security updates shall be timely. + - M C + - + - + + .. _ETSI_Provision_5_3_9: + * - Provision 5.3-9 + - The device should verify the authenticity and integrity of software updates. + - R C + - + - + + .. _ETSI_Provision_5_3_10: + * - Provision 5.3-10 + - Where updates are delivered over a network interface, the device shall verify + the authenticity and integrity of each update via a trust relationship. + - M + - + - + + .. _ETSI_Provision_5_3_11: + * - Provision 5.3-11 + - The manufacturer should inform the user in a recognizable and apparent manner + that a security update is required together with information on the risks + mitigated by that update. + - R C + - + - + + .. _ETSI_Provision_5_3_12: + * - Provision 5.3-12 + - The device should notify the user when the application of a software update + will disrupt the basic functioning of the device. + - R C + - + - + + .. _ETSI_Provision_5_3_13: + * - Provision 5.3-13 + - The manufacturer shall publish, in an accessible way that is clear and + transparent to the user, the defined support period. + - M + - + - + + .. _ETSI_Provision_5_3_14: + * - Provision 5.3-14 + - For constrained devices that cannot have their software updated, the rationale + for the absence of software updates, the period and method of hardware replacement + support and a defined support period should be published by the manufacturer in an + accessible way that is clear and transparent to the user. + - R C + - + - + + .. _ETSI_Provision_5_3_15: + * - Provision 5.3-15 + - For constrained devices that cannot have their software updated, the product + should be isolable and the hardware replaceable. + - R C + - + - + + .. _ETSI_Provision_5_3_16: + * - Provision 5.3-16 + - The model designation of the consumer IoT device shall be clearly recognizable, + either by labelling on the device or via a physical interface. + - M + - + - + + .. _ETSI_Provision_5_4_1: + * - Provision 5.4-1 + - Sensitive security parameters in persistent storage shall be stored securely by the device. + - M + - + - + + .. _ETSI_Provision_5_4_2: + * - Provision 5.4-2 + - Where a hard-coded unique per device identity is used in a device for security purposes, + it shall be implemented in such a way that it resists tampering by means such as physical, + electrical or software. + - M C + - + - + + .. _ETSI_Provision_5_4_3: + * - Provision 5.4-3 + - Hard-coded critical security parameters in device software source code shall not be used. + - M + - + - + + .. _ETSI_Provision_5_4_4: + * - Provision 5.4-4 + - Any critical security parameters used for integrity and authenticity checks of software + updates and for protection of communication with associated services in device software + shall be unique per device and shall be produced with a mechanism that reduces the risk + of automated attacks against classes of devices. + - M + - + - + + .. _ETSI_Provision_5_5_1: + * - Provision 5.5-1 + - The consumer IoT device shall use best practice cryptography to communicate securely. + - M + - + - + + .. _ETSI_Provision_5_5_2: + * - Provision 5.5-2 + - The consumer IoT device should use reviewed or evaluated implementations to deliver + network and security functionalities, particularly in the field of cryptography. + - R + - + - + + .. _ETSI_Provision_5_5_3: + * - Provision 5.5-3 + - Cryptographic algorithms and primitives should be updatable. + - R + - + - + + .. _ETSI_Provision_5_5_4: + * - Provision 5.5-4 + - Access to device functionality via a network interface in the initialized state should + only be possible after authentication on that interface. + - R + - + - + + .. _ETSI_Provision_5_5_5: + * - Provision 5.5-5 + - Device functionality that allows security-relevant changes in configuration via a + network interface shall only be accessible after authentication. The exception is for + network service protocols that are relied upon by the device and where the manufacturer + cannot guarantee what configuration will be required for the device to operate. + - M + - + - + + .. _ETSI_Provision_5_5_6: + * - Provision 5.5-6 + - Critical security parameters should be encrypted in transit, with such encryption + appropriate to the properties of the technology, risk and usage. + - R + - + - + + .. _ETSI_Provision_5_5_7: + * - Provision 5.5-7 + - The consumer IoT device shall protect the confidentiality of critical security + parameters that are communicated via remotely accessible network interfaces. + - M + - + - + + .. _ETSI_Provision_5_5_8: + * - Provision 5.5-8 + - The manufacturer shall follow secure management processes for critical security + parameters that relate to the device. + - M + - + - + + .. _ETSI_Provision_5_6_1: + * - Provision 5.6-1 + - All unused network and logical interfaces shall be disabled. + - M + - + - + + .. _ETSI_Provision_5_6_2: + * - Provision 5.6-2 + - In the initialized state, the network interfaces of the device shall minimize the + unauthenticated disclosure of security-relevant information. + - M + - + - + + .. _ETSI_Provision_5_6_3: + * - Provision 5.6-3 + - Device hardware should not unnecessarily expose physical interfaces to attack. + - R + - + - + + .. _ETSI_Provision_5_6_4: + * - Provision 5.6-4 + - Where a debug interface is physically accessible, it shall be disabled in software. + - M C + - + - + + .. _ETSI_Provision_5_6_5: + * - Provision 5.6-5 + - The manufacturer should only enable software services that are used or required for + the intended use or operation of the device. + - R + - + - + + .. _ETSI_Provision_5_6_6: + * - Provision 5.6-6 + - Code should be minimized to the functionality necessary for the service/device to operate. + - R + - + - + + .. _ETSI_Provision_5_6_7: + * - Provision 5.6-7 + - Software should run with least necessary privileges, taking account of both security + and functionality. + - R + - + - + + .. _ETSI_Provision_5_6_8: + * - Provision 5.6-8 + - The device should include a hardware-level access control mechanism for memory. + - R + - + - + + .. _ETSI_Provision_5_6_9: + * - Provision 5.6-9 + - The manufacturer should follow secure development processes for software deployed on + the device. + - R + - + - + + .. _ETSI_Provision_5_7_1: + * - Provision 5.7-1 + - The consumer IoT device should verify its software using secure boot mechanisms. + - R + - + - + + .. _ETSI_Provision_5_7_2: + * - Provision 5.7-2 + - If an unauthorized change is detected to the software, the device should alert the + user and/or administrator to the issue and should not connect to wider networks than + those necessary to perform the alerting function. + - R + - + - + + .. _ETSI_Provision_5_8_1: + * - Provision 5.8-1 + - The confidentiality of personal data transiting between a device and a service, + especially associated services, should be protected, with best practice cryptography. + - R + - + - + + .. _ETSI_Provision_5_8_2: + * - Provision 5.8-2 + - The confidentiality of sensitive personal data communicated between the device and + associated services shall be protected, with cryptography appropriate to the + properties of the technology and usage. + - M + - + - + + .. _ETSI_Provision_5_8_3: + * - Provision 5.8-3 + - All external sensing capabilities of the device shall be documented in an accessible + way that is clear and transparent for the user. + - M + - + - + + .. _ETSI_Provision_5_9_1: + * - Provision 5.9-1 + - Resilience should be built in to consumer IoT devices and services, taking into + account the possibility of outages of data networks and power. + - R + - + - + + .. _ETSI_Provision_5_9_2: + * - Provision 5.9-2 + - Consumer IoT devices should remain operating and locally functional in the case of a + loss of network access and should recover cleanly in the case of restoration of a + loss of power. + - R + - + - + + .. _ETSI_Provision_5_9_3: + * - Provision 5.9-3 + - The consumer IoT device should connect to networks in an expected, operational and + stable state and in an orderly fashion, taking the capability of the infrastructure + into consideration. + - R + - + - + + .. _ETSI_Provision_5_10_1: + * - Provision 5.10-1 + - If telemetry data is collected from consumer IoT devices and services, such as usage + and measurement data, it should be examined for security anomalies. + - R C + - + - + + .. _ETSI_Provision_5_11_1: + * - Provision 5.11-1 + - The user shall be provided with functionality such that user data can be erased from + the device in a simple manner. + - M + - + - + + .. _ETSI_Provision_5_11_2: + * - Provision 5.11-2 + - The consumer should be provided with functionality on the device such that personal + data can be removed from associated services in a simple manner. + - R + - + - + + .. _ETSI_Provision_5_11_3: + * - Provision 5.11-3 + - Users should be given clear instructions on how to delete their personal data. + - R + - + - + + .. _ETSI_Provision_5_11_4: + * - Provision 5.11-4 + - Users should be provided with clear confirmation that personal data has been deleted + from services, devices and applications. + - R + - + - + + .. _ETSI_Provision_5_12_1: + * - Provision 5.12-1 + - Installation and maintenance of consumer IoT should involve minimal decisions by the + user and should follow security best practice on usability. + - R + - + - + + .. _ETSI_Provision_5_12_2: + * - Provision 5.12-2 + - The manufacturer should provide users with guidance on how to securely set up their device. + - R + - + - + + .. _ETSI_Provision_5_12_3: + * - Provision 5.12-3 + - The manufacturer should provide users with guidance on how to check whether their + device is securely set up. + - R + - + - + + .. _ETSI_Provision_5_13_1: + * - Provision 5.13-1 + - The consumer IoT device software shall validate data input via user interfaces or + transferred via Application Programming Interfaces (APIs) or between networks in + services and devices. + - M + - + - + + .. _ETSI_Provision_6_1_1: + * - Provision 6.1-1 + - The manufacturer shall provide consumers with clear and transparent information about + what personal data is processed, how it is being used, by whom, and for what purposes, + for each device and service. This also applies to third parties that can be involved, + including advertisers. + - M + - + - + + .. _ETSI_Provision_6_1_2: + * - Provision 6.1-2 + - Where personal data is processed on the basis of consumers' consent, this consent + shall be obtained in a valid way. + - M C + - + - + + .. _ETSI_Provision_6_1_3: + * - Provision 6.1-3 + - Consumers who gave consent for the processing of their personal data shall have + the capability to withdraw it at any time. + - M + - + - + + .. _ETSI_Provision_6_1_4: + * - Provision 6.1-4 + - If telemetry data is collected from consumer IoT devices and services, the + processing of personal data should be kept to the minimum necessary for the + intended functionality. + - R C + - + - + + .. _ETSI_Provision_6_1_5: + * - Provision 6.1-5 + - If telemetry data is collected from consumer IoT devices and services, consumers + shall be provided with information on what telemetry data is collected, how it is + being used, by whom, and for what purposes. + - M C + - + - diff --git a/doc/security/standards/index.rst b/doc/security/standards/index.rst new file mode 100644 index 0000000000000..39b9a0c8db03a --- /dev/null +++ b/doc/security/standards/index.rst @@ -0,0 +1,22 @@ +.. _security_standards: + +Security standards and Zephyr +############################# + +For a long period organizations were, more or less, left responsible to deal +with cyber security on their own. This included how to assess the scale and impact +of the problem and who to properly respond it. + +Now, governments started looking how to regulate it and several regulations +and enforcements are rapidly emerging, and consequently, security standards. These +standards provide guidelines and outline requirements that products have to follow +to achieve compliance. + +This section aims to identify and assess which Zephyr project components are impacted +by security standards requirements and provide the right information to enable +organizations developing certifiable products using Zephyr project. + +.. toctree:: + :maxdepth: 1 + + etsi-303645.rst From 2c3e1a30472b268796a462e0bfdb890de223c801 Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Wed, 8 May 2024 12:27:32 -0700 Subject: [PATCH 1111/2849] doc: security/etsi: Provision 5.2.1 assessment Add self-assessment for provision 5.2.1 Signed-off-by: Flavio Ceolin --- doc/security/standards/etsi-303645.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/security/standards/etsi-303645.rst b/doc/security/standards/etsi-303645.rst index 903998d86ede9..85ca4c3db4fc5 100644 --- a/doc/security/standards/etsi-303645.rst +++ b/doc/security/standards/etsi-303645.rst @@ -238,8 +238,8 @@ Provisions Assessment - The manufacture shall make a vulnerability disclosure policy publicly available. - M - - - - + - Y + - :ref:`Vulnerability Management ` .. _ETSI_Provision_5_2_2: * - Provision 5.2-2 From da255c3e3dc433268a0c132a77dd935b318bfbbb Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Wed, 8 May 2024 12:34:26 -0700 Subject: [PATCH 1112/2849] doc: security/etsi: Provision 5.2.2 assessment Add self-assessment for provision 5.2.2 Signed-off-by: Flavio Ceolin --- doc/security/reporting.rst | 2 ++ doc/security/standards/etsi-303645.rst | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/doc/security/reporting.rst b/doc/security/reporting.rst index 376237fe938ce..946e502fa54ab 100644 --- a/doc/security/reporting.rst +++ b/doc/security/reporting.rst @@ -101,6 +101,8 @@ and 2. Exploitability of the issue. Issues that the subcommittee decides do not need an embargo will be reproduced in the regular Zephyr project bug tracking system. +.. _vulnerability_timeline: + Security sensitive vulnerabilities shall be made public after an embargo period of at most 90 days. The intent is to allow 30 days within the Zephyr project to fix the issues, and 60 days for external diff --git a/doc/security/standards/etsi-303645.rst b/doc/security/standards/etsi-303645.rst index 85ca4c3db4fc5..069dd749831d0 100644 --- a/doc/security/standards/etsi-303645.rst +++ b/doc/security/standards/etsi-303645.rst @@ -245,8 +245,8 @@ Provisions Assessment * - Provision 5.2-2 - Disclosed vulnerabilities should be acted on in a timely manner. - R - - - - + - Y + - :ref:`Vulnerability Timeline ` .. _ETSI_Provision_5_2_3: * - Provision 5.2-3 From 3abc5da089a378a624768e492f6bb7aefed14bbd Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Wed, 8 May 2024 12:37:24 -0700 Subject: [PATCH 1113/2849] doc: security/etsi: Provision 5.1.2 assessment Add self-assessment for provision 5.1.2 Signed-off-by: Flavio Ceolin --- doc/security/standards/etsi-303645.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/security/standards/etsi-303645.rst b/doc/security/standards/etsi-303645.rst index 069dd749831d0..15d3f987ea13e 100644 --- a/doc/security/standards/etsi-303645.rst +++ b/doc/security/standards/etsi-303645.rst @@ -202,7 +202,7 @@ Provisions Assessment these shall be generated with a mechanism that reduces the risk of automated attacks against a class or type of device. - M C - - + - N/A - .. _ETSI_Provision_5_1_3: From 5ac871b0779961a737f8bbb39139d88cce4d0c12 Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Wed, 8 May 2024 12:40:37 -0700 Subject: [PATCH 1114/2849] doc: security/etsi: Provision 5.3.4 assessment Add self-assessment for provision 5.3.4 Signed-off-by: Flavio Ceolin --- doc/security/standards/etsi-303645.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/security/standards/etsi-303645.rst b/doc/security/standards/etsi-303645.rst index 15d3f987ea13e..1df7734613d32 100644 --- a/doc/security/standards/etsi-303645.rst +++ b/doc/security/standards/etsi-303645.rst @@ -283,7 +283,7 @@ Provisions Assessment * - Provision 5.3-4 - Automatic mechanisms should be used for software updates. - R C - - + - N/A - .. _ETSI_Provision_5_3_5: From b170943d9f80a33b006103f12b34a5f29a11066b Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Wed, 8 May 2024 12:42:44 -0700 Subject: [PATCH 1115/2849] doc: security/etsi: Provision 5.3.3 assessment Add self-assessment for provision 5.3.3 Signed-off-by: Flavio Ceolin --- doc/security/standards/etsi-303645.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/security/standards/etsi-303645.rst b/doc/security/standards/etsi-303645.rst index 1df7734613d32..f51e41abfdf29 100644 --- a/doc/security/standards/etsi-303645.rst +++ b/doc/security/standards/etsi-303645.rst @@ -276,7 +276,7 @@ Provisions Assessment * - Provision 5.3-3 - An update shall be simple for the user to apply. - M C - - + - N/A - .. _ETSI_Provision_5_3_4: From a81591d3ecbd8810ba172a2b68f39b7af7c8a19b Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Wed, 8 May 2024 12:43:25 -0700 Subject: [PATCH 1116/2849] doc: security/etsi: Provision 5.3.5 assessment Add self-assessment for provision 5.3.5 Signed-off-by: Flavio Ceolin --- doc/security/standards/etsi-303645.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/security/standards/etsi-303645.rst b/doc/security/standards/etsi-303645.rst index f51e41abfdf29..8d5c9f6999368 100644 --- a/doc/security/standards/etsi-303645.rst +++ b/doc/security/standards/etsi-303645.rst @@ -291,7 +291,7 @@ Provisions Assessment - The device should check after initialization, and then periodically, whether security updates are available. - R C - - + - N/A - .. _ETSI_Provision_5_3_6: From 74d192f8b6f36d75340180a5570ba1eafcf5d86e Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Wed, 8 May 2024 12:44:11 -0700 Subject: [PATCH 1117/2849] doc: security/etsi: Provision 5.3.6 assessment Add self-assessment for provision 5.3.6 Signed-off-by: Flavio Ceolin --- doc/security/standards/etsi-303645.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/security/standards/etsi-303645.rst b/doc/security/standards/etsi-303645.rst index 8d5c9f6999368..cc24c4727b9a0 100644 --- a/doc/security/standards/etsi-303645.rst +++ b/doc/security/standards/etsi-303645.rst @@ -301,7 +301,7 @@ Provisions Assessment can enable, disable, or postpone installation of security updates and/or update notifications. - R C - - + - N/A - .. _ETSI_Provision_5_3_7: From 7fc502389d55f38b51cc2d4273dcf0376a2b6346 Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Wed, 8 May 2024 12:45:26 -0700 Subject: [PATCH 1118/2849] doc: security/etsi: Provision 6.1.4 assessment Add self-assessment for provision 6.1.4 Signed-off-by: Flavio Ceolin --- doc/security/standards/etsi-303645.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/security/standards/etsi-303645.rst b/doc/security/standards/etsi-303645.rst index cc24c4727b9a0..b110e8a09477b 100644 --- a/doc/security/standards/etsi-303645.rst +++ b/doc/security/standards/etsi-303645.rst @@ -718,7 +718,7 @@ Provisions Assessment processing of personal data should be kept to the minimum necessary for the intended functionality. - R C - - + - N/A - .. _ETSI_Provision_6_1_5: From db032226b5b297f689a54f084e32b348fa59bff2 Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Wed, 8 May 2024 12:45:56 -0700 Subject: [PATCH 1119/2849] doc: security/etsi: Provision 6.1.5 assessment Add self-assessment for provision 6.1.5 Signed-off-by: Flavio Ceolin --- doc/security/standards/etsi-303645.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/security/standards/etsi-303645.rst b/doc/security/standards/etsi-303645.rst index b110e8a09477b..5054ff1ed6e94 100644 --- a/doc/security/standards/etsi-303645.rst +++ b/doc/security/standards/etsi-303645.rst @@ -727,5 +727,5 @@ Provisions Assessment shall be provided with information on what telemetry data is collected, how it is being used, by whom, and for what purposes. - M C - - + - N/A - From defa4bdc4d7cd5fbef5ff3bf83e22e5f02fd0ed2 Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Wed, 8 May 2024 12:46:52 -0700 Subject: [PATCH 1120/2849] doc: security/etsi: Provision 6.1.3 assessment Add self-assessment for provision 6.1.3 Signed-off-by: Flavio Ceolin --- doc/security/standards/etsi-303645.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/security/standards/etsi-303645.rst b/doc/security/standards/etsi-303645.rst index 5054ff1ed6e94..62e4caa23b9e6 100644 --- a/doc/security/standards/etsi-303645.rst +++ b/doc/security/standards/etsi-303645.rst @@ -709,7 +709,7 @@ Provisions Assessment - Consumers who gave consent for the processing of their personal data shall have the capability to withdraw it at any time. - M - - + - N/A - .. _ETSI_Provision_6_1_4: From 1e763b4d8bb015ba6acfe9c60cd13e89111369cc Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Wed, 8 May 2024 12:47:40 -0700 Subject: [PATCH 1121/2849] doc: security/etsi: Provision 6.1.2 assessment Add self-assessment for provision 6.1.2 Signed-off-by: Flavio Ceolin --- doc/security/standards/etsi-303645.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/security/standards/etsi-303645.rst b/doc/security/standards/etsi-303645.rst index 62e4caa23b9e6..aac342f20bc70 100644 --- a/doc/security/standards/etsi-303645.rst +++ b/doc/security/standards/etsi-303645.rst @@ -701,7 +701,7 @@ Provisions Assessment - Where personal data is processed on the basis of consumers' consent, this consent shall be obtained in a valid way. - M C - - + - N/A - .. _ETSI_Provision_6_1_3: From b9b0e61f3c1938afbc40e24c2fc0fe39fa15493b Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Wed, 8 May 2024 12:48:21 -0700 Subject: [PATCH 1122/2849] doc: security/etsi: Provision 6.1.1 assessment Add self-assessment for provision 6.1.1 Signed-off-by: Flavio Ceolin --- doc/security/standards/etsi-303645.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/security/standards/etsi-303645.rst b/doc/security/standards/etsi-303645.rst index aac342f20bc70..30b4c6c8673a0 100644 --- a/doc/security/standards/etsi-303645.rst +++ b/doc/security/standards/etsi-303645.rst @@ -693,7 +693,7 @@ Provisions Assessment for each device and service. This also applies to third parties that can be involved, including advertisers. - M - - + - N/A - .. _ETSI_Provision_6_1_2: From 53ff81038e355545fd6b6521e0ef2905c2b4f274 Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Wed, 8 May 2024 13:01:06 -0700 Subject: [PATCH 1123/2849] doc: security/etsi: Provision 5.13.1 assessment Add self-assessment for provision 5.13.1 Signed-off-by: Flavio Ceolin --- doc/kernel/usermode/syscalls.rst | 2 ++ doc/security/standards/etsi-303645.rst | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/doc/kernel/usermode/syscalls.rst b/doc/kernel/usermode/syscalls.rst index f751697d9a307..8b35ce8099180 100644 --- a/doc/kernel/usermode/syscalls.rst +++ b/doc/kernel/usermode/syscalls.rst @@ -335,6 +335,8 @@ If any check fails, the macros will return a nonzero value. The macro calling thread. This is done instead of returning some error condition to keep the APIs the same when calling from supervisor mode. +.. _syscall_verification: + Verifier Definition =================== diff --git a/doc/security/standards/etsi-303645.rst b/doc/security/standards/etsi-303645.rst index 30b4c6c8673a0..ffc8f1f470684 100644 --- a/doc/security/standards/etsi-303645.rst +++ b/doc/security/standards/etsi-303645.rst @@ -683,8 +683,8 @@ Provisions Assessment transferred via Application Programming Interfaces (APIs) or between networks in services and devices. - M - - - - + - Y + - :ref:`Syscall verification ` and :ref:`Coding guidelines ` .. _ETSI_Provision_6_1_1: * - Provision 6.1-1 From 0017c592358a153b5a9b7204b31303aa8e24dc39 Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Wed, 8 May 2024 13:02:08 -0700 Subject: [PATCH 1124/2849] doc: security/etsi: Provision 5.12.2 assessment Add self-assessment for provision 5.12.2 Signed-off-by: Flavio Ceolin --- doc/security/standards/etsi-303645.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/security/standards/etsi-303645.rst b/doc/security/standards/etsi-303645.rst index ffc8f1f470684..593af452f181c 100644 --- a/doc/security/standards/etsi-303645.rst +++ b/doc/security/standards/etsi-303645.rst @@ -666,7 +666,7 @@ Provisions Assessment * - Provision 5.12-2 - The manufacturer should provide users with guidance on how to securely set up their device. - R - - + - N/A - .. _ETSI_Provision_5_12_3: From 235b2c93ee09927111cc83dc529cc865cf2618ce Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Wed, 8 May 2024 13:03:20 -0700 Subject: [PATCH 1125/2849] doc: security/etsi: Provision 5.12.3 assessment Add self-assessment for provision 5.12.3 Signed-off-by: Flavio Ceolin --- doc/security/standards/etsi-303645.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/security/standards/etsi-303645.rst b/doc/security/standards/etsi-303645.rst index 593af452f181c..3986afbcae88d 100644 --- a/doc/security/standards/etsi-303645.rst +++ b/doc/security/standards/etsi-303645.rst @@ -674,7 +674,7 @@ Provisions Assessment - The manufacturer should provide users with guidance on how to check whether their device is securely set up. - R - - + - N/A - .. _ETSI_Provision_5_13_1: From e227a6133a65f12aa6b05703db67d93b5972e122 Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Wed, 8 May 2024 13:05:53 -0700 Subject: [PATCH 1126/2849] doc: security/etsi: Provision 5.12.1 assessment Add self-assessment for provision 5.12.1 Signed-off-by: Flavio Ceolin --- doc/security/standards/etsi-303645.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/security/standards/etsi-303645.rst b/doc/security/standards/etsi-303645.rst index 3986afbcae88d..7599f7efb2e07 100644 --- a/doc/security/standards/etsi-303645.rst +++ b/doc/security/standards/etsi-303645.rst @@ -659,7 +659,7 @@ Provisions Assessment - Installation and maintenance of consumer IoT should involve minimal decisions by the user and should follow security best practice on usability. - R - - + - N/A - .. _ETSI_Provision_5_12_2: From d7d29690cd6005e065cd0abd490677f1990276b5 Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Wed, 8 May 2024 13:06:55 -0700 Subject: [PATCH 1127/2849] doc: security/etsi: Provision 5.11.3 assessment Add self-assessment for provision 5.11.3 Signed-off-by: Flavio Ceolin --- doc/security/standards/etsi-303645.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/security/standards/etsi-303645.rst b/doc/security/standards/etsi-303645.rst index 7599f7efb2e07..3245cca2a93f3 100644 --- a/doc/security/standards/etsi-303645.rst +++ b/doc/security/standards/etsi-303645.rst @@ -643,7 +643,7 @@ Provisions Assessment * - Provision 5.11-3 - Users should be given clear instructions on how to delete their personal data. - R - - + - N/A - .. _ETSI_Provision_5_11_4: From fded16b396558daebec4fc74f8caca15aec1cfb4 Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Wed, 8 May 2024 13:07:50 -0700 Subject: [PATCH 1128/2849] doc: security/etsi: Provision 5.11.4 assessment Add self-assessment for provision 5.11.4 Signed-off-by: Flavio Ceolin --- doc/security/standards/etsi-303645.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/security/standards/etsi-303645.rst b/doc/security/standards/etsi-303645.rst index 3245cca2a93f3..18bc9e3f0ef6c 100644 --- a/doc/security/standards/etsi-303645.rst +++ b/doc/security/standards/etsi-303645.rst @@ -651,7 +651,7 @@ Provisions Assessment - Users should be provided with clear confirmation that personal data has been deleted from services, devices and applications. - R - - + - N/A - .. _ETSI_Provision_5_12_1: From 058b5732d8d86eb4002db880645fccc1cdad04cc Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Wed, 8 May 2024 13:08:41 -0700 Subject: [PATCH 1129/2849] doc: security/etsi: Provision 5.10.1 assessment Add self-assessment for provision 5.10.1 Signed-off-by: Flavio Ceolin --- doc/security/standards/etsi-303645.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/security/standards/etsi-303645.rst b/doc/security/standards/etsi-303645.rst index 18bc9e3f0ef6c..252be1db323ec 100644 --- a/doc/security/standards/etsi-303645.rst +++ b/doc/security/standards/etsi-303645.rst @@ -620,7 +620,7 @@ Provisions Assessment - If telemetry data is collected from consumer IoT devices and services, such as usage and measurement data, it should be examined for security anomalies. - R C - - + - N/A - .. _ETSI_Provision_5_11_1: From 738b7020ed6ba0c32c4c8a689b4730905287a14d Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Wed, 8 May 2024 13:09:52 -0700 Subject: [PATCH 1130/2849] doc: security/etsi: Provision 5.11.2 assessment Add self-assessment for provision 5.11.2 Signed-off-by: Flavio Ceolin --- doc/security/standards/etsi-303645.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/security/standards/etsi-303645.rst b/doc/security/standards/etsi-303645.rst index 252be1db323ec..4f53a367684e6 100644 --- a/doc/security/standards/etsi-303645.rst +++ b/doc/security/standards/etsi-303645.rst @@ -636,7 +636,7 @@ Provisions Assessment - The consumer should be provided with functionality on the device such that personal data can be removed from associated services in a simple manner. - R - - + - N/A - .. _ETSI_Provision_5_11_3: From 82e8ab2218903658b383be002c28b6d13a16034a Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Wed, 8 May 2024 13:11:42 -0700 Subject: [PATCH 1131/2849] doc: security/etsi: Provision 5.8.1 assessment Add self-assessment for provision 5.8.1 Signed-off-by: Flavio Ceolin --- doc/security/standards/etsi-303645.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/security/standards/etsi-303645.rst b/doc/security/standards/etsi-303645.rst index 4f53a367684e6..dbc6f64943f45 100644 --- a/doc/security/standards/etsi-303645.rst +++ b/doc/security/standards/etsi-303645.rst @@ -569,7 +569,7 @@ Provisions Assessment - The confidentiality of personal data transiting between a device and a service, especially associated services, should be protected, with best practice cryptography. - R - - + - Y - .. _ETSI_Provision_5_8_2: From 7bb89fd02965b292fbcb5d583267561df66d91b3 Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Wed, 8 May 2024 14:44:43 -0700 Subject: [PATCH 1132/2849] doc: security/etsi: Provision 5.6.9 assessment Add self-assessment for provision 5.6.9 Signed-off-by: Flavio Ceolin --- doc/security/standards/etsi-303645.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/security/standards/etsi-303645.rst b/doc/security/standards/etsi-303645.rst index dbc6f64943f45..f042acd276fbb 100644 --- a/doc/security/standards/etsi-303645.rst +++ b/doc/security/standards/etsi-303645.rst @@ -545,8 +545,8 @@ Provisions Assessment - The manufacturer should follow secure development processes for software deployed on the device. - R - - - - + - Y + - :ref:`Security Overview ` and :ref:`Coding guidelines ` .. _ETSI_Provision_5_7_1: * - Provision 5.7-1 From ba2717ef852a8462bc9f1d0f311177f711ffbfca Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Wed, 8 May 2024 14:45:26 -0700 Subject: [PATCH 1133/2849] doc: security/etsi: Provision 5.1.1 assessment Add self-assessment for provision 5.1.1 Signed-off-by: Flavio Ceolin --- doc/security/standards/etsi-303645.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/security/standards/etsi-303645.rst b/doc/security/standards/etsi-303645.rst index f042acd276fbb..ce6170a7382f6 100644 --- a/doc/security/standards/etsi-303645.rst +++ b/doc/security/standards/etsi-303645.rst @@ -193,7 +193,7 @@ Provisions Assessment factory default, all consumer IoT device passwords shall be unique per device or defined by the user. - M C - - + - N/A - .. _ETSI_Provision_5_1_2: From c3319de9667c2b99e4387289c9e91e1af1ab00dc Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Wed, 8 May 2024 14:46:22 -0700 Subject: [PATCH 1134/2849] doc: security/etsi: Provision 5.1.4 assessment Add self-assessment for provision 5.1.4 Signed-off-by: Flavio Ceolin --- doc/security/standards/etsi-303645.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/security/standards/etsi-303645.rst b/doc/security/standards/etsi-303645.rst index ce6170a7382f6..6a30bb65285a4 100644 --- a/doc/security/standards/etsi-303645.rst +++ b/doc/security/standards/etsi-303645.rst @@ -220,7 +220,7 @@ Provisions Assessment shall provide to the user or an administrator a simple mechanism to change the authentication value used. - M C - - + - N/A - .. _ETSI_Provision_5_1_5: From 6d5cc9731affa9d673db353d8d4e638d97acc9a1 Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Wed, 8 May 2024 14:48:39 -0700 Subject: [PATCH 1135/2849] doc: security/etsi: Provision 5.1.3 assessment Add self-assessment for provision 5.1.3 Signed-off-by: Flavio Ceolin --- doc/security/standards/etsi-303645.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/security/standards/etsi-303645.rst b/doc/security/standards/etsi-303645.rst index 6a30bb65285a4..81b5a428fca73 100644 --- a/doc/security/standards/etsi-303645.rst +++ b/doc/security/standards/etsi-303645.rst @@ -211,7 +211,7 @@ Provisions Assessment device shall use best practice cryptography, appropriate to the properties of the technology, risk and usage. - M - - + - N/A - .. _ETSI_Provision_5_1_4: From 6259e921479f184cc876012fc94e0156c748f63a Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Wed, 8 May 2024 15:30:59 -0700 Subject: [PATCH 1136/2849] doc: security/etsi: Provision 5.2.3 assessment Add self-assessment for provision 5.2.3 Signed-off-by: Flavio Ceolin --- doc/security/standards/etsi-303645.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/security/standards/etsi-303645.rst b/doc/security/standards/etsi-303645.rst index 81b5a428fca73..6e39385470684 100644 --- a/doc/security/standards/etsi-303645.rst +++ b/doc/security/standards/etsi-303645.rst @@ -254,8 +254,8 @@ Provisions Assessment vulnerabilities within products and services they sell, produce, have produced and services they operate during the defined support period. - R - - - - + - Y + - `Modules `_ are covered .. _ETSI_Provision_5_3_1: * - Provision 5.3-1 From 3c8fa43b5742ba5ce6e3ad8739857bfc1a38fc15 Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Wed, 8 May 2024 15:32:19 -0700 Subject: [PATCH 1137/2849] doc: security/etsi: Provision 5.3.10 assessment Add self-assessment for provision 5.3.10 Signed-off-by: Flavio Ceolin --- doc/security/standards/etsi-303645.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/security/standards/etsi-303645.rst b/doc/security/standards/etsi-303645.rst index 6e39385470684..5af99c4e5855e 100644 --- a/doc/security/standards/etsi-303645.rst +++ b/doc/security/standards/etsi-303645.rst @@ -330,7 +330,7 @@ Provisions Assessment - Where updates are delivered over a network interface, the device shall verify the authenticity and integrity of each update via a trust relationship. - M - - + - N/A - .. _ETSI_Provision_5_3_11: From 7a7c1c3a2b6214b086bea92f7a26b5978a22d715 Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Wed, 8 May 2024 15:36:51 -0700 Subject: [PATCH 1138/2849] doc: security/etsi: Provision 5.3.13 assessment Add self-assessment for provision 5.3.13 Signed-off-by: Flavio Ceolin --- doc/releases/index.rst | 2 ++ doc/security/standards/etsi-303645.rst | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/doc/releases/index.rst b/doc/releases/index.rst index 4310b11d5d8c3..fc483fa606d4d 100644 --- a/doc/releases/index.rst +++ b/doc/releases/index.rst @@ -15,6 +15,8 @@ The technical documentation for current and past releases is available at https://docs.zephyrproject.org/ (use the version selector to select your release of interest). +.. _zephyr_release_cycle: + Release Life Cycle and Maintenance ********************************** diff --git a/doc/security/standards/etsi-303645.rst b/doc/security/standards/etsi-303645.rst index 5af99c4e5855e..1c26bbb68de64 100644 --- a/doc/security/standards/etsi-303645.rst +++ b/doc/security/standards/etsi-303645.rst @@ -355,8 +355,8 @@ Provisions Assessment - The manufacturer shall publish, in an accessible way that is clear and transparent to the user, the defined support period. - M - - - - + - Y + - :ref:`Release Life Cycle and Maintenance ` .. _ETSI_Provision_5_3_14: * - Provision 5.3-14 From 57580c4d38b2b2b68e8f56bef49acb584c3272cb Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Wed, 8 May 2024 15:40:29 -0700 Subject: [PATCH 1139/2849] doc: security/etsi: Provision 5.11.1 assessment Add self-assessment for provision 5.11.1 Signed-off-by: Flavio Ceolin --- doc/security/standards/etsi-303645.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/security/standards/etsi-303645.rst b/doc/security/standards/etsi-303645.rst index 1c26bbb68de64..f8c0a01ec6b9c 100644 --- a/doc/security/standards/etsi-303645.rst +++ b/doc/security/standards/etsi-303645.rst @@ -628,7 +628,7 @@ Provisions Assessment - The user shall be provided with functionality such that user data can be erased from the device in a simple manner. - M - - + - N/A - .. _ETSI_Provision_5_11_2: From 38fc1cb008d0a18eb14c1931b64b5dff94a66424 Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Wed, 8 May 2024 15:46:09 -0700 Subject: [PATCH 1140/2849] doc: security/etsi: Provision 5.7.2 assessment Add self-assessment for provision 5.7.2 Signed-off-by: Flavio Ceolin --- doc/security/standards/etsi-303645.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/security/standards/etsi-303645.rst b/doc/security/standards/etsi-303645.rst index f8c0a01ec6b9c..009fbdd709b7a 100644 --- a/doc/security/standards/etsi-303645.rst +++ b/doc/security/standards/etsi-303645.rst @@ -561,8 +561,8 @@ Provisions Assessment user and/or administrator to the issue and should not connect to wider networks than those necessary to perform the alerting function. - R - - - - + - N + - Zephyr does not provide runtime detection / notification. .. _ETSI_Provision_5_8_1: * - Provision 5.8-1 From 96becc41e546cde683350112e4646acb132cb680 Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Wed, 8 May 2024 15:52:46 -0700 Subject: [PATCH 1141/2849] doc: security/etsi: Provision 5.6.8 assessment Add self-assessment for provision 5.6.8 Signed-off-by: Flavio Ceolin --- doc/security/standards/etsi-303645.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/security/standards/etsi-303645.rst b/doc/security/standards/etsi-303645.rst index 009fbdd709b7a..ca9c0e93024e1 100644 --- a/doc/security/standards/etsi-303645.rst +++ b/doc/security/standards/etsi-303645.rst @@ -537,8 +537,8 @@ Provisions Assessment * - Provision 5.6-8 - The device should include a hardware-level access control mechanism for memory. - R - - - - + - Y + - :ref:`Memory protection ` .. _ETSI_Provision_5_6_9: * - Provision 5.6-9 From f68413aa86f92b494bcaba6c34f9f99f1df6d45a Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Wed, 8 May 2024 15:57:02 -0700 Subject: [PATCH 1142/2849] doc: security/etsi: Provision 5.6.4 assessment Add self-assessment for provision 5.6.4 Signed-off-by: Flavio Ceolin --- doc/security/standards/etsi-303645.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/security/standards/etsi-303645.rst b/doc/security/standards/etsi-303645.rst index ca9c0e93024e1..ef218a21b6877 100644 --- a/doc/security/standards/etsi-303645.rst +++ b/doc/security/standards/etsi-303645.rst @@ -507,8 +507,8 @@ Provisions Assessment * - Provision 5.6-4 - Where a debug interface is physically accessible, it shall be disabled in software. - M C - - - - + - Y + - :ref:`Hardening Tool ` .. _ETSI_Provision_5_6_5: * - Provision 5.6-5 From 1154bc009247e32e86c1d8075ae505a0041f946b Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Wed, 8 May 2024 16:01:57 -0700 Subject: [PATCH 1143/2849] doc: security/etsi: Provision 5.3.14 assessment Add self-assessment for provision 5.3.14 Signed-off-by: Flavio Ceolin --- doc/security/standards/etsi-303645.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/security/standards/etsi-303645.rst b/doc/security/standards/etsi-303645.rst index ef218a21b6877..c0376c6c11692 100644 --- a/doc/security/standards/etsi-303645.rst +++ b/doc/security/standards/etsi-303645.rst @@ -365,7 +365,7 @@ Provisions Assessment support and a defined support period should be published by the manufacturer in an accessible way that is clear and transparent to the user. - R C - - + - N/A - .. _ETSI_Provision_5_3_15: From abf6c4fce9ae68030902f37dd21d19fef3cebfed Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Wed, 8 May 2024 16:02:33 -0700 Subject: [PATCH 1144/2849] doc: security/etsi: Provision 5.3.15 assessment Add self-assessment for provision 5.3.15 Signed-off-by: Flavio Ceolin --- doc/security/standards/etsi-303645.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/security/standards/etsi-303645.rst b/doc/security/standards/etsi-303645.rst index c0376c6c11692..f829f7afd0d15 100644 --- a/doc/security/standards/etsi-303645.rst +++ b/doc/security/standards/etsi-303645.rst @@ -373,7 +373,7 @@ Provisions Assessment - For constrained devices that cannot have their software updated, the product should be isolable and the hardware replaceable. - R C - - + - N/A - .. _ETSI_Provision_5_3_16: From 9ad25f66da643cdde5344695e6a524e033a64cf9 Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Wed, 8 May 2024 16:09:05 -0700 Subject: [PATCH 1145/2849] doc: security/etsi: Provision 5.3.12 assessment Add self-assessment for provision 5.3.12 Signed-off-by: Flavio Ceolin --- doc/security/standards/etsi-303645.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/security/standards/etsi-303645.rst b/doc/security/standards/etsi-303645.rst index f829f7afd0d15..5e5f2757f2d98 100644 --- a/doc/security/standards/etsi-303645.rst +++ b/doc/security/standards/etsi-303645.rst @@ -347,8 +347,8 @@ Provisions Assessment - The device should notify the user when the application of a software update will disrupt the basic functioning of the device. - R C - - - - + - N/A + - Zephyr provides this information for its updates. Anyone using Zephyr in their products must check if they are affected .. _ETSI_Provision_5_3_13: * - Provision 5.3-13 From 18403137c81eef6c95eb5e04ef6e97e56de5abac Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Fri, 10 May 2024 16:37:40 -0700 Subject: [PATCH 1146/2849] doc: security/etsi: Provision 5.3.16 assessment Add self-assessment for provision 5.3.16 Signed-off-by: Flavio Ceolin --- doc/security/standards/etsi-303645.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/security/standards/etsi-303645.rst b/doc/security/standards/etsi-303645.rst index 5e5f2757f2d98..43caf8a4203d7 100644 --- a/doc/security/standards/etsi-303645.rst +++ b/doc/security/standards/etsi-303645.rst @@ -381,7 +381,7 @@ Provisions Assessment - The model designation of the consumer IoT device shall be clearly recognizable, either by labelling on the device or via a physical interface. - M - - + - N/A - .. _ETSI_Provision_5_4_1: From 058d2eba2c3aea1017737d5261e127cb113aeb21 Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Fri, 10 May 2024 16:40:52 -0700 Subject: [PATCH 1147/2849] doc: security/etsi: Provision 5.4.1 assessment Add self-assessment for provision 5.4.1 Signed-off-by: Flavio Ceolin --- doc/security/standards/etsi-303645.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/security/standards/etsi-303645.rst b/doc/security/standards/etsi-303645.rst index 43caf8a4203d7..1cfed93161b0b 100644 --- a/doc/security/standards/etsi-303645.rst +++ b/doc/security/standards/etsi-303645.rst @@ -388,8 +388,8 @@ Provisions Assessment * - Provision 5.4-1 - Sensitive security parameters in persistent storage shall be stored securely by the device. - M - - - - + - N + - There is not secure storage within Zephyr .. _ETSI_Provision_5_4_2: * - Provision 5.4-2 From dbd110dd0a93f59129c2a7e513e81060a739abf4 Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Mon, 13 May 2024 10:02:39 -0700 Subject: [PATCH 1148/2849] doc: security/etsi: Provision 5.6.6 assessment Add self-assessment for provision 5.6.6 Signed-off-by: Flavio Ceolin --- doc/security/standards/etsi-303645.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/security/standards/etsi-303645.rst b/doc/security/standards/etsi-303645.rst index 1cfed93161b0b..17575cb96b53c 100644 --- a/doc/security/standards/etsi-303645.rst +++ b/doc/security/standards/etsi-303645.rst @@ -522,8 +522,8 @@ Provisions Assessment * - Provision 5.6-6 - Code should be minimized to the functionality necessary for the service/device to operate. - R - - - - + - Y + - :ref:`Kconfig ` .. _ETSI_Provision_5_6_7: * - Provision 5.6-7 From e285c4c106d458f2de4e98e7a700260e5c21d3fa Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Mon, 13 May 2024 11:19:51 -0700 Subject: [PATCH 1149/2849] doc: security/etsi: Provision 5.7.1 assessment Add self-assessment for provision 5.7.1 Signed-off-by: Flavio Ceolin --- doc/security/standards/etsi-303645.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/security/standards/etsi-303645.rst b/doc/security/standards/etsi-303645.rst index 17575cb96b53c..16432fb8ec3e3 100644 --- a/doc/security/standards/etsi-303645.rst +++ b/doc/security/standards/etsi-303645.rst @@ -552,8 +552,8 @@ Provisions Assessment * - Provision 5.7-1 - The consumer IoT device should verify its software using secure boot mechanisms. - R - - - - + - Y + - Functionality provided by `MCUboot `. Also see :ref:`Security Overview ` .. _ETSI_Provision_5_7_2: * - Provision 5.7-2 From 255aa4a9207fe0c1a3712e7a4a0e87d57e26b43f Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Mon, 13 May 2024 11:24:51 -0700 Subject: [PATCH 1150/2849] doc: security/etsi: Provision 5.3.1 assessment Add self-assessment for provision 5.3.1 Signed-off-by: Flavio Ceolin --- doc/security/standards/etsi-303645.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/security/standards/etsi-303645.rst b/doc/security/standards/etsi-303645.rst index 16432fb8ec3e3..4a27626ab29eb 100644 --- a/doc/security/standards/etsi-303645.rst +++ b/doc/security/standards/etsi-303645.rst @@ -261,8 +261,8 @@ Provisions Assessment * - Provision 5.3-1 - All software components in consumer IoT devices should be securely updatable. - R - - - - + - Y + - :ref:`Device firwmware upgrade ` .. _ETSI_Provision_5_3_2: * - Provision 5.3-2 From ed2d429e7c0398ee215717397f6cb9bffa4e5198 Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Mon, 13 May 2024 11:25:19 -0700 Subject: [PATCH 1151/2849] doc: security/etsi: Provision 5.3.2 assessment Add self-assessment for provision 5.3.2 Signed-off-by: Flavio Ceolin --- doc/security/standards/etsi-303645.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/security/standards/etsi-303645.rst b/doc/security/standards/etsi-303645.rst index 4a27626ab29eb..9b075ea21a489 100644 --- a/doc/security/standards/etsi-303645.rst +++ b/doc/security/standards/etsi-303645.rst @@ -269,8 +269,8 @@ Provisions Assessment - When the device is not a constrained device, it shall have an update mechanism for the secure installation of updates. - M C - - - - + - Y + - :ref:`Device firwmware upgrade ` .. _ETSI_Provision_5_3_3: * - Provision 5.3-3 From 26f574c082a9ab95aeb8b0d08e272e79aceabec9 Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Mon, 13 May 2024 11:55:47 -0700 Subject: [PATCH 1152/2849] doc: security/etsi: Provision 5.3.7 assessment Add self-assessment for provision 5.3.7 Signed-off-by: Flavio Ceolin --- doc/security/standards/etsi-303645.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/security/standards/etsi-303645.rst b/doc/security/standards/etsi-303645.rst index 9b075ea21a489..60a9e498103f9 100644 --- a/doc/security/standards/etsi-303645.rst +++ b/doc/security/standards/etsi-303645.rst @@ -308,8 +308,8 @@ Provisions Assessment * - Provision 5.3-7 - The device shall use best practice cryptography to facilitate secure update mechanisms. - M C - - - - + - Y + - :ref:`West Sign ` .. _ETSI_Provision_5_3_8: * - Provision 5.3-8 From 5974e1711a0d6593c4d6fafd91e38607af5bd0d0 Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Mon, 13 May 2024 11:57:40 -0700 Subject: [PATCH 1153/2849] doc: security/etsi: Provision 5.3.9 assessment Add self-assessment for provision 5.3.9 Signed-off-by: Flavio Ceolin --- doc/security/standards/etsi-303645.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/security/standards/etsi-303645.rst b/doc/security/standards/etsi-303645.rst index 60a9e498103f9..1eb0b7ba32760 100644 --- a/doc/security/standards/etsi-303645.rst +++ b/doc/security/standards/etsi-303645.rst @@ -322,8 +322,8 @@ Provisions Assessment * - Provision 5.3-9 - The device should verify the authenticity and integrity of software updates. - R C - - - - + - Y + - Functionality provided by `MCUboot `. Also see :ref:`Device Firwmware Upgrade ` .. _ETSI_Provision_5_3_10: * - Provision 5.3-10 From 99a6e790ec0446cd372447c7a05d1e6f8c14bff4 Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Mon, 13 May 2024 11:58:53 -0700 Subject: [PATCH 1154/2849] doc: security/etsi: Provision 5.6.1 assessment Add self-assessment for provision 5.6.1 Signed-off-by: Flavio Ceolin --- doc/security/standards/etsi-303645.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/security/standards/etsi-303645.rst b/doc/security/standards/etsi-303645.rst index 1eb0b7ba32760..cb4f9779d82bd 100644 --- a/doc/security/standards/etsi-303645.rst +++ b/doc/security/standards/etsi-303645.rst @@ -485,8 +485,8 @@ Provisions Assessment * - Provision 5.6-1 - All unused network and logical interfaces shall be disabled. - M - - - - + - Y + - :ref:`Kconfig ` .. _ETSI_Provision_5_6_2: * - Provision 5.6-2 From a0b9c513bccbcb34cb7a4c03a462211d5aaebbd1 Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Mon, 13 May 2024 11:59:56 -0700 Subject: [PATCH 1155/2849] doc: security/etsi: Provision 5.6.3 assessment Add self-assessment for provision 5.6.3 Signed-off-by: Flavio Ceolin --- doc/security/standards/etsi-303645.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/security/standards/etsi-303645.rst b/doc/security/standards/etsi-303645.rst index cb4f9779d82bd..51821c6d21f12 100644 --- a/doc/security/standards/etsi-303645.rst +++ b/doc/security/standards/etsi-303645.rst @@ -500,8 +500,8 @@ Provisions Assessment * - Provision 5.6-3 - Device hardware should not unnecessarily expose physical interfaces to attack. - R - - - - + - Y + - :ref:`Kconfig ` and :ref:`Hardening Tool ` .. _ETSI_Provision_5_6_4: * - Provision 5.6-4 From 431ae0e4ed6aeac5b3d3b31666cc7b79cc8fcf46 Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Mon, 13 May 2024 12:00:57 -0700 Subject: [PATCH 1156/2849] doc: security/etsi: Provision 5.6.5 assessment Add self-assessment for provision 5.6.5 Signed-off-by: Flavio Ceolin --- doc/security/standards/etsi-303645.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/security/standards/etsi-303645.rst b/doc/security/standards/etsi-303645.rst index 51821c6d21f12..3faa4e4bac524 100644 --- a/doc/security/standards/etsi-303645.rst +++ b/doc/security/standards/etsi-303645.rst @@ -515,8 +515,8 @@ Provisions Assessment - The manufacturer should only enable software services that are used or required for the intended use or operation of the device. - R - - - - + - Y + - :ref:`Kconfig ` and :ref:`Hardening Tool ` .. _ETSI_Provision_5_6_6: * - Provision 5.6-6 From bd58b625d6ed5926a53567d53fd3bce757b81374 Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Mon, 13 May 2024 12:04:40 -0700 Subject: [PATCH 1157/2849] doc: security/etsi: Provision 5.6.7 assessment Add self-assessment for provision 5.6.7 Signed-off-by: Flavio Ceolin --- doc/security/standards/etsi-303645.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/security/standards/etsi-303645.rst b/doc/security/standards/etsi-303645.rst index 3faa4e4bac524..44626727ba4a3 100644 --- a/doc/security/standards/etsi-303645.rst +++ b/doc/security/standards/etsi-303645.rst @@ -530,8 +530,8 @@ Provisions Assessment - Software should run with least necessary privileges, taking account of both security and functionality. - R - - - - + - Y + - :ref:`Security Overview ` .. _ETSI_Provision_5_6_8: * - Provision 5.6-8 From 81c2e43677955d2b067b69d974053f22ab4ded28 Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Mon, 13 May 2024 12:10:13 -0700 Subject: [PATCH 1158/2849] doc: security/etsi: Provision 5.8.3 assessment Add self-assessment for provision 5.8.3 Signed-off-by: Flavio Ceolin --- doc/security/standards/etsi-303645.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/security/standards/etsi-303645.rst b/doc/security/standards/etsi-303645.rst index 44626727ba4a3..0c0320b138165 100644 --- a/doc/security/standards/etsi-303645.rst +++ b/doc/security/standards/etsi-303645.rst @@ -586,8 +586,8 @@ Provisions Assessment - All external sensing capabilities of the device shall be documented in an accessible way that is clear and transparent for the user. - M - - - - + - Y + - :ref:`Sensing Subsystem ` .. _ETSI_Provision_5_9_1: * - Provision 5.9-1 From ac0d3a72fc90c3272d4c03096bda549e1a3b9a02 Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Mon, 13 May 2024 12:11:07 -0700 Subject: [PATCH 1159/2849] doc: security/etsi: Provision 5.8.2 assessment Add self-assessment for provision 5.8.2 Signed-off-by: Flavio Ceolin --- doc/security/standards/etsi-303645.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/security/standards/etsi-303645.rst b/doc/security/standards/etsi-303645.rst index 0c0320b138165..9c9d623d668b6 100644 --- a/doc/security/standards/etsi-303645.rst +++ b/doc/security/standards/etsi-303645.rst @@ -578,7 +578,7 @@ Provisions Assessment associated services shall be protected, with cryptography appropriate to the properties of the technology and usage. - M - - + - Y - .. _ETSI_Provision_5_8_3: From 3e1252d61cdc0f80c7316ee7333e42c7b92bb032 Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Mon, 13 May 2024 12:18:10 -0700 Subject: [PATCH 1160/2849] doc: security/etsi: Provision 5.3.8 assessment Add self-assessment for provision 5.3.8 Signed-off-by: Flavio Ceolin --- doc/security/standards/etsi-303645.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/security/standards/etsi-303645.rst b/doc/security/standards/etsi-303645.rst index 9c9d623d668b6..a5581c761a979 100644 --- a/doc/security/standards/etsi-303645.rst +++ b/doc/security/standards/etsi-303645.rst @@ -315,7 +315,7 @@ Provisions Assessment * - Provision 5.3-8 - Security updates shall be timely. - M C - - + - N/A - .. _ETSI_Provision_5_3_9: From c1fa0552a9d6bfdb59a911ac916faf159b3fa233 Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Mon, 13 May 2024 12:19:00 -0700 Subject: [PATCH 1161/2849] doc: security/etsi: Provision 5.3.11 assessment Add self-assessment for provision 5.3.11 Signed-off-by: Flavio Ceolin --- doc/security/standards/etsi-303645.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/security/standards/etsi-303645.rst b/doc/security/standards/etsi-303645.rst index a5581c761a979..3617e33cc5009 100644 --- a/doc/security/standards/etsi-303645.rst +++ b/doc/security/standards/etsi-303645.rst @@ -339,7 +339,7 @@ Provisions Assessment that a security update is required together with information on the risks mitigated by that update. - R C - - + - N/A - .. _ETSI_Provision_5_3_12: From 0af7ecbfe9e58a63408f8c99f760651c6b961461 Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Mon, 13 May 2024 12:20:31 -0700 Subject: [PATCH 1162/2849] doc: security/etsi: Provision 5.4.2 assessment Add self-assessment for provision 5.4.2 Signed-off-by: Flavio Ceolin --- doc/security/standards/etsi-303645.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/security/standards/etsi-303645.rst b/doc/security/standards/etsi-303645.rst index 3617e33cc5009..9d4fa9a08fba3 100644 --- a/doc/security/standards/etsi-303645.rst +++ b/doc/security/standards/etsi-303645.rst @@ -397,7 +397,7 @@ Provisions Assessment it shall be implemented in such a way that it resists tampering by means such as physical, electrical or software. - M C - - + - N/A - .. _ETSI_Provision_5_4_3: From e5398174d34cee4d964bcd8a67ed158822b73fda Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Mon, 13 May 2024 12:21:34 -0700 Subject: [PATCH 1163/2849] doc: security/etsi: Provision 5.4.3 assessment Add self-assessment for provision 5.4.3 Signed-off-by: Flavio Ceolin --- doc/security/standards/etsi-303645.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/security/standards/etsi-303645.rst b/doc/security/standards/etsi-303645.rst index 9d4fa9a08fba3..e8c1020f7e59e 100644 --- a/doc/security/standards/etsi-303645.rst +++ b/doc/security/standards/etsi-303645.rst @@ -404,8 +404,8 @@ Provisions Assessment * - Provision 5.4-3 - Hard-coded critical security parameters in device software source code shall not be used. - M - - - - + - Y + - :ref:`Hardening Tool ` .. _ETSI_Provision_5_4_4: * - Provision 5.4-4 From d0a0877a0012c68d5bc8eb6f96f9f6fb45e5e9bc Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Mon, 13 May 2024 12:23:06 -0700 Subject: [PATCH 1164/2849] doc: security/etsi: Provision 5.4.4 assessment Add self-assessment for provision 5.4.4 Signed-off-by: Flavio Ceolin --- doc/security/standards/etsi-303645.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/security/standards/etsi-303645.rst b/doc/security/standards/etsi-303645.rst index e8c1020f7e59e..81f10db518151 100644 --- a/doc/security/standards/etsi-303645.rst +++ b/doc/security/standards/etsi-303645.rst @@ -414,7 +414,7 @@ Provisions Assessment shall be unique per device and shall be produced with a mechanism that reduces the risk of automated attacks against classes of devices. - M - - + - N/A - .. _ETSI_Provision_5_5_1: From cc19047cbdab4259036a5213ed308c20838fd08a Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Mon, 13 May 2024 12:24:17 -0700 Subject: [PATCH 1165/2849] doc: security/etsi: Provision 5.5.1 assessment Add self-assessment for provision 5.5.1 Signed-off-by: Flavio Ceolin --- doc/security/standards/etsi-303645.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/security/standards/etsi-303645.rst b/doc/security/standards/etsi-303645.rst index 81f10db518151..f7f4d94292e90 100644 --- a/doc/security/standards/etsi-303645.rst +++ b/doc/security/standards/etsi-303645.rst @@ -421,7 +421,7 @@ Provisions Assessment * - Provision 5.5-1 - The consumer IoT device shall use best practice cryptography to communicate securely. - M - - + - Y - .. _ETSI_Provision_5_5_2: From 142a824678c90cde54974c08610f90bac625d593 Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Mon, 13 May 2024 12:25:04 -0700 Subject: [PATCH 1166/2849] doc: security/etsi: Provision 5.5.2 assessment Add self-assessment for provision 5.5.2 Signed-off-by: Flavio Ceolin --- doc/security/standards/etsi-303645.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/security/standards/etsi-303645.rst b/doc/security/standards/etsi-303645.rst index f7f4d94292e90..788313a9c5134 100644 --- a/doc/security/standards/etsi-303645.rst +++ b/doc/security/standards/etsi-303645.rst @@ -429,7 +429,7 @@ Provisions Assessment - The consumer IoT device should use reviewed or evaluated implementations to deliver network and security functionalities, particularly in the field of cryptography. - R - - + - Y - .. _ETSI_Provision_5_5_3: From efa89c4f0112ce812fdae8966284b9cb146c80a5 Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Mon, 13 May 2024 12:29:46 -0700 Subject: [PATCH 1167/2849] doc: security/etsi: Provision 5.5.3 assessment Add self-assessment for provision 5.5.3 Signed-off-by: Flavio Ceolin --- doc/security/standards/etsi-303645.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/security/standards/etsi-303645.rst b/doc/security/standards/etsi-303645.rst index 788313a9c5134..89592c94d9206 100644 --- a/doc/security/standards/etsi-303645.rst +++ b/doc/security/standards/etsi-303645.rst @@ -436,8 +436,8 @@ Provisions Assessment * - Provision 5.5-3 - Cryptographic algorithms and primitives should be updatable. - R - - - - + - N + - The whole image must be updated .. _ETSI_Provision_5_5_4: * - Provision 5.5-4 From b236cf25140f7ab7ecbbf6927de5595192afc989 Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Mon, 13 May 2024 12:30:37 -0700 Subject: [PATCH 1168/2849] doc: security/etsi: Provision 5.5.4 assessment Add self-assessment for provision 5.5.4 Signed-off-by: Flavio Ceolin --- doc/security/standards/etsi-303645.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/security/standards/etsi-303645.rst b/doc/security/standards/etsi-303645.rst index 89592c94d9206..19064646ae698 100644 --- a/doc/security/standards/etsi-303645.rst +++ b/doc/security/standards/etsi-303645.rst @@ -444,7 +444,7 @@ Provisions Assessment - Access to device functionality via a network interface in the initialized state should only be possible after authentication on that interface. - R - - + - N/A - .. _ETSI_Provision_5_5_5: From d3f49786a21cf6a6cb9f6d4eb2d5d53536c1b99a Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Mon, 13 May 2024 12:33:50 -0700 Subject: [PATCH 1169/2849] doc: security/etsi: Provision 5.6.2 assessment Add self-assessment for provision 5.6.2 Signed-off-by: Flavio Ceolin --- doc/security/standards/etsi-303645.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/security/standards/etsi-303645.rst b/doc/security/standards/etsi-303645.rst index 19064646ae698..87c1d4d696990 100644 --- a/doc/security/standards/etsi-303645.rst +++ b/doc/security/standards/etsi-303645.rst @@ -493,7 +493,7 @@ Provisions Assessment - In the initialized state, the network interfaces of the device shall minimize the unauthenticated disclosure of security-relevant information. - M - - + - Y - .. _ETSI_Provision_5_6_3: From 3139ca8f3052bdc2f18b207631d108cc73a6cbd5 Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Mon, 13 May 2024 12:35:14 -0700 Subject: [PATCH 1170/2849] doc: security/etsi: Provision 5.5.8 assessment Add self-assessment for provision 5.5.8 Signed-off-by: Flavio Ceolin --- doc/security/standards/etsi-303645.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/security/standards/etsi-303645.rst b/doc/security/standards/etsi-303645.rst index 87c1d4d696990..a262128de86d7 100644 --- a/doc/security/standards/etsi-303645.rst +++ b/doc/security/standards/etsi-303645.rst @@ -478,7 +478,7 @@ Provisions Assessment - The manufacturer shall follow secure management processes for critical security parameters that relate to the device. - M - - + - N/A - .. _ETSI_Provision_5_6_1: From fd95061364f31944348c32a600c469b0689b8d40 Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Mon, 13 May 2024 12:36:17 -0700 Subject: [PATCH 1171/2849] doc: security/etsi: Provision 5.5.6 assessment Add self-assessment for provision 5.5.6 Signed-off-by: Flavio Ceolin --- doc/security/standards/etsi-303645.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/security/standards/etsi-303645.rst b/doc/security/standards/etsi-303645.rst index a262128de86d7..55162e228ae79 100644 --- a/doc/security/standards/etsi-303645.rst +++ b/doc/security/standards/etsi-303645.rst @@ -454,7 +454,7 @@ Provisions Assessment network service protocols that are relied upon by the device and where the manufacturer cannot guarantee what configuration will be required for the device to operate. - M - - + - N/A - .. _ETSI_Provision_5_5_6: From dcb8da2b00075b6bb4fe7874d5a0d4d93b5c3726 Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Mon, 13 May 2024 12:42:16 -0700 Subject: [PATCH 1172/2849] doc: security/etsi: Provision 5.1.5 assessment Add self-assessment for provision 5.1.5 Signed-off-by: Flavio Ceolin --- doc/security/standards/etsi-303645.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/security/standards/etsi-303645.rst b/doc/security/standards/etsi-303645.rst index 55162e228ae79..f41b34bfc6030 100644 --- a/doc/security/standards/etsi-303645.rst +++ b/doc/security/standards/etsi-303645.rst @@ -230,8 +230,8 @@ Provisions Assessment authentication mechanisms via network interfaces impracticable. - M C - - - - + - N + - **TODO** .. _ETSI_Provision_5_2_1: * - Provision 5.2-1 From 8000ed17910ed3453c7f90e3a7d01192803c8d5a Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Mon, 13 May 2024 12:44:23 -0700 Subject: [PATCH 1173/2849] doc: security/etsi: Provision 5.5.6 assessment Add self-assessment for provision 5.5.6 Signed-off-by: Flavio Ceolin --- doc/security/standards/etsi-303645.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/security/standards/etsi-303645.rst b/doc/security/standards/etsi-303645.rst index f41b34bfc6030..2d5b7bc99166a 100644 --- a/doc/security/standards/etsi-303645.rst +++ b/doc/security/standards/etsi-303645.rst @@ -462,7 +462,7 @@ Provisions Assessment - Critical security parameters should be encrypted in transit, with such encryption appropriate to the properties of the technology, risk and usage. - R - - + - Y - .. _ETSI_Provision_5_5_7: From 124b7af27bd3bb7d6074b8b69fc386d6ba155a9d Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Mon, 13 May 2024 12:45:19 -0700 Subject: [PATCH 1174/2849] doc: security/etsi: Provision 5.5.7 assessment Add self-assessment for provision 5.5.7 Signed-off-by: Flavio Ceolin --- doc/security/standards/etsi-303645.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/security/standards/etsi-303645.rst b/doc/security/standards/etsi-303645.rst index 2d5b7bc99166a..092b72d2cf552 100644 --- a/doc/security/standards/etsi-303645.rst +++ b/doc/security/standards/etsi-303645.rst @@ -470,7 +470,7 @@ Provisions Assessment - The consumer IoT device shall protect the confidentiality of critical security parameters that are communicated via remotely accessible network interfaces. - M - - + - Y - .. _ETSI_Provision_5_5_8: From 8fbf094c4ebd93e7b1e262b2bef75c5ef184e31f Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Mon, 13 May 2024 12:46:30 -0700 Subject: [PATCH 1175/2849] doc: security/etsi: Provision 5.9.1 assessment Add self-assessment for provision 5.9.1 Signed-off-by: Flavio Ceolin --- doc/security/standards/etsi-303645.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/security/standards/etsi-303645.rst b/doc/security/standards/etsi-303645.rst index 092b72d2cf552..7b97831328031 100644 --- a/doc/security/standards/etsi-303645.rst +++ b/doc/security/standards/etsi-303645.rst @@ -594,7 +594,7 @@ Provisions Assessment - Resilience should be built in to consumer IoT devices and services, taking into account the possibility of outages of data networks and power. - R - - + - Y - .. _ETSI_Provision_5_9_2: From 9d3222c7cb599b8773bf3f7bd72b9aaddbaa9046 Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Mon, 13 May 2024 12:47:11 -0700 Subject: [PATCH 1176/2849] doc: security/etsi: Provision 5.9.3 assessment Add self-assessment for provision 5.9.3 Signed-off-by: Flavio Ceolin --- doc/security/standards/etsi-303645.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/security/standards/etsi-303645.rst b/doc/security/standards/etsi-303645.rst index 7b97831328031..84e10c5bef0e4 100644 --- a/doc/security/standards/etsi-303645.rst +++ b/doc/security/standards/etsi-303645.rst @@ -612,7 +612,7 @@ Provisions Assessment stable state and in an orderly fashion, taking the capability of the infrastructure into consideration. - R - - + - Y - .. _ETSI_Provision_5_10_1: From 08417b4d73d564ef9e0ebb5bcb2c033ac7918ab2 Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Mon, 13 May 2024 12:47:43 -0700 Subject: [PATCH 1177/2849] doc: security/etsi: Provision 5.9.2 assessment Add self-assessment for provision 5.9.2 Signed-off-by: Flavio Ceolin --- doc/security/standards/etsi-303645.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/security/standards/etsi-303645.rst b/doc/security/standards/etsi-303645.rst index 84e10c5bef0e4..552756997e251 100644 --- a/doc/security/standards/etsi-303645.rst +++ b/doc/security/standards/etsi-303645.rst @@ -603,7 +603,7 @@ Provisions Assessment loss of network access and should recover cleanly in the case of restoration of a loss of power. - R - - + - Y - .. _ETSI_Provision_5_9_3: From ecda6b190ff35fdc93dbcdd7fdd22a521c452a4a Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Thu, 23 May 2024 14:06:18 +0300 Subject: [PATCH 1178/2849] net: dns: The DNS_EAI_ALLDONE is not an error If DNS_EAI_ALLDONE is returned, it indicates that the request was done and should not be considered an error. Signed-off-by: Jukka Rissanen --- subsys/net/lib/dns/resolve.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subsys/net/lib/dns/resolve.c b/subsys/net/lib/dns/resolve.c index 85bbf9a6feba0..9797fd54ada30 100644 --- a/subsys/net/lib/dns/resolve.c +++ b/subsys/net/lib/dns/resolve.c @@ -907,7 +907,7 @@ static void svc_handler(struct k_work *work) int ret; ret = recv_data(pev); - if (ret < 0) { + if (ret < 0 && ret != DNS_EAI_ALLDONE) { NET_ERR("DNS recv error (%d)", ret); } } From 5248657f57b3790d32f76977d2dba9e2152e4a75 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Thu, 23 May 2024 12:53:45 +0300 Subject: [PATCH 1179/2849] tests: net: dns_resolve: Fix resolver tests The compilation was failing if IPv4 was disabled. Also fix the IPv6 test so that they pass properly. Signed-off-by: Jukka Rissanen --- tests/net/lib/dns_resolve/src/main.c | 29 +++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/tests/net/lib/dns_resolve/src/main.c b/tests/net/lib/dns_resolve/src/main.c index 3d3bdcf9cf5f1..9d8696f545a59 100644 --- a/tests/net/lib/dns_resolve/src/main.c +++ b/tests/net/lib/dns_resolve/src/main.c @@ -69,6 +69,12 @@ static struct k_sem wait_data2; static uint16_t current_dns_id; static struct dns_addrinfo addrinfo; +#if defined(CONFIG_NET_IPV4) && defined(CONFIG_NET_IPV6) +#define EXPECTED_SERVER_COUNT CONFIG_DNS_RESOLVER_MAX_SERVERS +#else +#define EXPECTED_SERVER_COUNT (CONFIG_DNS_RESOLVER_MAX_SERVERS / 2) +#endif + /* this must be higher that the DNS_TIMEOUT */ #define WAIT_TIME K_MSEC(DNS_TIMEOUT + 300) @@ -104,6 +110,8 @@ static void net_iface_init(struct net_if *iface) net_if_set_link_addr(iface, mac, sizeof(struct net_eth_addr), NET_LINK_ETHERNET); + + net_if_flag_set(iface, NET_IF_IPV6_NO_ND); } static inline int get_slot_by_id(struct dns_resolve_context *ctx, @@ -343,7 +351,7 @@ ZTEST(dns_resolve, test_dns_query_server_count) struct dns_resolve_context *ctx = dns_resolve_get_default(); int i, count = 0; - for (i = 0; i < CONFIG_DNS_RESOLVER_MAX_SERVERS; i++) { + for (i = 0; i < EXPECTED_SERVER_COUNT; i++) { if (ctx->state != DNS_RESOLVE_CONTEXT_ACTIVE) { continue; } @@ -355,8 +363,9 @@ ZTEST(dns_resolve, test_dns_query_server_count) count++; } - zassert_equal(count, CONFIG_DNS_RESOLVER_MAX_SERVERS, - "Invalid number of servers"); + zassert_equal(count, EXPECTED_SERVER_COUNT, + "Invalid number of servers (%d vs %d)", + count, EXPECTED_SERVER_COUNT); } ZTEST(dns_resolve, test_dns_query_ipv4_server_count) @@ -364,6 +373,10 @@ ZTEST(dns_resolve, test_dns_query_ipv4_server_count) struct dns_resolve_context *ctx = dns_resolve_get_default(); int i, count = 0, port = 0; + if (!IS_ENABLED(CONFIG_NET_IPV4)) { + return; + } + for (i = 0; i < CONFIG_DNS_RESOLVER_MAX_SERVERS; i++) { if (ctx->state != DNS_RESOLVE_CONTEXT_ACTIVE) { continue; @@ -622,8 +635,7 @@ ZTEST(dns_resolve, test_dns_query_ipv4) } } -#if defined(TEMPORARILY_DISABLED_TEST) -static void test_dns_query_ipv6(void) +ZTEST(dns_resolve, test_dns_query_ipv6) { struct expected_status status = { .status1 = DNS_EAI_INPROGRESS, @@ -650,7 +662,6 @@ static void test_dns_query_ipv6(void) zassert_true(false, "Timeout while waiting data"); } } -#endif struct expected_addr_status { struct sockaddr addr; @@ -675,10 +686,12 @@ void dns_result_numeric_cb(enum dns_resolve_status status, } if (info && info->ai_family == AF_INET) { +#if defined(CONFIG_NET_IPV4) if (net_ipv4_addr_cmp(&net_sin(&info->ai_addr)->sin_addr, &my_addr2) != true) { zassert_true(false, "IPv4 address does not match"); } +#endif } if (info && info->ai_family == AF_INET6) { @@ -721,8 +734,7 @@ ZTEST(dns_resolve, test_dns_query_ipv4_numeric) } } -#if defined(TEMPORARILY_DISABLED_TEST) -static void test_dns_query_ipv6_numeric(void) +ZTEST(dns_resolve, test_dns_query_ipv6_numeric) { struct expected_addr_status status = { .status1 = DNS_EAI_INPROGRESS, @@ -749,6 +761,5 @@ static void test_dns_query_ipv6_numeric(void) zassert_true(false, "Timeout while waiting data"); } } -#endif ZTEST_SUITE(dns_resolve, NULL, test_init, NULL, NULL, NULL); From 81a3d764a097b6a4f1f91fc40570590c18c35b68 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Thu, 23 May 2024 14:33:09 +0300 Subject: [PATCH 1180/2849] doc: migration-guide-3.7: Add info for DNS resolver and responder Add information about DNS resolver and mDNS/LLMNR responders which are converted to use the socket services API. Signed-off-by: Jukka Rissanen --- doc/releases/migration-guide-3.7.rst | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/doc/releases/migration-guide-3.7.rst b/doc/releases/migration-guide-3.7.rst index 27834decc3fb1..fb7587ad1c587 100644 --- a/doc/releases/migration-guide-3.7.rst +++ b/doc/releases/migration-guide-3.7.rst @@ -470,6 +470,11 @@ Networking during a Coap Block-wise transfer. Any post write, validate or some firmware callbacks should be updated to include this parameter. (:github:`72590`) +* The DNS resolver and mDNS/LLMNR responders are converted to use socket service API. + This means that the number of pollable sockets in the system might need to be increased. + Please check that the values of :kconfig:option:`CONFIG_NET_SOCKETS_POLL_MAX` and + :kconfig:option:`CONFIG_POSIX_MAX_FDS` are high enough. Unfortunately no exact values + for these can be given as it depends on application needs and usage. (:github:`72834`) Other Subsystems From 631c0a3aab69a6bb8bde0d3d86b47794e783975e Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Thu, 23 May 2024 16:41:51 +0300 Subject: [PATCH 1181/2849] net: doc: socket_select.h: Document zsock_fd_set This fix avoids this warning: WARNING:root:Unused expression: \ .*Duplicate C declaration.*\n.*'\.\. c:.*:: zsock_fd_set'.* Signed-off-by: Jukka Rissanen --- include/zephyr/net/socket_select.h | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/include/zephyr/net/socket_select.h b/include/zephyr/net/socket_select.h index d4cfef32cbcd9..89a59aebc5e4f 100644 --- a/include/zephyr/net/socket_select.h +++ b/include/zephyr/net/socket_select.h @@ -26,14 +26,11 @@ extern "C" { #endif -/** @cond INTERNAL_HIDDEN */ - +/** Socket file descriptor set. */ 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 * From ee6805d3e08bc95864c7f6572f3b62a11cc4ed6c Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Thu, 23 May 2024 17:04:27 +0300 Subject: [PATCH 1182/2849] net: dns: resolver: No need to double the socket count The socket allocation count was incorrectly calculated as we have only one socket per DNS server. Signed-off-by: Jukka Rissanen --- include/zephyr/net/dns_resolve.h | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/include/zephyr/net/dns_resolve.h b/include/zephyr/net/dns_resolve.h index fff5d4ad867d8..f68a15e669789 100644 --- a/include/zephyr/net/dns_resolve.h +++ b/include/zephyr/net/dns_resolve.h @@ -193,11 +193,7 @@ struct dns_resolve_context { } 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 +#define DNS_RESOLVER_MAX_POLL (CONFIG_DNS_RESOLVER_MAX_SERVERS + DNS_MAX_MCAST_SERVERS) /** Socket polling for each server connection */ struct zsock_pollfd fds[DNS_RESOLVER_MAX_POLL]; /** @endcond */ From 2a16f4d2bca8a1388a14517aa7643d52bf0d7d3e Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Thu, 23 May 2024 17:08:05 +0300 Subject: [PATCH 1183/2849] net: dns: responder: No need to double the socket count The socket allocation count was incorrectly calculated as we have only one socket per listened port. Signed-off-by: Jukka Rissanen --- subsys/net/lib/dns/mdns_responder.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/subsys/net/lib/dns/mdns_responder.c b/subsys/net/lib/dns/mdns_responder.c index e92db7dd57b45..ab4e8e45bf6c7 100644 --- a/subsys/net/lib/dns/mdns_responder.c +++ b/subsys/net/lib/dns/mdns_responder.c @@ -65,11 +65,7 @@ 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 +#define MDNS_MAX_POLL (MAX_IPV4_IFACE_COUNT + MAX_IPV6_IFACE_COUNT) static void svc_handler(struct k_work *work); NET_SOCKET_SERVICE_SYNC_DEFINE_STATIC(svc_mdns, NULL, svc_handler, MDNS_MAX_POLL); From 3122296e1c9db2b76752c4a45d92361cb92928a3 Mon Sep 17 00:00:00 2001 From: Andries Kruithof Date: Mon, 20 May 2024 09:09:32 +0200 Subject: [PATCH 1184/2849] Bluetooth: CAP: fix bug in reception start The wrong number of subgroups was used in copying subgroups Signed-off-by: Andries Kruithof --- 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 80fd66c103afc..4da4410ed523e 100644 --- a/subsys/bluetooth/audio/cap_commander.c +++ b/subsys/bluetooth/audio/cap_commander.c @@ -358,7 +358,7 @@ int bt_cap_commander_broadcast_reception_start( 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); + sizeof(struct bt_bap_bass_subgroup) * member_param->num_subgroups); } active_proc->proc_initiated_cnt++; From 3ad57e30301a4b6e3475da5bd1d6f1e7682287bb Mon Sep 17 00:00:00 2001 From: Joakim Andersson Date: Wed, 15 May 2024 16:56:24 +0200 Subject: [PATCH 1185/2849] drivers: spi_bitbang: Fix timing in SPI bitbang driver Fix timing in SPI bitbang driver. The issue occurs with CPHA=1 when the input data is changed immediately after the clock shift on the last bit of the read. Because we read the input bit after changing the clock, this bit becomes invalid. Instead of doing wait, clock-change, read. Do wait, read, clock-change. Signed-off-by: Joakim Andersson --- drivers/spi/spi_bitbang.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/spi/spi_bitbang.c b/drivers/spi/spi_bitbang.c index cffd25abd9a0a..15ab576a139a8 100644 --- a/drivers/spi/spi_bitbang.c +++ b/drivers/spi/spi_bitbang.c @@ -177,22 +177,22 @@ static int spi_bitbang_transceive(const struct device *dev, k_busy_wait(wait_us); - /* first clock edge */ - gpio_pin_set_dt(&info->clk_gpio, !clock_state); - if (!loop && do_read && !cpha) { b = gpio_pin_get_dt(miso); } - k_busy_wait(wait_us); + /* first (leading) clock edge */ + gpio_pin_set_dt(&info->clk_gpio, !clock_state); - /* second clock edge */ - gpio_pin_set_dt(&info->clk_gpio, clock_state); + k_busy_wait(wait_us); if (!loop && do_read && cpha) { b = gpio_pin_get_dt(miso); } + /* second (trailing) clock edge */ + gpio_pin_set_dt(&info->clk_gpio, clock_state); + if (loop) { b = d; } From 1784446c8d07150f55b0badf539af37d9e2b847d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mo=C5=84?= Date: Tue, 21 May 2024 14:20:46 +0200 Subject: [PATCH 1186/2849] usb: device_next: Fix string descriptors response MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit 2f31ee63b5c5 ("usb: device_next: convert ASCII7 strings to UTF16LE on the fly") made string descriptors respond with twice as much of the actual string data. Fix the issue by taking into account that USB string descriptor length is already multiplied by two. Additionally, make it possible to return odd number of bytes if host requested so. Signed-off-by: Tomasz Moń --- subsys/usb/device_next/usbd_ch9.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/subsys/usb/device_next/usbd_ch9.c b/subsys/usb/device_next/usbd_ch9.c index 8e7db0b756e77..0553c16dcf8f1 100644 --- a/subsys/usb/device_next/usbd_ch9.c +++ b/subsys/usb/device_next/usbd_ch9.c @@ -563,6 +563,7 @@ static void string_ascii7_to_utf16le(struct usbd_desc_node *const dn, }; uint8_t *ascii7_str; size_t len; + size_t i; if (dn->str.utype == USBD_DUT_STRING_SERIAL_NUMBER && dn->str.use_hwinfo) { ssize_t hwid_len = get_sn_from_hwid(hwid_sn); @@ -575,7 +576,7 @@ static void string_ascii7_to_utf16le(struct usbd_desc_node *const dn, head.bLength = sizeof(head) + hwid_len * 2; ascii7_str = hwid_sn; } else { - head.bLength = dn->bLength, + head.bLength = dn->bLength; ascii7_str = (uint8_t *)dn->ptr; } @@ -588,12 +589,16 @@ static void string_ascii7_to_utf16le(struct usbd_desc_node *const dn, net_buf_add_mem(buf, &head, MIN(len, sizeof(head))); len -= MIN(len, sizeof(head)); - for (size_t i = 0; i < len; i++) { + for (i = 0; i < len / 2; 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]); } + + if (len & 1) { + net_buf_add_u8(buf, ascii7_str[i]); + } } static int sreq_get_desc_dev(struct usbd_contex *const uds_ctx, From c30ac4dfd88b730a13161185a3d478ddf9355f9f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mo=C5=84?= Date: Fri, 24 May 2024 08:50:31 +0200 Subject: [PATCH 1187/2849] usb: device_next: CDC ACM: Process TX on configuration enable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If CDC ACM uart side has TX enabled when the configuration gets enabled, depending on fifo state following has to happen: * if the fifo is empty - trigger TX ready interrupt * if the fifo is not empty - queue TX data on IN endpoint Signed-off-by: Tomasz Moń --- subsys/usb/device_next/class/usbd_cdc_acm.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/subsys/usb/device_next/class/usbd_cdc_acm.c b/subsys/usb/device_next/class/usbd_cdc_acm.c index 838550f18dd71..453759d55a55f 100644 --- a/subsys/usb/device_next/class/usbd_cdc_acm.c +++ b/subsys/usb/device_next/class/usbd_cdc_acm.c @@ -268,7 +268,13 @@ static void usbd_cdc_acm_enable(struct usbd_class_data *const c_data) } if (atomic_test_bit(&data->state, CDC_ACM_IRQ_TX_ENABLED)) { - /* TODO */ + if (ring_buf_is_empty(data->tx_fifo.rb)) { + /* Raise TX ready interrupt */ + cdc_acm_work_submit(&data->irq_cb_work); + } else { + /* Queue pending TX data on IN endpoint */ + cdc_acm_work_submit(&data->tx_fifo_work); + } } } From 809c6c34d376d8dd91822f5cda93bc5f23c52fdc Mon Sep 17 00:00:00 2001 From: Marcin Szymczyk Date: Wed, 22 May 2024 13:35:29 +0200 Subject: [PATCH 1188/2849] tests: drivers: timer: nrf_grtc_timer: add nRF54L15 FLPR to targets Allow testing FLPR with this testcase. Signed-off-by: Marcin Szymczyk --- tests/drivers/timer/nrf_grtc_timer/testcase.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/drivers/timer/nrf_grtc_timer/testcase.yaml b/tests/drivers/timer/nrf_grtc_timer/testcase.yaml index 00ac1ed584b1b..e81a37cbd2a81 100644 --- a/tests/drivers/timer/nrf_grtc_timer/testcase.yaml +++ b/tests/drivers/timer/nrf_grtc_timer/testcase.yaml @@ -3,5 +3,6 @@ tests: tags: drivers platform_allow: - nrf54l15pdk/nrf54l15/cpuapp + - nrf54l15pdk/nrf54l15/cpuflpr - nrf54h20dk/nrf54h20/cpuapp - nrf54h20dk/nrf54h20/cpurad From e65c6328ce32195296ef4138f19e38c0be26ef45 Mon Sep 17 00:00:00 2001 From: Torsten Rasmussen Date: Thu, 23 May 2024 14:37:09 +0200 Subject: [PATCH 1189/2849] sysbuild: use ARGN instead of ARGV1 Use of ARGV1 is undefined when number of arguments to function is less than 2. Therefore switch to ARGN which holds arguments beyond required arguments. If there are no optional arguments, then ARGN is just an empty list, thus making it safe to use. Signed-off-by: Torsten Rasmussen --- 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 ce0af2fe7b339..acbc5706e69fd 100644 --- a/share/sysbuild/cmake/modules/sysbuild_extensions.cmake +++ b/share/sysbuild/cmake/modules/sysbuild_extensions.cmake @@ -661,7 +661,7 @@ function(sysbuild_add_subdirectory source_dir) " (expected at most 2, got ${ARGC})" ) endif() - set(binary_dir ${ARGV1}) + set(binary_dir ${ARGN}) # Update SYSBUILD_CURRENT_SOURCE_DIR in this scope, to support nesting # of sysbuild_add_subdirectory() and even regular add_subdirectory(). From fc1884ecf59000aa6e4a40bb4bd772bd5e947415 Mon Sep 17 00:00:00 2001 From: Torsten Rasmussen Date: Fri, 17 May 2024 10:26:44 +0200 Subject: [PATCH 1190/2849] sysbuild: support sysbuild/CMakeLists.txt as entry point for samples This commit refactors sysbuild entry code by creating a CMake sysbuild module for image processing and place sysbuild entry code in a /sysbuild/CMakeLists.txt file. A template/CMakeLists.txt file will be use as template for applications which doesn't provide their own entry file. An application may create a sysbuild/CMakeLists.txt file. The sysbuild/CMakeLists.txt file is similar in nature to the toplevel CMakeLists.txt file but intended to used by sysbuild. This allows application developers to adjust how an application is built with sysbuild. Signed-off-by: Torsten Rasmussen --- .../cmake/SysbuildConfig.cmake | 9 +++++ .../cmake/SysbuildConfigVersion.cmake | 5 +++ share/sysbuild/CMakeLists.txt | 40 ++++--------------- .../cmake/modules/sysbuild_default.cmake | 19 +++++++++ .../cmake/modules/sysbuild_images.cmake | 27 +++++++++++++ .../cmake/modules/sysbuild_kconfig.cmake | 2 +- share/sysbuild/template/CMakeLists.txt | 12 ++++++ 7 files changed, 80 insertions(+), 34 deletions(-) create mode 100644 share/sysbuild-package/cmake/SysbuildConfig.cmake create mode 100644 share/sysbuild-package/cmake/SysbuildConfigVersion.cmake create mode 100644 share/sysbuild/cmake/modules/sysbuild_default.cmake create mode 100644 share/sysbuild/cmake/modules/sysbuild_images.cmake create mode 100644 share/sysbuild/template/CMakeLists.txt diff --git a/share/sysbuild-package/cmake/SysbuildConfig.cmake b/share/sysbuild-package/cmake/SysbuildConfig.cmake new file mode 100644 index 0000000000000..37343583bd80c --- /dev/null +++ b/share/sysbuild-package/cmake/SysbuildConfig.cmake @@ -0,0 +1,9 @@ +# SPDX-License-Identifier: Apache-2.0 + +if(Sysbuild_FIND_COMPONENTS) + set(Zephyr_FIND_COMPONENTS ${Sysbuild_FIND_COMPONENTS}) +else() + set(Zephyr_FIND_COMPONENTS sysbuild_default) +endif() +include(${CMAKE_CURRENT_LIST_DIR}/../../zephyr-package/cmake/ZephyrConfig.cmake) +set(Sysbuild_FOUND True) diff --git a/share/sysbuild-package/cmake/SysbuildConfigVersion.cmake b/share/sysbuild-package/cmake/SysbuildConfigVersion.cmake new file mode 100644 index 0000000000000..1dede077c1d16 --- /dev/null +++ b/share/sysbuild-package/cmake/SysbuildConfigVersion.cmake @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: Apache-2.0 + +include(${CMAKE_CURRENT_LIST_DIR}/../../zephyr-package/cmake/ZephyrConfigVersion.cmake) +list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}/../../sysbuild/cmake/modules) +set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} PARENT_SCOPE) diff --git a/share/sysbuild/CMakeLists.txt b/share/sysbuild/CMakeLists.txt index 4a6fde214d511..f4d5178448b29 100644 --- a/share/sysbuild/CMakeLists.txt +++ b/share/sysbuild/CMakeLists.txt @@ -12,38 +12,12 @@ endif() # If APP_DIR is a relative path, then CMake will adjust to absolute path based # on current working dir. set(APP_DIR ${APP_DIR} CACHE PATH "Main Application Source Directory") +set(Sysbuild_DIR ${CMAKE_CURRENT_LIST_DIR}/../sysbuild-package/cmake) -# Add sysbuild/cmake/modules to CMAKE_MODULE_PATH which allows us to integrate -# sysbuild CMake modules with general Zephyr CMake modules. -list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}/cmake/modules) -# List of Zephyr and sysbuild CMake modules we need for sysbuild. -# Note: sysbuild_kconfig will internally load kconfig CMake module. -set(zephyr_modules extensions - sysbuild_extensions python west root zephyr_module boards shields hwm_v2 - sysbuild_kconfig native_simulator_sb_extensions - ) +project(sysbuild_toplevel LANGUAGES) -find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE} COMPONENTS ${zephyr_modules}) - -project(sysbuild LANGUAGES) - -get_filename_component(APP_DIR ${APP_DIR} ABSOLUTE) -get_filename_component(app_name ${APP_DIR} NAME) -set(DEFAULT_IMAGE "${app_name}") - -# This is where all Zephyr applications are added to the multi-image build. -sysbuild_add_subdirectory(images) - -get_property(IMAGES GLOBAL PROPERTY sysbuild_images) -sysbuild_module_call(PRE_CMAKE MODULES ${SYSBUILD_MODULE_NAMES} IMAGES ${IMAGES}) -sysbuild_images_order(IMAGES_CONFIGURATION_ORDER CONFIGURE IMAGES ${IMAGES}) -foreach(image ${IMAGES_CONFIGURATION_ORDER}) - sysbuild_module_call(PRE_IMAGE_CMAKE MODULES ${SYSBUILD_MODULE_NAMES} IMAGES ${IMAGES} IMAGE ${image}) - ExternalZephyrProject_Cmake(APPLICATION ${image}) - sysbuild_module_call(POST_IMAGE_CMAKE MODULES ${SYSBUILD_MODULE_NAMES} IMAGES ${IMAGES} IMAGE ${image}) -endforeach() -sysbuild_module_call(POST_CMAKE MODULES ${SYSBUILD_MODULE_NAMES} IMAGES ${IMAGES}) - -sysbuild_module_call(PRE_DOMAINS MODULES ${SYSBUILD_MODULE_NAMES} IMAGES ${IMAGES}) -include(cmake/domains.cmake) -sysbuild_module_call(POST_DOMAINS MODULES ${SYSBUILD_MODULE_NAMES} IMAGES ${IMAGES}) +if(EXISTS ${APP_DIR}/sysbuild/CMakeLists.txt) + add_subdirectory(${APP_DIR}/sysbuild sysbuild/application) +else() + add_subdirectory(template sysbuild/application) +endif() diff --git a/share/sysbuild/cmake/modules/sysbuild_default.cmake b/share/sysbuild/cmake/modules/sysbuild_default.cmake new file mode 100644 index 0000000000000..6bcf714de952c --- /dev/null +++ b/share/sysbuild/cmake/modules/sysbuild_default.cmake @@ -0,0 +1,19 @@ +# Copyright (c) 2024 Nordic Semiconductor +# +# SPDX-License-Identifier: Apache-2.0 + +# +# Sysbuild default list of CMake modules to include in a regular sysbuild session. +# +include(extensions) +include(sysbuild_extensions) +include(python) +include(west) +include(root) +include(zephyr_module) +include(boards) +include(shields) +include(hwm_v2) +include(sysbuild_kconfig) +include(native_simulator_sb_extensions) +include(sysbuild_images) diff --git a/share/sysbuild/cmake/modules/sysbuild_images.cmake b/share/sysbuild/cmake/modules/sysbuild_images.cmake new file mode 100644 index 0000000000000..eb73ec994483f --- /dev/null +++ b/share/sysbuild/cmake/modules/sysbuild_images.cmake @@ -0,0 +1,27 @@ +# Copyright (c) 2024 Nordic Semiconductor +# +# SPDX-License-Identifier: Apache-2.0 + +# This module is responsible for including images into sysbuild and to call +# pre and post hooks. + +get_filename_component(APP_DIR ${APP_DIR} ABSOLUTE) +get_filename_component(app_name ${APP_DIR} NAME) +set(DEFAULT_IMAGE "${app_name}") + +# This is where all Zephyr applications are added to the multi-image build. +sysbuild_add_subdirectory(${sysbuild_toplevel_SOURCE_DIR}/images sysbuild/images) + +get_property(IMAGES GLOBAL PROPERTY sysbuild_images) +sysbuild_module_call(PRE_CMAKE MODULES ${SYSBUILD_MODULE_NAMES} IMAGES ${IMAGES}) +sysbuild_images_order(IMAGES_CONFIGURATION_ORDER CONFIGURE IMAGES ${IMAGES}) +foreach(image ${IMAGES_CONFIGURATION_ORDER}) + sysbuild_module_call(PRE_IMAGE_CMAKE MODULES ${SYSBUILD_MODULE_NAMES} IMAGES ${IMAGES} IMAGE ${image}) + ExternalZephyrProject_Cmake(APPLICATION ${image}) + sysbuild_module_call(POST_IMAGE_CMAKE MODULES ${SYSBUILD_MODULE_NAMES} IMAGES ${IMAGES} IMAGE ${image}) +endforeach() +sysbuild_module_call(POST_CMAKE MODULES ${SYSBUILD_MODULE_NAMES} IMAGES ${IMAGES}) + +sysbuild_module_call(PRE_DOMAINS MODULES ${SYSBUILD_MODULE_NAMES} IMAGES ${IMAGES}) +include(${sysbuild_toplevel_SOURCE_DIR}/cmake/domains.cmake) +sysbuild_module_call(POST_DOMAINS MODULES ${SYSBUILD_MODULE_NAMES} IMAGES ${IMAGES}) diff --git a/share/sysbuild/cmake/modules/sysbuild_kconfig.cmake b/share/sysbuild/cmake/modules/sysbuild_kconfig.cmake index d18b5b7978d02..531e670dbc9f7 100644 --- a/share/sysbuild/cmake/modules/sysbuild_kconfig.cmake +++ b/share/sysbuild/cmake/modules/sysbuild_kconfig.cmake @@ -56,7 +56,7 @@ endif() # Empty files to make kconfig.py happy. file(TOUCH ${CMAKE_CURRENT_BINARY_DIR}/empty.conf) -set(APPLICATION_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}) +set(APPLICATION_SOURCE_DIR ${sysbuild_toplevel_SOURCE_DIR}) set(AUTOCONF_H ${CMAKE_CURRENT_BINARY_DIR}/autoconf.h) set(CONF_FILE ${SB_CONF_FILE}) set(EXTRA_CONF_FILE "${SB_EXTRA_CONF_FILE}") diff --git a/share/sysbuild/template/CMakeLists.txt b/share/sysbuild/template/CMakeLists.txt new file mode 100644 index 0000000000000..fc348a8dafb2e --- /dev/null +++ b/share/sysbuild/template/CMakeLists.txt @@ -0,0 +1,12 @@ +# Copyright (c) 2024 Nordic Semiconductor +# +# SPDX-License-Identifier: Apache-2.0 + +# Generic sysbuild CMakeLists.txt file used as sysbuild entry point for multi-image builds. +# +# Applications which requires custom handling when built using sysbuild may copy this +# file to the folder `/sysbuild` and use as a template and extend as needed. + +find_package(Sysbuild REQUIRED HINTS $ENV{ZEPHYR_BASE}) + +project(sysbuild LANGUAGES) From 2b427f19d512acedaf32ffab074aeb0996891576 Mon Sep 17 00:00:00 2001 From: Torsten Rasmussen Date: Fri, 17 May 2024 11:27:40 +0200 Subject: [PATCH 1191/2849] sysbuild: add support for APPLICATION_CONFIG_DIR in sysbuild APPLICATION_CONFIG_DIR is supported in Zephyr and allows to adjust the location from which prj.conf and friends are picked up. This also works for images when using sysbuild, however sysbuild itself ignores the value of APPLICATION_CONFIG_DIR, meaning that sysbuild only accepts sysbuild.conf located directly in the sample folder. Extend sysbuild to support APPLICATION_CONFIG_DIR so sysbuild follows regular Zephyr CMake behavior. Introduce SB_APPLICATION_CONFIG_DIR to allow changing the location for sysbuild only, without propagating the value to images. Signed-off-by: Torsten Rasmussen --- .../cmake/modules/sysbuild_kconfig.cmake | 26 ++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/share/sysbuild/cmake/modules/sysbuild_kconfig.cmake b/share/sysbuild/cmake/modules/sysbuild_kconfig.cmake index 531e670dbc9f7..6d55e8c8997d0 100644 --- a/share/sysbuild/cmake/modules/sysbuild_kconfig.cmake +++ b/share/sysbuild/cmake/modules/sysbuild_kconfig.cmake @@ -13,13 +13,37 @@ set(EXTRA_KCONFIG_TARGET_COMMAND_FOR_sysbuild_guiconfig set(KCONFIG_TARGETS sysbuild_menuconfig sysbuild_guiconfig) list(TRANSFORM EXTRA_KCONFIG_TARGETS PREPEND "sysbuild_") +if(DEFINED APPLICATION_CONFIG_DIR AND NOT DEFINED CACHE{APPLICATION_CONFIG_DIR}) + set(APPLICATION_CONFIG_DIR "${APPLICATION_CONFIG_DIR}" CACHE INTERNAL "Application config dir") +elseif(DEFINED CACHE{APPLICATION_CONFIG_DIR} AND + NOT (APPLICATION_CONFIG_DIR STREQUAL "$CACHE{APPLICATION_CONFIG_DIR}")) + message(WARNING + "Sysbuild scoped APPLICATION_CONFIG_DIR and cached APPLICATION_CONFIG_DIR differs.\n" + "Setting value used internally by Sysbuild (sysbuild scoped):\n" + " - ${APPLICATION_CONFIG_DIR}\n" + "Setting value used by images (cached):\n" + " - $CACHE{APPLICATION_CONFIG_DIR}\n" + ) +endif() + +# If there is a dedicated SB_APPLICATION_CONFIG_DIR, then create a local +# scoped APPLICATION_CONFIG_DIR hiding any cache variant. +# The cache setting is the setting passed to sysbuild image cache files +if(DEFINED SB_APPLICATION_CONFIG_DIR) + set(APPLICATION_CONFIG_DIR ${SB_APPLICATION_CONFIG_DIR}) +elseif(NOT DEFINED APPLICATION_CONFIG_DIR) + get_filename_component(APP_DIR ${APP_DIR} ABSOLUTE) + set(APPLICATION_CONFIG_DIR ${APP_DIR}) +endif() +string(CONFIGURE ${APPLICATION_CONFIG_DIR} APPLICATION_CONFIG_DIR) + if(DEFINED SB_CONF_FILE) # SB_CONF_FILE already set so nothing to do. elseif(DEFINED ENV{SB_CONF_FILE}) set(SB_CONF_FILE $ENV{SB_CONF_FILE}) else() # sysbuild.conf is an optional file, because sysbuild is an opt-in feature. - zephyr_file(CONF_FILES ${APP_DIR} KCONF SB_CONF_FILE NAMES "sysbuild.conf" SUFFIX ${FILE_SUFFIX}) + zephyr_file(CONF_FILES ${APPLICATION_CONFIG_DIR} KCONF SB_CONF_FILE NAMES "sysbuild.conf" SUFFIX ${FILE_SUFFIX}) endif() if(NOT DEFINED SB_EXTRA_CONF_FILE AND DEFINED SB_OVERLAY_CONFIG) From 64de50f05235e5e681810510edbf8694e2b6a482 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Karol=20Laso=C5=84czyk?= Date: Tue, 21 May 2024 13:03:35 +0200 Subject: [PATCH 1192/2849] manifest: Update hal_nordic MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds 8bit support in SAADC hal. Signed-off-by: Karol Lasończyk --- west.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/west.yml b/west.yml index a89b3c29c826d..1dc935a9e955c 100644 --- a/west.yml +++ b/west.yml @@ -183,7 +183,7 @@ manifest: groups: - hal - name: hal_nordic - revision: a3aacc7e43dec644a9ddfee4aa578a4f8ff54610 + revision: 1a3e9f3a85ea34054811e4d9e5c5e5f8f751795b path: modules/hal/nordic groups: - hal From 641b77b740adc95f4c7d5bb7c642c0e78ae91847 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Mon, 27 May 2024 11:14:20 +0300 Subject: [PATCH 1193/2849] Bluetooth: samples: hci_ipc: Fix incorrect NULL pointer check The condition was the inverse of what it should have been, leading to an inevitable NULL pointer dereference later. Signed-off-by: Johan Hedberg --- samples/bluetooth/hci_ipc/src/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/bluetooth/hci_ipc/src/main.c b/samples/bluetooth/hci_ipc/src/main.c index 5f0614139be7a..814001646e46c 100644 --- a/samples/bluetooth/hci_ipc/src/main.c +++ b/samples/bluetooth/hci_ipc/src/main.c @@ -294,7 +294,7 @@ void bt_ctlr_assert_handle(char *file, uint32_t line) struct net_buf *buf; buf = hci_vs_err_assert(file, line); - if (buf == NULL) { + if (buf != NULL) { /* Send the event over ipc */ hci_ipc_send(buf, HCI_FATAL_ERR_MSG); } else { From 58cb4557f02eeedaad1d61f8fa4f88b488b20c2b Mon Sep 17 00:00:00 2001 From: Reto Schneider Date: Sun, 26 May 2024 16:01:34 +0200 Subject: [PATCH 1194/2849] net: ppp: Optimize memory allocation net_pkt_alloc_buffer() deducts the free space from the requested number of bytes. As ppp_save_byte() calls net_pkt_alloc_buffer() when the packet has one byte available still, this causes all but the first net_buf in the packet to be of size CONFIG_NET_BUF_DATA_SIZE - 1. Consequences: - With CONFIG_NET_BUF_FIXED_DATA_SIZE enabled, one byte per net_buf gets wasted. - CONFIG_NET_BUF_DATA_SIZE has typically an even, likely even a power of two value. Using exactly one byte less per buffer causes operations that require aligned memory (e.g. DMA) to become inefficient or to not work at all. Signed-off-by: Reto Schneider --- drivers/net/ppp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ppp.c b/drivers/net/ppp.c index 7904612b9a4e7..014da86ada620 100644 --- a/drivers/net/ppp.c +++ b/drivers/net/ppp.c @@ -326,7 +326,7 @@ static int ppp_save_byte(struct ppp_driver_context *ppp, uint8_t byte) */ if (ppp->available == 1) { ret = net_pkt_alloc_buffer(ppp->pkt, - CONFIG_NET_BUF_DATA_SIZE, + CONFIG_NET_BUF_DATA_SIZE + ppp->available, AF_UNSPEC, K_NO_WAIT); if (ret < 0) { LOG_ERR("[%p] cannot allocate new data buffer", ppp); From 8999446ab81a479fd74d6dab329a65c653c47f3c Mon Sep 17 00:00:00 2001 From: Marcin Szymczyk Date: Thu, 23 May 2024 16:43:18 +0200 Subject: [PATCH 1195/2849] tests: kernel: gen_isr_table: add support for nRF54L15 FLPR Align testcase to nRF54L15 FLPR. Follow up of #71948. Signed-off-by: Marcin Szymczyk --- tests/kernel/gen_isr_table/src/main.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/tests/kernel/gen_isr_table/src/main.c b/tests/kernel/gen_isr_table/src/main.c index b71b47dafbca0..492bca186bf0a 100644 --- a/tests/kernel/gen_isr_table/src/main.c +++ b/tests/kernel/gen_isr_table/src/main.c @@ -20,7 +20,12 @@ extern uint32_t _irq_vector_table[]; #endif #if defined(CONFIG_RISCV) -#if defined(CONFIG_RISCV_HAS_CLIC) +#if defined(CONFIG_NRFX_CLIC) +#define ISR1_OFFSET 15 +#define ISR3_OFFSET 16 +#define ISR5_OFFSET 17 +#define TRIG_CHECK_SIZE 18 +#elif defined(CONFIG_RISCV_HAS_CLIC) #define ISR1_OFFSET 3 #define ISR3_OFFSET 17 #define ISR5_OFFSET 18 @@ -42,7 +47,12 @@ extern uint32_t _irq_vector_table[]; #endif #define IRQ_LINE(offset) offset +#if defined(CONFIG_RISCV_RESERVED_IRQ_ISR_TABLES_OFFSET) +#define TABLE_INDEX(offset) offset + CONFIG_RISCV_RESERVED_IRQ_ISR_TABLES_OFFSET +#else #define TABLE_INDEX(offset) offset +#endif + #else #define ISR1_OFFSET 0 #define ISR2_OFFSET 1 From 3b0a7dedb0da346ce64bd812961a57fb0e46ff50 Mon Sep 17 00:00:00 2001 From: Noah Pendleton Date: Fri, 24 May 2024 10:56:18 -0400 Subject: [PATCH 1196/2849] samples: sensors: nucleo_f756zg added to die_temp_polling Added board overlay file to permit internal temperature sensor testing: - `nucleo_f756zg` Signed-off-by: Noah Pendleton --- .../boards/nucleo_f756zg.overlay | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 samples/sensor/die_temp_polling/boards/nucleo_f756zg.overlay diff --git a/samples/sensor/die_temp_polling/boards/nucleo_f756zg.overlay b/samples/sensor/die_temp_polling/boards/nucleo_f756zg.overlay new file mode 100644 index 0000000000000..296fa3c6aef0f --- /dev/null +++ b/samples/sensor/die_temp_polling/boards/nucleo_f756zg.overlay @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2024 Noah Pendleton + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + aliases { + die-temp0 = &die_temp; + }; +}; + +&die_temp { + status = "okay"; +}; + +&adc1 { + pinctrl-0 = <&adc1_in0_pa0>; + pinctrl-names = "default"; + st,adc-prescaler = <4>; + status = "okay"; +}; From 0620cd9912cbe664b0dd51112be2ca9d4cbaa17d Mon Sep 17 00:00:00 2001 From: Erwan Gouriou Date: Thu, 23 May 2024 15:23:21 +0200 Subject: [PATCH 1197/2849] soc: stm32: common: Fix Kconfig symbol usage These symbols don't exist. Signed-off-by: Erwan Gouriou --- soc/st/stm32/common/soc_config.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/soc/st/stm32/common/soc_config.c b/soc/st/stm32/common/soc_config.c index a791f334be453..091937602ae03 100644 --- a/soc/st/stm32/common/soc_config.c +++ b/soc/st/stm32/common/soc_config.c @@ -68,15 +68,15 @@ static int st_stm32_common_config(void) #if defined(CONFIG_SOC_SERIES_STM32H7X) || defined(CONFIG_SOC_SERIES_STM32MP1X) HAL_EnableDBGStopMode(); #else /* CONFIG_SOC_SERIES_STM32H7X || CONFIG_SOC_SERIES_STM32MP1X */ -#if defined(SOC_SERIES_STM32G0X) || defined(SOC_SERIES_STM32C0X) +#if defined(CONFIG_SOC_SERIES_STM32G0X) || defined(CONFIG_SOC_SERIES_STM32C0X) LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_DBGMCU); LL_DBGMCU_EnableDBGStopMode(); LL_APB1_GRP1_DisableClock(LL_APB1_GRP1_PERIPH_DBGMCU); -#elif defined(SOC_SERIES_STM32F0X) +#elif defined(CONFIG_SOC_SERIES_STM32F0X) LL_APB1_GRP2_EnableClock(LL_APB1_GRP2_PERIPH_DBGMCU); LL_DBGMCU_EnableDBGStopMode(); LL_APB1_GRP2_DisableClock(LL_APB1_GRP2_PERIPH_DBGMCU); -#elif defined(SOC_SERIES_STM32L0X) +#elif defined(CONFIG_SOC_SERIES_STM32L0X) LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_DBGMCU); LL_DBGMCU_EnableDBGStopMode(); LL_APB2_GRP1_DisableClock(LL_APB2_GRP1_PERIPH_DBGMCU); @@ -91,15 +91,15 @@ static int st_stm32_common_config(void) #if defined(CONFIG_SOC_SERIES_STM32H7X) || defined(CONFIG_SOC_SERIES_STM32MP1X) HAL_DisableDBGStopMode(); #else /* CONFIG_SOC_SERIES_STM32H7X || CONFIG_SOC_SERIES_STM32MP1X */ -#if defined(SOC_SERIES_STM32G0X) || defined(SOC_SERIES_STM32C0X) +#if defined(CONFIG_SOC_SERIES_STM32G0X) || defined(CONFIG_SOC_SERIES_STM32C0X) LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_DBGMCU); LL_DBGMCU_DisableDBGStopMode(); LL_APB1_GRP1_DisableClock(LL_APB1_GRP1_PERIPH_DBGMCU); -#elif defined(SOC_SERIES_STM32F0X) +#elif defined(CONFIG_SOC_SERIES_STM32F0X) LL_APB1_GRP2_EnableClock(LL_APB1_GRP2_PERIPH_DBGMCU); LL_DBGMCU_DisableDBGStopMode(); LL_APB1_GRP2_DisableClock(LL_APB1_GRP2_PERIPH_DBGMCU); -#elif defined(SOC_SERIES_STM32L0X) +#elif defined(CONFIG_SOC_SERIES_STM32L0X) LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_DBGMCU); LL_DBGMCU_DisableDBGStopMode(); LL_APB2_GRP1_DisableClock(LL_APB2_GRP1_PERIPH_DBGMCU); From 101f791994f70027e7bc1046cf3f1e5e941bd19f Mon Sep 17 00:00:00 2001 From: Erwan Gouriou Date: Thu, 23 May 2024 15:33:44 +0200 Subject: [PATCH 1198/2849] soc: stm32: common: Fix proprocessor if/else flow No reason to be more complex than it should be. Signed-off-by: Erwan Gouriou --- soc/st/stm32/common/soc_config.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/soc/st/stm32/common/soc_config.c b/soc/st/stm32/common/soc_config.c index 091937602ae03..f5e65a146cc9c 100644 --- a/soc/st/stm32/common/soc_config.c +++ b/soc/st/stm32/common/soc_config.c @@ -67,8 +67,7 @@ static int st_stm32_common_config(void) #if defined(CONFIG_SOC_SERIES_STM32H7X) || defined(CONFIG_SOC_SERIES_STM32MP1X) HAL_EnableDBGStopMode(); -#else /* CONFIG_SOC_SERIES_STM32H7X || CONFIG_SOC_SERIES_STM32MP1X */ -#if defined(CONFIG_SOC_SERIES_STM32G0X) || defined(CONFIG_SOC_SERIES_STM32C0X) +#elif defined(CONFIG_SOC_SERIES_STM32G0X) || defined(CONFIG_SOC_SERIES_STM32C0X) LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_DBGMCU); LL_DBGMCU_EnableDBGStopMode(); LL_APB1_GRP1_DisableClock(LL_APB1_GRP1_PERIPH_DBGMCU); @@ -83,15 +82,13 @@ static int st_stm32_common_config(void) #else /* all other parts */ LL_DBGMCU_EnableDBGStopMode(); #endif -#endif /* CONFIG_SOC_SERIES_STM32H7X || CONFIG_SOC_SERIES_STM32MP1X */ #else /* keeping in mind that debugging draws a lot of power we explcitly disable when not needed */ #if defined(CONFIG_SOC_SERIES_STM32H7X) || defined(CONFIG_SOC_SERIES_STM32MP1X) HAL_DisableDBGStopMode(); -#else /* CONFIG_SOC_SERIES_STM32H7X || CONFIG_SOC_SERIES_STM32MP1X */ -#if defined(CONFIG_SOC_SERIES_STM32G0X) || defined(CONFIG_SOC_SERIES_STM32C0X) +#elif defined(CONFIG_SOC_SERIES_STM32G0X) || defined(CONFIG_SOC_SERIES_STM32C0X) LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_DBGMCU); LL_DBGMCU_DisableDBGStopMode(); LL_APB1_GRP1_DisableClock(LL_APB1_GRP1_PERIPH_DBGMCU); @@ -106,7 +103,6 @@ static int st_stm32_common_config(void) #else /* all other parts */ LL_DBGMCU_DisableDBGStopMode(); #endif -#endif /* CONFIG_SOC_SERIES_STM32H7X || CONFIG_SOC_SERIES_STM32MP1X */ #endif /* CONFIG_STM32_ENABLE_DEBUG_SLEEP_STOP */ From 8fc76f1b6d16e94a93c26f55c21be1fc2cc8ea39 Mon Sep 17 00:00:00 2001 From: Kai Vehmanen Date: Thu, 23 May 2024 12:09:20 +0300 Subject: [PATCH 1199/2849] soc: intel_adsp: tools: improve FW boot handling on ace1.x Starting with ace1.x, the boot status is no longer reported by the boot ROM in the SRAM status window as it was done in older platforms. The current cavstool.py code works on these newer platforms, as Zephyr soc bootcode writes to same location, but this is not the recommended boot flow. Modify boot flow to use a dedicated register to observe boot state. This change improves usability of cavstool.py on ace1.x platforms as: - it is possible to start cavstool.py (e.g. in log-only or shell mode) while DSP has been already been booted, but is currently in low-power mode (and SRAM window is not accessible from host) - more reliable boot and better error reporting as actual ROM status is observed Furthermore, this change allows to remove the memory window writes from Zephyr intel_adsp boot_complete(). This IPC interface is application and IPC revision specific and the write should not be done in generic Zephyr SoC code. However, to keep cavstool.py working, the tool has to be updated first. Signed-off-by: Kai Vehmanen --- soc/intel/intel_adsp/tools/cavstool.py | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/soc/intel/intel_adsp/tools/cavstool.py b/soc/intel/intel_adsp/tools/cavstool.py index 3b82d5bf33648..b10cfa135fc1c 100755 --- a/soc/intel/intel_adsp/tools/cavstool.py +++ b/soc/intel/intel_adsp/tools/cavstool.py @@ -281,6 +281,7 @@ def map_regs(): dsp.HFIPCXCTL = 0x73228 dsp.HFIPCXTDDY = 0x73300 dsp.HFIPCXIDDY = 0x73380 + dsp.ROM_STATUS = 0x163200 dsp.SRAM_FW_STATUS = WINDOW_BASE_ACE else: dsp.ADSPCS = 0x00004 @@ -290,7 +291,8 @@ def map_regs(): 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.ROM_STATUS = WINDOW_BASE # Start of first SRAM window + dsp.SRAM_FW_STATUS = WINDOW_BASE dsp.freeze() return (hda, sd, dsp, hda_ostream_id) @@ -600,7 +602,7 @@ def load_firmware_ace(fw_file): log.info("ACK IPC") dsp.HFIPCXIDA |= (1 << 31) - log.info(f"Starting DMA, FW_STATUS = 0x{dsp.SRAM_FW_STATUS:x}") + log.info(f"Starting DMA, FW_STATUS = 0x{dsp.ROM_STATUS:x}") sd.CTL |= 2 # START flag wait_fw_entered() @@ -618,12 +620,12 @@ def load_firmware_ace(fw_file): log.info(f"ACE firmware load complete") def fw_is_alive(): - return dsp.SRAM_FW_STATUS & ((1 << 28) - 1) == 5 # "FW_ENTERED" + return dsp.ROM_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", + log.info("Waiting %s for firmware handoff, ROM_STATUS = 0x%x", "forever" if timeout_s is None else f"{timeout_s} seconds", - dsp.SRAM_FW_STATUS) + dsp.ROM_STATUS) hertz = 100 attempts = None if timeout_s is None else timeout_s * hertz while True: @@ -637,9 +639,9 @@ def wait_fw_entered(timeout_s=2): time.sleep(1 / hertz) if not alive: - log.warning("Load failed? FW_STATUS = 0x%x", dsp.SRAM_FW_STATUS) + log.warning("Load failed? ROM_STATUS = 0x%x", dsp.ROM_STATUS) else: - log.info("FW alive, FW_STATUS = 0x%x", dsp.SRAM_FW_STATUS) + log.info("FW alive, ROM_STATUS = 0x%x", dsp.ROM_STATUS) def winstream_offset(): ( base, stride ) = adsp_mem_window_config() From fa798ce2d5be6deb8a3b0cde307a0a1dc5e88dde Mon Sep 17 00:00:00 2001 From: Kai Vehmanen Date: Thu, 23 May 2024 12:09:05 +0300 Subject: [PATCH 1200/2849] soc: intel_adsp: only implement FW_STATUS boot protocol for cavs The software protocol to write status value of 0x05 (FW_ENTERED) into memory window 0 at Zephyr boot, is not needed in the ace1.x boot flow and does not match the semantics host systems are expecting at this location in the memory window (e.g. write of 0x05 is not expected). Make this logic specific to intel_adsp_cavs platforms and move the code out from common intel_adsp code. This commit depends on update to cavstool.py to use correct ROM status register to observe boot state. Signed-off-by: Kai Vehmanen --- soc/intel/intel_adsp/cavs/CMakeLists.txt | 1 + soc/intel/intel_adsp/{common => cavs}/boot_complete.c | 0 soc/intel/intel_adsp/common/CMakeLists.txt | 1 - 3 files changed, 1 insertion(+), 1 deletion(-) rename soc/intel/intel_adsp/{common => cavs}/boot_complete.c (100%) diff --git a/soc/intel/intel_adsp/cavs/CMakeLists.txt b/soc/intel/intel_adsp/cavs/CMakeLists.txt index fdf8200fa6e14..3a7007f53ffc5 100644 --- a/soc/intel/intel_adsp/cavs/CMakeLists.txt +++ b/soc/intel/intel_adsp/cavs/CMakeLists.txt @@ -11,6 +11,7 @@ zephyr_library_sources( sram.c power.c power_down_cavs.S + boot_complete.c ) if(CONFIG_SMP OR CONFIG_MP_MAX_NUM_CPUS GREATER 1) diff --git a/soc/intel/intel_adsp/common/boot_complete.c b/soc/intel/intel_adsp/cavs/boot_complete.c similarity index 100% rename from soc/intel/intel_adsp/common/boot_complete.c rename to soc/intel/intel_adsp/cavs/boot_complete.c diff --git a/soc/intel/intel_adsp/common/CMakeLists.txt b/soc/intel/intel_adsp/common/CMakeLists.txt index 11d8ca67c8b19..03b206bf58f3a 100644 --- a/soc/intel/intel_adsp/common/CMakeLists.txt +++ b/soc/intel/intel_adsp/common/CMakeLists.txt @@ -16,7 +16,6 @@ zephyr_library_sources( boot.c soc.c mem_window.c - boot_complete.c ) zephyr_library_sources_ifdef(CONFIG_ADSP_CLOCK clk.c) From 8b41f3bebb1b6de3c63ef1198b7dd0dc2b45e123 Mon Sep 17 00:00:00 2001 From: Erwan Gouriou Date: Thu, 23 May 2024 14:00:36 +0200 Subject: [PATCH 1201/2849] west.yml: hal_stm32: Don't include legacy headers anymore We're not supposed to rely on symbols provided by these files. In case it is required stm32 zephyr code base should be updated rather than relying on legacy definitions. Additionally: Fixes https://github.com/zephyrproject-rtos/zephyr/issues/70136 Signed-off-by: Erwan Gouriou --- west.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/west.yml b/west.yml index 1dc935a9e955c..0fac1c4109fd6 100644 --- a/west.yml +++ b/west.yml @@ -229,7 +229,7 @@ manifest: groups: - hal - name: hal_stm32 - revision: ed93098718d5c727d2fac5ef27023a2a14763e32 + revision: 366c5c909fbcecf94f32411887132024f61b0bcd path: modules/hal/stm32 groups: - hal From 251ddf0ab5273b7c161638c267fbc8076b4d5e43 Mon Sep 17 00:00:00 2001 From: Jordan Yates Date: Wed, 22 May 2024 13:53:59 +1000 Subject: [PATCH 1202/2849] net: l2: ethernet: arp: improve debug output Improve the ARP debug output by printing: * Sending ARP query * Queuing packets due to pending ARP query * Receiving ARP query response Signed-off-by: Jordan Yates --- subsys/net/l2/ethernet/arp.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/subsys/net/l2/ethernet/arp.c b/subsys/net/l2/ethernet/arp.c index 85eafd0eedb33..7032414bc1e73 100644 --- a/subsys/net/l2/ethernet/arp.c +++ b/subsys/net/l2/ethernet/arp.c @@ -339,6 +339,7 @@ static inline struct net_pkt *arp_prepare(struct net_if *iface, (void)memset(&hdr->src_ipaddr, 0, sizeof(struct in_addr)); } + NET_DBG("Generating request for %s", net_sprint_ipv4_addr(next_addr)); return pkt; } @@ -408,6 +409,8 @@ struct net_pkt *net_arp_prepare(struct net_pkt *pkt, if (!net_pkt_ipv4_auto(pkt) && k_queue_unique_append(&entry->pending_queue._queue, net_pkt_ref(pkt))) { + NET_DBG("Pending ARP request for %s, queuing pkt %p", + net_sprint_ipv4_addr(addr), pkt); k_mutex_unlock(&arp_mutex); return NULL; } @@ -867,6 +870,10 @@ enum net_verdict net_arp_input(struct net_pkt *pkt, case NET_ARP_REPLY: if (net_ipv4_is_my_addr((struct in_addr *)arp_hdr->dst_ipaddr)) { + NET_DBG("Received ll %s for IP %s", + net_sprint_ll_addr(arp_hdr->src_hwaddr.addr, + sizeof(struct net_eth_addr)), + net_sprint_ipv4_addr(arp_hdr->src_ipaddr)); net_arp_update(net_pkt_iface(pkt), (struct in_addr *)arp_hdr->src_ipaddr, &arp_hdr->src_hwaddr, From 37466ac8874b724c936c739af73788cda8febdaa Mon Sep 17 00:00:00 2001 From: Pisit Sawangvonganan Date: Mon, 25 Mar 2024 19:45:57 +0700 Subject: [PATCH 1203/2849] drivers: clock_control: stm32: fix typo Use a code spell-checking tool to scan and correct spelling errors in the following files: - clock_stm32_ll_common.c - clock_stm32_ll_h5.c - clock_stm32_ll_h7.c - clock_stm32_ll_u5.c - clock_stm32_ll_wba.c Signed-off-by: Pisit Sawangvonganan --- drivers/clock_control/clock_stm32_ll_common.c | 6 +++--- drivers/clock_control/clock_stm32_ll_h5.c | 6 +++--- drivers/clock_control/clock_stm32_ll_h7.c | 14 +++++++------- drivers/clock_control/clock_stm32_ll_u5.c | 10 +++++----- drivers/clock_control/clock_stm32_ll_wba.c | 6 +++--- 5 files changed, 21 insertions(+), 21 deletions(-) diff --git a/drivers/clock_control/clock_stm32_ll_common.c b/drivers/clock_control/clock_stm32_ll_common.c index 024e336561673..efac0b897c7c8 100644 --- a/drivers/clock_control/clock_stm32_ll_common.c +++ b/drivers/clock_control/clock_stm32_ll_common.c @@ -205,7 +205,7 @@ static inline int stm32_clock_control_on(const struct device *dev, ARG_UNUSED(dev); if (IN_RANGE(pclken->bus, STM32_PERIPH_BUS_MIN, STM32_PERIPH_BUS_MAX) == 0) { - /* Attemp to change a wrong periph clock bit */ + /* Attempt to change a wrong periph clock bit */ return -ENOTSUP; } @@ -228,7 +228,7 @@ static inline int stm32_clock_control_off(const struct device *dev, ARG_UNUSED(dev); if (IN_RANGE(pclken->bus, STM32_PERIPH_BUS_MIN, STM32_PERIPH_BUS_MAX) == 0) { - /* Attemp to toggle a wrong periph clock bit */ + /* Attempt to toggle a wrong periph clock bit */ return -ENOTSUP; } @@ -750,7 +750,7 @@ int stm32_clock_control_init(const struct device *dev) } #endif /* FLASH_ACR_LATENCY */ - /* Set up indiviual enabled clocks */ + /* Set up individual enabled clocks */ set_up_fixed_clock_sources(); /* Set up PLLs */ diff --git a/drivers/clock_control/clock_stm32_ll_h5.c b/drivers/clock_control/clock_stm32_ll_h5.c index 28e2dd3e0092f..e4423f3162aa0 100644 --- a/drivers/clock_control/clock_stm32_ll_h5.c +++ b/drivers/clock_control/clock_stm32_ll_h5.c @@ -150,7 +150,7 @@ static inline int stm32_clock_control_on(const struct device *dev, ARG_UNUSED(dev); if (IN_RANGE(pclken->bus, STM32_PERIPH_BUS_MIN, STM32_PERIPH_BUS_MAX) == 0) { - /* Attemp to toggle a wrong periph clock bit */ + /* Attempt to toggle a wrong periph clock bit */ return -ENOTSUP; } @@ -171,7 +171,7 @@ static inline int stm32_clock_control_off(const struct device *dev, ARG_UNUSED(dev); if (IN_RANGE(pclken->bus, STM32_PERIPH_BUS_MIN, STM32_PERIPH_BUS_MAX) == 0) { - /* Attemp to toggle a wrong periph clock bit */ + /* Attempt to toggle a wrong periph clock bit */ return -ENOTSUP; } @@ -722,7 +722,7 @@ int stm32_clock_control_init(const struct device *dev) return r; } - /* Set peripheral busses prescalers */ + /* Set peripheral buses prescalers */ LL_RCC_SetAHBPrescaler(ahb_prescaler(STM32_AHB_PRESCALER)); LL_RCC_SetAPB1Prescaler(apb1_prescaler(STM32_APB1_PRESCALER)); LL_RCC_SetAPB2Prescaler(apb2_prescaler(STM32_APB2_PRESCALER)); diff --git a/drivers/clock_control/clock_stm32_ll_h7.c b/drivers/clock_control/clock_stm32_ll_h7.c index e4d78e5ce6032..bcd1873dd81a5 100644 --- a/drivers/clock_control/clock_stm32_ll_h7.c +++ b/drivers/clock_control/clock_stm32_ll_h7.c @@ -142,7 +142,7 @@ #error "SYS clock frequency for M7 core doesn't match CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC" #endif -/* end of clock feasability check */ +/* end of clock feasibility check */ #endif /* CONFIG_CPU_CORTEX_M7 */ @@ -329,7 +329,7 @@ static uint32_t get_vco_output_range(uint32_t vco_input_range) #endif /* ! CONFIG_CPU_CORTEX_M4 */ -/** @brief Verifies clock is part of actve clock configuration */ +/** @brief Verifies clock is part of active clock configuration */ static int enabled_clock(uint32_t src_clk) { @@ -365,7 +365,7 @@ static inline int stm32_clock_control_on(const struct device *dev, ARG_UNUSED(dev); if (IN_RANGE(pclken->bus, STM32_PERIPH_BUS_MIN, STM32_PERIPH_BUS_MAX) == 0) { - /* Attemp to toggle a wrong periph clock bit */ + /* Attempt to toggle a wrong periph clock bit */ return -ENOTSUP; } @@ -391,7 +391,7 @@ static inline int stm32_clock_control_off(const struct device *dev, ARG_UNUSED(dev); if (IN_RANGE(pclken->bus, STM32_PERIPH_BUS_MIN, STM32_PERIPH_BUS_MAX) == 0) { - /* Attemp to toggle a wrong periph clock bit */ + /* Attempt to toggle a wrong periph clock bit */ return -ENOTSUP; } @@ -416,7 +416,7 @@ static inline int stm32_clock_control_configure(const struct device *dev, err = enabled_clock(pclken->bus); if (err < 0) { - /* Attemp to configure a src clock not available or not valid */ + /* Attempt to configure a src clock not available or not valid */ return err; } @@ -852,7 +852,7 @@ int stm32_clock_control_init(const struct device *dev) /* Configure MCO1/MCO2 based on Kconfig */ stm32_clock_control_mco_init(); - /* Set up indiviual enabled clocks */ + /* Set up individual enabled clocks */ set_up_fixed_clock_sources(); /* Set up PLLs */ @@ -877,7 +877,7 @@ int stm32_clock_control_init(const struct device *dev) LL_SetFlashLatency(new_hclk_freq); } - /* Preset the prescalers prior to chosing SYSCLK */ + /* Preset the prescalers prior to choosing SYSCLK */ /* Prevents APB clock to go over limits */ /* Set buses (Sys,AHB, APB1, APB2 & APB4) prescalers */ LL_RCC_SetSysPrescaler(sysclk_prescaler(STM32_D1CPRE)); diff --git a/drivers/clock_control/clock_stm32_ll_u5.c b/drivers/clock_control/clock_stm32_ll_u5.c index ec4d11546f3d4..f28fd6338b8b2 100644 --- a/drivers/clock_control/clock_stm32_ll_u5.c +++ b/drivers/clock_control/clock_stm32_ll_u5.c @@ -125,7 +125,7 @@ static int enabled_clock(uint32_t src_clk) if ((src_clk == STM32_SRC_SYSCLK) || ((src_clk == STM32_SRC_HSE) && IS_ENABLED(STM32_HSE_ENABLED)) || ((src_clk == STM32_SRC_HSI16) && IS_ENABLED(STM32_HSI_ENABLED)) || -+ ((src_clk == STM32_SRC_HSI48) && IS_ENABLED(STM32_HSI48_ENABLED)) || + ((src_clk == STM32_SRC_HSI48) && IS_ENABLED(STM32_HSI48_ENABLED)) || ((src_clk == STM32_SRC_LSE) && IS_ENABLED(STM32_LSE_ENABLED)) || ((src_clk == STM32_SRC_LSI) && IS_ENABLED(STM32_LSI_ENABLED)) || ((src_clk == STM32_SRC_MSIS) && IS_ENABLED(STM32_MSIS_ENABLED)) || @@ -154,7 +154,7 @@ static inline int stm32_clock_control_on(const struct device *dev, ARG_UNUSED(dev); if (IN_RANGE(pclken->bus, STM32_PERIPH_BUS_MIN, STM32_PERIPH_BUS_MAX) == 0) { - /* Attemp to toggle a wrong periph clock bit */ + /* Attempt to toggle a wrong periph clock bit */ return -ENOTSUP; } @@ -175,7 +175,7 @@ static inline int stm32_clock_control_off(const struct device *dev, ARG_UNUSED(dev); if (IN_RANGE(pclken->bus, STM32_PERIPH_BUS_MIN, STM32_PERIPH_BUS_MAX) == 0) { - /* Attemp to toggle a wrong periph clock bit */ + /* Attempt to toggle a wrong periph clock bit */ return -ENOTSUP; } @@ -715,7 +715,7 @@ static void set_up_fixed_clock_sources(void) while (!LL_RCC_LSE_IsReady()) { } - /* Enable LSESYS additionnally */ + /* Enable LSESYS additionally */ LL_RCC_LSE_EnablePropagation(); /* Wait till LSESYS is ready */ while (!LL_RCC_LSESYS_IsReady()) { @@ -830,7 +830,7 @@ int stm32_clock_control_init(const struct device *dev) return r; } - /* Set peripheral busses prescalers */ + /* Set peripheral buses prescalers */ LL_RCC_SetAHBPrescaler(ahb_prescaler(STM32_AHB_PRESCALER)); LL_RCC_SetAPB1Prescaler(apb1_prescaler(STM32_APB1_PRESCALER)); LL_RCC_SetAPB2Prescaler(apb2_prescaler(STM32_APB2_PRESCALER)); diff --git a/drivers/clock_control/clock_stm32_ll_wba.c b/drivers/clock_control/clock_stm32_ll_wba.c index 17857c0e7ca74..fc5b1751eb51d 100644 --- a/drivers/clock_control/clock_stm32_ll_wba.c +++ b/drivers/clock_control/clock_stm32_ll_wba.c @@ -67,7 +67,7 @@ static inline int stm32_clock_control_on(const struct device *dev, ARG_UNUSED(dev); if (IN_RANGE(pclken->bus, STM32_PERIPH_BUS_MIN, STM32_PERIPH_BUS_MAX) == 0) { - /* Attemp to toggle a wrong periph clock bit */ + /* Attempt to toggle a wrong periph clock bit */ return -ENOTSUP; } @@ -88,7 +88,7 @@ static inline int stm32_clock_control_off(const struct device *dev, ARG_UNUSED(dev); if (IN_RANGE(pclken->bus, STM32_PERIPH_BUS_MIN, STM32_PERIPH_BUS_MAX) == 0) { - /* Attemp to toggle a wrong periph clock bit */ + /* Attempt to toggle a wrong periph clock bit */ return -ENOTSUP; } @@ -487,7 +487,7 @@ static void set_up_fixed_clock_sources(void) /* Wait for LSE ready */ } - /* Enable LSESYS additionnally */ + /* Enable LSESYS additionally */ LL_RCC_LSE_EnablePropagation(); /* Wait till LSESYS is ready */ while (!LL_RCC_LSE_IsPropagationReady()) { From 512c18393a36d8f63542a746dd21486fff424ddd Mon Sep 17 00:00:00 2001 From: Pisit Sawangvonganan Date: Mon, 25 Mar 2024 19:56:34 +0700 Subject: [PATCH 1204/2849] drivers: clock_control: stm32: clean up unnecessary code This commit removes unnecessary initialization of the local variable where its value is guaranteed to be overwritten by subsequent operations. Signed-off-by: Pisit Sawangvonganan --- drivers/clock_control/clock_stm32_ll_h5.c | 4 ++-- drivers/clock_control/clock_stm32_ll_h7.c | 4 ++-- drivers/clock_control/clock_stm32_ll_u5.c | 4 ++-- drivers/clock_control/clock_stm32_ll_wba.c | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/clock_control/clock_stm32_ll_h5.c b/drivers/clock_control/clock_stm32_ll_h5.c index e4423f3162aa0..6ad08d1ee3b93 100644 --- a/drivers/clock_control/clock_stm32_ll_h5.c +++ b/drivers/clock_control/clock_stm32_ll_h5.c @@ -696,8 +696,8 @@ static void set_up_fixed_clock_sources(void) int stm32_clock_control_init(const struct device *dev) { - uint32_t old_hclk_freq = 0; - int r = 0; + uint32_t old_hclk_freq; + int r; ARG_UNUSED(dev); diff --git a/drivers/clock_control/clock_stm32_ll_h7.c b/drivers/clock_control/clock_stm32_ll_h7.c index bcd1873dd81a5..b11e2b5c9f5b6 100644 --- a/drivers/clock_control/clock_stm32_ll_h7.c +++ b/drivers/clock_control/clock_stm32_ll_h7.c @@ -835,8 +835,8 @@ int stm32_clock_control_init(const struct device *dev) int r = 0; #if defined(CONFIG_CPU_CORTEX_M7) - uint32_t old_hclk_freq = 0; - uint32_t new_hclk_freq = 0; + uint32_t old_hclk_freq; + uint32_t new_hclk_freq; /* HW semaphore Clock enable */ #if defined(CONFIG_SOC_STM32H7A3XX) || defined(CONFIG_SOC_STM32H7A3XXQ) || \ diff --git a/drivers/clock_control/clock_stm32_ll_u5.c b/drivers/clock_control/clock_stm32_ll_u5.c index f28fd6338b8b2..fc16b5e46e47b 100644 --- a/drivers/clock_control/clock_stm32_ll_u5.c +++ b/drivers/clock_control/clock_stm32_ll_u5.c @@ -804,8 +804,8 @@ static void set_up_fixed_clock_sources(void) int stm32_clock_control_init(const struct device *dev) { - uint32_t old_hclk_freq = 0; - int r = 0; + uint32_t old_hclk_freq; + int r; ARG_UNUSED(dev); diff --git a/drivers/clock_control/clock_stm32_ll_wba.c b/drivers/clock_control/clock_stm32_ll_wba.c index fc5b1751eb51d..36cf52064dac5 100644 --- a/drivers/clock_control/clock_stm32_ll_wba.c +++ b/drivers/clock_control/clock_stm32_ll_wba.c @@ -510,7 +510,7 @@ static void set_up_fixed_clock_sources(void) int stm32_clock_control_init(const struct device *dev) { uint32_t old_flash_freq; - int r = 0; + int r; ARG_UNUSED(dev); From fa716d9842f203f0ed5eab69064e8f27c6192d34 Mon Sep 17 00:00:00 2001 From: Jungo Lin Date: Sun, 10 Mar 2024 10:42:52 +0800 Subject: [PATCH 1205/2849] shell: fix index out bound issue In order to prevent index out of bounds access of the sh->ctx->cmd_buff array when sh->ctx->cmd_buff_pos is 0, it has been added a check for the value of sh->ctx->cmd_buff_pos. This ensures that the array will not be accessed beyond its boundaries. Signed-off-by: Jungo Lin --- subsys/shell/shell.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/subsys/shell/shell.c b/subsys/shell/shell.c index 29f9d856d5fcf..3432731daf710 100644 --- a/subsys/shell/shell.c +++ b/subsys/shell/shell.c @@ -288,8 +288,8 @@ static bool tab_prepare(const struct shell *sh, /* If last command is not completed (followed by space) it is treated * as uncompleted one. */ - int space = isspace((int)sh->ctx->cmd_buff[ - sh->ctx->cmd_buff_pos - 1]); + int space = (sh->ctx->cmd_buff_pos > 0) ? + isspace((int)sh->ctx->cmd_buff[sh->ctx->cmd_buff_pos - 1]) : 0; /* root command completion */ if ((*argc == 0) || ((space == 0) && (*argc == 1))) { From 7abb9d7593b7f4d727fa1fa6440a6d87f612f99a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20G=C5=82=C4=85bek?= Date: Tue, 21 May 2024 16:57:07 +0200 Subject: [PATCH 1206/2849] drivers: watchdog: Allow WDT_DISABLE_AT_BOOT only when supported MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Introduce a hidden Kconfig option named HAS_WDT_DISABLE_AT_BOOT and allow users to enable WDT_DISABLE_AT_BOOT only when that hidden option is selected by a watchdog driver, i.e. disabling at boot is supported. Select this new hidden option for all existing watchdog drivers that refer to WDT_DISABLE_AT_BOOT. Signed-off-by: Andrzej Głąbek --- drivers/watchdog/Kconfig | 4 ++++ drivers/watchdog/Kconfig.andes_atcwdt200 | 1 + drivers/watchdog/Kconfig.cc13xx_cc26xx | 1 + drivers/watchdog/Kconfig.cc32xx | 1 + drivers/watchdog/Kconfig.dw | 1 + drivers/watchdog/Kconfig.ene | 1 + drivers/watchdog/Kconfig.esp32 | 1 + drivers/watchdog/Kconfig.gd32 | 1 + drivers/watchdog/Kconfig.gecko | 2 +- drivers/watchdog/Kconfig.it8xxx2 | 1 + drivers/watchdog/Kconfig.npcx | 1 + drivers/watchdog/Kconfig.rpi_pico | 1 + drivers/watchdog/Kconfig.sam | 1 + drivers/watchdog/Kconfig.sam0 | 1 + drivers/watchdog/Kconfig.sifive | 1 + drivers/watchdog/Kconfig.smartbond | 1 + drivers/watchdog/Kconfig.stm32 | 1 + drivers/watchdog/Kconfig.tco | 1 + drivers/watchdog/Kconfig.xec | 1 + drivers/watchdog/Kconfig.xmc4xxx | 1 + 20 files changed, 23 insertions(+), 1 deletion(-) diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index 96cc4a61e0d2c..4a3982ba15d1d 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -11,8 +11,12 @@ menuconfig WATCHDOG if WATCHDOG +config HAS_WDT_DISABLE_AT_BOOT + bool + config WDT_DISABLE_AT_BOOT bool "Disable at boot" + depends on HAS_WDT_DISABLE_AT_BOOT help Disable watchdog at Zephyr system startup. diff --git a/drivers/watchdog/Kconfig.andes_atcwdt200 b/drivers/watchdog/Kconfig.andes_atcwdt200 index b4160c7bf242d..f942da491bae6 100644 --- a/drivers/watchdog/Kconfig.andes_atcwdt200 +++ b/drivers/watchdog/Kconfig.andes_atcwdt200 @@ -9,6 +9,7 @@ config WDT_ANDES_ATCWDT200 bool "Andes Watchdog driver" default y depends on DT_HAS_ANDESTECH_ATCWDT200_ENABLED + select HAS_WDT_DISABLE_AT_BOOT select COUNTER help Enable driver for the Andes Watchdog driver. diff --git a/drivers/watchdog/Kconfig.cc13xx_cc26xx b/drivers/watchdog/Kconfig.cc13xx_cc26xx index 4590c944a4b85..2ea45787f0307 100644 --- a/drivers/watchdog/Kconfig.cc13xx_cc26xx +++ b/drivers/watchdog/Kconfig.cc13xx_cc26xx @@ -5,6 +5,7 @@ config WDT_CC13XX_CC26XX bool "Watchdog Driver for CC13xx / CC26xx family of MCUs" default y depends on DT_HAS_TI_CC13XX_CC26XX_WATCHDOG_ENABLED + select HAS_WDT_DISABLE_AT_BOOT help Enable watchdog for CC13xx / CC26xx family of MCUs diff --git a/drivers/watchdog/Kconfig.cc32xx b/drivers/watchdog/Kconfig.cc32xx index 01734a4cdc8f0..a6a581fdfc759 100644 --- a/drivers/watchdog/Kconfig.cc32xx +++ b/drivers/watchdog/Kconfig.cc32xx @@ -5,6 +5,7 @@ config WDT_CC32XX bool "Watchdog Driver for cc32xx family of MCUs" default y depends on DT_HAS_TI_CC32XX_WATCHDOG_ENABLED + select HAS_WDT_DISABLE_AT_BOOT help Watchdog for cc32xx family of MCUs diff --git a/drivers/watchdog/Kconfig.dw b/drivers/watchdog/Kconfig.dw index a3fb726ddd838..ba35465af1326 100644 --- a/drivers/watchdog/Kconfig.dw +++ b/drivers/watchdog/Kconfig.dw @@ -7,5 +7,6 @@ config WDT_DW bool "Synopsys DesignWare Watchdog driver" default y depends on DT_HAS_SNPS_DESIGNWARE_WATCHDOG_ENABLED + select HAS_WDT_DISABLE_AT_BOOT help Synopsys DesignWare Watchdog driver. diff --git a/drivers/watchdog/Kconfig.ene b/drivers/watchdog/Kconfig.ene index 114c69b4c2b72..425b5bb63acfe 100644 --- a/drivers/watchdog/Kconfig.ene +++ b/drivers/watchdog/Kconfig.ene @@ -5,5 +5,6 @@ config WDT_ENE_KB1200 bool "ENE KB1200 watchdog driver" default y depends on DT_HAS_ENE_KB1200_WATCHDOG_ENABLED + select HAS_WDT_DISABLE_AT_BOOT help This option enables the KB1200 watchdog driver. diff --git a/drivers/watchdog/Kconfig.esp32 b/drivers/watchdog/Kconfig.esp32 index 68eb9e5577935..5fb736bf09270 100644 --- a/drivers/watchdog/Kconfig.esp32 +++ b/drivers/watchdog/Kconfig.esp32 @@ -7,5 +7,6 @@ config WDT_ESP32 bool "ESP32 Watchdog (WDT) Driver" default y depends on DT_HAS_ESPRESSIF_ESP32_WATCHDOG_ENABLED + select HAS_WDT_DISABLE_AT_BOOT help Enable WDT driver for ESP32. diff --git a/drivers/watchdog/Kconfig.gd32 b/drivers/watchdog/Kconfig.gd32 index 29da540738951..7d149f17b50ae 100644 --- a/drivers/watchdog/Kconfig.gd32 +++ b/drivers/watchdog/Kconfig.gd32 @@ -5,6 +5,7 @@ config FWDGT_GD32 bool "GD32 Free watchdog timer (FWDGT) driver" default y depends on DT_HAS_GD_GD32_FWDGT_ENABLED + select HAS_WDT_DISABLE_AT_BOOT select USE_GD32_FWDGT help Enable the Free watchdog timer (FWDGT) driver for GD32 SoCs. diff --git a/drivers/watchdog/Kconfig.gecko b/drivers/watchdog/Kconfig.gecko index 15b99e0b8b228..55fbd7b8e1755 100644 --- a/drivers/watchdog/Kconfig.gecko +++ b/drivers/watchdog/Kconfig.gecko @@ -9,7 +9,7 @@ config WDT_GECKO bool "Gecko series Watchdog (WDOG) Driver" default y depends on DT_HAS_SILABS_GECKO_WDOG_ENABLED + select HAS_WDT_DISABLE_AT_BOOT select SOC_GECKO_WDOG - default y help Enable WDOG driver for Silicon Labs Gecko MCUs. diff --git a/drivers/watchdog/Kconfig.it8xxx2 b/drivers/watchdog/Kconfig.it8xxx2 index 1ef3ad194494d..e042ded8b47ec 100644 --- a/drivers/watchdog/Kconfig.it8xxx2 +++ b/drivers/watchdog/Kconfig.it8xxx2 @@ -5,6 +5,7 @@ config WDT_ITE_IT8XXX2 bool "ITE it8xxx2 Watchdog Timer (WDT) driver" default y depends on DT_HAS_ITE_IT8XXX2_WATCHDOG_ENABLED + select HAS_WDT_DISABLE_AT_BOOT help This option enables the Watchdog Timer driver for ITE it8xxx2. This driver supports only one channel that id is 0 and 16-bits diff --git a/drivers/watchdog/Kconfig.npcx b/drivers/watchdog/Kconfig.npcx index 864208b49fe08..f69a70c8db571 100644 --- a/drivers/watchdog/Kconfig.npcx +++ b/drivers/watchdog/Kconfig.npcx @@ -7,6 +7,7 @@ config WDT_NPCX bool "Nuvoton NPCX embedded controller (EC) Watchdog Timer driver" default y depends on DT_HAS_NUVOTON_NPCX_WATCHDOG_ENABLED + select HAS_WDT_DISABLE_AT_BOOT help This option enables the Watchdog Timer driver for NPCX family of processors. diff --git a/drivers/watchdog/Kconfig.rpi_pico b/drivers/watchdog/Kconfig.rpi_pico index 2c99d50fdd1e2..a48d1c49fef1b 100644 --- a/drivers/watchdog/Kconfig.rpi_pico +++ b/drivers/watchdog/Kconfig.rpi_pico @@ -5,6 +5,7 @@ config WDT_RPI_PICO bool "Raspberry Pi Pico Watchdog driver" default y depends on DT_HAS_RASPBERRYPI_PICO_WATCHDOG_ENABLED + select HAS_WDT_DISABLE_AT_BOOT config WDT_RPI_PICO_INITIAL_TIMEOUT int "Default watchdog timeout in us" diff --git a/drivers/watchdog/Kconfig.sam b/drivers/watchdog/Kconfig.sam index 9cfd452532423..3556a46ff8726 100644 --- a/drivers/watchdog/Kconfig.sam +++ b/drivers/watchdog/Kconfig.sam @@ -7,5 +7,6 @@ config WDT_SAM bool "Atmel SAM MCU Family Watchdog (WDT) Driver" default y depends on DT_HAS_ATMEL_SAM_WATCHDOG_ENABLED + select HAS_WDT_DISABLE_AT_BOOT help Enable WDT driver for Atmel SAM MCUs. diff --git a/drivers/watchdog/Kconfig.sam0 b/drivers/watchdog/Kconfig.sam0 index 381a5347b9c5a..a7ac15c68a218 100644 --- a/drivers/watchdog/Kconfig.sam0 +++ b/drivers/watchdog/Kconfig.sam0 @@ -7,5 +7,6 @@ config WDT_SAM0 bool "Atmel SAM0 series Watchdog (WDT) Driver" default y depends on DT_HAS_ATMEL_SAM0_WATCHDOG_ENABLED + select HAS_WDT_DISABLE_AT_BOOT help Enable WDT driver for Atmel SAM0 MCUs. diff --git a/drivers/watchdog/Kconfig.sifive b/drivers/watchdog/Kconfig.sifive index 79623237b3750..43357cc7e0808 100644 --- a/drivers/watchdog/Kconfig.sifive +++ b/drivers/watchdog/Kconfig.sifive @@ -7,5 +7,6 @@ config WDT_SIFIVE bool "SiFive Watchdog (WDT) Driver" default y depends on DT_HAS_SIFIVE_WDT_ENABLED + select HAS_WDT_DISABLE_AT_BOOT help This option enables WDT driver for SiFive Freedom. diff --git a/drivers/watchdog/Kconfig.smartbond b/drivers/watchdog/Kconfig.smartbond index 5cf82ba5514e2..9978a8332cbbe 100644 --- a/drivers/watchdog/Kconfig.smartbond +++ b/drivers/watchdog/Kconfig.smartbond @@ -7,6 +7,7 @@ config WDT_SMARTBOND bool "Watchdog Driver for Smartbond family of MCUs" default y depends on DT_HAS_RENESAS_SMARTBOND_WATCHDOG_ENABLED + select HAS_WDT_DISABLE_AT_BOOT help Enable watchdog driver for Smartbond line of MCUs diff --git a/drivers/watchdog/Kconfig.stm32 b/drivers/watchdog/Kconfig.stm32 index af5a964f9a698..87ace6ba59bc0 100644 --- a/drivers/watchdog/Kconfig.stm32 +++ b/drivers/watchdog/Kconfig.stm32 @@ -9,6 +9,7 @@ config IWDG_STM32 bool "Independent Watchdog (IWDG) Driver for STM32 family of MCUs" default y depends on DT_HAS_ST_STM32_WATCHDOG_ENABLED + select HAS_WDT_DISABLE_AT_BOOT help Enable IWDG driver for STM32 line of MCUs diff --git a/drivers/watchdog/Kconfig.tco b/drivers/watchdog/Kconfig.tco index 2e479e37efd9f..7439ffbc8918c 100644 --- a/drivers/watchdog/Kconfig.tco +++ b/drivers/watchdog/Kconfig.tco @@ -7,5 +7,6 @@ config WDT_TCO bool "Intel TCO Watchdog driver" default y depends on DT_HAS_INTEL_TCO_WDT_ENABLED + select HAS_WDT_DISABLE_AT_BOOT help Enable support for Intel TCO WDT driver. diff --git a/drivers/watchdog/Kconfig.xec b/drivers/watchdog/Kconfig.xec index 7de929517005d..78e6bb616ae33 100644 --- a/drivers/watchdog/Kconfig.xec +++ b/drivers/watchdog/Kconfig.xec @@ -7,5 +7,6 @@ config WDT_XEC bool "Microchip XEC series Watchdog Timer (WDT) driver" default y depends on DT_HAS_MICROCHIP_XEC_WATCHDOG_ENABLED + select HAS_WDT_DISABLE_AT_BOOT help Enable WDT driver for Microchip XEC MCU series. diff --git a/drivers/watchdog/Kconfig.xmc4xxx b/drivers/watchdog/Kconfig.xmc4xxx index 8c18d06da0d24..de677089d4d07 100644 --- a/drivers/watchdog/Kconfig.xmc4xxx +++ b/drivers/watchdog/Kconfig.xmc4xxx @@ -7,6 +7,7 @@ config WDT_XMC4XXX bool "Infineon XMC4xxx MCU Family Watchdog (WDT) Driver" default y depends on DT_HAS_INFINEON_XMC4XXX_WATCHDOG_ENABLED + select HAS_WDT_DISABLE_AT_BOOT help Enable WDT driver for Infineon XMC4xxx MCUs. From a70bf0e488c5327ad67512c2854987d113318c79 Mon Sep 17 00:00:00 2001 From: Glenn Andrews Date: Sat, 25 May 2024 17:16:16 -0700 Subject: [PATCH 1207/2849] modules: lvgl: Fix inverting x/y if screen is rotated https://github.com/zephyrproject-rtos/zephyr/pull/70541 has an issue where if the screen has been rotated, values calculated if invert-x or invert-y are set will be overwritten. This breaks the adafruit_2_8_tft_touch_v2 touchscreen as the display is rotated by 90 degrees but uses invert-x and invert-y. This change makes the invert-x and invert-y options independent of screen rotation. Signed-off-by: Glenn Andrews --- modules/lvgl/input/lvgl_pointer_input.c | 42 ++++++++++++++++--------- 1 file changed, 27 insertions(+), 15 deletions(-) diff --git a/modules/lvgl/input/lvgl_pointer_input.c b/modules/lvgl/input/lvgl_pointer_input.c index e1b1224375057..11f350034cf38 100644 --- a/modules/lvgl/input/lvgl_pointer_input.c +++ b/modules/lvgl/input/lvgl_pointer_input.c @@ -61,37 +61,49 @@ static void lvgl_pointer_process_event(const struct device *dev, struct input_ev return; } - point->x = data->point_x; - point->y = data->point_y; + lv_point_t tmp_point = { + .x = data->point_x, + .y = data->point_y, + }; if (cfg->invert_x) { if (cap->current_orientation == DISPLAY_ORIENTATION_NORMAL || cap->current_orientation == DISPLAY_ORIENTATION_ROTATED_180) { - point->x = cap->x_resolution - data->point_x; + tmp_point.x = cap->x_resolution - tmp_point.x; } else { - point->x = cap->y_resolution - data->point_x; + tmp_point.x = cap->y_resolution - tmp_point.x; } } if (cfg->invert_y) { if (cap->current_orientation == DISPLAY_ORIENTATION_NORMAL || cap->current_orientation == DISPLAY_ORIENTATION_ROTATED_180) { - point->y = cap->y_resolution - data->point_y; + tmp_point.y = cap->y_resolution - tmp_point.y; } else { - point->y = cap->x_resolution - data->point_y; + tmp_point.y = cap->x_resolution - tmp_point.y; } } /* rotate touch point to match display rotation */ - if (cap->current_orientation == DISPLAY_ORIENTATION_ROTATED_90) { - point->x = data->point_y; - point->y = cap->y_resolution - data->point_x; - } else if (cap->current_orientation == DISPLAY_ORIENTATION_ROTATED_180) { - point->x = cap->x_resolution - data->point_x; - point->y = cap->y_resolution - data->point_y; - } else if (cap->current_orientation == DISPLAY_ORIENTATION_ROTATED_270) { - point->x = cap->x_resolution - data->point_y; - point->y = data->point_x; + switch (cap->current_orientation) { + case DISPLAY_ORIENTATION_NORMAL: + point->x = tmp_point.x; + point->y = tmp_point.y; + case DISPLAY_ORIENTATION_ROTATED_90: + point->x = tmp_point.y; + point->y = cap->y_resolution - tmp_point.x; + break; + case DISPLAY_ORIENTATION_ROTATED_180: + point->x = cap->x_resolution - tmp_point.x; + point->y = cap->y_resolution - tmp_point.y; + break; + case DISPLAY_ORIENTATION_ROTATED_270: + point->x = cap->x_resolution - tmp_point.y; + point->y = tmp_point.x; + break; + default: + LOG_ERR("Invalid display orientation"); + break; } /* filter readings within display */ From 3da35039ceb30d80e689d058626c2222142f16f0 Mon Sep 17 00:00:00 2001 From: Konrad Derda Date: Mon, 27 May 2024 19:56:16 +0200 Subject: [PATCH 1208/2849] net: ipv6: scope checking function fix Change the implementation of net_ipv6_is_addr_mcast_scope() inline function that let us check if a given IPv6 address has a specified scope. Previously, it was comparing the whole byte including flags of a multicast address. It meant, that while checking for a specific scope a one was also checking the flags. Even in Zephyr's net stack there are checks for a IPv6 link local scope that are failing for addresses that are not marked as "well known" (when least significant bit of the flags is set). Signed-off-by: Konrad Derda --- include/zephyr/net/net_ip.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/zephyr/net/net_ip.h b/include/zephyr/net/net_ip.h index 413d3efb09449..4764ba944569c 100644 --- a/include/zephyr/net/net_ip.h +++ b/include/zephyr/net/net_ip.h @@ -1122,7 +1122,7 @@ static inline bool net_ipv6_is_addr_solicited_node(const struct in6_addr *addr) static inline bool net_ipv6_is_addr_mcast_scope(const struct in6_addr *addr, int scope) { - return (addr->s6_addr[0] == 0xff) && (addr->s6_addr[1] == scope); + return (addr->s6_addr[0] == 0xff) && ((addr->s6_addr[1] & 0xF) == scope); } /** From 49399ec48c60e073536f1de954979c4cb3d97feb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fin=20Maa=C3=9F?= Date: Mon, 27 May 2024 10:58:01 +0200 Subject: [PATCH 1209/2849] dts: litex: add node label for cpu MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This adds a node label for the cpu. Signed-off-by: Fin Maaß --- dts/riscv/riscv32-litex-vexriscv.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dts/riscv/riscv32-litex-vexriscv.dtsi b/dts/riscv/riscv32-litex-vexriscv.dtsi index 8013decbafdfe..8032317f9d812 100644 --- a/dts/riscv/riscv32-litex-vexriscv.dtsi +++ b/dts/riscv/riscv32-litex-vexriscv.dtsi @@ -18,7 +18,7 @@ cpus { #address-cells = <1>; #size-cells = <0>; - cpu@0 { + cpu0: cpu@0 { clock-frequency = <100000000>; compatible = "litex,vexriscv-standard", "riscv"; device_type = "cpu"; From 86e0fe13e19240437ce93fd827da5449b770f189 Mon Sep 17 00:00:00 2001 From: Pisit Sawangvonganan Date: Fri, 24 May 2024 13:09:35 +0700 Subject: [PATCH 1210/2849] drivers: serial: stm32: reduce pointer level from config->usart to usart This change reduces the level of pointer indirection, which minimizes repeated dereferencing and helps reduce the overall code size. Signed-off-by: Pisit Sawangvonganan --- drivers/serial/uart_stm32.c | 217 +++++++++++++++++++----------------- 1 file changed, 117 insertions(+), 100 deletions(-) diff --git a/drivers/serial/uart_stm32.c b/drivers/serial/uart_stm32.c index f5a831f0d2b83..628b6c379a955 100644 --- a/drivers/serial/uart_stm32.c +++ b/drivers/serial/uart_stm32.c @@ -126,6 +126,7 @@ static void uart_stm32_pm_policy_state_lock_put(const struct device *dev) static inline void uart_stm32_set_baudrate(const struct device *dev, uint32_t baud_rate) { const struct uart_stm32_config *config = dev->config; + USART_TypeDef *usart = config->usart; struct uart_stm32_data *data = dev->data; uint32_t clock_rate; @@ -148,7 +149,7 @@ static inline void uart_stm32_set_baudrate(const struct device *dev, uint32_t ba } #if HAS_LPUART - if (IS_LPUART_INSTANCE(config->usart)) { + if (IS_LPUART_INSTANCE(usart)) { uint32_t lpuartdiv; #ifdef USART_PRESC_PRESCALER uint8_t presc_idx; @@ -168,7 +169,7 @@ static inline void uart_stm32_set_baudrate(const struct device *dev, uint32_t ba presc_val = presc_idx << USART_PRESC_PRESCALER_Pos; - LL_LPUART_SetPrescaler(config->usart, presc_val); + LL_LPUART_SetPrescaler(usart, presc_val); #else lpuartdiv = lpuartdiv_calc(clock_rate, baud_rate); if (lpuartdiv < LPUART_BRR_MIN_VALUE || lpuartdiv > LPUART_BRR_MASK) { @@ -176,26 +177,26 @@ static inline void uart_stm32_set_baudrate(const struct device *dev, uint32_t ba return; } #endif /* USART_PRESC_PRESCALER */ - LL_LPUART_SetBaudRate(config->usart, + LL_LPUART_SetBaudRate(usart, clock_rate, #ifdef USART_PRESC_PRESCALER presc_val, #endif baud_rate); /* Check BRR is greater than or equal to 0x300 */ - __ASSERT(LL_LPUART_ReadReg(config->usart, BRR) >= 0x300U, + __ASSERT(LL_LPUART_ReadReg(usart, BRR) >= 0x300U, "BaudRateReg >= 0x300"); /* Check BRR is lower than or equal to 0xFFFFF */ - __ASSERT(LL_LPUART_ReadReg(config->usart, BRR) < 0x000FFFFFU, + __ASSERT(LL_LPUART_ReadReg(usart, BRR) < 0x000FFFFFU, "BaudRateReg < 0xFFFF"); } else { #endif /* HAS_LPUART */ #ifdef USART_CR1_OVER8 - LL_USART_SetOverSampling(config->usart, + LL_USART_SetOverSampling(usart, LL_USART_OVERSAMPLING_16); #endif - LL_USART_SetBaudRate(config->usart, + LL_USART_SetBaudRate(usart, clock_rate, #ifdef USART_PRESC_PRESCALER LL_USART_PRESCALER_DIV1, @@ -205,7 +206,7 @@ static inline void uart_stm32_set_baudrate(const struct device *dev, uint32_t ba #endif baud_rate); /* Check BRR is greater than or equal to 16d */ - __ASSERT(LL_USART_ReadReg(config->usart, BRR) >= 16, + __ASSERT(LL_USART_ReadReg(usart, BRR) >= 16, "BaudRateReg >= 16"); #if HAS_LPUART @@ -533,6 +534,7 @@ static int uart_stm32_configure(const struct device *dev, const struct uart_config *cfg) { const struct uart_stm32_config *config = dev->config; + USART_TypeDef *usart = config->usart; struct uart_stm32_data *data = dev->data; struct uart_config *uart_cfg = data->uart_cfg; const uint32_t parity = uart_stm32_cfg2ll_parity(cfg->parity); @@ -569,21 +571,21 @@ static int uart_stm32_configure(const struct device *dev, /* Driver supports only RTS/CTS and RS485 flow control */ if (!(cfg->flow_ctrl == UART_CFG_FLOW_CTRL_NONE || (cfg->flow_ctrl == UART_CFG_FLOW_CTRL_RTS_CTS && - IS_UART_HWFLOW_INSTANCE(config->usart)) + IS_UART_HWFLOW_INSTANCE(usart)) #if HAS_DRIVER_ENABLE || (cfg->flow_ctrl == UART_CFG_FLOW_CTRL_RS485 && - IS_UART_DRIVER_ENABLE_INSTANCE(config->usart)) + IS_UART_DRIVER_ENABLE_INSTANCE(usart)) #endif )) { return -ENOTSUP; } - LL_USART_Disable(config->usart); + LL_USART_Disable(usart); /* Set basic parameters, such as data-/stop-bit, parity, and baudrate */ uart_stm32_parameters_set(dev, cfg); - LL_USART_Enable(config->usart); + LL_USART_Enable(usart); /* Upon successful configuration, persist the syscall-passed * uart_config. @@ -625,17 +627,18 @@ typedef void (*poll_in_fn)( static int uart_stm32_poll_in_visitor(const struct device *dev, void *in, poll_in_fn get_fn) { const struct uart_stm32_config *config = dev->config; + USART_TypeDef *usart = config->usart; /* Clear overrun error flag */ - if (LL_USART_IsActiveFlag_ORE(config->usart)) { - LL_USART_ClearFlag_ORE(config->usart); + if (LL_USART_IsActiveFlag_ORE(usart)) { + LL_USART_ClearFlag_ORE(usart); } /* * On stm32 F4X, F1X, and F2X, the RXNE flag is affected (cleared) by * the uart_err_check function call (on errors flags clearing) */ - if (!LL_USART_IsActiveFlag_RXNE(config->usart)) { + if (!LL_USART_IsActiveFlag_RXNE(usart)) { return -1; } @@ -650,6 +653,7 @@ typedef void (*poll_out_fn)( static void uart_stm32_poll_out_visitor(const struct device *dev, void *out, poll_out_fn set_fn) { const struct uart_stm32_config *config = dev->config; + USART_TypeDef *usart = config->usart; #ifdef CONFIG_PM struct uart_stm32_data *data = dev->data; #endif @@ -661,9 +665,9 @@ static void uart_stm32_poll_out_visitor(const struct device *dev, void *out, pol * interlaced with the characters potentially send with interrupt transmission API */ while (1) { - if (LL_USART_IsActiveFlag_TXE(config->usart)) { + if (LL_USART_IsActiveFlag_TXE(usart)) { key = irq_lock(); - if (LL_USART_IsActiveFlag_TXE(config->usart)) { + if (LL_USART_IsActiveFlag_TXE(usart)) { break; } irq_unlock(key); @@ -686,7 +690,7 @@ static void uart_stm32_poll_out_visitor(const struct device *dev, void *out, pol /* Enable TC interrupt so we can release suspend * constraint when done */ - LL_USART_EnableIT_TC(config->usart); + LL_USART_EnableIT_TC(usart); } #endif /* CONFIG_PM */ @@ -741,6 +745,7 @@ static void uart_stm32_poll_out_u16(const struct device *dev, uint16_t out_u16) static int uart_stm32_err_check(const struct device *dev) { const struct uart_stm32_config *config = dev->config; + USART_TypeDef *usart = config->usart; uint32_t err = 0U; /* Check for errors, then clear them. @@ -748,29 +753,29 @@ static int uart_stm32_err_check(const struct device *dev) * one is cleared. (e.g. F4X, F1X, and F2X). * The stm32 F4X, F1X, and F2X also reads the usart DR when clearing Errors */ - if (LL_USART_IsActiveFlag_ORE(config->usart)) { + if (LL_USART_IsActiveFlag_ORE(usart)) { err |= UART_ERROR_OVERRUN; } - if (LL_USART_IsActiveFlag_PE(config->usart)) { + if (LL_USART_IsActiveFlag_PE(usart)) { err |= UART_ERROR_PARITY; } - if (LL_USART_IsActiveFlag_FE(config->usart)) { + if (LL_USART_IsActiveFlag_FE(usart)) { err |= UART_ERROR_FRAMING; } - if (LL_USART_IsActiveFlag_NE(config->usart)) { + if (LL_USART_IsActiveFlag_NE(usart)) { err |= UART_ERROR_NOISE; } #if !defined(CONFIG_SOC_SERIES_STM32F0X) || defined(USART_LIN_SUPPORT) - if (LL_USART_IsActiveFlag_LBD(config->usart)) { + if (LL_USART_IsActiveFlag_LBD(usart)) { err |= UART_BREAK; } if (err & UART_BREAK) { - LL_USART_ClearFlag_LBD(config->usart); + LL_USART_ClearFlag_LBD(usart); } #endif /* Clearing error : @@ -779,19 +784,19 @@ static int uart_stm32_err_check(const struct device *dev) * --> so is the RXNE flag also cleared ! */ if (err & UART_ERROR_OVERRUN) { - LL_USART_ClearFlag_ORE(config->usart); + LL_USART_ClearFlag_ORE(usart); } if (err & UART_ERROR_PARITY) { - LL_USART_ClearFlag_PE(config->usart); + LL_USART_ClearFlag_PE(usart); } if (err & UART_ERROR_FRAMING) { - LL_USART_ClearFlag_FE(config->usart); + LL_USART_ClearFlag_FE(usart); } if (err & UART_ERROR_NOISE) { - LL_USART_ClearFlag_NE(config->usart); + LL_USART_ClearFlag_NE(usart); } return err; @@ -814,17 +819,18 @@ static int uart_stm32_fifo_fill_visitor(const struct device *dev, const void *tx fifo_fill_fn fill_fn) { const struct uart_stm32_config *config = dev->config; + USART_TypeDef *usart = config->usart; uint8_t num_tx = 0U; unsigned int key; - if (!LL_USART_IsActiveFlag_TXE(config->usart)) { + if (!LL_USART_IsActiveFlag_TXE(usart)) { return num_tx; } /* Lock interrupts to prevent nested interrupts or thread switch */ key = irq_lock(); - while ((size - num_tx > 0) && LL_USART_IsActiveFlag_TXE(config->usart)) { + while ((size - num_tx > 0) && LL_USART_IsActiveFlag_TXE(usart)) { /* TXE flag will be cleared with byte write to DR|RDR register */ /* Send a character */ @@ -862,17 +868,18 @@ static int uart_stm32_fifo_read_visitor(const struct device *dev, void *rx_data, fifo_read_fn read_fn) { const struct uart_stm32_config *config = dev->config; + USART_TypeDef *usart = config->usart; uint8_t num_rx = 0U; - while ((size - num_rx > 0) && LL_USART_IsActiveFlag_RXNE(config->usart)) { + while ((size - num_rx > 0) && LL_USART_IsActiveFlag_RXNE(usart)) { /* RXNE flag will be cleared upon read from DR|RDR register */ read_fn(config, rx_data, num_rx); num_rx++; /* Clear overrun error flag */ - if (LL_USART_IsActiveFlag_ORE(config->usart)) { - LL_USART_ClearFlag_ORE(config->usart); + if (LL_USART_IsActiveFlag_ORE(usart)) { + LL_USART_ClearFlag_ORE(usart); /* * On stm32 F4X, F1X, and F2X, the RXNE flag is affected (cleared) by * the uart_err_check function call (on errors flags clearing) @@ -1027,43 +1034,46 @@ static int uart_stm32_irq_rx_ready(const struct device *dev) static void uart_stm32_irq_err_enable(const struct device *dev) { const struct uart_stm32_config *config = dev->config; + USART_TypeDef *usart = config->usart; /* Enable FE, ORE interruptions */ - LL_USART_EnableIT_ERROR(config->usart); + LL_USART_EnableIT_ERROR(usart); #if !defined(CONFIG_SOC_SERIES_STM32F0X) || defined(USART_LIN_SUPPORT) /* Enable Line break detection */ - if (IS_UART_LIN_INSTANCE(config->usart)) { - LL_USART_EnableIT_LBD(config->usart); + if (IS_UART_LIN_INSTANCE(usart)) { + LL_USART_EnableIT_LBD(usart); } #endif /* Enable parity error interruption */ - LL_USART_EnableIT_PE(config->usart); + LL_USART_EnableIT_PE(usart); } static void uart_stm32_irq_err_disable(const struct device *dev) { const struct uart_stm32_config *config = dev->config; + USART_TypeDef *usart = config->usart; /* Disable FE, ORE interruptions */ - LL_USART_DisableIT_ERROR(config->usart); + LL_USART_DisableIT_ERROR(usart); #if !defined(CONFIG_SOC_SERIES_STM32F0X) || defined(USART_LIN_SUPPORT) /* Disable Line break detection */ - if (IS_UART_LIN_INSTANCE(config->usart)) { - LL_USART_DisableIT_LBD(config->usart); + if (IS_UART_LIN_INSTANCE(usart)) { + LL_USART_DisableIT_LBD(usart); } #endif /* Disable parity error interruption */ - LL_USART_DisableIT_PE(config->usart); + LL_USART_DisableIT_PE(usart); } static int uart_stm32_irq_is_pending(const struct device *dev) { const struct uart_stm32_config *config = dev->config; + USART_TypeDef *usart = config->usart; - return ((LL_USART_IsActiveFlag_RXNE(config->usart) && - LL_USART_IsEnabledIT_RXNE(config->usart)) || - (LL_USART_IsActiveFlag_TC(config->usart) && - LL_USART_IsEnabledIT_TC(config->usart))); + return ((LL_USART_IsActiveFlag_RXNE(usart) && + LL_USART_IsEnabledIT_RXNE(usart)) || + (LL_USART_IsActiveFlag_TC(usart) && + LL_USART_IsEnabledIT_TC(usart))); } static int uart_stm32_irq_update(const struct device *dev) @@ -1224,17 +1234,18 @@ static void uart_stm32_isr(const struct device *dev) struct uart_stm32_data *data = dev->data; #if defined(CONFIG_PM) || defined(CONFIG_UART_ASYNC_API) const struct uart_stm32_config *config = dev->config; + USART_TypeDef *usart = config->usart; #endif #ifdef CONFIG_PM - if (LL_USART_IsEnabledIT_TC(config->usart) && - LL_USART_IsActiveFlag_TC(config->usart)) { + if (LL_USART_IsEnabledIT_TC(usart) && + LL_USART_IsActiveFlag_TC(usart)) { if (data->tx_poll_stream_on) { /* A poll stream transmission just completed, * allow system to suspend */ - LL_USART_DisableIT_TC(config->usart); + LL_USART_DisableIT_TC(usart); data->tx_poll_stream_on = false; uart_stm32_pm_policy_state_lock_put(dev); } @@ -1252,10 +1263,10 @@ static void uart_stm32_isr(const struct device *dev) #endif /* CONFIG_UART_INTERRUPT_DRIVEN */ #ifdef CONFIG_UART_ASYNC_API - if (LL_USART_IsEnabledIT_IDLE(config->usart) && - LL_USART_IsActiveFlag_IDLE(config->usart)) { + if (LL_USART_IsEnabledIT_IDLE(usart) && + LL_USART_IsActiveFlag_IDLE(usart)) { - LL_USART_ClearFlag_IDLE(config->usart); + LL_USART_ClearFlag_IDLE(usart); LOG_DBG("idle interrupt occurred"); @@ -1266,24 +1277,24 @@ static void uart_stm32_isr(const struct device *dev) async_timer_start(&data->dma_rx.timeout_work, data->dma_rx.timeout); } - } else if (LL_USART_IsEnabledIT_TC(config->usart) && - LL_USART_IsActiveFlag_TC(config->usart)) { + } else if (LL_USART_IsEnabledIT_TC(usart) && + LL_USART_IsActiveFlag_TC(usart)) { - LL_USART_DisableIT_TC(config->usart); + LL_USART_DisableIT_TC(usart); /* Generate TX_DONE event when transmission is done */ async_evt_tx_done(data); #ifdef CONFIG_PM uart_stm32_pm_policy_state_lock_put(dev); #endif - } else if (LL_USART_IsEnabledIT_RXNE(config->usart) && - LL_USART_IsActiveFlag_RXNE(config->usart)) { + } else if (LL_USART_IsEnabledIT_RXNE(usart) && + LL_USART_IsActiveFlag_RXNE(usart)) { #ifdef USART_SR_RXNE /* clear the RXNE flag, because Rx data was not read */ - LL_USART_ClearFlag_RXNE(config->usart); + LL_USART_ClearFlag_RXNE(usart); #else /* clear the RXNE by flushing the fifo, because Rx data was not read */ - LL_USART_RequestRxDataFlush(config->usart); + LL_USART_RequestRxDataFlush(usart); #endif /* USART_SR_RXNE */ } @@ -1293,12 +1304,12 @@ static void uart_stm32_isr(const struct device *dev) #if defined(CONFIG_PM) && defined(IS_UART_WAKEUP_FROMSTOP_INSTANCE) \ && defined(USART_CR3_WUFIE) - if (LL_USART_IsEnabledIT_WKUP(config->usart) && - LL_USART_IsActiveFlag_WKUP(config->usart)) { + if (LL_USART_IsEnabledIT_WKUP(usart) && + LL_USART_IsActiveFlag_WKUP(usart)) { - LL_USART_ClearFlag_WKUP(config->usart); + LL_USART_ClearFlag_WKUP(usart); #ifdef USART_ISR_REACK - while (LL_USART_IsActiveFlag_REACK(config->usart) == 0) { + while (LL_USART_IsActiveFlag_REACK(usart) == 0) { } #endif } @@ -1395,6 +1406,7 @@ static inline void uart_stm32_dma_rx_disable(const struct device *dev) static int uart_stm32_async_rx_disable(const struct device *dev) { const struct uart_stm32_config *config = dev->config; + USART_TypeDef *usart = config->usart; struct uart_stm32_data *data = dev->data; struct uart_event disabled_event = { .type = UART_RX_DISABLED @@ -1405,7 +1417,7 @@ static int uart_stm32_async_rx_disable(const struct device *dev) return -EFAULT; } - LL_USART_DisableIT_IDLE(config->usart); + LL_USART_DisableIT_IDLE(usart); uart_stm32_dma_rx_flush(dev); @@ -1429,7 +1441,7 @@ static int uart_stm32_async_rx_disable(const struct device *dev) data->rx_next_buffer_len = 0; /* When async rx is disabled, enable interruptible instance of uart to function normally */ - LL_USART_EnableIT_RXNE(config->usart); + LL_USART_EnableIT_RXNE(usart); LOG_DBG("rx: disabled"); @@ -1465,6 +1477,7 @@ void uart_stm32_dma_tx_cb(const struct device *dma_dev, void *user_data, static void uart_stm32_dma_replace_buffer(const struct device *dev) { const struct uart_stm32_config *config = dev->config; + USART_TypeDef *usart = config->usart; struct uart_stm32_data *data = dev->data; /* Replace the buffer and reload the DMA */ @@ -1487,7 +1500,7 @@ static void uart_stm32_dma_replace_buffer(const struct device *dev) dma_start(data->dma_rx.dma_dev, data->dma_rx.dma_channel); - LL_USART_ClearFlag_IDLE(config->usart); + LL_USART_ClearFlag_IDLE(usart); /* Request next buffer */ async_evt_rx_buf_request(data); @@ -1534,6 +1547,7 @@ static int uart_stm32_async_tx(const struct device *dev, const uint8_t *tx_data, size_t buf_size, int32_t timeout) { const struct uart_stm32_config *config = dev->config; + USART_TypeDef *usart = config->usart; struct uart_stm32_data *data = dev->data; int ret; @@ -1559,10 +1573,10 @@ static int uart_stm32_async_tx(const struct device *dev, LOG_DBG("tx: l=%d", data->dma_tx.buffer_length); /* Clear TC flag */ - LL_USART_ClearFlag_TC(config->usart); + LL_USART_ClearFlag_TC(usart); /* Enable TC interrupt so we can signal correct TX done */ - LL_USART_EnableIT_TC(config->usart); + LL_USART_EnableIT_TC(usart); /* set source address */ data->dma_tx.blk_cfg.source_address = (uint32_t)data->dma_tx.buffer; @@ -1600,6 +1614,7 @@ static int uart_stm32_async_rx_enable(const struct device *dev, uint8_t *rx_buf, size_t buf_size, int32_t timeout) { const struct uart_stm32_config *config = dev->config; + USART_TypeDef *usart = config->usart; struct uart_stm32_data *data = dev->data; int ret; @@ -1626,7 +1641,7 @@ static int uart_stm32_async_rx_enable(const struct device *dev, data->dma_rx.timeout = timeout; /* Disable RX interrupts to let DMA to handle it */ - LL_USART_DisableIT_RXNE(config->usart); + LL_USART_DisableIT_RXNE(usart); data->dma_rx.blk_cfg.block_size = buf_size; data->dma_rx.blk_cfg.dest_address = (uint32_t)data->dma_rx.buffer; @@ -1646,9 +1661,9 @@ static int uart_stm32_async_rx_enable(const struct device *dev, /* Flush RX data buffer */ #ifdef USART_SR_RXNE - LL_USART_ClearFlag_RXNE(config->usart); + LL_USART_ClearFlag_RXNE(usart); #else - LL_USART_RequestRxDataFlush(config->usart); + LL_USART_RequestRxDataFlush(usart); #endif /* USART_SR_RXNE */ /* Enable RX DMA requests */ @@ -1657,10 +1672,10 @@ static int uart_stm32_async_rx_enable(const struct device *dev, /* Enable IRQ IDLE to define the end of a * RX DMA transaction. */ - LL_USART_ClearFlag_IDLE(config->usart); - LL_USART_EnableIT_IDLE(config->usart); + LL_USART_ClearFlag_IDLE(usart); + LL_USART_EnableIT_IDLE(usart); - LL_USART_EnableIT_ERROR(config->usart); + LL_USART_EnableIT_ERROR(usart); /* Request next buffer */ async_evt_rx_buf_request(data); @@ -1761,6 +1776,7 @@ static int uart_stm32_async_rx_buf_rsp(const struct device *dev, uint8_t *buf, static int uart_stm32_async_init(const struct device *dev) { const struct uart_stm32_config *config = dev->config; + USART_TypeDef *usart = config->usart; struct uart_stm32_data *data = dev->data; data->uart_dev = dev; @@ -1794,10 +1810,10 @@ static int uart_stm32_async_init(const struct device *dev) defined(CONFIG_SOC_SERIES_STM32F4X) || \ defined(CONFIG_SOC_SERIES_STM32L1X) data->dma_rx.blk_cfg.source_address = - LL_USART_DMA_GetRegAddr(config->usart); + LL_USART_DMA_GetRegAddr(usart); #else data->dma_rx.blk_cfg.source_address = - LL_USART_DMA_GetRegAddr(config->usart, + LL_USART_DMA_GetRegAddr(usart, LL_USART_DMA_REG_DATA_RECEIVE); #endif @@ -1833,10 +1849,10 @@ static int uart_stm32_async_init(const struct device *dev) defined(CONFIG_SOC_SERIES_STM32F4X) || \ defined(CONFIG_SOC_SERIES_STM32L1X) data->dma_tx.blk_cfg.dest_address = - LL_USART_DMA_GetRegAddr(config->usart); + LL_USART_DMA_GetRegAddr(usart); #else data->dma_tx.blk_cfg.dest_address = - LL_USART_DMA_GetRegAddr(config->usart, + LL_USART_DMA_GetRegAddr(usart, LL_USART_DMA_REG_DATA_TRANSMIT); #endif @@ -1968,10 +1984,11 @@ static int uart_stm32_clocks_enable(const struct device *dev) static int uart_stm32_registers_configure(const struct device *dev) { const struct uart_stm32_config *config = dev->config; + USART_TypeDef *usart = config->usart; struct uart_stm32_data *data = dev->data; struct uart_config *uart_cfg = data->uart_cfg; - LL_USART_Disable(config->usart); + LL_USART_Disable(usart); if (!device_is_ready(config->reset.dev)) { LOG_ERR("reset controller not ready"); @@ -1982,55 +1999,54 @@ static int uart_stm32_registers_configure(const struct device *dev) (void)reset_line_toggle_dt(&config->reset); /* TX/RX direction */ - LL_USART_SetTransferDirection(config->usart, - LL_USART_DIRECTION_TX_RX); + LL_USART_SetTransferDirection(usart, LL_USART_DIRECTION_TX_RX); /* Set basic parameters, such as data-/stop-bit, parity, and baudrate */ uart_stm32_parameters_set(dev, uart_cfg); /* Enable the single wire / half-duplex mode */ if (config->single_wire) { - LL_USART_EnableHalfDuplex(config->usart); + LL_USART_EnableHalfDuplex(usart); } #ifdef LL_USART_TXRX_SWAPPED if (config->tx_rx_swap) { - LL_USART_SetTXRXSwap(config->usart, LL_USART_TXRX_SWAPPED); + LL_USART_SetTXRXSwap(usart, LL_USART_TXRX_SWAPPED); } #endif #ifdef LL_USART_RXPIN_LEVEL_INVERTED if (config->rx_invert) { - LL_USART_SetRXPinLevel(config->usart, LL_USART_RXPIN_LEVEL_INVERTED); + LL_USART_SetRXPinLevel(usart, LL_USART_RXPIN_LEVEL_INVERTED); } #endif #ifdef LL_USART_TXPIN_LEVEL_INVERTED if (config->tx_invert) { - LL_USART_SetTXPinLevel(config->usart, LL_USART_TXPIN_LEVEL_INVERTED); + LL_USART_SetTXPinLevel(usart, LL_USART_TXPIN_LEVEL_INVERTED); } #endif #if HAS_DRIVER_ENABLE if (config->de_enable) { - if (!IS_UART_DRIVER_ENABLE_INSTANCE(config->usart)) { + if (!IS_UART_DRIVER_ENABLE_INSTANCE(usart)) { LOG_ERR("%s does not support driver enable", dev->name); return -EINVAL; } uart_stm32_set_driver_enable(dev, true); - LL_USART_SetDEAssertionTime(config->usart, config->de_assert_time); - LL_USART_SetDEDeassertionTime(config->usart, config->de_deassert_time); + LL_USART_SetDEAssertionTime(usart, config->de_assert_time); + LL_USART_SetDEDeassertionTime(usart, config->de_deassert_time); if (config->de_invert) { - LL_USART_SetDESignalPolarity(config->usart, LL_USART_DE_POLARITY_LOW); + LL_USART_SetDESignalPolarity(usart, LL_USART_DE_POLARITY_LOW); } } #endif #ifdef USART_CR1_FIFOEN if (config->fifo_enable) { - LL_USART_EnableFIFO(config->usart); + LL_USART_EnableFIFO(usart); } #endif @@ -2042,11 +2058,11 @@ static int uart_stm32_registers_configure(const struct device *dev) * CONFIG_PM_DEVICE=y : Controlled by pm_device_wakeup_enable() */ #ifdef USART_CR3_WUFIE - LL_USART_SetWKUPType(config->usart, LL_USART_WAKEUP_ON_RXNE); - LL_USART_EnableIT_WKUP(config->usart); - LL_USART_ClearFlag_WKUP(config->usart); + LL_USART_SetWKUPType(usart, LL_USART_WAKEUP_ON_RXNE); + LL_USART_EnableIT_WKUP(usart); + LL_USART_ClearFlag_WKUP(usart); #endif - LL_USART_EnableInStopMode(config->usart); + LL_USART_EnableInStopMode(usart); if (config->wakeup_line != STM32_EXTI_LINE_NONE) { /* Prepare the WAKEUP with the expected EXTI line */ @@ -2055,17 +2071,17 @@ static int uart_stm32_registers_configure(const struct device *dev) } #endif /* CONFIG_PM */ - LL_USART_Enable(config->usart); + LL_USART_Enable(usart); #ifdef USART_ISR_TEACK /* Wait until TEACK flag is set */ - while (!(LL_USART_IsActiveFlag_TEACK(config->usart))) { + while (!(LL_USART_IsActiveFlag_TEACK(usart))) { } #endif /* !USART_ISR_TEACK */ #ifdef USART_ISR_REACK /* Wait until REACK flag is set */ - while (!(LL_USART_IsActiveFlag_REACK(config->usart))) { + while (!(LL_USART_IsActiveFlag_REACK(usart))) { } #endif /* !USART_ISR_REACK */ @@ -2120,21 +2136,22 @@ static int uart_stm32_init(const struct device *dev) static void uart_stm32_suspend_setup(const struct device *dev) { const struct uart_stm32_config *config = dev->config; + USART_TypeDef *usart = config->usart; #ifdef USART_ISR_BUSY /* Make sure that no USART transfer is on-going */ - while (LL_USART_IsActiveFlag_BUSY(config->usart) == 1) { + while (LL_USART_IsActiveFlag_BUSY(usart) == 1) { } #endif - while (LL_USART_IsActiveFlag_TC(config->usart) == 0) { + while (LL_USART_IsActiveFlag_TC(usart) == 0) { } #ifdef USART_ISR_REACK /* Make sure that USART is ready for reception */ - while (LL_USART_IsActiveFlag_REACK(config->usart) == 0) { + while (LL_USART_IsActiveFlag_REACK(usart) == 0) { } #endif /* Clear OVERRUN flag */ - LL_USART_ClearFlag_ORE(config->usart); + LL_USART_ClearFlag_ORE(usart); } static int uart_stm32_pm_action(const struct device *dev, From f503b7a26d3d11cb54f9dfe6f0372ff2f19e4573 Mon Sep 17 00:00:00 2001 From: Pisit Sawangvonganan Date: Fri, 24 May 2024 13:17:38 +0700 Subject: [PATCH 1211/2849] drivers: serial: stm32: replace `config` parameter with `usart` Updated function parameters from `const struct uart_stm32_config *config` to `USART_TypeDef *usart`. This change reduces the level of pointer indirection, which minimizes repeated dereferencing and helps reduce the overall code size. Signed-off-by: Pisit Sawangvonganan --- drivers/serial/uart_stm32.c | 48 ++++++++++++++++++------------------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/drivers/serial/uart_stm32.c b/drivers/serial/uart_stm32.c index 628b6c379a955..10e5b310d8ff0 100644 --- a/drivers/serial/uart_stm32.c +++ b/drivers/serial/uart_stm32.c @@ -621,7 +621,7 @@ static int uart_stm32_config_get(const struct device *dev, #endif /* CONFIG_UART_USE_RUNTIME_CONFIGURE */ typedef void (*poll_in_fn)( - const struct uart_stm32_config *config, + USART_TypeDef *usart, void *in); static int uart_stm32_poll_in_visitor(const struct device *dev, void *in, poll_in_fn get_fn) @@ -642,13 +642,13 @@ static int uart_stm32_poll_in_visitor(const struct device *dev, void *in, poll_i return -1; } - get_fn(config, in); + get_fn(usart, in); return 0; } typedef void (*poll_out_fn)( - const struct uart_stm32_config *config, void *out); + USART_TypeDef *usart, void *out); static void uart_stm32_poll_out_visitor(const struct device *dev, void *out, poll_out_fn set_fn) { @@ -694,18 +694,18 @@ static void uart_stm32_poll_out_visitor(const struct device *dev, void *out, pol } #endif /* CONFIG_PM */ - set_fn(config, out); + set_fn(usart, out); irq_unlock(key); } -static void poll_in_u8(const struct uart_stm32_config *config, void *in) +static void poll_in_u8(USART_TypeDef *usart, void *in) { - *((unsigned char *)in) = (unsigned char)LL_USART_ReceiveData8(config->usart); + *((unsigned char *)in) = (unsigned char)LL_USART_ReceiveData8(usart); } -static void poll_out_u8(const struct uart_stm32_config *config, void *out) +static void poll_out_u8(USART_TypeDef *usart, void *out) { - LL_USART_TransmitData8(config->usart, *((uint8_t *)out)); + LL_USART_TransmitData8(usart, *((uint8_t *)out)); } static int uart_stm32_poll_in(const struct device *dev, unsigned char *c) @@ -720,14 +720,14 @@ static void uart_stm32_poll_out(const struct device *dev, unsigned char c) #ifdef CONFIG_UART_WIDE_DATA -static void poll_out_u9(const struct uart_stm32_config *config, void *out) +static void poll_out_u9(USART_TypeDef *usart, void *out) { - LL_USART_TransmitData9(config->usart, *((uint16_t *)out)); + LL_USART_TransmitData9(usart, *((uint16_t *)out)); } -static void poll_in_u9(const struct uart_stm32_config *config, void *in) +static void poll_in_u9(USART_TypeDef *usart, void *in) { - *((uint16_t *)in) = LL_USART_ReceiveData9(config->usart); + *((uint16_t *)in) = LL_USART_ReceiveData9(usart); } static int uart_stm32_poll_in_u16(const struct device *dev, uint16_t *in_u16) @@ -812,7 +812,7 @@ static inline void __uart_stm32_get_clock(const struct device *dev) #ifdef CONFIG_UART_INTERRUPT_DRIVEN -typedef void (*fifo_fill_fn)(const struct uart_stm32_config *config, const void *tx_data, +typedef void (*fifo_fill_fn)(USART_TypeDef *usart, const void *tx_data, const uint8_t offset); static int uart_stm32_fifo_fill_visitor(const struct device *dev, const void *tx_data, int size, @@ -834,7 +834,7 @@ static int uart_stm32_fifo_fill_visitor(const struct device *dev, const void *tx /* TXE flag will be cleared with byte write to DR|RDR register */ /* Send a character */ - fill_fn(config, tx_data, num_tx); + fill_fn(usart, tx_data, num_tx); num_tx++; } @@ -843,12 +843,12 @@ static int uart_stm32_fifo_fill_visitor(const struct device *dev, const void *tx return num_tx; } -static void fifo_fill_with_u8(const struct uart_stm32_config *config, +static void fifo_fill_with_u8(USART_TypeDef *usart, const void *tx_data, const uint8_t offset) { const uint8_t *data = (const uint8_t *)tx_data; /* Send a character (8bit) */ - LL_USART_TransmitData8(config->usart, data[offset]); + LL_USART_TransmitData8(usart, data[offset]); } static int uart_stm32_fifo_fill(const struct device *dev, const uint8_t *tx_data, int size) @@ -861,7 +861,7 @@ static int uart_stm32_fifo_fill(const struct device *dev, const uint8_t *tx_data fifo_fill_with_u8); } -typedef void (*fifo_read_fn)(const struct uart_stm32_config *config, void *rx_data, +typedef void (*fifo_read_fn)(USART_TypeDef *usart, void *rx_data, const uint8_t offset); static int uart_stm32_fifo_read_visitor(const struct device *dev, void *rx_data, const int size, @@ -874,7 +874,7 @@ static int uart_stm32_fifo_read_visitor(const struct device *dev, void *rx_data, while ((size - num_rx > 0) && LL_USART_IsActiveFlag_RXNE(usart)) { /* RXNE flag will be cleared upon read from DR|RDR register */ - read_fn(config, rx_data, num_rx); + read_fn(usart, rx_data, num_rx); num_rx++; /* Clear overrun error flag */ @@ -890,12 +890,12 @@ static int uart_stm32_fifo_read_visitor(const struct device *dev, void *rx_data, return num_rx; } -static void fifo_read_with_u8(const struct uart_stm32_config *config, void *rx_data, +static void fifo_read_with_u8(USART_TypeDef *usart, void *rx_data, const uint8_t offset) { uint8_t *data = (uint8_t *)rx_data; - data[offset] = LL_USART_ReceiveData8(config->usart); + data[offset] = LL_USART_ReceiveData8(usart); } static int uart_stm32_fifo_read(const struct device *dev, uint8_t *rx_data, const int size) @@ -910,13 +910,13 @@ static int uart_stm32_fifo_read(const struct device *dev, uint8_t *rx_data, cons #ifdef CONFIG_UART_WIDE_DATA -static void fifo_fill_with_u16(const struct uart_stm32_config *config, +static void fifo_fill_with_u16(USART_TypeDef *usart, const void *tx_data, const uint8_t offset) { const uint16_t *data = (const uint16_t *)tx_data; /* Send a character (9bit) */ - LL_USART_TransmitData9(config->usart, data[offset]); + LL_USART_TransmitData9(usart, data[offset]); } static int uart_stm32_fifo_fill_u16(const struct device *dev, const uint16_t *tx_data, int size) @@ -929,12 +929,12 @@ static int uart_stm32_fifo_fill_u16(const struct device *dev, const uint16_t *tx fifo_fill_with_u16); } -static void fifo_read_with_u16(const struct uart_stm32_config *config, void *rx_data, +static void fifo_read_with_u16(USART_TypeDef *usart, void *rx_data, const uint8_t offset) { uint16_t *data = (uint16_t *)rx_data; - data[offset] = LL_USART_ReceiveData9(config->usart); + data[offset] = LL_USART_ReceiveData9(usart); } static int uart_stm32_fifo_read_u16(const struct device *dev, uint16_t *rx_data, const int size) From 8cd8e53faf69ff47400edfdadd6a7521a6c7fc65 Mon Sep 17 00:00:00 2001 From: Erwan Gouriou Date: Thu, 23 May 2024 11:51:35 +0200 Subject: [PATCH 1212/2849] drivers: ethernet: stm32: Remove deprecated API support on impacted series In release V3.3 new STM32Cube HAL ethernet API was added to STM32 ethernet driver for STM32F4, STM32F7 and STM32H7 series. At the same time, the legacy API was deprecated for these series. I'm now fully removing the legacy API support for these series. Signed-off-by: Erwan Gouriou --- drivers/ethernet/Kconfig.stm32_hal | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/ethernet/Kconfig.stm32_hal b/drivers/ethernet/Kconfig.stm32_hal index 6bd0c65f9b91e..f980091a755ab 100644 --- a/drivers/ethernet/Kconfig.stm32_hal +++ b/drivers/ethernet/Kconfig.stm32_hal @@ -24,17 +24,17 @@ choice ETH_STM32_HAL_API_VERSION prompt "STM32Cube HAL Ethernet version" config ETH_STM32_HAL_API_V2 - bool "Use new HAL driver" + bool "Use official STM32Cube HAL driver" depends on SOC_SERIES_STM32H7X || SOC_SERIES_STM32H5X || SOC_SERIES_STM32F4X || SOC_SERIES_STM32F7X help - Use the new HAL driver instead of the legacy one. + Use the official STM32Cube HAL driver instead of the legacy one. config ETH_STM32_HAL_API_V1 - bool "Use legacy HAL driver" - depends on !SOC_SERIES_STM32H5X - select DEPRECATED if SOC_SERIES_STM32H7X || SOC_SERIES_STM32F4X || SOC_SERIES_STM32F7X + bool "Use legacy STM32Cube HAL driver" + depends on SOC_SERIES_STM32F1X || SOC_SERIES_STM32F2X help - Driver version based on legacy HAL version. Deprecated unless using STM32F2 series. + Driver version based on legacy HAL version as the current official API version. + Available only for STM32F1 and STM32F2 SoC series. endchoice From 4cec19952fbbf85c27b379a1c4af0082d25555da Mon Sep 17 00:00:00 2001 From: Alvis Sun Date: Wed, 8 May 2024 11:32:14 +0800 Subject: [PATCH 1213/2849] drivers: i3c: add hdr command code for i3c_msg Support 128 possible write and read commands for HDR-DDR, HDR-TSP and HDR-TSL. Signed-off-by: Alvis Sun --- include/zephyr/drivers/i3c.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/include/zephyr/drivers/i3c.h b/include/zephyr/drivers/i3c.h index 7233143fc705d..5b93bdb23d56c 100644 --- a/include/zephyr/drivers/i3c.h +++ b/include/zephyr/drivers/i3c.h @@ -498,6 +498,9 @@ struct i3c_msg { * Use SDR mode if none is set. */ uint8_t hdr_mode; + + /** HDR command code field (7-bit) for HDR-DDR, HDR-TSP and HDR-TSL */ + uint8_t hdr_cmd_code; }; /** @} */ @@ -1827,6 +1830,7 @@ static inline int i3c_write(struct i3c_device_desc *target, msg.buf = (uint8_t *)buf; msg.len = num_bytes; msg.flags = I3C_MSG_WRITE | I3C_MSG_STOP; + msg.hdr_cmd_code = 0; return i3c_transfer(target, &msg, 1); } @@ -1852,6 +1856,7 @@ static inline int i3c_read(struct i3c_device_desc *target, msg.buf = buf; msg.len = num_bytes; msg.flags = I3C_MSG_READ | I3C_MSG_STOP; + msg.hdr_cmd_code = 0; return i3c_transfer(target, &msg, 1); } @@ -1882,10 +1887,12 @@ static inline int i3c_write_read(struct i3c_device_desc *target, msg[0].buf = (uint8_t *)write_buf; msg[0].len = num_write; msg[0].flags = I3C_MSG_WRITE; + msg[0].hdr_cmd_code = 0; msg[1].buf = (uint8_t *)read_buf; msg[1].len = num_read; msg[1].flags = I3C_MSG_RESTART | I3C_MSG_READ | I3C_MSG_STOP; + msg[1].hdr_cmd_code = 0; return i3c_transfer(target, msg, 2); } @@ -1947,10 +1954,12 @@ static inline int i3c_burst_write(struct i3c_device_desc *target, msg[0].buf = &start_addr; msg[0].len = 1U; msg[0].flags = I3C_MSG_WRITE; + msg[0].hdr_cmd_code = 0; msg[1].buf = (uint8_t *)buf; msg[1].len = num_bytes; msg[1].flags = I3C_MSG_WRITE | I3C_MSG_STOP; + msg[1].hdr_cmd_code = 0; return i3c_transfer(target, msg, 2); } From 03580e4a1bde267aad7a11cb95aec49b593b92f9 Mon Sep 17 00:00:00 2001 From: Alvis Sun Date: Wed, 8 May 2024 11:20:04 +0800 Subject: [PATCH 1214/2849] drivers: i3c: npcx: add HDR-DDR mode for transfer 1. Support HDR-DDR DMA transfer. 2. Remove polling mode in transfer. Signed-off-by: Alvis Sun --- drivers/i3c/i3c_npcx.c | 185 +++++++++++++++++++++----- soc/nuvoton/npcx/common/reg/reg_def.h | 5 + 2 files changed, 155 insertions(+), 35 deletions(-) diff --git a/drivers/i3c/i3c_npcx.c b/drivers/i3c/i3c_npcx.c index 9790e593915e2..75b9c73c9669d 100644 --- a/drivers/i3c/i3c_npcx.c +++ b/drivers/i3c/i3c_npcx.c @@ -39,11 +39,14 @@ LOG_MODULE_REGISTER(npcx_i3c, CONFIG_I3C_LOG_LEVEL); #define MCLKD_FREQ_45_MHZ MHZ(45) -#define I3C_STATUS_CLR_MASK \ - (BIT(NPCX_I3C_MSTATUS_TGTSTART) | BIT(NPCX_I3C_MSTATUS_MCTRLDONE) | \ - BIT(NPCX_I3C_MSTATUS_COMPLETE) | BIT(NPCX_I3C_MSTATUS_IBIWON) | \ +#define I3C_STATUS_CLR_MASK \ + (BIT(NPCX_I3C_MSTATUS_TGTSTART) | BIT(NPCX_I3C_MSTATUS_MCTRLDONE) | \ + BIT(NPCX_I3C_MSTATUS_COMPLETE) | BIT(NPCX_I3C_MSTATUS_IBIWON) | \ BIT(NPCX_I3C_MSTATUS_NOWCNTLR)) +#define HDR_DDR_CMD_AND_CRC_SZ_WORD 0x2 /* 2 words = Command(1 word) + CRC(1 word) */ +#define HDR_RD_CMD 0x80 + /* Supported I3C MCLKD frequency */ enum npcx_i3c_speed { NPCX_I3C_BUS_SPEED_45MHZ, @@ -217,7 +220,7 @@ static inline void npcx_i3c_interrupt_enable(struct i3c_reg *inst, uint32_t mask static bool npcx_i3c_has_error(struct i3c_reg *inst) { if (IS_BIT_SET(inst->MSTATUS, NPCX_I3C_MSTATUS_ERRWARN)) { - LOG_WRN("ERROR: MSTATUS 0x%08x MERRWARN 0x%08x", inst->MSTATUS, inst->MERRWARN); + LOG_ERR("ERROR: MSTATUS 0x%08x MERRWARN 0x%08x", inst->MSTATUS, inst->MERRWARN); return true; } @@ -314,7 +317,8 @@ static inline int npcx_i3c_request_auto_ibi(struct i3c_reg *inst) * param[in] addr Dyamic address for xfer or 0x7E for CCC command. * param[in] op_type Request type. * param[in] is_read Read(true) or write(false) operation. - * param[in] read_sz Read size. + * param[in] read_sz Read size in bytes. + * If op_tye is HDR-DDR, the read_sz must be the number of words. * * return 0, success * else, error @@ -396,6 +400,56 @@ static inline int npcx_i3c_request_emit_stop(struct i3c_reg *inst) return 0; } +static inline int npcx_i3c_request_hdr_exit(struct i3c_reg *inst) +{ + uint32_t val = 0; + uint32_t state; + int ret; + + /* Before sending the HDR exit command, check the HDR mode */ + state = npcx_i3c_state_get(inst); + if (state != MSTATUS_STATE_MSGDDR) { + LOG_ERR("%s, state error: %#x", __func__, state); + return -EPERM; + } + + SET_FIELD(val, NPCX_I3C_MCTRL_TYPE, MCTRL_TYPE_HDR_EXIT); + SET_FIELD(val, NPCX_I3C_MCTRL_REQUEST, MCTRL_REQUEST_FORCEEXIT); + + ret = npcx_i3c_send_request(inst, val); + if (ret != 0) { + LOG_ERR("Request hdr exit error %d", ret); + return ret; + } + + return 0; +} + +static inline int npcx_i3c_xfer_stop(struct i3c_reg *inst) +{ + uint32_t state; + int ret; + + state = npcx_i3c_state_get(inst); + LOG_DBG("%s, state=%d", __func__, state); + + switch (state) { + case MSTATUS_STATE_NORMACT: /* SDR */ + ret = npcx_i3c_request_emit_stop(inst); + break; + case MSTATUS_STATE_MSGDDR: /* HDR-DDR */ + ret = npcx_i3c_request_hdr_exit(inst); + break; + default: + /* Not supported */ + ret = -ENOTSUP; + LOG_WRN("xfer_stop state not supported, state:%d", state); + break; + } + + return ret; +} + static inline int npcx_i3c_ibi_respond_nack(struct i3c_reg *inst) { uint32_t val = 0; @@ -668,6 +722,7 @@ static int npcx_i3c_xfer_write_fifo_dma(const struct device *dev, uint8_t *buf, /* * brief: Perform DMA read transaction. + * (Data width used for DMA transfers is "byte") * * For read end, use the MDMA end-of-transfer interrupt(SIEN bit) * instead of using the I3CI interrupt generated by COMPLETE bit in MSTATUS register. @@ -717,6 +772,7 @@ static int npcx_i3c_xfer_read_fifo_dma(const struct device *dev, uint8_t *buf, u /* * brief: Perform one transfer transaction by DMA. + * (Support SDR and HDR-DDR) * * param[in] inst Pointer to controller registers. * param[in] addr Target address. @@ -731,18 +787,45 @@ static int npcx_i3c_xfer_read_fifo_dma(const struct device *dev, uint8_t *buf, u */ static int npcx_i3c_do_one_xfer_dma(const struct device *dev, uint8_t addr, enum npcx_i3c_mctrl_type op_type, uint8_t *buf, size_t buf_sz, - bool is_read, bool emit_start, bool emit_stop) + bool is_read, bool emit_start, bool emit_stop, uint8_t hdr_cmd) { const struct npcx_i3c_config *config = dev->config; struct i3c_reg *inst = config->base; int ret = 0; + bool is_hdr_ddr = (op_type == NPCX_I3C_MCTRL_TYPE_I3C_HDR_DDR) ? true : false; + size_t rd_len = buf_sz; npcx_i3c_status_clear_all(inst); npcx_i3c_errwarn_clear_all(inst); + /* Check HDR-DDR moves data by words */ + if (is_hdr_ddr && (buf_sz % 2 != 0)) { + LOG_ERR("%s, HDR-DDR data length should be even, len=%#x", __func__, buf_sz); + return -EINVAL; + } + /* Emit START if needed */ if (emit_start) { - ret = npcx_i3c_request_emit_start(inst, addr, op_type, is_read, buf_sz); + /* + * For HDR-DDR mode read, RDTERM also includes one word (16 bits) for CRC. + * For example, to read 8 bytes, set RDTERM to 6. + * (1 word HDR-DDR command + 4 words data + 1 word for CRC) + */ + if (is_hdr_ddr) { + if (is_read) { + /* The unit of rd_len is "word" in DDR mode */ + rd_len /= sizeof(uint16_t); /* byte to word */ + rd_len += HDR_DDR_CMD_AND_CRC_SZ_WORD; + hdr_cmd |= HDR_RD_CMD; + } else { + hdr_cmd &= ~HDR_RD_CMD; + } + + /* Write the command code for the HDR-DDR message */ + inst->MWDATAB = hdr_cmd; + } + + ret = npcx_i3c_request_emit_start(inst, addr, op_type, is_read, rd_len); if (ret != 0) { LOG_ERR("%s: emit start fail", __func__); goto out_do_one_xfer_dma; @@ -773,9 +856,9 @@ static int npcx_i3c_do_one_xfer_dma(const struct device *dev, uint8_t addr, } out_do_one_xfer_dma: - /* Emit STOP if needed */ + /* Emit STOP or exit DDR if needed */ if (emit_stop) { - npcx_i3c_request_emit_stop(inst); + npcx_i3c_xfer_stop(inst); } return ret; @@ -784,6 +867,7 @@ static int npcx_i3c_do_one_xfer_dma(const struct device *dev, uint8_t addr, /* * brief: Perform one transfer transaction. + * (Support SDR only) * * param[in] inst Pointer to controller registers. * param[in] addr Target address. @@ -882,10 +966,12 @@ static int npcx_i3c_transfer(const struct device *dev, struct i3c_device_desc *t { const struct npcx_i3c_config *config = dev->config; struct i3c_reg *inst = config->base; + struct npcx_i3c_data *data = dev->data; uint32_t intmask; int xfered_len, ret = 0; bool send_broadcast = true; bool is_xfer_done = true; + enum npcx_i3c_mctrl_type op_type; if (msgs == NULL) { return -EINVAL; @@ -913,7 +999,6 @@ static int npcx_i3c_transfer(const struct device *dev, struct i3c_device_desc *t /* Iterate over all the messages */ for (int i = 0; i < num_msgs; i++) { - /* * Check message is read or write operaion. * For write operation, check the last data byte of a transmit message. @@ -958,35 +1043,63 @@ static int npcx_i3c_transfer(const struct device *dev, struct i3c_device_desc *t } #endif - /* - * Two ways to do read/write transfer . - * 1. [S] + [0x7E] + [address] + [data] + [Sr or P] - * 2. [S] + [address] + [data] + [Sr or P] - * - * Send broadcast header(0x7E) on first transfer or after a STOP, - * unless flag is set not to. - */ - if (!(msgs[i].flags & I3C_MSG_NBCH) && (send_broadcast)) { - ret = npcx_i3c_request_emit_start(inst, I3C_BROADCAST_ADDR, - NPCX_I3C_MCTRL_TYPE_I3C, false, 0); - if (ret < 0) { - LOG_ERR("%s: emit start of broadcast addr failed, error (%d)", - __func__, ret); + /* Check message SDR or HDR mode */ + bool is_msg_hdr = (msgs[i].flags & I3C_MSG_HDR) == I3C_MSG_HDR; + + /* Set emit start type SDR or HDR-DDR mode */ + if (!is_msg_hdr || msgs[i].hdr_mode == 0) { + op_type = NPCX_I3C_MCTRL_TYPE_I3C; /* Set operation type SDR */ + + /* + * SDR, send boradcast header(0x7E) + * + * Two ways to do read/write transfer (SDR mode). + * 1. [S] + [0x7E] + [address] + [data] + [Sr or P] + * 2. [S] + [address] + [data] + [Sr or P] + * + * Send broadcast header(0x7E) on first transfer or after a STOP, + * unless flag is set not to. + */ + if (!(msgs[i].flags & I3C_MSG_NBCH) && send_broadcast) { + ret = npcx_i3c_request_emit_start(inst, I3C_BROADCAST_ADDR, + NPCX_I3C_MCTRL_TYPE_I3C, false, + 0); + if (ret < 0) { + LOG_ERR("%s: emit start of broadcast addr failed, error " + "(%d)", + __func__, ret); + break; + } + send_broadcast = false; + } + } else if ((data->common.ctrl_config.supported_hdr & I3C_MSG_HDR_DDR) && + (msgs[i].hdr_mode == I3C_MSG_HDR_DDR) && is_msg_hdr) { + + op_type = NPCX_I3C_MCTRL_TYPE_I3C_HDR_DDR; /* Set operation type DDR */ + + /* Check HDR-DDR moves data by words */ + if ((msgs[i].len % 2) != 0x0) { + LOG_ERR("HDR-DDR data length should be number of words , xfer " + "len=%d", msgs[i].num_xfer); + ret = -EINVAL; break; } - send_broadcast = false; + } else { + LOG_ERR("%s: %s controller HDR Mode %#x\r\n" + "msg HDR mode %#x, msg flag %#x", + __func__, dev->name, data->common.ctrl_config.supported_hdr, + msgs[i].hdr_mode, msgs[i].flags); + ret = -ENOTSUP; + break; } #ifdef CONFIG_I3C_NPCX_DMA /* Do transfer with target device */ - xfered_len = npcx_i3c_do_one_xfer_dma(dev, target->dynamic_addr, - NPCX_I3C_MCTRL_TYPE_I3C, msgs[i].buf, - msgs[i].len, is_read, emit_start, emit_stop); -#else - xfered_len = npcx_i3c_do_one_xfer(inst, target->dynamic_addr, - NPCX_I3C_MCTRL_TYPE_I3C, msgs[i].buf, msgs[i].len, - is_read, emit_start, emit_stop, no_ending); + xfered_len = npcx_i3c_do_one_xfer_dma(dev, target->dynamic_addr, op_type, + msgs[i].buf, msgs[i].len, is_read, emit_start, + emit_stop, msgs[i].hdr_cmd_code); #endif + if (xfered_len < 0) { LOG_ERR("%s: do xfer fail", __func__); ret = xfered_len; /* Set error code to ret */ @@ -997,7 +1110,7 @@ static int npcx_i3c_transfer(const struct device *dev, struct i3c_device_desc *t msgs[i].num_xfer = xfered_len; if (emit_stop) { - /* After a STOP, send broadcast header before next msg */ + /* SDR. After a STOP, send broadcast header before next msg */ send_broadcast = true; } @@ -1009,7 +1122,7 @@ static int npcx_i3c_transfer(const struct device *dev, struct i3c_device_desc *t /* Emit stop if error occurs or stop flag not in the msg */ if ((ret != 0) || (is_xfer_done == false)) { - npcx_i3c_request_emit_stop(inst); + npcx_i3c_xfer_stop(inst); } npcx_i3c_errwarn_clear_all(inst); @@ -1681,6 +1794,8 @@ static void npcx_i3c_isr(const struct device *dev) #ifdef CONFIG_I3C_USE_IBI /* Target start detected */ if (IS_BIT_SET(inst->MSTATUS, NPCX_I3C_MSTATUS_TGTSTART)) { + LOG_DBG("ISR TGTSTART !"); + /* Disable further target initiated IBI interrupt */ inst->MINTCLR = BIT(NPCX_I3C_MINTCLR_TGTSTART); @@ -1958,7 +2073,7 @@ static int npcx_i3c_init(const struct device *dev) } ctrl_config->is_secondary = false; /* Currently can only act as primary controller. */ - ctrl_config->supported_hdr = 0U; /* HDR mode not supported at the moment. */ + ctrl_config->supported_hdr = I3C_MSG_HDR_DDR; /* HDR-DDR mode is supported. */ ctrl_config->scl.i3c = config->clocks.i3c_pp_scl_hz; /* Set I3C frequency */ ret = npcx_i3c_configure(dev, I3C_CONFIG_CONTROLLER, ctrl_config); diff --git a/soc/nuvoton/npcx/common/reg/reg_def.h b/soc/nuvoton/npcx/common/reg/reg_def.h index ae02a6e506d49..b43c3d54bc111 100644 --- a/soc/nuvoton/npcx/common/reg/reg_def.h +++ b/soc/nuvoton/npcx/common/reg/reg_def.h @@ -1913,12 +1913,17 @@ struct i3c_reg { #define MCTRL_IBIRESP_ACK_MANDATORY 2 /* ACK with mandatory byte */ #define MCTRL_IBIRESP_MANUAL 3 +/* For REQUEST = EmitStartAddr */ enum npcx_i3c_mctrl_type { NPCX_I3C_MCTRL_TYPE_I3C, NPCX_I3C_MCTRL_TYPE_I2C, NPCX_I3C_MCTRL_TYPE_I3C_HDR_DDR, }; +/* For REQUEST = ForceExit/Target Reset */ +#define MCTRL_TYPE_HDR_EXIT 0 +#define MCTRL_TYPE_TGT_RESTART 2 + /* MSTATUS options */ #define MSTATUS_STATE_IDLE 0x0 #define MSTATUS_STATE_TGTREQ 0x1 From fec0aaa80ec4e346af72b67a7fc2af4b57e890b1 Mon Sep 17 00:00:00 2001 From: Alvis Sun Date: Thu, 16 May 2024 10:17:07 +0800 Subject: [PATCH 1215/2849] drivers: i3c: npcx: update ibi error handling 1. Emit stop when not in the correct state and unsupported ibi type. 2. For IBI(MDB), ignore the callback when target not in the device tree list. Signed-off-by: Alvis Sun --- drivers/i3c/i3c_npcx.c | 68 +++++++++++++++++++++++------------------- 1 file changed, 38 insertions(+), 30 deletions(-) diff --git a/drivers/i3c/i3c_npcx.c b/drivers/i3c/i3c_npcx.c index 75b9c73c9669d..5c19d17e8f7fa 100644 --- a/drivers/i3c/i3c_npcx.c +++ b/drivers/i3c/i3c_npcx.c @@ -40,9 +40,8 @@ LOG_MODULE_REGISTER(npcx_i3c, CONFIG_I3C_LOG_LEVEL); #define MCLKD_FREQ_45_MHZ MHZ(45) #define I3C_STATUS_CLR_MASK \ - (BIT(NPCX_I3C_MSTATUS_TGTSTART) | BIT(NPCX_I3C_MSTATUS_MCTRLDONE) | \ - BIT(NPCX_I3C_MSTATUS_COMPLETE) | BIT(NPCX_I3C_MSTATUS_IBIWON) | \ - BIT(NPCX_I3C_MSTATUS_NOWCNTLR)) + (BIT(NPCX_I3C_MSTATUS_MCTRLDONE) | BIT(NPCX_I3C_MSTATUS_COMPLETE) | \ + BIT(NPCX_I3C_MSTATUS_IBIWON) | BIT(NPCX_I3C_MSTATUS_NOWCNTLR)) #define HDR_DDR_CMD_AND_CRC_SZ_WORD 0x2 /* 2 words = Command(1 word) + CRC(1 word) */ #define HDR_RD_CMD 0x80 @@ -358,7 +357,7 @@ static int npcx_i3c_request_emit_start(struct i3c_reg *inst, uint8_t addr, /* Check NACK after MCTRLDONE is get */ if (IS_BIT_SET(inst->MERRWARN, NPCX_I3C_MERRWARN_NACK)) { - LOG_DBG("%s: nack", __func__); + LOG_DBG("Address nacked"); return -ENODEV; } @@ -384,8 +383,8 @@ static inline int npcx_i3c_request_emit_stop(struct i3c_reg *inst) uint32_t i3c_state = npcx_i3c_state_get(inst); /* Make sure we are in a state where we can emit STOP */ - if ((i3c_state != MSTATUS_STATE_NORMACT) && (i3c_state != MSTATUS_STATE_DAA)) { - LOG_ERR("Request stop state error, state= %#x", i3c_state); + if (i3c_state == MSTATUS_STATE_IDLE) { + LOG_WRN("Request stop in idle state, state= %#x", i3c_state); return -ECANCELED; } @@ -431,7 +430,7 @@ static inline int npcx_i3c_xfer_stop(struct i3c_reg *inst) int ret; state = npcx_i3c_state_get(inst); - LOG_DBG("%s, state=%d", __func__, state); + LOG_DBG("Current working state=%d", state); switch (state) { case MSTATUS_STATE_NORMACT: /* SDR */ @@ -589,7 +588,7 @@ static int npcx_i3c_xfer_write_fifo(struct i3c_reg *inst, uint8_t *buf, uint8_t /* Check tx fifo not full */ if (WAIT_FOR(!IS_BIT_SET(inst->MDATACTRL, NPCX_I3C_MDATACTRL_TXFULL), NPCX_I3C_CHK_TIMEOUT_US, NULL) == false) { - LOG_DBG("%s: Check tx fifo not full timed out", __func__); + LOG_DBG("Check tx fifo not full timed out"); return -ETIMEDOUT; } @@ -696,14 +695,13 @@ static int npcx_i3c_xfer_write_fifo_dma(const struct device *dev, uint8_t *buf, /* Wait I3C COMPLETE */ ret = i3c_ctrl_wait_completion(dev); if (ret < 0) { - LOG_DBG("%s: Check complete time out, buf_size:%d", __func__, buf_sz); + LOG_DBG("Check complete time out, buf_size:%d", buf_sz); goto out_wr_fifo_dma; } /* Check and clear DMA TC after complete */ if (!IS_BIT_SET(mdma_inst->MDMA_CTL1, NPCX_MDMA_CTL_TC)) { - LOG_DBG("%s: DMA busy, TC=%d", __func__, - IS_BIT_SET(mdma_inst->MDMA_CTL1, NPCX_MDMA_CTL_TC)); + LOG_DBG("DMA busy, TC=%d", IS_BIT_SET(mdma_inst->MDMA_CTL1, NPCX_MDMA_CTL_TC)); ret = -EBUSY; goto out_wr_fifo_dma; } @@ -755,7 +753,7 @@ static int npcx_i3c_xfer_read_fifo_dma(const struct device *dev, uint8_t *buf, u /* Wait MDMA TC */ ret = i3c_ctrl_wait_completion(dev); if (ret < 0) { - LOG_DBG("%s: Check DMA done time out", __func__); + LOG_DBG("Check DMA done time out"); } else { ret = buf_sz - mdma_inst->MDMA_CTCNT0; /* Set transferred count */ LOG_DBG("Read cnt=%d", ret); @@ -923,7 +921,7 @@ static int npcx_i3c_do_one_xfer(struct i3c_reg *inst, uint8_t addr, /* Wait message transfer complete */ if (WAIT_FOR(IS_BIT_SET(inst->MSTATUS, NPCX_I3C_MSTATUS_COMPLETE), NPCX_I3C_CHK_TIMEOUT_US, NULL) == false) { - LOG_DBG("%s: timed out addr 0x%02x, buf_sz %u", __func__, addr, buf_sz); + LOG_DBG("Wait COMPLETE timed out, addr 0x%02x, buf_sz %u", addr, buf_sz); ret = -ETIMEDOUT; emit_stop = true; @@ -1467,9 +1465,10 @@ static void npcx_i3c_ibi_work(struct k_work *work) if (npcx_i3c_state_get(inst) != MSTATUS_STATE_TGTREQ) { LOG_DBG("IBI work %p running not because of IBI", work); + LOG_ERR("%s: IBI not in TGTREQ state, state : %#x", __func__, + npcx_i3c_state_get(inst)); LOG_ERR("%s: MSTATUS 0x%08x MERRWARN 0x%08x", __func__, inst->MSTATUS, inst->MERRWARN); - npcx_i3c_request_emit_stop(inst); goto out_ibi_work; @@ -1482,6 +1481,9 @@ static void npcx_i3c_ibi_work(struct k_work *work) if (WAIT_FOR(IS_BIT_SET(inst->MSTATUS, NPCX_I3C_MSTATUS_IBIWON), NPCX_I3C_CHK_TIMEOUT_US, NULL) == false) { LOG_ERR("IBI work, IBIWON timeout"); + LOG_ERR("%s: MSTATUS 0x%08x MERRWARN 0x%08x", __func__, inst->MSTATUS, + inst->MERRWARN); + npcx_i3c_request_emit_stop(inst); goto out_ibi_work; } @@ -1491,21 +1493,14 @@ static void npcx_i3c_ibi_work(struct k_work *work) switch (ibitype) { case MSTATUS_IBITYPE_IBI: - target = i3c_dev_list_i3c_addr_find(dev_list, (uint8_t)ibiaddr); - if (target != NULL) { - ret = npcx_i3c_xfer_read_fifo(inst, &payload[0], sizeof(payload)); - if (ret >= 0) { - payload_sz = (size_t)ret; - } else { - LOG_ERR("Error reading IBI payload"); - - npcx_i3c_request_emit_stop(inst); - - goto out_ibi_work; - } + ret = npcx_i3c_xfer_read_fifo(inst, &payload[0], sizeof(payload)); + if (ret >= 0) { + payload_sz = (size_t)ret; } else { - /* NACK IBI coming from unknown device */ - npcx_i3c_ibi_respond_nack(inst); + LOG_ERR("Error reading IBI payload"); + npcx_i3c_request_emit_stop(inst); + + goto out_ibi_work; } break; case MSTATUS_IBITYPE_HJ: @@ -1515,12 +1510,14 @@ static void npcx_i3c_ibi_work(struct k_work *work) case MSTATUS_IBITYPE_CR: LOG_DBG("Controller role handoff not supported"); npcx_i3c_ibi_respond_nack(inst); + npcx_i3c_request_emit_stop(inst); break; default: break; } if (npcx_i3c_has_error(inst)) { + LOG_ERR("%s: unexpected error, ibi type:%d", __func__, ibitype); /* * If the controller detects any errors, simply * emit a STOP to abort the IBI. The target will @@ -1533,10 +1530,13 @@ static void npcx_i3c_ibi_work(struct k_work *work) switch (ibitype) { case MSTATUS_IBITYPE_IBI: + target = i3c_dev_list_i3c_addr_find(dev_list, (uint8_t)ibiaddr); if (target != NULL) { if (i3c_ibi_work_enqueue_target_irq(target, &payload[0], payload_sz) != 0) { LOG_ERR("Error enqueue IBI IRQ work"); } + } else { + LOG_ERR("IBI (MDB) target not in the list"); } /* Finishing the IBI transaction */ @@ -1548,7 +1548,7 @@ static void npcx_i3c_ibi_work(struct k_work *work) } break; case MSTATUS_IBITYPE_CR: - /* Not supported */ + /* Not supported, for future use. */ break; default: break; @@ -1792,15 +1792,23 @@ static void npcx_i3c_isr(const struct device *dev) #endif /* CONFIG_I3C_NPCX_DMA */ #ifdef CONFIG_I3C_USE_IBI + int ret; + /* Target start detected */ if (IS_BIT_SET(inst->MSTATUS, NPCX_I3C_MSTATUS_TGTSTART)) { LOG_DBG("ISR TGTSTART !"); /* Disable further target initiated IBI interrupt */ inst->MINTCLR = BIT(NPCX_I3C_MINTCLR_TGTSTART); + /* Clear TGTSTART interrupt */ + inst->MSTATUS = BIT(NPCX_I3C_MSTATUS_TGTSTART); /* Handle IBI in workqueue */ - i3c_ibi_work_enqueue_cb(dev, npcx_i3c_ibi_work); + ret = i3c_ibi_work_enqueue_cb(dev, npcx_i3c_ibi_work); + if (ret < 0) { + LOG_ERR("Enqueuing ibi work fail, ret %d", ret); + inst->MINTSET = BIT(NPCX_I3C_MINTSET_TGTSTART); + } } #endif /* CONFIG_I3C_USE_IBI */ From e94adf1e2beb49c03845604fd92ee5b134dc4dfa Mon Sep 17 00:00:00 2001 From: Chris LaFlash Date: Fri, 17 May 2024 23:07:51 -0700 Subject: [PATCH 1216/2849] drivers: crypto: stm32: AES CTR IV is 16bytes AES-CTR IV is the same as the block size 128-bits(16 bytes) regardless of key size. Signed-off-by: Chris LaFlash --- drivers/crypto/crypto_stm32.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/crypto/crypto_stm32.c b/drivers/crypto/crypto_stm32.c index 680792bbb2c83..67f790f250b85 100644 --- a/drivers/crypto/crypto_stm32.c +++ b/drivers/crypto/crypto_stm32.c @@ -234,7 +234,7 @@ static int crypto_stm32_ctr_encrypt(struct cipher_ctx *ctx, { int ret; uint32_t ctr[BLOCK_LEN_WORDS] = {0}; - int ivlen = ctx->keylen - (ctx->mode_params.ctr_info.ctr_len >> 3); + int ivlen = BLOCK_LEN_BYTES - (ctx->mode_params.ctr_info.ctr_len >> 3); struct crypto_stm32_session *session = CRYPTO_STM32_SESSN(ctx); @@ -257,7 +257,7 @@ static int crypto_stm32_ctr_decrypt(struct cipher_ctx *ctx, { int ret; uint32_t ctr[BLOCK_LEN_WORDS] = {0}; - int ivlen = ctx->keylen - (ctx->mode_params.ctr_info.ctr_len >> 3); + int ivlen = BLOCK_LEN_BYTES - (ctx->mode_params.ctr_info.ctr_len >> 3); struct crypto_stm32_session *session = CRYPTO_STM32_SESSN(ctx); From 771afc34a59b55a77ae7d05f1f2b8e28c7664200 Mon Sep 17 00:00:00 2001 From: Omkar Kulkarni Date: Thu, 16 May 2024 13:28:31 +0200 Subject: [PATCH 1217/2849] gitignore: Ignore myresults.xml files These files are created as a result of local babblesim test runs and can be safely ignored. Signed-off-by: Omkar Kulkarni --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 15636eaaeac0e..053e78e384231 100644 --- a/.gitignore +++ b/.gitignore @@ -39,6 +39,7 @@ sanity-out* twister-out* bsim_out bsim_bt_out +myresults.xml tests/RunResults.xml scripts/grub doc/reference/kconfig/*.rst From a66672885d254d8d339c41dee41cc26558814cd3 Mon Sep 17 00:00:00 2001 From: Emil Gydesen Date: Thu, 16 May 2024 11:59:53 +0200 Subject: [PATCH 1218/2849] samples: Bluetooth: Audio: Add missing board/conf Add missing configuration files for the nRF5340DK and missing configuration values for the unicast samples w.r.t. buffer sizes and encryption. Signed-off-by: Emil Gydesen --- .../boards/nrf5340dk_nrf5340_cpuapp.conf | 3 +++ .../boards/nrf5340dk_nrf5340_cpuapp.overlay | 15 +++++++++++++++ .../boards/nrf5340dk_nrf5340_cpuapp.conf | 3 +++ .../boards/nrf5340dk_nrf5340_cpuapp.overlay | 15 +++++++++++++++ .../boards/nrf5340_audio_dk_nrf5340_cpuapp.conf | 7 +++++++ .../boards/nrf5340_audio_dk_nrf5340_cpuapp.conf | 7 +++++++ .../shell/boards/nrf5340dk_nrf5340_cpuapp.overlay | 15 +++++++++++++++ 7 files changed, 65 insertions(+) create mode 100644 samples/bluetooth/broadcast_audio_sink/boards/nrf5340dk_nrf5340_cpuapp.conf create mode 100644 samples/bluetooth/broadcast_audio_sink/boards/nrf5340dk_nrf5340_cpuapp.overlay create mode 100644 samples/bluetooth/broadcast_audio_source/boards/nrf5340dk_nrf5340_cpuapp.conf create mode 100644 samples/bluetooth/broadcast_audio_source/boards/nrf5340dk_nrf5340_cpuapp.overlay create mode 100644 tests/bluetooth/shell/boards/nrf5340dk_nrf5340_cpuapp.overlay diff --git a/samples/bluetooth/broadcast_audio_sink/boards/nrf5340dk_nrf5340_cpuapp.conf b/samples/bluetooth/broadcast_audio_sink/boards/nrf5340dk_nrf5340_cpuapp.conf new file mode 100644 index 0000000000000..69b3cc51473c7 --- /dev/null +++ b/samples/bluetooth/broadcast_audio_sink/boards/nrf5340dk_nrf5340_cpuapp.conf @@ -0,0 +1,3 @@ +# Use USB Audio as audio sink +CONFIG_USE_USB_AUDIO_OUTPUT=y +CONFIG_USB_DEVICE_PRODUCT="USB Broadcast Sink" diff --git a/samples/bluetooth/broadcast_audio_sink/boards/nrf5340dk_nrf5340_cpuapp.overlay b/samples/bluetooth/broadcast_audio_sink/boards/nrf5340dk_nrf5340_cpuapp.overlay new file mode 100644 index 0000000000000..b8e72f1b61c5b --- /dev/null +++ b/samples/bluetooth/broadcast_audio_sink/boards/nrf5340dk_nrf5340_cpuapp.overlay @@ -0,0 +1,15 @@ +zephyr_udc0: &usbd { + compatible = "nordic,nrf-usbd"; + status = "okay"; + + hs_0: hs_0 { + compatible = "usb-audio-hs"; + mic-feature-mute; + mic-channel-l; + mic-channel-r; + + hp-feature-mute; + hp-channel-l; + hp-channel-r; + }; +}; diff --git a/samples/bluetooth/broadcast_audio_source/boards/nrf5340dk_nrf5340_cpuapp.conf b/samples/bluetooth/broadcast_audio_source/boards/nrf5340dk_nrf5340_cpuapp.conf new file mode 100644 index 0000000000000..8b65fa9a9d857 --- /dev/null +++ b/samples/bluetooth/broadcast_audio_source/boards/nrf5340dk_nrf5340_cpuapp.conf @@ -0,0 +1,3 @@ +# Use USB Audio as audio source +CONFIG_USE_USB_AUDIO_INPUT=y +CONFIG_USB_DEVICE_PRODUCT="Zephyr Broadcast Source" diff --git a/samples/bluetooth/broadcast_audio_source/boards/nrf5340dk_nrf5340_cpuapp.overlay b/samples/bluetooth/broadcast_audio_source/boards/nrf5340dk_nrf5340_cpuapp.overlay new file mode 100644 index 0000000000000..b8e72f1b61c5b --- /dev/null +++ b/samples/bluetooth/broadcast_audio_source/boards/nrf5340dk_nrf5340_cpuapp.overlay @@ -0,0 +1,15 @@ +zephyr_udc0: &usbd { + compatible = "nordic,nrf-usbd"; + status = "okay"; + + hs_0: hs_0 { + compatible = "usb-audio-hs"; + mic-feature-mute; + mic-channel-l; + mic-channel-r; + + hp-feature-mute; + hp-channel-l; + hp-channel-r; + }; +}; diff --git a/samples/bluetooth/unicast_audio_client/boards/nrf5340_audio_dk_nrf5340_cpuapp.conf b/samples/bluetooth/unicast_audio_client/boards/nrf5340_audio_dk_nrf5340_cpuapp.conf index 8d48d5e1c2072..76df8dba27a4f 100644 --- a/samples/bluetooth/unicast_audio_client/boards/nrf5340_audio_dk_nrf5340_cpuapp.conf +++ b/samples/bluetooth/unicast_audio_client/boards/nrf5340_audio_dk_nrf5340_cpuapp.conf @@ -4,3 +4,10 @@ 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 + +CONFIG_BT_BUF_EVT_RX_SIZE=255 +CONFIG_BT_BUF_ACL_RX_SIZE=255 +CONFIG_BT_BUF_ACL_TX_SIZE=251 +CONFIG_BT_BUF_CMD_TX_SIZE=255 + +CONFIG_BT_TINYCRYPT_ECC=y diff --git a/samples/bluetooth/unicast_audio_server/boards/nrf5340_audio_dk_nrf5340_cpuapp.conf b/samples/bluetooth/unicast_audio_server/boards/nrf5340_audio_dk_nrf5340_cpuapp.conf index 8d48d5e1c2072..76df8dba27a4f 100644 --- a/samples/bluetooth/unicast_audio_server/boards/nrf5340_audio_dk_nrf5340_cpuapp.conf +++ b/samples/bluetooth/unicast_audio_server/boards/nrf5340_audio_dk_nrf5340_cpuapp.conf @@ -4,3 +4,10 @@ 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 + +CONFIG_BT_BUF_EVT_RX_SIZE=255 +CONFIG_BT_BUF_ACL_RX_SIZE=255 +CONFIG_BT_BUF_ACL_TX_SIZE=251 +CONFIG_BT_BUF_CMD_TX_SIZE=255 + +CONFIG_BT_TINYCRYPT_ECC=y diff --git a/tests/bluetooth/shell/boards/nrf5340dk_nrf5340_cpuapp.overlay b/tests/bluetooth/shell/boards/nrf5340dk_nrf5340_cpuapp.overlay new file mode 100644 index 0000000000000..b8e72f1b61c5b --- /dev/null +++ b/tests/bluetooth/shell/boards/nrf5340dk_nrf5340_cpuapp.overlay @@ -0,0 +1,15 @@ +zephyr_udc0: &usbd { + compatible = "nordic,nrf-usbd"; + status = "okay"; + + hs_0: hs_0 { + compatible = "usb-audio-hs"; + mic-feature-mute; + mic-channel-l; + mic-channel-r; + + hp-feature-mute; + hp-channel-l; + hp-channel-r; + }; +}; From b4e81054f262b9acd4ad4a434f49ee5aa2488d78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fin=20Maa=C3=9F?= Date: Tue, 14 May 2024 10:21:15 +0200 Subject: [PATCH 1219/2849] drivers: i2c: bitbang: add get_config MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit add get_config for the i2c bitbang driver. Signed-off-by: Fin Maaß --- drivers/i2c/i2c_bitbang.c | 13 +++++++++++++ drivers/i2c/i2c_bitbang.h | 9 ++++++++- 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/drivers/i2c/i2c_bitbang.c b/drivers/i2c/i2c_bitbang.c index b92583c888f92..4f99eb1b6dd1c 100644 --- a/drivers/i2c/i2c_bitbang.c +++ b/drivers/i2c/i2c_bitbang.c @@ -60,6 +60,19 @@ int i2c_bitbang_configure(struct i2c_bitbang *context, uint32_t dev_config) return -ENOTSUP; } + context->dev_config = dev_config; + + return 0; +} + +int i2c_bitbang_get_config(struct i2c_bitbang *context, uint32_t *config) +{ + if (context->dev_config == 0) { + return -EIO; + } + + *config = context->dev_config; + return 0; } diff --git a/drivers/i2c/i2c_bitbang.h b/drivers/i2c/i2c_bitbang.h index aa0a8dd6bdddd..14432c30e48b8 100644 --- a/drivers/i2c/i2c_bitbang.h +++ b/drivers/i2c/i2c_bitbang.h @@ -28,7 +28,8 @@ struct i2c_bitbang_io { struct i2c_bitbang { const struct i2c_bitbang_io *io; void *io_context; - uint32_t delays[2]; + uint32_t delays[2]; + uint32_t dev_config; }; /** @@ -48,6 +49,12 @@ void i2c_bitbang_init(struct i2c_bitbang *bitbang, */ int i2c_bitbang_configure(struct i2c_bitbang *bitbang, uint32_t dev_config); +/** + * Implementation of the functionality required by the 'get_config' function + * in struct i2c_driver_api. + */ +int i2c_bitbang_get_config(struct i2c_bitbang *context, uint32_t *config); + /** * Implementation of the functionality required by the 'recover_bus' * function in struct i2c_driver_api. From e7a088b4674743ca472a64e425f931c033f4530e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fin=20Maa=C3=9F?= Date: Tue, 14 May 2024 10:23:30 +0200 Subject: [PATCH 1220/2849] drivers: i2c: gpio: add get_config MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit add get_config for the gpio i2c driver. Signed-off-by: Fin Maaß --- drivers/i2c/i2c_gpio.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/drivers/i2c/i2c_gpio.c b/drivers/i2c/i2c_gpio.c index 4cb5606507a99..80c20f38ba67a 100644 --- a/drivers/i2c/i2c_gpio.c +++ b/drivers/i2c/i2c_gpio.c @@ -93,6 +93,23 @@ static int i2c_gpio_configure(const struct device *dev, uint32_t dev_config) return rc; } +static int i2c_gpio_get_config(const struct device *dev, uint32_t *config) +{ + struct i2c_gpio_context *context = dev->data; + int rc; + + k_mutex_lock(&context->mutex, K_FOREVER); + + rc = i2c_bitbang_get_config(&context->bitbang, config); + if (rc < 0) { + LOG_ERR("I2C controller not configured: %d", rc); + } + + k_mutex_unlock(&context->mutex); + + return rc; +} + static int i2c_gpio_transfer(const struct device *dev, struct i2c_msg *msgs, uint8_t num_msgs, uint16_t slave_address) { @@ -125,6 +142,7 @@ static int i2c_gpio_recover_bus(const struct device *dev) static const struct i2c_driver_api api = { .configure = i2c_gpio_configure, + .get_config = i2c_gpio_get_config, .transfer = i2c_gpio_transfer, .recover_bus = i2c_gpio_recover_bus, }; From dd897b51e04694f7edb4e60a8ccd71391b6e140b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fin=20Maa=C3=9F?= Date: Tue, 14 May 2024 10:29:47 +0200 Subject: [PATCH 1221/2849] drivers: i2c: i2c_sbcon: add get_config and recover_bus MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit add get_config and recover_bus for the sbcon i2c driver. Signed-off-by: Fin Maaß --- drivers/i2c/i2c_sbcon.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/drivers/i2c/i2c_sbcon.c b/drivers/i2c/i2c_sbcon.c index e3ddd62b26247..5be737b2a40b4 100644 --- a/drivers/i2c/i2c_sbcon.c +++ b/drivers/i2c/i2c_sbcon.c @@ -84,6 +84,13 @@ static int i2c_sbcon_configure(const struct device *dev, uint32_t dev_config) return i2c_bitbang_configure(&context->bitbang, dev_config); } +static int i2c_sbcon_get_config(const struct device *dev, uint32_t *config) +{ + struct i2c_sbcon_context *context = dev->data; + + return i2c_bitbang_get_config(&context->bitbang, config); +} + static int i2c_sbcon_transfer(const struct device *dev, struct i2c_msg *msgs, uint8_t num_msgs, uint16_t slave_address) { @@ -93,9 +100,18 @@ static int i2c_sbcon_transfer(const struct device *dev, struct i2c_msg *msgs, slave_address); } +static int i2c_sbcon_recover_bus(const struct device *dev) +{ + struct i2c_sbcon_context *context = dev->data; + + return i2c_bitbang_recover_bus(&context->bitbang); +} + static const struct i2c_driver_api api = { .configure = i2c_sbcon_configure, + .get_config = i2c_sbcon_get_config, .transfer = i2c_sbcon_transfer, + .recover_bus = i2c_sbcon_recover_bus, }; static int i2c_sbcon_init(const struct device *dev) From 2be9ed7103dbb8a9a43006218575e2d2387b2f5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fin=20Maa=C3=9F?= Date: Tue, 14 May 2024 10:39:39 +0200 Subject: [PATCH 1222/2849] drivers: i2c: litex: use frequency from device tree MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit use the clock frequency from the device tree. Signed-off-by: Fin Maaß --- drivers/i2c/i2c_litex.c | 16 +++++++++++++++- dts/bindings/i2c/litex,i2c.yaml | 3 +++ dts/riscv/riscv32-litex-vexriscv.dtsi | 3 +++ 3 files changed, 21 insertions(+), 1 deletion(-) diff --git a/drivers/i2c/i2c_litex.c b/drivers/i2c/i2c_litex.c index 58636209bf6a9..548e390f86b41 100644 --- a/drivers/i2c/i2c_litex.c +++ b/drivers/i2c/i2c_litex.c @@ -8,6 +8,11 @@ #include #include + +#include +LOG_MODULE_REGISTER(i2c_litex, CONFIG_I2C_LOG_LEVEL); + +#include "i2c-priv.h" #include "i2c_bitbang.h" #include @@ -25,6 +30,7 @@ struct i2c_litex_cfg { uint32_t write_addr; uint32_t read_addr; + uint32_t bitrate; }; #define GET_I2C_CFG(dev) \ @@ -87,11 +93,18 @@ static int i2c_litex_init(const struct device *dev) { const struct i2c_litex_cfg *config = GET_I2C_CFG(dev); struct i2c_bitbang *bitbang = GET_I2C_BITBANG(dev); + int ret; litex_write8(litex_read8(config->write_addr) | HIGH_STATE_ON_I2C_LINES, config->write_addr); i2c_bitbang_init(bitbang, &i2c_litex_bitbang_io, (void *)config); - return 0; + ret = i2c_bitbang_configure(bitbang, + I2C_MODE_CONTROLLER | i2c_map_dt_bitrate(config->bitrate)); + if (ret != 0) { + LOG_ERR("failed to configure I2C bitbang: %d", ret); + } + + return ret; } static int i2c_litex_configure(const struct device *dev, uint32_t dev_config) @@ -120,6 +133,7 @@ static const struct i2c_driver_api i2c_litex_driver_api = { static const struct i2c_litex_cfg i2c_litex_cfg_##n = { \ .write_addr = DT_INST_REG_ADDR_BY_NAME(n, write), \ .read_addr = DT_INST_REG_ADDR_BY_NAME(n, read), \ + .bitrate = DT_INST_PROP(n, clock_frequency), \ }; \ \ static struct i2c_bitbang i2c_bitbang_##n; \ diff --git a/dts/bindings/i2c/litex,i2c.yaml b/dts/bindings/i2c/litex,i2c.yaml index acb9032bd4eb7..04af4f9858def 100644 --- a/dts/bindings/i2c/litex,i2c.yaml +++ b/dts/bindings/i2c/litex,i2c.yaml @@ -13,3 +13,6 @@ include: i2c-controller.yaml properties: reg: required: true + + clock-frequency: + required: true diff --git a/dts/riscv/riscv32-litex-vexriscv.dtsi b/dts/riscv/riscv32-litex-vexriscv.dtsi index 8032317f9d812..336a2feb00159 100644 --- a/dts/riscv/riscv32-litex-vexriscv.dtsi +++ b/dts/riscv/riscv32-litex-vexriscv.dtsi @@ -4,6 +4,8 @@ * SPDX-License-Identifier: Apache-2.0 */ + #include + / { #address-cells = <1>; #size-cells = <1>; @@ -161,6 +163,7 @@ compatible = "litex,i2c"; reg = <0xe0005000 0x4 0xe0005004 0x4>; reg-names = "write", "read"; + clock-frequency = ; #address-cells = <1>; #size-cells = <0>; status = "disabled"; From dd1f9c346d34389adcbe40e1e04c75a2f3405024 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fin=20Maa=C3=9F?= Date: Tue, 14 May 2024 10:40:37 +0200 Subject: [PATCH 1223/2849] drivers: i2c: litex: add get_config and recover_bus MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit add get_config and recover_bus for the litex i2c driver. Signed-off-by: Fin Maaß --- drivers/i2c/i2c_litex.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/drivers/i2c/i2c_litex.c b/drivers/i2c/i2c_litex.c index 548e390f86b41..b237790e91cf8 100644 --- a/drivers/i2c/i2c_litex.c +++ b/drivers/i2c/i2c_litex.c @@ -114,6 +114,13 @@ static int i2c_litex_configure(const struct device *dev, uint32_t dev_config) return i2c_bitbang_configure(bitbang, dev_config); } +static int i2c_litex_get_config(const struct device *dev, uint32_t *config) +{ + struct i2c_bitbang *bitbang = GET_I2C_BITBANG(dev); + + return i2c_bitbang_get_config(bitbang, config); +} + static int i2c_litex_transfer(const struct device *dev, struct i2c_msg *msgs, uint8_t num_msgs, uint16_t addr) { @@ -122,9 +129,18 @@ static int i2c_litex_transfer(const struct device *dev, struct i2c_msg *msgs, return i2c_bitbang_transfer(bitbang, msgs, num_msgs, addr); } +static int i2c_litex_recover_bus(const struct device *dev) +{ + struct i2c_bitbang *bitbang = GET_I2C_BITBANG(dev); + + return i2c_bitbang_recover_bus(bitbang); +} + static const struct i2c_driver_api i2c_litex_driver_api = { .configure = i2c_litex_configure, + .get_config = i2c_litex_get_config, .transfer = i2c_litex_transfer, + .recover_bus = i2c_litex_recover_bus, }; /* Device Instantiation */ From cefbcc53230353f7f8ad9ce633b516a0e901418f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fin=20Maa=C3=9F?= Date: Tue, 21 May 2024 11:35:34 +0200 Subject: [PATCH 1224/2849] drivers: i2c: i2c_sbcon: use frequency from device tree MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit use the clock frequency from the device tree. Signed-off-by: Fin Maaß --- drivers/i2c/i2c_sbcon.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/drivers/i2c/i2c_sbcon.c b/drivers/i2c/i2c_sbcon.c index 5be737b2a40b4..9e077a81956e9 100644 --- a/drivers/i2c/i2c_sbcon.c +++ b/drivers/i2c/i2c_sbcon.c @@ -17,6 +17,11 @@ #include #include #include + +#include +LOG_MODULE_REGISTER(i2c_sbcon, CONFIG_I2C_LOG_LEVEL); + +#include "i2c-priv.h" #include "i2c_bitbang.h" /* SBCon hardware registers layout */ @@ -35,6 +40,7 @@ struct sbcon { /* Driver config */ struct i2c_sbcon_config { struct sbcon *sbcon; /* Address of hardware registers */ + uint32_t bitrate; /* I2C bus speed in Hz */ }; /* Driver instance data */ @@ -118,10 +124,17 @@ static int i2c_sbcon_init(const struct device *dev) { struct i2c_sbcon_context *context = dev->data; const struct i2c_sbcon_config *config = dev->config; + int ret; i2c_bitbang_init(&context->bitbang, &io_fns, config->sbcon); - return 0; + ret = i2c_bitbang_configure(&context->bitbang, + I2C_MODE_CONTROLLER | i2c_map_dt_bitrate(config->bitrate)); + if (ret != 0) { + LOG_ERR("failed to configure I2C bitbang: %d", ret); + } + + return ret; } #define DEFINE_I2C_SBCON(_num) \ @@ -129,7 +142,8 @@ static int i2c_sbcon_init(const struct device *dev) static struct i2c_sbcon_context i2c_sbcon_dev_data_##_num; \ \ static const struct i2c_sbcon_config i2c_sbcon_dev_cfg_##_num = { \ - .sbcon = (void *)DT_INST_REG_ADDR(_num), \ + .sbcon = (void *)DT_INST_REG_ADDR(_num), \ + .bitrate = DT_INST_PROP(_num, clock_frequency), \ }; \ \ I2C_DEVICE_DT_INST_DEFINE(_num, \ From 97ba7fd48da66a56bb5c7983b510ed2a12a466da Mon Sep 17 00:00:00 2001 From: Yong Cong Sin Date: Fri, 10 May 2024 18:08:51 +0800 Subject: [PATCH 1225/2849] drivers: i2c: add Broadcom iProc I2C driver Add device driver, bindings and build-only test for Broadcom iProc I2C. Signed-off-by: Yong Cong Sin --- drivers/i2c/CMakeLists.txt | 1 + drivers/i2c/Kconfig | 1 + drivers/i2c/Kconfig.bcm_iproc | 10 + drivers/i2c/i2c_bcm_iproc.c | 950 ++++++++++++++++++ dts/bindings/i2c/brcm,iproc-i2c.yaml | 16 + .../i2c/boards/qemu_cortex_m3.overlay | 12 + 6 files changed, 990 insertions(+) create mode 100644 drivers/i2c/Kconfig.bcm_iproc create mode 100644 drivers/i2c/i2c_bcm_iproc.c create mode 100644 dts/bindings/i2c/brcm,iproc-i2c.yaml diff --git a/drivers/i2c/CMakeLists.txt b/drivers/i2c/CMakeLists.txt index cb180ef24e3cd..16fa2b450d1fd 100644 --- a/drivers/i2c/CMakeLists.txt +++ b/drivers/i2c/CMakeLists.txt @@ -10,6 +10,7 @@ zephyr_library_sources_ifdef(CONFIG_I2C_RTIO i2c_rtio.c) zephyr_library_sources_ifdef(CONFIG_I2C_SHELL i2c_shell.c) zephyr_library_sources_ifdef(CONFIG_I2C_BITBANG i2c_bitbang.c) zephyr_library_sources_ifdef(CONFIG_I2C_TELINK_B91 i2c_b91.c) +zephyr_library_sources_ifdef(CONFIG_I2C_IPROC i2c_bcm_iproc.c) zephyr_library_sources_ifdef(CONFIG_I2C_CC13XX_CC26XX i2c_cc13xx_cc26xx.c) zephyr_library_sources_ifdef(CONFIG_I2C_CC32XX i2c_cc32xx.c) zephyr_library_sources_ifdef(CONFIG_I2C_ESP32 i2c_esp32.c) diff --git a/drivers/i2c/Kconfig b/drivers/i2c/Kconfig index 8af4bbbeb8b3e..f5dacfe8ea4ca 100644 --- a/drivers/i2c/Kconfig +++ b/drivers/i2c/Kconfig @@ -94,6 +94,7 @@ endif # I2C_RTIO # Include these first so that any properties (e.g. defaults) below can be # overridden (by defining symbols in multiple locations) source "drivers/i2c/Kconfig.b91" +source "drivers/i2c/Kconfig.bcm_iproc" source "drivers/i2c/Kconfig.cc13xx_cc26xx" source "drivers/i2c/Kconfig.dw" source "drivers/i2c/Kconfig.esp32" diff --git a/drivers/i2c/Kconfig.bcm_iproc b/drivers/i2c/Kconfig.bcm_iproc new file mode 100644 index 0000000000000..b192dc1483139 --- /dev/null +++ b/drivers/i2c/Kconfig.bcm_iproc @@ -0,0 +1,10 @@ +# Copyright 2020 Broadcom +# Copyright 2024 Meta Platforms +# SPDX-License-Identifier: Apache-2.0 + +config I2C_IPROC + bool "Broadcom iProc I2C controller" + default y + depends on DT_HAS_BRCM_IPROC_I2C_ENABLED + help + Enable support for Broadcom iProc I2C controller. diff --git a/drivers/i2c/i2c_bcm_iproc.c b/drivers/i2c/i2c_bcm_iproc.c new file mode 100644 index 0000000000000..fbc5dc4758373 --- /dev/null +++ b/drivers/i2c/i2c_bcm_iproc.c @@ -0,0 +1,950 @@ +/* + * Copyright 2020 Broadcom + * Copyright 2024 Meta Platforms + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT brcm_iproc_i2c + +#include +#include + +#include +#include +#include + +#define LOG_LEVEL CONFIG_I2C_LOG_LEVEL +LOG_MODULE_REGISTER(iproc_i2c); + +#include "i2c-priv.h" + +/* Registers */ +#define CFG_OFFSET 0x00 +#define CFG_RESET_SHIFT 31 +#define CFG_EN_SHIFT 30 +#define CFG_M_RETRY_CNT_SHIFT 16 +#define CFG_M_RETRY_CNT_MASK 0x0f + +#define TIM_CFG_OFFSET 0x04 +#define TIM_CFG_MODE_400_SHIFT 31 +#define TIM_RAND_TARGET_STRETCH_SHIFT 24 +#define TIM_RAND_TARGET_STRETCH_MASK 0x7f + +#define S_ADDR_OFFSET 0x08 +#define S_ADDR_OFFSET_ADDR0_MASK 0x7f +#define S_ADDR_OFFSET_ADDR0_SHIFT 0 +#define S_ADDR_OFFSET_ADDR0_EN_BIT 7 + +#define M_FIFO_CTRL_OFFSET 0x0c +#define M_FIFO_RX_FLUSH_SHIFT 31 +#define M_FIFO_TX_FLUSH_SHIFT 30 +#define M_FIFO_RX_CNT_SHIFT 16 +#define M_FIFO_RX_CNT_MASK 0x7f +#define M_FIFO_RX_THLD_SHIFT 8 +#define M_FIFO_RX_THLD_MASK 0x3f + +#define S_FIFO_CTRL_OFFSET 0x10 +#define S_FIFO_RX_FLUSH_SHIFT 31 +#define S_FIFO_TX_FLUSH_SHIFT 30 + +#define M_CMD_OFFSET 0x30 +#define M_CMD_START_BUSY_SHIFT 31 +#define M_CMD_STATUS_SHIFT 25 +#define M_CMD_STATUS_MASK 0x07 +#define M_CMD_STATUS_SUCCESS 0x0 +#define M_CMD_STATUS_LOST_ARB 0x1 +#define M_CMD_STATUS_NACK_ADDR 0x2 +#define M_CMD_STATUS_NACK_DATA 0x3 +#define M_CMD_STATUS_TIMEOUT 0x4 +#define M_CMD_STATUS_FIFO_UNDERRUN 0x5 +#define M_CMD_STATUS_RX_FIFO_FULL 0x6 +#define M_CMD_SMB_PROT_SHIFT 9 +#define M_CMD_SMB_PROT_QUICK 0x0 +#define M_CMD_SMB_PROT_MASK 0xf +#define M_CMD_SMB_PROT_BLK_WR 0x7 +#define M_CMD_SMB_PROT_BLK_RD 0x8 +#define M_CMD_PEC_SHIFT 8 +#define M_CMD_RD_CNT_MASK 0xff + +#define S_CMD_OFFSET 0x34 +#define S_CMD_START_BUSY_SHIFT 31 +#define S_CMD_STATUS_SHIFT 23 +#define S_CMD_STATUS_MASK 0x07 +#define S_CMD_STATUS_TIMEOUT 0x5 +#define S_CMD_STATUS_MASTER_ABORT 0x7 + +#define IE_OFFSET 0x38 +#define IE_M_RX_FIFO_FULL_SHIFT 31 +#define IE_M_RX_THLD_SHIFT 30 +#define IE_M_START_BUSY_SHIFT 28 +#define IE_M_TX_UNDERRUN_SHIFT 27 +#define IE_S_RX_FIFO_FULL_SHIFT 26 +#define IE_S_RX_THLD_SHIFT 25 +#define IE_S_RX_EVENT_SHIFT 24 +#define IE_S_START_BUSY_SHIFT 23 +#define IE_S_TX_UNDERRUN_SHIFT 22 +#define IE_S_RD_EN_SHIFT 21 + +#define IS_OFFSET 0x3c +#define IS_M_RX_FIFO_FULL_SHIFT 31 +#define IS_M_RX_THLD_SHIFT 30 +#define IS_M_START_BUSY_SHIFT 28 +#define IS_M_TX_UNDERRUN_SHIFT 27 +#define IS_S_RX_FIFO_FULL_SHIFT 26 +#define IS_S_RX_THLD_SHIFT 25 +#define IS_S_RX_EVENT_SHIFT 24 +#define IS_S_START_BUSY_SHIFT 23 +#define IS_S_TX_UNDERRUN_SHIFT 22 +#define IS_S_RD_EN_SHIFT 21 + +#define M_TX_OFFSET 0x40 +#define M_TX_WR_STATUS_SHIFT 31 +#define M_TX_DATA_MASK 0xff + +#define M_RX_OFFSET 0x44 +#define M_RX_STATUS_SHIFT 30 +#define M_RX_STATUS_MASK 0x03 +#define M_RX_PEC_ERR_SHIFT 29 +#define M_RX_DATA_SHIFT 0 +#define M_RX_DATA_MASK 0xff + +#define S_TX_OFFSET 0x48 +#define S_TX_WR_STATUS_SHIFT 31 + +#define S_RX_OFFSET 0x4c +#define S_RX_STATUS_SHIFT 30 +#define S_RX_STATUS_MASK 0x03 +#define S_RX_DATA_SHIFT 0x0 +#define S_RX_DATA_MASK 0xff + +#define I2C_TIMEOUT_MSEC 100 +#define TX_RX_FIFO_SIZE 64 +#define M_RX_FIFO_MAX_THLD_VALUE (TX_RX_FIFO_SIZE - 1) +#define M_RX_FIFO_THLD_VALUE 50 + +#define I2C_MAX_TARGET_ADDR 0x7f + +#define I2C_TARGET_RX_FIFO_EMPTY 0x0 +#define I2C_TARGET_RX_START 0x1 +#define I2C_TARGET_RX_DATA 0x2 +#define I2C_TARGET_RX_END 0x3 + +#define IE_S_ALL_INTERRUPT_SHIFT 21 +#define IE_S_ALL_INTERRUPT_MASK 0x3f + +#define TARGET_CLOCK_STRETCH_TIME 25 + +/* + * To keep running in ISR for less time, + * max target read per interrupt is set to 10 bytes. + */ +#define MAX_TARGET_RX_PER_INT 10 + +#define ISR_MASK_TARGET \ + (BIT(IS_S_START_BUSY_SHIFT) | BIT(IS_S_RX_EVENT_SHIFT) | BIT(IS_S_RD_EN_SHIFT) | \ + BIT(IS_S_TX_UNDERRUN_SHIFT) | BIT(IS_S_RX_FIFO_FULL_SHIFT) | BIT(IS_S_RX_THLD_SHIFT)) + +#define ISR_MASK \ + (BIT(IS_M_START_BUSY_SHIFT) | BIT(IS_M_TX_UNDERRUN_SHIFT) | BIT(IS_M_RX_THLD_SHIFT)) + +#define DEV_CFG(dev) ((struct iproc_i2c_config *)(dev)->config) +#define DEV_DATA(dev) ((struct iproc_i2c_data *)(dev)->data) +#define DEV_BASE(dev) ((DEV_CFG(dev))->base) + +struct iproc_i2c_config { + mem_addr_t base; + uint32_t bitrate; + void (*irq_config_func)(const struct device *dev); +}; + +struct iproc_i2c_data { + struct i2c_target_config *target_cfg; + struct i2c_msg *msg; + uint32_t tx_bytes; + uint32_t rx_bytes; + uint32_t thld_bytes; + uint32_t tx_underrun; + struct k_sem device_sync_sem; + uint32_t target_int_mask; + bool rx_start_rcvd; + bool target_read_complete; + bool target_rx_only; +}; + +static void iproc_i2c_enable_disable(const struct device *dev, bool enable) +{ + mem_addr_t base = DEV_BASE(dev); + uint32_t val; + + val = sys_read32(base + CFG_OFFSET); + if (enable) { + val |= BIT(CFG_EN_SHIFT); + } else { + val &= ~BIT(CFG_EN_SHIFT); + } + sys_write32(val, base + CFG_OFFSET); +} + +static void iproc_i2c_reset_controller(const struct device *dev) +{ + mem_addr_t base = DEV_BASE(dev); + uint32_t val; + + /* put controller in reset */ + val = sys_read32(base + CFG_OFFSET); + val |= BIT(CFG_RESET_SHIFT); + val &= ~BIT(CFG_EN_SHIFT); + sys_write32(val, base + CFG_OFFSET); + + k_busy_wait(100); + + /* bring controller out of reset */ + sys_clear_bit(base + CFG_OFFSET, CFG_RESET_SHIFT); +} + +#ifdef CONFIG_I2C_TARGET +/* Set target addr */ +static int iproc_i2c_target_set_address(const struct device *dev, uint16_t addr) +{ + mem_addr_t base = DEV_BASE(dev); + uint32_t val; + + if ((addr == 0) && (addr > I2C_MAX_TARGET_ADDR)) { + LOG_ERR("Invalid target address(0x%x) received", addr); + return -EINVAL; + } + + addr = ((addr & S_ADDR_OFFSET_ADDR0_MASK) | BIT(S_ADDR_OFFSET_ADDR0_EN_BIT)); + val = sys_read32(base + S_ADDR_OFFSET); + val &= ~(S_ADDR_OFFSET_ADDR0_MASK | BIT(S_ADDR_OFFSET_ADDR0_EN_BIT)); + val |= addr; + sys_write32(val, base + S_ADDR_OFFSET); + + return 0; +} + +static int iproc_i2c_target_init(const struct device *dev, bool need_reset) +{ + struct iproc_i2c_data *dd = DEV_DATA(dev); + mem_addr_t base = DEV_BASE(dev); + struct i2c_target_config *target_config = dd->target_cfg; + uint32_t val; + int ret; + + if (need_reset) { + iproc_i2c_reset_controller(dev); + } + + /* flush target TX/RX FIFOs */ + val = BIT(S_FIFO_RX_FLUSH_SHIFT) | BIT(S_FIFO_TX_FLUSH_SHIFT); + sys_write32(val, base + S_FIFO_CTRL_OFFSET); + + /* Maximum target stretch time */ + val = sys_read32(base + TIM_CFG_OFFSET); + val &= ~(TIM_RAND_TARGET_STRETCH_MASK << TIM_RAND_TARGET_STRETCH_SHIFT); + val |= (TARGET_CLOCK_STRETCH_TIME << TIM_RAND_TARGET_STRETCH_SHIFT); + sys_write32(val, base + TIM_CFG_OFFSET); + + /* Set target address */ + ret = iproc_i2c_target_set_address(dev, target_config->address); + if (ret) { + return ret; + } + + /* clear all pending target interrupts */ + sys_write32(ISR_MASK_TARGET, base + IS_OFFSET); + + /* Enable interrupt register to indicate a valid byte in receive fifo */ + val = BIT(IE_S_RX_EVENT_SHIFT); + /* Enable interrupt register to indicate target Rx FIFO Full */ + val |= BIT(IE_S_RX_FIFO_FULL_SHIFT); + /* Enable interrupt register to indicate a Master read transaction */ + val |= BIT(IE_S_RD_EN_SHIFT); + /* Enable interrupt register for the target BUSY command */ + val |= BIT(IE_S_START_BUSY_SHIFT); + dd->target_int_mask = val; + sys_write32(val, base + IE_OFFSET); + + return ret; +} + +static int iproc_i2c_check_target_status(const struct device *dev) +{ + mem_addr_t base = DEV_BASE(dev); + uint32_t val; + + val = sys_read32(base + S_CMD_OFFSET); + /* status is valid only when START_BUSY is cleared after it was set */ + if (val & BIT(S_CMD_START_BUSY_SHIFT)) { + return -EBUSY; + } + + val = (val >> S_CMD_STATUS_SHIFT) & S_CMD_STATUS_MASK; + if ((val == S_CMD_STATUS_TIMEOUT) || (val == S_CMD_STATUS_MASTER_ABORT)) { + if (val == S_CMD_STATUS_TIMEOUT) { + LOG_ERR("target random stretch time timeout"); + } else if (val == S_CMD_STATUS_MASTER_ABORT) { + LOG_ERR("Master aborted read transaction"); + } + + /* re-initialize i2c for recovery */ + iproc_i2c_enable_disable(dev, false); + iproc_i2c_target_init(dev, true); + iproc_i2c_enable_disable(dev, true); + + return -ETIMEDOUT; + } + + return 0; +} + +static void iproc_i2c_target_read(const struct device *dev) +{ + struct iproc_i2c_data *dd = DEV_DATA(dev); + struct i2c_target_config *target_cfg = dd->target_cfg; + mem_addr_t base = DEV_BASE(dev); + uint8_t rx_data, rx_status; + uint32_t rx_bytes = 0; + uint32_t val; + + while (rx_bytes < MAX_TARGET_RX_PER_INT) { + val = sys_read32(base + S_RX_OFFSET); + rx_status = (val >> S_RX_STATUS_SHIFT) & S_RX_STATUS_MASK; + rx_data = ((val >> S_RX_DATA_SHIFT) & S_RX_DATA_MASK); + + if (rx_status == I2C_TARGET_RX_START) { + /* Start of SMBUS Master write */ + target_cfg->callbacks->write_requested(target_cfg); + dd->rx_start_rcvd = true; + dd->target_read_complete = false; + } else if ((rx_status == I2C_TARGET_RX_DATA) && dd->rx_start_rcvd) { + /* Middle of SMBUS Master write */ + target_cfg->callbacks->write_received(target_cfg, rx_data); + } else if ((rx_status == I2C_TARGET_RX_END) && dd->rx_start_rcvd) { + /* End of SMBUS Master write */ + if (dd->target_rx_only) { + target_cfg->callbacks->write_received(target_cfg, rx_data); + } + target_cfg->callbacks->stop(target_cfg); + } else if (rx_status == I2C_TARGET_RX_FIFO_EMPTY) { + dd->rx_start_rcvd = false; + dd->target_read_complete = true; + break; + } + + rx_bytes++; + } +} + +static void iproc_i2c_target_rx(const struct device *dev) +{ + struct iproc_i2c_data *dd = DEV_DATA(dev); + mem_addr_t base = DEV_BASE(dev); + + iproc_i2c_target_read(dev); + + if (!dd->target_rx_only && dd->target_read_complete) { + /* + * In case of single byte master-read request, + * IS_S_TX_UNDERRUN_SHIFT event is generated before + * IS_S_START_BUSY_SHIFT event. Hence start target data send + * from first IS_S_TX_UNDERRUN_SHIFT event. + * + * This means don't send any data from target when + * IS_S_RD_EN_SHIFT event is generated else it will increment + * eeprom or other backend target driver read pointer twice. + */ + dd->tx_underrun = 0; + dd->target_int_mask |= BIT(IE_S_TX_UNDERRUN_SHIFT); + + /* clear IS_S_RD_EN_SHIFT interrupt */ + sys_write32(BIT(IS_S_RD_EN_SHIFT), base + IS_OFFSET); + } + + /* enable target interrupts */ + sys_write32(dd->target_int_mask, base + IE_OFFSET); +} + +static void iproc_i2c_target_isr(const struct device *dev, uint32_t status) +{ + struct iproc_i2c_data *dd = DEV_DATA(dev); + struct i2c_target_config *target_cfg = dd->target_cfg; + mem_addr_t base = DEV_BASE(dev); + uint32_t val; + uint8_t data; + + LOG_DBG("iproc_i2c(0x%x): %s: sl_sts 0x%x", (uint32_t)base, __func__, status); + + if (status & BIT(IS_S_RX_EVENT_SHIFT) || status & BIT(IS_S_RD_EN_SHIFT) || + status & BIT(IS_S_RX_FIFO_FULL_SHIFT)) { + /* disable target interrupts */ + val = sys_read32(base + IE_OFFSET); + val &= ~dd->target_int_mask; + sys_write32(val, base + IE_OFFSET); + + if (status & BIT(IS_S_RD_EN_SHIFT)) { + /* Master-write-read request */ + dd->target_rx_only = false; + } else { + /* Master-write request only */ + dd->target_rx_only = true; + } + + /* + * Clear IS_S_RX_EVENT_SHIFT & + * IS_S_RX_FIFO_FULL_SHIFT interrupt + */ + val = BIT(IS_S_RX_EVENT_SHIFT); + if (status & BIT(IS_S_RX_FIFO_FULL_SHIFT)) { + val |= BIT(IS_S_RX_FIFO_FULL_SHIFT); + } + sys_write32(val, base + IS_OFFSET); + + iproc_i2c_target_rx(dev); + } + + if (status & BIT(IS_S_TX_UNDERRUN_SHIFT)) { + dd->tx_underrun++; + if (dd->tx_underrun == 1) { + /* Start of SMBUS for Master Read */ + target_cfg->callbacks->read_requested(target_cfg, &data); + } else { + /* Master read other than start */ + target_cfg->callbacks->read_processed(target_cfg, &data); + } + + sys_write32(data, base + S_TX_OFFSET); + /* start transfer */ + val = BIT(S_CMD_START_BUSY_SHIFT); + sys_write32(val, base + S_CMD_OFFSET); + + sys_write32(BIT(IS_S_TX_UNDERRUN_SHIFT), base + IS_OFFSET); + } + + /* Stop received from master in case of master read transaction */ + if (status & BIT(IS_S_START_BUSY_SHIFT)) { + /* + * Disable interrupt for TX FIFO becomes empty and + * less than PKT_LENGTH bytes were output on the SMBUS + */ + dd->target_int_mask &= ~BIT(IE_S_TX_UNDERRUN_SHIFT); + sys_write32(dd->target_int_mask, base + IE_OFFSET); + + /* End of SMBUS for Master Read */ + val = BIT(S_TX_WR_STATUS_SHIFT); + sys_write32(val, base + S_TX_OFFSET); + + val = BIT(S_CMD_START_BUSY_SHIFT); + sys_write32(val, base + S_CMD_OFFSET); + + /* flush TX FIFOs */ + val = sys_read32(base + S_FIFO_CTRL_OFFSET); + val |= (BIT(S_FIFO_TX_FLUSH_SHIFT)); + sys_write32(val, base + S_FIFO_CTRL_OFFSET); + + target_cfg->callbacks->stop(target_cfg); + + sys_write32(BIT(IS_S_START_BUSY_SHIFT), base + IS_OFFSET); + } + + /* check target transmit status only if target is transmitting */ + if (!dd->target_rx_only) { + iproc_i2c_check_target_status(dev); + } +} + +static int iproc_i2c_target_register(const struct device *dev, + struct i2c_target_config *target_config) +{ + struct iproc_i2c_data *dd = DEV_DATA(dev); + mem_addr_t base = DEV_BASE(dev); + int ret = 0; + + if (dd->target_cfg) { + LOG_ERR("Target already registered"); + return -EBUSY; + } + + /* Save pointer to received target config */ + dd->target_cfg = target_config; + + ret = iproc_i2c_target_init(dev, false); + if (ret < 0) { + LOG_ERR("Failed to register iproc_i2c(0x%x) as target, ret %d", (uint32_t)base, + ret); + return ret; + } + + return 0; +} + +static int iproc_i2c_target_unregister(const struct device *dev, struct i2c_target_config *config) +{ + uint32_t val; + mem_addr_t base = DEV_BASE(dev); + struct iproc_i2c_data *dd = DEV_DATA(dev); + + if (!dd->target_cfg) { + return -EINVAL; + } + + /* Erase the target address programmed */ + sys_write32(0x0, base + S_ADDR_OFFSET); + + /* disable all target interrupts */ + val = sys_read32(base + IE_OFFSET); + val &= ~(IE_S_ALL_INTERRUPT_MASK << IE_S_ALL_INTERRUPT_SHIFT); + sys_write32(val, base + IE_OFFSET); + + dd->target_cfg = NULL; + + return 0; +} +#endif /* CONFIG_I2C_TARGET */ + +static void iproc_i2c_common_init(const struct device *dev) +{ + mem_addr_t base = DEV_BASE(dev); + uint32_t val; + + iproc_i2c_reset_controller(dev); + + /* flush TX/RX FIFOs and set RX FIFO threshold to zero */ + val = BIT(M_FIFO_RX_FLUSH_SHIFT) | BIT(M_FIFO_TX_FLUSH_SHIFT); + sys_write32(val, base + M_FIFO_CTRL_OFFSET); + + /* disable all interrupts */ + sys_write32(0, base + IE_OFFSET); + + /* clear all pending interrupts */ + sys_write32(~0, base + IS_OFFSET); +} + +static int iproc_i2c_check_status(const struct device *dev, uint16_t dev_addr, struct i2c_msg *msg) +{ + mem_addr_t base = DEV_BASE(dev); + uint32_t val; + int rc; + + val = sys_read32(base + M_CMD_OFFSET); + val >>= M_CMD_STATUS_SHIFT; + val &= M_CMD_STATUS_MASK; + + switch (val) { + case M_CMD_STATUS_SUCCESS: + rc = 0; + break; + + case M_CMD_STATUS_LOST_ARB: + LOG_ERR("lost bus arbitration"); + rc = -EAGAIN; + break; + + case M_CMD_STATUS_NACK_ADDR: + LOG_ERR("NAK addr:0x%02x", dev_addr); + rc = -ENXIO; + break; + + case M_CMD_STATUS_NACK_DATA: + LOG_ERR("NAK data"); + rc = -ENXIO; + break; + + case M_CMD_STATUS_TIMEOUT: + LOG_ERR("bus timeout"); + rc = -ETIMEDOUT; + break; + + case M_CMD_STATUS_FIFO_UNDERRUN: + LOG_ERR("FIFO Under-run"); + rc = -ENXIO; + break; + + case M_CMD_STATUS_RX_FIFO_FULL: + LOG_ERR("RX FIFO full"); + rc = -ETIMEDOUT; + break; + + default: + LOG_ERR("Unknown Error : 0x%x", val); + iproc_i2c_enable_disable(dev, false); + iproc_i2c_common_init(dev); + iproc_i2c_enable_disable(dev, true); + rc = -EIO; + break; + } + + if (rc < 0) { + /* flush both Master TX/RX FIFOs */ + val = BIT(M_FIFO_RX_FLUSH_SHIFT) | BIT(M_FIFO_TX_FLUSH_SHIFT); + sys_write32(val, base + M_FIFO_CTRL_OFFSET); + } + + return rc; +} + +static int iproc_i2c_configure(const struct device *dev, uint32_t dev_cfg_raw) +{ + mem_addr_t base = DEV_BASE(dev); + + if (I2C_ADDR_10_BITS & dev_cfg_raw) { + LOG_ERR("10-bit addressing not supported"); + return -ENOTSUP; + } + + switch (I2C_SPEED_GET(dev_cfg_raw)) { + case I2C_SPEED_STANDARD: + sys_clear_bit(base + TIM_CFG_OFFSET, TIM_CFG_MODE_400_SHIFT); + break; + case I2C_SPEED_FAST: + sys_set_bit(base + TIM_CFG_OFFSET, TIM_CFG_MODE_400_SHIFT); + break; + default: + LOG_ERR("Only standard or Fast speed modes are supported"); + return -ENOTSUP; + } + + return 0; +} + +static void iproc_i2c_read_valid_bytes(const struct device *dev) +{ + mem_addr_t base = DEV_BASE(dev); + struct iproc_i2c_data *dd = DEV_DATA(dev); + struct i2c_msg *msg = dd->msg; + uint32_t val; + + /* Read valid data from RX FIFO */ + while (dd->rx_bytes < msg->len) { + val = sys_read32(base + M_RX_OFFSET); + + /* rx fifo empty */ + if (!((val >> M_RX_STATUS_SHIFT) & M_RX_STATUS_MASK)) { + break; + } + + msg->buf[dd->rx_bytes] = (val >> M_RX_DATA_SHIFT) & M_RX_DATA_MASK; + dd->rx_bytes++; + } +} + +static int iproc_i2c_data_recv(const struct device *dev) +{ + struct iproc_i2c_data *dd = DEV_DATA(dev); + mem_addr_t base = DEV_BASE(dev); + struct i2c_msg *msg = dd->msg; + uint32_t bytes_left, val; + + iproc_i2c_read_valid_bytes(dev); + + bytes_left = msg->len - dd->rx_bytes; + if (bytes_left == 0) { + /* finished reading all data, disable rx thld event */ + sys_clear_bit(base + IE_OFFSET, IS_M_RX_THLD_SHIFT); + } else if (bytes_left < dd->thld_bytes) { + /* set bytes left as threshold */ + val = sys_read32(base + M_FIFO_CTRL_OFFSET); + val &= ~(M_FIFO_RX_THLD_MASK << M_FIFO_RX_THLD_SHIFT); + val |= (bytes_left << M_FIFO_RX_THLD_SHIFT); + sys_write32(val, base + M_FIFO_CTRL_OFFSET); + dd->thld_bytes = bytes_left; + } + /* + * if bytes_left >= dd->thld_bytes, no need to change the THRESHOLD. + * It will remain as dd->thld_bytes itself + */ + + return 0; +} + +static int iproc_i2c_transfer_one(const struct device *dev, struct i2c_msg *msg, uint16_t dev_addr) +{ + mem_addr_t base = DEV_BASE(dev); + struct iproc_i2c_data *dd = DEV_DATA(dev); + uint32_t val, addr, tx_bytes, val_intr_en; + int rc; + + if (!!(sys_read32(base + M_CMD_OFFSET) & BIT(M_CMD_START_BUSY_SHIFT))) { + LOG_ERR("Bus busy, prev xfer ongoing"); + return -EBUSY; + } + + LOG_DBG("%s: msg dev_addr 0x%x flags 0x%x len 0x%x val 0x%x\n", __func__, dev_addr, + msg->flags, msg->len, msg->buf[0]); + + /* Save current i2c_msg */ + dd->msg = msg; + + addr = dev_addr << 1 | (msg->flags & I2C_MSG_READ ? 1 : 0); + sys_write32(addr, base + M_TX_OFFSET); + + tx_bytes = MIN(msg->len, (TX_RX_FIFO_SIZE - 1)); + if (!(msg->flags & I2C_MSG_READ)) { + /* Fill master TX fifo */ + for (uint32_t i = 0; i < tx_bytes; i++) { + val = msg->buf[i]; + /* For the last byte, set MASTER_WR_STATUS bit */ + if (i == msg->len - 1) { + val |= BIT(M_TX_WR_STATUS_SHIFT); + } + sys_write32(val, base + M_TX_OFFSET); + } + + dd->tx_bytes = tx_bytes; + } + + /* + * Enable the "start busy" interrupt, which will be triggered after the + * transaction is done, i.e., the internal start_busy bit, transitions + * from 1 to 0. + */ + val_intr_en = BIT(IE_M_START_BUSY_SHIFT); + + if (!(msg->flags & I2C_MSG_READ) && (msg->len > dd->tx_bytes)) { + val_intr_en |= BIT(IE_M_TX_UNDERRUN_SHIFT); + } + + /* + * Program master command register (0x30) with protocol type and set + * start_busy_command bit to initiate the write transaction + */ + val = BIT(M_CMD_START_BUSY_SHIFT); + if (msg->len == 0) { + /* SMBUS QUICK Command (Read/Write) */ + val |= (M_CMD_SMB_PROT_QUICK << M_CMD_SMB_PROT_SHIFT); + } else if (msg->flags & I2C_MSG_READ) { + uint32_t tmp; + + dd->rx_bytes = 0; + + /* SMBUS Block Read Command */ + val |= M_CMD_SMB_PROT_BLK_RD << M_CMD_SMB_PROT_SHIFT; + val |= msg->len; + + if (msg->len > M_RX_FIFO_MAX_THLD_VALUE) { + dd->thld_bytes = M_RX_FIFO_THLD_VALUE; + } else { + dd->thld_bytes = msg->len; + } + + /* set threshold value */ + tmp = sys_read32(base + M_FIFO_CTRL_OFFSET); + tmp &= ~(M_FIFO_RX_THLD_MASK << M_FIFO_RX_THLD_SHIFT); + tmp |= dd->thld_bytes << M_FIFO_RX_THLD_SHIFT; + sys_write32(tmp, base + M_FIFO_CTRL_OFFSET); + + /* enable the RX threshold interrupt */ + val_intr_en |= BIT(IE_M_RX_THLD_SHIFT); + } else { + /* SMBUS Block Write Command */ + val |= M_CMD_SMB_PROT_BLK_WR << M_CMD_SMB_PROT_SHIFT; + } + + sys_write32(val_intr_en, base + IE_OFFSET); + + sys_write32(val, base + M_CMD_OFFSET); + + /* Wait for the transfer to complete or timeout */ + rc = k_sem_take(&dd->device_sync_sem, K_MSEC(I2C_TIMEOUT_MSEC)); + + /* disable all interrupts */ + sys_write32(0, base + IE_OFFSET); + + if (rc != 0) { + /* flush both Master TX/RX FIFOs */ + val = BIT(M_FIFO_RX_FLUSH_SHIFT) | BIT(M_FIFO_TX_FLUSH_SHIFT); + sys_write32(val, base + M_FIFO_CTRL_OFFSET); + return rc; + } + + /* Check for Master Xfer status */ + rc = iproc_i2c_check_status(dev, dev_addr, msg); + + return rc; +} + +static int iproc_i2c_transfer_multi(const struct device *dev, struct i2c_msg *msgs, + uint8_t num_msgs, uint16_t addr) +{ + int rc; + struct i2c_msg *msgs_chk = msgs; + + if (!msgs_chk) { + return -EINVAL; + } + + /* pre-check all msgs */ + for (uint8_t i = 0; i < num_msgs; i++, msgs_chk++) { + if (!msgs_chk->buf) { + LOG_ERR("Invalid msg buffer"); + return -EINVAL; + } + + if (I2C_MSG_ADDR_10_BITS & msgs_chk->flags) { + LOG_ERR("10-bit addressing not supported"); + return -ENOTSUP; + } + } + + for (uint8_t i = 0; i < num_msgs; i++, msgs++) { + rc = iproc_i2c_transfer_one(dev, msgs, addr); + if (rc < 0) { + return rc; + } + } + + return 0; +} + +static void iproc_i2c_send_data(const struct device *dev) +{ + mem_addr_t base = DEV_BASE(dev); + struct iproc_i2c_data *dd = DEV_DATA(dev); + struct i2c_msg *msg = dd->msg; + uint32_t tx_bytes = msg->len - dd->tx_bytes; + + /* can only fill up to the FIFO size */ + tx_bytes = MIN(tx_bytes, TX_RX_FIFO_SIZE); + for (uint32_t i = 0; i < tx_bytes; i++) { + /* start from where we left over */ + uint32_t idx = dd->tx_bytes + i; + + uint32_t val = msg->buf[idx]; + + /* mark the last byte */ + if (idx == (msg->len - 1)) { + uint32_t tmp; + + val |= BIT(M_TX_WR_STATUS_SHIFT); + + /* + * Since this is the last byte, we should now + * disable TX FIFO underrun interrupt + */ + tmp = sys_read32(base + IE_OFFSET); + tmp &= ~BIT(IE_M_TX_UNDERRUN_SHIFT); + sys_write32(tmp, base + IE_OFFSET); + } + + /* load data into TX FIFO */ + sys_write32(val, base + M_TX_OFFSET); + } + + /* update number of transferred bytes */ + dd->tx_bytes += tx_bytes; +} + +static void iproc_i2c_master_isr(const struct device *dev, uint32_t status) +{ + struct iproc_i2c_data *dd = DEV_DATA(dev); + + /* TX FIFO is empty and we have more data to send */ + if (status & BIT(IS_M_TX_UNDERRUN_SHIFT)) { + iproc_i2c_send_data(dev); + } + + /* RX FIFO threshold is reached and data needs to be read out */ + if (status & BIT(IS_M_RX_THLD_SHIFT)) { + iproc_i2c_data_recv(dev); + } + + /* transfer is done */ + if (status & BIT(IS_M_START_BUSY_SHIFT)) { + k_sem_give(&dd->device_sync_sem); + } +} + +static void iproc_i2c_isr(void *arg) +{ + const struct device *dev = (const struct device *)arg; + mem_addr_t base = DEV_BASE(dev); + uint32_t status; + uint32_t sl_status, curr_irqs; + + curr_irqs = sys_read32(base + IE_OFFSET); + status = sys_read32(base + IS_OFFSET); + + /* process only target interrupt which are enabled */ + sl_status = status & curr_irqs & ISR_MASK_TARGET; + LOG_DBG("iproc_i2c(0x%x): sts 0x%x, sl_sts 0x%x, curr_ints 0x%x", (uint32_t)base, status, + sl_status, curr_irqs); + +#ifdef CONFIG_I2C_TARGET + /* target events */ + if (sl_status) { + iproc_i2c_target_isr(dev, sl_status); + return; + } +#endif + + status &= ISR_MASK; + /* master events */ + if (status) { + iproc_i2c_master_isr(dev, status); + sys_write32(status, base + IS_OFFSET); + } +} + +static int iproc_i2c_init(const struct device *dev) +{ + const struct iproc_i2c_config *config = DEV_CFG(dev); + struct iproc_i2c_data *dd = DEV_DATA(dev); + uint32_t bitrate = config->bitrate; + int error; + + k_sem_init(&dd->device_sync_sem, 0, 1); + + iproc_i2c_common_init(dev); + + /* Set default clock frequency */ + bitrate = i2c_map_dt_bitrate(bitrate); + + if (dd->target_cfg == NULL) { + bitrate |= I2C_MODE_CONTROLLER; + } + + error = iproc_i2c_configure(dev, bitrate); + if (error) { + return error; + } + + config->irq_config_func(dev); + + iproc_i2c_enable_disable(dev, true); + + return 0; +} + +static const struct i2c_driver_api iproc_i2c_driver_api = { + .configure = iproc_i2c_configure, + .transfer = iproc_i2c_transfer_multi, +#ifdef CONFIG_I2C_TARGET + .target_register = iproc_i2c_target_register, + .target_unregister = iproc_i2c_target_unregister, +#endif +}; + +#define IPROC_I2C_DEVICE_INIT(n) \ + static void iproc_i2c_irq_config_func_##n(const struct device *dev) \ + { \ + ARG_UNUSED(dev); \ + IRQ_CONNECT(DT_INST_IRQN(n), DT_INST_IRQ(n, priority), iproc_i2c_isr, \ + DEVICE_DT_INST_GET(n), 0); \ + \ + irq_enable(DT_INST_IRQN(n)); \ + } \ + \ + static const struct iproc_i2c_config iproc_i2c_config_##n = { \ + .base = DT_INST_REG_ADDR(n), \ + .irq_config_func = iproc_i2c_irq_config_func_##n, \ + .bitrate = DT_INST_PROP(n, clock_frequency), \ + }; \ + \ + static struct iproc_i2c_data iproc_i2c_data_##n; \ + \ + I2C_DEVICE_DT_INST_DEFINE(n, &iproc_i2c_init, NULL, &iproc_i2c_data_##n, \ + &iproc_i2c_config_##n, POST_KERNEL, CONFIG_I2C_INIT_PRIORITY, \ + &iproc_i2c_driver_api); + +DT_INST_FOREACH_STATUS_OKAY(IPROC_I2C_DEVICE_INIT) diff --git a/dts/bindings/i2c/brcm,iproc-i2c.yaml b/dts/bindings/i2c/brcm,iproc-i2c.yaml new file mode 100644 index 0000000000000..343674488f49d --- /dev/null +++ b/dts/bindings/i2c/brcm,iproc-i2c.yaml @@ -0,0 +1,16 @@ +# Copyright 2020 Broadcom +# Copyright 2024 Meta Platforms +# SPDX-License-Identifier: Apache-2.0 + +description: Broadcom iProc I2C controller + +compatible: "brcm,iproc-i2c" + +include: i2c-controller.yaml + +properties: + reg: + required: true + + interrupts: + required: true diff --git a/tests/drivers/build_all/i2c/boards/qemu_cortex_m3.overlay b/tests/drivers/build_all/i2c/boards/qemu_cortex_m3.overlay index 1abc687904d64..b041b987dd1d6 100644 --- a/tests/drivers/build_all/i2c/boards/qemu_cortex_m3.overlay +++ b/tests/drivers/build_all/i2c/boards/qemu_cortex_m3.overlay @@ -4,6 +4,8 @@ * SPDX-License-Identifier: Apache-2.0 */ + #include + / { i2c0: i2c@88888888 { compatible = "xlnx,xps-iic-2.00.a"; @@ -22,4 +24,14 @@ interrupt-parent = <&nvic>; interrupts = <5 1>; }; + + i2c2: i2c@888A8888 { + compatible = "brcm,iproc-i2c"; + clock-frequency = ; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x888A8888 0x100>; + interrupt-parent = <&nvic>; + interrupts = <6 1>; + }; }; From af450ea3cc9a325002c3c383813ab5b7c43ac843 Mon Sep 17 00:00:00 2001 From: Yong Cong Sin Date: Fri, 10 May 2024 12:10:06 +0800 Subject: [PATCH 1226/2849] drivers: gpio: add Broadcom iProc GPIO controller driver Add device driver, bindings and build-only test for Broadcom iProc GPIO controller. Signed-off-by: Yong Cong Sin --- drivers/gpio/CMakeLists.txt | 1 + drivers/gpio/Kconfig | 1 + drivers/gpio/Kconfig.iproc | 11 + drivers/gpio/gpio_iproc.c | 225 +++++++++++++++++++++ dts/bindings/gpio/brcm,iproc-gpio.yaml | 29 +++ tests/drivers/build_all/gpio/iproc.overlay | 35 ++++ tests/drivers/build_all/gpio/testcase.yaml | 5 + 7 files changed, 307 insertions(+) create mode 100644 drivers/gpio/Kconfig.iproc create mode 100644 drivers/gpio/gpio_iproc.c create mode 100644 dts/bindings/gpio/brcm,iproc-gpio.yaml create mode 100644 tests/drivers/build_all/gpio/iproc.overlay diff --git a/drivers/gpio/CMakeLists.txt b/drivers/gpio/CMakeLists.txt index 787a10d7dd5d4..6e1cab6d2485e 100644 --- a/drivers/gpio/CMakeLists.txt +++ b/drivers/gpio/CMakeLists.txt @@ -32,6 +32,7 @@ zephyr_library_sources_ifdef(CONFIG_GPIO_GECKO gpio_gecko.c) zephyr_library_sources_ifdef(CONFIG_GPIO_IMX gpio_imx.c) zephyr_library_sources_ifdef(CONFIG_GPIO_INFINEON_CAT1 gpio_ifx_cat1.c) zephyr_library_sources_ifdef(CONFIG_GPIO_INTEL gpio_intel.c) +zephyr_library_sources_ifdef(CONFIG_GPIO_IPROC gpio_iproc.c) zephyr_library_sources_ifdef(CONFIG_GPIO_ITE_IT8XXX2 gpio_ite_it8xxx2.c) zephyr_library_sources_ifdef(CONFIG_GPIO_ITE_IT8XXX2_V2 gpio_ite_it8xxx2_v2.c) zephyr_library_sources_ifdef(CONFIG_GPIO_KSCAN_ITE_IT8XXX2 gpio_kscan_ite_it8xxx2.c) diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 9ce2b7f5859f9..f9126fef8d970 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -124,6 +124,7 @@ source "drivers/gpio/Kconfig.gecko" source "drivers/gpio/Kconfig.ifx_cat1" source "drivers/gpio/Kconfig.imx" source "drivers/gpio/Kconfig.intel" +source "drivers/gpio/Kconfig.iproc" source "drivers/gpio/Kconfig.it8xxx2" source "drivers/gpio/Kconfig.litex" source "drivers/gpio/Kconfig.lmp90xxx" diff --git a/drivers/gpio/Kconfig.iproc b/drivers/gpio/Kconfig.iproc new file mode 100644 index 0000000000000..8bec1c966d434 --- /dev/null +++ b/drivers/gpio/Kconfig.iproc @@ -0,0 +1,11 @@ +# Copyright 2020 Broadcom +# Copyright 2024 Meta +# SPDX-License-Identifier: Apache-2.0 + +config GPIO_IPROC + bool "Broadcom iProc GPIO controller driver" + default y + depends on DT_HAS_BRCM_IPROC_GPIO_ENABLED + help + This option enables the GPIO driver for iProc family + of GPIO controller. diff --git a/drivers/gpio/gpio_iproc.c b/drivers/gpio/gpio_iproc.c new file mode 100644 index 0000000000000..def1a07dd4ea8 --- /dev/null +++ b/drivers/gpio/gpio_iproc.c @@ -0,0 +1,225 @@ +/* + * Copyright 2020 Broadcom + * Copyright 2024 Meta + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT brcm_iproc_gpio + +#include +#include +#include +#include +#include +#include + +#define IPROC_GPIO_DATA_IN_OFFSET 0x00 +#define IPROC_GPIO_DATA_OUT_OFFSET 0x04 +#define IPROC_GPIO_OUT_EN_OFFSET 0x08 +#define IPROC_GPIO_INT_TYPE_OFFSET 0x0c +#define IPROC_GPIO_INT_DE_OFFSET 0x10 +#define IPROC_GPIO_INT_EDGE_OFFSET 0x14 +#define IPROC_GPIO_INT_MSK_OFFSET 0x18 +#define IPROC_GPIO_INT_STAT_OFFSET 0x1c +#define IPROC_GPIO_INT_MSTAT_OFFSET 0x20 +#define IPROC_GPIO_INT_CLR_OFFSET 0x24 +#define IPROC_GPIO_PAD_RES_OFFSET 0x34 +#define IPROC_GPIO_RES_EN_OFFSET 0x38 + +struct gpio_iproc_config { + /* gpio_driver_config needs to be first */ + struct gpio_driver_config common; + mem_addr_t base; + void (*irq_config_func)(const struct device *dev); +}; + +struct gpio_iproc_data { + /* gpio_driver_data needs to be first */ + struct gpio_driver_data common; + sys_slist_t cb; +}; + +#define DEV_CFG(dev) ((const struct gpio_iproc_config *const)(dev)->config) +#define DEV_DATA(dev) ((struct gpio_iproc_data *const)(dev)->data) + +static int gpio_iproc_configure(const struct device *dev, gpio_pin_t pin, gpio_flags_t flags) +{ + const struct gpio_iproc_config *const cfg = DEV_CFG(dev); + mem_addr_t base = cfg->base; + + /* Setup the pin direcion. */ + if (flags & GPIO_OUTPUT) { + /* configure pin for output */ + sys_set_bit(base + IPROC_GPIO_OUT_EN_OFFSET, pin); + } else if (flags & GPIO_INPUT) { + /* configure pin for input */ + sys_clear_bit(base + IPROC_GPIO_OUT_EN_OFFSET, pin); + } + + return 0; +} + +static int gpio_iproc_port_get_raw(const struct device *dev, uint32_t *value) +{ + const struct gpio_iproc_config *const cfg = DEV_CFG(dev); + mem_addr_t base = cfg->base; + + *value = sys_read32(base + IPROC_GPIO_DATA_IN_OFFSET); + + return 0; +} + +static int gpio_iproc_port_set_masked_raw(const struct device *dev, uint32_t mask, uint32_t value) +{ + const struct gpio_iproc_config *const cfg = DEV_CFG(dev); + mem_addr_t base = cfg->base; + + value = sys_read32(base + IPROC_GPIO_DATA_OUT_OFFSET); + value = (value & (~mask)) | (value & mask); + sys_write32(base + IPROC_GPIO_DATA_OUT_OFFSET, value); + + return 0; +} + +static int gpio_iproc_port_set_bits_raw(const struct device *dev, uint32_t mask) +{ + const struct gpio_iproc_config *const cfg = DEV_CFG(dev); + mem_addr_t base = cfg->base; + + sys_write32(base + IPROC_GPIO_DATA_OUT_OFFSET, mask); + + return 0; +} + +static int gpio_iproc_port_clear_bits_raw(const struct device *dev, uint32_t mask) +{ + uint32_t value; + const struct gpio_iproc_config *const cfg = DEV_CFG(dev); + mem_addr_t base = cfg->base; + + /* Clear pins. */ + value = sys_read32(base + IPROC_GPIO_DATA_OUT_OFFSET); + value = (value & ~mask); + sys_write32(base + IPROC_GPIO_DATA_OUT_OFFSET, value); + + return 0; +} + +static int gpio_iproc_port_toggle_bits(const struct device *dev, uint32_t mask) +{ + uint32_t value; + const struct gpio_iproc_config *const cfg = DEV_CFG(dev); + mem_addr_t base = cfg->base; + + /* toggles pins. */ + value = sys_read32(base + IPROC_GPIO_DATA_OUT_OFFSET); + value = (value ^ mask); + sys_write32(base + IPROC_GPIO_DATA_OUT_OFFSET, value); + + return 0; +} + +static int gpio_iproc_pin_interrupt_configure(const struct device *dev, gpio_pin_t pin, + enum gpio_int_mode mode, enum gpio_int_trig trig) +{ + const struct gpio_iproc_config *const cfg = DEV_CFG(dev); + mem_addr_t base = cfg->base; + + /* check for interrupt configurations */ + if (mode & GPIO_INT_ENABLE) { + if (mode & GPIO_INT_EDGE) { + sys_clear_bit(base + IPROC_GPIO_INT_TYPE_OFFSET, pin); + } else { + sys_set_bit(base + IPROC_GPIO_INT_TYPE_OFFSET, pin); + } + + /* Generate interrupt of both falling/rising edge */ + if (trig & GPIO_INT_EDGE_BOTH) { + sys_set_bit(base + IPROC_GPIO_INT_DE_OFFSET, pin); + } else if (trig & GPIO_INT_HIGH_1) { + /* Generate interrupt on rising edge */ + sys_clear_bit(base + IPROC_GPIO_INT_DE_OFFSET, pin); + sys_set_bit(base + IPROC_GPIO_INT_EDGE_OFFSET, pin); + } else if (trig & GPIO_INT_LOW_0) { + /* Generate interrupt on falling edge */ + sys_clear_bit(base + IPROC_GPIO_INT_DE_OFFSET, pin); + sys_clear_bit(base + IPROC_GPIO_INT_EDGE_OFFSET, pin); + } + + /* Unmask the interrupt */ + sys_clear_bit(base + IPROC_GPIO_INT_MSTAT_OFFSET, pin); + } else { + sys_set_bit(base + IPROC_GPIO_INT_MSK_OFFSET, pin); + } + return 0; +} + +static void gpio_iproc_isr(const struct device *dev) +{ + const struct gpio_iproc_config *const cfg = DEV_CFG(dev); + mem_addr_t base = cfg->base; + struct gpio_iproc_data *context = dev->data; + uint32_t int_stat; + + int_stat = sys_read32(base + IPROC_GPIO_INT_STAT_OFFSET); + + /* Clear the source of the interrupt */ + sys_write32(int_stat, base + IPROC_GPIO_INT_CLR_OFFSET); + + /* Handle the interrupt */ + gpio_fire_callbacks(&context->cb, dev, int_stat); +} + +static int gpio_iproc_manage_callback(const struct device *port, struct gpio_callback *callback, + bool set) +{ + struct gpio_iproc_data *context = port->data; + + return gpio_manage_callback(&context->cb, callback, set); +} + +static const struct gpio_driver_api gpio_iproc_api = { + .pin_configure = gpio_iproc_configure, + .port_get_raw = gpio_iproc_port_get_raw, + .port_set_masked_raw = gpio_iproc_port_set_masked_raw, + .port_set_bits_raw = gpio_iproc_port_set_bits_raw, + .port_clear_bits_raw = gpio_iproc_port_clear_bits_raw, + .port_toggle_bits = gpio_iproc_port_toggle_bits, + .pin_interrupt_configure = gpio_iproc_pin_interrupt_configure, + .manage_callback = gpio_iproc_manage_callback, +}; + +int gpio_iproc_init(const struct device *dev) +{ + const struct gpio_iproc_config *const cfg = DEV_CFG(dev); + + cfg->irq_config_func(dev); + + return 0; +} + +#define GPIO_IPROC_INIT(n) \ + static void port_iproc_config_func_##n(const struct device *dev) \ + { \ + IRQ_CONNECT(DT_INST_IRQN(n), DT_INST_IRQ(n, priority), gpio_iproc_isr, \ + DEVICE_DT_INST_GET(n), 0); \ + irq_enable(DT_INST_IRQN(n)); \ + } \ + \ + static const struct gpio_iproc_config gpio_port_config_##n = { \ + .common = \ + { \ + .port_pin_mask = GPIO_PORT_PIN_MASK_FROM_DT_INST(n), \ + }, \ + .base = DT_INST_REG_ADDR(n), \ + .irq_config_func = port_iproc_config_func_##n, \ + }; \ + \ + static struct gpio_iproc_data gpio_port_data_##n; \ + \ + DEVICE_DT_INST_DEFINE(n, gpio_iproc_init, NULL, &gpio_port_data_##n, \ + &gpio_port_config_##n, POST_KERNEL, CONFIG_GPIO_INIT_PRIORITY, \ + &gpio_iproc_api); + +DT_INST_FOREACH_STATUS_OKAY(GPIO_IPROC_INIT) diff --git a/dts/bindings/gpio/brcm,iproc-gpio.yaml b/dts/bindings/gpio/brcm,iproc-gpio.yaml new file mode 100644 index 0000000000000..11543d6fe7393 --- /dev/null +++ b/dts/bindings/gpio/brcm,iproc-gpio.yaml @@ -0,0 +1,29 @@ +# Copyright 2020 Broadcom +# SPDX-License-Identifier: Apache-2.0 + +description: Broadcom iProc GPIO Controller + +compatible: "brcm,iproc-gpio" + +include: [gpio-controller.yaml, base.yaml] + +properties: + reg: + required: true + description: | + Define the base and range of the I/O address space that contains SoC + GPIO/PINCONF controller registers + + ngpios: + required: true + description: Total number of in-use slots in GPIO controller + + interrupts: + required: true + + "#gpio-cells": + const: 2 + +gpio-cells: + - pin + - flags diff --git a/tests/drivers/build_all/gpio/iproc.overlay b/tests/drivers/build_all/gpio/iproc.overlay new file mode 100644 index 0000000000000..b25d6ec64bf45 --- /dev/null +++ b/tests/drivers/build_all/gpio/iproc.overlay @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2024, Meta Platforms + * + * SPDX-License-Identifier: Apache-2.0 + * + * Application overlay for testing iproc driver builds + */ + + / { + test { + test_int_gpio { + #address-cells = <1>; + #size-cells = <1>; + interrupt-parent = <&test_nvic>; + + test_nvic: interrupt-controller@bbbbcccc { + compatible = "arm,v6m-nvic"; + reg = <0xbbbbcccc 0xc00>; + interrupt-controller; + #interrupt-cells = <2>; + arm,num-irq-priority-bits = <3>; + }; + + test_gpio_iproc: gpio@c10fee { + compatible = "brcm,iproc-gpio"; + gpio-controller; + reg = <0xc10fee 0x4c>; + ngpios = <6>; + interrupts = <28 1>; + #gpio-cells = <0x2>; + status = "okay"; + }; + }; + }; +}; diff --git a/tests/drivers/build_all/gpio/testcase.yaml b/tests/drivers/build_all/gpio/testcase.yaml index b3f761413962d..6b87243550dc9 100644 --- a/tests/drivers/build_all/gpio/testcase.yaml +++ b/tests/drivers/build_all/gpio/testcase.yaml @@ -34,3 +34,8 @@ tests: extra_args: - DTC_OVERLAY_FILE="app.overlay;adc_ads1145s0x_gpio.overlay" - CONF_FILE="adc_ads1145s0x_gpio.conf" + + drivers.gpio.build.iproc: + platform_allow: qemu_cortex_m3 + depends_on: gpio + extra_args: DTC_OVERLAY_FILE="iproc.overlay" From ab8c0dd3c06bc3aa9b925649fe24a85836b30ce7 Mon Sep 17 00:00:00 2001 From: Yong Cong Sin Date: Sat, 11 May 2024 13:25:43 +0800 Subject: [PATCH 1227/2849] tests: drivers: build_all: gpio: fix efinix_sapphire indentation Fix indentation of the `efinix_sapphire.overlay` Signed-off-by: Yong Cong Sin --- tests/drivers/build_all/gpio/efinix_sapphire.overlay | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/drivers/build_all/gpio/efinix_sapphire.overlay b/tests/drivers/build_all/gpio/efinix_sapphire.overlay index bfa659c94abe8..0be1e3e525a41 100644 --- a/tests/drivers/build_all/gpio/efinix_sapphire.overlay +++ b/tests/drivers/build_all/gpio/efinix_sapphire.overlay @@ -14,7 +14,7 @@ gpio-controller; reg = <0xdeadbeef 0x1000>; #gpio-cells = <0x2>; - ngpios = <4>; + ngpios = <4>; status = "okay"; }; }; From 8b4822861be227d46059fffa51500315a55e68fc Mon Sep 17 00:00:00 2001 From: Bjarki Arge Andreasen Date: Tue, 27 Feb 2024 09:02:37 +0100 Subject: [PATCH 1228/2849] modem: chat: Add runtime API to modem chat matches Add APIs for changing the contents of modem chat matches safely at runtime. This allows for reusing a single modem_chat_match at the cost of placing the match and its buffers in RAM. Signed-off-by: Bjarki Arge Andreasen --- include/zephyr/modem/chat.h | 54 +++++++++++++++++++++++- subsys/modem/modem_chat.c | 54 ++++++++++++++++++++++++ tests/subsys/modem/modem_chat/src/main.c | 28 ++++++++++++ 3 files changed, 134 insertions(+), 2 deletions(-) diff --git a/include/zephyr/modem/chat.h b/include/zephyr/modem/chat.h index a30a7191ba967..4111c06aca44b 100644 --- a/include/zephyr/modem/chat.h +++ b/include/zephyr/modem/chat.h @@ -45,9 +45,9 @@ struct modem_chat_match { /** Size of separators array */ uint8_t separators_size; /** Set if modem chat instance shall use wildcards when matching */ - uint8_t wildcards : 1; + bool wildcards; /** Set if script shall not continue to next step in case of match */ - uint8_t partial : 1; + bool partial; /** Type of modem chat instance */ modem_chat_match_callback callback; }; @@ -376,6 +376,56 @@ void modem_chat_script_abort(struct modem_chat *chat); */ void modem_chat_release(struct modem_chat *chat); +/** + * @brief Initialize modem chat match + * @param chat_match Modem chat match instance + */ +void modem_chat_match_init(struct modem_chat_match *chat_match); + +/** + * @brief Set match of modem chat match instance + * @param chat_match Modem chat match instance + * @param match Match to set + * @note The lifetime of match must match or exceed the lifetime of chat_match + * @warning Always call this API after match is modified + * + * @retval 0 if successful, negative errno code otherwise + */ +int modem_chat_match_set_match(struct modem_chat_match *chat_match, const char *match); + +/** + * @brief Set separators of modem chat match instance + * @param chat_match Modem chat match instance + * @param separators Separators to set + * @note The lifetime of separators must match or exceed the lifetime of chat_match + * @warning Always call this API after separators are modified + * + * @retval 0 if successful, negative errno code otherwise + */ +int modem_chat_match_set_separators(struct modem_chat_match *chat_match, const char *separators); + +/** + * @brief Set modem chat match callback + * @param chat_match Modem chat match instance + * @param callback Callback to set + */ +void modem_chat_match_set_callback(struct modem_chat_match *chat_match, + modem_chat_match_callback callback); + +/** + * @brief Set modem chat match partial flag + * @param chat_match Modem chat match instance + * @param partial Partial flag to set + */ +void modem_chat_match_set_partial(struct modem_chat_match *chat_match, bool partial); + +/** + * @brief Set modem chat match wildcards flag + * @param chat_match Modem chat match instance + * @param enable Enable/disable Wildcards + */ +void modem_chat_match_enable_wildcards(struct modem_chat_match *chat_match, bool enable); + #ifdef __cplusplus } #endif diff --git a/subsys/modem/modem_chat.c b/subsys/modem/modem_chat.c index b13334d145ba6..82742e7329dde 100644 --- a/subsys/modem/modem_chat.c +++ b/subsys/modem/modem_chat.c @@ -4,6 +4,9 @@ * SPDX-License-Identifier: Apache-2.0 */ +#undef _POSIX_C_SOURCE +#define _POSIX_C_SOURCE 200809L + #include LOG_MODULE_REGISTER(modem_chat, CONFIG_MODEM_MODULES_LOG_LEVEL); @@ -929,3 +932,54 @@ void modem_chat_release(struct modem_chat *chat) chat->matches[MODEM_CHAT_MATCHES_INDEX_RESPONSE] = NULL; chat->matches_size[MODEM_CHAT_MATCHES_INDEX_RESPONSE] = 0; } + +void modem_chat_match_init(struct modem_chat_match *chat_match) +{ + memset(chat_match, 0, sizeof(struct modem_chat_match)); +} + +int modem_chat_match_set_match(struct modem_chat_match *chat_match, const char *match) +{ + size_t size; + + size = strnlen(match, UINT8_MAX + 1); + + if (size == (UINT8_MAX + 1)) { + return -ENOMEM; + } + + chat_match->match = match; + chat_match->match_size = (uint8_t)size; + return 0; +} + +int modem_chat_match_set_separators(struct modem_chat_match *chat_match, const char *separators) +{ + size_t size; + + size = strnlen(separators, UINT8_MAX + 1); + + if (size == (UINT8_MAX + 1)) { + return -ENOMEM; + } + + chat_match->separators = separators; + chat_match->separators_size = (uint8_t)size; + return 0; +} + +void modem_chat_match_set_callback(struct modem_chat_match *match, + modem_chat_match_callback callback) +{ + match->callback = callback; +} + +void modem_chat_match_set_partial(struct modem_chat_match *match, bool partial) +{ + match->partial = partial; +} + +void modem_chat_match_enable_wildcards(struct modem_chat_match *match, bool enable) +{ + match->wildcards = enable; +} diff --git a/tests/subsys/modem/modem_chat/src/main.c b/tests/subsys/modem/modem_chat/src/main.c index e589c34bb9287..532805b65f675 100644 --- a/tests/subsys/modem/modem_chat/src/main.c +++ b/tests/subsys/modem/modem_chat/src/main.c @@ -676,6 +676,34 @@ ZTEST(modem_chat, test_script_chat_timeout_cmd) "Script sent too many requests"); } +ZTEST(modem_chat, test_runtime_match) +{ + int ret; + struct modem_chat_match test_match; + + modem_chat_match_init(&test_match); + + ret = modem_chat_match_set_match(&test_match, "AT345"); + zassert_ok(ret, "Failed to set match"); + zassert_ok(strcmp(test_match.match, "AT345"), "Failed to set match"); + zassert_equal(test_match.match_size, 5, "Failed to set size of match"); + + ret = modem_chat_match_set_separators(&test_match, ",*"); + zassert_ok(ret, "Failed to set match"); + zassert_ok(strcmp(test_match.separators, ",*"), "Failed to set separators"); + zassert_equal(test_match.separators_size, 2, "Failed to set size of separators"); + + modem_chat_match_set_partial(&test_match, true); + zassert_equal(test_match.partial, true); + modem_chat_match_set_partial(&test_match, false); + zassert_equal(test_match.partial, false); + + modem_chat_match_enable_wildcards(&test_match, true); + zassert_equal(test_match.wildcards, true); + modem_chat_match_enable_wildcards(&test_match, false); + zassert_equal(test_match.wildcards, false); +} + /*************************************************************************************************/ /* Test suite */ /*************************************************************************************************/ From 2a575a6bf5f903ca7f7d7ce9481de70eafe75a73 Mon Sep 17 00:00:00 2001 From: Bjarki Arge Andreasen Date: Wed, 28 Feb 2024 07:17:15 +0100 Subject: [PATCH 1229/2849] modem: chat: Add runtime API to modem_chat_script_chat Add APIs allowing for modifying the modem_chat_script_chat safely at runtime. Signed-off-by: Bjarki Arge Andreasen --- include/zephyr/modem/chat.h | 39 ++++++++++++++++++++ subsys/modem/modem_chat.c | 46 ++++++++++++++++++++++++ tests/subsys/modem/modem_chat/src/main.c | 30 ++++++++++++++++ 3 files changed, 115 insertions(+) diff --git a/include/zephyr/modem/chat.h b/include/zephyr/modem/chat.h index 4111c06aca44b..be5cf4b8f11cb 100644 --- a/include/zephyr/modem/chat.h +++ b/include/zephyr/modem/chat.h @@ -426,6 +426,45 @@ void modem_chat_match_set_partial(struct modem_chat_match *chat_match, bool part */ void modem_chat_match_enable_wildcards(struct modem_chat_match *chat_match, bool enable); +/** + * @brief Initialize modem chat script chat + * @param script_chat Modem chat script chat instance + */ +void modem_chat_script_chat_init(struct modem_chat_script_chat *script_chat); + +/** + * @brief Set request of modem chat script chat instance + * @param script_chat Modem chat script chat instance + * @param request Request to set + * @note The lifetime of request must match or exceed the lifetime of script_chat + * @warning Always call this API after request is modified + * + * @retval 0 if successful, negative errno code otherwise + */ +int modem_chat_script_chat_set_request(struct modem_chat_script_chat *script_chat, + const char *request); + +/** + * @brief Set modem chat script chat matches + * @param script_chat Modem chat script chat instance + * @param response_matches Response match array to set + * @param response_matches_size Size of response match array + * @note The lifetime of response_matches must match or exceed the lifetime of script_chat + * + * @retval 0 if successful, negative errno code otherwise + */ +int modem_chat_script_chat_set_response_matches(struct modem_chat_script_chat *script_chat, + const struct modem_chat_match *response_matches, + uint16_t response_matches_size); + +/** + * @brief Set modem chat script chat timeout + * @param script_chat Modem chat script chat instance + * @param timeout_ms Timeout in milliseconds + */ +void modem_chat_script_chat_set_timeout(struct modem_chat_script_chat *script_chat, + uint16_t timeout_ms); + #ifdef __cplusplus } #endif diff --git a/subsys/modem/modem_chat.c b/subsys/modem/modem_chat.c index 82742e7329dde..ffd0fadf4657d 100644 --- a/subsys/modem/modem_chat.c +++ b/subsys/modem/modem_chat.c @@ -764,6 +764,12 @@ static void modem_chat_pipe_callback(struct modem_pipe *pipe, enum modem_pipe_ev } } +static bool modem_chat_validate_array(const void *array, size_t size) +{ + return ((array == NULL) && (size == 0)) || + ((array != NULL) && (size > 0)); +} + #if CONFIG_MODEM_STATS static uint32_t get_receive_buf_size(struct modem_chat *chat) { @@ -983,3 +989,43 @@ void modem_chat_match_enable_wildcards(struct modem_chat_match *match, bool enab { match->wildcards = enable; } + +void modem_chat_script_chat_init(struct modem_chat_script_chat *script_chat) +{ + memset(script_chat, 0, sizeof(struct modem_chat_script_chat)); +} + +int modem_chat_script_chat_set_request(struct modem_chat_script_chat *script_chat, + const char *request) +{ + size_t size; + + size = strnlen(request, UINT16_MAX + 1); + + if (size == (UINT16_MAX + 1)) { + return -ENOMEM; + } + + script_chat->request = request; + script_chat->request_size = (uint16_t)size; + return 0; +} + +int modem_chat_script_chat_set_response_matches(struct modem_chat_script_chat *script_chat, + const struct modem_chat_match *response_matches, + uint16_t response_matches_size) +{ + if (!modem_chat_validate_array(response_matches, response_matches_size)) { + return -EINVAL; + } + + script_chat->response_matches = response_matches; + script_chat->response_matches_size = response_matches_size; + return 0; +} + +void modem_chat_script_chat_set_timeout(struct modem_chat_script_chat *script_chat, + uint16_t timeout) +{ + script_chat->timeout = timeout; +} diff --git a/tests/subsys/modem/modem_chat/src/main.c b/tests/subsys/modem/modem_chat/src/main.c index 532805b65f675..fd5e773b08e3b 100644 --- a/tests/subsys/modem/modem_chat/src/main.c +++ b/tests/subsys/modem/modem_chat/src/main.c @@ -704,6 +704,36 @@ ZTEST(modem_chat, test_runtime_match) zassert_equal(test_match.wildcards, false); } +ZTEST(modem_chat, test_runtime_script_chat) +{ + int ret; + struct modem_chat_script_chat test_script_chat; + struct modem_chat_match test_response_matches[2]; + + modem_chat_script_chat_init(&test_script_chat); + + ret = modem_chat_script_chat_set_request(&test_script_chat, "AT345"); + zassert_ok(ret, "Failed to set request"); + zassert_ok(strcmp(test_script_chat.request, "AT345"), "Failed to set script_chat"); + zassert_equal(test_script_chat.request_size, 5, "Failed to set size of script_chat"); + + ret = modem_chat_script_chat_set_response_matches(&test_script_chat, + test_response_matches, + ARRAY_SIZE(test_response_matches)); + zassert_ok(ret, "Failed to set response matches"); + zassert_equal(test_script_chat.response_matches, test_response_matches, + "Failed to set response_matches"); + zassert_equal(test_script_chat.response_matches_size, ARRAY_SIZE(test_response_matches), + "Failed to set response_matches"); + + ret = modem_chat_script_chat_set_response_matches(&test_script_chat, + test_response_matches, 0); + zassert_equal(ret, -EINVAL, "Should have failed to set response matches"); + + ret = modem_chat_script_chat_set_response_matches(&test_script_chat, NULL, 1); + zassert_equal(ret, -EINVAL, "Should have failed to set response matches"); +} + /*************************************************************************************************/ /* Test suite */ /*************************************************************************************************/ From 000784b91d837a98559185809439f20ec77aabbc Mon Sep 17 00:00:00 2001 From: Bjarki Arge Andreasen Date: Thu, 29 Feb 2024 11:06:18 +0100 Subject: [PATCH 1230/2849] modem: chat: Add runtime APIs for chat scripts Add runtime APIs for chat scripts. Signed-off-by: Bjarki Arge Andreasen --- include/zephyr/modem/chat.h | 55 ++++++++++++++++++++++++ subsys/modem/modem_chat.c | 48 +++++++++++++++++++++ tests/subsys/modem/modem_chat/src/main.c | 39 +++++++++++++++++ 3 files changed, 142 insertions(+) diff --git a/include/zephyr/modem/chat.h b/include/zephyr/modem/chat.h index be5cf4b8f11cb..98778fb884172 100644 --- a/include/zephyr/modem/chat.h +++ b/include/zephyr/modem/chat.h @@ -465,6 +465,61 @@ int modem_chat_script_chat_set_response_matches(struct modem_chat_script_chat *s void modem_chat_script_chat_set_timeout(struct modem_chat_script_chat *script_chat, uint16_t timeout_ms); +/** + * @brief Initialize modem chat script + * @param script Modem chat script instance + */ +void modem_chat_script_init(struct modem_chat_script *script); + +/** + * @brief Set modem chat script name + * @param script Modem chat script instance + * @param name Name to set + * @note The lifetime of name must match or exceed the lifetime of script + */ +void modem_chat_script_set_name(struct modem_chat_script *script, const char *name); + +/** + * @brief Set modem chat script chats + * @param script Modem chat script instance + * @param script_chats Chat script array to set + * @param script_chats_size Size of chat script array + * @note The lifetime of script_chats must match or exceed the lifetime of script + * + * @retval 0 if successful, negative errno code otherwise + */ +int modem_chat_script_set_script_chats(struct modem_chat_script *script, + const struct modem_chat_script_chat *script_chats, + uint16_t script_chats_size); + +/** + * @brief Set modem chat script abort matches + * @param script Modem chat script instance + * @param abort_matches Abort match array to set + * @param abort_matches_size Size of abort match array + * @note The lifetime of abort_matches must match or exceed the lifetime of script + * + * @retval 0 if successful, negative errno code otherwise + */ +int modem_chat_script_set_abort_matches(struct modem_chat_script *script, + const struct modem_chat_match *abort_matches, + uint16_t abort_matches_size); + +/** + * @brief Set modem chat script callback + * @param script Modem chat script instance + * @param callback Callback to set + */ +void modem_chat_script_set_callback(struct modem_chat_script *script, + modem_chat_script_callback callback); + +/** + * @brief Set modem chat script timeout + * @param script Modem chat script instance + * @param timeout_s Timeout in seconds + */ +void modem_chat_script_set_timeout(struct modem_chat_script *script, uint32_t timeout_s); + #ifdef __cplusplus } #endif diff --git a/subsys/modem/modem_chat.c b/subsys/modem/modem_chat.c index ffd0fadf4657d..f0c580f11ec5d 100644 --- a/subsys/modem/modem_chat.c +++ b/subsys/modem/modem_chat.c @@ -1029,3 +1029,51 @@ void modem_chat_script_chat_set_timeout(struct modem_chat_script_chat *script_ch { script_chat->timeout = timeout; } + +void modem_chat_script_init(struct modem_chat_script *script) +{ + memset(script, 0, sizeof(struct modem_chat_script)); + script->name = ""; +} + +void modem_chat_script_set_name(struct modem_chat_script *script, const char *name) +{ + script->name = name; +} + +int modem_chat_script_set_script_chats(struct modem_chat_script *script, + const struct modem_chat_script_chat *script_chats, + uint16_t script_chats_size) +{ + if (!modem_chat_validate_array(script_chats, script_chats_size)) { + return -EINVAL; + } + + script->script_chats = script_chats; + script->script_chats_size = script_chats_size; + return 0; +} + +int modem_chat_script_set_abort_matches(struct modem_chat_script *script, + const struct modem_chat_match *abort_matches, + uint16_t abort_matches_size) +{ + if (!modem_chat_validate_array(abort_matches, abort_matches_size)) { + return -EINVAL; + } + + script->abort_matches = abort_matches; + script->abort_matches_size = abort_matches_size; + return 0; +} + +void modem_chat_script_set_callback(struct modem_chat_script *script, + modem_chat_script_callback callback) +{ + script->callback = callback; +} + +void modem_chat_script_set_timeout(struct modem_chat_script *script, uint32_t timeout_s) +{ + script->timeout = timeout_s; +} diff --git a/tests/subsys/modem/modem_chat/src/main.c b/tests/subsys/modem/modem_chat/src/main.c index fd5e773b08e3b..f988342899330 100644 --- a/tests/subsys/modem/modem_chat/src/main.c +++ b/tests/subsys/modem/modem_chat/src/main.c @@ -734,6 +734,45 @@ ZTEST(modem_chat, test_runtime_script_chat) zassert_equal(ret, -EINVAL, "Should have failed to set response matches"); } +ZTEST(modem_chat, test_runtime_script) +{ + int ret; + struct modem_chat_script test_script; + struct modem_chat_script_chat test_script_chats[2]; + struct modem_chat_match test_abort_matches[2]; + + modem_chat_script_init(&test_script); + zassert_equal(strlen(test_script.name), 0, "Failed to set default name"); + + ret = modem_chat_script_set_script_chats(&test_script, test_script_chats, + ARRAY_SIZE(test_script_chats)); + zassert_ok(ret, "Failed to set script chats"); + zassert_equal(test_script.script_chats, test_script_chats, + "Failed to set script_chats"); + zassert_equal(test_script.script_chats_size, ARRAY_SIZE(test_script_chats), + "Failed to set script_chats_size"); + + ret = modem_chat_script_set_script_chats(&test_script, test_script_chats, 0); + zassert_equal(ret, -EINVAL, "Should have failed to set script chats"); + + ret = modem_chat_script_set_script_chats(&test_script, NULL, 1); + zassert_equal(ret, -EINVAL, "Should have failed to set script chats"); + + ret = modem_chat_script_set_abort_matches(&test_script, test_abort_matches, + ARRAY_SIZE(test_abort_matches)); + zassert_ok(ret, "Failed to set abort matches"); + zassert_equal(test_script.abort_matches, test_abort_matches, + "Failed to set script_chats"); + zassert_equal(test_script.abort_matches_size, ARRAY_SIZE(test_abort_matches), + "Failed to set script_chats_size"); + + ret = modem_chat_script_set_abort_matches(&test_script, test_abort_matches, 0); + zassert_equal(ret, -EINVAL, "Should have failed to set abort matches"); + + ret = modem_chat_script_set_abort_matches(&test_script, NULL, 1); + zassert_equal(ret, -EINVAL, "Should have failed to set abort matches"); +} + /*************************************************************************************************/ /* Test suite */ /*************************************************************************************************/ From 51bcc5d20df28b45a68275eaf5b5f6f6a42564d8 Mon Sep 17 00:00:00 2001 From: Bjarki Arge Andreasen Date: Thu, 29 Feb 2024 12:50:53 +0100 Subject: [PATCH 1231/2849] drivers: gnss: LCX6G use modem chat runtime API Update the Quectel LCX6G device driver to use the modem chat runtime API to modify the dynamic pair chat script. This change makes the driver safer and more readible by ensuring safe modification of the members of the modem chat structures. Signed-off-by: Bjarki Arge Andreasen --- drivers/gnss/gnss_quectel_lcx6g.c | 212 ++++++++++++++++++------------ 1 file changed, 129 insertions(+), 83 deletions(-) diff --git a/drivers/gnss/gnss_quectel_lcx6g.c b/drivers/gnss/gnss_quectel_lcx6g.c index d3ac854ae9663..077dc0d7985ce 100644 --- a/drivers/gnss/gnss_quectel_lcx6g.c +++ b/drivers/gnss/gnss_quectel_lcx6g.c @@ -59,13 +59,12 @@ struct quectel_lcx6g_data { uint8_t chat_delimiter[2]; uint8_t *chat_argv[32]; - /* Dynamic chat script */ - uint8_t dynamic_match_buf[32]; - uint8_t dynamic_separators_buf[2]; - uint8_t dynamic_request_buf[32]; - struct modem_chat_match dynamic_match; - struct modem_chat_script_chat dynamic_script_chat; - struct modem_chat_script dynamic_script; + /* Pair chat script */ + uint8_t pair_request_buf[32]; + uint8_t pair_match_buf[32]; + struct modem_chat_match pair_match; + struct modem_chat_script_chat pair_script_chat; + struct modem_chat_script pair_script; /* Allocation for responses from GNSS modem */ union { @@ -141,23 +140,29 @@ static int quectel_lcx6g_configure_pps(const struct device *dev) break; } - ret = gnss_nmea0183_snprintk(data->dynamic_request_buf, sizeof(data->dynamic_request_buf), + ret = gnss_nmea0183_snprintk(data->pair_request_buf, sizeof(data->pair_request_buf), "PAIR752,%u,%u", pps_mode, config->pps_pulse_width); if (ret < 0) { return ret; } - data->dynamic_script_chat.request_size = ret; + ret = modem_chat_script_chat_set_request(&data->pair_script_chat, data->pair_request_buf); + if (ret < 0) { + return ret; + } - ret = gnss_nmea0183_snprintk(data->dynamic_match_buf, sizeof(data->dynamic_match_buf), + ret = gnss_nmea0183_snprintk(data->pair_match_buf, sizeof(data->pair_match_buf), "PAIR001,752,0"); if (ret < 0) { return ret; } - data->dynamic_match.match_size = ret; + ret = modem_chat_match_set_match(&data->pair_match, data->pair_match_buf); + if (ret < 0) { + return ret; + } - return modem_chat_run_script(&data->chat, &data->dynamic_script); + return modem_chat_run_script(&data->chat, &data->pair_script); } static void quectel_lcx6g_lock(const struct device *dev) @@ -312,23 +317,29 @@ static int quectel_lcx6g_set_fix_rate(const struct device *dev, uint32_t fix_int quectel_lcx6g_lock(dev); - ret = gnss_nmea0183_snprintk(data->dynamic_request_buf, sizeof(data->dynamic_request_buf), + ret = gnss_nmea0183_snprintk(data->pair_request_buf, sizeof(data->pair_request_buf), "PAIR050,%u", fix_interval_ms); if (ret < 0) { goto unlock_return; } - data->dynamic_script_chat.request_size = ret; + ret = modem_chat_script_chat_set_request(&data->pair_script_chat, data->pair_request_buf); + if (ret < 0) { + goto unlock_return; + } - ret = gnss_nmea0183_snprintk(data->dynamic_match_buf, sizeof(data->dynamic_match_buf), + ret = gnss_nmea0183_snprintk(data->pair_match_buf, sizeof(data->pair_match_buf), "PAIR001,050,0"); if (ret < 0) { goto unlock_return; } - data->dynamic_match.match_size = ret; + ret = modem_chat_match_set_match(&data->pair_match, data->pair_match_buf); + if (ret < 0) { + goto unlock_return; + } - ret = modem_chat_run_script(&data->chat, &data->dynamic_script); + ret = modem_chat_run_script(&data->chat, &data->pair_script); if (ret < 0) { goto unlock_return; } @@ -362,20 +373,26 @@ static int quectel_lcx6g_get_fix_rate(const struct device *dev, uint32_t *fix_in quectel_lcx6g_lock(dev); - ret = gnss_nmea0183_snprintk(data->dynamic_request_buf, sizeof(data->dynamic_request_buf), + ret = gnss_nmea0183_snprintk(data->pair_request_buf, sizeof(data->pair_request_buf), "PAIR051"); if (ret < 0) { goto unlock_return; } - data->dynamic_script_chat.request_size = ret; + ret = modem_chat_script_chat_set_request(&data->pair_script_chat, data->pair_request_buf); + if (ret < 0) { + goto unlock_return; + } - strncpy(data->dynamic_match_buf, "$PAIR051,", sizeof(data->dynamic_match_buf)); - data->dynamic_match.match_size = sizeof("$PAIR051,") - 1; - data->dynamic_match.callback = quectel_lcx6g_get_fix_rate_callback; + strncpy(data->pair_match_buf, "$PAIR051,", sizeof(data->pair_match_buf)); + ret = modem_chat_match_set_match(&data->pair_match, data->pair_match_buf); + if (ret < 0) { + goto unlock_return; + } - ret = modem_chat_run_script(&data->chat, &data->dynamic_script); - data->dynamic_match.callback = NULL; + modem_chat_match_set_callback(&data->pair_match, quectel_lcx6g_get_fix_rate_callback); + ret = modem_chat_run_script(&data->chat, &data->pair_script); + modem_chat_match_set_callback(&data->pair_match, NULL); if (ret < 0) { goto unlock_return; } @@ -414,23 +431,29 @@ static int quectel_lcx6g_set_navigation_mode(const struct device *dev, quectel_lcx6g_lock(dev); - ret = gnss_nmea0183_snprintk(data->dynamic_request_buf, sizeof(data->dynamic_request_buf), + ret = gnss_nmea0183_snprintk(data->pair_request_buf, sizeof(data->pair_request_buf), "PAIR080,%u", navigation_mode); if (ret < 0) { goto unlock_return; } - data->dynamic_script_chat.request_size = ret; + ret = modem_chat_script_chat_set_request(&data->pair_script_chat, data->pair_request_buf); + if (ret < 0) { + goto unlock_return; + } - ret = gnss_nmea0183_snprintk(data->dynamic_match_buf, sizeof(data->dynamic_match_buf), + ret = gnss_nmea0183_snprintk(data->pair_match_buf, sizeof(data->pair_match_buf), "PAIR001,080,0"); if (ret < 0) { goto unlock_return; } - data->dynamic_match.match_size = ret; + ret = modem_chat_match_set_match(&data->pair_match, data->pair_match_buf); + if (ret < 0) { + goto unlock_return; + } - ret = modem_chat_run_script(&data->chat, &data->dynamic_script); + ret = modem_chat_run_script(&data->chat, &data->pair_script); if (ret < 0) { goto unlock_return; } @@ -440,8 +463,8 @@ static int quectel_lcx6g_set_navigation_mode(const struct device *dev, return ret; } -static void quectel_lcx6g_get_navigation_mode_callback(struct modem_chat *chat, char **argv, - uint16_t argc, void *user_data) +static void quectel_lcx6g_get_nav_mode_callback(struct modem_chat *chat, char **argv, + uint16_t argc, void *user_data) { struct quectel_lcx6g_data *data = user_data; int32_t tmp; @@ -481,20 +504,26 @@ static int quectel_lcx6g_get_navigation_mode(const struct device *dev, quectel_lcx6g_lock(dev); - ret = gnss_nmea0183_snprintk(data->dynamic_request_buf, sizeof(data->dynamic_request_buf), + ret = gnss_nmea0183_snprintk(data->pair_request_buf, sizeof(data->pair_request_buf), "PAIR081"); if (ret < 0) { goto unlock_return; } - data->dynamic_script_chat.request_size = ret; + ret = modem_chat_script_chat_set_request(&data->pair_script_chat, data->pair_request_buf); + if (ret < 0) { + goto unlock_return; + } - strncpy(data->dynamic_match_buf, "$PAIR081,", sizeof(data->dynamic_match_buf)); - data->dynamic_match.match_size = sizeof("$PAIR081,") - 1; - data->dynamic_match.callback = quectel_lcx6g_get_navigation_mode_callback; + strncpy(data->pair_match_buf, "$PAIR081,", sizeof(data->pair_match_buf)); + ret = modem_chat_match_set_match(&data->pair_match, data->pair_match_buf); + if (ret < 0) { + goto unlock_return; + } - ret = modem_chat_run_script(&data->chat, &data->dynamic_script); - data->dynamic_match.callback = NULL; + modem_chat_match_set_callback(&data->pair_match, quectel_lcx6g_get_nav_mode_callback); + ret = modem_chat_run_script(&data->chat, &data->pair_script); + modem_chat_match_set_callback(&data->pair_match, NULL); if (ret < 0) { goto unlock_return; } @@ -521,7 +550,7 @@ static int quectel_lcx6g_set_enabled_systems(const struct device *dev, gnss_syst quectel_lcx6g_lock(dev); - ret = gnss_nmea0183_snprintk(data->dynamic_request_buf, sizeof(data->dynamic_request_buf), + ret = gnss_nmea0183_snprintk(data->pair_request_buf, sizeof(data->pair_request_buf), "PAIR066,%u,%u,%u,%u,%u,0", (0 < (systems & GNSS_SYSTEM_GPS)), (0 < (systems & GNSS_SYSTEM_GLONASS)), @@ -532,38 +561,50 @@ static int quectel_lcx6g_set_enabled_systems(const struct device *dev, gnss_syst goto unlock_return; } - data->dynamic_script_chat.request_size = ret; + ret = modem_chat_script_chat_set_request(&data->pair_script_chat, data->pair_request_buf); + if (ret < 0) { + goto unlock_return; + } - ret = gnss_nmea0183_snprintk(data->dynamic_match_buf, sizeof(data->dynamic_match_buf), + ret = gnss_nmea0183_snprintk(data->pair_match_buf, sizeof(data->pair_match_buf), "PAIR001,066,0"); if (ret < 0) { goto unlock_return; } - data->dynamic_match.match_size = ret; + ret = modem_chat_match_set_match(&data->pair_match, data->pair_match_buf); + if (ret < 0) { + goto unlock_return; + } - ret = modem_chat_run_script(&data->chat, &data->dynamic_script); + ret = modem_chat_run_script(&data->chat, &data->pair_script); if (ret < 0) { goto unlock_return; } - ret = gnss_nmea0183_snprintk(data->dynamic_request_buf, sizeof(data->dynamic_request_buf), + ret = gnss_nmea0183_snprintk(data->pair_request_buf, sizeof(data->pair_request_buf), "PAIR410,%u", (0 < (systems & GNSS_SYSTEM_SBAS))); if (ret < 0) { goto unlock_return; } - data->dynamic_script_chat.request_size = ret; + ret = modem_chat_script_chat_set_request(&data->pair_script_chat, data->pair_request_buf); + if (ret < 0) { + goto unlock_return; + } - ret = gnss_nmea0183_snprintk(data->dynamic_match_buf, sizeof(data->dynamic_match_buf), + ret = gnss_nmea0183_snprintk(data->pair_match_buf, sizeof(data->pair_match_buf), "PAIR001,410,0"); if (ret < 0) { goto unlock_return; } - data->dynamic_match.match_size = ret; + ret = modem_chat_match_set_match(&data->pair_match, data->pair_match_buf); + if (ret < 0) { + goto unlock_return; + } - ret = modem_chat_run_script(&data->chat, &data->dynamic_script); + ret = modem_chat_run_script(&data->chat, &data->pair_script); if (ret < 0) { goto unlock_return; } @@ -614,38 +655,50 @@ static int quectel_lcx6g_get_enabled_systems(const struct device *dev, gnss_syst quectel_lcx6g_lock(dev); - ret = gnss_nmea0183_snprintk(data->dynamic_request_buf, sizeof(data->dynamic_request_buf), + ret = gnss_nmea0183_snprintk(data->pair_request_buf, sizeof(data->pair_request_buf), "PAIR067"); if (ret < 0) { goto unlock_return; } - data->dynamic_script_chat.request_size = ret; + ret = modem_chat_script_chat_set_request(&data->pair_script_chat, data->pair_request_buf); + if (ret < 0) { + goto unlock_return; + } - strncpy(data->dynamic_match_buf, "$PAIR067,", sizeof(data->dynamic_match_buf)); - data->dynamic_match.match_size = sizeof("$PAIR067,") - 1; - data->dynamic_match.callback = quectel_lcx6g_get_search_mode_callback; + strncpy(data->pair_match_buf, "$PAIR067,", sizeof(data->pair_match_buf)); + ret = modem_chat_match_set_match(&data->pair_match, data->pair_match_buf); + if (ret < 0) { + goto unlock_return; + } - ret = modem_chat_run_script(&data->chat, &data->dynamic_script); - data->dynamic_match.callback = NULL; + modem_chat_match_set_callback(&data->pair_match, quectel_lcx6g_get_search_mode_callback); + ret = modem_chat_run_script(&data->chat, &data->pair_script); + modem_chat_match_set_callback(&data->pair_match, NULL); if (ret < 0) { goto unlock_return; } - ret = gnss_nmea0183_snprintk(data->dynamic_request_buf, sizeof(data->dynamic_request_buf), + ret = gnss_nmea0183_snprintk(data->pair_request_buf, sizeof(data->pair_request_buf), "PAIR411"); if (ret < 0) { goto unlock_return; } - data->dynamic_script_chat.request_size = ret; + ret = modem_chat_script_chat_set_request(&data->pair_script_chat, data->pair_request_buf); + if (ret < 0) { + goto unlock_return; + } - strncpy(data->dynamic_match_buf, "$PAIR411,", sizeof(data->dynamic_match_buf)); - data->dynamic_match.match_size = sizeof("$PAIR411,") - 1; - data->dynamic_match.callback = quectel_lcx6g_get_sbas_status_callback; + strncpy(data->pair_match_buf, "$PAIR411,", sizeof(data->pair_match_buf)); + ret = modem_chat_match_set_match(&data->pair_match, data->pair_match_buf); + if (ret < 0) { + goto unlock_return; + } - ret = modem_chat_run_script(&data->chat, &data->dynamic_script); - data->dynamic_match.callback = NULL; + modem_chat_match_set_callback(&data->pair_match, quectel_lcx6g_get_sbas_status_callback); + ret = modem_chat_run_script(&data->chat, &data->pair_script); + modem_chat_match_set_callback(&data->pair_match, NULL); if (ret < 0) { goto unlock_return; } @@ -726,28 +779,22 @@ static int quectel_lcx6g_init_chat(const struct device *dev) return modem_chat_init(&data->chat, &chat_config); } -static void quectel_lcx6g_init_dynamic_script(const struct device *dev) +static void quectel_lcx6g_init_pair_script(const struct device *dev) { struct quectel_lcx6g_data *data = dev->data; - data->dynamic_match.match = data->dynamic_match_buf; - data->dynamic_match.separators = data->dynamic_separators_buf; - data->dynamic_match.separators_size = sizeof(data->dynamic_separators_buf); - data->dynamic_match.wildcards = false; - data->dynamic_match.partial = false; - - data->dynamic_script_chat.request = data->dynamic_request_buf; - data->dynamic_script_chat.response_matches = &data->dynamic_match; - data->dynamic_script_chat.response_matches_size = 1; - data->dynamic_script_chat.timeout = 0; - - data->dynamic_script.name = "pair"; - 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 = 10; + modem_chat_match_init(&data->pair_match); + modem_chat_match_set_separators(&data->pair_match, ",*"); + + modem_chat_script_chat_init(&data->pair_script_chat); + modem_chat_script_chat_set_response_matches(&data->pair_script_chat, + &data->pair_match, 1); + + modem_chat_script_init(&data->pair_script); + modem_chat_script_set_name(&data->pair_script, "pair"); + modem_chat_script_set_script_chats(&data->pair_script, &data->pair_script_chat, 1); + modem_chat_script_set_abort_matches(&data->pair_script, NULL, 0); + modem_chat_script_set_timeout(&data->pair_script, 10); } static int quectel_lcx6g_init(const struct device *dev) @@ -769,7 +816,7 @@ static int quectel_lcx6g_init(const struct device *dev) return ret; } - quectel_lcx6g_init_dynamic_script(dev); + quectel_lcx6g_init_pair_script(dev); quectel_lcx6g_pm_changed(dev); @@ -798,7 +845,6 @@ static int quectel_lcx6g_init(const struct device *dev) \ static struct quectel_lcx6g_data LCX6G_INST_NAME(inst, data) = { \ .chat_delimiter = {'\r', '\n'}, \ - .dynamic_separators_buf = {',', '*'}, \ }; \ \ PM_DEVICE_DT_INST_DEFINE(inst, quectel_lcx6g_pm_action); \ From 20b55425d32592a8fa25c2fdb797c0baba6b5cd4 Mon Sep 17 00:00:00 2001 From: Hess Nathan Date: Thu, 2 May 2024 14:02:20 +0200 Subject: [PATCH 1232/2849] coding guidelines: comply with MISRA Rule 13.4 avoid the direct use of assignment expression values for conditions Signed-off-by: Hess Nathan --- kernel/condvar.c | 4 ++-- kernel/msg_q.c | 3 ++- kernel/sched.c | 4 ++-- kernel/stack.c | 3 ++- 4 files changed, 8 insertions(+), 6 deletions(-) diff --git a/kernel/condvar.c b/kernel/condvar.c index 9d8ca7a5bc87f..2430523cdb905 100644 --- a/kernel/condvar.c +++ b/kernel/condvar.c @@ -84,8 +84,8 @@ int z_impl_k_condvar_broadcast(struct k_condvar *condvar) SYS_PORT_TRACING_OBJ_FUNC_ENTER(k_condvar, broadcast, condvar); /* wake up any threads that are waiting to write */ - while ((pending_thread = z_unpend_first_thread(&condvar->wait_q)) != - NULL) { + for (pending_thread = z_unpend_first_thread(&condvar->wait_q); pending_thread != NULL; + pending_thread = z_unpend_first_thread(&condvar->wait_q)) { woken++; arch_thread_return_value_set(pending_thread, 0); z_ready_thread(pending_thread); diff --git a/kernel/msg_q.c b/kernel/msg_q.c index b3cd959d578ac..5214902b1653b 100644 --- a/kernel/msg_q.c +++ b/kernel/msg_q.c @@ -383,7 +383,8 @@ void z_impl_k_msgq_purge(struct k_msgq *msgq) SYS_PORT_TRACING_OBJ_FUNC(k_msgq, purge, msgq); /* wake up any threads that are waiting to write */ - while ((pending_thread = z_unpend_first_thread(&msgq->wait_q)) != NULL) { + for (pending_thread = z_unpend_first_thread(&msgq->wait_q); pending_thread != NULL; + pending_thread = z_unpend_first_thread(&msgq->wait_q)) { arch_thread_return_value_set(pending_thread, -ENOMSG); z_ready_thread(pending_thread); } diff --git a/kernel/sched.c b/kernel/sched.c index bb9676b18320e..98de4f73963aa 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -958,7 +958,7 @@ int z_unpend_all(_wait_q_t *wait_q) int need_sched = 0; struct k_thread *thread; - while ((thread = z_waitq_head(wait_q)) != NULL) { + for (thread = z_waitq_head(wait_q); thread != NULL; thread = z_waitq_head(wait_q)) { z_unpend_thread(thread); z_ready_thread(thread); need_sched = 1; @@ -1269,7 +1269,7 @@ static inline void unpend_all(_wait_q_t *wait_q) { struct k_thread *thread; - while ((thread = z_waitq_head(wait_q)) != NULL) { + for (thread = z_waitq_head(wait_q); thread != NULL; thread = z_waitq_head(wait_q)) { unpend_thread_no_timeout(thread); (void)z_abort_thread_timeout(thread); arch_thread_return_value_set(thread, 0); diff --git a/kernel/stack.c b/kernel/stack.c index 5ddc4178f89df..5c2bae6f61ccd 100644 --- a/kernel/stack.c +++ b/kernel/stack.c @@ -29,7 +29,8 @@ void k_stack_init(struct k_stack *stack, stack_data_t *buffer, { z_waitq_init(&stack->wait_q); stack->lock = (struct k_spinlock) {}; - stack->next = stack->base = buffer; + stack->next = buffer; + stack->base = buffer; stack->top = stack->base + num_entries; SYS_PORT_TRACING_OBJ_INIT(k_stack, stack); From 1f563b7821aab8791cf11261659497552b03ec80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Chru=C5=9Bci=C5=84ski?= Date: Fri, 10 May 2024 14:45:12 +0200 Subject: [PATCH 1233/2849] modules: hal_nordic: Add NRFX_GPIOTE130_CHANNELS_USED mask MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On SoC like nrf54h20 GPIOTE channels are split between cores. They are reserved at compile time in devicetree. We need to ensure that dynamically allocated channels are used only from pool assigned to the given core. This is done using NRFX_GPIOTE130_CHANNELS_USED mask which contains data from the device tree. Signed-off-by: Krzysztof Chruściński --- modules/hal_nordic/nrfx/nrfx_glue.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/modules/hal_nordic/nrfx/nrfx_glue.h b/modules/hal_nordic/nrfx/nrfx_glue.h index 6b470c77733ce..0dd8b2bba9473 100644 --- a/modules/hal_nordic/nrfx/nrfx_glue.h +++ b/modules/hal_nordic/nrfx/nrfx_glue.h @@ -334,6 +334,9 @@ 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 GPIOTE130 channels reserved for use outside of the nrfx library. */ +#define NRFX_GPIOTE130_CHANNELS_USED ~NRFX_CONFIG_MASK_DT(DT_NODELABEL(gpiote130), owned_channels) + #if defined(CONFIG_BT_CTLR) /* * The enabled Bluetooth controller subsystem is responsible for providing From 4a61fa32f08bd52c14adda20cecf216ae58eb770 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Chru=C5=9Bci=C5=84ski?= Date: Fri, 10 May 2024 11:43:01 +0200 Subject: [PATCH 1234/2849] tests: drivers: gpio: gpio_basic_api: Add nrf54h20dk overlays MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add overlays for nrf54h20dk_nrf54h20 cpuapp and cpurad. Signed-off-by: Krzysztof Chruściński --- .../boards/nrf54h20dk_nrf54h20_common.dtsi | 19 +++++++++++++++++++ .../boards/nrf54h20dk_nrf54h20_cpuapp.overlay | 3 +++ .../boards/nrf54h20dk_nrf54h20_cpurad.overlay | 3 +++ 3 files changed, 25 insertions(+) create mode 100644 tests/drivers/gpio/gpio_basic_api/boards/nrf54h20dk_nrf54h20_common.dtsi create mode 100644 tests/drivers/gpio/gpio_basic_api/boards/nrf54h20dk_nrf54h20_cpuapp.overlay create mode 100644 tests/drivers/gpio/gpio_basic_api/boards/nrf54h20dk_nrf54h20_cpurad.overlay diff --git a/tests/drivers/gpio/gpio_basic_api/boards/nrf54h20dk_nrf54h20_common.dtsi b/tests/drivers/gpio/gpio_basic_api/boards/nrf54h20dk_nrf54h20_common.dtsi new file mode 100644 index 0000000000000..917e28211b81a --- /dev/null +++ b/tests/drivers/gpio/gpio_basic_api/boards/nrf54h20dk_nrf54h20_common.dtsi @@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +/ { + resources { + compatible = "test-gpio-basic-api"; + out-gpios = <&gpio0 6 0>; + in-gpios = <&gpio0 7 0>; + }; +}; + +&gpio0 { + status = "okay"; + sense-edge-mask = <0x60>; +}; + +&gpiote130 { + status = "okay"; + owned-channels = < 0 1 >; +}; diff --git a/tests/drivers/gpio/gpio_basic_api/boards/nrf54h20dk_nrf54h20_cpuapp.overlay b/tests/drivers/gpio/gpio_basic_api/boards/nrf54h20dk_nrf54h20_cpuapp.overlay new file mode 100644 index 0000000000000..f65b4dd3b0ba0 --- /dev/null +++ b/tests/drivers/gpio/gpio_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/gpio/gpio_basic_api/boards/nrf54h20dk_nrf54h20_cpurad.overlay b/tests/drivers/gpio/gpio_basic_api/boards/nrf54h20dk_nrf54h20_cpurad.overlay new file mode 100644 index 0000000000000..f65b4dd3b0ba0 --- /dev/null +++ b/tests/drivers/gpio/gpio_basic_api/boards/nrf54h20dk_nrf54h20_cpurad.overlay @@ -0,0 +1,3 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +#include "nrf54h20dk_nrf54h20_common.dtsi" From 0b220dd6a6d1a4320e07071d1bdc69adcbe6f65b Mon Sep 17 00:00:00 2001 From: alperen sener Date: Mon, 27 May 2024 12:06:49 +0200 Subject: [PATCH 1235/2849] bluetooth: mesh: increase the friend adv latency range Increasing the adv latency range to the minimum valid ReceiveDelay value, 10ms. 4ms might be small for some target systems. Signed-off-by: alperen sener --- subsys/bluetooth/mesh/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subsys/bluetooth/mesh/Kconfig b/subsys/bluetooth/mesh/Kconfig index 796982280a882..2f23f26725bb7 100644 --- a/subsys/bluetooth/mesh/Kconfig +++ b/subsys/bluetooth/mesh/Kconfig @@ -1648,7 +1648,7 @@ config BT_MESH_FRIEND_SEG_RX config BT_MESH_FRIEND_ADV_LATENCY int "Latency for enabling advertising" - range 0 4 + range 0 10 default 0 help Latency in milliseconds between request for and start of Friend From d4209ab6c411225a909b286a351ead2ce8ae30d3 Mon Sep 17 00:00:00 2001 From: Ioannis Karachalios Date: Mon, 20 May 2024 14:35:27 +0300 Subject: [PATCH 1236/2849] drivers: dma: smartbond: Add support for PM This commit should add all the functionality needed for the DMA driver to work when PM is enabled. Signed-off-by: Ioannis Karachalios --- drivers/dma/dma_smartbond.c | 100 ++++++++++++++++++++++++++++++++++-- 1 file changed, 95 insertions(+), 5 deletions(-) diff --git a/drivers/dma/dma_smartbond.c b/drivers/dma/dma_smartbond.c index 855e56b9aff5f..d3ded5ebc37bb 100644 --- a/drivers/dma/dma_smartbond.c +++ b/drivers/dma/dma_smartbond.c @@ -9,10 +9,14 @@ #include #include #include +#include #include #include #include #include +#include +#include +#include #include LOG_MODULE_REGISTER(dma_smartbond, CONFIG_DMA_LOG_LEVEL); @@ -154,6 +158,10 @@ struct dma_smartbond_data { ATOMIC_DEFINE(channels_atomic, DMA_CHANNELS_COUNT); +#if defined(CONFIG_PM_DEVICE) || defined(CONFIG_PM_DEVICE_RUNTIME) + ATOMIC_DEFINE(pm_policy_state_flag, 1); +#endif + /* User callbacks and data to be stored per channel */ struct dma_channel_data channel_data[DMA_CHANNELS_COUNT]; }; @@ -175,7 +183,31 @@ static bool dma_smartbond_is_dma_active(void) return false; } -static void dma_smartbond_set_channel_status(uint32_t channel, bool status) +static inline void dma_smartbond_pm_policy_state_lock_get(const struct device *dev) +{ +#if defined(CONFIG_PM_DEVICE) || defined(CONFIG_PM_DEVICE_RUNTIME) + struct dma_smartbond_data *data = dev->data; + + if (atomic_test_and_set_bit(data->pm_policy_state_flag, 0) == 0) { + pm_policy_state_lock_get(PM_STATE_STANDBY, PM_ALL_SUBSTATES); + } +#endif +} + +static inline void dma_smartbond_pm_policy_state_lock_put(const struct device *dev) +{ +#if defined(CONFIG_PM_DEVICE) || defined(CONFIG_PM_DEVICE_RUNTIME) + struct dma_smartbond_data *data = dev->data; + + /* Make PM lock put has a matched PM lock get invocation */ + if (atomic_test_and_clear_bit(data->pm_policy_state_flag, 0) == 1) { + pm_policy_state_lock_put(PM_STATE_STANDBY, PM_ALL_SUBSTATES); + } +#endif +} + +static void dma_smartbond_set_channel_status(const struct device *dev, + uint32_t channel, bool status) { unsigned int key; struct channel_regs *regs = DMA_CHN2REG(channel); @@ -191,6 +223,8 @@ static void dma_smartbond_set_channel_status(uint32_t channel, bool status) /* Check if this is the first attempt to enable DMA interrupts. */ if (!irq_is_enabled(SMARTBOND_IRQN)) { irq_enable(SMARTBOND_IRQN); + /* Prevent sleep as long as DMA operations are ongoing */ + dma_smartbond_pm_policy_state_lock_get(dev); } DMA_CTRL_REG_SET_FIELD(DMA_ON, regs->DMA_CTRL_REG, 0x1); @@ -212,6 +246,8 @@ static void dma_smartbond_set_channel_status(uint32_t channel, bool status) /* DMA interrupts should be disabled only if all channels are disabled. */ if (!dma_smartbond_is_dma_active()) { irq_disable(SMARTBOND_IRQN); + /* Allow entering sleep once all DMA channels are inactive */ + dma_smartbond_pm_policy_state_lock_put(dev); } } @@ -707,7 +743,7 @@ static int dma_smartbond_start(const struct device *dev, uint32_t channel) return 0; } - dma_smartbond_set_channel_status(channel, true); + dma_smartbond_set_channel_status(dev, channel, true); return 0; } @@ -727,7 +763,7 @@ static int dma_smartbond_stop(const struct device *dev, uint32_t channel) * the corresponding register mask and disable NVIC if there is no other * channel in use. */ - dma_smartbond_set_channel_status(channel, false); + dma_smartbond_set_channel_status(dev, channel, false); return 0; } @@ -928,6 +964,57 @@ static void smartbond_dma_isr(const void *arg) } } +#if defined(CONFIG_PM_DEVICE) || defined(CONFIG_PM_DEVICE_RUNTIME) +static bool dma_smartbond_is_sleep_allowed(const struct device *dev) +{ + struct dma_smartbond_data *data = dev->data; + + for (int i = 0; i < data->dma_ctx.dma_channels; i++) { + if (atomic_test_bit(data->dma_ctx.atomic, i)) { + /* Abort sleeping if at least one dma channel is acquired */ + return false; + } + } + + return true; +} + +static int dma_smartbond_pm_action(const struct device *dev, + enum pm_device_action action) +{ + int ret = 0; + + switch (action) { + case PM_DEVICE_ACTION_SUSPEND: + /* + * When we reach this point there should be no ongoing DMA transfers. + * However, a DMA channel can still be acquired and so the configured + * channel(s) should be retained. To avoid reconfiguring DMA or + * read/write DMA channels' registers we assume that sleep is not allowed + * as long as all DMA channels are released. + */ + if (!dma_smartbond_is_sleep_allowed(dev)) { + ret = -EBUSY; + } + /* + * No need to perform any actions here as the DMA engine + * should already be turned off. + */ + break; + case PM_DEVICE_ACTION_RESUME: + /* + * No need to perform any actions here as the DMA engine + * will be configured by application explicitly. + */ + break; + default: + return -ENOTSUP; + } + + return ret; +} +#endif + static int dma_smartbond_init(const struct device *dev) { #ifdef CONFIG_DMA_64BIT @@ -945,7 +1032,7 @@ static int dma_smartbond_init(const struct device *dev) /* Make sure that all channels are disabled. */ for (idx = 0; idx < DMA_CHANNELS_COUNT; idx++) { - dma_smartbond_set_channel_status(idx, false); + dma_smartbond_set_channel_status(dev, idx, false); data->channel_data[idx].is_dma_configured = false; } @@ -958,9 +1045,12 @@ static int dma_smartbond_init(const struct device *dev) #define SMARTBOND_DMA_INIT(inst) \ BUILD_ASSERT((inst) == 0, "multiple instances are not supported"); \ \ + PM_DEVICE_DT_INST_DEFINE(inst, dma_smartbond_pm_action); \ + \ static struct dma_smartbond_data dma_smartbond_data_ ## inst; \ \ - DEVICE_DT_INST_DEFINE(0, dma_smartbond_init, NULL, \ + DEVICE_DT_INST_DEFINE(0, dma_smartbond_init, \ + PM_DEVICE_DT_INST_GET(inst), \ &dma_smartbond_data_ ## inst, NULL, \ POST_KERNEL, \ CONFIG_DMA_INIT_PRIORITY, \ From 69dc8752431ccb1a335194d221068ff629309fc1 Mon Sep 17 00:00:00 2001 From: Franck Thebault Date: Thu, 4 Apr 2024 12:15:15 +0200 Subject: [PATCH 1237/2849] dts: arm: st: h5: add I2S nodes Addition of I2S nodes Signed-off-by: Franck Thebault Signed-off-by: IBEN EL HADJ MESSAOUD Marwa --- dts/arm/st/h5/stm32h5.dtsi | 48 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/dts/arm/st/h5/stm32h5.dtsi b/dts/arm/st/h5/stm32h5.dtsi index 64a2ac37fee40..9b2e14209af10 100644 --- a/dts/arm/st/h5/stm32h5.dtsi +++ b/dts/arm/st/h5/stm32h5.dtsi @@ -530,6 +530,54 @@ status = "disabled"; }; + i2s1: i2s@40013000 { + compatible = "st,stm32h7-i2s", "st,stm32-i2s"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x40013000 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_APB2 0x00001000>, + <&rcc STM32_SRC_PLL1_Q SPI1_SEL(0)>; + dmas = <&gpdma1 0 7 (STM32_DMA_PERIPH_TX |STM32_DMA_16BITS | \ + STM32_DMA_PRIORITY_HIGH) + &gpdma1 1 6 (STM32_DMA_PERIPH_RX | STM32_DMA_16BITS | \ + STM32_DMA_PRIORITY_HIGH)>; + dma-names = "tx", "rx"; + interrupts = <55 3>; + status = "disabled"; + }; + + i2s2: i2s@40003800 { + compatible = "st,stm32h7-i2s", "st,stm32-i2s"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x40003800 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_APB1 0x00004000>, + <&rcc STM32_SRC_PLL1_Q SPI2_SEL(0)>; + dmas = <&gpdma1 2 9 (STM32_DMA_PERIPH_TX | STM32_DMA_16BITS | \ + STM32_DMA_PRIORITY_HIGH) + &gpdma1 3 8 (STM32_DMA_PERIPH_RX | STM32_DMA_16BITS | \ + STM32_DMA_PRIORITY_HIGH)>; + dma-names = "tx", "rx"; + interrupts = <56 3>; + status = "disabled"; + }; + + i2s3: i2s@40003c00 { + compatible = "st,stm32h7-i2s", "st,stm32-i2s"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x40003c00 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_APB1 0x00008000>, + <&rcc STM32_SRC_PLL1_Q SPI3_SEL(0)>; + dmas = <&gpdma1 4 11 (STM32_DMA_PERIPH_TX | STM32_DMA_16BITS | \ + STM32_DMA_PRIORITY_HIGH) + &gpdma1 5 10 (STM32_DMA_PERIPH_RX | STM32_DMA_16BITS | \ + STM32_DMA_PRIORITY_HIGH)>; + dma-names = "tx", "rx"; + interrupts = <57 3>; + status = "disabled"; + }; + usb: usb@40016000 { compatible = "st,stm32-usb"; reg = <0x40016000 0x400>; From c12cfb247de26f892b2de9e6876c14d3c0840067 Mon Sep 17 00:00:00 2001 From: Franck Thebault Date: Thu, 4 Apr 2024 12:31:21 +0200 Subject: [PATCH 1238/2849] tests: drivers: i2s: speed: add stm32h5 support Test on STM32H573i disco board , only the Tx transfer is ok. Signed-off-by: Franck Thebault Signed-off-by: IBEN EL HADJ MESSAOUD Marwa --- .../i2s/i2s_speed/boards/stm32h573i_dk.conf | 6 ++++++ .../i2s_speed/boards/stm32h573i_dk.overlay | 20 +++++++++++++++++++ 2 files changed, 26 insertions(+) create mode 100644 tests/drivers/i2s/i2s_speed/boards/stm32h573i_dk.conf create mode 100644 tests/drivers/i2s/i2s_speed/boards/stm32h573i_dk.overlay diff --git a/tests/drivers/i2s/i2s_speed/boards/stm32h573i_dk.conf b/tests/drivers/i2s/i2s_speed/boards/stm32h573i_dk.conf new file mode 100644 index 0000000000000..e55cda8d8e7d4 --- /dev/null +++ b/tests/drivers/i2s/i2s_speed/boards/stm32h573i_dk.conf @@ -0,0 +1,6 @@ +# +# Copyright (c) 2024 STMicroelectronics +# +# SPDX-License-Identifier: Apache-2.0 +# +CONFIG_I2S_TEST_SEPARATE_DEVICES=y diff --git a/tests/drivers/i2s/i2s_speed/boards/stm32h573i_dk.overlay b/tests/drivers/i2s/i2s_speed/boards/stm32h573i_dk.overlay new file mode 100644 index 0000000000000..6357edea91b90 --- /dev/null +++ b/tests/drivers/i2s/i2s_speed/boards/stm32h573i_dk.overlay @@ -0,0 +1,20 @@ +/* i2s-node0 is the receiver */ +/* i2s-node1 is the transmitter */ +/ { + aliases { + i2s-node0 = &i2s1; + i2s-node1 = &i2s2; + }; +}; + +&i2s1 { + pinctrl-0 = <&i2s1_ws_pa4 &i2s1_ck_pa5 &spi1_miso_pa6 &spi1_mosi_pb5>; + pinctrl-names = "default"; + status = "okay"; +}; + +&i2s2 { + pinctrl-0 = <&i2s2_ws_pa3 &i2s2_ck_pi1 &spi2_miso_pi2 &spi2_mosi_pb15>; + pinctrl-names = "default"; + status = "okay"; +}; From 343f2842bdfe133e4d78835067c0caf93c1782b1 Mon Sep 17 00:00:00 2001 From: IBEN EL HADJ MESSAOUD Marwa Date: Tue, 21 May 2024 14:41:35 +0200 Subject: [PATCH 1239/2849] include: zephyr: dt-bindings: dma: Add flag STM32_DMA_16BITS Add flag STM32_DMA_16BITS as a combination of STM32_DMA_PERIPH_16BITS and STM32_DMA_MEM_16BITS Signed-off-by: IBEN EL HADJ MESSAOUD Marwa --- include/zephyr/dt-bindings/dma/stm32_dma.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/zephyr/dt-bindings/dma/stm32_dma.h b/include/zephyr/dt-bindings/dma/stm32_dma.h index 3021231c7bb60..d61f6dfa4786d 100644 --- a/include/zephyr/dt-bindings/dma/stm32_dma.h +++ b/include/zephyr/dt-bindings/dma/stm32_dma.h @@ -64,6 +64,8 @@ #define STM32_DMA_PERIPH_TX (STM32_DMA_MEMORY_TO_PERIPH | STM32_DMA_MEM_INC) #define STM32_DMA_PERIPH_RX (STM32_DMA_PERIPH_TO_MEMORY | STM32_DMA_MEM_INC) +#define STM32_DMA_16BITS (STM32_DMA_PERIPH_16BITS | STM32_DMA_MEM_16BITS) + /** @} */ #endif /* ZEPHYR_INCLUDE_DT_BINDINGS_STM32_DMA_H_ */ From f000e1a58a16e5d267f0bdc8b2cb203f012c28a7 Mon Sep 17 00:00:00 2001 From: IBEN EL HADJ MESSAOUD Marwa Date: Tue, 21 May 2024 16:33:16 +0200 Subject: [PATCH 1240/2849] drivers: i2s : enable rx path for H7 and H5 In i2s_stm32_isr, remove the errors from SR register i2s_stm32_configure, enable the rx path for H7 I2S compatible IP Signed-off-by: Franck Thebault Signed-off-by: IBEN EL HADJ MESSAOUD Marwa --- drivers/i2s/i2s_ll_stm32.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/drivers/i2s/i2s_ll_stm32.c b/drivers/i2s/i2s_ll_stm32.c index b289ddabe750d..5b59648eae873 100644 --- a/drivers/i2s/i2s_ll_stm32.c +++ b/drivers/i2s/i2s_ll_stm32.c @@ -174,9 +174,6 @@ static int i2s_stm32_configure(const struct device *dev, enum i2s_dir dir, int ret; if (dir == I2S_DIR_RX) { -#if DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_i2s) - return -ENOSYS; -#endif stream = &dev_data->rx; } else if (dir == I2S_DIR_TX) { stream = &dev_data->tx; @@ -652,11 +649,6 @@ static uint32_t i2s_stm32_irq_udr_count; static void i2s_stm32_isr(const struct device *dev) { const struct i2s_stm32_cfg *cfg = dev->config; - struct i2s_stm32_data *const dev_data = dev->data; - struct stream *stream = &dev_data->rx; - - LOG_ERR("%s: err=%d", __func__, (int)LL_I2S_ReadReg(cfg->i2s, SR)); - stream->state = I2S_STATE_ERROR; /* OVR error must be explicitly cleared */ if (LL_I2S_IsActiveFlag_OVR(cfg->i2s)) { From 6cef92a908b9e7eb87420ea29651b44137ebb742 Mon Sep 17 00:00:00 2001 From: IBEN EL HADJ MESSAOUD Marwa Date: Tue, 21 May 2024 17:05:30 +0200 Subject: [PATCH 1241/2849] drivers: dma: u5: fix dma reload In dma_stm32_reload, the size is the number of bytes and not number of elements. Signed-off-by: Franck Thebault Signed-off-by: IBEN EL HADJ MESSAOUD Marwa --- drivers/dma/dma_stm32u5.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/drivers/dma/dma_stm32u5.c b/drivers/dma/dma_stm32u5.c index 88ab979df625e..91871292fafce 100644 --- a/drivers/dma/dma_stm32u5.c +++ b/drivers/dma/dma_stm32u5.c @@ -543,13 +543,7 @@ static int dma_stm32_reload(const struct device *dev, uint32_t id, dma_stm32_id_to_stream(id), src, dst); - if (stream->source_periph) { - LL_DMA_SetBlkDataLength(dma, dma_stm32_id_to_stream(id), - size / stream->src_size); - } else { - LL_DMA_SetBlkDataLength(dma, dma_stm32_id_to_stream(id), - size / stream->dst_size); - } + LL_DMA_SetBlkDataLength(dma, dma_stm32_id_to_stream(id), size); /* When reloading the dma, the stream is busy again before enabling */ stream->busy = true; From f3004dc6711838292bdb66a1d3c924873ea6125a Mon Sep 17 00:00:00 2001 From: IBEN EL HADJ MESSAOUD Marwa Date: Thu, 23 May 2024 17:25:32 +0200 Subject: [PATCH 1242/2849] drivers: i2s: Add DMA busy function Add the function ll_func_i2s_dma_busy to be able to check the transmission of all the DMA TX packet. Signed-off-by: IBEN EL HADJ MESSAOUD Marwa --- drivers/i2s/i2s_ll_stm32.h | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/drivers/i2s/i2s_ll_stm32.h b/drivers/i2s/i2s_ll_stm32.h index 2351b8e2cea56..1d3fdae8b675f 100644 --- a/drivers/i2s/i2s_ll_stm32.h +++ b/drivers/i2s/i2s_ll_stm32.h @@ -58,4 +58,16 @@ struct i2s_stm32_data { struct stream tx; }; +/* checks that DMA Tx packet is fully transmitted over the I2S */ +static inline uint32_t ll_func_i2s_dma_busy(SPI_TypeDef *i2s) +{ +#if DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_i2s) + return LL_SPI_IsActiveFlag_TXC(i2s) == 0; +#else + /* the I2S Tx empty and busy flags are needed */ + return (LL_SPI_IsActiveFlag_TXE(i2s) && + !LL_SPI_IsActiveFlag_BSY(i2s)); +#endif +} + #endif /* _STM32_I2S_H_ */ From c27ed31eb365228e63daecc491d7bdc79281e3ba Mon Sep 17 00:00:00 2001 From: Franck Thebault Date: Tue, 23 Apr 2024 14:33:09 +0200 Subject: [PATCH 1243/2849] drivers: i2s : correct TRIGGER_DRAIN and TRIGGER_STOP commands Correction of the handling of Tx audio samples via DMA Signed-off-by: Franck Thebault Signed-off-by: IBEN EL HADJ MESSAOUD Marwa --- drivers/i2s/i2s_ll_stm32.c | 87 ++++++++++++++++++++++++++++++++++---- drivers/i2s/i2s_ll_stm32.h | 1 + 2 files changed, 79 insertions(+), 9 deletions(-) diff --git a/drivers/i2s/i2s_ll_stm32.c b/drivers/i2s/i2s_ll_stm32.c index 5b59648eae873..9b60bfbed6032 100644 --- a/drivers/i2s/i2s_ll_stm32.c +++ b/drivers/i2s/i2s_ll_stm32.c @@ -30,6 +30,23 @@ static unsigned int div_round_closest(uint32_t dividend, uint32_t divisor) return (dividend + (divisor / 2U)) / divisor; } +static bool queue_is_empty(struct ring_buf *rb) +{ + unsigned int key; + + key = irq_lock(); + + if (rb->tail != rb->head) { + /* Ring buffer is not empty */ + irq_unlock(key); + return false; + } + + irq_unlock(key); + + return true; +} + /* * Get data from the queue */ @@ -39,8 +56,7 @@ static int queue_get(struct ring_buf *rb, void **mem_block, size_t *size) key = irq_lock(); - if (rb->tail == rb->head) { - /* Ring buffer is empty */ + if (queue_is_empty(rb) == true) { irq_unlock(key); return -ENOMEM; } @@ -290,6 +306,7 @@ static int i2s_stm32_trigger(const struct device *dev, enum i2s_dir dir, enum i2s_trigger_cmd cmd) { struct i2s_stm32_data *const dev_data = dev->data; + const struct i2s_stm32_cfg *const cfg = dev->config; struct stream *stream; unsigned int key; int ret; @@ -332,11 +349,20 @@ static int i2s_stm32_trigger(const struct device *dev, enum i2s_dir dir, LOG_ERR("STOP trigger: invalid state"); return -EIO; } +do_trigger_stop: + if (ll_func_i2s_dma_busy(cfg->i2s)) { + stream->state = I2S_STATE_STOPPING; + /* + * Indicate that the transition to I2S_STATE_STOPPING + * is triggered by STOP command + */ + stream->tx_stop_for_drain = false; + } else { + stream->stream_disable(stream, dev); + stream->state = I2S_STATE_READY; + stream->last_block = true; + } irq_unlock(key); - stream->stream_disable(stream, dev); - stream->queue_drop(stream); - stream->state = I2S_STATE_READY; - stream->last_block = true; break; case I2S_TRIGGER_DRAIN: @@ -346,9 +372,26 @@ static int i2s_stm32_trigger(const struct device *dev, enum i2s_dir dir, LOG_ERR("DRAIN trigger: invalid state"); return -EIO; } - stream->stream_disable(stream, dev); - stream->queue_drop(stream); - stream->state = I2S_STATE_READY; + + if (dir == I2S_DIR_TX) { + if ((queue_is_empty(&stream->mem_block_queue) == false) || + (ll_func_i2s_dma_busy(cfg->i2s))) { + stream->state = I2S_STATE_STOPPING; + /* + * Indicate that the transition to I2S_STATE_STOPPING + * is triggered by DRAIN command + */ + stream->tx_stop_for_drain = true; + } else { + stream->stream_disable(stream, dev); + stream->state = I2S_STATE_READY; + } + } else if (dir == I2S_DIR_RX) { + goto do_trigger_stop; + } else { + LOG_ERR("Unavailable direction"); + return -EINVAL; + } irq_unlock(key); break; @@ -600,6 +643,28 @@ static void dma_tx_callback(const struct device *dma_dev, void *arg, goto tx_disable; } + /* Check if we finished transferring one block and stopping is requested */ + if ((stream->state == I2S_STATE_STOPPING) && (status == DMA_STATUS_COMPLETE)) { + /* + * Check if all tx samples have been completely handled + * as stated in zephyr i2s specification, in case of DRAIN command + * send all data in the transmit queue and stop the transmission. + */ + if (queue_is_empty(&stream->mem_block_queue) == true) { + stream->queue_drop(stream); + stream->state = I2S_STATE_READY; + goto tx_disable; + } else if (stream->tx_stop_for_drain == false) { + /* + * In case of STOP command, just stop the transmission + * at the current. The transmission can be resumed. + */ + stream->state = I2S_STATE_READY; + goto tx_disable; + } + /* else: DRAIN trigger -> continue TX normally until queue is empty */ + } + /* Stop transmission if we were requested */ if (stream->last_block) { stream->state = I2S_STATE_READY; @@ -669,8 +734,12 @@ static int i2s_stm32_initialize(const struct device *dev) { const struct i2s_stm32_cfg *cfg = dev->config; struct i2s_stm32_data *const dev_data = dev->data; + struct stream *stream = &dev_data->tx; int ret, i; + /* Initialize the variable used to handle the TX */ + stream->tx_stop_for_drain = false; + /* Enable I2S clock propagation */ ret = i2s_stm32_enable_clock(dev); if (ret < 0) { diff --git a/drivers/i2s/i2s_ll_stm32.h b/drivers/i2s/i2s_ll_stm32.h index 1d3fdae8b675f..1f9d0eb0113dc 100644 --- a/drivers/i2s/i2s_ll_stm32.h +++ b/drivers/i2s/i2s_ll_stm32.h @@ -41,6 +41,7 @@ struct stream { bool src_addr_increment; bool dst_addr_increment; uint8_t fifo_threshold; + bool tx_stop_for_drain; struct i2s_config cfg; struct ring_buf mem_block_queue; From fdd6627df97a9d19a230833f329060a987cf3dd2 Mon Sep 17 00:00:00 2001 From: IBEN EL HADJ MESSAOUD Marwa Date: Mon, 27 May 2024 15:59:12 +0200 Subject: [PATCH 1244/2849] drivers: i2s: i2s_ll_stm32: tx_stream_disable: Add busy wait Add a k_busy_wait to the function tx_stream_disable to be able to complete the drain of the TX queue before disabling. Signed-off-by: IBEN EL HADJ MESSAOUD Marwa --- drivers/i2s/i2s_ll_stm32.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/i2s/i2s_ll_stm32.c b/drivers/i2s/i2s_ll_stm32.c index 9b60bfbed6032..696394e7a51be 100644 --- a/drivers/i2s/i2s_ll_stm32.c +++ b/drivers/i2s/i2s_ll_stm32.c @@ -932,6 +932,8 @@ static void tx_stream_disable(struct stream *stream, const struct device *dev) stream->mem_block = NULL; } + /* Wait for TX queue to drain before disabling */ + k_busy_wait(100); LL_I2S_Disable(cfg->i2s); active_dma_tx_channel[stream->dma_channel] = NULL; From ed1c78ec150bd32349ce26069d76b0ee5668ab9e Mon Sep 17 00:00:00 2001 From: Jordan Yates Date: Tue, 14 May 2024 20:31:10 +1000 Subject: [PATCH 1245/2849] boards: thingy53: define ADC channel for battery Define the ADC channel for battery monitoring so that `voltage-divider` driver works. Signed-off-by: Jordan Yates --- .../nordic/thingy53/thingy53_nrf5340_common.dtsi | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/boards/nordic/thingy53/thingy53_nrf5340_common.dtsi b/boards/nordic/thingy53/thingy53_nrf5340_common.dtsi index 694a6960584e4..017fa9e8a2674 100644 --- a/boards/nordic/thingy53/thingy53_nrf5340_common.dtsi +++ b/boards/nordic/thingy53/thingy53_nrf5340_common.dtsi @@ -88,7 +88,7 @@ regulator-boot-on; }; - vbatt { + vbatt: vbatt { compatible = "voltage-divider"; io-channels = <&adc 2>; output-ohms = <180000>; @@ -155,7 +155,19 @@ }; &adc { + #address-cells = <1>; + #size-cells = <0>; status = "okay"; + + channel@2 { + reg = <2>; + zephyr,gain = "ADC_GAIN_1"; + zephyr,reference = "ADC_REF_INTERNAL"; + zephyr,vref-mv = <600>; + zephyr,acquisition-time = ; + zephyr,resolution = <12>; + zephyr,input-positive = ; + }; }; &gpiote { From 0b654c1502478829f0ceab7c5fdb5b68a2c6c9d4 Mon Sep 17 00:00:00 2001 From: Emil Gydesen Date: Mon, 13 May 2024 10:46:49 +0200 Subject: [PATCH 1246/2849] Bluetooth: BAP: Fix conn checks for bcast assistant notifications The notify handle in the BAP broadcast assistant did not handle conn == NULL properly, and neither did delayed_bap_read_handler. Add better NULL checks, which also fixes a coverity issue. Signed-off-by: Emil Gydesen --- .../bluetooth/audio/bap_broadcast_assistant.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/subsys/bluetooth/audio/bap_broadcast_assistant.c b/subsys/bluetooth/audio/bap_broadcast_assistant.c index 6013afbf81776..90402d2db96ec 100644 --- a/subsys/bluetooth/audio/bap_broadcast_assistant.c +++ b/subsys/bluetooth/audio/bap_broadcast_assistant.c @@ -343,6 +343,10 @@ static void long_bap_read(struct bt_conn *conn, uint16_t handle) LOG_DBG("conn %p busy %u", conn, broadcast_assistant.busy); + if (conn == NULL) { + return; /* noop */ + } + if (broadcast_assistant.busy) { /* If the client is busy reading or writing something else, reschedule the * long read. @@ -402,6 +406,11 @@ static uint8_t notify_handler(struct bt_conn *conn, return BT_GATT_ITER_STOP; } + if (conn == NULL) { + /* Indicates that the CCC has been removed - no-op */ + return BT_GATT_ITER_CONTINUE; + } + LOG_HEXDUMP_DBG(data, length, "Receive state notification:"); index = lookup_index_by_handle(handle); @@ -413,17 +422,11 @@ static uint8_t notify_handler(struct bt_conn *conn, if (length != 0) { const uint8_t att_ntf_header_size = 3; /* opcode (1) + handle (2) */ - uint16_t max_ntf_size; + const uint16_t max_ntf_size = bt_gatt_get_mtu(conn) - att_ntf_header_size; /* Cancel any pending long reads containing now obsolete information */ (void)k_work_cancel_delayable(&broadcast_assistant.bap_read_work); - if (conn != NULL) { - max_ntf_size = bt_gatt_get_mtu(conn) - att_ntf_header_size; - } else { - max_ntf_size = MIN(BT_L2CAP_RX_MTU, BT_L2CAP_TX_MTU) - att_ntf_header_size; - } - if (length == max_ntf_size) { /* TODO: if we are busy we should not overwrite the long_read_handle, * we'll have to keep track of the handle and parameters separately From 7bc9a98a70387e34a9664e0eedff89daac4c1f93 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Szprejda?= Date: Mon, 4 Mar 2024 17:47:49 +0100 Subject: [PATCH 1247/2849] Twister: Rework integration with renode-test MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Initial integration with renode-test was introduced in commit bdf02ff, which added support for calling the `renode-test` command from both west and twister. This commit removes the custom run_renode_test target used for running Robot tests with the `west build` command and makes twister call `renode-test` directly instead. Signed-off-by: Michał Szprejda --- boards/microchip/m2gl025_miv/m2gl025_miv.yaml | 3 ++ .../riscv32_virtual/riscv32_virtual.yaml | 3 ++ boards/sifive/hifive1/hifive1.yaml | 3 ++ .../hifive_unleashed/hifive_unleashed.yaml | 3 ++ .../hifive_unmatched/hifive_unmatched.yaml | 3 ++ cmake/emu/renode.cmake | 35 +------------------ doc/develop/test/twister.rst | 6 ---- scripts/pylib/twister/twisterlib/handlers.py | 17 ++++++++- scripts/pylib/twister/twisterlib/harness.py | 9 +++-- scripts/pylib/twister/twisterlib/platform.py | 5 +++ scripts/schemas/twister/platform-schema.yaml | 7 ++++ scripts/tests/twister/test_handlers.py | 13 +++++-- scripts/tests/twister/test_harness.py | 2 +- 13 files changed, 59 insertions(+), 50 deletions(-) diff --git a/boards/microchip/m2gl025_miv/m2gl025_miv.yaml b/boards/microchip/m2gl025_miv/m2gl025_miv.yaml index 3f60b02c59e8f..4ba9e126a7fea 100644 --- a/boards/microchip/m2gl025_miv/m2gl025_miv.yaml +++ b/boards/microchip/m2gl025_miv/m2gl025_miv.yaml @@ -12,4 +12,7 @@ testing: ignore_tags: - net - bluetooth + renode: + uart: sysbus.uart + resc: boards/microchip/m2gl025_miv/support/m2gl025_miv.resc vendor: microchip diff --git a/boards/renode/riscv32_virtual/riscv32_virtual.yaml b/boards/renode/riscv32_virtual/riscv32_virtual.yaml index 600a5679f7e0c..64cab1f32ba5e 100644 --- a/boards/renode/riscv32_virtual/riscv32_virtual.yaml +++ b/boards/renode/riscv32_virtual/riscv32_virtual.yaml @@ -12,5 +12,8 @@ testing: ignore_tags: - net - bluetooth + renode: + uart: sysbus.uart0 + resc: boards/renode/riscv32_virtual/support/riscv32_virtual.resc supported: - uart diff --git a/boards/sifive/hifive1/hifive1.yaml b/boards/sifive/hifive1/hifive1.yaml index 345768fb2797a..99463674324ba 100644 --- a/boards/sifive/hifive1/hifive1.yaml +++ b/boards/sifive/hifive1/hifive1.yaml @@ -19,4 +19,7 @@ testing: - bluetooth - flash - newlib + renode: + uart: sysbus.uart0 + resc: boards/sifive/hifive1/support/hifive1.resc vendor: sifive diff --git a/boards/sifive/hifive_unleashed/hifive_unleashed.yaml b/boards/sifive/hifive_unleashed/hifive_unleashed.yaml index 749c62f4dcae8..1fb91e4c2e0ed 100644 --- a/boards/sifive/hifive_unleashed/hifive_unleashed.yaml +++ b/boards/sifive/hifive_unleashed/hifive_unleashed.yaml @@ -14,6 +14,9 @@ testing: - flash - newlib - crypto + renode: + uart: sysbus.uart0 + resc: boards/sifive/hifive_unleashed/support/hifive_unleashed.resc supported: - gpio - spi diff --git a/boards/sifive/hifive_unmatched/hifive_unmatched.yaml b/boards/sifive/hifive_unmatched/hifive_unmatched.yaml index 0743a9cc0f5d4..6fbfb696ce153 100644 --- a/boards/sifive/hifive_unmatched/hifive_unmatched.yaml +++ b/boards/sifive/hifive_unmatched/hifive_unmatched.yaml @@ -11,6 +11,9 @@ testing: ignore_tags: - net - bluetooth + renode: + uart: sysbus.uart0 + resc: boards/sifive/hifive_unmatched/support/hifive_unmatched.resc supported: - spi - memc diff --git a/cmake/emu/renode.cmake b/cmake/emu/renode.cmake index ab26cfeaf809c..4deebd848c996 100644 --- a/cmake/emu/renode.cmake +++ b/cmake/emu/renode.cmake @@ -22,40 +22,7 @@ add_custom_target(run_renode COMMAND ${RENODE} ${RENODE_FLAGS} - -e '$$bin=@${APPLICATION_BINARY_DIR}/zephyr/${KERNEL_ELF_NAME}\; include @${RENODE_SCRIPT}\; ${RENODE_OVERLAY} s' - WORKING_DIRECTORY ${APPLICATION_BINARY_DIR} - DEPENDS ${logical_target_for_zephyr_elf} - USES_TERMINAL - ) - -find_program( - RENODE_TEST - renode-test - ) - -set(RENODE_TEST_FLAGS - --variable ELF:@${APPLICATION_BINARY_DIR}/zephyr/${KERNEL_ELF_NAME} - --variable RESC:@${RENODE_SCRIPT} - --variable UART:${RENODE_UART} - --variable KEYWORDS:${ZEPHYR_BASE}/tests/robot/common.robot - --results-dir ${APPLICATION_BINARY_DIR} - ) - -add_custom_target(run_renode_test - COMMAND /bin/sh -c "\ - if [ -z $$ROBOT_FILES ] \;\ - then\ - echo ''\;\ - echo '--- Error: Robot file path is required to run Robot tests in Renode. To provide the path please set the ROBOT_FILES variable.'\;\ - echo '--- To rerun the test with west execute:'\;\ - echo '--- ROBOT_FILES=\\ west build -p -b \\ -s \\ -t run_renode_test'\;\ - echo ''\;\ - exit 1\;\ - fi\;" - COMMAND - ${RENODE_TEST} - ${RENODE_TEST_FLAGS} - ${APPLICATION_SOURCE_DIR}/$$ROBOT_FILES + -e '$$bin=@${PROJECT_BINARY_DIR}/${KERNEL_ELF_NAME}\; include @${RENODE_SCRIPT}\; ${RENODE_OVERLAY} s' WORKING_DIRECTORY ${APPLICATION_BINARY_DIR} DEPENDS ${logical_target_for_zephyr_elf} USES_TERMINAL diff --git a/doc/develop/test/twister.rst b/doc/develop/test/twister.rst index 4f0169ecec69b..3be0132b05cd7 100644 --- a/doc/develop/test/twister.rst +++ b/doc/develop/test/twister.rst @@ -1347,12 +1347,6 @@ To execute a Robot test suite with twister, run the following command: python .\scripts\twister --platform hifive1 --test samples/subsys/shell/shell_module/sample.shell.shell_module.robot -It's also possible to run it by `west` directly, with: - -.. code-block:: bash - - $ ROBOT_FILES=shell_module.robot west build -p -b hifive1 -s samples/subsys/shell/shell_module -t run_renode_test - Writing Robot tests =================== diff --git a/scripts/pylib/twister/twisterlib/handlers.py b/scripts/pylib/twister/twisterlib/handlers.py index 414f89f207ace..3a3c8de4cb37e 100755 --- a/scripts/pylib/twister/twisterlib/handlers.py +++ b/scripts/pylib/twister/twisterlib/handlers.py @@ -21,6 +21,7 @@ from queue import Queue, Empty from twisterlib.environment import ZEPHYR_BASE, strip_ansi_sequences from twisterlib.error import TwisterException +from twisterlib.platform import Platform sys.path.insert(0, os.path.join(ZEPHYR_BASE, "scripts/pylib/build_helpers")) from domains import Domains @@ -232,7 +233,21 @@ def _output_handler(self, proc, harness): def _create_command(self, robot_test): if robot_test: - command = [self.generator_cmd, "run_renode_test"] + keywords = os.path.join(self.options.coverage_basedir, 'tests/robot/common.robot') + elf = os.path.join(self.build_dir, "zephyr/zephyr.elf") + command = [self.generator_cmd] + resc = "" + uart = "" + # os.path.join cannot be used on a Mock object, so we are + # explicitly checking the type + if isinstance(self.instance.platform, Platform): + resc = os.path.join(self.options.coverage_basedir, self.instance.platform.resc) + uart = self.instance.platform.uart + command = ["renode-test", + "--variable", "KEYWORDS:" + keywords, + "--variable", "ELF:@" + elf, + "--variable", "RESC:@" + resc, + "--variable", "UART:" + uart] elif self.call_make_run: command = [self.generator_cmd, "run"] elif self.instance.testsuite.type == "unit": diff --git a/scripts/pylib/twister/twisterlib/harness.py b/scripts/pylib/twister/twisterlib/harness.py index b0925c0fce096..8f4f47a7f082d 100644 --- a/scripts/pylib/twister/twisterlib/harness.py +++ b/scripts/pylib/twister/twisterlib/harness.py @@ -152,18 +152,17 @@ def handle(self, line): tc.status = "passed" def run_robot_test(self, command, handler): - start_time = time.time() env = os.environ.copy() - env["ROBOT_FILES"] = self.path + command.append(os.path.join(handler.sourcedir, self.path)) with subprocess.Popen(command, stdout=subprocess.PIPE, - stderr=subprocess.STDOUT, cwd=self.instance.build_dir, env=env) as cmake_proc: - out, _ = cmake_proc.communicate() + stderr=subprocess.STDOUT, cwd=self.instance.build_dir, env=env) as renode_test_proc: + out, _ = renode_test_proc.communicate() self.instance.execution_time = time.time() - start_time - if cmake_proc.returncode == 0: + if renode_test_proc.returncode == 0: self.instance.status = "passed" # all tests in one Robot file are treated as a single test case, # so its status should be set accordingly to the instance status diff --git a/scripts/pylib/twister/twisterlib/platform.py b/scripts/pylib/twister/twisterlib/platform.py index 769876cf05ae5..44672c36a77cf 100644 --- a/scripts/pylib/twister/twisterlib/platform.py +++ b/scripts/pylib/twister/twisterlib/platform.py @@ -46,6 +46,8 @@ def __init__(self): self.env = [] self.env_satisfied = True self.filter_data = dict() + self.uart = "" + self.resc = "" def load(self, platform_file): scp = TwisterConfigParser(platform_file, self.platform_schema) @@ -63,6 +65,9 @@ def load(self, platform_file): self.only_tags = testing.get("only_tags", []) self.default = testing.get("default", False) self.binaries = testing.get("binaries", []) + renode = testing.get("renode", {}) + self.uart = renode.get("uart", "") + self.resc = renode.get("resc", "") # if no flash size is specified by the board, take a default of 512K self.flash = data.get("flash", 512) self.supported = set() diff --git a/scripts/schemas/twister/platform-schema.yaml b/scripts/schemas/twister/platform-schema.yaml index b5c3339fc03ab..dd9dfe10dafea 100644 --- a/scripts/schemas/twister/platform-schema.yaml +++ b/scripts/schemas/twister/platform-schema.yaml @@ -100,3 +100,10 @@ mapping: type: seq seq: - type: str + "renode": + type: map + mapping: + "uart": + type: str + "resc": + type: str diff --git a/scripts/tests/twister/test_handlers.py b/scripts/tests/twister/test_handlers.py index b5012646eb904..2aa6aa92fcb11 100644 --- a/scripts/tests/twister/test_handlers.py +++ b/scripts/tests/twister/test_handlers.py @@ -18,10 +18,12 @@ from importlib import reload from serial import SerialException from subprocess import CalledProcessError, TimeoutExpired +from types import SimpleNamespace import twisterlib.harness -from conftest import ZEPHYR_BASE +ZEPHYR_BASE = os.getenv("ZEPHYR_BASE") + from twisterlib.error import TwisterException from twisterlib.handlers import ( Handler, @@ -413,7 +415,7 @@ def wait(self, *args, **kwargs): ['valgrind', '--error-exitcode=2', '--leak-check=full', f'--suppressions={ZEPHYR_BASE}/scripts/valgrind.supp', '--log-file=build_dir/valgrind.log', '--track-origins=yes', - 'generator', 'run_renode_test']), + 'generator']), (False, True, False, 123, None, ['generator', 'run', '--seed=123']), (False, False, False, None, ['ex1', 'ex2'], ['build_dir/zephyr/zephyr.exe', 'ex1', 'ex2']), ] @@ -437,11 +439,16 @@ def test_binaryhandler_create_command( handler.generator_cmd = 'generator' handler.binary = 'bin' handler.call_make_run = call_make_run - handler.options = mock.Mock(enable_valgrind=enable_valgrind) + handler.options = SimpleNamespace() + handler.options.enable_valgrind = enable_valgrind + handler.options.coverage_basedir = "coverage_basedir" handler.seed = seed handler.extra_test_args = extra_args handler.build_dir = 'build_dir' handler.instance.testsuite.sysbuild = False + handler.platform = SimpleNamespace() + handler.platform.resc = "file.resc" + handler.platform.uart = "uart" command = handler._create_command(robot_test) diff --git a/scripts/tests/twister/test_harness.py b/scripts/tests/twister/test_harness.py index a01d313cb28ee..6a92a4ffba0c1 100644 --- a/scripts/tests/twister/test_harness.py +++ b/scripts/tests/twister/test_harness.py @@ -166,7 +166,7 @@ def test_robot_handle(tmp_path): ) def test_robot_run_robot_test(tmp_path, caplog, exp_out, returncode, expected_status): # Arrange - command = "command" + command = ["command"] handler = mock.Mock() handler.sourcedir = "sourcedir" From 959ea1a1727a86b299545b3219da8379e72c4615 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Szprejda?= Date: Mon, 4 Mar 2024 17:51:33 +0100 Subject: [PATCH 1248/2849] resc: cmake: robot: Rename Renode variable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rename Renode variable used to store the .elf file path from `bin` to `elf` for consistency. Signed-off-by: Michał Szprejda --- boards/ite/it8xxx2_evb/support/it8xxx2_evb.resc | 2 +- boards/microchip/m2gl025_miv/support/m2gl025_miv.resc | 2 +- boards/microchip/mpfs_icicle/support/mpfs250t.resc | 2 +- boards/renode/riscv32_virtual/support/riscv32_virtual.resc | 2 +- boards/sifive/hifive1/support/hifive1.resc | 2 +- boards/sifive/hifive_unleashed/support/hifive_unleashed.resc | 2 +- boards/sifive/hifive_unmatched/support/hifive_unmatched.resc | 2 +- cmake/emu/renode.cmake | 2 +- tests/robot/common.robot | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/boards/ite/it8xxx2_evb/support/it8xxx2_evb.resc b/boards/ite/it8xxx2_evb/support/it8xxx2_evb.resc index 987fed77bac33..5ef1ae4e5bbc5 100644 --- a/boards/ite/it8xxx2_evb/support/it8xxx2_evb.resc +++ b/boards/ite/it8xxx2_evb/support/it8xxx2_evb.resc @@ -12,6 +12,6 @@ cpu PerformanceInMips 80 macro reset """ - sysbus LoadELF $bin + sysbus LoadELF $elf """ runMacro $reset diff --git a/boards/microchip/m2gl025_miv/support/m2gl025_miv.resc b/boards/microchip/m2gl025_miv/support/m2gl025_miv.resc index 2227e89bff282..d45eb5e7855d6 100644 --- a/boards/microchip/m2gl025_miv/support/m2gl025_miv.resc +++ b/boards/microchip/m2gl025_miv/support/m2gl025_miv.resc @@ -12,6 +12,6 @@ cpu PerformanceInMips 4 macro reset """ - sysbus LoadELF $bin + sysbus LoadELF $elf """ runMacro $reset diff --git a/boards/microchip/mpfs_icicle/support/mpfs250t.resc b/boards/microchip/mpfs_icicle/support/mpfs250t.resc index 8892b2839ded9..29005c8f1988a 100644 --- a/boards/microchip/mpfs_icicle/support/mpfs250t.resc +++ b/boards/microchip/mpfs_icicle/support/mpfs250t.resc @@ -12,6 +12,6 @@ e51 PerformanceInMips 80 macro reset """ - sysbus LoadELF $bin + sysbus LoadELF $elf """ runMacro $reset diff --git a/boards/renode/riscv32_virtual/support/riscv32_virtual.resc b/boards/renode/riscv32_virtual/support/riscv32_virtual.resc index 87e327287b61a..dedbc699078b1 100644 --- a/boards/renode/riscv32_virtual/support/riscv32_virtual.resc +++ b/boards/renode/riscv32_virtual/support/riscv32_virtual.resc @@ -12,6 +12,6 @@ cpu PerformanceInMips 4 macro reset """ - sysbus LoadELF $bin + sysbus LoadELF $elf """ runMacro $reset diff --git a/boards/sifive/hifive1/support/hifive1.resc b/boards/sifive/hifive1/support/hifive1.resc index e9aaa1be62d57..bbe5f26c8add1 100644 --- a/boards/sifive/hifive1/support/hifive1.resc +++ b/boards/sifive/hifive1/support/hifive1.resc @@ -23,6 +23,6 @@ showAnalyzer uart0 macro reset """ - sysbus LoadELF $bin + sysbus LoadELF $elf """ runMacro $reset diff --git a/boards/sifive/hifive_unleashed/support/hifive_unleashed.resc b/boards/sifive/hifive_unleashed/support/hifive_unleashed.resc index a46d377d7c2bc..4d06081c5c946 100644 --- a/boards/sifive/hifive_unleashed/support/hifive_unleashed.resc +++ b/boards/sifive/hifive_unleashed/support/hifive_unleashed.resc @@ -20,6 +20,6 @@ showAnalyzer uart0 macro reset """ - sysbus LoadELF $bin + sysbus LoadELF $elf """ runMacro $reset diff --git a/boards/sifive/hifive_unmatched/support/hifive_unmatched.resc b/boards/sifive/hifive_unmatched/support/hifive_unmatched.resc index 535bb06c69cea..4d18a9b86dd78 100644 --- a/boards/sifive/hifive_unmatched/support/hifive_unmatched.resc +++ b/boards/sifive/hifive_unmatched/support/hifive_unmatched.resc @@ -20,6 +20,6 @@ showAnalyzer uart0 macro reset """ - sysbus LoadELF $bin + sysbus LoadELF $elf """ runMacro $reset diff --git a/cmake/emu/renode.cmake b/cmake/emu/renode.cmake index 4deebd848c996..fa99da0f8fd6e 100644 --- a/cmake/emu/renode.cmake +++ b/cmake/emu/renode.cmake @@ -22,7 +22,7 @@ add_custom_target(run_renode COMMAND ${RENODE} ${RENODE_FLAGS} - -e '$$bin=@${PROJECT_BINARY_DIR}/${KERNEL_ELF_NAME}\; include @${RENODE_SCRIPT}\; ${RENODE_OVERLAY} s' + -e '$$elf=@${PROJECT_BINARY_DIR}/${KERNEL_ELF_NAME}\; include @${RENODE_SCRIPT}\; ${RENODE_OVERLAY} s' WORKING_DIRECTORY ${APPLICATION_BINARY_DIR} DEPENDS ${logical_target_for_zephyr_elf} USES_TERMINAL diff --git a/tests/robot/common.robot b/tests/robot/common.robot index 55c52d915c5a0..2bebe95579747 100644 --- a/tests/robot/common.robot +++ b/tests/robot/common.robot @@ -2,6 +2,6 @@ *** Keywords *** Prepare Machine - Execute Command $bin = ${ELF} + Execute Command $elf = ${ELF} Execute Command include ${RESC} Create Terminal Tester ${UART} From 73b73c91f40073f8c398828a34249edfd6f9bd60 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Szprejda?= Date: Mon, 4 Mar 2024 18:03:21 +0100 Subject: [PATCH 1249/2849] West: Add option to supress elf/bin/hex file params MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add capability allowing to suppress the --file parameters that can be passed to a west command runner. Signed-off-by: Michał Szprejda --- scripts/west_commands/runners/core.py | 32 +++++++++++++++++---------- 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/scripts/west_commands/runners/core.py b/scripts/west_commands/runners/core.py index fdc38013a9ddb..d77784486d099 100644 --- a/scripts/west_commands/runners/core.py +++ b/scripts/west_commands/runners/core.py @@ -247,6 +247,8 @@ class RunnerCaps: - file: whether the runner supports a --file option, which specifies exactly the file that should be used to flash, overriding any default discovered in the build directory. + + - hide_load_files: whether the elf/hex/bin file arguments should be hidden. ''' commands: Set[str] = field(default_factory=lambda: set(_RUNNERCAPS_COMMANDS)) @@ -257,6 +259,7 @@ class RunnerCaps: extload: bool = False tool_opt: bool = False file: bool = False + hide_load_files: bool = False def __post_init__(self): if not self.commands.issubset(_RUNNERCAPS_COMMANDS): @@ -511,18 +514,23 @@ def add_parser(cls, parser): parser.add_argument('-f', '--file', help=argparse.SUPPRESS) parser.add_argument('-t', '--file-type', help=argparse.SUPPRESS) - parser.add_argument('--elf-file', - metavar='FILE', - action=(partial(depr_action, cls=cls, replacement='-f/--file') if caps.file else None), - help='path to zephyr.elf' if not caps.file else 'Deprecated, use -f/--file instead.') - parser.add_argument('--hex-file', - metavar='FILE', - action=(partial(depr_action, cls=cls, replacement='-f/--file') if caps.file else None), - help='path to zephyr.hex' if not caps.file else 'Deprecated, use -f/--file instead.') - parser.add_argument('--bin-file', - metavar='FILE', - action=(partial(depr_action, cls=cls, replacement='-f/--file') if caps.file else None), - help='path to zephyr.bin' if not caps.file else 'Deprecated, use -f/--file instead.') + if caps.hide_load_files: + parser.add_argument('--elf-file', help=argparse.SUPPRESS) + parser.add_argument('--hex-file', help=argparse.SUPPRESS) + parser.add_argument('--bin-file', help=argparse.SUPPRESS) + else: + parser.add_argument('--elf-file', + metavar='FILE', + action=(partial(depr_action, cls=cls, replacement='-f/--file') if caps.file else None), + help='path to zephyr.elf' if not caps.file else 'Deprecated, use -f/--file instead.') + parser.add_argument('--hex-file', + metavar='FILE', + action=(partial(depr_action, cls=cls, replacement='-f/--file') if caps.file else None), + help='path to zephyr.hex' if not caps.file else 'Deprecated, use -f/--file instead.') + parser.add_argument('--bin-file', + metavar='FILE', + action=(partial(depr_action, cls=cls, replacement='-f/--file') if caps.file else None), + help='path to zephyr.bin' if not caps.file else 'Deprecated, use -f/--file instead.') parser.add_argument('--erase', '--no-erase', nargs=0, action=_ToggleAction, From f155ff596cbf2e5bf604f1aaa6d6e978365a4e54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Szprejda?= Date: Mon, 4 Mar 2024 18:07:31 +0100 Subject: [PATCH 1250/2849] West: runners: Add explicit capabilities MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add explicit capabilities to nios2, nsim and openocd runners to prevent them from having potentially unwanted ones (for example when new capabilities are added to Zephyr). Signed-off-by: Michał Szprejda --- scripts/west_commands/runners/nios2.py | 6 +++++- scripts/west_commands/runners/nsim.py | 6 +++++- scripts/west_commands/runners/openocd.py | 6 +++++- 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/scripts/west_commands/runners/nios2.py b/scripts/west_commands/runners/nios2.py index 6312aefc94559..15939b3bb0f96 100644 --- a/scripts/west_commands/runners/nios2.py +++ b/scripts/west_commands/runners/nios2.py @@ -4,7 +4,7 @@ '''Runner for NIOS II, based on quartus-flash.py and GDB.''' -from runners.core import ZephyrBinaryRunner, NetworkPortHelper +from runners.core import ZephyrBinaryRunner, NetworkPortHelper, RunnerCaps class Nios2BinaryRunner(ZephyrBinaryRunner): @@ -29,6 +29,10 @@ def __init__(self, cfg, quartus_py=None, cpu_sof=None, tui=False): def name(cls): return 'nios2' + @classmethod + def capabilities(cls): + return RunnerCaps(commands={'flash', 'debug', 'debugserver', 'attach'}) + @classmethod def do_add_parser(cls, parser): # TODO merge quartus-flash.py script into this file. diff --git a/scripts/west_commands/runners/nsim.py b/scripts/west_commands/runners/nsim.py index 4ec1b76e858d0..94bd09c3dacb7 100644 --- a/scripts/west_commands/runners/nsim.py +++ b/scripts/west_commands/runners/nsim.py @@ -7,7 +7,7 @@ from os import path -from runners.core import ZephyrBinaryRunner +from runners.core import ZephyrBinaryRunner, RunnerCaps DEFAULT_ARC_GDB_PORT = 3333 DEFAULT_PROPS_FILE = 'nsim_em.props' @@ -40,6 +40,10 @@ def __init__(self, cfg, def name(cls): return 'arc-nsim' + @classmethod + def capabilities(cls): + return RunnerCaps(commands={'flash', 'debug', 'debugserver', 'attach'}) + @classmethod def do_add_parser(cls, parser): parser.add_argument('--gdb-port', default=DEFAULT_ARC_GDB_PORT, diff --git a/scripts/west_commands/runners/openocd.py b/scripts/west_commands/runners/openocd.py index 3377705687971..5619c583d96eb 100644 --- a/scripts/west_commands/runners/openocd.py +++ b/scripts/west_commands/runners/openocd.py @@ -18,7 +18,7 @@ except ImportError: pass -from runners.core import ZephyrBinaryRunner +from runners.core import ZephyrBinaryRunner, RunnerCaps DEFAULT_OPENOCD_TCL_PORT = 6333 DEFAULT_OPENOCD_TELNET_PORT = 4444 @@ -100,6 +100,10 @@ def __init__(self, cfg, pre_init=None, reset_halt_cmd=DEFAULT_OPENOCD_RESET_HALT def name(cls): return 'openocd' + @classmethod + def capabilities(cls): + return RunnerCaps(commands={'flash', 'debug', 'debugserver', 'attach'}) + @classmethod def do_add_parser(cls, parser): parser.add_argument('--config', action='append', From 80900cbc3be9bb533a37bc044cc2f8bfb92312a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Szprejda?= Date: Thu, 7 Mar 2024 10:30:09 +0100 Subject: [PATCH 1251/2849] West: Add `west simulate` command MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Introduce `simulate `command for running samples on a simulator of choice. Initial implementation consists of one runner, dedicated for Renode. Signed-off-by: Michał Szprejda --- boards/common/renode.board.cmake | 8 +++ boards/microchip/m2gl025_miv/board.cmake | 3 + boards/sifive/hifive1/board.cmake | 3 + cmake/flash/CMakeLists.txt | 4 ++ cmake/modules/extensions.cmake | 14 +++-- doc/develop/west/build-flash-debug.rst | 43 ++++++++++++++ scripts/west-commands.yml | 5 ++ scripts/west_commands/run_common.py | 2 +- scripts/west_commands/runners/__init__.py | 1 + scripts/west_commands/runners/core.py | 4 +- scripts/west_commands/runners/renode.py | 62 +++++++++++++++++++++ scripts/west_commands/simulate.py | 29 ++++++++++ scripts/west_commands/tests/test_imports.py | 1 + 13 files changed, 172 insertions(+), 7 deletions(-) create mode 100644 boards/common/renode.board.cmake create mode 100644 scripts/west_commands/runners/renode.py create mode 100644 scripts/west_commands/simulate.py diff --git a/boards/common/renode.board.cmake b/boards/common/renode.board.cmake new file mode 100644 index 0000000000000..c7c9b02ec59fd --- /dev/null +++ b/boards/common/renode.board.cmake @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: Apache-2.0 + +board_set_sim_runner_ifnset(renode) + +board_runner_args(renode "--renode-command=$elf=@${PROJECT_BINARY_DIR}/${KERNEL_ELF_NAME}") +board_runner_args(renode "--renode-command=include @${RENODE_SCRIPT}") + +board_finalize_runner_args(renode) diff --git a/boards/microchip/m2gl025_miv/board.cmake b/boards/microchip/m2gl025_miv/board.cmake index 2919ac7874201..74cca86292d8f 100644 --- a/boards/microchip/m2gl025_miv/board.cmake +++ b/boards/microchip/m2gl025_miv/board.cmake @@ -3,3 +3,6 @@ set(SUPPORTED_EMU_PLATFORMS renode) set(RENODE_SCRIPT ${CMAKE_CURRENT_LIST_DIR}/support/m2gl025_miv.resc) set(RENODE_UART sysbus.uart) + +set_ifndef(BOARD_SIM_RUNNER renode) +include(${ZEPHYR_BASE}/boards/common/renode.board.cmake) diff --git a/boards/sifive/hifive1/board.cmake b/boards/sifive/hifive1/board.cmake index 4f39320870c18..29ec8b2e6ab0a 100644 --- a/boards/sifive/hifive1/board.cmake +++ b/boards/sifive/hifive1/board.cmake @@ -28,3 +28,6 @@ elseif("${BOARD_REVISION}" STREQUAL "B") board_runner_args(jlink "--tool-opt=-autoconnect 1") include(${ZEPHYR_BASE}/boards/common/jlink.board.cmake) endif() + +set_ifndef(BOARD_SIM_RUNNER renode) +include(${ZEPHYR_BASE}/boards/common/renode.board.cmake) diff --git a/cmake/flash/CMakeLists.txt b/cmake/flash/CMakeLists.txt index 392274891f196..bdfa7fd5f875a 100644 --- a/cmake/flash/CMakeLists.txt +++ b/cmake/flash/CMakeLists.txt @@ -97,6 +97,10 @@ function(create_runners_yaml) runners_yaml_append("\n# Default debug runner if --runner is not given.") runners_yaml_append("debug-runner: ${BOARD_DEBUG_RUNNER}") endif() + if(DEFINED BOARD_SIM_RUNNER) + runners_yaml_append("\n# Default simulation runner if --runner is not given.") + runners_yaml_append("sim-runner: ${BOARD_SIM_RUNNER}") + endif() # Sets up common runner configuration values. runners_yaml_append_config() diff --git a/cmake/modules/extensions.cmake b/cmake/modules/extensions.cmake index 315890732c321..6c0231676a202 100644 --- a/cmake/modules/extensions.cmake +++ b/cmake/modules/extensions.cmake @@ -705,9 +705,10 @@ endfunction() # This section provides glue between CMake and the Python code that # manages the runners. +set(TYPES "FLASH" "DEBUG" "SIM") function(_board_check_runner_type type) # private helper - if (NOT (("${type}" STREQUAL "FLASH") OR ("${type}" STREQUAL "DEBUG"))) - message(FATAL_ERROR "invalid type ${type}; should be FLASH or DEBUG") + if (NOT "${type}" IN_LIST TYPES) + message(FATAL_ERROR "invalid type ${type}; should be one of: ${TYPES}") endif() endfunction() @@ -723,8 +724,8 @@ endfunction() # # This would set the board's flash runner to "pyocd". # -# In general, "type" is FLASH or DEBUG, and "runner" is the name of a -# runner. +# In general, "type" is FLASH, DEBUG or SIM and "runner" is +# the name of a runner. function(board_set_runner type runner) _board_check_runner_type(${type}) if (DEFINED BOARD_${type}_RUNNER) @@ -765,6 +766,11 @@ macro(board_set_debugger_ifnset runner) board_set_runner_ifnset(DEBUG ${runner}) endmacro() +# A convenience macro for board_set_runner_ifnset(SIM ${runner}). +macro(board_set_sim_runner_ifnset runner) + board_set_runner_ifnset(SIM ${runner}) +endmacro() + # This function is intended for board.cmake files and application # CMakeLists.txt files. # diff --git a/doc/develop/west/build-flash-debug.rst b/doc/develop/west/build-flash-debug.rst index 8356d95cade64..4456151aa06c1 100644 --- a/doc/develop/west/build-flash-debug.rst +++ b/doc/develop/west/build-flash-debug.rst @@ -698,6 +698,49 @@ determined by the imported subclasses of ``ZephyrBinaryRunner``. runner implementations are in other submodules, such as ``runners.nrfjprog``, ``runners.openocd``, etc. +Simulating a board with: ``west simulate`` +****************************************** + +Basics +====== + +Currently the command supports only one runner which is using Renode, +but can be easily extended by adding other runners. + +From a Zephyr build directory, to run the built binary:: + + west simulate --runner=renode + +This will start Renode and configure simulation based on a default ``.resc`` script +for the current platform with the zephyr.elf file loaded by default. The simulation +then can be started by typing "start" or "s" in Renode's Monitor. This can also be +done by passing a command to Renode, using an argument provided by the runner: + + west simulate --runner=renode --renode-command start + +To pass an argument to Renode itself, for example to start Renode in console mode +intead of a separate window: + + west simulate --runner=renode --renode-arg="--console" + +From that point on Renode can be used normally in both console and window modes. +For details on using Renode see `Renode - documentation`_. + +.. _Renode - documentation: + http://docs.renode.io + +Runner-Specific Overrides +========================= + +To view all of the available options supported by the runners, as well +as their usage information, use ``--context`` (or``-H``):: + + west simulate --runner=renode --context + +To view all available options Renode supports, use:: + + west simulate --runner=renode --renode-help + Hacking ******* diff --git a/scripts/west-commands.yml b/scripts/west-commands.yml index 6cd0c511fb3bc..54254c381faf7 100644 --- a/scripts/west-commands.yml +++ b/scripts/west-commands.yml @@ -66,3 +66,8 @@ west-commands: - name: bindesc class: Bindesc help: work with Binary Descriptors + - file: scripts/west_commands/simulate.py + commands: + - name: simulate + class: Simulate + help: simulate board diff --git a/scripts/west_commands/run_common.py b/scripts/west_commands/run_common.py index 8656d0907679b..7cd30c86fe6f7 100644 --- a/scripts/west_commands/run_common.py +++ b/scripts/west_commands/run_common.py @@ -512,7 +512,7 @@ def runners_yaml_path(build_dir, board): ret = Path(build_dir) / 'zephyr' / 'runners.yaml' if not ret.is_file(): log.die(f'either a pristine build is needed, or board {board} ' - "doesn't support west flash/debug " + "doesn't support west flash/debug/simulate " '(no ZEPHYR_RUNNERS_YAML in CMake cache)') return ret diff --git a/scripts/west_commands/runners/__init__.py b/scripts/west_commands/runners/__init__.py index aa5686f73b067..53df19d055049 100644 --- a/scripts/west_commands/runners/__init__.py +++ b/scripts/west_commands/runners/__init__.py @@ -48,6 +48,7 @@ def _import_runner_module(runner_name): 'nxp_s32dbg', 'openocd', 'pyocd', + 'renode', 'qemu', 'silabs_commander', 'spi_burn', diff --git a/scripts/west_commands/runners/core.py b/scripts/west_commands/runners/core.py index d77784486d099..618cb4e1ee29e 100644 --- a/scripts/west_commands/runners/core.py +++ b/scripts/west_commands/runners/core.py @@ -200,7 +200,7 @@ def __init__(self, program): super().__init__(errno.ENOENT, os.strerror(errno.ENOENT), program) -_RUNNERCAPS_COMMANDS = {'flash', 'debug', 'debugserver', 'attach'} +_RUNNERCAPS_COMMANDS = {'flash', 'debug', 'debugserver', 'attach', 'simulate'} @dataclass class RunnerCaps: @@ -212,7 +212,7 @@ class RunnerCaps: Available capabilities: - commands: set of supported commands; default is {'flash', - 'debug', 'debugserver', 'attach'}. + 'debug', 'debugserver', 'attach', 'simulate'}. - dev_id: whether the runner supports device identifiers, in the form of an -i, --dev-id option. This is useful when the user has multiple debuggers diff --git a/scripts/west_commands/runners/renode.py b/scripts/west_commands/runners/renode.py new file mode 100644 index 0000000000000..8937199420c78 --- /dev/null +++ b/scripts/west_commands/runners/renode.py @@ -0,0 +1,62 @@ +# Copyright (c) 2024 Antmicro +# +# SPDX-License-Identifier: Apache-2.0 + +'''Runner stub for Renode.''' + +import subprocess +from runners.core import ZephyrBinaryRunner, RunnerCaps + + +class RenodeRunner(ZephyrBinaryRunner): + '''Place-holder for Renode runner customizations.''' + + def __init__(self, cfg, args): + super().__init__(cfg) + self.renode_arg = args.renode_arg + self.renode_command = args.renode_command + self.renode_help = args.renode_help + + @classmethod + def name(cls): + return 'renode' + + @classmethod + def capabilities(cls): + return RunnerCaps(commands={'simulate'}, hide_load_files=True) + + @classmethod + def do_add_parser(cls, parser): + parser.add_argument('--renode-arg', + metavar='ARG', + action='append', + help='additional argument passed to Renode; `--help` will print all possible arguments') + parser.add_argument('--renode-command', + metavar='COMMAND', + action='append', + help='additional command passed to Renode\'s simulation') + parser.add_argument('--renode-help', + default=False, + action='store_true', + help='print all possible `Renode` arguments') + + @classmethod + def do_create(cls, cfg, args): + return RenodeRunner(cfg, args) + + def do_run(self, command, **kwargs): + self.run_test(**kwargs) + + def run_test(self, **kwargs): + cmd = ['renode'] + if self.renode_help is True: + cmd.append('--help') + else: + if self.renode_arg is not None: + for arg in self.renode_arg: + cmd.append(arg) + if self.renode_command is not None: + for command in self.renode_command: + cmd.append('-e') + cmd.append(command) + subprocess.run(cmd, check=True) diff --git a/scripts/west_commands/simulate.py b/scripts/west_commands/simulate.py new file mode 100644 index 0000000000000..ad3d9073303b6 --- /dev/null +++ b/scripts/west_commands/simulate.py @@ -0,0 +1,29 @@ +# Copyright (c) 2024 Antmicro +# +# SPDX-License-Identifier: Apache-2.0 + +from west.commands import WestCommand +from run_common import add_parser_common, do_run_common + +EXPORT_DESCRIPTION = '''\ +Simulate the board on a runner of choice using generated artifacts. +''' + + +class Simulate(WestCommand): + + def __init__(self): + super(Simulate, self).__init__( + 'simulate', + # Keep this in sync with the string in west-commands.yml. + 'simulate board', + EXPORT_DESCRIPTION, + accepts_unknown_args=True) + + self.runner_key = 'sim-runner' # in runners.yaml + + def do_add_parser(self, parser_adder): + return add_parser_common(self, parser_adder) + + def do_run(self, my_args, runner_args): + do_run_common(self, my_args, runner_args) diff --git a/scripts/west_commands/tests/test_imports.py b/scripts/west_commands/tests/test_imports.py index b101ab42fe6c3..c842df0cd51e5 100644 --- a/scripts/west_commands/tests/test_imports.py +++ b/scripts/west_commands/tests/test_imports.py @@ -39,6 +39,7 @@ def test_runner_imports(): 'openocd', 'pyocd', 'qemu', + 'renode', 'silabs_commander', 'spi_burn', 'stm32cubeprogrammer', From 7c084b66496db8d272ec7383b2a95ea46892c309 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Szprejda?= Date: Thu, 7 Mar 2024 10:35:06 +0100 Subject: [PATCH 1252/2849] West: Add `west robot` command MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Introduce `robot` command for running Robot Framework test suites. Initial implementation consists of one runner dedicated for renode-test, which is a Renode wrapper for running Robot tests. Signed-off-by: Michał Szprejda --- boards/common/renode_robot.board.cmake | 17 ++++++ boards/microchip/m2gl025_miv/board.cmake | 2 + boards/sifive/hifive1/board.cmake | 2 + cmake/flash/CMakeLists.txt | 4 ++ cmake/modules/extensions.cmake | 9 ++- doc/develop/west/build-flash-debug.rst | 38 ++++++++++++ scripts/west-commands.yml | 5 ++ scripts/west_commands/robot.py | 29 +++++++++ scripts/west_commands/runners/__init__.py | 1 + scripts/west_commands/runners/core.py | 4 +- scripts/west_commands/runners/renode-robot.py | 60 +++++++++++++++++++ scripts/west_commands/tests/test_imports.py | 1 + 12 files changed, 168 insertions(+), 4 deletions(-) create mode 100644 boards/common/renode_robot.board.cmake create mode 100644 scripts/west_commands/robot.py create mode 100644 scripts/west_commands/runners/renode-robot.py diff --git a/boards/common/renode_robot.board.cmake b/boards/common/renode_robot.board.cmake new file mode 100644 index 0000000000000..3d42b3b8de1ac --- /dev/null +++ b/boards/common/renode_robot.board.cmake @@ -0,0 +1,17 @@ +# SPDX-License-Identifier: Apache-2.0 + +board_set_robot_runner_ifnset(renode-robot) + +# `--variable` is a renode-test argument, for setting a variable that can be later used in a .robot file: +# ELF: used in common.robot to set the `elf` variable in the default .resc script defined in board.cmake +# RESC: path to the .resc script, defined in board.cmake +# UART: default UART used by Robot in tests, defined in board.cmake +# KEYWORDS: path to common.robot, which contains common Robot keywords +# RESULTS_DIR: directory in which Robot artifacts will be generated after running a testsuite +board_runner_args(renode-robot "--renode-robot-arg=--variable=ELF:@${PROJECT_BINARY_DIR}/${KERNEL_ELF_NAME}") +board_runner_args(renode-robot "--renode-robot-arg=--variable=RESC:@${RENODE_SCRIPT}") +board_runner_args(renode-robot "--renode-robot-arg=--variable=UART:${RENODE_UART}") +board_runner_args(renode-robot "--renode-robot-arg=--variable=KEYWORDS:${ZEPHYR_BASE}/tests/robot/common.robot") +board_runner_args(renode-robot "--renode-robot-arg=--variable=RESULTS_DIR:${APPLICATION_BINARY_DIR}") + +board_finalize_runner_args(renode-robot) diff --git a/boards/microchip/m2gl025_miv/board.cmake b/boards/microchip/m2gl025_miv/board.cmake index 74cca86292d8f..b2d72a05eca3d 100644 --- a/boards/microchip/m2gl025_miv/board.cmake +++ b/boards/microchip/m2gl025_miv/board.cmake @@ -5,4 +5,6 @@ set(RENODE_SCRIPT ${CMAKE_CURRENT_LIST_DIR}/support/m2gl025_miv.resc) set(RENODE_UART sysbus.uart) set_ifndef(BOARD_SIM_RUNNER renode) +set_ifndef(BOARD_ROBOT_RUNNER renode-robot) include(${ZEPHYR_BASE}/boards/common/renode.board.cmake) +include(${ZEPHYR_BASE}/boards/common/renode_robot.board.cmake) diff --git a/boards/sifive/hifive1/board.cmake b/boards/sifive/hifive1/board.cmake index 29ec8b2e6ab0a..93a6487d6c85b 100644 --- a/boards/sifive/hifive1/board.cmake +++ b/boards/sifive/hifive1/board.cmake @@ -30,4 +30,6 @@ elseif("${BOARD_REVISION}" STREQUAL "B") endif() set_ifndef(BOARD_SIM_RUNNER renode) +set_ifndef(BOARD_ROBOT_RUNNER renode-robot) include(${ZEPHYR_BASE}/boards/common/renode.board.cmake) +include(${ZEPHYR_BASE}/boards/common/renode_robot.board.cmake) diff --git a/cmake/flash/CMakeLists.txt b/cmake/flash/CMakeLists.txt index bdfa7fd5f875a..9c2b18b6e898d 100644 --- a/cmake/flash/CMakeLists.txt +++ b/cmake/flash/CMakeLists.txt @@ -101,6 +101,10 @@ function(create_runners_yaml) runners_yaml_append("\n# Default simulation runner if --runner is not given.") runners_yaml_append("sim-runner: ${BOARD_SIM_RUNNER}") endif() + if(DEFINED BOARD_ROBOT_RUNNER) + runners_yaml_append("\n# Default test runner if --runner is not given.") + runners_yaml_append("robot-runner: ${BOARD_ROBOT_RUNNER}") + endif() # Sets up common runner configuration values. runners_yaml_append_config() diff --git a/cmake/modules/extensions.cmake b/cmake/modules/extensions.cmake index 6c0231676a202..d8ea799016a69 100644 --- a/cmake/modules/extensions.cmake +++ b/cmake/modules/extensions.cmake @@ -705,7 +705,7 @@ endfunction() # This section provides glue between CMake and the Python code that # manages the runners. -set(TYPES "FLASH" "DEBUG" "SIM") +set(TYPES "FLASH" "DEBUG" "SIM" "ROBOT") function(_board_check_runner_type type) # private helper if (NOT "${type}" IN_LIST TYPES) message(FATAL_ERROR "invalid type ${type}; should be one of: ${TYPES}") @@ -724,7 +724,7 @@ endfunction() # # This would set the board's flash runner to "pyocd". # -# In general, "type" is FLASH, DEBUG or SIM and "runner" is +# In general, "type" is FLASH, DEBUG, SIM or ROBOT and "runner" is # the name of a runner. function(board_set_runner type runner) _board_check_runner_type(${type}) @@ -766,6 +766,11 @@ macro(board_set_debugger_ifnset runner) board_set_runner_ifnset(DEBUG ${runner}) endmacro() +# A convenience macro for board_set_runner_ifnset(ROBOT ${runner}). +macro(board_set_robot_runner_ifnset runner) + board_set_runner_ifnset(ROBOT ${runner}) +endmacro() + # A convenience macro for board_set_runner_ifnset(SIM ${runner}). macro(board_set_sim_runner_ifnset runner) board_set_runner_ifnset(SIM ${runner}) diff --git a/doc/develop/west/build-flash-debug.rst b/doc/develop/west/build-flash-debug.rst index 4456151aa06c1..75db9a8a90b6d 100644 --- a/doc/develop/west/build-flash-debug.rst +++ b/doc/develop/west/build-flash-debug.rst @@ -698,6 +698,44 @@ determined by the imported subclasses of ``ZephyrBinaryRunner``. runner implementations are in other submodules, such as ``runners.nrfjprog``, ``runners.openocd``, etc. +Running Robot Framework tests: ``west robot`` +********************************************* + +.. tip:: Run ``west robot -h`` for additional help. + +Basics +====== + +Currently the command supports only one runner which is using ``renode-test``, +(essentially a wrapper for running Robot tests in Renode), but can be +easily extended by adding other runners. + +From a Zephyr build directory, to run a Robot test suite:: + + west robot --runner=renode-robot --testsuite path/to/testsuite.robot + +This will run all tests from testsuite.robot and print output provided +by Robot Framework. + +To pass additional parameters to Renode use ``--renode-robot-args`` switch. +For example to show Renode logs in addition to Robot Framework's output: + + west robot --runner=renode-robot --testsuite path/to/testsuite.robot --renode-robot-arg="--show-log" + +Runner-Specific Overrides +========================= + +To view all of the available options for the Robot runners your board +supports, as well as their usage information, use ``--context`` (or +``-H``):: + + west robot --runner=renode-robot --context + + +To view all available options "renode-test" runner supports, use:: + + west robot --runner=renode-robot --renode-robot-help + Simulating a board with: ``west simulate`` ****************************************** diff --git a/scripts/west-commands.yml b/scripts/west-commands.yml index 54254c381faf7..24bbddb984535 100644 --- a/scripts/west-commands.yml +++ b/scripts/west-commands.yml @@ -66,6 +66,11 @@ west-commands: - name: bindesc class: Bindesc help: work with Binary Descriptors + - file: scripts/west_commands/robot.py + commands: + - name: robot + class: Robot + help: run RobotFramework test suites - file: scripts/west_commands/simulate.py commands: - name: simulate diff --git a/scripts/west_commands/robot.py b/scripts/west_commands/robot.py new file mode 100644 index 0000000000000..fb5325afe9423 --- /dev/null +++ b/scripts/west_commands/robot.py @@ -0,0 +1,29 @@ +# Copyright (c) 2024 Antmicro +# +# SPDX-License-Identifier: Apache-2.0 + +from west.commands import WestCommand +from run_common import add_parser_common, do_run_common + +EXPORT_DESCRIPTION = '''\ +Run RobotFramework test suites with a runner of choice. +''' + + +class Robot(WestCommand): + + def __init__(self): + super(Robot, self).__init__( + 'robot', + # Keep this in sync with the string in west-commands.yml. + 'run RobotFramework test suites', + EXPORT_DESCRIPTION, + accepts_unknown_args=True) + + self.runner_key = 'robot-runner' # in runners.yaml + + def do_add_parser(self, parser_adder): + return add_parser_common(self, parser_adder) + + def do_run(self, my_args, runner_args): + do_run_common(self, my_args, runner_args) diff --git a/scripts/west_commands/runners/__init__.py b/scripts/west_commands/runners/__init__.py index 53df19d055049..0f08aa366599b 100644 --- a/scripts/west_commands/runners/__init__.py +++ b/scripts/west_commands/runners/__init__.py @@ -49,6 +49,7 @@ def _import_runner_module(runner_name): 'openocd', 'pyocd', 'renode', + 'renode-robot', 'qemu', 'silabs_commander', 'spi_burn', diff --git a/scripts/west_commands/runners/core.py b/scripts/west_commands/runners/core.py index 618cb4e1ee29e..f411f56cad3ed 100644 --- a/scripts/west_commands/runners/core.py +++ b/scripts/west_commands/runners/core.py @@ -200,7 +200,7 @@ def __init__(self, program): super().__init__(errno.ENOENT, os.strerror(errno.ENOENT), program) -_RUNNERCAPS_COMMANDS = {'flash', 'debug', 'debugserver', 'attach', 'simulate'} +_RUNNERCAPS_COMMANDS = {'flash', 'debug', 'debugserver', 'attach', 'simulate', 'robot'} @dataclass class RunnerCaps: @@ -212,7 +212,7 @@ class RunnerCaps: Available capabilities: - commands: set of supported commands; default is {'flash', - 'debug', 'debugserver', 'attach', 'simulate'}. + 'debug', 'debugserver', 'attach', 'simulate', 'robot'}. - dev_id: whether the runner supports device identifiers, in the form of an -i, --dev-id option. This is useful when the user has multiple debuggers diff --git a/scripts/west_commands/runners/renode-robot.py b/scripts/west_commands/runners/renode-robot.py new file mode 100644 index 0000000000000..3a5c87ad7d0ea --- /dev/null +++ b/scripts/west_commands/runners/renode-robot.py @@ -0,0 +1,60 @@ +# Copyright (c) 2024 Antmicro +# +# SPDX-License-Identifier: Apache-2.0 + +'''Runner stub for renode-test.''' + +import subprocess +from runners.core import ZephyrBinaryRunner, RunnerCaps + + +class RenodeRobotRunner(ZephyrBinaryRunner): + '''Place-holder for Renode runner customizations.''' + + def __init__(self, cfg, args): + super().__init__(cfg) + self.testsuite = args.testsuite + self.renode_robot_arg = args.renode_robot_arg + self.renode_robot_help = args.renode_robot_help + + @classmethod + def name(cls): + return 'renode-robot' + + @classmethod + def capabilities(cls): + return RunnerCaps(commands={'robot'}, hide_load_files=True) + + @classmethod + def do_add_parser(cls, parser): + parser.add_argument('--testsuite', + help='path to Robot test suite') + parser.add_argument('--renode-robot-arg', + metavar='ARG', + action='append', + help='additional argument passed to renode-test') + parser.add_argument('--renode-robot-help', + default=False, + action='store_true', + help='print all possible `renode-test` arguments') + + @classmethod + def do_create(cls, cfg, args): + return RenodeRobotRunner(cfg, args) + + def do_run(self, command, **kwargs): + self.run_test(**kwargs) + + def run_test(self, **kwargs): + cmd = ['renode-test'] + if self.renode_robot_help is True: + cmd.append('--help') + else: + if self.renode_robot_arg is not None: + for arg in self.renode_robot_arg: + cmd.append(arg) + if self.testsuite is not None: + cmd.append(self.testsuite) + else: + self.logger.error("No Robot testsuite passed to renode-test! Use the `--testsuite` argument to provide one.") + subprocess.run(cmd, check=True) diff --git a/scripts/west_commands/tests/test_imports.py b/scripts/west_commands/tests/test_imports.py index c842df0cd51e5..4675da612569f 100644 --- a/scripts/west_commands/tests/test_imports.py +++ b/scripts/west_commands/tests/test_imports.py @@ -40,6 +40,7 @@ def test_runner_imports(): 'pyocd', 'qemu', 'renode', + 'renode-robot', 'silabs_commander', 'spi_burn', 'stm32cubeprogrammer', From bdca41d0bf9863e83f09b9713b4c24d672d2cf8e Mon Sep 17 00:00:00 2001 From: Mark Wang Date: Thu, 11 Apr 2024 16:39:13 +0800 Subject: [PATCH 1253/2849] Bluetooth: A2DP: Implement the a2dp and avdtp implement a2dp.c and avdtp.c add a2dp related Kconfig: BT_AVDTP_RTP_VERSION, BT_A2DP_SOURCE and BT_A2DP_SINK a2dp_codec_sbc.c/h are used to provide some APIs to get A2DP SBC codec information. (like: channel num). Signed-off-by: Mark Wang --- include/zephyr/bluetooth/classic/a2dp-codec.h | 115 -- include/zephyr/bluetooth/classic/a2dp.h | 762 ++++++++++- .../zephyr/bluetooth/classic/a2dp_codec_sbc.h | 124 ++ include/zephyr/bluetooth/classic/avdtp.h | 142 +- subsys/bluetooth/host/classic/CMakeLists.txt | 2 +- subsys/bluetooth/host/classic/Kconfig | 24 + subsys/bluetooth/host/classic/a2dp.c | 818 +++++++++++- .../bluetooth/host/classic/a2dp_codec_sbc.c | 51 + subsys/bluetooth/host/classic/avdtp.c | 1157 ++++++++++++++++- .../bluetooth/host/classic/avdtp_internal.h | 171 ++- 10 files changed, 3071 insertions(+), 295 deletions(-) delete mode 100644 include/zephyr/bluetooth/classic/a2dp-codec.h create mode 100644 include/zephyr/bluetooth/classic/a2dp_codec_sbc.h create mode 100644 subsys/bluetooth/host/classic/a2dp_codec_sbc.c diff --git a/include/zephyr/bluetooth/classic/a2dp-codec.h b/include/zephyr/bluetooth/classic/a2dp-codec.h deleted file mode 100644 index 3da36420dcd21..0000000000000 --- a/include/zephyr/bluetooth/classic/a2dp-codec.h +++ /dev/null @@ -1,115 +0,0 @@ -/** @file - * @brief Advance Audio Distribution Profile - SBC Codec header. - */ -/* - * SPDX-License-Identifier: Apache-2.0 - * Copyright (c) 2015-2016 Intel Corporation - * - * 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. - */ -#ifndef ZEPHYR_INCLUDE_BLUETOOTH_A2DP_CODEC_H_ -#define ZEPHYR_INCLUDE_BLUETOOTH_A2DP_CODEC_H_ - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @name Sampling Frequency - * @{ - */ -#define A2DP_SBC_SAMP_FREQ_16000 BIT(7) /**< 16 kHz */ -#define A2DP_SBC_SAMP_FREQ_32000 BIT(6) /**< 32 kHz */ -#define A2DP_SBC_SAMP_FREQ_44100 BIT(5) /**< 44.1 kHz */ -#define A2DP_SBC_SAMP_FREQ_48000 BIT(4) /**< 48 kHz */ -/** @} */ - -/** - * @name Channel Mode - * @{ - */ -#define A2DP_SBC_CH_MODE_MONO BIT(3) /**< Mono */ -#define A2DP_SBC_CH_MODE_DUAL BIT(2) /**< Dual Channel */ -#define A2DP_SBC_CH_MODE_STREO BIT(1) /**< Stereo */ -#define A2DP_SBC_CH_MODE_JOINT BIT(0) /**< Joint Stereo */ -/** @} */ - -/** - * @name Block Length - * @{ - */ -#define A2DP_SBC_BLK_LEN_4 BIT(7) /**< 4 blocks */ -#define A2DP_SBC_BLK_LEN_8 BIT(6) /**< 8 blocks */ -#define A2DP_SBC_BLK_LEN_12 BIT(5) /**< 12 blocks */ -#define A2DP_SBC_BLK_LEN_16 BIT(4) /**< 16 blocks */ -/** @} */ - -/** - * @name Subbands - * @{ - */ -#define A2DP_SBC_SUBBAND_4 BIT(3) /**< 4 subbands */ -#define A2DP_SBC_SUBBAND_8 BIT(2) /**< 8 subbands */ -/** @} */ - -/** - * @name Bit pool Allocation Method - * @{ - */ -#define A2DP_SBC_ALLOC_MTHD_SNR BIT(1) /**< Allocate based on loudness of the subband signal */ -#define A2DP_SBC_ALLOC_MTHD_LOUDNESS BIT(0) /**< Allocate based on the signal-to-noise ratio */ -/** @} */ - -/** - * Gets the sampling rate from a codec preset - * @param preset Codec preset - */ -#define BT_A2DP_SBC_SAMP_FREQ(preset) ((preset->config[0] >> 4) & 0x0f) -/** - * Gets the channel mode from a codec preset - * @param preset Codec preset - */ -#define BT_A2DP_SBC_CHAN_MODE(preset) ((preset->config[0]) & 0x0f) -/** - * Gets the block length from a codec preset - * @param preset Codec preset - */ -#define BT_A2DP_SBC_BLK_LEN(preset) ((preset->config[1] >> 4) & 0x0f) -/** - * Gets the number subbands from a codec preset - * @param preset Codec preset - */ -#define BT_A2DP_SBC_SUB_BAND(preset) ((preset->config[1] >> 2) & 0x03) -/** - * Gets the bitpool allocation method from a codec preset - * @param preset Codec preset - */ -#define BT_A2DP_SBC_ALLOC_MTHD(preset) ((preset->config[1]) & 0x03) - -/** @brief SBC Codec */ -struct bt_a2dp_codec_sbc_params { - /** First two octets of configuration */ - uint8_t config[2]; - /** Minimum Bitpool Value */ - uint8_t min_bitpool; - /** Maximum Bitpool Value */ - uint8_t max_bitpool; -} __packed; - -#ifdef __cplusplus -} -#endif - -#endif /* ZEPHYR_INCLUDE_BLUETOOTH_A2DP_CODEC_H_ */ diff --git a/include/zephyr/bluetooth/classic/a2dp.h b/include/zephyr/bluetooth/classic/a2dp.h index a065012280289..540899c2197b2 100644 --- a/include/zephyr/bluetooth/classic/a2dp.h +++ b/include/zephyr/bluetooth/classic/a2dp.h @@ -4,6 +4,7 @@ /* * Copyright (c) 2015-2016 Intel Corporation + * Copyright 2024 NXP * * SPDX-License-Identifier: Apache-2.0 */ @@ -12,19 +13,262 @@ #include +#include +#include #include #ifdef __cplusplus extern "C" { #endif -/** @brief Stream Structure */ -struct bt_a2dp_stream { - /* TODO */ +#define BT_A2DP_STREAM_BUF_RESERVE (12u + BT_L2CAP_BUF_SIZE(0)) + +/** SBC IE length */ +#define BT_A2DP_SBC_IE_LENGTH (4u) +/** MPEG1,2 IE length */ +#define BT_A2DP_MPEG_1_2_IE_LENGTH (4u) +/** MPEG2,4 IE length */ +#define BT_A2DP_MPEG_2_4_IE_LENGTH (6u) +/** The max IE (Codec Info Element) length */ +#define A2DP_MAX_IE_LENGTH (8U) + +/** @brief define the audio endpoint + * @param _role BT_AVDTP_SOURCE or BT_AVDTP_SINK. + * @param _codec value of enum bt_a2dp_codec_id. + * @param _capability the codec capability. + */ +#define BT_A2DP_EP_INIT(_role, _codec, _capability)\ +{\ + .codec_type = _codec,\ + .sep = {.sep_info = {.media_type = BT_AVDTP_AUDIO, .tsep = _role}},\ + .codec_cap = _capability,\ + .stream = NULL,\ +} + +/** @brief define the audio sink endpoint + * @param _codec value of enum bt_a2dp_codec_id. + * @param _capability the codec capability. + */ +#define BT_A2DP_SINK_EP_INIT(_codec, _capability)\ +BT_A2DP_EP_INIT(BT_AVDTP_SINK, _codec, _capability) + +/** @brief define the audio source endpoint + * @param _codec value of enum bt_a2dp_codec_id. + * @param _capability the codec capability. + */ +#define BT_A2DP_SOURCE_EP_INIT(_codec, _capability)\ +BT_A2DP_EP_INIT(BT_AVDTP_SOURCE, _codec, _capability) + +/** @brief define the SBC sink endpoint that can be used as + * bt_a2dp_register_endpoint's parameter. + * + * SBC is mandatory as a2dp specification, BT_A2DP_SBC_SINK_EP_DEFAULT + * is more convenient for user to register SBC endpoint. + * + * @param _freq sbc codec frequency. + * for example: A2DP_SBC_SAMP_FREQ_44100 | A2DP_SBC_SAMP_FREQ_48000 + * @param _ch_mode sbc codec channel mode. + * for example: A2DP_SBC_CH_MODE_MONO | A2DP_SBC_CH_MODE_STREO + * @param _blk_len sbc codec block length. + * for example: A2DP_SBC_BLK_LEN_16 + * @param _subband sbc codec subband. + * for example: A2DP_SBC_SUBBAND_8 + * @param _alloc_mthd sbc codec allocate method. + * for example: A2DP_SBC_ALLOC_MTHD_LOUDNESS + * @param _min_bitpool sbc codec min bit pool. for example: 18 + * @param _max_bitpool sbc codec max bit pool. for example: 35 + * @ + */ +#define BT_A2DP_SBC_SINK_EP(_name, _freq, _ch_mode, _blk_len, _subband,\ +_alloc_mthd, _min_bitpool, _max_bitpool)\ +static struct bt_a2dp_codec_ie bt_a2dp_ep_cap_ie##_name =\ +{.len = BT_A2DP_SBC_IE_LENGTH, .codec_ie = {_freq | _ch_mode,\ +_blk_len | _subband | _alloc_mthd, _min_bitpool, _max_bitpool}};\ +static struct bt_a2dp_ep _name = BT_A2DP_SINK_EP_INIT(BT_A2DP_SBC,\ +(&bt_a2dp_ep_cap_ie##_name)) + +/** @brief define the SBC source endpoint that can be used as bt_a2dp_register_endpoint's + * parameter. + * + * SBC is mandatory as a2dp specification, BT_A2DP_SBC_SOURCE_EP_DEFAULT + * is more convenient for user to register SBC endpoint. + * + * @param _name the endpoint variable name. + * @param _freq sbc codec frequency. + * for example: A2DP_SBC_SAMP_FREQ_44100 | A2DP_SBC_SAMP_FREQ_48000 + * @param _ch_mode sbc codec channel mode. + * for example: A2DP_SBC_CH_MODE_MONO | A2DP_SBC_CH_MODE_STREO + * @param _blk_len sbc codec block length. + * for example: A2DP_SBC_BLK_LEN_16 + * @param _subband sbc codec subband. + * for example: A2DP_SBC_SUBBAND_8 + * @param _alloc_mthd sbc codec allocate method. + * for example: A2DP_SBC_ALLOC_MTHD_LOUDNESS + * @param _min_bitpool sbc codec min bit pool. for example: 18 + * @param _max_bitpool sbc codec max bit pool. for example: 35 + */ +#define BT_A2DP_SBC_SOURCE_EP(_name, _freq, _ch_mode, _blk_len, _subband,\ +_alloc_mthd, _min_bitpool, _max_bitpool)\ +static struct bt_a2dp_codec_ie bt_a2dp_ep_cap_ie##_name =\ +{.len = BT_A2DP_SBC_IE_LENGTH, .codec_ie = {_freq | _ch_mode,\ +_blk_len | _subband | _alloc_mthd, _min_bitpool, _max_bitpool}};\ +static struct bt_a2dp_ep _name = BT_A2DP_SOURCE_EP_INIT(BT_A2DP_SBC,\ +&bt_a2dp_ep_cap_ie##_name) + +/** @brief define the default SBC sink endpoint that can be used as + * bt_a2dp_register_endpoint's parameter. + * + * SBC is mandatory as a2dp specification, BT_A2DP_SBC_SINK_EP_DEFAULT + * is more convenient for user to register SBC endpoint. + * + * @param _name the endpoint variable name. + */ +#define BT_A2DP_SBC_SINK_EP_DEFAULT(_name)\ +static struct bt_a2dp_codec_ie bt_a2dp_ep_cap_ie##_name =\ +{.len = BT_A2DP_SBC_IE_LENGTH, .codec_ie = {A2DP_SBC_SAMP_FREQ_44100 |\ +A2DP_SBC_SAMP_FREQ_48000 | A2DP_SBC_CH_MODE_MONO | A2DP_SBC_CH_MODE_STREO |\ +A2DP_SBC_CH_MODE_JOINT, A2DP_SBC_BLK_LEN_16 |\ +A2DP_SBC_SUBBAND_8 | A2DP_SBC_ALLOC_MTHD_LOUDNESS, 18U, 35U}};\ +static struct bt_a2dp_ep _name = BT_A2DP_SINK_EP_INIT(BT_A2DP_SBC,\ +&bt_a2dp_ep_cap_ie##_name) + +/** @brief define the default SBC source endpoint that can be used as bt_a2dp_register_endpoint's + * parameter. + * + * SBC is mandatory as a2dp specification, BT_A2DP_SBC_SOURCE_EP_DEFAULT + * is more convenient for user to register SBC endpoint. + * + * @param _name the endpoint variable name. + */ +#define BT_A2DP_SBC_SOURCE_EP_DEFAULT(_name)\ +static struct bt_a2dp_codec_ie bt_a2dp_ep_cap_ie##_name =\ +{.len = BT_A2DP_SBC_IE_LENGTH, .codec_ie = {A2DP_SBC_SAMP_FREQ_44100 | \ +A2DP_SBC_SAMP_FREQ_48000 | A2DP_SBC_CH_MODE_MONO | A2DP_SBC_CH_MODE_STREO | \ +A2DP_SBC_CH_MODE_JOINT, A2DP_SBC_BLK_LEN_16 | A2DP_SBC_SUBBAND_8 | A2DP_SBC_ALLOC_MTHD_LOUDNESS,\ +18U, 35U},};\ +static struct bt_a2dp_ep _name = BT_A2DP_SOURCE_EP_INIT(BT_A2DP_SBC,\ +&bt_a2dp_ep_cap_ie##_name) + +/** @brief define the SBC default configuration. + * + * @param _freq_cfg sbc codec frequency. + * for example: A2DP_SBC_SAMP_FREQ_44100 + * @param _ch_mode_cfg sbc codec channel mode. + * for example: A2DP_SBC_CH_MODE_JOINT + * @param _blk_len_cfg sbc codec block length. + * for example: A2DP_SBC_BLK_LEN_16 + * @param _subband_cfg sbc codec subband. + * for example: A2DP_SBC_SUBBAND_8 + * @param _alloc_mthd_cfg sbc codec allocate method. + * for example: A2DP_SBC_ALLOC_MTHD_LOUDNESS + * @param _min_bitpool_cfg sbc codec min bit pool. for example: 18 + * @param _max_bitpool_cfg sbc codec max bit pool. for example: 35 + */ +#define BT_A2DP_SBC_EP_CFG(_name, _freq_cfg, _ch_mode_cfg, _blk_len_cfg, _subband_cfg,\ +_alloc_mthd_cfg, _min_bitpool_cfg, _max_bitpool_cfg)\ +static struct bt_a2dp_codec_ie bt_a2dp_codec_ie##_name = {\ +.len = BT_A2DP_SBC_IE_LENGTH, .codec_ie = {_freq_cfg | _ch_mode_cfg,\ +_blk_len_cfg | _subband_cfg | _alloc_mthd_cfg, _min_bitpool_cfg, _max_bitpool_cfg},};\ +struct bt_a2dp_codec_cfg _name = {.codec_config = &bt_a2dp_codec_ie##_name,} + +/** @brief define the SBC default configuration. + * + * @param _freq_cfg the frequency to configure the remote same codec type endpoint. + */ +#define BT_A2DP_SBC_EP_CFG_DEFAULT(_name, _freq_cfg)\ +static struct bt_a2dp_codec_ie bt_a2dp_codec_ie##_name = {\ +.len = BT_A2DP_SBC_IE_LENGTH, .codec_ie = {_freq_cfg | A2DP_SBC_CH_MODE_JOINT,\ +A2DP_SBC_BLK_LEN_16 | A2DP_SBC_SUBBAND_8 | A2DP_SBC_ALLOC_MTHD_LOUDNESS, 18U, 35U},};\ +struct bt_a2dp_codec_cfg _name = {.codec_config = &bt_a2dp_codec_ie##_name,} + +/** + * @brief A2DP error code + */ +enum bt_a2dp_err_code { + /** Media Codec Type is not valid */ + BT_A2DP_INVALID_CODEC_TYPE = 0xC1, + /** Media Codec Type is not supported */ + BT_A2DP_NOT_SUPPORTED_CODEC_TYPE = 0xC2, + /** Sampling Frequency is not valid or multiple values have been selected */ + BT_A2DP_INVALID_SAMPLING_FREQUENCY = 0xC3, + /** Sampling Frequency is not supported */ + BT_A2DP_NOT_SUPPORTED_SAMPLING_FREQUENCY = 0xC4, + /** Channel Mode is not valid or multiple values have been selected */ + BT_A2DP_INVALID_CHANNEL_MODE = 0xC5, + /** Channel Mode is not supported */ + BT_A2DP_NOT_SUPPORTED_CHANNEL_MODE = 0xC6, + /** None or multiple values have been selected for Number of Subbands */ + BT_A2DP_INVALID_SUBBANDS = 0xC7, + /** Number of Subbands is not supported */ + BT_A2DP_NOT_SUPPORTED_SUBBANDS = 0xC8, + /** None or multiple values have been selected for Allocation Method */ + BT_A2DP_INVALID_ALLOCATION_METHOD = 0xC9, + /** Allocation Method is not supported */ + BT_A2DP_NOT_SUPPORTED_ALLOCATION_METHOD = 0xCA, + /** Minimum Bitpool Value is not valid */ + BT_A2DP_INVALID_MINIMUM_BITPOOL_VALUE = 0xCB, + /** Minimum Bitpool Value is not supported */ + BT_A2DP_NOT_SUPPORTED_MINIMUM_BITPOOL_VALUE = 0xCC, + /** Maximum Bitpool Value is not valid */ + BT_A2DP_INVALID_MAXIMUM_BITPOOL_VALUE = 0xCD, + /** Maximum Bitpool Value is not supported */ + BT_A2DP_NOT_SUPPORTED_MAXIMUM_BITPOOL_VALUE = 0xCE, + /** None or multiple values have been selected for Layer */ + BT_A2DP_INVALID_LAYER = 0xCF, + /** Layer is not supported */ + BT_A2DP_NOT_SUPPORTED_LAYER = 0xD0, + /** CRC is not supported */ + BT_A2DP_NOT_SUPPORTED_CRC = 0xD1, + /** MPF-2 is not supported */ + BT_A2DP_NOT_SUPPORTED_MPF = 0xD2, + /** VBR is not supported */ + BT_A2DP_NOT_SUPPORTED_VBR = 0xD3, + /** None or multiple values have been selected for Bit Rate */ + BT_A2DP_INVALID_BIT_RATE = 0xD4, + /** Bit Rate is not supported */ + BT_A2DP_NOT_SUPPORTED_BIT_RATE = 0xD5, + /** Either 1) Object type is not valid or + * 2) None or multiple values have been selected for Object Type + */ + BT_A2DP_INVALID_OBJECT_TYPE = 0xD6, + /** Object Type is not supported */ + BT_A2DP_NOT_SUPPORTED_OBJECT_TYPE = 0xD7, + /** Either 1) Channels is not valid or + * 2) None or multiple values have been selected for Channels + */ + BT_A2DP_INVALID_CHANNELS = 0xD8, + /** Channels is not supported */ + BT_A2DP_NOT_SUPPORTED_CHANNELS = 0xD9, + /** Version is not valid */ + BT_A2DP_INVALID_VERSION = 0xDA, + /** Version is not supported */ + BT_A2DP_NOT_SUPPORTED_VERSION = 0xDB, + /** Maximum SUL is not acceptable for the Decoder in the SNK */ + BT_A2DP_NOT_SUPPORTED_MAXIMUM_SUL = 0xDC, + /** None or multiple values have been selected for Block Length */ + BT_A2DP_INVALID_BLOCK_LENGTH = 0xDD, + /** The requested CP Type is not supported */ + BT_A2DP_INVALID_CP_TYPE = 0xE0, + /** The format of Content Protection Service Capability/Content + * Protection Scheme Dependent Data is not correct + */ + BT_A2DP_INVALID_CP_FORMAT = 0xE1, + /** The codec parameter is invalid. + * Used if a more specific error code does not exist for the codec in use + */ + BT_A2DP_INVALID_CODEC_PARAMETER = 0xE2, + /** The codec parameter is not supported. + * Used if a more specific error code does not exist for the codec in use + */ + BT_A2DP_NOT_SUPPORTED_CODEC_PARAMETER = 0xE3, + /** Combination of Object Type and DRC is invalid */ + BT_A2DP_INVALID_DRC = 0xE4, + /** DRC is not supported */ + BT_A2DP_NOT_SUPPORTED_DRC = 0xE5, }; -/** @brief Codec ID */ -enum bt_a2dp_codec_id { +/** @brief Codec Type */ +enum bt_a2dp_codec_type { /** Codec SBC */ BT_A2DP_SBC = 0x00, /** Codec MPEG-1 */ @@ -37,52 +281,266 @@ enum bt_a2dp_codec_id { BT_A2DP_VENDOR = 0xff }; -/** @brief Preset for the endpoint */ -struct bt_a2dp_preset { - /** Length of preset */ +/** @brief A2DP structure */ +struct bt_a2dp; + +/* Internal to pass build */ +struct bt_a2dp_stream; + +/** @brief codec information elements for the endpoint */ +struct bt_a2dp_codec_ie { + /** Length of codec_cap */ uint8_t len; - /** Preset */ - uint8_t preset[0]; + /** codec information element */ + uint8_t codec_ie[A2DP_MAX_IE_LENGTH]; +}; + +/** @brief The endpoint configuration */ +struct bt_a2dp_codec_cfg { + /** The media codec configuration content */ + struct bt_a2dp_codec_ie *codec_config; }; /** @brief Stream End Point */ -struct bt_a2dp_endpoint { - /** Code ID */ - uint8_t codec_id; - /** Stream End Point Information */ - struct bt_avdtp_seid_lsep info; - /** Pointer to preset codec chosen */ - struct bt_a2dp_preset *preset; +struct bt_a2dp_ep { + /** Code Type @ref bt_a2dp_codec_type */ + uint8_t codec_type; /** Capabilities */ - struct bt_a2dp_preset *caps; + struct bt_a2dp_codec_ie *codec_cap; + /** AVDTP Stream End Point Identifier */ + struct bt_avdtp_sep sep; + /* Internally used stream object pointer */ + struct bt_a2dp_stream *stream; }; -/** @brief Stream End Point Media Type */ -enum MEDIA_TYPE { - /** Audio Media Type */ - BT_A2DP_AUDIO = 0x00, - /** Video Media Type */ - BT_A2DP_VIDEO = 0x01, - /** Multimedia Media Type */ - BT_A2DP_MULTIMEDIA = 0x02 +struct bt_a2dp_ep_info { + /** Code Type @ref bt_a2dp_codec_type */ + uint8_t codec_type; + /** Codec capabilities, if SBC, use function of a2dp_codec_sbc.h to parse it */ + struct bt_a2dp_codec_ie codec_cap; + /** Stream End Point Information */ + struct bt_avdtp_sep_info sep_info; }; -/** @brief Stream End Point Role */ -enum ROLE_TYPE { - /** Source Role */ - BT_A2DP_SOURCE = 0, - /** Sink Role */ - BT_A2DP_SINK = 1 +/** @brief Helper enum to be used as return value of bt_a2dp_discover_ep_cb. + * The value informs the caller to perform further pending actions or stop them. + */ +enum { + BT_A2DP_DISCOVER_EP_STOP = 0, + BT_A2DP_DISCOVER_EP_CONTINUE, }; -/** @brief A2DP structure */ -struct bt_a2dp; +/** @typedef bt_a2dp_discover_ep_cb + * + * @brief Called when a stream endpoint is discovered. + * + * A function of this type is given by the user to the bt_a2dp_discover_param + * object. It'll be called on each valid stream endpoint discovery completion. + * When no more endpoint then NULL is passed to the user. Otherwise user can get + * valid endpoint information from parameter info, user can set parameter ep to + * get the endpoint after the callback is return. + * The returned function value allows the user to control retrieving follow-up + * endpoints if any. If the user doesn't want to read more endpoints since + * current found endpoints fulfill its requirements then should return + * BT_A2DP_DISCOVER_EP_STOP. Otherwise returned value means + * more subcall iterations are allowable. + * + * @param a2dp a2dp connection object identifying a2dp connection to queried remote. + * @param info Object pointing to the information of the callbacked endpoint. + * @param ep If the user want to use this found endpoint, user can set value to it + * to get the ednpoint that can be used futher in other A2DP APIs. It is NULL if info + * is NULL (no more endpoint is found). + * + * @return BT_A2DP_DISCOVER_EP_STOP in case of no more need to continue discovery + * for next endpoint. By returning BT_A2DP_DISCOVER_EP_STOP user allows this + * discovery continuation. + */ +typedef uint8_t (*bt_a2dp_discover_ep_cb)(struct bt_a2dp *a2dp, + struct bt_a2dp_ep_info *info, struct bt_a2dp_ep **ep); + +struct bt_a2dp_discover_param { + /** discover callback */ + bt_a2dp_discover_ep_cb cb; + /** The discovered endpoint info that is callbacked by cb */ + struct bt_a2dp_ep_info info; + /** The max count of remote endpoints that can be got, + * it save endpoint info internally. + */ + struct bt_avdtp_sep_info *seps_info; + /** The max count of seps (strem endpoint) that can be got in this call route */ + uint8_t sep_count; +}; + +/** @brief The connecting callback */ +struct bt_a2dp_cb { + /** @brief A a2dp connection has been established. + * + * This callback notifies the application of a a2dp connection. + * It means the AVDTP L2CAP connection. + * In case the err parameter is non-zero it means that the + * connection establishment failed. + * + * @param a2dp a2dp connection object. + * @param err error code. + */ + void (*connected)(struct bt_a2dp *a2dp, int err); + /** @brief A a2dp connection has been disconnected. + * + * This callback notifies the application that a a2dp connection + * has been disconnected. + * + * @param a2dp a2dp connection object. + */ + void (*disconnected)(struct bt_a2dp *a2dp); + /** + * @brief Endpoint config request callback + * + * The callback is called whenever an endpoint is requested to be + * configured. + * + * @param a2dp a2dp connection object. + * @param[in] ep Local Audio Endpoint being configured. + * @param[in] codec_cfg Codec configuration. + * @param[out] stream Pointer to stream that will be configured for the endpoint. + * @param[out] rsp_err_code give the error code if response error. + * bt_a2dp_err_code or bt_avdtp_err_code + * + * @return 0 in case of success or negative value in case of error. + */ + int (*config_req)(struct bt_a2dp *a2dp, struct bt_a2dp_ep *ep, + struct bt_a2dp_codec_cfg *codec_cfg, struct bt_a2dp_stream **stream, + uint8_t *rsp_err_code); + /** @brief Callback function for bt_a2dp_stream_config() + * + * Called when the codec configure operation is completed. + * + * @param[in] stream Pointer to stream object. + * @param[in] rsp_err_code the remote responsed error code + * bt_a2dp_err_code or bt_avdtp_err_code + */ + void (*config_rsp)(struct bt_a2dp_stream *stream, uint8_t rsp_err_code); + /** + * @brief stream establishment request callback + * + * The callback is called whenever an stream is requested to be + * established (open cmd and create the stream l2cap channel). + * + * @param[in] stream Pointer to stream object. + * @param[out] rsp_err_code give the error code if response error. + * bt_a2dp_err_code or bt_avdtp_err_code + * + * @return 0 in case of success or negative value in case of error. + */ + int (*establish_req)(struct bt_a2dp_stream *stream, uint8_t *rsp_err_code); + /** @brief Callback function for bt_a2dp_stream_establish() + * + * Called when the establishment operation is completed. + * (open cmd and create the stream l2cap channel). + * + * @param[in] stream Pointer to stream object. + * @param[in] rsp_err_code the remote responsed error code + * bt_a2dp_err_code or bt_avdtp_err_code + */ + void (*establish_rsp)(struct bt_a2dp_stream *stream, uint8_t rsp_err_code); + /** + * @brief stream release request callback + * + * The callback is called whenever an stream is requested to be + * released (release cmd and release the l2cap channel) + * + * @param[in] stream Pointer to stream object. + * @param[out] rsp_err_code give the error code if response error. + * bt_a2dp_err_code or bt_avdtp_err_code + * + * @return 0 in case of success or negative value in case of error. + */ + int (*release_req)(struct bt_a2dp_stream *stream, uint8_t *rsp_err_code); + /** @brief Callback function for bt_a2dp_stream_release() + * + * Called when the release operation is completed. + * (release cmd and release the l2cap channel) + * + * @param[in] stream Pointer to stream object. + * @param[in] rsp_err_code the remote responsed error code + * bt_a2dp_err_code or bt_avdtp_err_code + */ + void (*release_rsp)(struct bt_a2dp_stream *stream, uint8_t rsp_err_code); + /** + * @brief stream start request callback + * + * The callback is called whenever an stream is requested to be + * started. + * + * @param[in] stream Pointer to stream object. + * @param[out] rsp_err_code give the error code if response error. + * bt_a2dp_err_code or bt_avdtp_err_code + * + * @return 0 in case of success or negative value in case of error. + */ + int (*start_req)(struct bt_a2dp_stream *stream, uint8_t *rsp_err_code); + /** @brief Callback function for bt_a2dp_stream_start() + * + * Called when the start operation is completed. + * + * @param[in] stream Pointer to stream object. + * @param[in] rsp_err_code the remote responsed error code + * bt_a2dp_err_code or bt_avdtp_err_code + */ + void (*start_rsp)(struct bt_a2dp_stream *stream, uint8_t rsp_err_code); + /** + * @brief Endpoint suspend request callback + * + * The callback is called whenever an stream is requested to be + * suspended. + * + * @param[in] stream Pointer to stream object. + * @param[out] rsp_err_code give the error code if response error. + * bt_a2dp_err_code or bt_avdtp_err_code + * + * @return 0 in case of success or negative value in case of error. + */ + int (*suspend_req)(struct bt_a2dp_stream *stream, uint8_t *rsp_err_code); + /** @brief Callback function for bt_a2dp_stream_suspend() + * + * Called when the suspend operation is completed. + * + * @param[in] stream Pointer to stream object. + * @param[in] rsp_err_code the remote responsed error code + * bt_a2dp_err_code or bt_avdtp_err_code + */ + void (*suspend_rsp)(struct bt_a2dp_stream *stream, uint8_t rsp_err_code); + /** + * @brief Endpoint config request callback + * + * The callback is called whenever an endpoint is requested to be + * reconfigured. + * + * @param[in] stream Pointer to stream object. + * @param[out] rsp_err_code give the error code if response error. + * bt_a2dp_err_code or bt_avdtp_err_code + * + * @return 0 in case of success or negative value in case of error. + */ + int (*reconfig_req)(struct bt_a2dp_stream *stream, uint8_t *rsp_err_code); + /** @brief Callback function for bt_a2dp_stream_reconfig() + * + * Called when the reconfig operation is completed. + * + * @param[in] stream Pointer to stream object. + * @param[in] rsp_err_code the remote responsed error code + * bt_a2dp_err_code or bt_avdtp_err_code + */ + void (*reconfig_rsp)(struct bt_a2dp_stream *stream, uint8_t rsp_err_code); +}; /** @brief A2DP Connect. * * This function is to be called after the conn parameter is obtained by * performing a GAP procedure. The API is to be used to establish A2DP * connection between devices. + * This function only establish AVDTP L2CAP Signaling connection. + * After connection success, the callback that is registered by + * bt_a2dp_register_connect_callback is called. * * @param conn Pointer to bt_conn structure. * @@ -91,20 +549,242 @@ struct bt_a2dp; */ struct bt_a2dp *bt_a2dp_connect(struct bt_conn *conn); -/** @brief Endpoint Registration. +/** @brief disconnect l2cap a2dp + * + * This function close AVDTP L2CAP Signaling connection. + * It closes the AVDTP L2CAP Media connection too if it is established. * - * This function is used for registering the stream end points. The user has - * to take care of allocating the memory, the preset pointer and then pass the - * required arguments. Also, only one sep can be registered at a time. + * @param a2dp The a2dp instance. + * + * @return 0 in case of success and error code in case of error. + */ +int bt_a2dp_disconnect(struct bt_a2dp *a2dp); + +/** @brief Endpoint Registration. * - * @param endpoint Pointer to bt_a2dp_endpoint structure. + * @param ep Pointer to bt_a2dp_ep structure. * @param media_type Media type that the Endpoint is. * @param role Role of Endpoint. * * @return 0 in case of success and error code in case of error. */ -int bt_a2dp_register_endpoint(struct bt_a2dp_endpoint *endpoint, - uint8_t media_type, uint8_t role); +int bt_a2dp_register_ep(struct bt_a2dp_ep *ep, uint8_t media_type, uint8_t role); + +/** @brief register callback. + * + * The cb is called when bt_a2dp_connect is called or it is operated by remote device. + * + * @param cb The callback function. + * + * @return 0 in case of success and error code in case of error. + */ +int bt_a2dp_register_cb(struct bt_a2dp_cb *cb); + +/** @brief Discover remote endpoints. + * + * @param a2dp The a2dp instance. + * @param param the discover used param. + * + * @return 0 in case of success and error code in case of error. + */ +int bt_a2dp_discover(struct bt_a2dp *a2dp, struct bt_a2dp_discover_param *param); + +/** @brief A2DP Stream */ +struct bt_a2dp_stream { + /** local endpoint */ + struct bt_a2dp_ep *local_ep; + /** remote endpoint */ + struct bt_a2dp_ep *remote_ep; + /** remote endpoint's Stream End Point ID */ + uint8_t remote_ep_id; + /** Audio stream operations */ + struct bt_a2dp_stream_ops *ops; + /** the a2dp connection */ + struct bt_a2dp *a2dp; + /** the stream current configuration */ + struct bt_a2dp_codec_ie codec_config; +}; + +/** @brief The stream endpoint related operations */ +struct bt_a2dp_stream_ops { + /** + * @brief Stream configured callback + * + * The callback is called whenever an Audio Stream has been configured. + * + * @param stream Stream object that has been configured. + */ + void (*configured)(struct bt_a2dp_stream *stream); + /** + * @brief Stream establishment callback + * + * The callback is called whenever an Audio Stream has been established. + * + * @param stream Stream object that has been established. + */ + void (*established)(struct bt_a2dp_stream *stream); + /** + * @brief Stream release callback + * + * The callback is called whenever an Audio Stream has been released. + * + * @param stream Stream object that has been released. + */ + void (*released)(struct bt_a2dp_stream *stream); + /** + * @brief Stream start callback + * + * The callback is called whenever an Audio Stream has been started. + * + * @param stream Stream object that has been started. + */ + void (*started)(struct bt_a2dp_stream *stream); + /** + * @brief Stream suspend callback + * + * The callback is called whenever an Audio Stream has been suspended. + * + * @param stream Stream object that has been suspended. + */ + void (*suspended)(struct bt_a2dp_stream *stream); + /** + * @brief Stream reconfigured callback + * + * The callback is called whenever an Audio Stream has been reconfigured. + * + * @param stream Stream object that has been reconfigured. + */ + void (*reconfigured)(struct bt_a2dp_stream *stream); +#if defined(CONFIG_BT_A2DP_SINK) + /** @brief the media streaming data, only for sink + * + * @param buf the data buf + * @param seq_num the seqence number + * @param ts the time stamp + */ + void (*recv)(struct bt_a2dp_stream *stream, + struct net_buf *buf, uint16_t seq_num, uint32_t ts); +#endif +#if defined(CONFIG_BT_A2DP_SOURCE) + /** + * @brief Stream audio HCI sent callback + * + * This callback will be called once the controller marks the SDU + * as completed. When the controller does so is implementation + * dependent. It could be after the SDU is enqueued for transmission, + * or after it is sent on air or flushed. + * + * This callback is only used if the ISO data path is HCI. + * + * @param stream Stream object. + */ + void (*sent)(struct bt_a2dp_stream *stream); +#endif +}; + +/** + * @brief Register Audio callbacks for a stream. + * + * Register Audio callbacks for a stream. + * + * @param stream Stream object. + * @param ops Stream operations structure. + */ +void bt_a2dp_stream_cb_register(struct bt_a2dp_stream *stream, struct bt_a2dp_stream_ops *ops); + +/** @brief configure endpoint. + * + * bt_a2dp_discover can be used to find remote's endpoints. + * This function to configure the selected endpoint that is found by + * bt_a2dp_discover. + * This function sends AVDTP_SET_CONFIGURATION. + * + * @param a2dp The a2dp instance. + * @param stream Stream object. + * @param local_ep The configured endpoint that is registered. + * @param remote_ep The remote endpoint. + * @param config The config to configure the endpoint. + * + * @return 0 in case of success and error code in case of error. + */ +int bt_a2dp_stream_config(struct bt_a2dp *a2dp, struct bt_a2dp_stream *stream, + struct bt_a2dp_ep *local_ep, struct bt_a2dp_ep *remote_ep, + struct bt_a2dp_codec_cfg *config); + +/** @brief establish a2dp streamer. + * + * This function sends the AVDTP_OPEN command and create the l2cap channel. + * + * @param stream The stream object. + * + * @return 0 in case of success and error code in case of error. + */ +int bt_a2dp_stream_establish(struct bt_a2dp_stream *stream); + +/** @brief release a2dp streamer. + * + * This function sends the AVDTP_CLOSE command and release the l2cap channel. + * + * @param stream The stream object. + * + * @return 0 in case of success and error code in case of error. + */ +int bt_a2dp_stream_release(struct bt_a2dp_stream *stream); + +/** @brief start a2dp streamer. + * + * This function sends the AVDTP_START command. + * + * @param stream The stream object. + * + * @return 0 in case of success and error code in case of error. + */ +int bt_a2dp_stream_start(struct bt_a2dp_stream *stream); + +/** @brief suspend a2dp streamer. + * + * This function sends the AVDTP_SUSPEND command. + * + * @param stream The stream object. + * + * @return 0 in case of success and error code in case of error. + */ +int bt_a2dp_stream_suspend(struct bt_a2dp_stream *stream); + +/** @brief re-configure a2dp streamer + * + * This function sends the AVDTP_RECONFIGURE command. + * + * @param stream The stream object. + * @param config The config to configure the stream. + * + * @return 0 in case of success and error code in case of error. + */ +int bt_a2dp_stream_reconfig(struct bt_a2dp_stream *stream, struct bt_a2dp_codec_cfg *config); + +/** @brief get the stream l2cap mtu + * + * @param stream The stream object. + * + * @return mtu value + */ +uint32_t bt_a2dp_get_mtu(struct bt_a2dp_stream *stream); + +#if defined(CONFIG_BT_A2DP_SOURCE) +/** @brief send a2dp media data + * + * Only A2DP source side can call this function. + * + * @param stream The stream object. + * @param buf The data. + * @param seq_num The sequence number. + * @param ts The time stamp. + * + * @return 0 in case of success and error code in case of error. + */ +int bt_a2dp_stream_send(struct bt_a2dp_stream *stream, struct net_buf *buf, + uint16_t seq_num, uint32_t ts); +#endif #ifdef __cplusplus } diff --git a/include/zephyr/bluetooth/classic/a2dp_codec_sbc.h b/include/zephyr/bluetooth/classic/a2dp_codec_sbc.h new file mode 100644 index 0000000000000..1a96c914324c9 --- /dev/null +++ b/include/zephyr/bluetooth/classic/a2dp_codec_sbc.h @@ -0,0 +1,124 @@ +/** @file + * @brief Advance Audio Distribution Profile - SBC Codec header. + */ +/* + * SPDX-License-Identifier: Apache-2.0 + * Copyright (c) 2015-2016 Intel Corporation + * Copyright (c) 2021 NXP + * + * 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. + */ +#ifndef ZEPHYR_INCLUDE_BLUETOOTH_A2DP_CODEC_H_ +#define ZEPHYR_INCLUDE_BLUETOOTH_A2DP_CODEC_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/* Sampling Frequency */ +#define A2DP_SBC_SAMP_FREQ_16000 BIT(7) +#define A2DP_SBC_SAMP_FREQ_32000 BIT(6) +#define A2DP_SBC_SAMP_FREQ_44100 BIT(5) +#define A2DP_SBC_SAMP_FREQ_48000 BIT(4) + +/* Channel Mode */ +#define A2DP_SBC_CH_MODE_MONO BIT(3) +#define A2DP_SBC_CH_MODE_DUAL BIT(2) +#define A2DP_SBC_CH_MODE_STREO BIT(1) +#define A2DP_SBC_CH_MODE_JOINT BIT(0) + +/* Block Length */ +#define A2DP_SBC_BLK_LEN_4 BIT(7) +#define A2DP_SBC_BLK_LEN_8 BIT(6) +#define A2DP_SBC_BLK_LEN_12 BIT(5) +#define A2DP_SBC_BLK_LEN_16 BIT(4) + +/* Subbands */ +#define A2DP_SBC_SUBBAND_4 BIT(3) +#define A2DP_SBC_SUBBAND_8 BIT(2) + +/* Allocation Method */ +#define A2DP_SBC_ALLOC_MTHD_SNR BIT(1) +#define A2DP_SBC_ALLOC_MTHD_LOUDNESS BIT(0) + +#define BT_A2DP_SBC_SAMP_FREQ(cap) ((cap->config[0] >> 4) & 0x0f) +#define BT_A2DP_SBC_CHAN_MODE(cap) ((cap->config[0]) & 0x0f) +#define BT_A2DP_SBC_BLK_LEN(cap) ((cap->config[1] >> 4) & 0x0f) +#define BT_A2DP_SBC_SUB_BAND(cap) ((cap->config[1] >> 2) & 0x03) +#define BT_A2DP_SBC_ALLOC_MTHD(cap) ((cap->config[1]) & 0x03) + +/** @brief SBC Codec */ +struct bt_a2dp_codec_sbc_params { + /** First two octets of configuration */ + uint8_t config[2]; + /** Minimum Bitpool Value */ + uint8_t min_bitpool; + /** Maximum Bitpool Value */ + uint8_t max_bitpool; +} __packed; + +/** If the F bit is set to 0, this field indicates the number of frames contained + * in this packet. If the F bit is set to 1, this field indicates the number + * of remaining fragments, including the current fragment. + * Therefore, the last counter value shall be one. + */ +#define BT_A2DP_SBC_MEDIA_HDR_NUM_FRAMES_GET(hdr) FIELD_GET(GENMASK(3, 0), (hdr)) +/** Set to 1 for the last packet of a fragmented SBC frame, otherwise set to 0. */ +#define BT_A2DP_SBC_MEDIA_HDR_L_GET(hdr) FIELD_GET(BIT(5), (hdr)) +/** Set to 1 for the starting packet of a fragmented SBC frame, otherwise set to 0. */ +#define BT_A2DP_SBC_MEDIA_HDR_S_GET(hdr) FIELD_GET(BIT(6), (hdr)) +/** Set to 1 if the SBC frame is fragmented, otherwise set to 0. */ +#define BT_A2DP_SBC_MEDIA_HDR_F_GET(hdr) FIELD_GET(BIT(7), (hdr)) + +/** If the F bit is set to 0, this field indicates the number of frames contained + * in this packet. If the F bit is set to 1, this field indicates the number + * of remaining fragments, including the current fragment. + * Therefore, the last counter value shall be one. + */ +#define BT_A2DP_SBC_MEDIA_HDR_NUM_FRAMES_SET(hdr, val)\ + hdr = ((hdr) & ~GENMASK(3, 0)) | FIELD_PREP(GENMASK(3, 0), (val)) +/** Set to 1 for the last packet of a fragmented SBC frame, otherwise set to 0. */ +#define BT_A2DP_SBC_MEDIA_HDR_L_SET(hdr, val)\ + hdr = ((hdr) & ~BIT(5)) | FIELD_PREP(BIT(5), (val)) +/** Set to 1 for the starting packet of a fragmented SBC frame, otherwise set to 0. */ +#define BT_A2DP_SBC_MEDIA_HDR_S_SET(hdr, val)\ + hdr = ((hdr) & ~BIT(6)) | FIELD_PREP(BIT(6), (val)) +/** Set to 1 if the SBC frame is fragmented, otherwise set to 0. */ +#define BT_A2DP_SBC_MEDIA_HDR_F_SET(hdr, val)\ + hdr = ((hdr) & ~BIT(7)) | FIELD_PREP(BIT(7), (val)) + +#define BT_A2DP_SBC_MEDIA_HDR_ENCODE(num_frames, l, s, f)\ + FIELD_PREP(GENMASK(3, 0), num_frames) | FIELD_PREP(BIT(5), l) |\ + FIELD_PREP(BIT(6), s) | FIELD_PREP(BIT(7), f) + +/** @brief get channel num of a2dp sbc config. + * + * @param sbc_codec The a2dp sbc parameter. + * + * @return the channel num. + */ +uint8_t bt_a2dp_sbc_get_channel_num(struct bt_a2dp_codec_sbc_params *sbc_codec); + +/** @brief get sample rate of a2dp sbc config. + * + * @param sbc_codec The a2dp sbc parameter. + * + * @return the sample rate. + */ +uint32_t bt_a2dp_sbc_get_sampling_frequency(struct bt_a2dp_codec_sbc_params *sbc_codec); + +#ifdef __cplusplus +} +#endif + +#endif /* ZEPHYR_INCLUDE_BLUETOOTH_A2DP_CODEC_H_ */ diff --git a/include/zephyr/bluetooth/classic/avdtp.h b/include/zephyr/bluetooth/classic/avdtp.h index 396025814b806..cfd419239783e 100644 --- a/include/zephyr/bluetooth/classic/avdtp.h +++ b/include/zephyr/bluetooth/classic/avdtp.h @@ -4,49 +4,137 @@ /* * Copyright (c) 2015-2016 Intel Corporation + * Copyright 2024 NXP * * SPDX-License-Identifier: Apache-2.0 */ #ifndef ZEPHYR_INCLUDE_BLUETOOTH_AVDTP_H_ #define ZEPHYR_INCLUDE_BLUETOOTH_AVDTP_H_ -#include - #ifdef __cplusplus extern "C" { #endif -/** @brief AVDTP SEID Information */ -struct bt_avdtp_seid_info { - /** Stream End Point ID */ - uint8_t id:6; +/** + * @brief AVDTP error code + */ +enum bt_avdtp_err_code { + /** The response is success, it is not from avdtp spec. */ + BT_AVDTP_SUCCESS = 0x00, + /** The request is time out without response, it is not from avdtp spec. */ + BT_AVDTP_TIME_OUT = 0xFF, + /** The request packet header format error */ + BT_AVDTP_BAD_HEADER_FORMAT = 0x01, + /** The request packet length is not match the assumed length */ + BT_AVDTP_BAD_LENGTH = 0x11, + /** The requested command indicates an invalid ACP SEID (not addressable) */ + BT_AVDTP_BAD_ACP_SEID = 0x12, + /** The SEP is in use */ + BT_AVDTP_SEP_IN_USE = 0x13, + /** The SEP is not in use */ + BT_AVDTP_SEP_NOT_IN_USE = 0x14, + /** The value of Service Category in the request packet is not defined in AVDTP */ + BT_AVDTP_BAD_SERV_CATEGORY = 0x17, + /** The requested command has an incorrect payload format */ + BT_AVDTP_BAD_PAYLOAD_FORMAT = 0x18, + /** The requested command is not supported by the device */ + BT_AVDTP_NOT_SUPPORTED_COMMAND = 0x19, + /** The reconfigure command is an attempt to reconfigure a transport service codec_cap + * of the SEP. Reconfigure is only permitted for application service codec_cap + */ + BT_AVDTP_INVALID_CAPABILITIES = 0x1A, + /** The requested Recovery Type is not defined in AVDTP */ + BT_AVDTP_BAD_RECOVERY_TYPE = 0x22, + /** The format of Media Transport Capability is not correct */ + BT_AVDTP_BAD_MEDIA_TRANSPORT_FORMAT = 0x23, + /** The format of Recovery Service Capability is not correct */ + BT_AVDTP_BAD_RECOVERY_FORMAT = 0x25, + /** The format of Header Compression Service Capability is not correct */ + BT_AVDTP_BAD_ROHC_FORMAT = 0x26, + /** The format of Content Protection Service Capability is not correct */ + BT_AVDTP_BAD_CP_FORMAT = 0x27, + /** The format of Multiplexing Service Capability is not correct */ + BT_AVDTP_BAD_MULTIPLEXING_FORMAT = 0x28, + /** Configuration not supported */ + BT_AVDTP_UNSUPPORTED_CONFIGURAION = 0x29, + /** Indicates that the ACP state machine is in an invalid state in order to process the + * signal. This also includes the situation when an INT receives a request for the + * same command that it is currently expecting a response + */ + BT_AVDTP_BAD_STATE = 0x31, +}; + +/** @brief Stream End Point Type */ +enum bt_avdtp_sep_type { + /** Source Role */ + BT_AVDTP_SOURCE = 0, + /** Sink Role */ + BT_AVDTP_SINK = 1 +}; + +/** @brief Stream End Point Media Type */ +enum bt_avdtp_media_type { + /** Audio Media Type */ + BT_AVDTP_AUDIO = 0x00, + /** Video Media Type */ + BT_AVDTP_VIDEO = 0x01, + /** Multimedia Media Type */ + BT_AVDTP_MULTIMEDIA = 0x02 +}; + +/** @brief AVDTP stream endpoint information. + * Don't need to care endianness because it is not used for data parsing. + */ +struct bt_avdtp_sep_info { /** End Point usage status */ uint8_t inuse:1; + /** Stream End Point ID that is the identifier of the stream endpoint */ + uint8_t id:6; /** Reserved */ - uint8_t rfa0:1; - /** Media-type of the End Point */ - uint8_t media_type:4; - /** TSEP of the End Point */ - uint8_t tsep:1; - /** Reserved */ - uint8_t rfa1:3; -} __packed; + uint8_t reserved:1; + /** Stream End-point Type that indicates if the stream end-point is SNK or SRC */ + enum bt_avdtp_sep_type tsep; + /** Media-type of the End Point + * Only @ref BT_AVDTP_AUDIO is supported now. + */ + enum bt_avdtp_media_type media_type; +}; -/** @brief AVDTP Local SEP*/ -struct bt_avdtp_seid_lsep { - /** Stream End Point information */ - struct bt_avdtp_seid_info sep; - /** Pointer to next local Stream End Point structure */ - struct bt_avdtp_seid_lsep *next; +/** @brief service category Type */ +enum bt_avdtp_service_category { + /** Media Transport */ + BT_AVDTP_SERVICE_MEDIA_TRANSPORT = 0x01, + /** Reporting */ + BT_AVDTP_SERVICE_REPORTING = 0x02, + /** Recovery */ + BT_AVDTP_SERVICE_MEDIA_RECOVERY = 0x03, + /** Content Protection */ + BT_AVDTP_SERVICE_CONTENT_PROTECTION = 0x04, + /** Header Compression */ + BT_AVDTP_SERVICE_HEADER_COMPRESSION = 0x05, + /** Multiplexing */ + BT_AVDTP_SERVICE_MULTIPLEXING = 0x06, + /** Media Codec */ + BT_AVDTP_SERVICE_MEDIA_CODEC = 0x07, + /** Delay Reporting */ + BT_AVDTP_SERVICE_DELAY_REPORTING = 0x08, }; -/** @brief AVDTP Stream */ -struct bt_avdtp_stream { - struct bt_l2cap_br_chan chan; /* Transport Channel*/ - struct bt_avdtp_seid_info lsep; /* Configured Local SEP */ - struct bt_avdtp_seid_info rsep; /* Configured Remote SEP*/ - uint8_t state; /* current state of the stream */ - struct bt_avdtp_stream *next; +/** @brief AVDTP Stream End Point */ +struct bt_avdtp_sep { + /** Stream End Point information */ + struct bt_avdtp_sep_info sep_info; + /** Media Transport Channel*/ + struct bt_l2cap_br_chan chan; + /** the endpoint media data */ + void (*media_data_cb)(struct bt_avdtp_sep *sep, + struct net_buf *buf); + /** avdtp session */ + struct bt_avdtp *session; + /** SEP state */ + uint8_t state; + /* Internally used list node */ + sys_snode_t _node; }; #ifdef __cplusplus diff --git a/subsys/bluetooth/host/classic/CMakeLists.txt b/subsys/bluetooth/host/classic/CMakeLists.txt index 039f961c78627..001bdb86f3153 100644 --- a/subsys/bluetooth/host/classic/CMakeLists.txt +++ b/subsys/bluetooth/host/classic/CMakeLists.txt @@ -3,7 +3,7 @@ zephyr_library() zephyr_library_link_libraries(subsys__bluetooth) -zephyr_library_sources_ifdef(CONFIG_BT_A2DP a2dp.c) +zephyr_library_sources_ifdef(CONFIG_BT_A2DP a2dp.c a2dp_codec_sbc.c) zephyr_library_sources_ifdef(CONFIG_BT_AVDTP avdtp.c) zephyr_library_sources_ifdef(CONFIG_BT_RFCOMM rfcomm.c) diff --git a/subsys/bluetooth/host/classic/Kconfig b/subsys/bluetooth/host/classic/Kconfig index 2869978f9c78c..9c47a8b53f612 100644 --- a/subsys/bluetooth/host/classic/Kconfig +++ b/subsys/bluetooth/host/classic/Kconfig @@ -154,6 +154,30 @@ config BT_A2DP help This option enables the A2DP profile +if BT_AVDTP + +config BT_AVDTP_RTP_VERSION + int "Bluetooth AVDTP RTP version" + default 2 + help + This option sets the AVDTP RTP protocol version + +endif # BT_AVDTP + +if BT_A2DP + +config BT_A2DP_SOURCE + bool "Bluetooth A2DP Profile Source Function" + help + This option enables the A2DP profile source function + +config BT_A2DP_SINK + bool "Bluetooth A2DP Profile Sink Function" + help + This option enables the A2DP profile sink function + +endif # BT_A2DP + config BT_PAGE_TIMEOUT hex "Bluetooth Page Timeout" default 0x2000 diff --git a/subsys/bluetooth/host/classic/a2dp.c b/subsys/bluetooth/host/classic/a2dp.c index 0fb6723480ef7..a958660f9c589 100644 --- a/subsys/bluetooth/host/classic/a2dp.c +++ b/subsys/bluetooth/host/classic/a2dp.c @@ -4,6 +4,7 @@ /* * Copyright (c) 2015-2016 Intel Corporation + * Copyright 2021,2024 NXP * * SPDX-License-Identifier: Apache-2.0 */ @@ -19,12 +20,31 @@ #include #include #include +#include #include #include "common/assert.h" +#define A2DP_SBC_PAYLOAD_TYPE (0x60u) + +#define A2DP_AVDTP(_avdtp) CONTAINER_OF(_avdtp, struct bt_a2dp, session) +#define DISCOVER_REQ(_req) CONTAINER_OF(_req, struct bt_avdtp_discover_params, req) +#define DISCOVER_PARAM(_discover_param) CONTAINER_OF(_discover_param, struct bt_a2dp,\ + discover_param) +#define GET_CAP_REQ(_req) CONTAINER_OF(_req, struct bt_avdtp_get_capabilities_params, req) +#define GET_CAP_PARAM(_get_cap_param) CONTAINER_OF(_get_cap_param, struct bt_a2dp,\ + get_capabilities_param) +#define SET_CONF_REQ(_req) CONTAINER_OF(_req, struct bt_avdtp_set_configuration_params, req) +#define SET_CONF_PARAM(_set_conf_param) CONTAINER_OF(_set_conf_param, struct bt_a2dp,\ + set_config_param) +#define OPEN_REQ(_req) CONTAINER_OF(_req, struct bt_avdtp_open_params, req) +#define OPEN_PARAM(_open_param) CONTAINER_OF(_open_param, struct bt_a2dp, open_param) +#define START_REQ(_req) CONTAINER_OF(_req, struct bt_avdtp_start_params, req) +#define START_PARAM(_start_param) CONTAINER_OF(_start_param, struct bt_a2dp, start_param) + #include "host/hci_core.h" #include "host/conn_internal.h" +#include "host/l2cap_internal.h" #include "avdtp_internal.h" #include "a2dp_internal.h" @@ -34,19 +54,41 @@ LOG_MODULE_REGISTER(bt_a2dp); #define A2DP_NO_SPACE (-1) +enum bt_a2dp_internal_state { + INTERNAL_STATE_IDLE = 0, + INTERNAL_STATE_AVDTP_CONNECTED, +}; + struct bt_a2dp { struct bt_avdtp session; + struct bt_avdtp_discover_params discover_param; + struct bt_a2dp_discover_param *discover_cb_param; + struct bt_avdtp_get_capabilities_params get_capabilities_param; + struct bt_avdtp_set_configuration_params set_config_param; + struct bt_avdtp_open_params open_param; + struct bt_avdtp_start_params start_param; + uint8_t get_cap_index; + enum bt_a2dp_internal_state a2dp_state; + uint8_t peer_seps_count; }; +static struct bt_a2dp_cb *a2dp_cb; +K_MUTEX_DEFINE(a2dp_mutex); + +#define A2DP_LOCK() k_mutex_lock(&a2dp_mutex, K_FOREVER) +#define A2DP_UNLOCK() k_mutex_unlock(&a2dp_mutex) + /* Connections */ static struct bt_a2dp connection[CONFIG_BT_MAX_CONN]; -void a2d_reset(struct bt_a2dp *a2dp_conn) +static int bt_a2dp_get_sep_caps(struct bt_a2dp *a2dp); + +static void a2dp_reset(struct bt_a2dp *a2dp) { - (void)memset(a2dp_conn, 0, sizeof(struct bt_a2dp)); + (void)memset(a2dp, 0, sizeof(struct bt_a2dp)); } -struct bt_a2dp *get_new_connection(struct bt_conn *conn) +static struct bt_a2dp *get_new_connection(struct bt_conn *conn) { int8_t i, free; @@ -61,12 +103,13 @@ struct bt_a2dp *get_new_connection(struct bt_conn *conn) for (i = 0; i < CONFIG_BT_MAX_CONN; i++) { if (connection[i].session.br_chan.chan.conn == conn) { LOG_DBG("Conn already exists"); - return NULL; + return &connection[i]; } if (!connection[i].session.br_chan.chan.conn && - free == A2DP_NO_SPACE) { + free == A2DP_NO_SPACE) { free = i; + break; } } @@ -76,35 +119,721 @@ struct bt_a2dp *get_new_connection(struct bt_conn *conn) } /* Clean the memory area before returning */ - a2d_reset(&connection[free]); + a2dp_reset(&connection[free]); return &connection[free]; } -int a2dp_accept(struct bt_conn *conn, struct bt_avdtp **session) +/* The AVDTP L2CAP signal channel established */ +static void a2dp_connected(struct bt_avdtp *session) { - struct bt_a2dp *a2dp_conn; + struct bt_a2dp *a2dp = A2DP_AVDTP(session); - a2dp_conn = get_new_connection(conn); - if (!a2dp_conn) { - return -ENOMEM; + a2dp->a2dp_state = INTERNAL_STATE_AVDTP_CONNECTED; + /* notify a2dp app the connection. */ + if ((a2dp_cb != NULL) && (a2dp_cb->connected != NULL)) { + a2dp_cb->connected(a2dp, 0); } +} + +/* The AVDTP L2CAP signal channel released */ +static void a2dp_disconnected(struct bt_avdtp *session) +{ + struct bt_a2dp *a2dp = A2DP_AVDTP(session); + + /* notify a2dp app the disconnection. */ + if ((a2dp_cb != NULL) && (a2dp_cb->disconnected != NULL)) { + a2dp_cb->disconnected(a2dp); + } +} - *session = &(a2dp_conn->session); - LOG_DBG("session: %p", &(a2dp_conn->session)); +/* avdtp alloc buf from upper layer */ +static struct net_buf *a2dp_alloc_buf(struct bt_avdtp *session) +{ + return NULL; +} +static int a2dp_discovery_ind(struct bt_avdtp *session, uint8_t *errcode) +{ + *errcode = 0; + return 0; +} + +static int a2dp_get_capabilities_ind(struct bt_avdtp *session, struct bt_avdtp_sep *sep, + struct net_buf *rsp_buf, uint8_t *errcode) +{ + struct bt_a2dp_ep *ep; + + *errcode = 0; + /* Service Category: Media Transport */ + net_buf_add_u8(rsp_buf, BT_AVDTP_SERVICE_MEDIA_TRANSPORT); + net_buf_add_u8(rsp_buf, 0); + /* Service Category: Media Codec */ + net_buf_add_u8(rsp_buf, BT_AVDTP_SERVICE_MEDIA_CODEC); + ep = CONTAINER_OF(sep, struct bt_a2dp_ep, sep); + /* Length Of Service Capability */ + net_buf_add_u8(rsp_buf, ep->codec_cap->len + 2u); + /* Media Type */ + net_buf_add_u8(rsp_buf, sep->sep_info.media_type << 4u); + /* Media Codec Type */ + net_buf_add_u8(rsp_buf, ep->codec_type); + /* Codec Info Element */ + net_buf_add_mem(rsp_buf, &ep->codec_cap->codec_ie[0], ep->codec_cap->len); return 0; } -/* Callback for incoming requests */ -static struct bt_avdtp_ind_cb cb_ind = { - /*TODO*/ +static int a2dp_set_config_ind(struct bt_avdtp *session, struct bt_avdtp_sep *sep, + uint8_t int_seid, struct net_buf *buf, uint8_t *errcode) +{ + struct bt_a2dp *a2dp = A2DP_AVDTP(session); + struct bt_a2dp_ep *ep; + struct bt_a2dp_stream *stream; + struct bt_a2dp_stream_ops *ops; + uint8_t codec_type; + uint8_t *codec_info_element; + uint16_t codec_info_element_len; + int err; + + *errcode = 0; + ep = CONTAINER_OF(sep, struct bt_a2dp_ep, sep); + if (ep == NULL) { + *errcode = BT_AVDTP_BAD_ACP_SEID; + return -1; + } + + /* parse the configuration */ + codec_info_element_len = 4U; + err = bt_avdtp_parse_capability_codec(buf, + &codec_type, &codec_info_element, + &codec_info_element_len); + if (err) { + *errcode = BT_AVDTP_BAD_ACP_SEID; + return -1; + } + + if (codec_type == BT_A2DP_SBC) { + struct bt_a2dp_codec_sbc_params *sbc_set; + struct bt_a2dp_codec_sbc_params *sbc; + + if (codec_info_element_len != 4U) { + *errcode = BT_AVDTP_BAD_ACP_SEID; + return -1; + } + + sbc_set = (struct bt_a2dp_codec_sbc_params *)codec_info_element; + sbc = (struct bt_a2dp_codec_sbc_params *)&ep->codec_cap->codec_ie[0]; + if (((BT_A2DP_SBC_SAMP_FREQ(sbc_set) & BT_A2DP_SBC_SAMP_FREQ(sbc)) == 0) || + ((BT_A2DP_SBC_CHAN_MODE(sbc_set) & BT_A2DP_SBC_CHAN_MODE(sbc)) == 0) || + ((BT_A2DP_SBC_BLK_LEN(sbc_set) & BT_A2DP_SBC_BLK_LEN(sbc)) == 0) || + ((BT_A2DP_SBC_SUB_BAND(sbc_set) & BT_A2DP_SBC_SUB_BAND(sbc)) == 0) || + ((BT_A2DP_SBC_ALLOC_MTHD(sbc_set) & BT_A2DP_SBC_ALLOC_MTHD(sbc)) == 0)) { + *errcode = BT_AVDTP_BAD_ACP_SEID; + return -1; + } + } + + if ((a2dp_cb != NULL) && (a2dp_cb->config_req != NULL)) { + struct bt_a2dp_codec_cfg cfg; + struct bt_a2dp_codec_ie codec_config; + uint8_t rsp_err_code; + + cfg.codec_config = &codec_config; + cfg.codec_config->len = codec_info_element_len; + memcpy(&cfg.codec_config->codec_ie[0], codec_info_element, + (codec_info_element_len > A2DP_MAX_IE_LENGTH ? + A2DP_MAX_IE_LENGTH : codec_info_element_len)); + err = a2dp_cb->config_req(a2dp, ep, &cfg, &stream, &rsp_err_code); + if (err) { + *errcode = rsp_err_code; + } else if (stream != NULL) { + stream->a2dp = a2dp; + stream->local_ep = ep; + stream->remote_ep_id = int_seid; + stream->remote_ep = NULL; + stream->codec_config = *cfg.codec_config; + ep->stream = stream; + } + } + + ops = stream->ops; + if (*errcode == 0) { + if ((ops != NULL) && (stream->ops->configured != NULL)) { + stream->ops->configured(stream); + } + } + + return (*errcode == 0) ? 0 : -1; +} + +#if defined(CONFIG_BT_A2DP_SINK) +static void bt_a2dp_media_data_callback( + struct bt_avdtp_sep *sep, + struct net_buf *buf) +{ + struct bt_avdtp_media_hdr *media_hdr; + struct bt_a2dp_ep *ep; + struct bt_a2dp_stream *stream; + + ep = CONTAINER_OF(sep, struct bt_a2dp_ep, sep); + if ((ep == NULL) || (ep->stream == NULL)) { + return; + } + stream = ep->stream; + + media_hdr = net_buf_pull_mem(buf, sizeof(*media_hdr)); + + stream->ops->recv(stream, buf, + sys_get_be16((uint8_t *)&media_hdr->sequence_number), + sys_get_be32((uint8_t *)&media_hdr->time_stamp)); +} +#endif + +static int a2dp_open_ind(struct bt_avdtp *session, struct bt_avdtp_sep *sep, uint8_t *errcode) +{ + struct bt_a2dp_ep *ep; + struct bt_a2dp_stream *stream; + struct bt_a2dp_stream_ops *ops; + + *errcode = 0; + ep = CONTAINER_OF(sep, struct bt_a2dp_ep, sep); + if (ep->stream == NULL) { + *errcode = BT_AVDTP_BAD_ACP_SEID; + return -1; + } + stream = ep->stream; + + if ((a2dp_cb != NULL) && (a2dp_cb->establish_req != NULL)) { + uint8_t rsp_err_code; + int err; + + err = a2dp_cb->establish_req(stream, &rsp_err_code); + if (err) { + *errcode = rsp_err_code; + } + } + + ops = stream->ops; + if (*errcode == 0) { + if ((ops != NULL) && (stream->ops->established != NULL)) { + stream->ops->established(stream); + } + } + + return (*errcode == 0) ? 0 : -1; +} + +static int a2dp_start_ind(struct bt_avdtp *session, struct bt_avdtp_sep *sep, uint8_t *errcode) +{ + struct bt_a2dp_ep *ep; + struct bt_a2dp_stream *stream; + struct bt_a2dp_stream_ops *ops; + + *errcode = 0; + ep = CONTAINER_OF(sep, struct bt_a2dp_ep, sep); + if (ep->stream == NULL) { + *errcode = BT_AVDTP_BAD_ACP_SEID; + return -1; + } + stream = ep->stream; + + if ((a2dp_cb != NULL) && (a2dp_cb->start_req != NULL)) { + uint8_t rsp_err_code; + int err; + + err = a2dp_cb->start_req(stream, &rsp_err_code); + if (err) { + *errcode = rsp_err_code; + } + } + + ops = stream->ops; + if (*errcode == 0) { + if ((ops != NULL) && (stream->ops->started != NULL)) { + stream->ops->started(stream); + } + } + + return (*errcode == 0) ? 0 : -1; +} + +static int a2dp_close_ind(struct bt_avdtp *session, struct bt_avdtp_sep *sep, uint8_t *errcode) +{ + struct bt_a2dp_ep *ep; + struct bt_a2dp_stream *stream; + struct bt_a2dp_stream_ops *ops; + + *errcode = 0; + ep = CONTAINER_OF(sep, struct bt_a2dp_ep, sep); + if (ep->stream == NULL) { + *errcode = BT_AVDTP_BAD_ACP_SEID; + return -1; + } + stream = ep->stream; + + if ((a2dp_cb != NULL) && (a2dp_cb->release_req != NULL)) { + uint8_t rsp_err_code; + int err; + + err = a2dp_cb->release_req(stream, &rsp_err_code); + if (err) { + *errcode = rsp_err_code; + } + } + + ops = stream->ops; + if (*errcode == 0) { + if ((ops != NULL) && (stream->ops->released != NULL)) { + stream->ops->released(stream); + } + } + + return (*errcode == 0) ? 0 : -1; +} + +static int a2dp_suspend_ind(struct bt_avdtp *session, struct bt_avdtp_sep *sep, uint8_t *errcode) +{ + struct bt_a2dp_ep *ep; + struct bt_a2dp_stream *stream; + struct bt_a2dp_stream_ops *ops; + + *errcode = 0; + ep = CONTAINER_OF(sep, struct bt_a2dp_ep, sep); + if (ep->stream == NULL) { + *errcode = BT_AVDTP_BAD_ACP_SEID; + return -1; + } + stream = ep->stream; + + if ((a2dp_cb != NULL) && (a2dp_cb->suspend_req != NULL)) { + uint8_t rsp_err_code; + int err; + + err = a2dp_cb->suspend_req(stream, &rsp_err_code); + if (err) { + *errcode = rsp_err_code; + } + } + + ops = stream->ops; + if (*errcode == 0) { + if ((ops != NULL) && (stream->ops->suspended != NULL)) { + stream->ops->suspended(stream); + } + } + + return (*errcode == 0) ? 0 : -1; +} + +static int bt_a2dp_open_cb(struct bt_avdtp_req *req) +{ + struct bt_a2dp *a2dp = OPEN_PARAM(OPEN_REQ(req)); + struct bt_a2dp_ep *ep; + struct bt_a2dp_stream *stream; + struct bt_a2dp_stream_ops *ops; + + ep = CONTAINER_OF(a2dp->open_param.sep, struct bt_a2dp_ep, sep); + if (ep->stream == NULL) { + return -1; + } + stream = ep->stream; + + LOG_DBG("OPEN result:%d", a2dp->open_param.status); + + if ((a2dp_cb != NULL) && (a2dp_cb->establish_rsp != NULL)) { + a2dp_cb->establish_rsp(stream, a2dp->open_param.status); + } + + ops = stream->ops; + if ((!a2dp->open_param.status) && (ops->established != NULL)) { + ops->established(stream); + } + return 0; +} + +static int bt_a2dp_set_config_cb(struct bt_avdtp_req *req) +{ + struct bt_a2dp *a2dp = SET_CONF_PARAM(SET_CONF_REQ(req)); + struct bt_a2dp_ep *ep; + struct bt_a2dp_stream *stream; + struct bt_a2dp_stream_ops *ops; + + ep = CONTAINER_OF(a2dp->set_config_param.sep, struct bt_a2dp_ep, sep); + if (ep->stream == NULL) { + return -1; + } + stream = ep->stream; + + LOG_DBG("SET CONFIGURATION result:%d", a2dp->set_config_param.status); + + if ((a2dp_cb != NULL) && (a2dp_cb->config_rsp != NULL)) { + a2dp_cb->config_rsp(stream, a2dp->set_config_param.status); + } + + ops = stream->ops; + if ((!a2dp->set_config_param.status) && (ops->configured != NULL)) { + ops->configured(stream); + } + return 0; +} + +static int bt_a2dp_get_capabilities_cb(struct bt_avdtp_req *req) +{ + int err; + uint8_t *codec_info_element; + struct bt_a2dp *a2dp = GET_CAP_PARAM(GET_CAP_REQ(req)); + uint16_t codec_info_element_len; + uint8_t codec_type; + uint8_t user_ret; + + LOG_DBG("GET CAPABILITIES result:%d", a2dp->get_capabilities_param.status); + if (a2dp->get_capabilities_param.status) { + if ((a2dp->discover_cb_param != NULL) && + (a2dp->discover_cb_param->cb != NULL)) { + a2dp->discover_cb_param->cb(a2dp, NULL, NULL); + a2dp->discover_cb_param = NULL; + } + return 0; + } + + err = bt_avdtp_parse_capability_codec(a2dp->get_capabilities_param.buf, + &codec_type, &codec_info_element, &codec_info_element_len); + if (err) { + LOG_DBG("codec capability parsing fail"); + return 0; + } + + if (codec_info_element_len > A2DP_MAX_IE_LENGTH) { + codec_info_element_len = A2DP_MAX_IE_LENGTH; + } + + if ((a2dp->discover_cb_param != NULL) && (a2dp->discover_cb_param->cb != NULL)) { + struct bt_a2dp_ep *ep; + struct bt_a2dp_ep_info *info = &a2dp->discover_cb_param->info; + + info->codec_type = codec_type; + info->sep_info = a2dp->discover_cb_param->seps_info[a2dp->get_cap_index]; + memcpy(&info->codec_cap.codec_ie, + codec_info_element, codec_info_element_len); + info->codec_cap.len = codec_info_element_len; + user_ret = a2dp->discover_cb_param->cb(a2dp, info, &ep); + if (ep != NULL) { + ep->codec_type = info->codec_type; + ep->sep.sep_info = info->sep_info; + *ep->codec_cap = info->codec_cap; + ep->stream = NULL; + } + + if (user_ret == BT_A2DP_DISCOVER_EP_CONTINUE) { + if (bt_a2dp_get_sep_caps(a2dp) != 0) { + a2dp->discover_cb_param->cb(a2dp, NULL, NULL); + a2dp->discover_cb_param = NULL; + } + } else { + a2dp->discover_cb_param = NULL; + } + } + + return 0; +} + +static int bt_a2dp_get_sep_caps(struct bt_a2dp *a2dp) +{ + int err; + + if ((a2dp->discover_cb_param == NULL) || (a2dp->discover_cb_param->cb == NULL)) { + return -EINVAL; + } + + if (a2dp->get_cap_index == 0xFFu) { + a2dp->get_cap_index = 0U; + } else { + a2dp->get_cap_index++; + } + + for (; a2dp->get_cap_index < a2dp->peer_seps_count; + a2dp->get_cap_index++) { + if (a2dp->discover_cb_param->seps_info[a2dp->get_cap_index].media_type == + BT_AVDTP_AUDIO) { + a2dp->get_capabilities_param.req.func = bt_a2dp_get_capabilities_cb; + a2dp->get_capabilities_param.buf = NULL; + a2dp->get_capabilities_param.stream_endpoint_id = + a2dp->discover_cb_param->seps_info[a2dp->get_cap_index].id; + err = bt_avdtp_get_capabilities(&a2dp->session, + &a2dp->get_capabilities_param); + if (err) { + LOG_DBG("AVDTP get codec_cap failed"); + a2dp->discover_cb_param->cb(a2dp, NULL, NULL); + a2dp->discover_cb_param = NULL; + } + return 0; + } + } + return -1; +} + +static int bt_a2dp_discover_cb(struct bt_avdtp_req *req) +{ + struct bt_a2dp *a2dp = DISCOVER_PARAM(DISCOVER_REQ(req)); + struct bt_avdtp_sep_info *sep_info; + int err; + + LOG_DBG("DISCOVER result:%d", DISCOVER_REQ(req)->status); + if (a2dp->discover_cb_param == NULL) { + return -EINVAL; + } + a2dp->peer_seps_count = 0U; + if (!(DISCOVER_REQ(req)->status)) { + if (a2dp->discover_cb_param->sep_count == 0) { + if (a2dp->discover_cb_param->cb != NULL) { + a2dp->discover_cb_param->cb(a2dp, NULL, NULL); + a2dp->discover_cb_param = NULL; + } + return -EINVAL; + } + + do { + sep_info = &a2dp->discover_cb_param->seps_info[a2dp->peer_seps_count]; + err = bt_avdtp_parse_sep(DISCOVER_REQ(req)->buf, sep_info); + if (err) { + break; + } + a2dp->peer_seps_count++; + LOG_DBG("id:%d, inuse:%d, media_type:%d, tsep:%d, ", + sep_info->id, + sep_info->inuse, + sep_info->media_type, + sep_info->tsep); + } while (a2dp->peer_seps_count < a2dp->discover_cb_param->sep_count); + + /* trigger the getting capability */ + a2dp->get_cap_index = 0xFFu; + if (bt_a2dp_get_sep_caps(a2dp) != 0) { + /* the peer_seps' caps is done.*/ + if (a2dp->discover_cb_param->cb != NULL) { + a2dp->discover_cb_param->cb(a2dp, NULL, NULL); + a2dp->discover_cb_param = NULL; + } + } + } else { + if (a2dp->discover_cb_param->cb != NULL) { + a2dp->discover_cb_param->cb(a2dp, NULL, NULL); + a2dp->discover_cb_param = NULL; + } + } + + return 0; +} + +static int bt_a2dp_start_cb(struct bt_avdtp_req *req) +{ + struct bt_a2dp *a2dp = START_PARAM(START_REQ(req)); + struct bt_a2dp_ep *ep; + struct bt_a2dp_stream *stream; + struct bt_a2dp_stream_ops *ops; + + ep = CONTAINER_OF(a2dp->start_param.sep, struct bt_a2dp_ep, sep); + if (ep->stream == NULL) { + return -1; + } + stream = ep->stream; + + LOG_DBG("START result:%d", a2dp->start_param.status); + + if ((a2dp_cb != NULL) && (a2dp_cb->start_rsp != NULL)) { + a2dp_cb->start_rsp(stream, a2dp->start_param.status); + } + + ops = stream->ops; + if ((!a2dp->start_param.status) && (ops->started != NULL)) { + ops->started(stream); + } + return 0; +} + +int bt_a2dp_discover(struct bt_a2dp *a2dp, struct bt_a2dp_discover_param *param) +{ + int err; + + if ((a2dp == NULL) || (param == NULL)) { + return -EINVAL; + } + + if (a2dp->a2dp_state != INTERNAL_STATE_AVDTP_CONNECTED) { + return -EIO; + } + + if (a2dp->discover_cb_param != NULL) { + return -EBUSY; + } + + a2dp->discover_cb_param = param; + a2dp->discover_param.req.func = bt_a2dp_discover_cb; + a2dp->discover_param.buf = NULL; + err = bt_avdtp_discover(&a2dp->session, &a2dp->discover_param); + if (err) { + if (a2dp->discover_cb_param->cb != NULL) { + a2dp->discover_cb_param->cb(a2dp, NULL, NULL); + } + a2dp->discover_cb_param = NULL; + } + + return err; +} + +void bt_a2dp_stream_cb_register(struct bt_a2dp_stream *stream, struct bt_a2dp_stream_ops *ops) +{ + BT_ASSERT(stream); + stream->ops = ops; +} + +int bt_a2dp_stream_config(struct bt_a2dp *a2dp, struct bt_a2dp_stream *stream, + struct bt_a2dp_ep *local_ep, struct bt_a2dp_ep *remote_ep, + struct bt_a2dp_codec_cfg *config) +{ + if ((a2dp == NULL) || (stream == NULL) || (local_ep == NULL) || + (remote_ep == NULL) || (config == NULL)) { + return -EINVAL; + } + + if ((local_ep->sep.sep_info.tsep == remote_ep->sep.sep_info.tsep) || + (local_ep->codec_type != remote_ep->codec_type)) { + return -EINVAL; + } + + stream->local_ep = local_ep; + stream->remote_ep = remote_ep; + stream->remote_ep_id = remote_ep->sep.sep_info.id; + stream->a2dp = a2dp; + local_ep->stream = stream; + remote_ep->stream = stream; + a2dp->set_config_param.req.func = bt_a2dp_set_config_cb; + a2dp->set_config_param.acp_stream_ep_id = remote_ep->sep.sep_info.id; + a2dp->set_config_param.int_stream_endpoint_id = local_ep->sep.sep_info.id; + a2dp->set_config_param.media_type = BT_AVDTP_AUDIO; + a2dp->set_config_param.media_codec_type = local_ep->codec_type; + a2dp->set_config_param.codec_specific_ie_len = config->codec_config->len; + a2dp->set_config_param.codec_specific_ie = &config->codec_config->codec_ie[0]; + a2dp->set_config_param.sep = &local_ep->sep; + return bt_avdtp_set_configuration(&a2dp->session, &a2dp->set_config_param); +} + +int bt_a2dp_stream_establish(struct bt_a2dp_stream *stream) +{ + struct bt_a2dp *a2dp; + + if ((stream == NULL) || (stream->local_ep == NULL) || (stream->a2dp == NULL)) { + return -EINVAL; + } + + a2dp = stream->a2dp; + a2dp->open_param.req.func = bt_a2dp_open_cb; + a2dp->open_param.acp_stream_ep_id = stream->remote_ep == NULL ? + stream->remote_ep->sep.sep_info.id : stream->remote_ep_id; + a2dp->open_param.sep = a2dp->set_config_param.sep; + return bt_avdtp_open(&a2dp->session, &a2dp->open_param); +} + +int bt_a2dp_stream_release(struct bt_a2dp_stream *stream) +{ + /* todo: see the API description in a2dp.h */ + return -ENOTSUP; +} + +int bt_a2dp_stream_start(struct bt_a2dp_stream *stream) +{ + struct bt_a2dp *a2dp; + + if ((stream == NULL) || (stream->local_ep == NULL) || (stream->a2dp == NULL)) { + return -EINVAL; + } + + a2dp = stream->a2dp; + a2dp->start_param.req.func = bt_a2dp_start_cb; + a2dp->start_param.acp_stream_ep_id = stream->remote_ep == NULL ? + stream->remote_ep->sep.sep_info.id : stream->remote_ep_id; + a2dp->start_param.sep = &stream->local_ep->sep; + return bt_avdtp_start(&a2dp->session, &a2dp->start_param); +} + +int bt_a2dp_stream_suspend(struct bt_a2dp_stream *stream) +{ + /* todo: see the API description in a2dp.h */ + return -ENOTSUP; +} + +int bt_a2dp_stream_reconfig(struct bt_a2dp_stream *stream, struct bt_a2dp_codec_cfg *config) +{ + /* todo: see the API description in a2dp.h */ + return -ENOTSUP; +} + +uint32_t bt_a2dp_get_mtu(struct bt_a2dp_stream *stream) +{ + if ((stream == NULL) || (stream->local_ep == NULL)) { + return -EINVAL; + } + + return bt_avdtp_get_media_mtu(&stream->local_ep->sep); +} + +#if defined(CONFIG_BT_A2DP_SOURCE) +int bt_a2dp_stream_send(struct bt_a2dp_stream *stream, struct net_buf *buf, + uint16_t seq_num, uint32_t ts) +{ + struct bt_avdtp_media_hdr *media_hdr; + + if (stream == NULL) { + return -EINVAL; + } + + media_hdr = net_buf_push(buf, sizeof(struct bt_avdtp_media_hdr)); + if (stream->local_ep->codec_type == BT_A2DP_SBC) { + media_hdr->playload_type = A2DP_SBC_PAYLOAD_TYPE; + } + + memset(media_hdr, 0, sizeof(struct bt_avdtp_media_hdr)); + media_hdr->synchronization_source = 0U; + /* update time_stamp in the buf */ + sys_put_be32(ts, (uint8_t *)&media_hdr->time_stamp); + /* update sequence_number in the buf */ + sys_put_be16(seq_num, (uint8_t *)&media_hdr->sequence_number); + /* send the buf */ + return bt_avdtp_send_media_data(&stream->local_ep->sep, buf); +} +#endif + +static const struct bt_avdtp_ops_cb signaling_avdtp_ops = { + .connected = a2dp_connected, + .disconnected = a2dp_disconnected, + .alloc_buf = a2dp_alloc_buf, + .discovery_ind = a2dp_discovery_ind, + .get_capabilities_ind = a2dp_get_capabilities_ind, + .set_configuration_ind = a2dp_set_config_ind, + .open_ind = a2dp_open_ind, + .start_ind = a2dp_start_ind, + .close_ind = a2dp_close_ind, + .suspend_ind = a2dp_suspend_ind, }; +int a2dp_accept(struct bt_conn *conn, struct bt_avdtp **session) +{ + struct bt_a2dp *a2dp; + + a2dp = get_new_connection(conn); + if (!a2dp) { + return -ENOMEM; + } + + *session = &(a2dp->session); + a2dp->session.ops = &signaling_avdtp_ops; + LOG_DBG("session: %p", &(a2dp->session)); + + return 0; +} + /* The above callback structures need to be packed and passed to AVDTP */ static struct bt_avdtp_event_cb avdtp_cb = { - .ind = &cb_ind, - .accept = a2dp_accept + .accept = a2dp_accept, }; int bt_a2dp_init(void) @@ -118,46 +847,77 @@ int bt_a2dp_init(void) return err; } + for (uint8_t i = 0; i < CONFIG_BT_MAX_CONN; i++) { + memset(&connection[i], 0, sizeof(struct bt_a2dp)); + } + LOG_DBG("A2DP Initialized successfully."); return 0; } struct bt_a2dp *bt_a2dp_connect(struct bt_conn *conn) { - struct bt_a2dp *a2dp_conn; + struct bt_a2dp *a2dp; int err; - a2dp_conn = get_new_connection(conn); - if (!a2dp_conn) { + A2DP_LOCK(); + a2dp = get_new_connection(conn); + if (!a2dp) { + A2DP_UNLOCK(); LOG_ERR("Cannot allocate memory"); return NULL; } - err = bt_avdtp_connect(conn, &(a2dp_conn->session)); + a2dp->a2dp_state = INTERNAL_STATE_IDLE; + + a2dp->session.ops = &signaling_avdtp_ops; + err = bt_avdtp_connect(conn, &(a2dp->session)); if (err < 0) { /* If error occurs, undo the saving and return the error */ - a2d_reset(a2dp_conn); + a2dp_reset(a2dp); + A2DP_UNLOCK(); LOG_DBG("AVDTP Connect failed"); return NULL; } + A2DP_UNLOCK(); LOG_DBG("Connect request sent"); - return a2dp_conn; + return a2dp; } -int bt_a2dp_register_endpoint(struct bt_a2dp_endpoint *endpoint, - uint8_t media_type, uint8_t role) +int bt_a2dp_disconnect(struct bt_a2dp *a2dp) +{ + /* todo: see the API description in a2dp.h */ + return -ENOTSUP; +} + +int bt_a2dp_register_ep(struct bt_a2dp_ep *ep, uint8_t media_type, uint8_t role) { int err; - BT_ASSERT(endpoint); + BT_ASSERT(ep); - err = bt_avdtp_register_sep(media_type, role, &(endpoint->info)); +#if defined(CONFIG_BT_A2DP_SINK) + if (role == BT_AVDTP_SINK) { + ep->sep.media_data_cb = bt_a2dp_media_data_callback; + } else { + ep->sep.media_data_cb = NULL; + } +#else + ep->sep.media_data_cb = NULL; +#endif + A2DP_LOCK(); + err = bt_avdtp_register_sep(media_type, role, &(ep->sep)); + A2DP_UNLOCK(); if (err < 0) { return err; } - /* TODO: Register SDP record */ + return 0; +} +int bt_a2dp_register_cb(struct bt_a2dp_cb *cb) +{ + a2dp_cb = cb; return 0; } diff --git a/subsys/bluetooth/host/classic/a2dp_codec_sbc.c b/subsys/bluetooth/host/classic/a2dp_codec_sbc.c new file mode 100644 index 0000000000000..e5f66cd1e9309 --- /dev/null +++ b/subsys/bluetooth/host/classic/a2dp_codec_sbc.c @@ -0,0 +1,51 @@ +/* + * Copyright 2024 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + + +uint8_t bt_a2dp_sbc_get_channel_num(struct bt_a2dp_codec_sbc_params *sbc_codec) +{ + __ASSERT_NO_MSG(sbc_codec != NULL); + + if (sbc_codec->config[0] & A2DP_SBC_CH_MODE_MONO) { + return 1U; + } else if (sbc_codec->config[0] & A2DP_SBC_CH_MODE_DUAL) { + return 2U; + } else if (sbc_codec->config[0] & A2DP_SBC_CH_MODE_STREO) { + return 2U; + } else if (sbc_codec->config[0] & A2DP_SBC_CH_MODE_JOINT) { + return 2U; + } else { + return 0U; + } +} + +uint32_t bt_a2dp_sbc_get_sampling_frequency(struct bt_a2dp_codec_sbc_params *sbc_codec) +{ + __ASSERT_NO_MSG(sbc_codec != NULL); + + if (sbc_codec->config[0] & A2DP_SBC_SAMP_FREQ_16000) { + return 16000U; + } else if (sbc_codec->config[0] & A2DP_SBC_SAMP_FREQ_32000) { + return 32000U; + } else if (sbc_codec->config[0] & A2DP_SBC_SAMP_FREQ_44100) { + return 44100U; + } else if (sbc_codec->config[0] & A2DP_SBC_SAMP_FREQ_48000) { + return 48000U; + } else { + return 0U; + } +} diff --git a/subsys/bluetooth/host/classic/avdtp.c b/subsys/bluetooth/host/classic/avdtp.c index 5f323bf87c639..e969d1f7696c6 100644 --- a/subsys/bluetooth/host/classic/avdtp.c +++ b/subsys/bluetooth/host/classic/avdtp.c @@ -38,35 +38,771 @@ LOG_MODULE_REGISTER(bt_avdtp); #define AVDTP_GET_SIG_ID(s) (s & AVDTP_SIGID_MASK) static struct bt_avdtp_event_cb *event_cb; - -static struct bt_avdtp_seid_lsep *lseps; +static sys_slist_t seps; #define AVDTP_CHAN(_ch) CONTAINER_OF(_ch, struct bt_avdtp, br_chan.chan) -#define AVDTP_KWORK(_work) CONTAINER_OF(k_work_delayable_from_work(_work), \ - struct bt_avdtp_req, timeout_work) +#define AVDTP_KWORK(_work) CONTAINER_OF(CONTAINER_OF(_work, struct k_work_delayable, work),\ + struct bt_avdtp, timeout_work) + +#define DISCOVER_REQ(_req) CONTAINER_OF(_req, struct bt_avdtp_discover_params, req) +#define GET_CAP_REQ(_req) CONTAINER_OF(_req, struct bt_avdtp_get_capabilities_params, req) +#define SET_CONF_REQ(_req) CONTAINER_OF(_req, struct bt_avdtp_set_configuration_params, req) +#define OPEN_REQ(_req) CONTAINER_OF(_req, struct bt_avdtp_open_params, req) +#define START_REQ(_req) CONTAINER_OF(_req, struct bt_avdtp_start_params, req) #define AVDTP_TIMEOUT K_SECONDS(6) -static const struct { - uint8_t sig_id; - void (*func)(struct bt_avdtp *session, struct net_buf *buf, - uint8_t msg_type); -} handler[] = { +K_MUTEX_DEFINE(avdtp_mutex); +#define AVDTP_LOCK() k_mutex_lock(&avdtp_mutex, K_FOREVER) +#define AVDTP_UNLOCK() k_mutex_unlock(&avdtp_mutex) + +enum sep_state { + AVDTP_IDLE = 0, + AVDTP_CONFIGURED, + /* establishing the transport sessions. */ + AVDTP_OPENING, + AVDTP_OPEN, + AVDTP_STREAMING, + AVDTP_CLOSING, + AVDTP_ABORTING, }; +/* L2CAP Interface callbacks */ +void bt_avdtp_media_l2cap_connected(struct bt_l2cap_chan *chan) +{ + struct bt_avdtp *session; + struct bt_avdtp_sep *sep = + CONTAINER_OF(chan, struct bt_avdtp_sep, chan.chan); + + if (!chan) { + LOG_ERR("Invalid AVDTP chan"); + return; + } + + session = sep->session; + if (session == NULL) { + return; + } + + LOG_DBG("chan %p session %p", chan, session); + sep->state = AVDTP_OPEN; + if (session->req != NULL) { + struct bt_avdtp_req *req = session->req; + + OPEN_REQ(req)->status = 0; + AVDTP_LOCK(); + session->req = NULL; + AVDTP_UNLOCK(); + if (req->func != NULL) { + req->func(req); + } + } +} + +void bt_avdtp_media_l2cap_disconnected(struct bt_l2cap_chan *chan) +{ + struct bt_avdtp_sep *sep = + CONTAINER_OF(chan, struct bt_avdtp_sep, chan.chan); + + LOG_DBG("chan %p", chan); + chan->conn = NULL; + if (sep->state > AVDTP_OPENING) { + sep->state = AVDTP_OPENING; + } +} + +int bt_avdtp_media_l2cap_recv(struct bt_l2cap_chan *chan, struct net_buf *buf) +{ + /* media data is received */ + struct bt_avdtp_sep *sep = + CONTAINER_OF(chan, struct bt_avdtp_sep, chan.chan); + + if (sep->media_data_cb != NULL) { + sep->media_data_cb(sep, buf); + } + return 0; +} + +static int avdtp_media_connect(struct bt_avdtp *session, struct bt_avdtp_sep *sep) +{ + static const struct bt_l2cap_chan_ops ops = { + .connected = bt_avdtp_media_l2cap_connected, + .disconnected = bt_avdtp_media_l2cap_disconnected, + .recv = bt_avdtp_media_l2cap_recv + }; + + if (!session) { + return -EINVAL; + } + + sep->session = session; + sep->chan.rx.mtu = BT_L2CAP_RX_MTU; + sep->chan.chan.ops = &ops; + sep->chan.required_sec_level = BT_SECURITY_L2; + + return bt_l2cap_chan_connect(session->br_chan.chan.conn, &sep->chan.chan, + BT_L2CAP_PSM_AVDTP); +} + +static struct net_buf *avdtp_create_reply_pdu(uint8_t msg_type, + uint8_t pkt_type, + uint8_t sig_id, + uint8_t tid) +{ + struct net_buf *buf; + struct bt_avdtp_single_sig_hdr *hdr; + + LOG_DBG(""); + + buf = bt_l2cap_create_pdu(NULL, 0); + if (!buf) { + LOG_ERR("Error: No Buff available"); + return NULL; + } + + hdr = net_buf_add(buf, sizeof(*hdr)); + + hdr->hdr = (msg_type | pkt_type << AVDTP_PKT_POSITION | + tid << AVDTP_TID_POSITION); + hdr->signal_id = sig_id & AVDTP_SIGID_MASK; + + LOG_DBG("hdr = 0x%02X, Signal_ID = 0x%02X", hdr->hdr, hdr->signal_id); + return buf; +} + +static void avdtp_discover_handler(struct bt_avdtp *session, + struct net_buf *buf, uint8_t msg_type, + uint8_t tid) +{ + if (msg_type == BT_AVDTP_CMD) { + int err; + struct bt_avdtp_sep *sep; + struct net_buf *rsp_buf; + uint8_t error_code = 0; + + if (session->ops->discovery_ind == NULL) { + err = -ENOTSUP; + } else { + err = session->ops->discovery_ind(session, &error_code); + } + + rsp_buf = avdtp_create_reply_pdu(err ? + BT_AVDTP_REJECT : BT_AVDTP_ACCEPT, + BT_AVDTP_PACKET_TYPE_SINGLE, + BT_AVDTP_DISCOVER, tid); + if (!rsp_buf) { + return; + } + + if (err) { + if (error_code == 0) { + error_code = BT_AVDTP_BAD_STATE; + } + LOG_DBG("discover err code:%d", error_code); + net_buf_add_u8(rsp_buf, error_code); + } else { + struct bt_avdtp_sep_data sep_data; + + SYS_SLIST_FOR_EACH_CONTAINER(&seps, sep, _node) { + memset(&sep_data, 0, sizeof(sep_data)); + sep_data.inuse = sep->sep_info.inuse; + sep_data.id = sep->sep_info.id; + sep_data.tsep = sep->sep_info.tsep; + sep_data.media_type = sep->sep_info.media_type; + net_buf_add_mem(rsp_buf, &sep_data, sizeof(sep_data)); + } + } + + err = bt_l2cap_chan_send(&session->br_chan.chan, rsp_buf); + if (err < 0) { + net_buf_unref(rsp_buf); + LOG_ERR("Error:L2CAP send fail - result = %d", err); + return; + } + } else { + struct bt_avdtp_req *req = session->req; + + if (session->req == NULL) { + return; + } + k_work_cancel_delayable(&session->timeout_work); + if (msg_type == BT_AVDTP_ACCEPT) { + DISCOVER_REQ(session->req)->status = 0; + DISCOVER_REQ(session->req)->buf = buf; + } else if (msg_type == BT_AVDTP_REJECT) { + DISCOVER_REQ(session->req)->status = net_buf_pull_u8(buf); + } else if (msg_type == BT_AVDTP_GEN_REJECT) { + DISCOVER_REQ(session->req)->status = BT_AVDTP_NOT_SUPPORTED_COMMAND; + } + AVDTP_LOCK(); + session->req = NULL; + AVDTP_UNLOCK(); + if (req->func != NULL) { + req->func(req); + } + } +} + +static struct bt_avdtp_sep *avdtp_get_sep(uint8_t stream_endpoint_id) +{ + struct bt_avdtp_sep *sep = NULL; + + SYS_SLIST_FOR_EACH_CONTAINER(&seps, sep, _node) { + if (sep->sep_info.id == stream_endpoint_id) { + break; + } + } + + return sep; +} + +static void avdtp_get_capabilities_handler(struct bt_avdtp *session, + struct net_buf *buf, uint8_t msg_type, uint8_t tid) +{ + if (msg_type == BT_AVDTP_CMD) { + int err = 0; + struct net_buf *rsp_buf; + struct bt_avdtp_sep *sep; + uint8_t error_code = 0; + + sep = avdtp_get_sep(net_buf_pull_u8(buf) >> 2); + if ((sep == NULL) || (session->ops->get_capabilities_ind == NULL)) { + err = -ENOTSUP; + } else { + rsp_buf = avdtp_create_reply_pdu(BT_AVDTP_ACCEPT, + BT_AVDTP_PACKET_TYPE_SINGLE, + BT_AVDTP_GET_CAPABILITIES, + tid); + if (!rsp_buf) { + return; + } + err = session->ops->get_capabilities_ind(session, + sep, rsp_buf, &error_code); + if (err) { + net_buf_unref(rsp_buf); + } + } + + if (err) { + rsp_buf = avdtp_create_reply_pdu(BT_AVDTP_REJECT, + BT_AVDTP_PACKET_TYPE_SINGLE, + BT_AVDTP_GET_CAPABILITIES, tid); + if (!rsp_buf) { + return; + } + + if (error_code == 0) { + error_code = BT_AVDTP_BAD_ACP_SEID; + } + LOG_DBG("get cap err code:%d", error_code); + net_buf_add_u8(rsp_buf, error_code); + } + + err = bt_l2cap_chan_send(&session->br_chan.chan, rsp_buf); + if (err < 0) { + net_buf_unref(rsp_buf); + LOG_ERR("Error:L2CAP send fail - result = %d", err); + return; + } + } else { + struct bt_avdtp_req *req = session->req; + + if (session->req == NULL) { + return; + } + k_work_cancel_delayable(&session->timeout_work); + GET_CAP_REQ(session->req)->buf = NULL; + + if (msg_type == BT_AVDTP_ACCEPT) { + GET_CAP_REQ(session->req)->status = 0; + if (session->req != NULL) { + GET_CAP_REQ(session->req)->buf = buf; + } + } else if (msg_type == BT_AVDTP_REJECT) { + GET_CAP_REQ(session->req)->status = net_buf_pull_u8(buf); + } else if (msg_type == BT_AVDTP_GEN_REJECT) { + GET_CAP_REQ(session->req)->status = BT_AVDTP_NOT_SUPPORTED_COMMAND; + } + AVDTP_LOCK(); + session->req = NULL; + AVDTP_UNLOCK(); + if (req->func != NULL) { + req->func(req); + } + } +} + +static void avdtp_process_configuration(struct bt_avdtp *session, + struct net_buf *buf, uint8_t msg_type, uint8_t tid) +{ + if (msg_type == BT_AVDTP_CMD) { + int err = 0; + struct bt_avdtp_sep *sep; + struct net_buf *rsp_buf; + uint8_t error_code = 0; + + sep = avdtp_get_sep(net_buf_pull_u8(buf) >> 2); + if ((sep == NULL) || (session->ops->set_configuration_ind == NULL)) { + err = -ENOTSUP; + } else { + if (sep->state == AVDTP_STREAMING) { + err = -ENOTSUP; + error_code = BT_AVDTP_BAD_STATE; + } else { + uint8_t int_seid; + + /* INT Stream Endpoint ID */ + int_seid = net_buf_pull_u8(buf); + err = session->ops->set_configuration_ind(session, + sep, int_seid, buf, &error_code); + } + } + + rsp_buf = avdtp_create_reply_pdu(err ? + BT_AVDTP_REJECT : BT_AVDTP_ACCEPT, + BT_AVDTP_PACKET_TYPE_SINGLE, + BT_AVDTP_SET_CONFIGURATION, tid); + if (!rsp_buf) { + return; + } + + if (err) { + if (error_code == 0) { + error_code = BT_AVDTP_BAD_ACP_SEID; + } + LOG_DBG("set configuration err code:%d", error_code); + /* Service Category: Media Codec */ + net_buf_add_u8(rsp_buf, BT_AVDTP_SERVICE_MEDIA_CODEC); + /* Length Of Service Capability */ + net_buf_add_u8(rsp_buf, 0); + /* ERROR CODE */ + net_buf_add_u8(rsp_buf, error_code); + } else { + sep->state = AVDTP_CONFIGURED; + } + + err = bt_l2cap_chan_send(&session->br_chan.chan, rsp_buf); + if (err < 0) { + net_buf_unref(rsp_buf); + LOG_ERR("Error:L2CAP send fail - result = %d", err); + return; + } + } else { + struct bt_avdtp_req *req = session->req; + + if (session->req == NULL) { + return; + } + k_work_cancel_delayable(&session->timeout_work); + if (msg_type == BT_AVDTP_ACCEPT) { + SET_CONF_REQ(req)->status = 0; + SET_CONF_REQ(req)->sep->state = AVDTP_CONFIGURED; + } else if (msg_type == BT_AVDTP_REJECT) { + /* Service Category */ + net_buf_pull_u8(buf); + SET_CONF_REQ(req)->status = net_buf_pull_u8(buf); + } else if (msg_type == BT_AVDTP_GEN_REJECT) { + SET_CONF_REQ(req)->status = BT_AVDTP_NOT_SUPPORTED_COMMAND; + } + AVDTP_LOCK(); + session->req = NULL; + AVDTP_UNLOCK(); + if (req->func != NULL) { + req->func(req); + } + } +} + +static void avdtp_set_configuration_handler(struct bt_avdtp *session, + struct net_buf *buf, uint8_t msg_type, uint8_t tid) +{ + avdtp_process_configuration(session, buf, msg_type, tid); +} + +static void avdtp_get_configuration_handler(struct bt_avdtp *session, + struct net_buf *buf, uint8_t msg_type, uint8_t tid) +{ + /* todo: is not supported now, reply reject */ + struct net_buf *rsp_buf; + int err; + + rsp_buf = avdtp_create_reply_pdu(BT_AVDTP_REJECT, + BT_AVDTP_PACKET_TYPE_SINGLE, + BT_AVDTP_GET_CONFIGURATION, tid); + if (!rsp_buf) { + LOG_ERR("Error: No Buff available"); + return; + } + + err = bt_l2cap_chan_send(&session->br_chan.chan, rsp_buf); + if (err < 0) { + net_buf_unref(rsp_buf); + LOG_ERR("Error:L2CAP send fail - result = %d", err); + return; + } +} + +static void avdtp_re_configure_handler(struct bt_avdtp *session, + struct net_buf *buf, uint8_t msg_type, uint8_t tid) +{ + avdtp_process_configuration(session, buf, msg_type, tid); +} + +static void avdtp_open_handler(struct bt_avdtp *session, + struct net_buf *buf, uint8_t msg_type, uint8_t tid) +{ + if (msg_type == BT_AVDTP_CMD) { + int err = 0; + struct bt_avdtp_sep *sep; + struct net_buf *rsp_buf; + uint8_t error_code = 0; + + sep = avdtp_get_sep(net_buf_pull_u8(buf) >> 2); + if ((sep == NULL) || (session->ops->open_ind == NULL)) { + err = -ENOTSUP; + } else { + if (sep->state != AVDTP_CONFIGURED) { + err = -ENOTSUP; + error_code = BT_AVDTP_BAD_STATE; + } else { + err = session->ops->open_ind(session, sep, &error_code); + } + } + + rsp_buf = avdtp_create_reply_pdu(err ? + BT_AVDTP_REJECT : BT_AVDTP_ACCEPT, + BT_AVDTP_PACKET_TYPE_SINGLE, + BT_AVDTP_OPEN, tid); + if (!rsp_buf) { + return; + } + + if (err) { + if (error_code == 0) { + error_code = BT_AVDTP_BAD_ACP_SEID; + } + LOG_DBG("open_ind err code:%d", error_code); + net_buf_add_u8(rsp_buf, error_code); + } else { + session->current_sep = sep; + sep->state = AVDTP_OPENING; + sep->sep_info.inuse = 1u; + } + + err = bt_l2cap_chan_send(&session->br_chan.chan, rsp_buf); + if (err < 0) { + net_buf_unref(rsp_buf); + LOG_ERR("Error:L2CAP send fail - result = %d", err); + return; + } + } else { + struct bt_avdtp_req *req = session->req; + + if (session->req == NULL) { + return; + } + k_work_cancel_delayable(&session->timeout_work); + if (msg_type == BT_AVDTP_ACCEPT) { + OPEN_REQ(req)->status = 0; + OPEN_REQ(req)->sep->state = AVDTP_OPENING; + if (!avdtp_media_connect(session, OPEN_REQ(req)->sep)) { + return; + } + } else if (msg_type == BT_AVDTP_REJECT) { + OPEN_REQ(req)->status = net_buf_pull_u8(buf); + } else if (msg_type == BT_AVDTP_GEN_REJECT) { + OPEN_REQ(req)->status = BT_AVDTP_NOT_SUPPORTED_COMMAND; + } + if (OPEN_REQ(req)->status) { + /* wait the media l2cap is established */ + AVDTP_LOCK(); + session->req = NULL; + AVDTP_UNLOCK(); + if (req->func != NULL) { + req->func(req); + } + } + } +} + +static void avdtp_start_handler(struct bt_avdtp *session, + struct net_buf *buf, uint8_t msg_type, uint8_t tid) +{ + if (msg_type == BT_AVDTP_CMD) { + int err = 0; + struct bt_avdtp_sep *sep; + struct net_buf *rsp_buf; + uint8_t error_code = 0; + + sep = avdtp_get_sep(net_buf_pull_u8(buf) >> 2); + if ((sep == NULL) || (session->ops->start_ind == NULL)) { + err = -ENOTSUP; + } else { + if (sep->state != AVDTP_OPEN) { + err = -ENOTSUP; + error_code = BT_AVDTP_BAD_STATE; + } else { + err = session->ops->start_ind(session, sep, &error_code); + } + } + + rsp_buf = avdtp_create_reply_pdu(err ? + BT_AVDTP_REJECT : BT_AVDTP_ACCEPT, + BT_AVDTP_PACKET_TYPE_SINGLE, + BT_AVDTP_START, tid); + if (!rsp_buf) { + return; + } + + if (err) { + if (error_code == 0) { + error_code = BT_AVDTP_BAD_ACP_SEID; + } + LOG_DBG("start err code:%d", error_code); + net_buf_add_u8(rsp_buf, error_code); + } else { + sep->state = AVDTP_STREAMING; + } + + err = bt_l2cap_chan_send(&session->br_chan.chan, rsp_buf); + if (err < 0) { + net_buf_unref(rsp_buf); + LOG_ERR("Error:L2CAP send fail - result = %d", err); + return; + } + } else { + struct bt_avdtp_req *req = session->req; + + if (session->req == NULL) { + return; + } + k_work_cancel_delayable(&session->timeout_work); + if (msg_type == BT_AVDTP_ACCEPT) { + START_REQ(req)->status = 0; + START_REQ(req)->sep->state = AVDTP_STREAMING; + } else if (msg_type == BT_AVDTP_REJECT) { + uint8_t acp_seid; + + acp_seid = net_buf_pull_u8(buf); + if (acp_seid != START_REQ(req)->acp_stream_ep_id) { + return; + } + + START_REQ(req)->status = net_buf_pull_u8(buf); + } else if (msg_type == BT_AVDTP_GEN_REJECT) { + START_REQ(req)->status = BT_AVDTP_NOT_SUPPORTED_COMMAND; + } + AVDTP_LOCK(); + session->req = NULL; + AVDTP_UNLOCK(); + if (req->func != NULL) { + req->func(req); + } + } +} + +static void avdtp_close_handler(struct bt_avdtp *session, + struct net_buf *buf, uint8_t msg_type, uint8_t tid) +{ + if (msg_type == BT_AVDTP_CMD) { + int err = 0; + struct bt_avdtp_sep *sep; + struct net_buf *rsp_buf; + uint8_t error_code = 0; + + sep = avdtp_get_sep(net_buf_pull_u8(buf) >> 2); + if ((sep == NULL) || (session->ops->close_ind == NULL)) { + err = -ENOTSUP; + } else { + if (sep->state != AVDTP_OPEN) { + err = -ENOTSUP; + error_code = BT_AVDTP_BAD_STATE; + } else { + err = session->ops->close_ind(session, sep, &error_code); + } + } + + rsp_buf = avdtp_create_reply_pdu(err ? + BT_AVDTP_REJECT : BT_AVDTP_ACCEPT, + BT_AVDTP_PACKET_TYPE_SINGLE, + BT_AVDTP_CLOSE, tid); + if (!rsp_buf) { + return; + } + + if (err) { + if (error_code == 0) { + error_code = BT_AVDTP_BAD_ACP_SEID; + } + LOG_DBG("close err code:%d", error_code); + net_buf_add_u8(rsp_buf, error_code); + } else { + sep->state = AVDTP_CONFIGURED; + sep->sep_info.inuse = 0u; + } + + err = bt_l2cap_chan_send(&session->br_chan.chan, rsp_buf); + if (err < 0) { + net_buf_unref(rsp_buf); + LOG_ERR("Error:L2CAP send fail - result = %d", err); + return; + } + } +} + +static void avdtp_suspend_handler(struct bt_avdtp *session, + struct net_buf *buf, uint8_t msg_type, uint8_t tid) +{ + if (msg_type == BT_AVDTP_CMD) { + int err = 0; + struct bt_avdtp_sep *sep; + struct net_buf *rsp_buf; + uint8_t error_code = 0; + + sep = avdtp_get_sep(net_buf_pull_u8(buf) >> 2); + if ((sep == NULL) || (session->ops->suspend_ind == NULL)) { + err = -ENOTSUP; + } else { + if (sep->state != AVDTP_STREAMING) { + err = -ENOTSUP; + error_code = BT_AVDTP_BAD_STATE; + } else { + err = session->ops->suspend_ind(session, sep, &error_code); + } + } + + rsp_buf = avdtp_create_reply_pdu(err ? + BT_AVDTP_REJECT : BT_AVDTP_ACCEPT, + BT_AVDTP_PACKET_TYPE_SINGLE, + BT_AVDTP_SUSPEND, tid); + if (!rsp_buf) { + return; + } + + if (err) { + if (error_code == 0) { + error_code = BT_AVDTP_BAD_ACP_SEID; + } + LOG_DBG("suspend err code:%d", error_code); + net_buf_add_u8(rsp_buf, error_code); + } else { + sep->state = AVDTP_OPEN; + } + + err = bt_l2cap_chan_send(&session->br_chan.chan, rsp_buf); + if (err < 0) { + net_buf_unref(rsp_buf); + LOG_ERR("Error:L2CAP send fail - result = %d", err); + return; + } + } +} + +static void avdtp_abort_handler(struct bt_avdtp *session, + struct net_buf *buf, uint8_t msg_type, uint8_t tid) +{ + if (msg_type == BT_AVDTP_CMD) { + int err = 0; + struct bt_avdtp_sep *sep; + struct net_buf *rsp_buf; + uint8_t error_code = 0; + + sep = avdtp_get_sep(net_buf_pull_u8(buf) >> 2); + if ((sep == NULL) || (session->ops->abort_ind == NULL)) { + err = -ENOTSUP; + } else { + err = session->ops->abort_ind(session, sep, &error_code); + } + + rsp_buf = avdtp_create_reply_pdu(err ? + BT_AVDTP_REJECT : BT_AVDTP_ACCEPT, + BT_AVDTP_PACKET_TYPE_SINGLE, + BT_AVDTP_ABORT, tid); + if (!rsp_buf) { + return; + } + + if (err) { + if (error_code == 0) { + error_code = BT_AVDTP_BAD_ACP_SEID; + } + LOG_DBG("abort err code:%d", error_code); + net_buf_add_u8(rsp_buf, error_code); + } else { + sep->state = AVDTP_IDLE; + } + + err = bt_l2cap_chan_send(&session->br_chan.chan, rsp_buf); + if (err < 0) { + net_buf_unref(rsp_buf); + LOG_ERR("Error:L2CAP send fail - result = %d", err); + return; + } + } +} + +/* Timeout handler */ +static void avdtp_timeout(struct k_work *work) +{ + struct bt_avdtp_req *req = (AVDTP_KWORK(work))->req; + + /* add process code */ + /* Gracefully Disconnect the Signalling and streaming L2cap chann*/ + if (req) { + LOG_DBG("Failed Signal_id = %d", req->sig); + + switch (req->sig) { + case BT_AVDTP_DISCOVER: + DISCOVER_REQ(req)->status = BT_AVDTP_TIME_OUT; + req->func(req); + break; + case BT_AVDTP_GET_CAPABILITIES: + GET_CAP_REQ(req)->status = BT_AVDTP_TIME_OUT; + req->func(req); + break; + case BT_AVDTP_SET_CONFIGURATION: + SET_CONF_REQ(req)->status = BT_AVDTP_TIME_OUT; + req->func(req); + break; + case BT_AVDTP_OPEN: + OPEN_REQ(req)->status = BT_AVDTP_TIME_OUT; + req->func(req); + break; + case BT_AVDTP_START: + START_REQ(req)->status = BT_AVDTP_TIME_OUT; + req->func(req); + break; + default: + break; + } + + AVDTP_KWORK(work)->req = NULL; + } +} + static int avdtp_send(struct bt_avdtp *session, - struct net_buf *buf, struct bt_avdtp_req *req) + struct net_buf *buf, struct bt_avdtp_req *req) { int result; struct bt_avdtp_single_sig_hdr *hdr; + AVDTP_LOCK(); + if (session->req != NULL) { + AVDTP_UNLOCK(); + return -EBUSY; + } + session->req = req; + AVDTP_UNLOCK(); hdr = (struct bt_avdtp_single_sig_hdr *)buf->data; result = bt_l2cap_chan_send(&session->br_chan.chan, buf); if (result < 0) { LOG_ERR("Error:L2CAP send fail - result = %d", result); net_buf_unref(buf); + AVDTP_LOCK(); + session->req = NULL; + AVDTP_UNLOCK(); return result; } @@ -75,9 +811,10 @@ static int avdtp_send(struct bt_avdtp *session, req->tid = AVDTP_GET_TR_ID(hdr->hdr); LOG_DBG("sig 0x%02X, tid 0x%02X", req->sig, req->tid); - session->req = req; + /* Init the timer */ + k_work_init_delayable(&session->timeout_work, avdtp_timeout); /* Start timeout work */ - k_work_reschedule(&session->req->timeout_work, AVDTP_TIMEOUT); + k_work_reschedule(&session->timeout_work, AVDTP_TIMEOUT); return result; } @@ -96,7 +833,7 @@ static struct net_buf *avdtp_create_pdu(uint8_t msg_type, hdr = net_buf_add(buf, sizeof(*hdr)); hdr->hdr = (msg_type | pkt_type << AVDTP_PKT_POSITION | - tid++ << AVDTP_TID_POSITION); + tid++ << AVDTP_TID_POSITION); tid %= 16; /* Loop for 16*/ hdr->signal_id = sig_id & AVDTP_SIGID_MASK; @@ -104,15 +841,6 @@ static struct net_buf *avdtp_create_pdu(uint8_t msg_type, return buf; } -/* Timeout handler */ -static void avdtp_timeout(struct k_work *work) -{ - LOG_DBG("Failed Signal_id = %d", (AVDTP_KWORK(work))->sig); - - /* Gracefully Disconnect the Signalling and streaming L2cap chann*/ - -} - /* L2CAP Interface callbacks */ void bt_avdtp_l2cap_connected(struct bt_l2cap_chan *chan) { @@ -125,9 +853,9 @@ void bt_avdtp_l2cap_connected(struct bt_l2cap_chan *chan) session = AVDTP_CHAN(chan); LOG_DBG("chan %p session %p", chan, session); - /* Init the timer */ - k_work_init_delayable(&session->req->timeout_work, avdtp_timeout); + /* notify a2dp connection result */ + session->ops->connected(session); } void bt_avdtp_l2cap_disconnected(struct bt_l2cap_chan *chan) @@ -136,7 +864,11 @@ void bt_avdtp_l2cap_disconnected(struct bt_l2cap_chan *chan) LOG_DBG("chan %p session %p", chan, session); session->br_chan.chan.conn = NULL; - /* Clear the Pending req if set*/ + session->signalling_l2cap_connected = 0; + /* todo: Clear the Pending req if set*/ + + /* notify a2dp disconnect */ + session->ops->disconnected(session); } void bt_avdtp_l2cap_encrypt_changed(struct bt_l2cap_chan *chan, uint8_t status) @@ -144,11 +876,28 @@ void bt_avdtp_l2cap_encrypt_changed(struct bt_l2cap_chan *chan, uint8_t status) LOG_DBG(""); } +static const struct { + uint8_t sig_id; + void (*func)(struct bt_avdtp *session, struct net_buf *buf, + uint8_t msg_type, uint8_t tid); +} handler[] = { + {BT_AVDTP_DISCOVER, avdtp_discover_handler}, + {BT_AVDTP_GET_CAPABILITIES, avdtp_get_capabilities_handler}, + {BT_AVDTP_SET_CONFIGURATION, avdtp_set_configuration_handler}, + {BT_AVDTP_GET_CONFIGURATION, avdtp_get_configuration_handler}, + {BT_AVDTP_RECONFIGURE, avdtp_re_configure_handler}, + {BT_AVDTP_OPEN, avdtp_open_handler}, + {BT_AVDTP_START, avdtp_start_handler}, + {BT_AVDTP_CLOSE, avdtp_close_handler}, + {BT_AVDTP_SUSPEND, avdtp_suspend_handler}, + {BT_AVDTP_ABORT, avdtp_abort_handler}, +}; + int bt_avdtp_l2cap_recv(struct bt_l2cap_chan *chan, struct net_buf *buf) { struct bt_avdtp_single_sig_hdr *hdr; struct bt_avdtp *session = AVDTP_CHAN(chan); - uint8_t i, msgtype, sigid, tid; + uint8_t i, msgtype, pack_type, sigid, tid; if (buf->len < sizeof(*hdr)) { LOG_ERR("Recvd Wrong AVDTP Header"); @@ -156,11 +905,36 @@ int bt_avdtp_l2cap_recv(struct bt_l2cap_chan *chan, struct net_buf *buf) } hdr = net_buf_pull_mem(buf, sizeof(*hdr)); + pack_type = AVDTP_GET_PKT_TYPE(hdr->hdr); msgtype = AVDTP_GET_MSG_TYPE(hdr->hdr); sigid = AVDTP_GET_SIG_ID(hdr->signal_id); tid = AVDTP_GET_TR_ID(hdr->hdr); - LOG_DBG("msg_type[0x%02x] sig_id[0x%02x] tid[0x%02x]", msgtype, sigid, tid); + LOG_DBG("pack_type[0x%02x] msg_type[0x%02x] sig_id[0x%02x] tid[0x%02x]", + pack_type, msgtype, sigid, tid); + + /* TODO: only support single packet now */ + if (pack_type != BT_AVDTP_PACKET_TYPE_SINGLE) { + if (pack_type == BT_AVDTP_PACKET_TYPE_START) { + struct net_buf *rsp_buf; + int err; + + sigid = net_buf_pull_u8(buf); + rsp_buf = avdtp_create_reply_pdu(BT_AVDTP_REJECT, + BT_AVDTP_PACKET_TYPE_SINGLE, + sigid, tid); + if (!rsp_buf) { + LOG_ERR("Error: No Buff available"); + return 0; + } + err = bt_l2cap_chan_send(&session->br_chan.chan, rsp_buf); + if (err < 0) { + net_buf_unref(rsp_buf); + LOG_ERR("Error:L2CAP send fail - result = %d", err); + } + } + return 0; + } /* validate if there is an outstanding resp expected*/ if (msgtype != BT_AVDTP_CMD) { @@ -170,7 +944,7 @@ int bt_avdtp_l2cap_recv(struct bt_l2cap_chan *chan, struct net_buf *buf) } if (session->req->sig != sigid || - session->req->tid != tid) { + session->req->tid != tid) { LOG_DBG("Peer mismatch resp, expected sig[0x%02x]" "tid[0x%02x]", session->req->sig, session->req->tid); @@ -178,9 +952,14 @@ int bt_avdtp_l2cap_recv(struct bt_l2cap_chan *chan, struct net_buf *buf) } } + if (!session) { + LOG_DBG("Error: Session not valid"); + return 0; + } + for (i = 0U; i < ARRAY_SIZE(handler); i++) { if (sigid == handler[i].sig_id) { - handler[i].func(session, buf, msgtype); + handler[i].func(session, buf, msgtype, tid); return 0; } } @@ -202,11 +981,13 @@ int bt_avdtp_connect(struct bt_conn *conn, struct bt_avdtp *session) return -EINVAL; } + session->signalling_l2cap_connected = 1; + session->br_chan.rx.mtu = BT_L2CAP_RX_MTU; session->br_chan.chan.ops = &ops; session->br_chan.required_sec_level = BT_SECURITY_L2; return bt_l2cap_chan_connect(conn, &session->br_chan.chan, - BT_L2CAP_PSM_AVDTP); + BT_L2CAP_PSM_AVDTP); } int bt_avdtp_disconnect(struct bt_avdtp *session) @@ -217,19 +998,15 @@ int bt_avdtp_disconnect(struct bt_avdtp *session) LOG_DBG("session %p", session); + session->signalling_l2cap_connected = 0; return bt_l2cap_chan_disconnect(&session->br_chan.chan); } int bt_avdtp_l2cap_accept(struct bt_conn *conn, struct bt_l2cap_server *server, - struct bt_l2cap_chan **chan) + struct bt_l2cap_chan **chan) { struct bt_avdtp *session = NULL; int result; - static const struct bt_l2cap_chan_ops ops = { - .connected = bt_avdtp_l2cap_connected, - .disconnected = bt_avdtp_l2cap_disconnected, - .recv = bt_avdtp_l2cap_recv, - }; LOG_DBG("conn %p", conn); /* Get the AVDTP session from upper layer */ @@ -237,9 +1014,35 @@ int bt_avdtp_l2cap_accept(struct bt_conn *conn, struct bt_l2cap_server *server, if (result < 0) { return result; } - session->br_chan.chan.ops = &ops; - session->br_chan.rx.mtu = BT_AVDTP_MAX_MTU; - *chan = &session->br_chan.chan; + + if (session->signalling_l2cap_connected == 0) { + static const struct bt_l2cap_chan_ops ops = { + .connected = bt_avdtp_l2cap_connected, + .disconnected = bt_avdtp_l2cap_disconnected, + .recv = bt_avdtp_l2cap_recv, + }; + session->signalling_l2cap_connected = 1; + session->br_chan.chan.ops = &ops; + session->br_chan.rx.mtu = BT_L2CAP_RX_MTU; + *chan = &session->br_chan.chan; + } else { + /* get the current opening endpoint */ + if (session->current_sep != NULL) { + static const struct bt_l2cap_chan_ops ops = { + .connected = bt_avdtp_media_l2cap_connected, + .disconnected = bt_avdtp_media_l2cap_disconnected, + .recv = bt_avdtp_media_l2cap_recv + }; + session->current_sep->session = session; + session->current_sep->chan.chan.ops = &ops; + session->current_sep->chan.rx.mtu = BT_L2CAP_RX_MTU; + session->current_sep->chan.required_sec_level = + BT_SECURITY_L2; + *chan = &session->current_sep->chan.chan; + session->current_sep = NULL; + } + } + return 0; } @@ -258,27 +1061,27 @@ int bt_avdtp_register(struct bt_avdtp_event_cb *cb) } int bt_avdtp_register_sep(uint8_t media_type, uint8_t role, - struct bt_avdtp_seid_lsep *lsep) + struct bt_avdtp_sep *sep) { LOG_DBG(""); - static uint8_t bt_avdtp_seid = BT_AVDTP_MIN_SEID; + static uint8_t bt_avdtp_sep = BT_AVDTP_MIN_SEID; - if (!lsep) { + if (!sep) { return -EIO; } - if (bt_avdtp_seid == BT_AVDTP_MAX_SEID) { + if (bt_avdtp_sep == BT_AVDTP_MAX_SEID) { return -EIO; } - lsep->sep.id = bt_avdtp_seid++; - lsep->sep.inuse = 0U; - lsep->sep.media_type = media_type; - lsep->sep.tsep = role; + sep->sep_info.id = bt_avdtp_sep++; + sep->sep_info.inuse = 0U; + sep->sep_info.media_type = media_type; + sep->sep_info.tsep = role; + sep->state = AVDTP_IDLE; - lsep->next = lseps; - lseps = lsep; + sys_slist_append(&seps, &sep->_node); return 0; } @@ -306,7 +1109,7 @@ int bt_avdtp_init(void) /* AVDTP Discover Request */ int bt_avdtp_discover(struct bt_avdtp *session, - struct bt_avdtp_discover_params *param) + struct bt_avdtp_discover_params *param) { struct net_buf *buf; @@ -317,14 +1120,264 @@ int bt_avdtp_discover(struct bt_avdtp *session, } buf = avdtp_create_pdu(BT_AVDTP_CMD, - BT_AVDTP_PACKET_TYPE_SINGLE, - BT_AVDTP_DISCOVER); + BT_AVDTP_PACKET_TYPE_SINGLE, + BT_AVDTP_DISCOVER); + if (!buf) { + LOG_ERR("Error: No Buff available"); + return -ENOMEM; + } + + return avdtp_send(session, buf, ¶m->req); +} + +int bt_avdtp_parse_sep(struct net_buf *buf, struct bt_avdtp_sep_info *sep_info) +{ + struct bt_avdtp_sep_data *sep_data; + + if ((sep_info != NULL) && (buf != NULL)) { + if (buf->len >= sizeof(*sep_data)) { + sep_data = net_buf_pull_mem(buf, sizeof(*sep_data)); + sep_info->inuse = sep_data->inuse; + sep_info->id = sep_data->id; + sep_info->tsep = sep_data->tsep; + sep_info->media_type = sep_data->media_type; + return 0; + } + } + + return -EINVAL; +} + +/* AVDTP Get Capabilities Request */ +int bt_avdtp_get_capabilities(struct bt_avdtp *session, + struct bt_avdtp_get_capabilities_params *param) +{ + struct net_buf *buf; + + LOG_DBG(""); + if (!param || !session) { + LOG_DBG("Error: Callback/Session not valid"); + return -EINVAL; + } + + buf = avdtp_create_pdu(BT_AVDTP_CMD, + BT_AVDTP_PACKET_TYPE_SINGLE, + BT_AVDTP_GET_CAPABILITIES); if (!buf) { LOG_ERR("Error: No Buff available"); return -ENOMEM; } /* Body of the message */ + net_buf_add_u8(buf, (param->stream_endpoint_id << 2u)); return avdtp_send(session, buf, ¶m->req); } + +int bt_avdtp_parse_capability_codec(struct net_buf *buf, + uint8_t *codec_type, uint8_t **codec_info_element, + uint16_t *codec_info_element_len) +{ + uint8_t data; + uint8_t length; + + if (!buf) { + LOG_DBG("Error: buf not valid"); + return -EINVAL; + } + + while (buf->len) { + data = net_buf_pull_u8(buf); + switch (data) { + case BT_AVDTP_SERVICE_MEDIA_TRANSPORT: + case BT_AVDTP_SERVICE_REPORTING: + case BT_AVDTP_SERVICE_MEDIA_RECOVERY: + case BT_AVDTP_SERVICE_CONTENT_PROTECTION: + case BT_AVDTP_SERVICE_HEADER_COMPRESSION: + case BT_AVDTP_SERVICE_MULTIPLEXING: + case BT_AVDTP_SERVICE_DELAY_REPORTING: + length = net_buf_pull_u8(buf); + if (length > 0) { + net_buf_pull_mem(buf, length); + } + break; + + case BT_AVDTP_SERVICE_MEDIA_CODEC: + length = net_buf_pull_u8(buf); + if (length > 3) { + data = net_buf_pull_u8(buf); + if (net_buf_tailroom(buf) < (length - 1)) { + return -EINVAL; + } + if (data == BT_AVDTP_AUDIO) { + data = net_buf_pull_u8(buf); + *codec_type = data; + *codec_info_element_len = (length - 2); + *codec_info_element = + net_buf_pull_mem(buf, (*codec_info_element_len)); + return 0; + } + } + break; + + default: + break; + } + } + return -EIO; +} + +static int avdtp_process_configure_command(struct bt_avdtp *session, + uint8_t cmd, + struct bt_avdtp_set_configuration_params *param) +{ + struct net_buf *buf; + + LOG_DBG(""); + if (!param || !session) { + LOG_DBG("Error: Callback/Session not valid"); + return -EINVAL; + } + + buf = avdtp_create_pdu(BT_AVDTP_CMD, + BT_AVDTP_PACKET_TYPE_SINGLE, + cmd); + if (!buf) { + LOG_ERR("Error: No Buff available"); + return -ENOMEM; + } + + /* Body of the message */ + /* ACP Stream Endpoint ID */ + net_buf_add_u8(buf, (param->acp_stream_ep_id << 2u)); + /* INT Stream Endpoint ID */ + net_buf_add_u8(buf, (param->int_stream_endpoint_id << 2u)); + /* Service Category: Media Transport */ + net_buf_add_u8(buf, BT_AVDTP_SERVICE_MEDIA_TRANSPORT); + /* LOSC */ + net_buf_add_u8(buf, 0); + /* Service Category: Media Codec */ + net_buf_add_u8(buf, BT_AVDTP_SERVICE_MEDIA_CODEC); + /* LOSC */ + net_buf_add_u8(buf, param->codec_specific_ie_len + 2); + /* Media Type */ + net_buf_add_u8(buf, param->media_type << 4U); + /* Media Codec Type */ + net_buf_add_u8(buf, param->media_codec_type); + /* Codec Info Element */ + net_buf_add_mem(buf, param->codec_specific_ie, param->codec_specific_ie_len); + + return avdtp_send(session, buf, ¶m->req); +} + +int bt_avdtp_set_configuration(struct bt_avdtp *session, + struct bt_avdtp_set_configuration_params *param) +{ + if (!param || !session || !param->sep) { + LOG_DBG("Error: parameters not valid"); + return -EINVAL; + } + + if (param->sep->state != AVDTP_IDLE) { + return -EINVAL; + } + + return avdtp_process_configure_command(session, BT_AVDTP_SET_CONFIGURATION, param); +} + +int bt_avdtp_reconfigure(struct bt_avdtp *session, + struct bt_avdtp_set_configuration_params *param) +{ + if (!param || !session || !param->sep) { + LOG_DBG("Error: parameters not valid"); + return -EINVAL; + } + + if (param->sep->state != AVDTP_OPEN) { + return -EINVAL; + } + + return avdtp_process_configure_command(session, BT_AVDTP_RECONFIGURE, param); +} + +int bt_avdtp_open(struct bt_avdtp *session, + struct bt_avdtp_open_params *param) +{ + struct net_buf *buf; + + LOG_DBG(""); + if (!param || !session || !param->sep) { + LOG_DBG("Error: parameters not valid"); + return -EINVAL; + } + + if (param->sep->state != AVDTP_CONFIGURED) { + return -EINVAL; + } + + buf = avdtp_create_pdu(BT_AVDTP_CMD, + BT_AVDTP_PACKET_TYPE_SINGLE, + BT_AVDTP_OPEN); + if (!buf) { + LOG_ERR("Error: No Buff available"); + return -ENOMEM; + } + + /* Body of the message */ + /* ACP Stream Endpoint ID */ + net_buf_add_u8(buf, (param->acp_stream_ep_id << 2u)); + + return avdtp_send(session, buf, ¶m->req); +} + +int bt_avdtp_start(struct bt_avdtp *session, + struct bt_avdtp_start_params *param) +{ + struct net_buf *buf; + + LOG_DBG(""); + if (!param || !session || !param->sep) { + LOG_DBG("Error: parameters not valid"); + return -EINVAL; + } + + if (param->sep->state != AVDTP_OPEN) { + return -EINVAL; + } + + buf = avdtp_create_pdu(BT_AVDTP_CMD, + BT_AVDTP_PACKET_TYPE_SINGLE, + BT_AVDTP_START); + if (!buf) { + LOG_ERR("Error: No Buff available"); + return -ENOMEM; + } + + /* Body of the message */ + /* ACP Stream Endpoint ID */ + net_buf_add_u8(buf, (param->acp_stream_ep_id << 2u)); + + return avdtp_send(session, buf, ¶m->req); +} + +int bt_avdtp_send_media_data(struct bt_avdtp_sep *sep, struct net_buf *buf) +{ + int err; + + if (sep->state != AVDTP_STREAMING) { + return -EIO; + } + + err = bt_l2cap_chan_send(&sep->chan.chan, buf); + if (err < 0) { + LOG_ERR("Error:L2CAP send fail - err = %d", err); + return err; + } + + return err; +} + +uint32_t bt_avdtp_get_media_mtu(struct bt_avdtp_sep *sep) +{ + return sep->chan.tx.mtu; +} diff --git a/subsys/bluetooth/host/classic/avdtp_internal.h b/subsys/bluetooth/host/classic/avdtp_internal.h index 5b971fcaac786..dc756cb11a705 100644 --- a/subsys/bluetooth/host/classic/avdtp_internal.h +++ b/subsys/bluetooth/host/classic/avdtp_internal.h @@ -2,6 +2,7 @@ * avdtp_internal.h - avdtp handling * Copyright (c) 2015-2016 Intel Corporation + * Copyright 2021,2024 NXP * * SPDX-License-Identifier: Apache-2.0 */ @@ -82,22 +83,38 @@ #define BT_AVDTP_ERR_UNSUPPORTED_CONFIGURAION 0x29 #define BT_AVDTP_ERR_BAD_STATE 0x31 -#define BT_AVDTP_MAX_MTU BT_L2CAP_RX_MTU - #define BT_AVDTP_MIN_SEID 0x01 #define BT_AVDTP_MAX_SEID 0x3E struct bt_avdtp; struct bt_avdtp_req; +struct bt_avdtp_sep_info; + +/** @brief AVDTP SEID Information AVDTP_SPEC V13 Table 8.8 */ +struct bt_avdtp_sep_data { +#ifdef CONFIG_LITTLE_ENDIAN + uint8_t rfa0:1; + uint8_t inuse:1; + uint8_t id:6; + uint8_t rfa1:3; + uint8_t tsep:1; + uint8_t media_type:4; +#else + uint8_t id:6; + uint8_t inuse:1; + uint8_t rfa0:1; + uint8_t media_type:4; + uint8_t tsep:1; + uint8_t rfa1:3; +#endif +} __packed; -typedef int (*bt_avdtp_func_t)(struct bt_avdtp *session, - struct bt_avdtp_req *req); +typedef int (*bt_avdtp_func_t)(struct bt_avdtp_req *req); struct bt_avdtp_req { uint8_t sig; uint8_t tid; bt_avdtp_func_t func; - struct k_work_delayable timeout_work; }; struct bt_avdtp_single_sig_hdr { @@ -105,47 +122,108 @@ struct bt_avdtp_single_sig_hdr { uint8_t signal_id; } __packed; -#define BT_AVDTP_SIG_HDR_LEN sizeof(struct bt_avdtp_single_sig_hdr) - -struct bt_avdtp_ind_cb { - /* - * discovery_ind; - * get_capabilities_ind; - * set_configuration_ind; - * open_ind; - * start_ind; - * suspend_ind; - * close_ind; - */ +struct bt_avdtp_media_hdr { +#ifdef CONFIG_LITTLE_ENDIAN + uint8_t CSRC_count:4; + uint8_t header_extension:1; + uint8_t padding:1; + uint8_t RTP_version:2; + uint8_t playload_type:7; + uint8_t marker:1; +#else + uint8_t RTP_version:2; + uint8_t padding:1; + uint8_t header_extension:1; + uint8_t CSRC_count:4; + uint8_t marker:1; + uint8_t playload_type:7; +#endif + uint16_t sequence_number; + uint32_t time_stamp; + uint32_t synchronization_source; +} __packed; + +struct bt_avdtp_discover_params { + struct bt_avdtp_req req; + uint8_t status; + struct net_buf *buf; +}; + +struct bt_avdtp_get_capabilities_params { + struct bt_avdtp_req req; + uint8_t status; + uint8_t stream_endpoint_id; + struct net_buf *buf; }; -struct bt_avdtp_cap { - uint8_t cat; - uint8_t len; - uint8_t data[0]; +struct bt_avdtp_set_configuration_params { + struct bt_avdtp_req req; + struct bt_avdtp_sep *sep; + uint8_t status; + uint8_t acp_stream_ep_id; + uint8_t int_stream_endpoint_id; + uint8_t media_type; + uint8_t media_codec_type; + uint8_t codec_specific_ie_len; + uint8_t *codec_specific_ie; }; -struct bt_avdtp_sep { - uint8_t seid; - uint8_t len; - struct bt_avdtp_cap caps[0]; +struct bt_avdtp_open_params { + struct bt_avdtp_req req; + struct bt_avdtp_sep *sep; + uint8_t status; + uint8_t acp_stream_ep_id; }; -struct bt_avdtp_discover_params { +struct bt_avdtp_start_params { struct bt_avdtp_req req; + struct bt_avdtp_sep *sep; uint8_t status; - struct bt_avdtp_sep *caps; + uint8_t acp_stream_ep_id; +}; + +struct bt_avdtp_ops_cb { + void (*connected)(struct bt_avdtp *session); + + void (*disconnected)(struct bt_avdtp *session); + + struct net_buf *(*alloc_buf)(struct bt_avdtp *session); + + int (*discovery_ind)(struct bt_avdtp *session, uint8_t *errcode); + + int (*get_capabilities_ind)(struct bt_avdtp *session, + struct bt_avdtp_sep *sep, struct net_buf *rsp_buf, uint8_t *errcode); + + int (*set_configuration_ind)(struct bt_avdtp *session, struct bt_avdtp_sep *sep, + uint8_t int_seid, struct net_buf *buf, uint8_t *errcode); + + int (*open_ind)(struct bt_avdtp *session, + struct bt_avdtp_sep *sep, uint8_t *errcode); + + int (*close_ind)(struct bt_avdtp *session, + struct bt_avdtp_sep *sep, uint8_t *errcode); + + int (*start_ind)(struct bt_avdtp *session, + struct bt_avdtp_sep *sep, uint8_t *errcode); + + int (*suspend_ind)(struct bt_avdtp *session, + struct bt_avdtp_sep *sep, uint8_t *errcode); + + int (*abort_ind)(struct bt_avdtp *session, + struct bt_avdtp_sep *sep, uint8_t *errcode); }; /** @brief Global AVDTP session structure. */ struct bt_avdtp { struct bt_l2cap_br_chan br_chan; - struct bt_avdtp_stream *streams; /* List of AV streams */ struct bt_avdtp_req *req; + const struct bt_avdtp_ops_cb *ops; + struct bt_avdtp_sep *current_sep; + struct k_work_delayable timeout_work; + uint8_t signalling_l2cap_connected; }; struct bt_avdtp_event_cb { - struct bt_avdtp_ind_cb *ind; int (*accept)(struct bt_conn *conn, struct bt_avdtp **session); }; @@ -163,8 +241,41 @@ int bt_avdtp_disconnect(struct bt_avdtp *session); /* AVDTP SEP register function */ int bt_avdtp_register_sep(uint8_t media_type, uint8_t role, - struct bt_avdtp_seid_lsep *sep); + struct bt_avdtp_sep *sep); /* AVDTP Discover Request */ int bt_avdtp_discover(struct bt_avdtp *session, struct bt_avdtp_discover_params *param); + +/* Parse the sep of discovered result */ +int bt_avdtp_parse_sep(struct net_buf *buf, struct bt_avdtp_sep_info *sep_info); + +/* AVDTP Get Capabilities */ +int bt_avdtp_get_capabilities(struct bt_avdtp *session, + struct bt_avdtp_get_capabilities_params *param); + +/* Parse the codec type of capabilities */ +int bt_avdtp_parse_capability_codec(struct net_buf *buf, uint8_t *codec_type, + uint8_t **codec_info_element, uint16_t *codec_info_element_len); + +/* AVDTP Set Configuration */ +int bt_avdtp_set_configuration(struct bt_avdtp *session, + struct bt_avdtp_set_configuration_params *param); + +/* AVDTP reconfigure */ +int bt_avdtp_reconfigure(struct bt_avdtp *session, + struct bt_avdtp_set_configuration_params *param); + +/* AVDTP OPEN */ +int bt_avdtp_open(struct bt_avdtp *session, + struct bt_avdtp_open_params *param); + +/* AVDTP START */ +int bt_avdtp_start(struct bt_avdtp *session, + struct bt_avdtp_start_params *param); + +/* AVDTP send data */ +int bt_avdtp_send_media_data(struct bt_avdtp_sep *sep, struct net_buf *buf); + +/* get media l2cap connection MTU */ +uint32_t bt_avdtp_get_media_mtu(struct bt_avdtp_sep *sep); From c56183529c240a7800ea4bd7a798d53ac9533c88 Mon Sep 17 00:00:00 2001 From: Mark Wang Date: Thu, 11 Apr 2024 16:41:06 +0800 Subject: [PATCH 1254/2849] tests: bluetooth: shell: add a2dp shell test implement the current a2dp APIs test. update the document. Signed-off-by: Mark Wang --- .../bluetooth/bluetooth-shell.rst | 89 +++ subsys/bluetooth/shell/CMakeLists.txt | 4 + subsys/bluetooth/shell/a2dp.c | 708 ++++++++++++++++++ tests/bluetooth/shell/prj_br.conf | 3 + 4 files changed, 804 insertions(+) create mode 100644 subsys/bluetooth/shell/a2dp.c diff --git a/doc/connectivity/bluetooth/bluetooth-shell.rst b/doc/connectivity/bluetooth/bluetooth-shell.rst index 0e54ab627c97c..80ae3c35b4335 100644 --- a/doc/connectivity/bluetooth/bluetooth-shell.rst +++ b/doc/connectivity/bluetooth/bluetooth-shell.rst @@ -445,6 +445,95 @@ On device A, you should have received the data: Incoming data channel 0x20000210 len 14 00000000: ff ff ff ff ff ff ff ff ff ff ff ff ff ff |........ ...... | +A2DP +***** +The :code:`a2dp` command exposes parts of the A2DP API. + +The following examples assume that you have two devices already connected. + +Here is a example connecting two devices: + * Source and Sink sides register a2dp callbacks. using :code:`a2dp register_cb`. + * Source and Sink sides register stream endpoints. using :code:`a2dp register_ep source sbc` and :code:`a2dp register_ep sink sbc`. + * Source establish A2dp connection. It will create the AVDTP Signaling and Media L2CAP channels. using :code:`a2dp connect`. + * Source and Sink side can discover remote device's stream endpoints. using :code:`a2dp discover_peer_eps` + * Source or Sink configure the stream to create the stream after discover remote's endpoints. using :code:`a2dp configure`. + * Source or Sink establish the stream. using :code:`a2dp establish`. + * Source or Sink start the media. using :code:`a2dp start`. + * Source test the media sending. using :code:`a2dp send_media` to send one test packet data. + +.. tabs:: + + .. group-tab:: Device A (Audio Source Side) + + .. code-block:: console + + uart:~$ a2dp register_cb + success + uart:~$ a2dp register_ep source sbc + SBC source endpoint is registered + uart:~$ a2dp connect + Bonded with XX:XX:XX:XX:XX:XX + Security changed: XX:XX:XX:XX:XX:XX level 2 + a2dp connected + uart:~$ a2dp discover_peer_eps + endpoint id: 1, (sink), (idle): + codec type: SBC + sample frequency: + 44100 + 48000 + channel mode: + Mono + Stereo + Joint-Stereo + Block Length: + 16 + Subbands: + 8 + Allocation Method: + Loudness + Bitpool Range: 18 - 35 + uart:~$ a2dp configure + success to configure + stream configured + uart:~$ a2dp establish + success to establish + stream established + uart:~$ a2dp start + success to start + stream started + uart:~$ a2dp send_media + frames num: 1, data length: 160 + data: 1, 2, 3, 4, 5, 6 ...... + + .. group-tab:: Device B (Audio Sink Side) + + .. code-block:: console + + uart:~$ a2dp register_cb + success + uart:~$ a2dp register_ep sink sbc + SBC sink endpoint is registered + + Connected: XX:XX:XX:XX:XX:XX + Bonded with XX:XX:XX:XX:XX:XX + Security changed: XX:XX:XX:XX:XX:XX level 2 + a2dp connected + + receive requesting config and accept + SBC configure success + sample rate 44100Hz + stream configured + + receive requesting establishment and accept + stream established + + receive requesting start and accept + stream started + + received, num of frames: 1, data length: 160 + data: 1, 2, 3, 4, 5, 6 ...... + ... + Logging ******* diff --git a/subsys/bluetooth/shell/CMakeLists.txt b/subsys/bluetooth/shell/CMakeLists.txt index 608721307e4a7..58d3ba5b2d951 100644 --- a/subsys/bluetooth/shell/CMakeLists.txt +++ b/subsys/bluetooth/shell/CMakeLists.txt @@ -21,6 +21,10 @@ zephyr_library_sources_ifdef( CONFIG_BT_RFCOMM rfcomm.c ) +zephyr_library_sources_ifdef( + CONFIG_BT_A2DP + a2dp.c + ) zephyr_library_sources_ifdef( CONFIG_BT_ISO iso.c diff --git a/subsys/bluetooth/shell/a2dp.c b/subsys/bluetooth/shell/a2dp.c new file mode 100644 index 0000000000000..b02891fa6c5b2 --- /dev/null +++ b/subsys/bluetooth/shell/a2dp.c @@ -0,0 +1,708 @@ +/* + * Copyright 2024 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "bt.h" + +struct bt_a2dp *default_a2dp; +static uint8_t a2dp_sink_sdp_registered; +static uint8_t a2dp_source_sdp_registered; +static uint8_t a2dp_initied; +BT_A2DP_SBC_SINK_EP_DEFAULT(sink_sbc_endpoint); +BT_A2DP_SBC_SOURCE_EP_DEFAULT(source_sbc_endpoint); +struct bt_a2dp_codec_ie peer_sbc_capabilities; +static struct bt_a2dp_ep peer_sbc_endpoint = { + .codec_cap = &peer_sbc_capabilities, +}; +static struct bt_a2dp_ep *found_peer_sbc_endpoint; +static struct bt_a2dp_ep *registered_sbc_endpoint; +static struct bt_a2dp_stream sbc_stream; +static struct bt_a2dp_stream_ops stream_ops; +static uint8_t media_data[] = { +0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, +0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, +0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, +0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, +0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, +0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, +0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, +0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, +0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, +0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, +}; + +NET_BUF_POOL_DEFINE(a2dp_tx_pool, CONFIG_BT_MAX_CONN, + BT_L2CAP_BUF_SIZE(CONFIG_BT_L2CAP_TX_MTU), + CONFIG_BT_CONN_TX_USER_DATA_SIZE, NULL); + +static struct bt_sdp_attribute a2dp_sink_attrs[] = { + BT_SDP_NEW_SERVICE, + BT_SDP_LIST( + BT_SDP_ATTR_SVCLASS_ID_LIST, + BT_SDP_TYPE_SIZE_VAR(BT_SDP_SEQ8, 3), /* 35 03 */ + BT_SDP_DATA_ELEM_LIST( + { + BT_SDP_TYPE_SIZE(BT_SDP_UUID16), /* 19 */ + BT_SDP_ARRAY_16(BT_SDP_AUDIO_SINK_SVCLASS) /* 11 0B */ + }, + ) + ), + BT_SDP_LIST( + BT_SDP_ATTR_PROTO_DESC_LIST, + BT_SDP_TYPE_SIZE_VAR(BT_SDP_SEQ8, 16),/* 35 10 */ + BT_SDP_DATA_ELEM_LIST( + { + BT_SDP_TYPE_SIZE_VAR(BT_SDP_SEQ8, 6),/* 35 06 */ + BT_SDP_DATA_ELEM_LIST( + { + BT_SDP_TYPE_SIZE(BT_SDP_UUID16), /* 19 */ + BT_SDP_ARRAY_16(BT_SDP_PROTO_L2CAP) /* 01 00 */ + }, + { + BT_SDP_TYPE_SIZE(BT_SDP_UINT16), /* 09 */ + BT_SDP_ARRAY_16(BT_UUID_AVDTP_VAL) /* 00 19 */ + }, + ) + }, + { + BT_SDP_TYPE_SIZE_VAR(BT_SDP_SEQ8, 6),/* 35 06 */ + BT_SDP_DATA_ELEM_LIST( + { + BT_SDP_TYPE_SIZE(BT_SDP_UUID16), /* 19 */ + BT_SDP_ARRAY_16(BT_UUID_AVDTP_VAL) /* 00 19 */ + }, + { + BT_SDP_TYPE_SIZE(BT_SDP_UINT16), /* 09 */ + BT_SDP_ARRAY_16(0X0100u) /* AVDTP version: 01 00 */ + }, + ) + }, + ) + ), + BT_SDP_LIST( + BT_SDP_ATTR_PROFILE_DESC_LIST, + BT_SDP_TYPE_SIZE_VAR(BT_SDP_SEQ8, 8), /* 35 08 */ + BT_SDP_DATA_ELEM_LIST( + { + BT_SDP_TYPE_SIZE_VAR(BT_SDP_SEQ8, 6), /* 35 06 */ + BT_SDP_DATA_ELEM_LIST( + { + BT_SDP_TYPE_SIZE(BT_SDP_UUID16), /* 19 */ + BT_SDP_ARRAY_16(BT_SDP_ADVANCED_AUDIO_SVCLASS) /* 11 0d */ + }, + { + BT_SDP_TYPE_SIZE(BT_SDP_UINT16), /* 09 */ + BT_SDP_ARRAY_16(0x0103U) /* 01 03 */ + }, + ) + }, + ) + ), + BT_SDP_SERVICE_NAME("A2DPSink"), + BT_SDP_SUPPORTED_FEATURES(0x0001U), +}; + +static struct bt_sdp_record a2dp_sink_rec = BT_SDP_RECORD(a2dp_sink_attrs); + +static struct bt_sdp_attribute a2dp_source_attrs[] = { + BT_SDP_NEW_SERVICE, + BT_SDP_LIST( + BT_SDP_ATTR_SVCLASS_ID_LIST, + BT_SDP_TYPE_SIZE_VAR(BT_SDP_SEQ8, 3), + BT_SDP_DATA_ELEM_LIST( + { + BT_SDP_TYPE_SIZE(BT_SDP_UUID16), + BT_SDP_ARRAY_16(BT_SDP_AUDIO_SOURCE_SVCLASS) + }, + ) + ), + BT_SDP_LIST( + BT_SDP_ATTR_PROTO_DESC_LIST, + BT_SDP_TYPE_SIZE_VAR(BT_SDP_SEQ8, 16), + BT_SDP_DATA_ELEM_LIST( + { + BT_SDP_TYPE_SIZE_VAR(BT_SDP_SEQ8, 6), + BT_SDP_DATA_ELEM_LIST( + { + BT_SDP_TYPE_SIZE(BT_SDP_UUID16), + BT_SDP_ARRAY_16(BT_SDP_PROTO_L2CAP) + }, + { + BT_SDP_TYPE_SIZE(BT_SDP_UINT16), + BT_SDP_ARRAY_16(BT_UUID_AVDTP_VAL) + }, + ) + }, + { + BT_SDP_TYPE_SIZE_VAR(BT_SDP_SEQ8, 6), + BT_SDP_DATA_ELEM_LIST( + { + BT_SDP_TYPE_SIZE(BT_SDP_UUID16), + BT_SDP_ARRAY_16(BT_UUID_AVDTP_VAL) + }, + { + BT_SDP_TYPE_SIZE(BT_SDP_UINT16), + BT_SDP_ARRAY_16(0X0100u) + }, + ) + }, + ) + ), + BT_SDP_LIST( + BT_SDP_ATTR_PROFILE_DESC_LIST, + BT_SDP_TYPE_SIZE_VAR(BT_SDP_SEQ8, 8), + BT_SDP_DATA_ELEM_LIST( + { + BT_SDP_TYPE_SIZE_VAR(BT_SDP_SEQ8, 6), + BT_SDP_DATA_ELEM_LIST( + { + BT_SDP_TYPE_SIZE(BT_SDP_UUID16), + BT_SDP_ARRAY_16(BT_SDP_ADVANCED_AUDIO_SVCLASS) + }, + { + BT_SDP_TYPE_SIZE(BT_SDP_UINT16), + BT_SDP_ARRAY_16(0x0103U) + }, + ) + }, + ) + ), + BT_SDP_SERVICE_NAME("A2DPSink"), + BT_SDP_SUPPORTED_FEATURES(0x0001U), +}; + +static struct bt_sdp_record a2dp_source_rec = BT_SDP_RECORD(a2dp_source_attrs); + +static void shell_a2dp_print_capabilities(struct bt_a2dp_ep_info *ep_info) +{ + uint8_t codec_type; + uint8_t *codec_ie; + uint16_t codec_ie_len; + + codec_type = ep_info->codec_type; + codec_ie = ep_info->codec_cap.codec_ie; + codec_ie_len = ep_info->codec_cap.len; + shell_print(ctx_shell, "endpoint id: %d, %s, %s:", ep_info->sep_info.id, + (ep_info->sep_info.tsep == BT_AVDTP_SINK) ? "(sink)" : "(source)", + (ep_info->sep_info.inuse) ? "(in use)" : "(idle)"); + if (BT_A2DP_SBC == codec_type) { + shell_print(ctx_shell, " codec type: SBC"); + + if (BT_A2DP_SBC_IE_LENGTH != codec_ie_len) { + shell_error(ctx_shell, " wrong sbc codec ie"); + return; + } + + shell_print(ctx_shell, " sample frequency:"); + if (0U != (codec_ie[0U] & A2DP_SBC_SAMP_FREQ_16000)) { + shell_print(ctx_shell, " 16000 "); + } + if (0U != (codec_ie[0U] & A2DP_SBC_SAMP_FREQ_32000)) { + shell_print(ctx_shell, " 32000 "); + } + if (0U != (codec_ie[0U] & A2DP_SBC_SAMP_FREQ_44100)) { + shell_print(ctx_shell, " 44100 "); + } + if (0U != (codec_ie[0U] & A2DP_SBC_SAMP_FREQ_48000)) { + shell_print(ctx_shell, " 48000"); + } + + shell_print(ctx_shell, " channel mode:"); + if (0U != (codec_ie[0U] & A2DP_SBC_CH_MODE_MONO)) { + shell_print(ctx_shell, " Mono "); + } + if (0U != (codec_ie[0U] & A2DP_SBC_CH_MODE_DUAL)) { + shell_print(ctx_shell, " Dual "); + } + if (0U != (codec_ie[0U] & A2DP_SBC_CH_MODE_STREO)) { + shell_print(ctx_shell, " Stereo "); + } + if (0U != (codec_ie[0U] & A2DP_SBC_CH_MODE_JOINT)) { + shell_print(ctx_shell, " Joint-Stereo"); + } + + /* Decode Support for Block Length */ + shell_print(ctx_shell, " Block Length:"); + if (0U != (codec_ie[1U] & A2DP_SBC_BLK_LEN_4)) { + shell_print(ctx_shell, " 4 "); + } + if (0U != (codec_ie[1U] & A2DP_SBC_BLK_LEN_8)) { + shell_print(ctx_shell, " 8 "); + } + if (0U != (codec_ie[1U] & A2DP_SBC_BLK_LEN_12)) { + shell_print(ctx_shell, " 12 "); + } + if (0U != (codec_ie[1U] & A2DP_SBC_BLK_LEN_16)) { + shell_print(ctx_shell, " 16"); + } + + /* Decode Support for Subbands */ + shell_print(ctx_shell, " Subbands:"); + if (0U != (codec_ie[1U] & A2DP_SBC_SUBBAND_4)) { + shell_print(ctx_shell, " 4 "); + } + if (0U != (codec_ie[1U] & A2DP_SBC_SUBBAND_8)) { + shell_print(ctx_shell, " 8"); + } + + /* Decode Support for Allocation Method */ + shell_print(ctx_shell, " Allocation Method:"); + if (0U != (codec_ie[1U] & A2DP_SBC_ALLOC_MTHD_SNR)) { + shell_print(ctx_shell, " SNR "); + } + if (0U != (codec_ie[1U] & A2DP_SBC_ALLOC_MTHD_LOUDNESS)) { + shell_print(ctx_shell, " Loudness"); + } + + shell_print(ctx_shell, " Bitpool Range: %d - %d", + codec_ie[2U], codec_ie[3U]); + } else { + shell_print(ctx_shell, " not SBC codecs"); + } +} + +void app_connected(struct bt_a2dp *a2dp, int err) +{ + if (!err) { + default_a2dp = a2dp; + shell_print(ctx_shell, "a2dp connected"); + } else { + shell_print(ctx_shell, "a2dp connecting fail"); + } +} + +void app_disconnected(struct bt_a2dp *a2dp) +{ + found_peer_sbc_endpoint = NULL; + shell_print(ctx_shell, "a2dp disconnected"); +} + +int app_config_req(struct bt_a2dp *a2dp, struct bt_a2dp_ep *ep, + struct bt_a2dp_codec_cfg *codec_cfg, struct bt_a2dp_stream **stream, + uint8_t *rsp_err_code) +{ + bt_a2dp_stream_cb_register(&sbc_stream, &stream_ops); + *stream = &sbc_stream; + *rsp_err_code = 0; + + shell_print(ctx_shell, "receive requesting config and accept"); + if (*rsp_err_code == 0) { + uint32_t sample_rate; + + shell_print(ctx_shell, "SBC configure success"); + sample_rate = bt_a2dp_sbc_get_sampling_frequency( + (struct bt_a2dp_codec_sbc_params *)&codec_cfg->codec_config->codec_ie[0]); + shell_print(ctx_shell, "sample rate %dHz", sample_rate); + } else { + shell_print(ctx_shell, "configure err"); + } + return 0; +} + +void app_config_rsp(struct bt_a2dp_stream *stream, uint8_t rsp_err_code) +{ + if (rsp_err_code == 0) { + shell_print(ctx_shell, "success to configure"); + } else { + shell_print(ctx_shell, "fail to configure"); + } +} + +int app_establish_req(struct bt_a2dp_stream *stream, uint8_t *rsp_err_code) +{ + *rsp_err_code = 0; + shell_print(ctx_shell, "receive requesting establishment and accept"); + return 0; +} + +void app_establish_rsp(struct bt_a2dp_stream *stream, uint8_t rsp_err_code) +{ + if (rsp_err_code == 0) { + shell_print(ctx_shell, "success to establish"); + } else { + shell_print(ctx_shell, "fail to establish"); + } +} + +int app_start_req(struct bt_a2dp_stream *stream, uint8_t *rsp_err_code) +{ + *rsp_err_code = 0; + shell_print(ctx_shell, "receive requesting start and accept"); + return 0; +} + +void app_start_rsp(struct bt_a2dp_stream *stream, uint8_t rsp_err_code) +{ + if (rsp_err_code == 0) { + shell_print(ctx_shell, "success to start"); + } else { + shell_print(ctx_shell, "fail to start"); + } +} + +void stream_configured(struct bt_a2dp_stream *stream) +{ + shell_print(ctx_shell, "stream configured"); +} + +void stream_established(struct bt_a2dp_stream *stream) +{ + shell_print(ctx_shell, "stream established"); +} + +void stream_released(struct bt_a2dp_stream *stream) +{ + shell_print(ctx_shell, "stream released"); +} + +void stream_started(struct bt_a2dp_stream *stream) +{ + shell_print(ctx_shell, "stream started"); +} + +void sink_sbc_streamer_data(struct bt_a2dp_stream *stream, struct net_buf *buf, + uint16_t seq_num, uint32_t ts) +{ + uint8_t sbc_hdr; + + sbc_hdr = net_buf_pull_u8(buf); + shell_print(ctx_shell, "received, num of frames: %d, data length:%d", + (uint8_t)BT_A2DP_SBC_MEDIA_HDR_NUM_FRAMES_GET(sbc_hdr), buf->len); + shell_print(ctx_shell, "data: %d, %d, %d, %d, %d, %d ......", buf->data[0], + buf->data[1], buf->data[2], buf->data[3], buf->data[4], buf->data[5]); +} + +void stream_recv(struct bt_a2dp_stream *stream, + struct net_buf *buf, uint16_t seq_num, uint32_t ts) +{ + sink_sbc_streamer_data(stream, buf, seq_num, ts); +} + +struct bt_a2dp_cb a2dp_cb = { + .connected = app_connected, + .disconnected = app_disconnected, + .config_req = app_config_req, + .config_rsp = app_config_rsp, + .establish_req = app_establish_req, + .establish_rsp = app_establish_rsp, + .release_req = NULL, + .release_rsp = NULL, + .start_req = app_start_req, + .start_rsp = app_start_rsp, + .suspend_req = NULL, + .suspend_rsp = NULL, + .reconfig_req = NULL, + .reconfig_rsp = NULL, +}; + +static int cmd_register_cb(const struct shell *sh, int32_t argc, char *argv[]) +{ + int err = -1; + + if (a2dp_initied == 0) { + a2dp_initied = 1; + + err = bt_a2dp_register_cb(&a2dp_cb); + if (!err) { + shell_print(sh, "success"); + } else { + shell_print(sh, "fail"); + } + } else { + shell_print(sh, "already registered"); + } + + return 0; +} + +static int cmd_register_ep(const struct shell *sh, int32_t argc, char *argv[]) +{ + int err = -1; + const char *type; + const char *action; + + if (a2dp_initied == 0) { + shell_print(sh, "need to register a2dp connection callbacks"); + return -ENOEXEC; + } + + type = argv[1]; + action = argv[2]; + if (!strcmp(action, "sbc")) { + if (!strcmp(type, "sink")) { + if (a2dp_sink_sdp_registered == 0) { + a2dp_sink_sdp_registered = 1; + bt_sdp_register_service(&a2dp_sink_rec); + } + err = bt_a2dp_register_ep(&sink_sbc_endpoint, + BT_AVDTP_AUDIO, BT_AVDTP_SINK); + if (!err) { + shell_print(sh, "SBC sink endpoint is registered"); + registered_sbc_endpoint = &sink_sbc_endpoint; + } + } else if (!strcmp(type, "source")) { + if (a2dp_source_sdp_registered == 0) { + a2dp_source_sdp_registered = 1; + bt_sdp_register_service(&a2dp_source_rec); + } + err = bt_a2dp_register_ep(&source_sbc_endpoint, + BT_AVDTP_AUDIO, BT_AVDTP_SOURCE); + if (!err) { + shell_print(sh, "SBC source endpoint is registered"); + registered_sbc_endpoint = &source_sbc_endpoint; + } + } else { + shell_help(sh); + return 0; + } + } else { + shell_help(sh); + return 0; + } + + if (err) { + shell_print(sh, "fail to register endpoint"); + } + + return 0; +} + +static int cmd_connect(const struct shell *sh, int32_t argc, char *argv[]) +{ + if (a2dp_initied == 0) { + shell_print(sh, "need to register a2dp connection callbacks"); + return -ENOEXEC; + } + + if (!default_conn) { + shell_error(sh, "Not connected"); + return -ENOEXEC; + } + + default_a2dp = bt_a2dp_connect(default_conn); + if (NULL == default_a2dp) { + shell_error(sh, "fail to connect a2dp"); + } + return 0; +} + +static int cmd_disconnect(const struct shell *sh, int32_t argc, char *argv[]) +{ + if (a2dp_initied == 0) { + shell_print(sh, "need to register a2dp connection callbacks"); + return -ENOEXEC; + } + + if (default_a2dp != NULL) { + bt_a2dp_disconnect(default_a2dp); + default_a2dp = NULL; + } else { + shell_error(sh, "a2dp is not connected"); + } + return 0; +} + +void app_configured(int err) +{ + if (err) { + shell_print(ctx_shell, "configure fail"); + } +} + +static struct bt_a2dp_stream_ops stream_ops = { + .configured = stream_configured, + .established = stream_established, + .released = stream_released, + .started = stream_started, + .suspended = NULL, + .reconfigured = NULL, + .recv = stream_recv, + .sent = NULL, +}; + +BT_A2DP_SBC_EP_CFG_DEFAULT(sbc_cfg_default, A2DP_SBC_SAMP_FREQ_44100); +static int cmd_configure(const struct shell *sh, int32_t argc, char *argv[]) +{ + int err; + + if (a2dp_initied == 0) { + shell_print(sh, "need to register a2dp connection callbacks"); + return -ENOEXEC; + } + + if (default_a2dp != NULL) { + if (registered_sbc_endpoint == NULL) { + shell_error(sh, "no endpoint"); + return 0; + } + + if (found_peer_sbc_endpoint == NULL) { + shell_error(sh, "don't find the peer sbc endpoint"); + return 0; + } + + bt_a2dp_stream_cb_register(&sbc_stream, &stream_ops); + + err = bt_a2dp_stream_config(default_a2dp, &sbc_stream, + registered_sbc_endpoint, found_peer_sbc_endpoint, + &sbc_cfg_default); + if (err) { + shell_error(sh, "fail to configure"); + } + } else { + shell_error(sh, "a2dp is not connected"); + } + return 0; +} + +static uint8_t bt_a2dp_discover_peer_endpoint_cb(struct bt_a2dp *a2dp, + struct bt_a2dp_ep_info *info, struct bt_a2dp_ep **ep) +{ + if (info != NULL) { + shell_print(ctx_shell, "find one endpoint"); + shell_a2dp_print_capabilities(info); + if ((info->codec_type == BT_A2DP_SBC) && + (ep != NULL)) { + *ep = &peer_sbc_endpoint; + found_peer_sbc_endpoint = &peer_sbc_endpoint; + } + } + return BT_A2DP_DISCOVER_EP_CONTINUE; +} + +static struct bt_avdtp_sep_info found_seps[5]; + +struct bt_a2dp_discover_param discover_param = { + .cb = bt_a2dp_discover_peer_endpoint_cb, + .seps_info = &found_seps[0], + .sep_count = 5, +}; + +static int cmd_get_peer_eps(const struct shell *sh, int32_t argc, char *argv[]) +{ + if (a2dp_initied == 0) { + shell_print(sh, "need to register a2dp connection callbacks"); + return -ENOEXEC; + } + + if (default_a2dp != NULL) { + int err = bt_a2dp_discover(default_a2dp, &discover_param); + + if (err) { + shell_error(sh, "discover fail"); + } + } else { + shell_error(sh, "a2dp is not connected"); + } + return 0; +} + +static int cmd_establish(const struct shell *sh, int32_t argc, char *argv[]) +{ + if (a2dp_initied == 0) { + shell_print(sh, "need to register a2dp connection callbacks"); + return -ENOEXEC; + } + + if (bt_a2dp_stream_establish(&sbc_stream) != 0) { + shell_print(sh, "fail"); + } + return 0; +} + +static int cmd_start(const struct shell *sh, int32_t argc, char *argv[]) +{ + if (a2dp_initied == 0) { + shell_print(sh, "need to register a2dp connection callbacks"); + return -ENOEXEC; + } + + if (bt_a2dp_stream_start(&sbc_stream) != 0) { + shell_print(sh, "fail"); + } + return 0; +} + +static int cmd_send_media(const struct shell *sh, int32_t argc, char *argv[]) +{ + struct net_buf *buf; + int ret; + + if (a2dp_initied == 0) { + shell_print(sh, "need to register a2dp connection callbacks"); + return -ENOEXEC; + } + + buf = net_buf_alloc(&a2dp_tx_pool, K_FOREVER); + net_buf_reserve(buf, BT_A2DP_STREAM_BUF_RESERVE); + + /* num of frames is 1 */ + net_buf_add_u8(buf, (uint8_t)BT_A2DP_SBC_MEDIA_HDR_ENCODE(1, 0, 0, 0)); + net_buf_add_mem(buf, media_data, sizeof(media_data)); + shell_print(sh, "num of frames: %d, data length: %d", 1u, sizeof(media_data)); + shell_print(sh, "data: %d, %d, %d, %d, %d, %d ......", media_data[0], + media_data[1], media_data[2], media_data[3], media_data[4], media_data[5]); + + ret = bt_a2dp_stream_send(&sbc_stream, buf, 0u, 0u); + if (ret < 0) { + printk(" Failed to send SBC audio data on streams(%d)\n", ret); + net_buf_unref(buf); + } + + return 0; +} + +#define HELP_NONE "[none]" + +SHELL_STATIC_SUBCMD_SET_CREATE(a2dp_cmds, + SHELL_CMD_ARG(register_cb, NULL, "register a2dp connection callbacks", + cmd_register_cb, 1, 0), + SHELL_CMD_ARG(register_ep, NULL, " ", + cmd_register_ep, 3, 0), + SHELL_CMD_ARG(connect, NULL, HELP_NONE, cmd_connect, 1, 0), + SHELL_CMD_ARG(disconnect, NULL, HELP_NONE, cmd_disconnect, 1, 0), + SHELL_CMD_ARG(discover_peer_eps, NULL, HELP_NONE, cmd_get_peer_eps, 1, 0), + SHELL_CMD_ARG(configure, NULL, HELP_NONE, cmd_configure, 1, 0), + SHELL_CMD_ARG(establish, NULL, HELP_NONE, cmd_establish, 1, 0), + SHELL_CMD_ARG(start, NULL, "\"start the default selected ep\"", cmd_start, 1, 0), + SHELL_CMD_ARG(send_media, NULL, HELP_NONE, cmd_send_media, 1, 0), + SHELL_SUBCMD_SET_END +); + +static int cmd_a2dp(const struct shell *sh, size_t argc, char **argv) +{ + if (argc == 1) { + shell_help(sh); + /* sh returns 1 when help is printed */ + return 1; + } + + shell_error(sh, "%s unknown parameter: %s", argv[0], argv[1]); + + return -ENOEXEC; +} + +SHELL_CMD_ARG_REGISTER(a2dp, &a2dp_cmds, "Bluetooth A2DP sh commands", + cmd_a2dp, 1, 1); diff --git a/tests/bluetooth/shell/prj_br.conf b/tests/bluetooth/shell/prj_br.conf index 764a0e6b3e4c2..d41ec3053087f 100644 --- a/tests/bluetooth/shell/prj_br.conf +++ b/tests/bluetooth/shell/prj_br.conf @@ -2,6 +2,9 @@ CONFIG_TEST=y CONFIG_BT=y CONFIG_BT_CLASSIC=y CONFIG_BT_RFCOMM=y +CONFIG_BT_A2DP=y +CONFIG_BT_A2DP_SOURCE=y +CONFIG_BT_A2DP_SINK=y CONFIG_BT_SHELL=y CONFIG_LOG=y CONFIG_BT_CENTRAL=y From 5a8652b0c2209bf45466932d38f694309eee3e78 Mon Sep 17 00:00:00 2001 From: Mark Wang Date: Thu, 11 Apr 2024 16:41:18 +0800 Subject: [PATCH 1255/2849] tests: bluetooth: shell: test a2dp on mimxrt1060_evk + murata 1xk add the mimxrt1060_evk hci uart overlay file. Signed-off-by: Mark Wang --- .../shell/boards/mimxrt1060_evk.overlay | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 tests/bluetooth/shell/boards/mimxrt1060_evk.overlay diff --git a/tests/bluetooth/shell/boards/mimxrt1060_evk.overlay b/tests/bluetooth/shell/boards/mimxrt1060_evk.overlay new file mode 100644 index 0000000000000..f48eea9172ce5 --- /dev/null +++ b/tests/bluetooth/shell/boards/mimxrt1060_evk.overlay @@ -0,0 +1,17 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + chosen { + zephyr,bt-uart = &lpuart3; + }; +}; + +&lpuart3 { + status = "okay"; + current-speed = <3000000>; + hw-flow-control; +}; From 87bacf378d2825ddc99483f86ba2bf9db130f146 Mon Sep 17 00:00:00 2001 From: Robert Lubos Date: Fri, 24 May 2024 16:52:22 +0200 Subject: [PATCH 1256/2849] net: l2: ethernet: arp: Fix ARP probe target HW address matching According to RFC3927 and RFC5227, an ARP probe target HW address should be set to all-zeroes: "The 'target hardware address' field is ignored and SHOULD be set to all zeroes." Hence, we should allow the ARP probes to have all-zeroes target HW address as well. Signed-off-by: Robert Lubos --- include/zephyr/net/ethernet.h | 21 +++++++++++++++++++++ subsys/net/l2/ethernet/arp.c | 13 +++++-------- 2 files changed, 26 insertions(+), 8 deletions(-) diff --git a/include/zephyr/net/ethernet.h b/include/zephyr/net/ethernet.h index 30fbb200bce44..f0d1b1b6e86c7 100644 --- a/include/zephyr/net/ethernet.h +++ b/include/zephyr/net/ethernet.h @@ -725,6 +725,27 @@ static inline bool net_eth_is_addr_broadcast(struct net_eth_addr *addr) return false; } +/** + * @brief Check if the Ethernet MAC address is a all zeroes address. + * + * @param addr A valid pointer to an Ethernet MAC address. + * + * @return true if address is an all zeroes address, false if not + */ +static inline bool net_eth_is_addr_all_zeroes(struct net_eth_addr *addr) +{ + if (addr->addr[0] == 0x00 && + addr->addr[1] == 0x00 && + addr->addr[2] == 0x00 && + addr->addr[3] == 0x00 && + addr->addr[4] == 0x00 && + addr->addr[5] == 0x00) { + return true; + } + + return false; +} + /** * @brief Check if the Ethernet MAC address is unspecified. * diff --git a/subsys/net/l2/ethernet/arp.c b/subsys/net/l2/ethernet/arp.c index 7032414bc1e73..de5de8821e9f2 100644 --- a/subsys/net/l2/ethernet/arp.c +++ b/subsys/net/l2/ethernet/arp.c @@ -794,14 +794,11 @@ enum net_verdict net_arp_input(struct net_pkt *pkt, } if (IS_ENABLED(CONFIG_NET_ARP_GRATUITOUS)) { - if (memcmp(ð_hdr->dst, - net_eth_broadcast_addr(), - sizeof(struct net_eth_addr)) == 0 && - memcmp(&arp_hdr->dst_hwaddr, - net_eth_broadcast_addr(), - sizeof(struct net_eth_addr)) == 0 && - memcmp(&arp_hdr->dst_ipaddr, &arp_hdr->src_ipaddr, - sizeof(struct in_addr)) == 0) { + if (net_eth_is_addr_broadcast(ð_hdr->dst) && + (net_eth_is_addr_broadcast(&arp_hdr->dst_hwaddr) || + net_eth_is_addr_all_zeroes(&arp_hdr->dst_hwaddr)) && + net_ipv4_addr_cmp_raw(arp_hdr->dst_ipaddr, + arp_hdr->src_ipaddr)) { /* If the IP address is in our cache, * then update it here. */ From 4b40c11c42e89a842a94962bc3cf8cdc3f3f39a1 Mon Sep 17 00:00:00 2001 From: Ioannis Damigos Date: Fri, 24 May 2024 14:53:15 +0300 Subject: [PATCH 1257/2849] smartbond_timer: Fix convertion of watchdog value to LP clock ticks Fix convertion of watchdog value to LP clock ticks Signed-off-by: Ioannis Damigos --- drivers/timer/smartbond_timer.c | 34 ++++++++++++++++++++++++++++++--- 1 file changed, 31 insertions(+), 3 deletions(-) diff --git a/drivers/timer/smartbond_timer.c b/drivers/timer/smartbond_timer.c index 9726b6d9b9af7..ceef22ce5fa2f 100644 --- a/drivers/timer/smartbond_timer.c +++ b/drivers/timer/smartbond_timer.c @@ -5,6 +5,8 @@ */ #include +#include +#include #include #include #include @@ -17,6 +19,10 @@ #define TICK_TO_CYC(tick) k_ticks_to_cyc_ceil32(tick) #define CYC_TO_TICK(cyc) k_cyc_to_ticks_ceil32(cyc) #define MAX_TICKS (((COUNTER_SPAN / 2) - CYC_PER_TICK) / (CYC_PER_TICK)) +#define SMARTBOND_CLOCK_CONTROLLER DEVICE_DT_GET(DT_NODELABEL(osc)) +/* Margin values are based on DA1469x characterization data */ +#define RC32K_FREQ_POSITIVE_MARGIN_DUE_TO_VOLTAGE (675) +#define RC32K_FREQ_MARGIN_DUE_TO_TEMPERATURE (450) static uint32_t last_timer_val_reg; static uint32_t timer_val_31_24; @@ -25,6 +31,19 @@ static uint32_t last_isr_val; static uint32_t last_isr_val_rounded; static uint32_t announced_ticks; +static uint32_t get_rc32k_max_frequency(void) +{ + /* According to DA1469x datasheet */ + uint32_t r32k_frequency = 37000; + + clock_control_get_rate(SMARTBOND_CLOCK_CONTROLLER, + (clock_control_subsys_t)SMARTBOND_CLK_RC32K, &r32k_frequency); + + r32k_frequency += RC32K_FREQ_POSITIVE_MARGIN_DUE_TO_VOLTAGE + + RC32K_FREQ_MARGIN_DUE_TO_TEMPERATURE; + return r32k_frequency; +} + static void set_reload(uint32_t val) { TIMER2->TIMER2_RELOAD_REG = val & TIMER2_TIMER2_RELOAD_REG_TIM_RELOAD_Msk; @@ -88,11 +107,20 @@ void sys_clock_set_timeout(int32_t ticks, bool idle) uint32_t watchdog_expire_ticks; if (CRG_TOP->CLK_RCX_REG & CRG_TOP_CLK_RCX_REG_RCX_ENABLE_Msk) { - watchdog_expire_ticks = SYS_WDOG->WATCHDOG_REG * 21 * - CONFIG_SYS_CLOCK_TICKS_PER_SEC / 1000; + /* + * When LP clock is RCX, the watchdog is clocked by RCX clock + * divided by 320. + */ + watchdog_expire_ticks = SYS_WDOG->WATCHDOG_REG * 320; } else { + /* + * When LP clock is not RCX, the watchdog is clocked by RC32K + * divided by 320. In this case watchdog value to LP clock + * ticks must be calculated according to XTAL32K frequency and + * RC32K maximum frequency. + */ watchdog_expire_ticks = SYS_WDOG->WATCHDOG_REG * - CONFIG_SYS_CLOCK_TICKS_PER_SEC / 100; + CONFIG_SYS_CLOCK_TICKS_PER_SEC / (get_rc32k_max_frequency() / 320); } if (watchdog_expire_ticks - 2 < ticks) { ticks = watchdog_expire_ticks - 2; From aa458a279af7d11f2de91fa3949ca52c3eb46ed1 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Fri, 24 May 2024 12:12:20 +0300 Subject: [PATCH 1258/2849] Revert "net: sockets: Check eventfd errors better" This reverts commit b56297bf161e739cd53eb7783f1e0bd5d8ead2b1 because it is causing problems when using native_sim and not having CONFIG_POSIX_API set. The proper fix is to set CONFIG_POSIX_API when using eventfd and native_sim so that picolibc is used instead of host libc. Signed-off-by: Jukka Rissanen --- subsys/net/lib/sockets/sockets_service.c | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/subsys/net/lib/sockets/sockets_service.c b/subsys/net/lib/sockets/sockets_service.c index 6e034d57ea5b6..f8398e95df1dc 100644 --- a/subsys/net/lib/sockets/sockets_service.c +++ b/subsys/net/lib/sockets/sockets_service.c @@ -180,7 +180,6 @@ 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); @@ -254,25 +253,11 @@ 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 74f9a1c482fe4b2e36fd8b47e1cc175d00ecde24 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Fri, 24 May 2024 14:18:02 +0300 Subject: [PATCH 1259/2849] net: sockets_service: Add build check for using zephyr libc Add checks to make sure that we are not trying to use the socket service library with eventfd if CONFIG_POSIX_API is not set and if using native_sim based board. The reason is that we should always use zephyr libc based eventfd implementation instead of host libc one. Signed-off-by: Jukka Rissanen --- subsys/net/lib/sockets/Kconfig | 2 ++ subsys/net/lib/sockets/sockets_service.c | 11 +++++++++++ 2 files changed, 13 insertions(+) diff --git a/subsys/net/lib/sockets/Kconfig b/subsys/net/lib/sockets/Kconfig index b93369e62ce33..4111f3058678f 100644 --- a/subsys/net/lib/sockets/Kconfig +++ b/subsys/net/lib/sockets/Kconfig @@ -103,6 +103,8 @@ config NET_SOCKETS_SERVICE bool "Socket service support [EXPERIMENTAL]" select EXPERIMENTAL select EVENTFD + # We select here POSIX_API so that zephyr libc will be used for native_sim + select POSIX_API if BOARD_NATIVE_SIM help The socket service can monitor multiple sockets and save memory by only having one thread listening socket data. If data is received diff --git a/subsys/net/lib/sockets/sockets_service.c b/subsys/net/lib/sockets/sockets_service.c index f8398e95df1dc..185a75359f84a 100644 --- a/subsys/net/lib/sockets/sockets_service.c +++ b/subsys/net/lib/sockets/sockets_service.c @@ -12,6 +12,17 @@ LOG_MODULE_REGISTER(net_sock_svc, CONFIG_NET_SOCKETS_LOG_LEVEL); #include #include +/* Next checks makes sure that we are not trying to use this library + * with eventfd if CONFIG_POSIX_API is not set and if using native_sim + * based board. The reason is that we should always use zephyr libc based + * eventfd implementation instead of host libc one. + */ +#if defined(CONFIG_NATIVE_LIBC) && defined(CONFIG_EVENTFD) +#error "The eventfd support CONFIG_EVENTFD will not work with host libc " + "so you need to enable CONFIG_POSIX_API in this case which will turn " + "off the host libc usage." +#endif + static int init_socket_service(void); static bool init_done; From 3f96a87d1cfcf2c3f9f0047afae719283b74074b Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Fri, 24 May 2024 14:13:12 +0300 Subject: [PATCH 1260/2849] net: dns: Fix resolver debug print Make sure that we are not trying to print NULL pointer string. Signed-off-by: Jukka Rissanen --- subsys/net/lib/dns/resolve.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/subsys/net/lib/dns/resolve.c b/subsys/net/lib/dns/resolve.c index 9797fd54ada30..d866b814c386c 100644 --- a/subsys/net/lib/dns/resolve.c +++ b/subsys/net/lib/dns/resolve.c @@ -1073,8 +1073,8 @@ static int dns_resolve_cancel_with_hash(struct dns_resolve_context *ctx, } NET_DBG("Cancelling DNS req %u (name %s type %d hash %u)", dns_id, - query_name, ctx->queries[i].query_type, - query_hash); + query_name == NULL ? "" : query_name, + ctx->queries[i].query_type, query_hash); dns_resolve_cancel_slot(ctx, i); From 6465e738251315892611c26f8ef2a22ed1cbfbd4 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Fri, 24 May 2024 14:14:47 +0300 Subject: [PATCH 1261/2849] tests: net: dns_resolve: Increase the number of socket descriptors The test needs couple of more socket/file descriptors to work because CONFIG_POSIX_API creates three more file descriptors namely the stdin, stdout and stderr descriptors. Signed-off-by: Jukka Rissanen --- tests/net/lib/dns_resolve/prj.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/net/lib/dns_resolve/prj.conf b/tests/net/lib/dns_resolve/prj.conf index 4bc1b8706cec9..9f5452f5834b6 100644 --- a/tests/net/lib/dns_resolve/prj.conf +++ b/tests/net/lib/dns_resolve/prj.conf @@ -30,4 +30,4 @@ CONFIG_ZTEST=y CONFIG_MAIN_STACK_SIZE=1344 CONFIG_NET_SOCKETS_POLL_MAX=9 -CONFIG_POSIX_MAX_FDS=5 +CONFIG_POSIX_MAX_FDS=8 From 96c26c22681964df49631962bee7e69237659777 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Mon, 27 May 2024 09:58:23 +0300 Subject: [PATCH 1262/2849] shell: backend: telnet: Rename write and read functions Rename write() to telnet_write(), and read() to telnet_read() so that if we enable CONFIG_POSIX_API, the compiler will not complain about those two functions as they conflict with POSIX API ones. Signed-off-by: Jukka Rissanen --- subsys/shell/backends/shell_telnet.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/subsys/shell/backends/shell_telnet.c b/subsys/shell/backends/shell_telnet.c index e75d5ebaa865d..473f58e36ee63 100644 --- a/subsys/shell/backends/shell_telnet.c +++ b/subsys/shell/backends/shell_telnet.c @@ -657,8 +657,8 @@ static int enable(const struct shell_transport *transport, bool blocking) return 0; } -static int write(const struct shell_transport *transport, - const void *data, size_t length, size_t *cnt) +static int telnet_write(const struct shell_transport *transport, + const void *data, size_t length, size_t *cnt) { struct shell_telnet_line_buf *lb; size_t copy_len; @@ -725,8 +725,8 @@ static int write(const struct shell_transport *transport, return 0; } -static int read(const struct shell_transport *transport, - void *data, size_t length, size_t *cnt) +static int telnet_read(const struct shell_transport *transport, + void *data, size_t length, size_t *cnt) { size_t read_len; @@ -772,8 +772,8 @@ const struct shell_transport_api shell_telnet_transport_api = { .init = init, .uninit = uninit, .enable = enable, - .write = write, - .read = read + .write = telnet_write, + .read = telnet_read }; static int enable_shell_telnet(void) From 39e472ffba5b43ca6aead63af65ed4f4ed278b17 Mon Sep 17 00:00:00 2001 From: Abderrahmane Jarmouni Date: Thu, 16 May 2024 14:33:31 +0200 Subject: [PATCH 1263/2849] include: drivers: gpio: fix gpio_dt_flags_t overflow when GPIO_INT_WAKEUP flag is used in a DT gpios property the gpio_dt_flags_t var that holds the flags overflows Hence moving GPIO_INT_WAKEUP flag from bit 28 to bit 6 Signed-off-by: Abderrahmane Jarmouni --- include/zephyr/dt-bindings/gpio/gpio.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/zephyr/dt-bindings/gpio/gpio.h b/include/zephyr/dt-bindings/gpio/gpio.h index b4110208b3fe9..d485e609f12ac 100644 --- a/include/zephyr/dt-bindings/gpio/gpio.h +++ b/include/zephyr/dt-bindings/gpio/gpio.h @@ -79,12 +79,12 @@ /** @} */ -/* Note: Bits 15 downto 8 are reserved for SoC specific flags. */ - /** * Configures GPIO interrupt to wakeup the system from low power mode. */ -#define GPIO_INT_WAKEUP (1 << 28) +#define GPIO_INT_WAKEUP (1 << 6) + +/* Note: Bits 15 downto 8 are reserved for SoC specific flags. */ /** * @} From 0a677ec31b410d8b01537b7696b48c219aad591f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C4=99drzej=20Ciupis?= Date: Fri, 17 May 2024 12:50:53 +0200 Subject: [PATCH 1264/2849] CODEOWNERS: update codeowners MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Update codeowner for nRF ieee802154 solutions. Signed-off-by: Jędrzej Ciupis --- CODEOWNERS | 2 +- MAINTAINERS.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CODEOWNERS b/CODEOWNERS index d1940b8d606ca..c6fe49d726396 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -263,7 +263,7 @@ /drivers/i3c/i3c_cdns.c @XenuIsWatching /drivers/ieee802154/ @rlubos @tbursztyka @jukkar @fgrandel /drivers/ieee802154/*b91* @andy-liu-telink -/drivers/ieee802154/ieee802154_nrf5* @jciupis +/drivers/ieee802154/ieee802154_nrf5* @ankuns /drivers/ieee802154/ieee802154_rf2xx* @tbursztyka @nandojve /drivers/ieee802154/ieee802154_cc13xx* @bwitherspoon @cfriedt @vaishnavachath /drivers/interrupt_controller/ @dcpleung @nashif diff --git a/MAINTAINERS.yml b/MAINTAINERS.yml index ad197d1cf376d..1faf6126159fe 100644 --- a/MAINTAINERS.yml +++ b/MAINTAINERS.yml @@ -1421,7 +1421,7 @@ Release Notes: - fgrandel collaborators: - rlubos - - jciupis + - ankuns - cfriedt - jukkar files: From 09eaa8757faa566a6e05c7d16057e0500ddc357e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fin=20Maa=C3=9F?= Date: Mon, 13 May 2024 09:15:35 +0200 Subject: [PATCH 1265/2849] kernel: implement k_realloc MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit implement k_realloc. Signed-off-by: Fin Maaß --- include/zephyr/kernel.h | 45 +++++++++++++++++++++++++++++++++++++++++ kernel/kheap.c | 26 ++++++++++++++++++++++++ kernel/mempool.c | 28 +++++++++++++++++++++++++ 3 files changed, 99 insertions(+) diff --git a/include/zephyr/kernel.h b/include/zephyr/kernel.h index 32c554c159da6..06bbfa1e69178 100644 --- a/include/zephyr/kernel.h +++ b/include/zephyr/kernel.h @@ -5381,6 +5381,32 @@ void *k_heap_aligned_alloc(struct k_heap *h, size_t align, size_t bytes, void *k_heap_alloc(struct k_heap *h, size_t bytes, k_timeout_t timeout) __attribute_nonnull(1); +/** + * @brief Reallocate memory from a k_heap + * + * Reallocates and returns a memory buffer from the memory region owned + * by the heap. If no memory is available immediately, the call will + * block for the specified timeout (constructed via the standard + * timeout API, or K_NO_WAIT or K_FOREVER) waiting for memory to be + * freed. If the allocation cannot be performed by the expiration of + * the timeout, NULL will be returned. + * Reallocated memory is aligned on a multiple of pointer sizes. + * + * @note @a timeout must be set to K_NO_WAIT if called from ISR. + * @note When CONFIG_MULTITHREADING=n any @a timeout is treated as K_NO_WAIT. + * + * @funcprops \isr_ok + * + * @param h Heap from which to allocate + * @param ptr Original pointer returned from a previous allocation + * @param bytes Desired size of block to allocate + * @param timeout How long to wait, or K_NO_WAIT + * + * @return Pointer to memory the caller can now use, or NULL + */ +void *k_heap_realloc(struct k_heap *h, void *ptr, size_t bytes, k_timeout_t timeout) + __attribute_nonnull(1); + /** * @brief Free memory allocated by k_heap_alloc() * @@ -5528,6 +5554,25 @@ void k_free(void *ptr); */ void *k_calloc(size_t nmemb, size_t size); +/** @brief Expand the size of an existing allocation + * + * Returns a pointer to a new memory region with the same contents, + * but a different allocated size. If the new allocation can be + * expanded in place, the pointer returned will be identical. + * Otherwise the data will be copies to a new block and the old one + * will be freed as per sys_heap_free(). If the specified size is + * smaller than the original, the block will be truncated in place and + * the remaining memory returned to the heap. If the allocation of a + * new block fails, then NULL will be returned and the old block will + * not be freed or modified. + * + * @param ptr Original pointer returned from a previous allocation + * @param size Amount of memory requested (in bytes). + * + * @return Pointer to memory the caller can now use, or NULL. + */ +void *k_realloc(void *ptr, size_t size); + /** @} */ /* polling API - PRIVATE */ diff --git a/kernel/kheap.c b/kernel/kheap.c index ccdd66907880c..a452f172a56d2 100644 --- a/kernel/kheap.c +++ b/kernel/kheap.c @@ -116,6 +116,32 @@ void *k_heap_alloc(struct k_heap *heap, size_t bytes, k_timeout_t timeout) return ret; } +void *k_heap_realloc(struct k_heap *heap, void *ptr, size_t bytes, k_timeout_t timeout) +{ + k_timepoint_t end = sys_timepoint_calc(timeout); + void *ret = NULL; + + k_spinlock_key_t key = k_spin_lock(&heap->lock); + + __ASSERT(!arch_is_in_isr() || K_TIMEOUT_EQ(timeout, K_NO_WAIT), ""); + + while (ret == NULL) { + ret = sys_heap_aligned_realloc(&heap->heap, ptr, sizeof(void *), bytes); + + if (!IS_ENABLED(CONFIG_MULTITHREADING) || + (ret != NULL) || K_TIMEOUT_EQ(timeout, K_NO_WAIT)) { + break; + } + + timeout = sys_timepoint_timeout(end); + (void) z_pend_curr(&heap->lock, key, &heap->wait_q, timeout); + key = k_spin_lock(&heap->lock); + } + + k_spin_unlock(&heap->lock, key); + return ret; +} + void k_heap_free(struct k_heap *heap, void *mem) { k_spinlock_key_t key = k_spin_lock(&heap->lock); diff --git a/kernel/mempool.c b/kernel/mempool.c index 13e9c7abec24e..3d7dba22faca0 100644 --- a/kernel/mempool.c +++ b/kernel/mempool.c @@ -113,6 +113,34 @@ void *k_calloc(size_t nmemb, size_t size) return ret; } +void *k_realloc(void *ptr, size_t size) +{ + struct k_heap *heap, **heap_ref; + void *ret; + + if (size == 0) { + k_free(ptr); + return NULL; + } + if (ptr == NULL) { + return k_malloc(size); + } + heap_ref = ptr; + ptr = --heap_ref; + heap = *heap_ref; + + if (size_add_overflow(size, sizeof(heap_ref), &size)) { + return NULL; + } + + ret = k_heap_realloc(heap, ptr, size, K_NO_WAIT); + if (ret != NULL) { + heap_ref = ret; + ret = ++heap_ref; + } + return ret; +} + void k_thread_system_pool_assign(struct k_thread *thread) { thread->resource_pool = _SYSTEM_HEAP; From 8c37f14b981f40cac1dc2425652112aa6bd06fcb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fin=20Maa=C3=9F?= Date: Mon, 13 May 2024 09:17:24 +0200 Subject: [PATCH 1266/2849] tracing: add k_realloc trace MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For `k_realloc` add tracing feature. Signed-off-by: Fin Maaß --- include/zephyr/tracing/tracing.h | 32 +++++++++++++++++++ kernel/kheap.c | 4 +++ kernel/mempool.c | 7 ++++ subsys/tracing/ctf/tracing_ctf.h | 4 +++ subsys/tracing/sysview/tracing_sysview.h | 10 ++++++ subsys/tracing/sysview/tracing_sysview_ids.h | 1 + .../tracing/test/tracing_string_format_test.c | 10 ++++++ subsys/tracing/test/tracing_test.h | 13 ++++++++ subsys/tracing/user/tracing_user.h | 4 +++ 9 files changed, 85 insertions(+) diff --git a/include/zephyr/tracing/tracing.h b/include/zephyr/tracing/tracing.h index f1bbddeec5143..dc14830288683 100644 --- a/include/zephyr/tracing/tracing.h +++ b/include/zephyr/tracing/tracing.h @@ -1690,6 +1690,25 @@ */ #define sys_port_trace_k_heap_free(h) +/** + * @brief Trace Heap realloc enter + * @param h Heap object + * @param ptr Pointer to reallocate + * @param bytes Bytes to reallocate + * @param timeout Timeout period + */ +#define sys_port_trace_k_heap_realloc_enter(h, ptr, bytes, timeout) + +/** + * @brief Trace Heap realloc exit + * @param h Heap object + * @param ptr Pointer to reallocate + * @param bytes Bytes to reallocate + * @param timeout Timeout period + * @param ret Return value + */ +#define sys_port_trace_k_heap_realloc_exit(h, ptr, bytes, timeout, ret) + /** * @brief Trace System Heap aligned alloc enter * @param heap Heap object @@ -1743,6 +1762,19 @@ */ #define sys_port_trace_k_heap_sys_k_calloc_exit(heap, ret) +/** + * @brief Trace System heap realloc enter + * @param heap + */ +#define sys_port_trace_k_heap_sys_k_realloc_enter(heap, ptr) + +/** + * @brief Trace System heap realloc exit + * @param heap Heap object + * @param ret Return value + */ +#define sys_port_trace_k_heap_sys_k_realloc_exit(heap, ptr, ret) + /** @} */ /* end of subsys_tracing_apis_heap */ /** diff --git a/kernel/kheap.c b/kernel/kheap.c index a452f172a56d2..55b9feffced90 100644 --- a/kernel/kheap.c +++ b/kernel/kheap.c @@ -123,6 +123,8 @@ void *k_heap_realloc(struct k_heap *heap, void *ptr, size_t bytes, k_timeout_t t k_spinlock_key_t key = k_spin_lock(&heap->lock); + SYS_PORT_TRACING_OBJ_FUNC_ENTER(k_heap, realloc, heap, ptr, bytes, timeout); + __ASSERT(!arch_is_in_isr() || K_TIMEOUT_EQ(timeout, K_NO_WAIT), ""); while (ret == NULL) { @@ -138,6 +140,8 @@ void *k_heap_realloc(struct k_heap *heap, void *ptr, size_t bytes, k_timeout_t t key = k_spin_lock(&heap->lock); } + SYS_PORT_TRACING_OBJ_FUNC_EXIT(k_heap, realloc, heap, ptr, bytes, timeout, ret); + k_spin_unlock(&heap->lock, key); return ret; } diff --git a/kernel/mempool.c b/kernel/mempool.c index 3d7dba22faca0..c8298f0d6fc39 100644 --- a/kernel/mempool.c +++ b/kernel/mempool.c @@ -129,15 +129,22 @@ void *k_realloc(void *ptr, size_t size) ptr = --heap_ref; heap = *heap_ref; + SYS_PORT_TRACING_OBJ_FUNC_ENTER(k_heap_sys, k_realloc, heap, ptr); + if (size_add_overflow(size, sizeof(heap_ref), &size)) { + SYS_PORT_TRACING_OBJ_FUNC_EXIT(k_heap_sys, k_realloc, heap, ptr, NULL); return NULL; } ret = k_heap_realloc(heap, ptr, size, K_NO_WAIT); + if (ret != NULL) { heap_ref = ret; ret = ++heap_ref; } + + SYS_PORT_TRACING_OBJ_FUNC_EXIT(k_heap_sys, k_realloc, heap, ptr, ret); + return ret; } diff --git a/subsys/tracing/ctf/tracing_ctf.h b/subsys/tracing/ctf/tracing_ctf.h index 986a314f915ad..2c95195f94d53 100644 --- a/subsys/tracing/ctf/tracing_ctf.h +++ b/subsys/tracing/ctf/tracing_ctf.h @@ -303,6 +303,8 @@ extern "C" { #define sys_port_trace_k_heap_alloc_enter(heap, timeout) #define sys_port_trace_k_heap_alloc_exit(heap, timeout, ret) #define sys_port_trace_k_heap_free(heap) +#define sys_port_trace_k_heap_realloc_enter(h, ptr, bytes, timeout) +#define sys_port_trace_k_heap_realloc_exit(h, ptr, bytes, timeout, ret) #define sys_port_trace_k_heap_sys_k_aligned_alloc_enter(heap) #define sys_port_trace_k_heap_sys_k_aligned_alloc_exit(heap, ret) #define sys_port_trace_k_heap_sys_k_malloc_enter(heap) @@ -311,6 +313,8 @@ extern "C" { #define sys_port_trace_k_heap_sys_k_free_exit(heap, heap_ref) #define sys_port_trace_k_heap_sys_k_calloc_enter(heap) #define sys_port_trace_k_heap_sys_k_calloc_exit(heap, ret) +#define sys_port_trace_k_heap_sys_k_realloc_enter(heap, ptr) +#define sys_port_trace_k_heap_sys_k_realloc_exit(heap, ptr, ret) #define sys_port_trace_k_mem_slab_init(slab, rc) #define sys_port_trace_k_mem_slab_alloc_enter(slab, timeout) diff --git a/subsys/tracing/sysview/tracing_sysview.h b/subsys/tracing/sysview/tracing_sysview.h index 8d50f02c82760..b5255824d16a0 100644 --- a/subsys/tracing/sysview/tracing_sysview.h +++ b/subsys/tracing/sysview/tracing_sysview.h @@ -566,6 +566,14 @@ void sys_trace_thread_info(struct k_thread *thread); #define sys_port_trace_k_heap_free(heap) \ SEGGER_SYSVIEW_RecordU32(TID_HEAP_FREE, (uint32_t)(uintptr_t)heap) +#define sys_port_trace_k_heap_realloc_enter(heap, ptr, bytes, timeout) \ + SEGGER_SYSVIEW_RecordU32x4(TID_HEAP_REALLOC, (uint32_t)(uintptr_t)heap, \ + (uint32_t)(uintptr_t)ptr, (uint32_t)bytes, \ + (uint32_t)timeout.ticks) + +#define sys_port_trace_k_heap_realloc_exit(heap, ptr, bytes, timeout, ret) \ + SEGGER_SYSVIEW_RecordEndCallU32(TID_HEAP_REALLOC, (uint32_t)ret) + #define sys_port_trace_k_heap_sys_k_aligned_alloc_enter(heap) #define sys_port_trace_k_heap_sys_k_aligned_alloc_exit(heap, ret) #define sys_port_trace_k_heap_sys_k_malloc_enter(heap) @@ -574,6 +582,8 @@ void sys_trace_thread_info(struct k_thread *thread); #define sys_port_trace_k_heap_sys_k_free_exit(heap, heap_ref) #define sys_port_trace_k_heap_sys_k_calloc_enter(heap) #define sys_port_trace_k_heap_sys_k_calloc_exit(heap, ret) +#define sys_port_trace_k_heap_sys_k_realloc_enter(heap, ptr) +#define sys_port_trace_k_heap_sys_k_realloc_exit(heap, ptr, ret) #define sys_port_trace_k_mem_slab_init(slab, rc) \ SEGGER_SYSVIEW_RecordU32(TID_MSLAB_INIT, (uint32_t)(uintptr_t)slab) diff --git a/subsys/tracing/sysview/tracing_sysview_ids.h b/subsys/tracing/sysview/tracing_sysview_ids.h index 4c50130cc6dbe..3b8cd8701759a 100644 --- a/subsys/tracing/sysview/tracing_sysview_ids.h +++ b/subsys/tracing/sysview/tracing_sysview_ids.h @@ -71,6 +71,7 @@ extern "C" { #define TID_HEAP_ALLOC (45u + TID_OFFSET) #define TID_HEAP_FREE (46u + TID_OFFSET) #define TID_HEAP_ALIGNED_ALLOC (47u + TID_OFFSET) +#define TID_HEAP_REALLOC (48u + TID_OFFSET) #define TID_MSLAB_INIT (52u + TID_OFFSET) #define TID_MSLAB_ALLOC (53u + TID_OFFSET) diff --git a/subsys/tracing/test/tracing_string_format_test.c b/subsys/tracing/test/tracing_string_format_test.c index 29d781ad1ba5a..d0e5eb67371f5 100644 --- a/subsys/tracing/test/tracing_string_format_test.c +++ b/subsys/tracing/test/tracing_string_format_test.c @@ -361,6 +361,16 @@ void sys_trace_k_heap_free(struct k_heap *h, void *mem) TRACING_STRING("%s: %p\n", __func__, h); } +void sys_trace_k_heap_realloc_enter(struct k_heap *h, void *ptr, size_t bytes, k_timeout_t timeout) +{ + TRACING_STRING("%s: %p\n", __func__, h); +} +void sys_trace_k_heap_realloc_exit(struct k_heap *h, void *ptr, size_t bytes, k_timeout_t timeout, + void *ret) +{ + TRACING_STRING("%s: %p\n", __func__, h); +} + void sys_trace_k_heap_aligned_alloc_blocking(struct k_heap *h, size_t bytes, k_timeout_t timeout) { TRACING_STRING("%s: %p\n", __func__, h); diff --git a/subsys/tracing/test/tracing_test.h b/subsys/tracing/test/tracing_test.h index 71b63a762c59c..1e40a6831e8ea 100644 --- a/subsys/tracing/test/tracing_test.h +++ b/subsys/tracing/test/tracing_test.h @@ -379,6 +379,10 @@ #define sys_port_trace_k_heap_alloc_exit(h, timeout, ret) \ sys_trace_k_heap_alloc_exit(h, bytes, timeout, ret) #define sys_port_trace_k_heap_free(h) sys_trace_k_heap_free(h, mem) +#define sys_port_trace_k_heap_realloc_enter(h, ptr, bytes, timeout) \ + sys_trace_k_heap_realloc_enter(h, ptr, bytes, timeout) +#define sys_port_trace_k_heap_realloc_exit(h, ptr, bytes, timeout, ret) \ + sys_trace_k_heap_realloc_exit(h, ptr, bytes, timeout, ret) #define sys_port_trace_k_heap_sys_k_aligned_alloc_enter(heap) \ sys_trace_k_heap_sys_k_aligned_alloc_enter(heap, align, size) #define sys_port_trace_k_heap_sys_k_aligned_alloc_exit(heap, ret) \ @@ -395,6 +399,10 @@ sys_trace_k_heap_sys_k_calloc_enter(heap, nmemb, size) #define sys_port_trace_k_heap_sys_k_calloc_exit(heap, ret) \ sys_trace_k_heap_sys_k_calloc_exit(heap, nmemb, size, ret) +#define sys_port_trace_k_heap_sys_k_realloc_enter(heap, ptr) \ + sys_trace_k_heap_sys_k_realloc_enter(heap, ptr, size) +#define sys_port_trace_k_heap_sys_k_realloc_exit(heap, ptr, ret) \ + sys_trace_k_heap_sys_k_realloc_exit(heap, ptr, size, ret) #define sys_port_trace_k_mem_slab_init(slab, rc) \ sys_trace_k_mem_slab_init(slab, buffer, block_size, num_blocks, rc) @@ -654,6 +662,9 @@ void sys_trace_k_heap_aligned_alloc_blocking(struct k_heap *h, size_t bytes, k_t void sys_trace_k_heap_aligned_alloc_exit(struct k_heap *h, size_t bytes, k_timeout_t timeout, void *ret); void sys_trace_k_heap_free(struct k_heap *h, void *mem); +void sys_trace_k_heap_realloc_enter(struct k_heap *h, void *ptr, size_t bytes, k_timeout_t timeout); +void sys_trace_k_heap_realloc_exit(struct k_heap *h, void *ptr, size_t bytes, k_timeout_t timeout, + void *ret); void sys_trace_k_heap_sys_k_aligned_alloc_enter(struct k_heap *h, size_t align, size_t size); void sys_trace_k_heap_sys_k_aligned_alloc_exit(struct k_heap *h, size_t align, size_t size, void *ret); @@ -663,6 +674,8 @@ void sys_trace_k_heap_sys_k_free_enter(struct k_heap *h, struct k_heap **heap_re void sys_trace_k_heap_sys_k_free_exit(struct k_heap *h, struct k_heap **heap_ref); void sys_trace_k_heap_sys_k_calloc_enter(struct k_heap *h, size_t nmemb, size_t size); void sys_trace_k_heap_sys_k_calloc_exit(struct k_heap *h, size_t nmemb, size_t size, void *ret); +void sys_trace_k_heap_sys_k_realloc_enter(struct k_heap *h, void *ptr, size_t bytes); +void sys_trace_k_heap_sys_k_realloc_exit(struct k_heap *h, void *ptr, size_t bytes, void *ret); void sys_trace_k_mem_slab_init(struct k_mem_slab *slab, void *buffer, size_t block_size, uint32_t num_blocks, int ret); diff --git a/subsys/tracing/user/tracing_user.h b/subsys/tracing/user/tracing_user.h index c4231503d70a0..4f6f808b99b18 100644 --- a/subsys/tracing/user/tracing_user.h +++ b/subsys/tracing/user/tracing_user.h @@ -288,6 +288,8 @@ void sys_trace_idle(void); #define sys_port_trace_k_heap_alloc_enter(heap, timeout) #define sys_port_trace_k_heap_alloc_exit(heap, timeout, ret) #define sys_port_trace_k_heap_free(heap) +#define sys_port_trace_k_heap_realloc_enter(h, ptr, bytes, timeout) +#define sys_port_trace_k_heap_realloc_exit(h, ptr, bytes, timeout, ret) #define sys_port_trace_k_heap_sys_k_aligned_alloc_enter(heap) #define sys_port_trace_k_heap_sys_k_aligned_alloc_exit(heap, ret) #define sys_port_trace_k_heap_sys_k_malloc_enter(heap) @@ -296,6 +298,8 @@ void sys_trace_idle(void); #define sys_port_trace_k_heap_sys_k_free_exit(heap, heap_ref) #define sys_port_trace_k_heap_sys_k_calloc_enter(heap) #define sys_port_trace_k_heap_sys_k_calloc_exit(heap, ret) +#define sys_port_trace_k_heap_sys_k_realloc_enter(heap) +#define sys_port_trace_k_heap_sys_k_realloc_exit(heap, ret) #define sys_port_trace_k_mem_slab_init(slab, rc) #define sys_port_trace_k_mem_slab_alloc_enter(slab, timeout) From cd0c67f35aaf01a120f4b1bd0a336c721924f066 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fin=20Maa=C3=9F?= Date: Mon, 13 May 2024 09:47:36 +0200 Subject: [PATCH 1267/2849] tests: kernel: add test for k_realloc MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit add test for k_realloc. Co-authored-by: Yong Cong Sin Signed-off-by: Fin Maaß --- tests/lib/multi_heap/src/test_mheap_api.c | 61 +++++++++++++++++++++++ 1 file changed, 61 insertions(+) diff --git a/tests/lib/multi_heap/src/test_mheap_api.c b/tests/lib/multi_heap/src/test_mheap_api.c index f4f4e573de511..0c024ec7abdcc 100644 --- a/tests/lib/multi_heap/src/test_mheap_api.c +++ b/tests/lib/multi_heap/src/test_mheap_api.c @@ -101,6 +101,67 @@ ZTEST(mheap_api, test_mheap_malloc_free) zassert_is_null(block_fail, NULL); } +ZTEST(mheap_api, test_mheap_realloc) +{ + void *block1, *block2; + size_t nb; + + /* Realloc NULL pointer is equivalent to malloc() */ + block1 = k_realloc(NULL, BLK_SIZE_MIN); + zassert_not_null(block1); + + /* Allocate something larger than the heap */ + block2 = k_realloc(NULL, OVERFLOW_SIZE); + /* Should fail and return NULL */ + zassert_is_null(block2); + + /* Keep making the allocated buffer bigger until the heap is depleted */ + for (nb = 2; nb < (2 * BLK_NUM_MAX); nb++) { + void *last_block1 = block1; + + block1 = k_realloc(block1, nb * BLK_SIZE_MIN); + if (block1 == NULL) { + block1 = last_block1; + break; + } + } + + /* Allocate buffer2 when the heap has been depleted */ + block2 = k_realloc(NULL, BLK_SIZE_MIN); + /* Should fail and return NULL */ + zassert_is_null(block2); + + /* Now, make block1 smaller */ + block1 = k_realloc(block1, BLK_SIZE_MIN); + zassert_not_null(block1); + + /* Try to allocate buffer2 again */ + block2 = k_realloc(NULL, BLK_SIZE_MIN); + /* Should pass this time */ + zassert_not_null(block2); + + /* Deallocate everything */ + k_free(block1); + /* equivalent to k_free() */ + block2 = k_realloc(block2, 0); + /* Return NULL after freed */ + zassert_is_null(block2); + + /* After all allocated buffers have been freed, make sure that we are able to allocate as + * many again + */ + block1 = k_malloc(BLK_SIZE_MIN); + zassert_not_null(block1); + for (size_t i = 1; i < nb; i++) { + block1 = k_realloc(block1, i * BLK_SIZE_MIN); + zassert_not_null(block1); + } + + /* Free block1 with k_realloc() this time */ + block1 = k_realloc(block1, 0); + zassert_is_null(block1); +} + /** * @brief Test to demonstrate k_calloc() API functionality. * From c00288c37d5f305af4f550ab6363438a5d3f3367 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fin=20Maa=C3=9F?= Date: Mon, 13 May 2024 13:04:11 +0200 Subject: [PATCH 1268/2849] doc: releases: add k_realloc() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit add k_realloc() to the release notes. Signed-off-by: Fin Maaß --- doc/releases/release-notes-3.7.rst | 3 +++ 1 file changed, 3 insertions(+) diff --git a/doc/releases/release-notes-3.7.rst b/doc/releases/release-notes-3.7.rst index 334d12ed0535f..121bf88467e78 100644 --- a/doc/releases/release-notes-3.7.rst +++ b/doc/releases/release-notes-3.7.rst @@ -93,6 +93,9 @@ Kernel * Added :c:func:`k_uptime_seconds` function to simplify `k_uptime_get() / 1000` usage. + * Added :c:func:`k_realloc`, that uses kernel heap to implement traditional :c:func:`realloc` + semantics. + Bluetooth ********* * Audio From a4b37c7947fa93c80111baff778c1bb6ea88cfa9 Mon Sep 17 00:00:00 2001 From: Simon Hein Date: Thu, 23 May 2024 10:19:20 +0200 Subject: [PATCH 1269/2849] MAINTAINERS: Add simhein to coding guidelines collaborators Add myself to coding guidelines collaborators list to aid in reviewing PRs and move topics forward in that area. Signed-off-by: Simon Hein --- MAINTAINERS.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/MAINTAINERS.yml b/MAINTAINERS.yml index 1faf6126159fe..88a9729467383 100644 --- a/MAINTAINERS.yml +++ b/MAINTAINERS.yml @@ -646,6 +646,7 @@ Coding Guidelines: - nashif - carlescufi - jfischer-no + - simhein files: - .checkpatch.conf - .clang-format From 3ce106c620850626ec9d0a30fed2d2748a5f2a11 Mon Sep 17 00:00:00 2001 From: Rubin Gerritsen Date: Mon, 13 May 2024 13:51:57 +0200 Subject: [PATCH 1270/2849] Bluetooth: Host: Fix not clearing IDs and keys upon bt_disable() Expectation: After calling `bt_disable()` it is possible to use the Bluetooth APIs as if `bt_enable()` was never called. This was not the case for `bt_id_create()`, it was not possible to set the default identity. This prevented an application developer to restart the stack as a different identity. Keys also need to be cleared to avoid the following pattern: 1. Pair two devices 2. Central calls `bt_disable()` and `bt_enable()`. The central will now generate a new identity address. 3. Connect the two devices. 4. Re-establish encryption. Now the central will try to use the previously used keys. The procedure will fail because the peripheral does not have any keys associated with the new central address. The API documentation is updated accordingly. Signed-off-by: Rubin Gerritsen --- include/zephyr/bluetooth/bluetooth.h | 4 ++ subsys/bluetooth/host/hci_core.c | 7 +++ subsys/bluetooth/host/keys.c | 5 ++ subsys/bluetooth/host/keys.h | 6 ++ tests/bsim/bluetooth/host/iso/cis/prj.conf | 1 + .../host/misc/disable/src/main_disable.c | 63 +++++++++++++++++++ .../tests_scripts/disable_set_default_id.sh | 20 ++++++ 7 files changed, 106 insertions(+) create mode 100755 tests/bsim/bluetooth/host/misc/disable/tests_scripts/disable_set_default_id.sh diff --git a/include/zephyr/bluetooth/bluetooth.h b/include/zephyr/bluetooth/bluetooth.h index 59689974b8763..72c386ae4d68b 100644 --- a/include/zephyr/bluetooth/bluetooth.h +++ b/include/zephyr/bluetooth/bluetooth.h @@ -231,6 +231,10 @@ int bt_enable(bt_ready_cb_t cb); * * Disable Bluetooth. Can't be called before bt_enable has completed. * + * This API will clear all configured identities and keys that are not persistently + * stored with @kconfig{CONFIG_BT_SETTINGS}. These can be restored + * with settings_load() before reenabling the stack. + * * Close and release HCI resources. Result is architecture dependent. * * @return Zero on success or (negative) error code otherwise. diff --git a/subsys/bluetooth/host/hci_core.c b/subsys/bluetooth/host/hci_core.c index 1c4a5ca67e146..3f0a32dd09405 100644 --- a/subsys/bluetooth/host/hci_core.c +++ b/subsys/bluetooth/host/hci_core.c @@ -4233,6 +4233,13 @@ int bt_disable(void) /* Some functions rely on checking this bitfield */ memset(bt_dev.supported_commands, 0x00, sizeof(bt_dev.supported_commands)); + /* Reset IDs and corresponding keys. */ + bt_dev.id_count = 0; +#if defined(CONFIG_BT_SMP) + bt_dev.le.rl_entries = 0; + bt_keys_reset(); +#endif + /* If random address was set up - clear it */ bt_addr_le_copy(&bt_dev.random_addr, BT_ADDR_LE_ANY); diff --git a/subsys/bluetooth/host/keys.c b/subsys/bluetooth/host/keys.c index c8184d7cbb47d..6740d43b1cd08 100644 --- a/subsys/bluetooth/host/keys.c +++ b/subsys/bluetooth/host/keys.c @@ -80,6 +80,11 @@ static bool key_is_in_use(uint8_t id) } #endif /* CONFIG_BT_KEYS_OVERWRITE_OLDEST */ +void bt_keys_reset(void) +{ + memset(key_pool, 0, sizeof(key_pool)); +} + struct bt_keys *bt_keys_get_addr(uint8_t id, const bt_addr_le_t *addr) { struct bt_keys *keys; diff --git a/subsys/bluetooth/host/keys.h b/subsys/bluetooth/host/keys.h index 198b6991ca912..76508e0cf3969 100644 --- a/subsys/bluetooth/host/keys.h +++ b/subsys/bluetooth/host/keys.h @@ -82,6 +82,12 @@ struct bt_keys { #define BT_KEYS_STORAGE_LEN (sizeof(struct bt_keys) - \ offsetof(struct bt_keys, storage_start)) +/** Clears all keys. + * + * Keys stored in settings are not cleared. + */ +void bt_keys_reset(void); + /** * @brief Get a call through the callback for each key with the same type * diff --git a/tests/bsim/bluetooth/host/iso/cis/prj.conf b/tests/bsim/bluetooth/host/iso/cis/prj.conf index 134cd4beed5c0..8637b14f0045f 100644 --- a/tests/bsim/bluetooth/host/iso/cis/prj.conf +++ b/tests/bsim/bluetooth/host/iso/cis/prj.conf @@ -2,6 +2,7 @@ CONFIG_BT=y CONFIG_LOG=y CONFIG_ASSERT=y CONFIG_BT_SMP=y +CONFIG_BT_MAX_PAIRED=2 CONFIG_BT_DEVICE_NAME="CIS test" diff --git a/tests/bsim/bluetooth/host/misc/disable/src/main_disable.c b/tests/bsim/bluetooth/host/misc/disable/src/main_disable.c index d4a6f6d904a7e..43f9b00af8b69 100644 --- a/tests/bsim/bluetooth/host/misc/disable/src/main_disable.c +++ b/tests/bsim/bluetooth/host/misc/disable/src/main_disable.c @@ -35,6 +35,62 @@ static void test_disable_main(void) PASS("Disable test passed\n"); } +static void test_disable_set_default_id(void) +{ + /* FIXME: Temporary workaround to get around a bug in the controller. + * The controller gets stuck in the POWER_CLOCK ISR without this. + * See open PR: https://github.com/zephyrproject-rtos/zephyr/pull/73342 + * for more details. + */ + k_sleep(K_MSEC(1)); + + for (int i = 0; i < NUM_ITERATIONS; i++) { + int err; + size_t id_count; + bt_addr_le_t stored_id; + bt_addr_le_t addr = {.type = BT_ADDR_LE_RANDOM, + .a = {.val = {i, 2, 3, 4, 5, 0xc0}}}; + + err = bt_id_create(&addr, NULL); + if (err != 0) { + FAIL("Creating ID failed (err %d)\n", err); + } + + err = bt_enable(NULL); + if (err != 0) { + FAIL("Enable failed (err %d)\n", err); + } + + bt_id_get(NULL, &id_count); + if (id_count != 1) { + FAIL("Expected only one ID, but got: %u\n", id_count); + } + + id_count = 1; + bt_id_get(&stored_id, &id_count); + if (id_count != 1) { + FAIL("Expected only one ID, but got: %u\n", id_count); + } + + if (!bt_addr_le_eq(&stored_id, &addr)) { + uint8_t addr_set_str[BT_ADDR_LE_STR_LEN]; + uint8_t addr_stored_str[BT_ADDR_LE_STR_LEN]; + + bt_addr_le_to_str(&addr, addr_set_str, BT_ADDR_LE_STR_LEN); + bt_addr_le_to_str(&stored_id, addr_stored_str, BT_ADDR_LE_STR_LEN); + FAIL("Expected stored ID to be equal to set ID: %s, %s\n", + addr_set_str, addr_stored_str); + } + + err = bt_disable(); + if (err) { + FAIL("Enable failed (err %d)\n", err); + } + } + + PASS("Disable set default ID test passed\n"); +} + static const struct bst_test_instance test_def[] = { { .test_id = "disable", @@ -43,6 +99,13 @@ static const struct bst_test_instance test_def[] = { .test_tick_f = test_tick, .test_main_f = test_disable_main }, + { + .test_id = "disable_set_default_id", + .test_descr = "disable_test where each iteration sets the default ID", + .test_pre_init_f = test_init, + .test_tick_f = test_tick, + .test_main_f = test_disable_set_default_id + }, BSTEST_END_MARKER }; diff --git a/tests/bsim/bluetooth/host/misc/disable/tests_scripts/disable_set_default_id.sh b/tests/bsim/bluetooth/host/misc/disable/tests_scripts/disable_set_default_id.sh new file mode 100755 index 0000000000000..437dcdff139af --- /dev/null +++ b/tests/bsim/bluetooth/host/misc/disable/tests_scripts/disable_set_default_id.sh @@ -0,0 +1,20 @@ +#!/usr/bin/env bash +# Copyright (c) 2022 Nordic Semiconductor +# SPDX-License-Identifier: Apache-2.0 + +source ${ZEPHYR_BASE}/tests/bsim/sh_common.source + +# Disable test: bt_enable and bt_disable are called in a loop. +# Each iteration the default ID is updated +simulation_id="disable_test_set_default_id" +verbosity_level=2 + +cd ${BSIM_OUT_PATH}/bin + +Execute ./bs_${BOARD_TS}_tests_bsim_bluetooth_host_misc_disable_prj_conf \ + -v=${verbosity_level} -s=${simulation_id} -d=0 -testid=disable_set_default_id + +Execute ./bs_2G4_phy_v1 -v=${verbosity_level} -s=${simulation_id} \ + -D=1 -sim_length=10e6 $@ + +wait_for_background_jobs From ff80c0b926e42409ba3a69e7c0aa375ccc286803 Mon Sep 17 00:00:00 2001 From: Rubin Gerritsen Date: Mon, 13 May 2024 11:51:41 +0200 Subject: [PATCH 1271/2849] Bluetooth: Host: Fix connection establishment upon RPA timeout Before this commit, the following bugs were present: - When `CONFIG_BT_FILTER_ACCEPT_LIST` was set, connection establishment was cancelled upon RPA timeout. This required the application to restart the initiator every RPA timeout. - When `CONFIG_BT_FILTER_ACCEPT_LIST` was not set, the RPA was not updated while the initiator was running. This commit unifies the RPA timeout handling for both these cases. Upon RPA timeout the initiator is cancelled and restarted when the controller raises the LE Connection Complete event. The workqueue state is checked when restarting the initiator to prevent it being restarted when the timeout is hit. Corresponding test cases have been added to ensure that this feature works. Signed-off-by: Rubin Gerritsen --- subsys/bluetooth/host/hci_core.c | 36 +++++----- subsys/bluetooth/host/id.c | 1 - .../host/privacy/central/CMakeLists.txt | 6 ++ .../bluetooth/host/privacy/central/prj.conf | 5 ++ .../bluetooth/host/privacy/central/src/dut.c | 70 +++++++++++++++++++ .../bluetooth/host/privacy/central/src/main.c | 30 ++++++++ .../host/privacy/central/src/tester.c | 60 ++++++++++++++++ .../run_test_short_conn_timeout.sh | 26 +++++++ .../run_test_short_rpa_timeout.sh | 31 ++++++++ 9 files changed, 248 insertions(+), 17 deletions(-) create mode 100755 tests/bsim/bluetooth/host/privacy/central/test_scripts/run_test_short_conn_timeout.sh create mode 100755 tests/bsim/bluetooth/host/privacy/central/test_scripts/run_test_short_rpa_timeout.sh diff --git a/subsys/bluetooth/host/hci_core.c b/subsys/bluetooth/host/hci_core.c index 3f0a32dd09405..9a87a47f6db1f 100644 --- a/subsys/bluetooth/host/hci_core.c +++ b/subsys/bluetooth/host/hci_core.c @@ -1159,6 +1159,7 @@ static void conn_auto_initiate(struct bt_conn *conn) static void le_conn_complete_cancel(uint8_t err) { + int ret; struct bt_conn *conn; /* Handle create connection cancel. @@ -1172,27 +1173,30 @@ static void le_conn_complete_cancel(uint8_t err) return; } - conn->err = err; - - /* Handle cancellation of outgoing connection attempt. */ - if (!IS_ENABLED(CONFIG_BT_FILTER_ACCEPT_LIST)) { - /* We notify before checking autoconnect flag - * as application may choose to change it from - * callback. - */ - bt_conn_set_state(conn, BT_CONN_DISCONNECTED); - /* Check if device is marked for autoconnect. */ - if (atomic_test_bit(conn->flags, BT_CONN_AUTO_CONNECT)) { + if (atomic_test_bit(conn->flags, BT_CONN_AUTO_CONNECT)) { + if (!IS_ENABLED(CONFIG_BT_FILTER_ACCEPT_LIST)) { /* Restart passive scanner for device */ bt_conn_set_state(conn, BT_CONN_SCAN_BEFORE_INITIATING); + } else { + /* Restart FAL initiator after RPA timeout. */ + ret = bt_le_create_conn(conn); + if (ret) { + LOG_ERR("Failed to restart initiator"); + } } } else { - if (atomic_test_bit(conn->flags, BT_CONN_AUTO_CONNECT)) { - /* Restart FAL initiator after RPA timeout. */ - bt_le_create_conn(conn); - } else { - /* Create connection canceled by timeout */ + int busy_status = k_work_delayable_busy_get(&conn->deferred_work); + + if (!(busy_status & (K_WORK_QUEUED | K_WORK_DELAYED))) { + /* Connection initiation timeout triggered. */ + conn->err = err; bt_conn_set_state(conn, BT_CONN_DISCONNECTED); + } else { + /* Restart initiator after RPA timeout. */ + ret = bt_le_create_conn(conn); + if (ret) { + LOG_ERR("Failed to restart initiator"); + } } } diff --git a/subsys/bluetooth/host/id.c b/subsys/bluetooth/host/id.c index d6f23f2db6415..38263e1cb2a65 100644 --- a/subsys/bluetooth/host/id.c +++ b/subsys/bluetooth/host/id.c @@ -606,7 +606,6 @@ static void le_update_private_addr(void) } #endif if (IS_ENABLED(CONFIG_BT_CENTRAL) && - IS_ENABLED(CONFIG_BT_FILTER_ACCEPT_LIST) && atomic_test_bit(bt_dev.flags, BT_DEV_INITIATING)) { /* Canceled initiating procedure will be restarted by * connection complete event. diff --git a/tests/bsim/bluetooth/host/privacy/central/CMakeLists.txt b/tests/bsim/bluetooth/host/privacy/central/CMakeLists.txt index 75e1deb8f8237..7ec3436c8f841 100644 --- a/tests/bsim/bluetooth/host/privacy/central/CMakeLists.txt +++ b/tests/bsim/bluetooth/host/privacy/central/CMakeLists.txt @@ -5,6 +5,12 @@ cmake_minimum_required(VERSION 3.20.0) find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) project(bsim_test_rpa_central) +add_subdirectory(${ZEPHYR_BASE}/tests/bluetooth/common/testlib testlib) +target_link_libraries(app PRIVATE testlib) + +add_subdirectory(${ZEPHYR_BASE}/tests/bsim/babblekit babblekit) +target_link_libraries(app PRIVATE babblekit) + target_sources(app PRIVATE src/bs_bt_utils.c src/tester.c diff --git a/tests/bsim/bluetooth/host/privacy/central/prj.conf b/tests/bsim/bluetooth/host/privacy/central/prj.conf index e3fa9de43d71a..a4eea958b17ec 100644 --- a/tests/bsim/bluetooth/host/privacy/central/prj.conf +++ b/tests/bsim/bluetooth/host/privacy/central/prj.conf @@ -11,3 +11,8 @@ CONFIG_BT_RPA_TIMEOUT=10 CONFIG_BT_CTLR_ADV_SET=2 CONFIG_BT_CTLR_SCAN_REQ_NOTIFY=y CONFIG_BT_SCAN_WITH_IDENTITY=y + +# Enable the possibility to set the RPA such that the RPA +# refreshes before the connection attempt has completed +CONFIG_BT_RPA_TIMEOUT_DYNAMIC=y +CONFIG_BT_CREATE_CONN_TIMEOUT=10 diff --git a/tests/bsim/bluetooth/host/privacy/central/src/dut.c b/tests/bsim/bluetooth/host/privacy/central/src/dut.c index e80b9bc8f93f4..5a49b6e5097bf 100644 --- a/tests/bsim/bluetooth/host/privacy/central/src/dut.c +++ b/tests/bsim/bluetooth/host/privacy/central/src/dut.c @@ -12,6 +12,10 @@ #include #include +#include +#include +#include + void start_scanning(void) { int err; @@ -46,3 +50,69 @@ void dut_procedure(void) PASS("PASS\n"); } + +void dut_procedure_connect_short_rpa_timeout(void) +{ + backchannel_init(1); + + const uint16_t rpa_timeout_s = 1; + + int err; + bt_addr_le_t peer = {}; + struct bt_conn *conn = NULL; + + /* Enable bluetooth */ + err = bt_enable(NULL); + TEST_ASSERT(!err, "Failed to enable bluetooth (err %d)"); + + /* Central to use a short RPA timeout */ + err = bt_le_set_rpa_timeout(rpa_timeout_s); + TEST_ASSERT(!err, "Failed to set RPA timeout (err %d)", err); + + err = bt_testlib_scan_find_name(&peer, CONFIG_BT_DEVICE_NAME); + TEST_ASSERT(!err, "Failed to start scan (err %d)", err); + + /* Indicate to the peer device that we have found the advertiser. */ + backchannel_sync_send(); + + /* Create a connection using that address */ + err = bt_testlib_connect(&peer, &conn); + TEST_ASSERT(!err, "Failed to initiate connection (err %d)", err); + + PASS("PASS\n"); +} + +void dut_procedure_connect_timeout(void) +{ + const uint16_t rpa_timeout_s = 1; + + int err; + bt_addr_le_t peer = {.type = BT_ADDR_LE_RANDOM, .a = {.val = {1, 2, 3, 4, 5, 6}}}; + struct bt_conn *conn = NULL; + + /* Enable bluetooth */ + err = bt_enable(NULL); + TEST_ASSERT(!err, "Failed to enable bluetooth (err %d)", err); + + /* Central to use a short RPA timeout */ + err = bt_le_set_rpa_timeout(rpa_timeout_s); + TEST_ASSERT(!err, "Failed to set RPA timeout (err %d)", err); + + int64_t old_time = k_uptime_get(); + + /* Create a connection using that address */ + err = bt_testlib_connect(&peer, &conn); + TEST_ASSERT(err == BT_HCI_ERR_UNKNOWN_CONN_ID, + "Expected connection establishment to time out (err %d)", err); + + int64_t new_time = k_uptime_get(); + int64_t time_diff_ms = new_time - old_time; + int64_t expected_conn_timeout_ms = CONFIG_BT_CREATE_CONN_TIMEOUT * 1000; + int64_t diff_to_expected_ms = abs(time_diff_ms - expected_conn_timeout_ms); + + printk("Connection creation timed out after %d ms\n", time_diff_ms); + TEST_ASSERT(diff_to_expected_ms < 0.1 * expected_conn_timeout_ms, + "Connection timeout not within 10 \%% of expected timeout"); + + PASS("PASS\n"); +} diff --git a/tests/bsim/bluetooth/host/privacy/central/src/main.c b/tests/bsim/bluetooth/host/privacy/central/src/main.c index cb5f12f9d0fcc..a2f48b09ec84d 100644 --- a/tests/bsim/bluetooth/host/privacy/central/src/main.c +++ b/tests/bsim/bluetooth/host/privacy/central/src/main.c @@ -8,21 +8,51 @@ #include "bstests.h" void tester_procedure(void); +void tester_procedure_periph_delayed_start_of_conn_adv(void); void dut_procedure(void); +void dut_procedure_connect_short_rpa_timeout(void); +void dut_procedure_connect_timeout(void); static const struct bst_test_instance test_to_add[] = { { .test_id = "central", + .test_descr = "Central performs active scanning using RPA", .test_post_init_f = test_init, .test_tick_f = test_tick, .test_main_f = dut_procedure, }, + { + .test_id = "central_connect_short_rpa_timeout", + .test_descr = "Central connects to a peripheral using a short RPA timeout", + .test_post_init_f = test_init, + .test_tick_f = test_tick, + .test_main_f = dut_procedure_connect_short_rpa_timeout, + }, + { + .test_id = "central_connect_fails_with_short_rpa_timeout", + .test_descr = "Central connects to a peripheral using a short RPA timeout" + " but expects connection establishment to time out.", + .test_post_init_f = test_init, + .test_tick_f = test_tick, + .test_main_f = dut_procedure_connect_timeout, + }, { .test_id = "peripheral", + .test_descr = "Performs scannable advertising, validates that the scanner" + " RPA address refreshes", .test_post_init_f = test_init, .test_tick_f = test_tick, .test_main_f = tester_procedure, }, + { + .test_id = "periph_delayed_start_of_conn_adv", + .test_descr = "Performs connectable advertising. " + "The advertiser is stopped for 10 seconds when instructed by the DUT" + " to allow it to run the initiator for longer than its RPA timeout.", + .test_post_init_f = test_init, + .test_tick_f = test_tick, + .test_main_f = tester_procedure_periph_delayed_start_of_conn_adv, + }, BSTEST_END_MARKER, }; diff --git a/tests/bsim/bluetooth/host/privacy/central/src/tester.c b/tests/bsim/bluetooth/host/privacy/central/src/tester.c index 1bbb8fc8de6e8..b1c6e9fd1bc6d 100644 --- a/tests/bsim/bluetooth/host/privacy/central/src/tester.c +++ b/tests/bsim/bluetooth/host/privacy/central/src/tester.c @@ -14,7 +14,10 @@ #include #include +#include + DEFINE_FLAG(flag_new_address); +DEFINE_FLAG(flag_connected); void scanned_cb(struct bt_le_ext_adv *adv, struct bt_le_ext_adv_scanned_info *info) { @@ -64,8 +67,14 @@ void scanned_cb(struct bt_le_ext_adv *adv, struct bt_le_ext_adv_scanned_info *in old_addr = new_addr; } +static void connected_cb(struct bt_le_ext_adv *adv, struct bt_le_ext_adv_connected_info *info) +{ + SET_FLAG(flag_connected); +} + static struct bt_le_ext_adv_cb adv_callbacks = { .scanned = scanned_cb, + .connected = connected_cb }; void start_advertising(void) @@ -125,3 +134,54 @@ void tester_procedure(void) PASS("PASS\n"); } + +void tester_procedure_periph_delayed_start_of_conn_adv(void) +{ + backchannel_init(0); + + int err; + struct bt_le_adv_param params = + BT_LE_ADV_PARAM_INIT(BT_LE_ADV_OPT_CONNECTABLE | BT_LE_ADV_OPT_USE_IDENTITY, + BT_GAP_ADV_FAST_INT_MIN_2, + BT_GAP_ADV_FAST_INT_MAX_2, NULL); + struct bt_data ad; + struct bt_le_ext_adv *adv; + + /* Enable bluetooth */ + err = bt_enable(NULL); + TEST_ASSERT(!err, "Failed to enable bluetooth (err %d)"); + + /* Advertiser to use a long RPA timeout */ + err = bt_le_set_rpa_timeout(100); + TEST_ASSERT(!err, "Failed to set RPA timeout (err %d)", err); + + err = bt_le_ext_adv_create(¶ms, &adv_callbacks, &adv); + TEST_ASSERT(!err, "Failed to create advertising set (err %d)", err); + + ad.type = BT_DATA_NAME_COMPLETE; + ad.data_len = strlen(CONFIG_BT_DEVICE_NAME); + ad.data = (const uint8_t *)CONFIG_BT_DEVICE_NAME; + + err = bt_le_ext_adv_set_data(adv, &ad, 1, NULL, 0); + TEST_ASSERT(!err, "Failed to set advertising data (err %d)", err); + + err = bt_le_ext_adv_start(adv, BT_LE_EXT_ADV_START_DEFAULT); + TEST_ASSERT(!err, "Failed to start advertiser (err %d)", err); + + backchannel_sync_wait(); + + err = bt_le_ext_adv_stop(adv); + TEST_ASSERT(!err, "Failed to stop advertiser (err %d)", err); + + /* Wait a few RPA cycles before restaring the advertiser to force RPA timeout + * on the DUT. + */ + k_sleep(K_SECONDS(7)); + + err = bt_le_ext_adv_start(adv, BT_LE_EXT_ADV_START_DEFAULT); + TEST_ASSERT(!err, "Failed to restart advertiser (err %d)", err); + + WAIT_FOR_FLAG(flag_connected); + + PASS("PASS\n"); +} diff --git a/tests/bsim/bluetooth/host/privacy/central/test_scripts/run_test_short_conn_timeout.sh b/tests/bsim/bluetooth/host/privacy/central/test_scripts/run_test_short_conn_timeout.sh new file mode 100755 index 0000000000000..5e15e78517839 --- /dev/null +++ b/tests/bsim/bluetooth/host/privacy/central/test_scripts/run_test_short_conn_timeout.sh @@ -0,0 +1,26 @@ +#!/usr/bin/env bash +# Copyright 2024 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 +set -eu + +source ${ZEPHYR_BASE}/tests/bsim/sh_common.source + +EXECUTE_TIMEOUT=100 +verbosity_level=2 + +# Test that connection establishment times out when RPA +# timeout is shorter than the connection establishment timeout +simulation_id="test_central_connect_fails_with_short_rpa_timeout" + +central_exe="${BSIM_OUT_PATH}/bin/bs_${BOARD_TS}_$(guess_test_long_name)_prj_conf" + +cd ${BSIM_OUT_PATH}/bin + +Execute "$central_exe" \ + -v=${verbosity_level} -s=${simulation_id} -d=0 \ + -testid=central_connect_fails_with_short_rpa_timeout -RealEncryption=1 + +Execute ./bs_2G4_phy_v1 -v=${verbosity_level} -s=${simulation_id} \ + -D=1 -sim_length=60e6 $@ + +wait_for_background_jobs diff --git a/tests/bsim/bluetooth/host/privacy/central/test_scripts/run_test_short_rpa_timeout.sh b/tests/bsim/bluetooth/host/privacy/central/test_scripts/run_test_short_rpa_timeout.sh new file mode 100755 index 0000000000000..0ed76b2f86ac2 --- /dev/null +++ b/tests/bsim/bluetooth/host/privacy/central/test_scripts/run_test_short_rpa_timeout.sh @@ -0,0 +1,31 @@ +#!/usr/bin/env bash +# Copyright 2024 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 +set -eu + +source ${ZEPHYR_BASE}/tests/bsim/sh_common.source + +EXECUTE_TIMEOUT=100 +verbosity_level=2 + +# Test connection establishment when the RPA times out before +# we expect the connection to be established +simulation_id="test_central_connect_short_rpa_timeout" + +central_exe="${BSIM_OUT_PATH}/bin/bs_${BOARD_TS}_$(guess_test_long_name)_prj_conf" +peripheral_exe="${central_exe}" + +cd ${BSIM_OUT_PATH}/bin + +Execute "$central_exe" \ + -v=${verbosity_level} -s=${simulation_id} -d=0 \ + -testid=central_connect_short_rpa_timeout -RealEncryption=1 + +Execute "$peripheral_exe" \ + -v=${verbosity_level} -s=${simulation_id} -d=1 \ + -testid=periph_delayed_start_of_conn_adv -RealEncryption=1 + +Execute ./bs_2G4_phy_v1 -v=${verbosity_level} -s=${simulation_id} \ + -D=2 -sim_length=60e6 $@ + +wait_for_background_jobs From b4047307fac9f740dbd1b94e60f0f868b7b95488 Mon Sep 17 00:00:00 2001 From: Adam Kondraciuk Date: Mon, 29 Jan 2024 15:04:01 +0100 Subject: [PATCH 1272/2849] drivers: timer: grtc: Fix ticks calculation for GRTC Fixed calculation of GRTC ticks inside `z_nrf_grtc_timer_get_ticks()` function. Signed-off-by: Adam Kondraciuk --- drivers/timer/nrf_grtc_timer.c | 7 +++++-- include/zephyr/drivers/timer/nrf_grtc_timer.h | 2 +- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/timer/nrf_grtc_timer.c b/drivers/timer/nrf_grtc_timer.c index a12bf607555d4..45cd2212bc827 100644 --- a/drivers/timer/nrf_grtc_timer.c +++ b/drivers/timer/nrf_grtc_timer.c @@ -332,18 +332,21 @@ uint64_t z_nrf_grtc_timer_get_ticks(k_timeout_t t) int64_t curr_tick; int64_t result; int64_t abs_ticks; + int64_t grtc_ticks; curr_time = counter(); curr_tick = sys_clock_tick_get(); + grtc_ticks = t.ticks * CYC_PER_TICK; abs_ticks = Z_TICK_ABS(t.ticks); if (abs_ticks < 0) { /* relative timeout */ - return (t.ticks > (int64_t)COUNTER_SPAN) ? -EINVAL : (curr_time + t.ticks); + return (grtc_ticks > (int64_t)COUNTER_SPAN) ? + -EINVAL : (curr_time + grtc_ticks); } /* absolute timeout */ - result = abs_ticks - curr_tick; + result = (abs_ticks - curr_tick) * CYC_PER_TICK; if (result > (int64_t)COUNTER_SPAN) { return -EINVAL; diff --git a/include/zephyr/drivers/timer/nrf_grtc_timer.h b/include/zephyr/drivers/timer/nrf_grtc_timer.h index 036d58517255b..4cd3f8d14cb2e 100644 --- a/include/zephyr/drivers/timer/nrf_grtc_timer.h +++ b/include/zephyr/drivers/timer/nrf_grtc_timer.h @@ -113,7 +113,7 @@ int z_nrf_grtc_timer_compare_read(int32_t chan, uint64_t *val); * * @param chan Channel ID. * - * @param target_time Absolute target time in ticks. + * @param target_time Absolute target time in GRTC ticks. * * @param handler User function called in the context of the GRTC interrupt. * From cac0da313b238a746acc2d998d40aac54ad040c3 Mon Sep 17 00:00:00 2001 From: Adam Kondraciuk Date: Tue, 19 Dec 2023 15:25:08 +0100 Subject: [PATCH 1273/2849] drivers: timer: grtc: Update GRTC driver This commit aligns the GRTC driver to changes introduced in hal_nordic. Some of the features regarding GRTC sleep/wakeup functionality has been modified and moved out to the nrfx driver's code. Signed-off-by: Adam Kondraciuk --- drivers/timer/Kconfig.nrf_grtc | 13 ++- drivers/timer/nrf_grtc_timer.c | 88 +++++-------------- include/zephyr/drivers/timer/nrf_grtc_timer.h | 1 + modules/hal_nordic/nrfx/CMakeLists.txt | 4 - modules/hal_nordic/nrfx/nrfx_config.h | 13 +++ 5 files changed, 48 insertions(+), 71 deletions(-) diff --git a/drivers/timer/Kconfig.nrf_grtc b/drivers/timer/Kconfig.nrf_grtc index 0436c071fa200..cda39ae8b1c2b 100644 --- a/drivers/timer/Kconfig.nrf_grtc +++ b/drivers/timer/Kconfig.nrf_grtc @@ -41,9 +41,20 @@ config NRF_GRTC_TIMER_CLOCK_MANAGEMENT the GRTC. Usually this is only needed by the processor that is starting the SYSCOUNTER, but can be shared by multiple processors in the system. -config NRF_GRTC_SLEEP_MINIMUM_LATENCY +config NRF_GRTC_SYSCOUNTER_SLEEP_MINIMUM_LATENCY int default 1000 depends on NRF_GRTC_SLEEP_ALLOWED + help + The value (in us) ensures that the wakeup event will not fire + too early. In other words, applying SYSCOUNTER sleep state for less than + NRF_GRTC_SYSCOUNTER_SLEEP_MINIMUM_LATENCY period makes no sense. + +config NRF_GRTC_TIMER_AUTO_KEEP_ALIVE + bool + default y if NRF_GRTC_START_SYSCOUNTER + help + This feature prevents the SYSCOUNTER to sleep when any core is in + active state. endif # NRF_GRTC_TIMER diff --git a/drivers/timer/nrf_grtc_timer.c b/drivers/timer/nrf_grtc_timer.c index 45cd2212bc827..8c1c927b142ea 100644 --- a/drivers/timer/nrf_grtc_timer.c +++ b/drivers/timer/nrf_grtc_timer.c @@ -29,12 +29,6 @@ #define CHAN_COUNT NRFX_GRTC_CONFIG_NUM_OF_CC_CHANNELS #define EXT_CHAN_COUNT (CHAN_COUNT - 1) -/* The reset value of waketime is 1, which doesn't seem to work. - * It's being looked into, but for the time being use 4. - * Timeout must always be higher than waketime, so setting that to 5. - */ -#define WAKETIME (4) -#define TIMEOUT (WAKETIME + 1) #ifndef GRTC_SYSCOUNTERL_VALUE_Msk #define GRTC_SYSCOUNTERL_VALUE_Msk GRTC_SYSCOUNTER_SYSCOUNTERL_VALUE_Msk @@ -55,8 +49,7 @@ #define MAX_CYCLES (MAX_TICKS * CYC_PER_TICK) -/* The maximum SYSCOUNTERVALID settling time equals 1x32k cycles + 20x1MHz cycles. */ -#define GRTC_SYSCOUNTERVALID_SETTLE_MAX_TIME_US 51 +#define LFCLK_FREQUENCY_HZ 32768 #if defined(CONFIG_TEST) const int32_t z_sys_timer_irq_for_test = DT_IRQN(GRTC_NODE); @@ -78,36 +71,6 @@ static nrfx_grtc_channel_t system_clock_channel_data = { __ASSERT_NO_MSG((NRFX_GRTC_CONFIG_ALLOWED_CC_CHANNELS_MASK & (1UL << (chan))) && \ ((chan) != system_clock_channel_data.channel)) -static inline void grtc_active_set(void) -{ -#if defined(NRF_GRTC_HAS_SYSCOUNTER_ARRAY) && (NRF_GRTC_HAS_SYSCOUNTER_ARRAY == 1) - nrfy_grtc_sys_counter_active_set(NRF_GRTC, true); - while (!nrfy_grtc_sys_conter_ready_check(NRF_GRTC)) { - } -#else - nrfy_grtc_sys_counter_active_state_request_set(NRF_GRTC, true); - k_busy_wait(GRTC_SYSCOUNTERVALID_SETTLE_MAX_TIME_US); -#endif -} - -static inline void grtc_wakeup(void) -{ - if (IS_ENABLED(CONFIG_NRF_GRTC_SLEEP_ALLOWED)) { - grtc_active_set(); - } -} - -static inline void grtc_sleep(void) -{ - if (IS_ENABLED(CONFIG_NRF_GRTC_SLEEP_ALLOWED)) { -#if defined(NRF_GRTC_HAS_SYSCOUNTER_ARRAY) && (NRF_GRTC_HAS_SYSCOUNTER_ARRAY == 1) - nrfy_grtc_sys_counter_active_set(NRF_GRTC, false); -#else - nrfy_grtc_sys_counter_active_state_request_set(NRF_GRTC, false); -#endif - } -} - static inline uint64_t counter_sub(uint64_t a, uint64_t b) { return (a - b); @@ -116,10 +79,7 @@ static inline uint64_t counter_sub(uint64_t a, uint64_t b) static inline uint64_t counter(void) { uint64_t now; - - grtc_wakeup(); nrfx_grtc_syscounter_get(&now); - grtc_sleep(); return now; } @@ -143,10 +103,8 @@ static inline int get_comparator(uint32_t chan, uint64_t *cc) static void system_timeout_set_relative(uint64_t value) { if (value <= NRF_GRTC_SYSCOUNTER_CCADD_MASK) { - grtc_wakeup(); nrfx_grtc_syscounter_cc_relative_set(&system_clock_channel_data, value, true, NRFX_GRTC_CC_RELATIVE_SYSCOUNTER); - grtc_sleep(); } else { nrfx_grtc_syscounter_cc_absolute_set(&system_clock_channel_data, value + counter(), true); @@ -386,6 +344,7 @@ int z_nrf_grtc_timer_capture_read(int32_t chan, uint64_t *captured_time) */ uint64_t capt_time; + nrfx_err_t result; IS_CHANNEL_ALLOWED_ASSERT(chan); @@ -396,8 +355,10 @@ int z_nrf_grtc_timer_capture_read(int32_t chan, uint64_t *captured_time) */ return -EBUSY; } - - capt_time = nrfy_grtc_sys_counter_cc_get(NRF_GRTC, chan); + result = nrfx_grtc_syscounter_cc_value_read(chan, &capt_time); + if (result != NRFX_SUCCESS) { + return -EPERM; + } __ASSERT_NO_MSG(capt_time < COUNTER_SPAN); @@ -412,16 +373,23 @@ int z_nrf_grtc_wakeup_prepare(uint64_t wake_time_us) nrfx_err_t err_code; static uint8_t systemoff_channel; uint64_t now = counter(); + nrfx_grtc_sleep_config_t sleep_cfg; /* Minimum time that ensures valid execution of system-off procedure. */ - uint32_t minimum_latency_us = nrfy_grtc_waketime_get(NRF_GRTC) + - nrfy_grtc_timeout_get(NRF_GRTC) + - CONFIG_NRF_GRTC_SLEEP_MINIMUM_LATENCY; + uint32_t minimum_latency_us; uint32_t chan; int ret; + nrfx_grtc_sleep_configuration_get(&sleep_cfg); + minimum_latency_us = (sleep_cfg.waketime + sleep_cfg.timeout) * + USEC_PER_SEC / LFCLK_FREQUENCY_HZ + + CONFIG_NRF_GRTC_SYSCOUNTER_SLEEP_MINIMUM_LATENCY; + sleep_cfg.auto_mode = false; + nrfx_grtc_sleep_configure(&sleep_cfg); + if (minimum_latency_us > wake_time_us) { return -EINVAL; } + k_spinlock_key_t key = k_spin_lock(&lock); err_code = nrfx_grtc_channel_alloc(&systemoff_channel); @@ -430,7 +398,9 @@ int z_nrf_grtc_wakeup_prepare(uint64_t wake_time_us) return -ENOMEM; } (void)nrfx_grtc_syscounter_cc_int_disable(systemoff_channel); - ret = compare_set(systemoff_channel, now + wake_time_us, NULL, NULL); + ret = compare_set(systemoff_channel, + now + wake_time_us * sys_clock_hw_cycles_per_sec() / USEC_PER_SEC, NULL, + NULL); if (ret < 0) { k_spin_unlock(&lock, key); return ret; @@ -446,7 +416,7 @@ int z_nrf_grtc_wakeup_prepare(uint64_t wake_time_us) } /* Make sure that wake_time_us was not triggered yet. */ - if (nrfy_grtc_sys_counter_compare_event_check(NRF_GRTC, systemoff_channel)) { + if (nrfx_grtc_syscounter_compare_event_check(systemoff_channel)) { k_spin_unlock(&lock, key); return -EINVAL; } @@ -457,7 +427,7 @@ int z_nrf_grtc_wakeup_prepare(uint64_t wake_time_us) MAX_CC_LATCH_WAIT_TIME_US; k_busy_wait(wait_time); #if NRF_GRTC_HAS_CLKSEL - nrfy_grtc_clksel_set(NRF_GRTC, NRF_GRTC_CLKSEL_LFXO); + nrfx_grtc_clock_source_set(NRF_GRTC_CLKSEL_LFXO); #endif k_spin_unlock(&lock, key); return 0; @@ -498,16 +468,9 @@ static int sys_clock_driver_init(void) #if defined(CONFIG_NRF_GRTC_TIMER_CLOCK_MANAGEMENT) && \ (defined(NRF_GRTC_HAS_CLKSEL) && (NRF_GRTC_HAS_CLKSEL == 1)) /* Use System LFCLK as the low-frequency clock source. */ - nrfy_grtc_clksel_set(NRF_GRTC, NRF_GRTC_CLKSEL_LFCLK); + nrfx_grtc_clock_source_set(NRF_GRTC_CLKSEL_LFCLK); #endif -#if defined(CONFIG_NRF_GRTC_START_SYSCOUNTER) - /* SYSCOUNTER needs to be turned off before initialization. */ - nrfy_grtc_sys_counter_set(NRF_GRTC, false); - nrfy_grtc_timeout_set(NRF_GRTC, TIMEOUT); - nrfy_grtc_waketime_set(NRF_GRTC, WAKETIME); -#endif /* CONFIG_NRF_GRTC_START_SYSCOUNTER */ - IRQ_CONNECT(DT_IRQN(GRTC_NODE), DT_IRQ(GRTC_NODE, priority), nrfx_isr, nrfx_grtc_irq_handler, 0); @@ -521,9 +484,6 @@ static int sys_clock_driver_init(void) if (err_code != NRFX_SUCCESS) { return err_code == NRFX_ERROR_NO_MEM ? -ENOMEM : -EPERM; } - if (IS_ENABLED(CONFIG_NRF_GRTC_SLEEP_ALLOWED)) { - nrfy_grtc_sys_counter_auto_mode_set(NRF_GRTC, false); - } #else err_code = nrfx_grtc_channel_alloc(&system_clock_channel_data.channel); if (err_code != NRFX_SUCCESS) { @@ -531,10 +491,6 @@ static int sys_clock_driver_init(void) } #endif /* CONFIG_NRF_GRTC_START_SYSCOUNTER */ - if (!IS_ENABLED(CONFIG_NRF_GRTC_SLEEP_ALLOWED)) { - grtc_active_set(); - } - int_mask = NRFX_GRTC_CONFIG_ALLOWED_CC_CHANNELS_MASK; if (!IS_ENABLED(CONFIG_TICKLESS_KERNEL)) { system_timeout_set_relative(CYC_PER_TICK); diff --git a/include/zephyr/drivers/timer/nrf_grtc_timer.h b/include/zephyr/drivers/timer/nrf_grtc_timer.h index 4cd3f8d14cb2e..f8b69d7ddf021 100644 --- a/include/zephyr/drivers/timer/nrf_grtc_timer.h +++ b/include/zephyr/drivers/timer/nrf_grtc_timer.h @@ -171,6 +171,7 @@ int z_nrf_grtc_timer_capture_prepare(int32_t chan); * * @retval 0 if the timestamp was successfully caught and read. * @retval -EBUSY if capturing has not been triggered. + * @retval -EPERM if either channel is unavailable or SYSCOUNTER is not running. */ int z_nrf_grtc_timer_capture_read(int32_t chan, uint64_t *captured_time); diff --git a/modules/hal_nordic/nrfx/CMakeLists.txt b/modules/hal_nordic/nrfx/CMakeLists.txt index e46e458ccab84..5ad29dddc4632 100644 --- a/modules/hal_nordic/nrfx/CMakeLists.txt +++ b/modules/hal_nordic/nrfx/CMakeLists.txt @@ -131,10 +131,6 @@ if(CONFIG_NRFX_TWI OR CONFIG_NRFX_TWIM) zephyr_library_sources(${SRC_DIR}/nrfx_twi_twim.c) endif() -if (CONFIG_NRF_GRTC_TIMER AND CONFIG_NRF_GRTC_TIMER_CLOCK_MANAGEMENT) - zephyr_compile_definitions(NRF_GRTC_HAS_EXTENDED=1) -endif() - # Inject HAL "CONFIG_NFCT_PINS_AS_GPIOS" definition if user requests to # configure the NFCT pins as GPIOS. Do the same with "CONFIG_GPIO_AS_PINRESET" # to configure the reset GPIO as nRESET. This way, the HAL will take care of diff --git a/modules/hal_nordic/nrfx/nrfx_config.h b/modules/hal_nordic/nrfx/nrfx_config.h index 397d7b2a32093..a0f2f481bc37e 100644 --- a/modules/hal_nordic/nrfx/nrfx_config.h +++ b/modules/hal_nordic/nrfx/nrfx_config.h @@ -120,6 +120,19 @@ #define NRFX_GRTC_CONFIG_LOG_ENABLED 1 #endif +#ifdef CONFIG_NRF_GRTC_TIMER_CLOCK_MANAGEMENT +#define NRF_GRTC_HAS_EXTENDED 1 +#endif +#ifdef CONFIG_NRF_GRTC_SLEEP_ALLOWED +#define NRFX_GRTC_CONFIG_SLEEP_ALLOWED 1 +#endif +#ifdef CONFIG_NRF_GRTC_TIMER_AUTO_KEEP_ALIVE +#define NRFX_GRTC_CONFIG_AUTOEN 1 +#endif +#ifdef CONFIG_NRF_GRTC_START_SYSCOUNTER +#define NRFX_GRTC_CONFIG_AUTOSTART 1 +#endif + #ifdef CONFIG_NRFX_GPIOTE #define NRFX_GPIOTE_ENABLED 1 #endif From 2cd2d5fef317554d5375e93b141baa557f5b1094 Mon Sep 17 00:00:00 2001 From: Adam Kondraciuk Date: Thu, 1 Feb 2024 09:46:02 +0100 Subject: [PATCH 1274/2849] tests: drivers: timer: grtc: Fix GRTC test The `z_nrf_grtc_timer_get_ticks()` function converts system ticks to GRTC ticks. It gets the current system tick to calculate an absolute GRTC value. The same does the test function to provide an argument to be converted. If the system tick occurs between those `sys_clock_tick_get()` calls the `z_nrf_grtc_timer_get_ticks()` will take into account the newer tick while the test estimate bases on the old tick value. Due to that the maximum result error is 1 system tick minus 1 GRTC tick which equals (`CYC_PER_TICK` - 1) for GRTC ticks. Signed-off-by: Adam Kondraciuk --- drivers/timer/Kconfig.nrf_grtc | 2 +- tests/drivers/timer/nrf_grtc_timer/src/main.c | 41 ++++++++++++------- .../timer/nrf_grtc_timer/testcase.yaml | 1 + 3 files changed, 28 insertions(+), 16 deletions(-) diff --git a/drivers/timer/Kconfig.nrf_grtc b/drivers/timer/Kconfig.nrf_grtc index cda39ae8b1c2b..b136f65425236 100644 --- a/drivers/timer/Kconfig.nrf_grtc +++ b/drivers/timer/Kconfig.nrf_grtc @@ -54,7 +54,7 @@ config NRF_GRTC_TIMER_AUTO_KEEP_ALIVE bool default y if NRF_GRTC_START_SYSCOUNTER help - This feature prevents the SYSCOUNTER to sleep when any core is in + This feature prevents the SYSCOUNTER from sleeping when any core is in active state. endif # NRF_GRTC_TIMER diff --git a/tests/drivers/timer/nrf_grtc_timer/src/main.c b/tests/drivers/timer/nrf_grtc_timer/src/main.c index 197270cc6a40b..f8d33d8c53ac3 100644 --- a/tests/drivers/timer/nrf_grtc_timer/src/main.c +++ b/tests/drivers/timer/nrf_grtc_timer/src/main.c @@ -8,12 +8,15 @@ #include #define GRTC_SLEW_TICKS 10 +#define NUMBER_OF_TRIES 2000 +#define CYC_PER_TICK \ + ((uint64_t)sys_clock_hw_cycles_per_sec() / (uint64_t)CONFIG_SYS_CLOCK_TICKS_PER_SEC) ZTEST(nrf_grtc_timer, test_get_ticks) { k_timeout_t t = K_MSEC(1); - uint64_t exp_ticks = z_nrf_grtc_timer_read() + t.ticks; + uint64_t exp_ticks = z_nrf_grtc_timer_read() + t.ticks * CYC_PER_TICK; int64_t ticks; /* Relative 1ms from now timeout converted to GRTC */ @@ -21,20 +24,28 @@ ZTEST(nrf_grtc_timer, test_get_ticks) zassert_true((ticks >= exp_ticks) && (ticks <= (exp_ticks + GRTC_SLEW_TICKS)), "Unexpected result %" PRId64 " (expected: %" PRId64 ")", ticks, exp_ticks); - /* Absolute timeout 1ms in the past */ - t = Z_TIMEOUT_TICKS(Z_TICK_ABS(sys_clock_tick_get() - K_MSEC(1).ticks)); - - exp_ticks = z_nrf_grtc_timer_read() - K_MSEC(1).ticks; - ticks = z_nrf_grtc_timer_get_ticks(t); - zassert_true((ticks >= exp_ticks) && (ticks <= (exp_ticks + GRTC_SLEW_TICKS)), - "Unexpected result %" PRId64 " (expected: %" PRId64 ")", ticks, exp_ticks); - - /* Absolute timeout 10ms in the future */ - t = Z_TIMEOUT_TICKS(Z_TICK_ABS(sys_clock_tick_get() + K_MSEC(10).ticks)); - exp_ticks = z_nrf_grtc_timer_read() + K_MSEC(10).ticks; - ticks = z_nrf_grtc_timer_get_ticks(t); - zassert_true((ticks >= exp_ticks) && (ticks <= (exp_ticks + GRTC_SLEW_TICKS)), - "Unexpected result %" PRId64 " (expected: %" PRId64 ")", ticks, exp_ticks); + k_msleep(1); + + for (uint32_t i = 0; i < NUMBER_OF_TRIES; i++) { + /* Absolute timeout 1ms in the past */ + t = Z_TIMEOUT_TICKS(Z_TICK_ABS(sys_clock_tick_get() - K_MSEC(1).ticks)); + + exp_ticks = z_nrf_grtc_timer_read() - K_MSEC(1).ticks * CYC_PER_TICK; + ticks = z_nrf_grtc_timer_get_ticks(t); + zassert_true((ticks >= (exp_ticks - CYC_PER_TICK + 1)) && + (ticks <= (exp_ticks + GRTC_SLEW_TICKS)), + "Unexpected result %" PRId64 " (expected: %" PRId64 ")", ticks, + exp_ticks); + + /* Absolute timeout 10ms in the future */ + t = Z_TIMEOUT_TICKS(Z_TICK_ABS(sys_clock_tick_get() + K_MSEC(10).ticks)); + exp_ticks = z_nrf_grtc_timer_read() + K_MSEC(10).ticks * CYC_PER_TICK; + ticks = z_nrf_grtc_timer_get_ticks(t); + zassert_true((ticks >= (exp_ticks - CYC_PER_TICK + 1)) && + (ticks <= (exp_ticks + GRTC_SLEW_TICKS)), + "Unexpected result %" PRId64 " (expected: %" PRId64 ")", ticks, + exp_ticks); + } } ZTEST_SUITE(nrf_grtc_timer, NULL, NULL, NULL, NULL, NULL); diff --git a/tests/drivers/timer/nrf_grtc_timer/testcase.yaml b/tests/drivers/timer/nrf_grtc_timer/testcase.yaml index e81a37cbd2a81..3b93b1570125a 100644 --- a/tests/drivers/timer/nrf_grtc_timer/testcase.yaml +++ b/tests/drivers/timer/nrf_grtc_timer/testcase.yaml @@ -4,5 +4,6 @@ tests: platform_allow: - nrf54l15pdk/nrf54l15/cpuapp - nrf54l15pdk/nrf54l15/cpuflpr + - nrf54l15bsim/nrf54l15/cpuapp - nrf54h20dk/nrf54h20/cpuapp - nrf54h20dk/nrf54h20/cpurad From 4049e17c625c34511c9b497ac8d2ed570506cbd8 Mon Sep 17 00:00:00 2001 From: Seppo Takalo Date: Wed, 22 May 2024 15:56:44 +0300 Subject: [PATCH 1275/2849] net: lwm2m: Fix null dereference when post-write cb is set When opaque resources have post-write callback set, but the write is not a Block-Wise write, there is no block_ctx and the code causes null pointer dereference when calculating the offset of the data. Signed-off-by: Seppo Takalo --- subsys/net/lib/lwm2m/lwm2m_message_handling.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/subsys/net/lib/lwm2m/lwm2m_message_handling.c b/subsys/net/lib/lwm2m/lwm2m_message_handling.c index f7e79dc40aa7a..41165ef406383 100644 --- a/subsys/net/lib/lwm2m/lwm2m_message_handling.c +++ b/subsys/net/lib/lwm2m/lwm2m_message_handling.c @@ -996,10 +996,10 @@ static int lwm2m_write_handler_opaque(struct lwm2m_engine_obj_inst *obj_inst, #endif /* CONFIG_LWM2M_ENGINE_VALIDATION_BUFFER_SIZE > 0 */ 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, - msg->in.block_ctx->ctx.current); + 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, + (msg->in.block_ctx ? msg->in.block_ctx->ctx.current : 0)); if (ret < 0) { return ret; } From 89489d6e2d36c2b711610d1156accb445c081927 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20G=C5=82=C4=85b?= Date: Tue, 28 May 2024 13:17:00 +0200 Subject: [PATCH 1276/2849] tests: drivers: counter: counter_nrf_rtc: Run test on nrf54h20 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add nrf54h20dk to platform allow list. Overlay for tht target was already added. Signed-off-by: Sebastian Głąb --- tests/drivers/counter/counter_nrf_rtc/fixed_top/testcase.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/drivers/counter/counter_nrf_rtc/fixed_top/testcase.yaml b/tests/drivers/counter/counter_nrf_rtc/fixed_top/testcase.yaml index 2905fe55a1c23..2260957e2c05c 100644 --- a/tests/drivers/counter/counter_nrf_rtc/fixed_top/testcase.yaml +++ b/tests/drivers/counter/counter_nrf_rtc/fixed_top/testcase.yaml @@ -7,3 +7,5 @@ tests: platform_allow: - nrf52840dk/nrf52840 - nrf52_bsim + - nrf54h20dk/nrf54h20/cpuapp + - nrf54h20dk/nrf54h20/cpurad From d8fe0514f8eb5001da0bbda1bfd457b37ad8e621 Mon Sep 17 00:00:00 2001 From: Ethan Duckett Date: Fri, 24 May 2024 10:19:23 +0100 Subject: [PATCH 1277/2849] drivers: adc: ltc2451: Add ltc2451 default conversion speed Adds default conversion speed as it isn't a required property Signed-off-by: Ethan Duckett --- dts/bindings/adc/lltc,ltc2451.yaml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/dts/bindings/adc/lltc,ltc2451.yaml b/dts/bindings/adc/lltc,ltc2451.yaml index b68f127337f7b..a3707e2c54903 100644 --- a/dts/bindings/adc/lltc,ltc2451.yaml +++ b/dts/bindings/adc/lltc,ltc2451.yaml @@ -10,7 +10,11 @@ include: i2c-device.yaml properties: conversion-speed: type: int + default: 60 enum: - 30 - 60 - description: Set conversion speed in Hz + description: | + Set conversion speed in Hz + Default value corresponds to the default value of the register + To specify channel 2 and 4 = 0b001010 = 10 From aa2b83d4ab9f15d83d0d4897d0176c585d94ecde Mon Sep 17 00:00:00 2001 From: Chris Friedt Date: Thu, 23 May 2024 10:42:06 -0400 Subject: [PATCH 1278/2849] clang-format: add array-for-each to correct formatting issues The ARRAY_FOR_EACH() and ARRAY_FOR_EACH_PTR() macros were not formatting correctly in vs code (and I would guess other editors). Add an entry to .clang-format so that the opening brace is on the same line as the macro. Signed-off-by: Chris Friedt --- .clang-format | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.clang-format b/.clang-format index 150127471485c..8dc1f55d57581 100644 --- a/.clang-format +++ b/.clang-format @@ -32,6 +32,8 @@ ColumnLimit: 100 ConstructorInitializerIndentWidth: 8 ContinuationIndentWidth: 8 ForEachMacros: + - 'ARRAY_FOR_EACH' + - 'ARRAY_FOR_EACH_PTR' - 'FOR_EACH' - 'FOR_EACH_FIXED_ARG' - 'FOR_EACH_IDX' From 8e026ba19e9a4706dfb269ccc8bfee1e50b26229 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 8 May 2024 17:21:19 -0700 Subject: [PATCH 1279/2849] docs: modbus: Change pymodbus unit= parameter to slave= The PyModbus project changed the `unit=` parameter to `slave=` in the v3.3.0 release. See https://pymodbus.readthedocs.io/en/latest/source/api_changes.html#api-changes-3-3-0 Signed-off-by: Chris Wilson --- samples/subsys/modbus/rtu_server/README.rst | 12 ++++++------ samples/subsys/modbus/tcp_gateway/README.rst | 12 ++++++------ samples/subsys/modbus/tcp_server/README.rst | 12 ++++++------ 3 files changed, 18 insertions(+), 18 deletions(-) diff --git a/samples/subsys/modbus/rtu_server/README.rst b/samples/subsys/modbus/rtu_server/README.rst index aae880b78659f..b269f563d2880 100644 --- a/samples/subsys/modbus/rtu_server/README.rst +++ b/samples/subsys/modbus/rtu_server/README.rst @@ -85,7 +85,7 @@ For example, to set LED0 on use FC01 command (write_coil). .. code-block:: console - > client.write_coil address=0 value=1 unit=1 + > client.write_coil address=0 value=1 slave=1 Client should confirm successful communication and LED0 should light. @@ -100,13 +100,13 @@ To set LED0 off but LED1 and LED2 on use FC15 command (write_coils). .. code-block:: console - > client.write_coils address=0 values=0,1,1 unit=1 + > client.write_coils address=0 values=0,1,1 slave=1 To read LED0, LED1, LED2 state FC05 command (read_coils) can be used. .. code-block:: console - > client.read_coils address=0 count=3 unit=1 + > client.read_coils address=0 count=3 slave=1 { "bits": [ false, @@ -128,19 +128,19 @@ To write single holding registers use FC06 command (write_register), .. code-block:: console - > client.write_register address=0 value=42 unit=1 + > client.write_register address=0 value=42 slave=1 or FC16 command (write_registers). .. code-block:: console - > client.write_registers address=0 values=42,42,42 unit=1 + > client.write_registers address=0 values=42,42,42 slave=1 To read holding registers use FC03 command (read_holding_registers). .. code-block:: console - > client.read_holding_registers address=0 count=3 unit=1 + > client.read_holding_registers address=0 count=3 slave=1 { "registers": [ 42, diff --git a/samples/subsys/modbus/tcp_gateway/README.rst b/samples/subsys/modbus/tcp_gateway/README.rst index 5fbc02b41ef2f..7780143efb007 100644 --- a/samples/subsys/modbus/tcp_gateway/README.rst +++ b/samples/subsys/modbus/tcp_gateway/README.rst @@ -54,7 +54,7 @@ For example, to set LED0 on use FC01 command (write_coil). .. code-block:: console > client.connect - > client.write_coil address=0 value=1 unit=1 + > client.write_coil address=0 value=1 slave=1 Client should confirm successful communication and LED0 should light. @@ -69,13 +69,13 @@ To set LED0 off but LED1 and LED2 on use FC15 command (write_coils). .. code-block:: console - > client.write_coils address=0 values=0,1,1 unit=1 + > client.write_coils address=0 values=0,1,1 slave=1 To read LED0, LED1, LED2 state FC05 command (read_coils) can be used. .. code-block:: console - > client.read_coils address=0 count=3 unit=1 + > client.read_coils address=0 count=3 slave=1 { "bits": [ false, @@ -97,19 +97,19 @@ To write single holding registers use FC06 command (write_register), .. code-block:: console - > client.write_register address=0 value=42 unit=1 + > client.write_register address=0 value=42 slave=1 or FC16 command (write_registers). .. code-block:: console - > client.write_registers address=0 values=42,42,42 unit=1 + > client.write_registers address=0 values=42,42,42 slave=1 To read holding registers use FC03 command (read_holding_registers). .. code-block:: console - > client.read_holding_registers address=0 count=3 unit=1 + > client.read_holding_registers address=0 count=3 slave=1 { "registers": [ 42, diff --git a/samples/subsys/modbus/tcp_server/README.rst b/samples/subsys/modbus/tcp_server/README.rst index 1b3f777db45e3..d7410e99c4e78 100644 --- a/samples/subsys/modbus/tcp_server/README.rst +++ b/samples/subsys/modbus/tcp_server/README.rst @@ -50,7 +50,7 @@ For example, to set LED0 on use FC01 command (write_coil). .. code-block:: console > client.connect - > client.write_coil address=0 value=1 unit=1 + > client.write_coil address=0 value=1 slave=1 Client should confirm successful communication and LED0 should light. @@ -65,13 +65,13 @@ To set LED0 off but LED1 and LED2 on use FC15 command (write_coils). .. code-block:: console - > client.write_coils address=0 values=0,1,1 unit=1 + > client.write_coils address=0 values=0,1,1 slave=1 To read LED0, LED1, LED2 state FC05 command (read_coils) can be used. .. code-block:: console - > client.read_coils address=0 count=3 unit=1 + > client.read_coils address=0 count=3 slave=1 { "bits": [ false, @@ -93,19 +93,19 @@ To write single holding registers use FC06 command (write_register), .. code-block:: console - > client.write_register address=0 value=42 unit=1 + > client.write_register address=0 value=42 slave=1 or FC16 command (write_registers). .. code-block:: console - > client.write_registers address=0 values=42,42,42 unit=1 + > client.write_registers address=0 values=42,42,42 slave=1 To read holding registers use FC03 command (read_holding_registers). .. code-block:: console - > client.read_holding_registers address=0 count=3 unit=1 + > client.read_holding_registers address=0 count=3 slave=1 { "registers": [ 42, From b8131b7567c7fa4df48e3b5e6ac03a34764b665b Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 8 May 2024 17:25:36 -0700 Subject: [PATCH 1280/2849] docs: modbus: Update PyModbus GitHub project URL The PyModbus project changed the GitHub project URL from: https://github.com/riptideio/pymodbus to: https://github.com/pymodbus-dev/pymodbus Signed-off-by: Chris Wilson --- samples/subsys/modbus/rtu_server/README.rst | 2 +- samples/subsys/modbus/tcp_gateway/README.rst | 2 +- samples/subsys/modbus/tcp_server/README.rst | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/samples/subsys/modbus/rtu_server/README.rst b/samples/subsys/modbus/rtu_server/README.rst index b269f563d2880..38604bd1f7a56 100644 --- a/samples/subsys/modbus/rtu_server/README.rst +++ b/samples/subsys/modbus/rtu_server/README.rst @@ -150,4 +150,4 @@ To read holding registers use FC03 command (read_holding_registers). } .. _`joy-it RS-485 shield for Arduino`: https://joy-it.net/en/products/ARD-RS485 -.. _`PyModbus`: https://github.com/riptideio/pymodbus +.. _`PyModbus`: https://github.com/pymodbus-dev/pymodbus diff --git a/samples/subsys/modbus/tcp_gateway/README.rst b/samples/subsys/modbus/tcp_gateway/README.rst index 7780143efb007..483c2311fea5b 100644 --- a/samples/subsys/modbus/tcp_gateway/README.rst +++ b/samples/subsys/modbus/tcp_gateway/README.rst @@ -118,4 +118,4 @@ To read holding registers use FC03 command (read_holding_registers). ] } -.. _`PyModbus`: https://github.com/riptideio/pymodbus +.. _`PyModbus`: https://github.com/pymodbus-dev/pymodbus diff --git a/samples/subsys/modbus/tcp_server/README.rst b/samples/subsys/modbus/tcp_server/README.rst index d7410e99c4e78..14e1817f175ef 100644 --- a/samples/subsys/modbus/tcp_server/README.rst +++ b/samples/subsys/modbus/tcp_server/README.rst @@ -114,4 +114,4 @@ To read holding registers use FC03 command (read_holding_registers). ] } -.. _`PyModbus`: https://github.com/riptideio/pymodbus +.. _`PyModbus`: https://github.com/pymodbus-dev/pymodbus From 1c968a4a8f6a39e324492d0d0bd54f0451377627 Mon Sep 17 00:00:00 2001 From: Alexander Kozhinov Date: Sun, 5 May 2024 22:56:52 +0200 Subject: [PATCH 1281/2849] drivers: usb: device: fix cbprintf_package warning cbprintf_package complains about char usage for %p string argument and suggests void * usage. Signed-off-by: Alexander Kozhinov --- drivers/usb/device/usb_dc_rpi_pico.c | 2 +- drivers/usb/device/usb_dc_stm32.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/usb/device/usb_dc_rpi_pico.c b/drivers/usb/device/usb_dc_rpi_pico.c index bb99fa365b285..c6623727c1e2a 100644 --- a/drivers/usb/device/usb_dc_rpi_pico.c +++ b/drivers/usb/device/usb_dc_rpi_pico.c @@ -787,7 +787,7 @@ int usb_dc_ep_read_wait(uint8_t ep, uint8_t *data, } LOG_DBG("ep 0x%02x, %u bytes, %u+%u, %p", ep, max_data_len, ep_state->read_offset, - read_count, data); + read_count, (void *)data); if (data) { read_count = MIN(read_count, max_data_len); diff --git a/drivers/usb/device/usb_dc_stm32.c b/drivers/usb/device/usb_dc_stm32.c index fbc7ff07e71cf..dbfd359f10bbc 100644 --- a/drivers/usb/device/usb_dc_stm32.c +++ b/drivers/usb/device/usb_dc_stm32.c @@ -883,7 +883,7 @@ int usb_dc_ep_read_wait(uint8_t ep, uint8_t *data, uint32_t max_data_len, read_count = ep_state->read_count; LOG_DBG("ep 0x%02x, %u bytes, %u+%u, %p", ep, max_data_len, - ep_state->read_offset, read_count, data); + ep_state->read_offset, read_count, (void *)data); if (!USB_EP_DIR_IS_OUT(ep)) { /* check if OUT ep */ LOG_ERR("Wrong endpoint direction: 0x%02x", ep); From bf77d74e918967e6fc05aea370c11d50069878cc Mon Sep 17 00:00:00 2001 From: Alexander Kozhinov Date: Sun, 5 May 2024 23:08:13 +0200 Subject: [PATCH 1282/2849] usb: device: usb_descriptor.c fix cbprintf_package warning. cbprintf_package complains about char usage for %p string argument and suggests void * usage. Signed-off-by: Alexander Kozhinov --- subsys/usb/device/usb_descriptor.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subsys/usb/device/usb_descriptor.c b/subsys/usb/device/usb_descriptor.c index 325989dc7fdee..f11e39fde848d 100644 --- a/subsys/usb/device/usb_descriptor.c +++ b/subsys/usb/device/usb_descriptor.c @@ -169,7 +169,7 @@ static void ascii7_to_utf16le(void *descriptor) uint8_t *buf = (uint8_t *)&str_descr->bString; LOG_DBG("idx_max %d, ascii_idx_max %d, buf %p", - idx_max, ascii_idx_max, buf); + idx_max, ascii_idx_max, (void *)buf); for (int i = idx_max; i >= 0; i -= 2) { LOG_DBG("char %c : %x, idx %d -> %d", From 225e28bf3527eb6b0aeb47e32ce064789eecaf19 Mon Sep 17 00:00:00 2001 From: Xavier Ruppen Date: Mon, 29 Apr 2024 15:23:23 +0200 Subject: [PATCH 1283/2849] drivers: ethernet: enc28j60: ESTAT TXABRT bit should be cleared on error If the TXABRT bit from ESTAT is ever set (because of a single failed transmission), the driver will continue showing an error on every subsequent packet sent, although it is correctly sent: eth_enc28j60: TX failed! The enc28j60 datasheet says under "12.1.3 TRANSMIT ERROR INTERRUPT FLAG (TXERIF)": "After determining the problem and solution, the host controller should clear the LATECOL (if set) and TXABRT bits so that future aborts can be detected accurately." Therefore, clear the TXABRT and LATECOL bits in case of transmission error. Signed-off-by: Xavier Ruppen --- drivers/ethernet/eth_enc28j60.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/drivers/ethernet/eth_enc28j60.c b/drivers/ethernet/eth_enc28j60.c index 979910f759aaf..7444c79e40100 100644 --- a/drivers/ethernet/eth_enc28j60.c +++ b/drivers/ethernet/eth_enc28j60.c @@ -527,6 +527,18 @@ static int eth_enc28j60_tx(const struct device *dev, struct net_pkt *pkt) if (tx_end & ENC28J60_BIT_ESTAT_TXABRT) { LOG_ERR("%s: TX failed!", dev->name); + + /* 12.1.3 "TRANSMIT ERROR INTERRUPT FLAG (TXERIF)" states: + * + * "After determining the problem and solution, the + * host controller should clear the LATECOL (if set) and + * TXABRT bits so that future aborts can be detected + * accurately." + */ + eth_enc28j60_clear_eth_reg(dev, ENC28J60_REG_ESTAT, + ENC28J60_BIT_ESTAT_TXABRT + | ENC28J60_BIT_ESTAT_LATECOL); + return -EIO; } From 20983c7ced08b1ea4e009794b9954db5a495b073 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mo=C5=84?= Date: Mon, 29 Apr 2024 10:37:58 +0200 Subject: [PATCH 1284/2849] usb: device_next: uac2: Fix integer handling issues MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix integer handling issues found out by Coverity Scan. Coverity-CID: 363729 Coverity-CID: 363737 Signed-off-by: Tomasz Moń --- subsys/usb/device_next/class/usbd_uac2.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/subsys/usb/device_next/class/usbd_uac2.c b/subsys/usb/device_next/class/usbd_uac2.c index f69da75e3362e..46a28951a8abc 100644 --- a/subsys/usb/device_next/class/usbd_uac2.c +++ b/subsys/usb/device_next/class/usbd_uac2.c @@ -123,7 +123,8 @@ get_as_data_ep(struct usbd_class_data *const c_data, int as_idx) const struct uac2_cfg *cfg = dev->config; const struct usb_desc_header *desc = NULL; - if ((as_idx < cfg->num_ifaces) && cfg->ep_indexes[as_idx]) { + if ((as_idx >= 0) && (as_idx < cfg->num_ifaces) && + cfg->ep_indexes[as_idx]) { desc = cfg->descriptors[cfg->ep_indexes[as_idx]]; } @@ -344,6 +345,8 @@ static void write_explicit_feedback(struct usbd_class_data *const c_data, int as_idx = terminal_to_as_interface(dev, terminal); int ret; + __ASSERT_NO_MSG(as_idx >= 0); + buf = net_buf_alloc(&uac2_pool, K_NO_WAIT); if (!buf) { LOG_ERR("No buf for feedback"); From d034106b4035f26002c938f33ed59f6802ff235b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mo=C5=84?= Date: Mon, 13 Nov 2023 10:27:59 +0100 Subject: [PATCH 1285/2849] usb: device: cdc_acm: Warn once about full ring buffer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Generating separate log entry at INFO level for every single character dropped is excessive and leads to log flood. Logging dropped character in no way helps end user and is really a delayed performance killer that triggers when CDC ACM buffer gets full. If user does not want to lose outgoing characters then the solution is to enable hardware flow control which properly blocks in the case the output buffer is full. Signed-off-by: Tomasz Moń --- subsys/usb/device/class/cdc_acm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subsys/usb/device/class/cdc_acm.c b/subsys/usb/device/class/cdc_acm.c index 80e9b5610593a..d3148fba48f7e 100644 --- a/subsys/usb/device/class/cdc_acm.c +++ b/subsys/usb/device/class/cdc_acm.c @@ -1033,7 +1033,7 @@ static void cdc_acm_poll_out(const struct device *dev, unsigned char c) while (!ring_buf_put(dev_data->tx_ringbuf, &c, 1)) { if (k_is_in_isr() || !dev_data->flow_ctrl) { - LOG_INF("Ring buffer full, discard %c", c); + LOG_WRN_ONCE("Ring buffer full, discard data"); break; } From bbe5e1e6ebf4a1a66c023d834fbdfca22a98ee7d Mon Sep 17 00:00:00 2001 From: Yong Cong Sin Date: Wed, 24 Jan 2024 17:35:04 +0800 Subject: [PATCH 1286/2849] build: namespace the generated headers with `zephyr/` Namespaced the generated headers with `zephyr` to prevent potential conflict with other headers. Introduce a temporary Kconfig `LEGACY_GENERATED_INCLUDE_PATH` that is enabled by default. This allows the developers to continue the use of the old include paths for the time being until it is deprecated and eventually removed. The Kconfig will generate a build-time warning message, similar to the `CONFIG_TIMER_RANDOM_GENERATOR`. Updated the includes path of in-tree sources accordingly. Most of the changes here are scripted, check the PR for more info. Signed-off-by: Yong Cong Sin --- CMakeLists.txt | 58 +++++++++++----- Kconfig.zephyr | 17 +++++ arch/arc/include/offsets_short_arch.h | 2 +- arch/arm/include/offsets_short_arch.h | 2 +- arch/arm64/core/reset.S | 2 +- arch/arm64/core/vector_table.S | 2 +- arch/arm64/include/offsets_short_arch.h | 2 +- arch/mips/include/offsets_short_arch.h | 2 +- arch/nios2/include/offsets_short_arch.h | 2 +- arch/posix/include/offsets_short_arch.h | 2 +- arch/riscv/core/fatal.c | 2 +- arch/riscv/core/fpu.S | 2 +- arch/riscv/core/reset.S | 2 +- arch/riscv/include/offsets_short_arch.h | 2 +- arch/sparc/include/offsets_short_arch.h | 2 +- arch/x86/include/ia32/offsets_short_arch.h | 2 +- arch/x86/include/intel64/offsets_short_arch.h | 2 +- arch/xtensa/core/CMakeLists.txt | 4 +- arch/xtensa/core/coredump.c | 2 +- arch/xtensa/core/debug_helpers_asm.S | 2 +- arch/xtensa/core/fatal.c | 2 +- arch/xtensa/core/irq_offload.c | 2 +- arch/xtensa/core/userspace.S | 4 +- arch/xtensa/core/vector_handlers.c | 4 +- arch/xtensa/core/window_vectors.S | 2 +- arch/xtensa/core/xtensa_asm2_util.S | 4 +- arch/xtensa/core/xtensa_hifi.S | 2 +- arch/xtensa/include/kernel_arch_func.h | 2 +- arch/xtensa/include/xtensa_asm2_s.h | 4 +- boards/qemu/x86/qemu_x86_tiny.ld | 2 +- .../eclipse_cdt4_generator_amendment.cmake | 10 +-- cmake/kobj.cmake | 5 +- .../modules/generated_file_directories.cmake | 4 +- cmake/modules/kconfig.cmake | 3 +- cmake/modules/unittest.cmake | 2 +- doc/build/cmake/index.rst | 2 +- doc/build/dts/howtos.rst | 2 +- doc/build/dts/intro-input-output.rst | 2 +- doc/build/dts/troubleshooting.rst | 2 +- doc/build/dts/zephyr_dt_inputs_outputs.svg | 2 +- doc/kernel/drivers/index.rst | 4 +- doc/kernel/usermode/syscalls.rst | 8 +-- doc/services/retention/blinfo.rst | 2 +- drivers/adc/adc_handlers.c | 6 +- drivers/auxdisplay/auxdisplay_handlers.c | 38 +++++------ drivers/bbram/bbram_handlers.c | 12 ++-- drivers/cache/cache_handlers.c | 6 +- drivers/can/can_handlers.c | 66 +++++++++---------- drivers/charger/charger_handlers.c | 6 +- drivers/console/uart_mux.c | 2 +- drivers/counter/counter_handlers.c | 32 ++++----- drivers/counter/maxim_ds3231.c | 4 +- drivers/dac/dac_handlers.c | 4 +- drivers/dma/dma_handlers.c | 4 +- drivers/eeprom/eeprom_handlers.c | 6 +- drivers/entropy/entropy_handlers.c | 2 +- drivers/espi/espi_handlers.c | 26 ++++---- drivers/flash/flash_handlers.c | 22 +++---- drivers/flash/flash_simulator.c | 2 +- drivers/flash/nrf_qspi_nor.c | 2 +- drivers/fpga/fpga_shell.c | 2 +- .../emul_fuel_gauge_syscall_handlers.c | 4 +- .../fuel_gauge/fuel_gauge_syscall_handlers.c | 12 ++-- drivers/gpio/gpio_handlers.c | 20 +++--- drivers/hwinfo/hwinfo_handlers.c | 10 +-- drivers/hwspinlock/hwspinlock_handlers.c | 8 +-- drivers/i2c/i2c_handlers.c | 12 ++-- drivers/i2s/i2s_handlers.c | 8 +-- drivers/i3c/i3c_handlers.c | 4 +- drivers/ipm/ipm_handlers.c | 8 +-- drivers/kscan/kscan_handlers.c | 6 +- drivers/led/led_handlers.c | 16 ++--- drivers/mbox/mbox_handlers.c | 8 +-- drivers/misc/devmux/devmux.c | 4 +- .../timeaware_gpio/timeaware_gpio_handlers.c | 12 ++-- drivers/peci/peci_handlers.c | 8 +-- drivers/ps2/ps2_handlers.c | 10 +-- drivers/ptp_clock/ptp_clock.c | 2 +- drivers/pwm/pwm_handlers.c | 10 +-- drivers/retained_mem/retained_mem_handlers.c | 8 +-- drivers/rtc/rtc_handlers.c | 16 ++--- drivers/sensor/sensor_handlers.c | 14 ++-- drivers/serial/uart_handlers.c | 48 +++++++------- drivers/smbus/smbus_handlers.c | 30 ++++----- drivers/spi/spi_handlers.c | 4 +- .../virtualization/virt_ivshmem_handlers.c | 24 +++---- drivers/w1/w1_handlers.c | 22 +++---- drivers/watchdog/wdt_handlers.c | 6 +- include/zephyr/arch/riscv/error.h | 2 +- include/zephyr/arch/x86/ia32/linker.ld | 2 +- include/zephyr/arch/xtensa/arch.h | 2 +- include/zephyr/arch/xtensa/arch_inlines.h | 2 +- include/zephyr/cache.h | 2 +- include/zephyr/device.h | 4 +- include/zephyr/devicetree.h | 2 +- include/zephyr/drivers/adc.h | 2 +- include/zephyr/drivers/auxdisplay.h | 2 +- include/zephyr/drivers/bbram.h | 2 +- include/zephyr/drivers/can.h | 2 +- include/zephyr/drivers/charger.h | 2 +- include/zephyr/drivers/console/uart_mux.h | 2 +- include/zephyr/drivers/counter.h | 2 +- include/zephyr/drivers/dac.h | 2 +- include/zephyr/drivers/dma.h | 2 +- include/zephyr/drivers/eeprom.h | 2 +- include/zephyr/drivers/emul_fuel_gauge.h | 2 +- include/zephyr/drivers/entropy.h | 2 +- include/zephyr/drivers/espi.h | 2 +- include/zephyr/drivers/espi_saf.h | 2 +- include/zephyr/drivers/flash.h | 2 +- .../zephyr/drivers/flash/flash_simulator.h | 2 +- include/zephyr/drivers/flash/nrf_qspi_nor.h | 2 +- include/zephyr/drivers/fuel_gauge.h | 2 +- include/zephyr/drivers/gnss.h | 2 +- include/zephyr/drivers/gpio.h | 2 +- include/zephyr/drivers/hwinfo.h | 2 +- include/zephyr/drivers/hwspinlock.h | 2 +- include/zephyr/drivers/i2c.h | 2 +- include/zephyr/drivers/i2s.h | 2 +- include/zephyr/drivers/i3c.h | 2 +- include/zephyr/drivers/ipm.h | 2 +- include/zephyr/drivers/kscan.h | 2 +- include/zephyr/drivers/led.h | 2 +- include/zephyr/drivers/mbox.h | 2 +- include/zephyr/drivers/mdio.h | 2 +- include/zephyr/drivers/misc/devmux/devmux.h | 2 +- .../misc/timeaware_gpio/timeaware_gpio.h | 2 +- include/zephyr/drivers/peci.h | 2 +- include/zephyr/drivers/ps2.h | 2 +- include/zephyr/drivers/ptp_clock.h | 2 +- include/zephyr/drivers/pwm.h | 2 +- include/zephyr/drivers/reset.h | 2 +- include/zephyr/drivers/retained_mem.h | 2 +- include/zephyr/drivers/rtc.h | 2 +- include/zephyr/drivers/rtc/maxim_ds3231.h | 2 +- include/zephyr/drivers/sdhc.h | 2 +- include/zephyr/drivers/sensor.h | 2 +- .../zephyr/drivers/sip_svc/sip_svc_driver.h | 2 +- include/zephyr/drivers/smbus.h | 2 +- include/zephyr/drivers/spi.h | 2 +- include/zephyr/drivers/syscon.h | 2 +- include/zephyr/drivers/uart.h | 2 +- include/zephyr/drivers/usb/usb_bc12.h | 2 +- .../zephyr/drivers/virtualization/ivshmem.h | 2 +- include/zephyr/drivers/w1.h | 2 +- include/zephyr/drivers/watchdog.h | 2 +- include/zephyr/internal/syscall_handler.h | 2 +- include/zephyr/kernel.h | 2 +- include/zephyr/kernel/mm/demand_paging.h | 2 +- include/zephyr/linker/kobject-data.ld | 4 +- include/zephyr/linker/kobject-priv-stacks.ld | 4 +- include/zephyr/linker/kobject-rom.ld | 4 +- include/zephyr/linker/linker-defs.h | 2 +- include/zephyr/logging/log_ctrl.h | 2 +- include/zephyr/logging/log_msg.h | 2 +- include/zephyr/mgmt/updatehub.h | 2 +- include/zephyr/net/ethernet.h | 2 +- include/zephyr/net/net_if.h | 2 +- include/zephyr/net/net_ip.h | 2 +- include/zephyr/net/socket.h | 2 +- include/zephyr/net/socket_select.h | 2 +- include/zephyr/net/socket_service.h | 2 +- include/zephyr/random/random.h | 2 +- include/zephyr/rtio/rtio.h | 2 +- include/zephyr/sys/atomic_c.h | 2 +- include/zephyr/sys/errno_private.h | 2 +- include/zephyr/sys/kobject.h | 4 +- include/zephyr/sys/libc-hooks.h | 2 +- include/zephyr/sys/mutex.h | 2 +- include/zephyr/sys/time_units.h | 2 +- include/zephyr/syscall.h | 2 +- include/zephyr/usb/usb_ch9.h | 2 +- kernel/atomic_c.c | 20 +++--- kernel/banner.c | 2 +- kernel/busy_wait.c | 2 +- kernel/condvar.c | 8 +-- kernel/device.c | 4 +- kernel/dynamic.c | 4 +- kernel/errno.c | 2 +- kernel/events.c | 14 ++-- kernel/float.c | 4 +- kernel/futex.c | 4 +- kernel/include/kernel_offsets.h | 2 +- kernel/include/offsets_short.h | 2 +- kernel/init.c | 2 +- kernel/msg_q.c | 18 ++--- kernel/mutex.c | 6 +- kernel/paging/statistics.c | 10 +-- kernel/pipes.c | 12 ++-- kernel/poll.c | 10 +-- kernel/queue.c | 16 ++--- kernel/sched.c | 22 +++---- kernel/sem.c | 10 +-- kernel/stack.c | 6 +- kernel/thread.c | 22 +++---- kernel/timeout.c | 4 +- kernel/timer.c | 16 ++--- kernel/userspace.c | 4 +- kernel/userspace_handler.c | 8 +-- kernel/version.c | 2 +- lib/libc/arcmwdt/libc-hooks.c | 2 +- .../minimal/source/stdout/stdout_console.c | 4 +- lib/libc/newlib/libc-hooks.c | 4 +- lib/libc/picolibc/libc-hooks.c | 2 +- lib/os/mutex.c | 4 +- lib/os/printk.c | 2 +- lib/posix/options/clock.c | 2 +- lib/posix/options/posix_clock.h | 2 +- lib/posix/options/uname.c | 2 +- samples/posix/env/src/main.c | 3 +- .../subsys/llext/edk/app/include/app_api.h | 2 +- samples/subsys/llext/edk/app/src/pubsub.c | 6 +- samples/subsys/shell/shell_module/src/main.c | 2 +- .../userspace/prod_consumer/src/app_syscall.c | 2 +- .../userspace/prod_consumer/src/app_syscall.h | 2 +- .../prod_consumer/src/sample_driver.h | 2 +- .../src/sample_driver_handlers.c | 4 +- scripts/build/gen_syscalls.py | 4 +- soc/andestech/ae350/soc_irq.S | 2 +- soc/common/riscv-privileged/soc_irq.S | 2 +- soc/espressif/esp32/gdbstub.c | 2 +- soc/espressif/esp32c3/soc_irq.S | 2 +- soc/intel/intel_adsp/common/multiprocessing.c | 2 +- soc/ite/ec/common/soc_irq.S | 2 +- soc/nordic/common/vpr/soc_context.S | 2 +- soc/openisa/rv32m1/soc_irq.S | 2 +- soc/telink/tlsr/tlsr951x/soc_irq.S | 2 +- subsys/bindesc/bindesc_version.c | 4 +- subsys/bluetooth/controller/hci/hci.c | 2 +- subsys/logging/log_core.c | 6 +- subsys/logging/log_mgmt.c | 2 +- subsys/logging/log_msg.c | 2 +- subsys/mgmt/mcumgr/grp/os_mgmt/src/os_mgmt.c | 2 +- subsys/mgmt/mcumgr/transport/src/smp_shell.c | 2 +- subsys/mgmt/updatehub/updatehub_handlers.c | 10 +-- subsys/net/ip/net_if.c | 20 +++--- subsys/net/ip/utils.c | 4 +- subsys/net/l2/ethernet/ethernet.c | 2 +- subsys/net/l2/openthread/openthread.c | 2 +- subsys/net/lib/sockets/getaddrinfo.c | 2 +- subsys/net/lib/sockets/socketpair.c | 2 +- subsys/net/lib/sockets/sockets.c | 40 +++++------ subsys/net/lib/sockets/sockets_misc.c | 2 +- subsys/net/lib/sockets/sockets_select.c | 2 +- subsys/random/random_handlers.c | 4 +- subsys/rtio/rtio_handlers.c | 12 ++-- subsys/shell/modules/kernel_service.c | 2 +- .../ztest/include/zephyr/ztest_error_hook.h | 2 +- .../ztest/include/zephyr/ztest_test.h | 2 +- subsys/testsuite/ztest/src/ztest.c | 8 +-- subsys/testsuite/ztest/src/ztest_error_hook.c | 4 +- .../arm/arm_interrupt/src/arm_interrupt.c | 2 +- .../arm/arm_interrupt/src/test_syscalls.h | 2 +- .../arm/arm_thread_swap/src/arm_syscalls.c | 4 +- .../arm/arm_thread_swap/src/test_syscalls.h | 2 +- tests/arch/x86/cpu_scrubs_regs/src/main.c | 2 +- .../x86/cpu_scrubs_regs/src/test_syscalls.h | 2 +- tests/arch/x86/pagetables/src/main.c | 2 +- tests/arch/x86/pagetables/src/main.h | 2 +- tests/benchmarks/app_kernel/src/master.c | 2 +- tests/benchmarks/app_kernel/src/master.h | 2 +- tests/benchmarks/footprints/src/userspace.c | 4 +- tests/benchmarks/footprints/src/userspace.h | 2 +- .../latency_measure/src/timing_sc.c | 2 +- .../latency_measure/src/timing_sc.h | 2 +- .../mocks/{ => zephyr}/devicetree_generated.h | 0 .../id/mocks/{ => zephyr}/syscalls/device.h | 0 .../mocks/{ => zephyr}/syscalls/mem_manage.h | 0 .../boot/mcuboot_data_sharing/CMakeLists.txt | 6 +- tests/boot/mcuboot_data_sharing/src/main.c | 2 +- tests/kernel/common/src/main.c | 2 +- tests/kernel/fatal/exception/src/main.c | 2 +- .../fatal/exception/src/test_syscalls.h | 2 +- .../mem_protect/mem_protect/src/inherit.c | 2 +- .../mem_protect/mem_protect/src/mem_protect.h | 2 +- tests/kernel/mem_protect/syscalls/src/main.c | 16 ++--- .../mem_protect/syscalls/src/test_syscalls.h | 2 +- tests/kernel/mem_protect/userspace/src/main.c | 2 +- .../mem_protect/userspace/src/test_syscall.h | 2 +- .../kernel/threads/dynamic_thread/src/main.c | 2 +- tests/kernel/threads/thread_stack/src/main.c | 4 +- .../threads/thread_stack/src/test_syscall.h | 2 +- tests/misc/llext-edk/include/app_api.h | 2 +- tests/misc/llext-edk/src/foo.c | 2 +- tests/subsys/bindesc/definition/src/main.c | 2 +- tests/subsys/llext/simple/src/syscalls_ext.h | 2 +- .../llext/simple/src/test_llext_simple.c | 2 +- .../logging/log_benchmark/src/test_helpers.c | 6 +- .../logging/log_benchmark/src/test_helpers.h | 2 +- .../mgmt/mcumgr/cb_notifications/src/main.c | 2 +- .../mgmt/mcumgr/os_mgmt_info/src/build_date.c | 2 +- .../mgmt/mcumgr/os_mgmt_info/src/limited.c | 2 +- .../mgmt/mcumgr/os_mgmt_info/src/main.c | 2 +- .../shell/shell_backend_uart/src/main.c | 2 +- 294 files changed, 770 insertions(+), 726 deletions(-) rename tests/bluetooth/host/id/mocks/{ => zephyr}/devicetree_generated.h (100%) rename tests/bluetooth/host/id/mocks/{ => zephyr}/syscalls/device.h (100%) rename tests/bluetooth/host/id/mocks/{ => zephyr}/syscalls/mem_manage.h (100%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 0e9fc7280a9e6..7cb3ed7c7fb9e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -109,6 +109,15 @@ add_library(zephyr_interface INTERFACE) # flags that come with zephyr_interface. zephyr_library_named(zephyr) +if(CONFIG_LEGACY_GENERATED_INCLUDE_PATH) + zephyr_include_directories(${PROJECT_BINARY_DIR}/include/generated/zephyr) + message(WARNING " + Warning: CONFIG_LEGACY_GENERATED_INCLUDE_PATH is currently enabled by default + so that user applications can continue to use the legacy include paths for the + generated headers. This Kconfig will be deprecated and eventually removed in + the future releases.") +endif() + zephyr_include_directories( include ${PROJECT_BINARY_DIR}/include/generated @@ -541,9 +550,9 @@ if(ZEPHYR_GIT_INDEX) endif() add_custom_command( - OUTPUT ${PROJECT_BINARY_DIR}/include/generated/version.h + OUTPUT ${PROJECT_BINARY_DIR}/include/generated/zephyr/version.h COMMAND ${CMAKE_COMMAND} -DZEPHYR_BASE=${ZEPHYR_BASE} - -DOUT_FILE=${PROJECT_BINARY_DIR}/include/generated/version.h + -DOUT_FILE=${PROJECT_BINARY_DIR}/include/generated/zephyr/version.h -DVERSION_TYPE=KERNEL -DVERSION_FILE=${ZEPHYR_BASE}/VERSION -DKERNEL_VERSION_CUSTOMIZATION="$" @@ -552,13 +561,13 @@ add_custom_command( DEPENDS ${ZEPHYR_BASE}/VERSION ${git_dependency} COMMAND_EXPAND_LISTS ) -add_custom_target(version_h DEPENDS ${PROJECT_BINARY_DIR}/include/generated/version.h) +add_custom_target(version_h DEPENDS ${PROJECT_BINARY_DIR}/include/generated/zephyr/version.h) if(EXISTS ${APPLICATION_SOURCE_DIR}/VERSION) add_custom_command( - OUTPUT ${PROJECT_BINARY_DIR}/include/generated/app_version.h + OUTPUT ${PROJECT_BINARY_DIR}/include/generated/zephyr/app_version.h COMMAND ${CMAKE_COMMAND} -DZEPHYR_BASE=${ZEPHYR_BASE} - -DOUT_FILE=${PROJECT_BINARY_DIR}/include/generated/app_version.h + -DOUT_FILE=${PROJECT_BINARY_DIR}/include/generated/zephyr/app_version.h -DVERSION_TYPE=APP -DVERSION_FILE=${APPLICATION_SOURCE_DIR}/VERSION -DAPP_VERSION_CUSTOMIZATION="$" @@ -567,7 +576,9 @@ if(EXISTS ${APPLICATION_SOURCE_DIR}/VERSION) DEPENDS ${APPLICATION_SOURCE_DIR}/VERSION ${git_dependency} COMMAND_EXPAND_LISTS ) - add_custom_target(app_version_h DEPENDS ${PROJECT_BINARY_DIR}/include/generated/app_version.h) + add_custom_target( + app_version_h + DEPENDS ${PROJECT_BINARY_DIR}/include/generated/zephyr/app_version.h) add_dependencies(zephyr_interface app_version_h) endif() @@ -622,8 +633,8 @@ set(ZEPHYR_CURRENT_CMAKE_DIR) get_property(LIBC_LINK_LIBRARIES TARGET zephyr_interface PROPERTY LIBC_LINK_LIBRARIES) 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(syscall_list_h ${CMAKE_CURRENT_BINARY_DIR}/include/generated/zephyr/syscall_list.h) +set(edk_syscall_list_h ${CMAKE_CURRENT_BINARY_DIR}/edk/include/generated/zephyr/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) @@ -761,7 +772,7 @@ add_custom_target(${SYSCALL_LIST_H_TARGET} DEPENDS ${syscall_list_h} ${picolibc_ set_property(TARGET ${SYSCALL_LIST_H_TARGET} APPEND PROPERTY ADDITIONAL_CLEAN_FILES - ${CMAKE_CURRENT_BINARY_DIR}/include/generated/syscalls + ${CMAKE_CURRENT_BINARY_DIR}/include/generated/zephyr/syscalls ) add_custom_target(${PARSE_SYSCALLS_TARGET} @@ -781,19 +792,30 @@ if(CONFIG_TIMEOUT_64BIT) set(SYSCALL_SPLIT_TIMEOUT_ARG --split-type k_timeout_t --split-type k_ticks_t) endif() +# percepio/TraceRecorder/kernelports/Zephyr/scripts/tz_parse_syscalls.py hardcodes the path +# to the `syscall_list.h`, make a copy of the generated file so that percepio is able to build +if(CONFIG_LEGACY_GENERATED_INCLUDE_PATH) + set(LEGACY_SYSCALL_LIST_H_ARGS + ${CMAKE_COMMAND} -E copy + ${syscall_list_h} + ${CMAKE_CURRENT_BINARY_DIR}/include/generated/syscall_list.h) +endif() + add_custom_command(OUTPUT include/generated/syscall_dispatch.c ${syscall_list_h} - # Also, some files are written to include/generated/syscalls/ + # Also, some files are written to include/generated/zephyr/syscalls/ COMMAND ${PYTHON_EXECUTABLE} ${ZEPHYR_BASE}/scripts/build/gen_syscalls.py --json-file ${syscalls_json} # Read this file - --base-output include/generated/syscalls # Write to this dir + --base-output include/generated/zephyr/syscalls # Write to this dir --syscall-dispatch include/generated/syscall_dispatch.c # Write this file --syscall-export-llext include/generated/syscall_export_llext.c --syscall-list ${syscall_list_h} $<$:--gen-mrsh-files> ${SYSCALL_LONG_REGISTERS_ARG} ${SYSCALL_SPLIT_TIMEOUT_ARG} + COMMAND + ${LEGACY_SYSCALL_LIST_H_ARGS} WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} DEPENDS ${PARSE_SYSCALLS_TARGET} ) @@ -801,7 +823,7 @@ add_custom_command(OUTPUT include/generated/syscall_dispatch.c ${syscall_list_h} # This is passed into all calls to the gen_kobject_list.py script. set(gen_kobject_list_include_args --include-subsystem-list ${struct_tags_json}) -set(DRV_VALIDATION ${PROJECT_BINARY_DIR}/include/generated/driver-validation.h) +set(DRV_VALIDATION ${PROJECT_BINARY_DIR}/include/generated/zephyr/driver-validation.h) add_custom_command( OUTPUT ${DRV_VALIDATION} COMMAND @@ -834,7 +856,7 @@ add_dependencies(zephyr_generated_headers set(OFFSETS_LIB offsets) set(OFFSETS_C_PATH ${ARCH_DIR}/${ARCH}/core/offsets/offsets.c) -set(OFFSETS_H_PATH ${PROJECT_BINARY_DIR}/include/generated/offsets.h) +set(OFFSETS_H_PATH ${PROJECT_BINARY_DIR}/include/generated/zephyr/offsets.h) add_library( ${OFFSETS_LIB} OBJECT ${OFFSETS_C_PATH}) target_include_directories(${OFFSETS_LIB} PRIVATE @@ -1197,7 +1219,7 @@ if(CONFIG_USERSPACE) PUBLIC $ ) - set(KOBJECT_LINKER_HEADER_DATA "${PROJECT_BINARY_DIR}/include/generated/linker-kobject-prebuilt-data.h") + set(KOBJECT_LINKER_HEADER_DATA "${PROJECT_BINARY_DIR}/include/generated/zephyr/linker-kobject-prebuilt-data.h") add_custom_command( OUTPUT ${KOBJECT_LINKER_HEADER_DATA} @@ -1205,7 +1227,7 @@ if(CONFIG_USERSPACE) ${PYTHON_EXECUTABLE} ${ZEPHYR_BASE}/scripts/build/gen_kobject_placeholders.py --object $ - --outdir ${PROJECT_BINARY_DIR}/include/generated + --outdir ${PROJECT_BINARY_DIR}/include/generated/zephyr --datapct ${CONFIG_KOBJECT_DATA_AREA_RESERVE_EXTRA_PERCENT} --rodata ${CONFIG_KOBJECT_RODATA_AREA_EXTRA_BYTES} $<$:--verbose> @@ -1962,7 +1984,7 @@ if(LOG_DICT_DB_NAME_ARG) ${ZEPHYR_BASE}/scripts/logging/dictionary/database_gen.py ${KERNEL_ELF_NAME} ${LOG_DICT_DB_NAME_ARG}=${LOG_DICT_DB_NAME} - --build-header ${PROJECT_BINARY_DIR}/include/generated/version.h + --build-header ${PROJECT_BINARY_DIR}/include/generated/zephyr/version.h WORKING_DIRECTORY ${PROJECT_BINARY_DIR} COMMENT "Generating logging dictionary database: ${LOG_DICT_DB_NAME}" DEPENDS ${logical_target_for_zephyr_elf} @@ -2093,12 +2115,12 @@ 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 + -E make_directory edk/include/generated/zephyr 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 + --base-output edk/include/generated/zephyr/syscalls # Write to this dir --syscall-dispatch edk/include/generated/syscall_dispatch.c # Write this file --syscall-list ${edk_syscall_list_h} $<$:--userspace-only> diff --git a/Kconfig.zephyr b/Kconfig.zephyr index e44cd327cb5f0..01b5f4497e095 100644 --- a/Kconfig.zephyr +++ b/Kconfig.zephyr @@ -1048,3 +1048,20 @@ config BOOTLOADER_BOSSA_ADAFRUIT_UF2 endchoice endmenu + +menu "Compatibility" + +config LEGACY_GENERATED_INCLUDE_PATH + bool "Legacy include path for generated headers" + default y + help + Allow applications and libraries to use the Zephyr legacy include + path for the generated headers which does not use the `zephyr/` prefix. + + From now on, i.e., the preferred way to include the `version.h` header is to + use , this Kconfig is currently enabled by default so that + user applications won't immediately fail to compile. + + This Kconfig will be deprecated and eventually removed in the future releases. + +endmenu diff --git a/arch/arc/include/offsets_short_arch.h b/arch/arc/include/offsets_short_arch.h index 5bf2c23fc3a36..f461112ae7926 100644 --- a/arch/arc/include/offsets_short_arch.h +++ b/arch/arc/include/offsets_short_arch.h @@ -7,7 +7,7 @@ #ifndef ZEPHYR_ARCH_ARC_INCLUDE_OFFSETS_SHORT_ARCH_H_ #define ZEPHYR_ARCH_ARC_INCLUDE_OFFSETS_SHORT_ARCH_H_ -#include +#include /* kernel */ diff --git a/arch/arm/include/offsets_short_arch.h b/arch/arm/include/offsets_short_arch.h index 4ceb1fc3f7aec..ea6af4db92df3 100644 --- a/arch/arm/include/offsets_short_arch.h +++ b/arch/arm/include/offsets_short_arch.h @@ -7,7 +7,7 @@ #ifndef ZEPHYR_ARCH_ARM_INCLUDE_OFFSETS_SHORT_ARCH_H_ #define ZEPHYR_ARCH_ARM_INCLUDE_OFFSETS_SHORT_ARCH_H_ -#include +#include /* kernel */ diff --git a/arch/arm64/core/reset.S b/arch/arm64/core/reset.S index 5e406bea1323d..a01139ad70091 100644 --- a/arch/arm64/core/reset.S +++ b/arch/arm64/core/reset.S @@ -7,7 +7,7 @@ #include #include #include -#include +#include #include "boot.h" #include "macro_priv.inc" diff --git a/arch/arm64/core/vector_table.S b/arch/arm64/core/vector_table.S index 1a1b649d4f295..499dbd292a53a 100644 --- a/arch/arm64/core/vector_table.S +++ b/arch/arm64/core/vector_table.S @@ -10,7 +10,7 @@ #include #include -#include +#include #include #include #include diff --git a/arch/arm64/include/offsets_short_arch.h b/arch/arm64/include/offsets_short_arch.h index abd93bba7bace..11dd5f642561d 100644 --- a/arch/arm64/include/offsets_short_arch.h +++ b/arch/arm64/include/offsets_short_arch.h @@ -7,7 +7,7 @@ #ifndef ZEPHYR_ARCH_ARM64_INCLUDE_OFFSETS_SHORT_ARCH_H_ #define ZEPHYR_ARCH_ARM64_INCLUDE_OFFSETS_SHORT_ARCH_H_ -#include +#include #define _thread_offset_to_exception_depth \ (___thread_t_arch_OFFSET + ___thread_arch_t_exception_depth_OFFSET) diff --git a/arch/mips/include/offsets_short_arch.h b/arch/mips/include/offsets_short_arch.h index bd64deef114f5..8440f0ff70137 100644 --- a/arch/mips/include/offsets_short_arch.h +++ b/arch/mips/include/offsets_short_arch.h @@ -9,7 +9,7 @@ #ifndef ZEPHYR_ARCH_MIPS_INCLUDE_OFFSETS_SHORT_ARCH_H_ #define ZEPHYR_ARCH_MIPS_INCLUDE_OFFSETS_SHORT_ARCH_H_ -#include +#include #define _thread_offset_to_sp \ (___thread_t_callee_saved_OFFSET + ___callee_saved_t_sp_OFFSET) diff --git a/arch/nios2/include/offsets_short_arch.h b/arch/nios2/include/offsets_short_arch.h index b3f60972c3b88..3b961e1fcb92c 100644 --- a/arch/nios2/include/offsets_short_arch.h +++ b/arch/nios2/include/offsets_short_arch.h @@ -7,7 +7,7 @@ #ifndef ZEPHYR_ARCH_NIOS2_INCLUDE_OFFSETS_SHORT_ARCH_H_ #define ZEPHYR_ARCH_NIOS2_INCLUDE_OFFSETS_SHORT_ARCH_H_ -#include +#include /* kernel */ diff --git a/arch/posix/include/offsets_short_arch.h b/arch/posix/include/offsets_short_arch.h index b33414b3f6e1b..5281d68e092d5 100644 --- a/arch/posix/include/offsets_short_arch.h +++ b/arch/posix/include/offsets_short_arch.h @@ -7,7 +7,7 @@ #ifndef ZEPHYR_ARCH_POSIX_INCLUDE_OFFSETS_SHORT_ARCH_H_ #define ZEPHYR_ARCH_POSIX_INCLUDE_OFFSETS_SHORT_ARCH_H_ -#include +#include /* kernel */ diff --git a/arch/riscv/core/fatal.c b/arch/riscv/core/fatal.c index 2624edbec9093..b8736f36144f3 100644 --- a/arch/riscv/core/fatal.c +++ b/arch/riscv/core/fatal.c @@ -263,6 +263,6 @@ static void z_vrfy_user_fault(unsigned int reason) z_impl_user_fault(reason); } -#include +#include #endif /* CONFIG_USERSPACE */ diff --git a/arch/riscv/core/fpu.S b/arch/riscv/core/fpu.S index 2708d11fec1c4..981bd576cb773 100644 --- a/arch/riscv/core/fpu.S +++ b/arch/riscv/core/fpu.S @@ -7,7 +7,7 @@ #include #include -#include +#include #ifdef CONFIG_CPU_HAS_FPU_DOUBLE_PRECISION #define LOAD fld diff --git a/arch/riscv/core/reset.S b/arch/riscv/core/reset.S index e9424e7a8e2af..89c488faa9475 100644 --- a/arch/riscv/core/reset.S +++ b/arch/riscv/core/reset.S @@ -8,7 +8,7 @@ #include #include #include -#include +#include #include "asm_macros.inc" /* exports */ diff --git a/arch/riscv/include/offsets_short_arch.h b/arch/riscv/include/offsets_short_arch.h index 3d3a878f16ea1..27c01a77461d3 100644 --- a/arch/riscv/include/offsets_short_arch.h +++ b/arch/riscv/include/offsets_short_arch.h @@ -7,7 +7,7 @@ #ifndef ZEPHYR_ARCH_RISCV_INCLUDE_OFFSETS_SHORT_ARCH_H_ #define ZEPHYR_ARCH_RISCV_INCLUDE_OFFSETS_SHORT_ARCH_H_ -#include +#include #define _thread_offset_to_sp \ (___thread_t_callee_saved_OFFSET + ___callee_saved_t_sp_OFFSET) diff --git a/arch/sparc/include/offsets_short_arch.h b/arch/sparc/include/offsets_short_arch.h index c53f2b3705bea..0f9272f332b66 100644 --- a/arch/sparc/include/offsets_short_arch.h +++ b/arch/sparc/include/offsets_short_arch.h @@ -7,7 +7,7 @@ #ifndef ZEPHYR_ARCH_SPARC_INCLUDE_OFFSETS_SHORT_ARCH_H_ #define ZEPHYR_ARCH_SPARC_INCLUDE_OFFSETS_SHORT_ARCH_H_ -#include +#include #define _thread_offset_to_y \ (___thread_t_callee_saved_OFFSET + ___callee_saved_t_y_OFFSET) diff --git a/arch/x86/include/ia32/offsets_short_arch.h b/arch/x86/include/ia32/offsets_short_arch.h index 2033a5585f711..cb5cdb218f0ae 100644 --- a/arch/x86/include/ia32/offsets_short_arch.h +++ b/arch/x86/include/ia32/offsets_short_arch.h @@ -7,7 +7,7 @@ #ifndef ZEPHYR_ARCH_X86_INCLUDE_IA32_OFFSETS_SHORT_ARCH_H_ #define ZEPHYR_ARCH_X86_INCLUDE_IA32_OFFSETS_SHORT_ARCH_H_ -#include +#include /* kernel */ diff --git a/arch/x86/include/intel64/offsets_short_arch.h b/arch/x86/include/intel64/offsets_short_arch.h index 4252ac687dba7..1ffabc899c204 100644 --- a/arch/x86/include/intel64/offsets_short_arch.h +++ b/arch/x86/include/intel64/offsets_short_arch.h @@ -6,7 +6,7 @@ #ifndef ZEPHYR_ARCH_X86_INCLUDE_INTEL64_OFFSETS_SHORT_ARCH_H_ #define ZEPHYR_ARCH_X86_INCLUDE_INTEL64_OFFSETS_SHORT_ARCH_H_ -#include +#include #define _thread_offset_to_rsp \ (___thread_t_callee_saved_OFFSET + ___callee_saved_t_rsp_OFFSET) diff --git a/arch/xtensa/core/CMakeLists.txt b/arch/xtensa/core/CMakeLists.txt index 4c2ce8173ca59..56ca1071b0130 100644 --- a/arch/xtensa/core/CMakeLists.txt +++ b/arch/xtensa/core/CMakeLists.txt @@ -48,7 +48,7 @@ add_subdirectory(startup) # are the official places where we find core-isa.h. (Also that we # undefine __XCC_ because that compiler actually trips an error trying # to build this file to protect against mismatched versions.) -set(CORE_ISA_DM ${CMAKE_BINARY_DIR}/zephyr/include/generated/core-isa-dM.h) +set(CORE_ISA_DM ${CMAKE_BINARY_DIR}/zephyr/include/generated/zephyr/core-isa-dM.h) set(CORE_ISA_IN ${CMAKE_BINARY_DIR}/zephyr/include/generated/core-isa-dM.c) file(WRITE ${CORE_ISA_IN} "#include \n") add_custom_command(OUTPUT ${CORE_ISA_DM} @@ -73,7 +73,7 @@ else() endif() # Generates a list of device-specific scratch register choices -set(ZSR_H ${CMAKE_BINARY_DIR}/zephyr/include/generated/zsr.h) +set(ZSR_H ${CMAKE_BINARY_DIR}/zephyr/include/generated/zephyr/zsr.h) add_custom_command(OUTPUT ${ZSR_H} DEPENDS ${CORE_ISA_DM} COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/gen_zsr.py $<$:--mmu> diff --git a/arch/xtensa/core/coredump.c b/arch/xtensa/core/coredump.c index a2eec6207743c..7f010eb1954a7 100644 --- a/arch/xtensa/core/coredump.c +++ b/arch/xtensa/core/coredump.c @@ -7,7 +7,7 @@ #include #include #include -#include +#include #define ARCH_HDR_VER 1 #define XTENSA_BLOCK_HDR_VER 2 diff --git a/arch/xtensa/core/debug_helpers_asm.S b/arch/xtensa/core/debug_helpers_asm.S index 3dacc1a4587f5..6ed5ced8c61a8 100644 --- a/arch/xtensa/core/debug_helpers_asm.S +++ b/arch/xtensa/core/debug_helpers_asm.S @@ -10,7 +10,7 @@ #include #include -#include +#include .section .iram1, "ax" .align 4 diff --git a/arch/xtensa/core/fatal.c b/arch/xtensa/core/fatal.c index 6ec5549f2e469..0d5da1ca8179d 100644 --- a/arch/xtensa/core/fatal.c +++ b/arch/xtensa/core/fatal.c @@ -154,6 +154,6 @@ static void z_vrfy_xtensa_user_fault(unsigned int reason) z_impl_xtensa_user_fault(reason); } -#include +#include #endif /* CONFIG_USERSPACE */ diff --git a/arch/xtensa/core/irq_offload.c b/arch/xtensa/core/irq_offload.c index ad35ef4cd0e4d..c142bfc5fc669 100644 --- a/arch/xtensa/core/irq_offload.c +++ b/arch/xtensa/core/irq_offload.c @@ -5,7 +5,7 @@ #include #include -#include +#include #include static struct { diff --git a/arch/xtensa/core/userspace.S b/arch/xtensa/core/userspace.S index 1578e3be971a5..507ae17267e84 100644 --- a/arch/xtensa/core/userspace.S +++ b/arch/xtensa/core/userspace.S @@ -5,10 +5,10 @@ */ #include -#include +#include #include #include -#include +#include #include diff --git a/arch/xtensa/core/vector_handlers.c b/arch/xtensa/core/vector_handlers.c index f0b0a9175ff2c..dd3c0c00f5246 100644 --- a/arch/xtensa/core/vector_handlers.c +++ b/arch/xtensa/core/vector_handlers.c @@ -12,8 +12,8 @@ #include #include #include -#include -#include +#include +#include #include #ifdef CONFIG_XTENSA_GEN_HANDLERS diff --git a/arch/xtensa/core/window_vectors.S b/arch/xtensa/core/window_vectors.S index 90eba495bde80..6c4e8c4480321 100644 --- a/arch/xtensa/core/window_vectors.S +++ b/arch/xtensa/core/window_vectors.S @@ -4,7 +4,7 @@ * SPDX-License-Identifier: Apache-2.0 */ #include -#include +#include /* WINDOW OVERFLOW AND UNDERFLOW EXCEPTION VECTORS AND ALLOCA EXCEPTION * HANDLER diff --git a/arch/xtensa/core/xtensa_asm2_util.S b/arch/xtensa/core/xtensa_asm2_util.S index dad8f1993594f..58ca9b46eec3c 100644 --- a/arch/xtensa/core/xtensa_asm2_util.S +++ b/arch/xtensa/core/xtensa_asm2_util.S @@ -4,8 +4,8 @@ * SPDX-License-Identifier: Apache-2.0 */ #include -#include -#include +#include +#include #if defined(CONFIG_SIMULATOR_XTENSA) || defined(XT_SIMULATOR) #include diff --git a/arch/xtensa/core/xtensa_hifi.S b/arch/xtensa/core/xtensa_hifi.S index 3c311acab0f4b..dff714cce183b 100644 --- a/arch/xtensa/core/xtensa_hifi.S +++ b/arch/xtensa/core/xtensa_hifi.S @@ -4,7 +4,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include +#include #include #include diff --git a/arch/xtensa/include/kernel_arch_func.h b/arch/xtensa/include/kernel_arch_func.h index 48599f0e76927..29a8982660a0c 100644 --- a/arch/xtensa/include/kernel_arch_func.h +++ b/arch/xtensa/include/kernel_arch_func.h @@ -14,7 +14,7 @@ #include #include #include -#include +#include #ifdef __cplusplus extern "C" { diff --git a/arch/xtensa/include/xtensa_asm2_s.h b/arch/xtensa/include/xtensa_asm2_s.h index dddf7bb309c67..0af8c4cb51fdc 100644 --- a/arch/xtensa/include/xtensa_asm2_s.h +++ b/arch/xtensa/include/xtensa_asm2_s.h @@ -7,10 +7,10 @@ #ifndef ZEPHYR_ARCH_XTENSA_INCLUDE_XTENSA_ASM2_S_H #define ZEPHYR_ARCH_XTENSA_INCLUDE_XTENSA_ASM2_S_H -#include +#include #include "xtensa_asm2_context.h" -#include +#include /* Assembler header! This file contains macros designed to be included * only by the assembler. diff --git a/boards/qemu/x86/qemu_x86_tiny.ld b/boards/qemu/x86/qemu_x86_tiny.ld index 623a11fb41699..3b3ecde113cc3 100644 --- a/boards/qemu/x86/qemu_x86_tiny.ld +++ b/boards/qemu/x86/qemu_x86_tiny.ld @@ -6,7 +6,7 @@ */ #include -#include +#include #include #include #include diff --git a/cmake/ide/eclipse_cdt4_generator_amendment.cmake b/cmake/ide/eclipse_cdt4_generator_amendment.cmake index 1bad729118e37..5fd32a2ddd3d9 100644 --- a/cmake/ide/eclipse_cdt4_generator_amendment.cmake +++ b/cmake/ide/eclipse_cdt4_generator_amendment.cmake @@ -9,7 +9,7 @@ # # Solution: # The amendment function generates a macro header file -# ${CMAKE_BINARY_DIR}/zephyr/include/generated/cmake_intdef.h +# ${CMAKE_BINARY_DIR}/zephyr/include/generated/zephyr/cmake_intdef.h # based on INTERFACE_COMPILE_DEFINITIONS and appends the # defines from the file to # CMAKE_EXTRA_GENERATOR_C_SYSTEM_DEFINED_MACROS. @@ -88,7 +88,7 @@ else(${_param_defs} EQUAL 1) message(" ${_work_mode}") endif(${_param_defs} EQUAL 1) -set(OUTPUT_FILE ${CMAKE_BINARY_DIR}/zephyr/include/generated/cmake_intdef.h) +set(OUTPUT_FILE ${CMAKE_BINARY_DIR}/zephyr/include/generated/zephyr/cmake_intdef.h) file(WRITE ${OUTPUT_FILE} "/* Generated by eclipse_cd4_generator_amendment.cmake */\n") file(APPEND ${OUTPUT_FILE} "/* The header contains the defines collected from the */\n") file(APPEND ${OUTPUT_FILE} "/* INTERFACE_COMPILE_DEFINITIONS target property */\n") @@ -104,7 +104,7 @@ if (${_work_mode} STREQUAL "C and CXX includes, defines in Eclipse with project message(" -------------------------------------------------------------------------") message(" Add the following two command line parameters:") message("") - message(" -imacros ${CMAKE_BINARY_DIR}/zephyr/include/generated/cmake_intdef.h") + message(" -imacros ${CMAKE_BINARY_DIR}/zephyr/include/generated/zephyr/cmake_intdef.h") message(" -imacros ${AUTOCONF_H}") message("") message(" to 'CDT cross GCC Built-in Compiler Settings' provider command definition") @@ -125,7 +125,7 @@ if ( (${_work_mode} STREQUAL "C and CXX includes, defines in .settings - [EXPERI file(APPEND ${OUTPUT_FILE} "\t\t\t\n") file(APPEND ${OUTPUT_FILE} "\t\t\t\n") if (${_work_mode} STREQUAL "C and CXX includes, defines in .settings with project defines - [EXPERIMENTAL]") - file(APPEND ${OUTPUT_FILE} "\t\t\t\n") + file(APPEND ${OUTPUT_FILE} "\t\t\t\n") else () file(APPEND ${OUTPUT_FILE} "\t\t\t\n") endif () @@ -167,7 +167,7 @@ if ( (${_work_mode} STREQUAL "C and CXX includes, defines in .cproject without _ endif() - file(STRINGS ${CMAKE_BINARY_DIR}/zephyr/include/generated/cmake_intdef.h _int_comp_def) + file(STRINGS ${CMAKE_BINARY_DIR}/zephyr/include/generated/zephyr/cmake_intdef.h _int_comp_def) set (_resultDefines "${CMAKE_EXTRA_GENERATOR_C_SYSTEM_DEFINED_MACROS}") foreach( d ${_int_comp_def} ) string(REGEX MATCH "^#define +([A-Za-z_][A-Za-z0-9_]*) *(.*) *$" _dummy "${d}") diff --git a/cmake/kobj.cmake b/cmake/kobj.cmake index dc693509b119d..22fa36ae44af4 100644 --- a/cmake/kobj.cmake +++ b/cmake/kobj.cmake @@ -2,9 +2,9 @@ function(gen_kobj gen_dir_out) if (PROJECT_BINARY_DIR) - set(gen_dir ${PROJECT_BINARY_DIR}/include/generated) + set(gen_dir ${PROJECT_BINARY_DIR}/include/generated/zephyr) else () - set(gen_dir ${CMAKE_BINARY_DIR}/include/generated) + set(gen_dir ${CMAKE_BINARY_DIR}/include/generated/zephyr) endif () set(KOBJ_TYPES ${gen_dir}/kobj-types-enum.h) @@ -30,6 +30,7 @@ function(gen_kobj gen_dir_out) ) add_custom_target(${KOBJ_TYPES_H_TARGET} DEPENDS ${KOBJ_TYPES} ${KOBJ_OTYPE}) + cmake_path(GET gen_dir PARENT_PATH gen_dir) set(${gen_dir_out} ${gen_dir} PARENT_SCOPE) endfunction () diff --git a/cmake/modules/generated_file_directories.cmake b/cmake/modules/generated_file_directories.cmake index 9b18e1794de03..9865296879635 100644 --- a/cmake/modules/generated_file_directories.cmake +++ b/cmake/modules/generated_file_directories.cmake @@ -7,7 +7,7 @@ include_guard(GLOBAL) # # Outcome: # - BINARY_DIR_INCLUDE is set to ${PROJECT_BINARY_DIR}/include -# - BINARY_DIR_INCLUDE_GENERATED is set to ${BINARY_DIR_INCLUDE}/generated +# - BINARY_DIR_INCLUDE_GENERATED is set to ${BINARY_DIR_INCLUDE}/generated/zephyr # - BINARY_DIR_INCLUDE_GENERATED is a directory # # Required variables: @@ -20,5 +20,5 @@ include_guard(GLOBAL) # None set(BINARY_DIR_INCLUDE ${PROJECT_BINARY_DIR}/include) -set(BINARY_DIR_INCLUDE_GENERATED ${BINARY_DIR_INCLUDE}/generated) +set(BINARY_DIR_INCLUDE_GENERATED ${BINARY_DIR_INCLUDE}/generated/zephyr) file(MAKE_DIRECTORY ${BINARY_DIR_INCLUDE_GENERATED}) diff --git a/cmake/modules/kconfig.cmake b/cmake/modules/kconfig.cmake index 01fbdf73f3c06..4606f71cc767c 100644 --- a/cmake/modules/kconfig.cmake +++ b/cmake/modules/kconfig.cmake @@ -5,7 +5,8 @@ include_guard(GLOBAL) include(extensions) include(python) -# autoconf.h is generated by Kconfig and placed in /zephyr/include/generated/autoconf.h. +# autoconf.h is generated by Kconfig and placed in +# /zephyr/include/generated/autoconf.h. # A project may request a custom location by setting AUTOCONF_H explicitly before # calling 'find_package(Zephyr)' or loading this module. set_ifndef(AUTOCONF_H ${PROJECT_BINARY_DIR}/include/generated/autoconf.h) diff --git a/cmake/modules/unittest.cmake b/cmake/modules/unittest.cmake index 892358999cfc4..de5b0f3eeb618 100644 --- a/cmake/modules/unittest.cmake +++ b/cmake/modules/unittest.cmake @@ -59,7 +59,7 @@ 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_DIR ${APPLICATION_BINARY_DIR}/zephyr/include/generated/zephyr) set(INCL_GENERATED_SYSCALL_DIR ${INCL_GENERATED_DIR}/syscalls) list(APPEND INCL_GENERATED_HEADERS ${INCL_GENERATED_DIR}/devicetree_generated.h diff --git a/doc/build/cmake/index.rst b/doc/build/cmake/index.rst index 534c3ff34e106..ee9bde7206ff8 100644 --- a/doc/build/cmake/index.rst +++ b/doc/build/cmake/index.rst @@ -88,7 +88,7 @@ Devicetree The preprocessed devicetree sources are parsed by :zephyr_file:`gen_defines.py ` to generate a - :file:`build/zephyr/include/generated/devicetree_generated.h` header with + :file:`build/zephyr/include/generated/zephyr/devicetree_generated.h` header with preprocessor macros. Source code should access preprocessor macros generated from devicetree by diff --git a/doc/build/dts/howtos.rst b/doc/build/dts/howtos.rst index c6ee5a80d3024..8875e9cfc4259 100644 --- a/doc/build/dts/howtos.rst +++ b/doc/build/dts/howtos.rst @@ -42,7 +42,7 @@ CMake prints the input and output file locations like this: -- Found BOARD.dts: .../zephyr/boards/arm/qemu_cortex_m3/qemu_cortex_m3.dts -- Generated zephyr.dts: .../zephyr/build/zephyr/zephyr.dts - -- Generated devicetree_generated.h: .../zephyr/build/zephyr/include/generated/devicetree_generated.h + -- Generated devicetree_generated.h: .../zephyr/build/zephyr/include/generated/zephyr/devicetree_generated.h The :file:`zephyr.dts` file is the final devicetree in DTS format. diff --git a/doc/build/dts/intro-input-output.rst b/doc/build/dts/intro-input-output.rst index 698012d5821fa..d069ae4660c9a 100644 --- a/doc/build/dts/intro-input-output.rst +++ b/doc/build/dts/intro-input-output.rst @@ -129,7 +129,7 @@ These are created in your application's build directory. input to :file:`gen_defines.py` and used to create :file:`zephyr.dts` and :file:`devicetree_generated.h`. -:file:`/zephyr/include/generated/devicetree_generated.h` +:file:`/zephyr/include/generated/zephyr/devicetree_generated.h` The generated macros and additional comments describing the devicetree. Included by ``devicetree.h``. diff --git a/doc/build/dts/troubleshooting.rst b/doc/build/dts/troubleshooting.rst index 54169b3ab4252..71521a3026bcb 100644 --- a/doc/build/dts/troubleshooting.rst +++ b/doc/build/dts/troubleshooting.rst @@ -66,7 +66,7 @@ Below, ```` means your build directory. To find the devicetree node you need to check, use the number ```` from the linker error. Look for this number in the list of nodes at the top of -:file:`/zephyr/include/generated/devicetree_generated.h`. For example, if +:file:`/zephyr/include/generated/zephyr/devicetree_generated.h`. For example, if ```` is 15, and your :file:`devicetree_generated.h` file looks like this, the node you are interested in is ``/soc/i2c@deadbeef``: diff --git a/doc/build/dts/zephyr_dt_inputs_outputs.svg b/doc/build/dts/zephyr_dt_inputs_outputs.svg index 833353aa654c8..3aace1d0fb8fe 100644 --- a/doc/build/dts/zephyr_dt_inputs_outputs.svg +++ b/doc/build/dts/zephyr_dt_inputs_outputs.svg @@ -1,4 +1,4 @@ -
FILE_1.overlay
...
FILE_n.overlay
FILE_1.overlay...
Devicetree overlays:
optional DTS format files
which override <BOARD>.dts.
Devi...
In board directory.
The "base" devicetree.
Includes SoC .dtsi file,
may include other files.
In...
<BOARD>.dts
<BOARD>.dts
BINDING_1.yaml
...
BINDING_n.yaml
BINDING_1.yaml...
Devicetree bindings:
contain rules for devicetree's
contents.
Devi...
Devicetree scripts in scripts/dts/
Devicetree scri...
Intermediate output in build/zephyr/. C preprocessor output of including <BOARD>.dts and overlays.
Intermediate output in bu...
Generated C header files, in
build/zephyr/include/generated/.

Access these via <devicetree.h>
Gene...
Generated C headers
Generated C headers
zephyr.dts.pre
zephyr.dts.pre
zephyr.dts
zephyr.dts
Final merged devicetree in
build/zephyr/. Useful for debugging. Passed to dtc if it is installed.
Final merged devicetree i...
dtc (optional, just for errors/warnings)
dtc (optional, just...
Viewer does not support full SVG 1.1
\ No newline at end of file +
FILE_1.overlay
...
FILE_n.overlay
FILE_1.overlay...
Devicetree overlays:
optional DTS format files
which override <BOARD>.dts.
Devi...
In board directory.
The "base" devicetree.
Includes SoC .dtsi file,
may include other files.
In...
<BOARD>.dts
<BOARD>.dts
BINDING_1.yaml
...
BINDING_n.yaml
BINDING_1.yaml...
Devicetree bindings:
contain rules for devicetree's
contents.
Devi...
Devicetree scripts in scripts/dts/
Devicetree scri...
Intermediate output in build/zephyr/. C preprocessor output of including <BOARD>.dts and overlays.
Intermediate output in bu...
Generated C header files, in
build/zephyr/include/generated/zephyr/.

Access these via <devicetree.h>
Gene...
Generated C headers
Generated C headers
zephyr.dts.pre
zephyr.dts.pre
zephyr.dts
zephyr.dts
Final merged devicetree in
build/zephyr/. Useful for debugging. Passed to dtc if it is installed.
Final merged devicetree i...
dtc (optional, just for errors/warnings)
dtc (optional, just...
Viewer does not support full SVG 1.1
diff --git a/doc/kernel/drivers/index.rst b/doc/kernel/drivers/index.rst index fcc2e6676501f..96574e0899538 100644 --- a/doc/kernel/drivers/index.rst +++ b/doc/kernel/drivers/index.rst @@ -203,7 +203,7 @@ A device-specific API definition typically looks like this: __syscall int specific_from_user(const struct device *dev, int bar); /* Only needed when extensions include syscalls */ - #include + #include A driver implementing extensions to the subsystem will define the real implementation of both the subsystem API and the specific APIs: @@ -243,7 +243,7 @@ implementation of both the subsystem API and the specific APIs: return z_impl_specific_do_that(dev, bar) } - #include + #include #endif /* CONFIG_USERSPACE */ diff --git a/doc/kernel/usermode/syscalls.rst b/doc/kernel/usermode/syscalls.rst index 8b35ce8099180..1490a758db5e9 100644 --- a/doc/kernel/usermode/syscalls.rst +++ b/doc/kernel/usermode/syscalls.rst @@ -87,7 +87,7 @@ bottom of ``include/sensor.h``: .. code-block:: c - #include + #include C prototype functions must be declared in one of the directories listed in the CMake variable ``SYSCALL_INCLUDE_DIRS``. This list @@ -143,7 +143,7 @@ C and header files by the :ref:`gen_syscalls.py` script, all of which can be fou the project out directory under ``include/generated/``: * The system call is added to the enumerated type of system call IDs, - which is expressed in ``include/generated/syscall_list.h``. It is the name + which is expressed in ``include/generated/zephyr/syscall_list.h``. It is the name of the API in uppercase, prefixed with ``K_SYSCALL_``. * An entry for the system call is created in the dispatch table @@ -172,7 +172,7 @@ The body of the API is created in the generated system header. Using the example of :c:func:`k_sem_init()`, this API is declared in ``include/kernel.h``. At the bottom of ``include/kernel.h`` is:: - #include + #include Inside this header is the body of :c:func:`k_sem_init()`:: @@ -362,7 +362,7 @@ For example: K_OOPS(K_SYSCALL_OBJ(sem, K_OBJ_SEM)); return z_impl_k_sem_take(sem, timeout); } - #include + #include Verification Memory Access Policies diff --git a/doc/services/retention/blinfo.rst b/doc/services/retention/blinfo.rst index 6f34b0f9a3564..6d18b1d8688d4 100644 --- a/doc/services/retention/blinfo.rst +++ b/doc/services/retention/blinfo.rst @@ -122,7 +122,7 @@ this mode: #include #include - #include + #include #include API Reference diff --git a/drivers/adc/adc_handlers.c b/drivers/adc/adc_handlers.c index 2b00c2d95a9fc..c2f0fd4aef2fc 100644 --- a/drivers/adc/adc_handlers.c +++ b/drivers/adc/adc_handlers.c @@ -21,7 +21,7 @@ static inline int z_vrfy_adc_channel_setup(const struct device *dev, return z_impl_adc_channel_setup((const struct device *)dev, &channel_cfg); } -#include +#include static bool copy_sequence(struct adc_sequence *dst, struct adc_sequence_options *options, @@ -66,7 +66,7 @@ static inline int z_vrfy_adc_read(const struct device *dev, return z_impl_adc_read((const struct device *)dev, &sequence); } -#include +#include #ifdef CONFIG_ADC_ASYNC static inline int z_vrfy_adc_read_async(const struct device *dev, @@ -89,5 +89,5 @@ static inline int z_vrfy_adc_read_async(const struct device *dev, return z_impl_adc_read_async((const struct device *)dev, &sequence, (struct k_poll_signal *)async); } -#include +#include #endif /* CONFIG_ADC_ASYNC */ diff --git a/drivers/auxdisplay/auxdisplay_handlers.c b/drivers/auxdisplay/auxdisplay_handlers.c index 5c88e7afa09bc..45b22303ec3ad 100644 --- a/drivers/auxdisplay/auxdisplay_handlers.c +++ b/drivers/auxdisplay/auxdisplay_handlers.c @@ -12,21 +12,21 @@ static inline int z_vrfy_auxdisplay_display_on(const struct device *dev) K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_AUXDISPLAY)); return z_impl_auxdisplay_display_on(dev); } -#include +#include static inline int z_vrfy_auxdisplay_display_off(const struct device *dev) { K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_AUXDISPLAY)); return z_impl_auxdisplay_display_off(dev); } -#include +#include static inline int z_vrfy_auxdisplay_cursor_set_enabled(const struct device *dev, bool enabled) { K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_AUXDISPLAY)); return z_impl_auxdisplay_cursor_set_enabled(dev, enabled); } -#include +#include static inline int z_vrfy_auxdisplay_position_blinking_set_enabled(const struct device *dev, bool enabled) @@ -34,7 +34,7 @@ static inline int z_vrfy_auxdisplay_position_blinking_set_enabled(const struct d K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_AUXDISPLAY)); return z_impl_auxdisplay_position_blinking_set_enabled(dev, enabled); } -#include +#include static inline int z_vrfy_auxdisplay_cursor_shift_set(const struct device *dev, uint8_t direction, bool display_shift) @@ -42,7 +42,7 @@ static inline int z_vrfy_auxdisplay_cursor_shift_set(const struct device *dev, u K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_AUXDISPLAY)); return z_impl_auxdisplay_cursor_shift_set(dev, direction, display_shift); } -#include +#include static inline int z_vrfy_auxdisplay_cursor_position_set(const struct device *dev, enum auxdisplay_position type, @@ -51,7 +51,7 @@ static inline int z_vrfy_auxdisplay_cursor_position_set(const struct device *dev K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_AUXDISPLAY)); return z_impl_auxdisplay_cursor_position_set(dev, type, x, y); } -#include +#include static inline int z_vrfy_auxdisplay_cursor_position_get(const struct device *dev, int16_t *x, int16_t *y) @@ -59,7 +59,7 @@ static inline int z_vrfy_auxdisplay_cursor_position_get(const struct device *dev K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_AUXDISPLAY)); return z_impl_auxdisplay_cursor_position_get(dev, x, y); } -#include +#include static inline int z_vrfy_auxdisplay_display_position_set(const struct device *dev, enum auxdisplay_position type, @@ -68,7 +68,7 @@ static inline int z_vrfy_auxdisplay_display_position_set(const struct device *de K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_AUXDISPLAY)); return z_impl_auxdisplay_display_position_set(dev, type, x, y); } -#include +#include static inline int z_vrfy_auxdisplay_display_position_get(const struct device *dev, int16_t *x, int16_t *y) @@ -76,7 +76,7 @@ static inline int z_vrfy_auxdisplay_display_position_get(const struct device *de K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_AUXDISPLAY)); return z_impl_auxdisplay_display_position_get(dev, x, y); } -#include +#include static inline int z_vrfy_auxdisplay_capabilities_get(const struct device *dev, struct auxdisplay_capabilities *capabilities) @@ -84,14 +84,14 @@ static inline int z_vrfy_auxdisplay_capabilities_get(const struct device *dev, K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_AUXDISPLAY)); return z_impl_auxdisplay_capabilities_get(dev, capabilities); } -#include +#include static inline int z_vrfy_auxdisplay_clear(const struct device *dev) { K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_AUXDISPLAY)); return z_impl_auxdisplay_clear(dev); } -#include +#include static inline int z_vrfy_auxdisplay_brightness_get(const struct device *dev, uint8_t *brightness) @@ -99,7 +99,7 @@ static inline int z_vrfy_auxdisplay_brightness_get(const struct device *dev, K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_AUXDISPLAY)); return z_impl_auxdisplay_brightness_get(dev, brightness); } -#include +#include static inline int z_vrfy_auxdisplay_brightness_set(const struct device *dev, uint8_t brightness) @@ -107,7 +107,7 @@ static inline int z_vrfy_auxdisplay_brightness_set(const struct device *dev, K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_AUXDISPLAY)); return z_impl_auxdisplay_brightness_set(dev, brightness); } -#include +#include static inline int z_vrfy_auxdisplay_backlight_get(const struct device *dev, uint8_t *backlight) @@ -115,7 +115,7 @@ static inline int z_vrfy_auxdisplay_backlight_get(const struct device *dev, K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_AUXDISPLAY)); return z_impl_auxdisplay_backlight_get(dev, backlight); } -#include +#include static inline int z_vrfy_auxdisplay_backlight_set(const struct device *dev, uint8_t backlight) @@ -123,14 +123,14 @@ static inline int z_vrfy_auxdisplay_backlight_set(const struct device *dev, K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_AUXDISPLAY)); return z_impl_auxdisplay_backlight_set(dev, backlight); } -#include +#include static inline int z_vrfy_auxdisplay_is_busy(const struct device *dev) { K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_AUXDISPLAY)); return z_impl_auxdisplay_is_busy(dev); } -#include +#include static inline int z_vrfy_auxdisplay_custom_character_set(const struct device *dev, struct auxdisplay_character *character) @@ -138,7 +138,7 @@ static inline int z_vrfy_auxdisplay_custom_character_set(const struct device *de K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_AUXDISPLAY)); return z_impl_auxdisplay_custom_character_set(dev, character); } -#include +#include static inline int z_vrfy_auxdisplay_write(const struct device *dev, const uint8_t *data, uint16_t len) @@ -146,7 +146,7 @@ static inline int z_vrfy_auxdisplay_write(const struct device *dev, const uint8_ K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_AUXDISPLAY)); return z_impl_auxdisplay_write(dev, data, len); } -#include +#include static inline int z_vrfy_auxdisplay_custom_command(const struct device *dev, struct auxdisplay_custom_data *data) @@ -154,4 +154,4 @@ static inline int z_vrfy_auxdisplay_custom_command(const struct device *dev, K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_AUXDISPLAY)); return z_impl_auxdisplay_custom_command(dev, data); } -#include +#include diff --git a/drivers/bbram/bbram_handlers.c b/drivers/bbram/bbram_handlers.c index 14e4abe21b35d..2fc26954014a2 100644 --- a/drivers/bbram/bbram_handlers.c +++ b/drivers/bbram/bbram_handlers.c @@ -12,21 +12,21 @@ static inline int z_vrfy_bbram_check_invalid(const struct device *dev) K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_BBRAM)); return z_impl_bbram_check_invalid(dev); } -#include +#include static inline int z_vrfy_bbram_check_standby_power(const struct device *dev) { K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_BBRAM)); return z_impl_bbram_check_standby_power(dev); } -#include +#include static inline int z_vrfy_bbram_check_power(const struct device *dev) { K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_BBRAM)); return z_impl_bbram_check_power(dev); } -#include +#include static inline int z_vrfy_bbram_get_size(const struct device *dev, size_t *size) { @@ -34,7 +34,7 @@ static inline int z_vrfy_bbram_get_size(const struct device *dev, size_t *size) K_OOPS(K_SYSCALL_MEMORY_WRITE(size, sizeof(size_t))); return z_impl_bbram_get_size(dev, size); } -#include +#include static inline int z_vrfy_bbram_read(const struct device *dev, size_t offset, size_t size, uint8_t *data) @@ -43,7 +43,7 @@ static inline int z_vrfy_bbram_read(const struct device *dev, size_t offset, K_OOPS(K_SYSCALL_MEMORY_WRITE(data, size)); return z_impl_bbram_read(dev, offset, size, data); } -#include +#include static inline int z_vrfy_bbram_write(const struct device *dev, size_t offset, size_t size, const uint8_t *data) @@ -52,4 +52,4 @@ static inline int z_vrfy_bbram_write(const struct device *dev, size_t offset, K_OOPS(K_SYSCALL_MEMORY_READ(data, size)); return z_impl_bbram_write(dev, offset, size, data); } -#include +#include diff --git a/drivers/cache/cache_handlers.c b/drivers/cache/cache_handlers.c index 2005124136f76..692ec1306d9c8 100644 --- a/drivers/cache/cache_handlers.c +++ b/drivers/cache/cache_handlers.c @@ -13,7 +13,7 @@ static inline int z_vrfy_sys_cache_data_flush_range(void *addr, size_t size) return z_impl_sys_cache_data_flush_range(addr, size); } -#include +#include static inline int z_vrfy_sys_cache_data_invd_range(void *addr, size_t size) { @@ -21,7 +21,7 @@ static inline int z_vrfy_sys_cache_data_invd_range(void *addr, size_t size) return z_impl_sys_cache_data_invd_range(addr, size); } -#include +#include static inline int z_vrfy_sys_cache_data_flush_and_invd_range(void *addr, size_t size) { @@ -29,4 +29,4 @@ static inline int z_vrfy_sys_cache_data_flush_and_invd_range(void *addr, size_t return z_impl_sys_cache_data_flush_and_invd_range(addr, size); } -#include +#include diff --git a/drivers/can/can_handlers.c b/drivers/can/can_handlers.c index b762b80d9209c..c67ce015330d5 100644 --- a/drivers/can/can_handlers.c +++ b/drivers/can/can_handlers.c @@ -21,7 +21,7 @@ static int z_vrfy_can_calc_timing(const struct device *dev, struct can_timing *r return err; } -#include +#include static inline int z_vrfy_can_set_timing(const struct device *dev, const struct can_timing *timing) @@ -33,7 +33,7 @@ static inline int z_vrfy_can_set_timing(const struct device *dev, return z_impl_can_set_timing(dev, &timing_copy); } -#include +#include static inline int z_vrfy_can_get_core_clock(const struct device *dev, uint32_t *rate) @@ -43,7 +43,7 @@ static inline int z_vrfy_can_get_core_clock(const struct device *dev, return z_impl_can_get_core_clock(dev, rate); } -#include +#include static inline uint32_t z_vrfy_can_get_bitrate_min(const struct device *dev) { @@ -51,7 +51,7 @@ static inline uint32_t z_vrfy_can_get_bitrate_min(const struct device *dev) return z_impl_can_get_bitrate_min(dev); } -#include +#include static inline uint32_t z_vrfy_can_get_bitrate_max(const struct device *dev) { @@ -59,7 +59,7 @@ static inline uint32_t z_vrfy_can_get_bitrate_max(const struct device *dev) return z_impl_can_get_bitrate_max(dev); } -#include +#include static inline const struct can_timing *z_vrfy_can_get_timing_min(const struct device *dev) { @@ -67,7 +67,7 @@ static inline const struct can_timing *z_vrfy_can_get_timing_min(const struct de return z_impl_can_get_timing_min(dev); } -#include +#include static inline const struct can_timing *z_vrfy_can_get_timing_max(const struct device *dev) { @@ -75,7 +75,7 @@ static inline const struct can_timing *z_vrfy_can_get_timing_max(const struct de return z_impl_can_get_timing_max(dev); } -#include +#include #ifdef CONFIG_CAN_FD_MODE @@ -93,7 +93,7 @@ static int z_vrfy_can_calc_timing_data(const struct device *dev, struct can_timi return err; } -#include +#include static inline const struct can_timing *z_vrfy_can_get_timing_data_min(const struct device *dev) { @@ -101,7 +101,7 @@ static inline const struct can_timing *z_vrfy_can_get_timing_data_min(const stru return z_impl_can_get_timing_data_min(dev); } -#include +#include static inline const struct can_timing *z_vrfy_can_get_timing_data_max(const struct device *dev) { @@ -109,7 +109,7 @@ static inline const struct can_timing *z_vrfy_can_get_timing_data_max(const stru return z_impl_can_get_timing_data_max(dev); } -#include +#include static inline int z_vrfy_can_set_timing_data(const struct device *dev, const struct can_timing *timing_data) @@ -121,7 +121,7 @@ static inline int z_vrfy_can_set_timing_data(const struct device *dev, return z_impl_can_set_timing_data(dev, &timing_data_copy); } -#include +#include static inline int z_vrfy_can_set_bitrate_data(const struct device *dev, uint32_t bitrate_data) @@ -130,7 +130,7 @@ static inline int z_vrfy_can_set_bitrate_data(const struct device *dev, return z_impl_can_set_bitrate_data(dev, bitrate_data); } -#include +#include #endif /* CONFIG_CAN_FD_MODE */ @@ -141,7 +141,7 @@ static inline int z_vrfy_can_get_max_filters(const struct device *dev, bool ide) return z_impl_can_get_max_filters(dev, ide); } -#include +#include static inline int z_vrfy_can_get_capabilities(const struct device *dev, can_mode_t *cap) { @@ -150,7 +150,7 @@ static inline int z_vrfy_can_get_capabilities(const struct device *dev, can_mode return z_impl_can_get_capabilities(dev, cap); } -#include +#include static inline const struct device *z_vrfy_can_get_transceiver(const struct device *dev) { @@ -158,7 +158,7 @@ static inline const struct device *z_vrfy_can_get_transceiver(const struct devic return z_impl_can_get_transceiver(dev); } -#include +#include static inline int z_vrfy_can_start(const struct device *dev) { @@ -166,7 +166,7 @@ static inline int z_vrfy_can_start(const struct device *dev) return z_impl_can_start(dev); } -#include +#include static inline int z_vrfy_can_stop(const struct device *dev) { @@ -174,7 +174,7 @@ static inline int z_vrfy_can_stop(const struct device *dev) return z_impl_can_stop(dev); } -#include +#include static inline int z_vrfy_can_set_mode(const struct device *dev, can_mode_t mode) { @@ -182,7 +182,7 @@ static inline int z_vrfy_can_set_mode(const struct device *dev, can_mode_t mode) return z_impl_can_set_mode(dev, mode); } -#include +#include static inline can_mode_t z_vrfy_can_get_mode(const struct device *dev) { @@ -190,7 +190,7 @@ static inline can_mode_t z_vrfy_can_get_mode(const struct device *dev) return z_impl_can_get_mode(dev); } -#include +#include static inline int z_vrfy_can_set_bitrate(const struct device *dev, uint32_t bitrate) { @@ -198,7 +198,7 @@ static inline int z_vrfy_can_set_bitrate(const struct device *dev, uint32_t bitr return z_impl_can_set_bitrate(dev, bitrate); } -#include +#include static inline int z_vrfy_can_send(const struct device *dev, const struct can_frame *frame, @@ -214,7 +214,7 @@ static inline int z_vrfy_can_send(const struct device *dev, return z_impl_can_send(dev, &frame_copy, timeout, callback, user_data); } -#include +#include static inline int z_vrfy_can_add_rx_filter_msgq(const struct device *dev, struct k_msgq *msgq, @@ -228,7 +228,7 @@ static inline int z_vrfy_can_add_rx_filter_msgq(const struct device *dev, return z_impl_can_add_rx_filter_msgq(dev, msgq, &filter_copy); } -#include +#include static inline void z_vrfy_can_remove_rx_filter(const struct device *dev, int filter_id) { @@ -236,7 +236,7 @@ static inline void z_vrfy_can_remove_rx_filter(const struct device *dev, int fil z_impl_can_remove_rx_filter(dev, filter_id); } -#include +#include static inline int z_vrfy_can_get_state(const struct device *dev, enum can_state *state, struct can_bus_err_cnt *err_cnt) @@ -253,7 +253,7 @@ static inline int z_vrfy_can_get_state(const struct device *dev, enum can_state return z_impl_can_get_state(dev, state, err_cnt); } -#include +#include #ifdef CONFIG_CAN_MANUAL_RECOVERY_MODE static inline int z_vrfy_can_recover(const struct device *dev, k_timeout_t timeout) @@ -263,7 +263,7 @@ static inline int z_vrfy_can_recover(const struct device *dev, k_timeout_t timeo return z_impl_can_recover(dev, timeout); } -#include +#include #endif /* CONFIG_CAN_MANUAL_RECOVERY_MODE */ #ifdef CONFIG_CAN_STATS @@ -274,7 +274,7 @@ static inline uint32_t z_vrfy_can_stats_get_bit_errors(const struct device *dev) return z_impl_can_stats_get_bit_errors(dev); } -#include +#include static inline uint32_t z_vrfy_can_stats_get_bit0_errors(const struct device *dev) { @@ -282,7 +282,7 @@ static inline uint32_t z_vrfy_can_stats_get_bit0_errors(const struct device *dev return z_impl_can_stats_get_bit0_errors(dev); } -#include +#include static inline uint32_t z_vrfy_can_stats_get_bit1_errors(const struct device *dev) { @@ -290,7 +290,7 @@ static inline uint32_t z_vrfy_can_stats_get_bit1_errors(const struct device *dev return z_impl_can_stats_get_bit1_errors(dev); } -#include +#include static inline uint32_t z_vrfy_can_stats_get_stuff_errors(const struct device *dev) { @@ -298,7 +298,7 @@ static inline uint32_t z_vrfy_can_stats_get_stuff_errors(const struct device *de return z_impl_can_stats_get_stuff_errors(dev); } -#include +#include static inline uint32_t z_vrfy_can_stats_get_crc_errors(const struct device *dev) { @@ -306,7 +306,7 @@ static inline uint32_t z_vrfy_can_stats_get_crc_errors(const struct device *dev) return z_impl_can_stats_get_crc_errors(dev); } -#include +#include static inline uint32_t z_vrfy_can_stats_get_form_errors(const struct device *dev) { @@ -314,7 +314,7 @@ static inline uint32_t z_vrfy_can_stats_get_form_errors(const struct device *dev return z_impl_can_stats_get_form_errors(dev); } -#include +#include static inline uint32_t z_vrfy_can_stats_get_ack_errors(const struct device *dev) { @@ -322,7 +322,7 @@ static inline uint32_t z_vrfy_can_stats_get_ack_errors(const struct device *dev) return z_impl_can_stats_get_ack_errors(dev); } -#include +#include static inline uint32_t z_vrfy_can_stats_get_rx_overruns(const struct device *dev) { @@ -330,6 +330,6 @@ static inline uint32_t z_vrfy_can_stats_get_rx_overruns(const struct device *dev return z_impl_can_stats_get_rx_overruns(dev); } -#include +#include #endif /* CONFIG_CAN_STATS */ diff --git a/drivers/charger/charger_handlers.c b/drivers/charger/charger_handlers.c index 4fdf6ca7140e5..44042b3fdd916 100644 --- a/drivers/charger/charger_handlers.c +++ b/drivers/charger/charger_handlers.c @@ -21,7 +21,7 @@ static inline int z_vrfy_charger_get_prop(const struct device *dev, const charge return ret; } -#include +#include static inline int z_vrfy_charger_set_prop(const struct device *dev, const charger_prop_t prop, const union charger_propval *val) @@ -35,7 +35,7 @@ static inline int z_vrfy_charger_set_prop(const struct device *dev, const charge return z_impl_charger_set_prop(dev, prop, &k_val); } -#include +#include static inline int z_vrfy_charger_charge_enable(const struct device *dev, const bool enable) { @@ -44,4 +44,4 @@ static inline int z_vrfy_charger_charge_enable(const struct device *dev, const b return z_impl_charger_charge_enable(dev, enable); } -#include +#include diff --git a/drivers/console/uart_mux.c b/drivers/console/uart_mux.c index 8ade93ef0bbaa..f42b1c3a3054b 100644 --- a/drivers/console/uart_mux.c +++ b/drivers/console/uart_mux.c @@ -739,7 +739,7 @@ static inline const struct device *z_vrfy_uart_mux_find(int dlci_address) { return z_impl_uart_mux_find(dlci_address); } -#include +#include #endif /* CONFIG_USERSPACE */ const struct device *z_impl_uart_mux_find(int dlci_address) diff --git a/drivers/counter/counter_handlers.c b/drivers/counter/counter_handlers.c index 15cd0cb588163..df2a20562a360 100644 --- a/drivers/counter/counter_handlers.c +++ b/drivers/counter/counter_handlers.c @@ -21,30 +21,30 @@ COUNTER_HANDLER(get_pending_int) COUNTER_HANDLER(stop) COUNTER_HANDLER(start) -#include -#include -#include +#include +#include +#include static inline bool z_vrfy_counter_is_counting_up(const struct device *dev) { K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_COUNTER)); return z_impl_counter_is_counting_up((const struct device *)dev); } -#include +#include static inline uint8_t z_vrfy_counter_get_num_of_channels(const struct device *dev) { K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_COUNTER)); return z_impl_counter_get_num_of_channels((const struct device *)dev); } -#include +#include static inline uint32_t z_vrfy_counter_get_frequency(const struct device *dev) { K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_COUNTER)); return z_impl_counter_get_frequency((const struct device *)dev); } -#include +#include static inline uint32_t z_vrfy_counter_us_to_ticks(const struct device *dev, uint64_t us) @@ -53,7 +53,7 @@ static inline uint32_t z_vrfy_counter_us_to_ticks(const struct device *dev, return z_impl_counter_us_to_ticks((const struct device *)dev, (uint64_t)us); } -#include +#include static inline uint64_t z_vrfy_counter_ticks_to_us(const struct device *dev, uint32_t ticks) @@ -62,7 +62,7 @@ static inline uint64_t z_vrfy_counter_ticks_to_us(const struct device *dev, return z_impl_counter_ticks_to_us((const struct device *)dev, (uint32_t)ticks); } -#include +#include static inline int z_vrfy_counter_get_value(const struct device *dev, uint32_t *ticks) @@ -80,7 +80,7 @@ static inline int z_vrfy_counter_get_value_64(const struct device *dev, return z_impl_counter_get_value_64((const struct device *)dev, ticks); } -#include +#include static inline int z_vrfy_counter_set_channel_alarm(const struct device *dev, uint8_t chan_id, @@ -97,7 +97,7 @@ static inline int z_vrfy_counter_set_channel_alarm(const struct device *dev, (const struct counter_alarm_cfg *)&cfg_copy); } -#include +#include static inline int z_vrfy_counter_cancel_channel_alarm(const struct device *dev, uint8_t chan_id) @@ -106,7 +106,7 @@ static inline int z_vrfy_counter_cancel_channel_alarm(const struct device *dev, return z_impl_counter_cancel_channel_alarm((const struct device *)dev, (uint8_t)chan_id); } -#include +#include static inline int z_vrfy_counter_set_top_value(const struct device *dev, const struct counter_top_cfg @@ -122,21 +122,21 @@ static inline int z_vrfy_counter_set_top_value(const struct device *dev, (const struct counter_top_cfg *) &cfg_copy); } -#include +#include static inline uint32_t z_vrfy_counter_get_top_value(const struct device *dev) { K_OOPS(K_SYSCALL_DRIVER_COUNTER(dev, get_top_value)); return z_impl_counter_get_top_value((const struct device *)dev); } -#include +#include static inline uint32_t z_vrfy_counter_get_max_top_value(const struct device *dev) { K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_COUNTER)); return z_impl_counter_get_max_top_value((const struct device *)dev); } -#include +#include static inline uint32_t z_vrfy_counter_get_guard_period(const struct device *dev, uint32_t flags) @@ -145,7 +145,7 @@ static inline uint32_t z_vrfy_counter_get_guard_period(const struct device *dev, return z_impl_counter_get_guard_period((const struct device *)dev, flags); } -#include +#include static inline int z_vrfy_counter_set_guard_period(const struct device *dev, uint32_t ticks, uint32_t flags) @@ -155,4 +155,4 @@ static inline int z_vrfy_counter_set_guard_period(const struct device *dev, ticks, flags); } -#include +#include diff --git a/drivers/counter/maxim_ds3231.c b/drivers/counter/maxim_ds3231.c index c6b8e08b79c71..146be21762a75 100644 --- a/drivers/counter/maxim_ds3231.c +++ b/drivers/counter/maxim_ds3231.c @@ -1321,7 +1321,7 @@ int z_vrfy_maxim_ds3231_get_syncpoint(const struct device *dev, return rv; } -#include +#include int z_vrfy_maxim_ds3231_req_syncpoint(const struct device *dev, struct k_poll_signal *sig) @@ -1334,6 +1334,6 @@ int z_vrfy_maxim_ds3231_req_syncpoint(const struct device *dev, return z_impl_maxim_ds3231_req_syncpoint(dev, sig); } -#include +#include #endif /* CONFIG_USERSPACE */ diff --git a/drivers/dac/dac_handlers.c b/drivers/dac/dac_handlers.c index bd9ee0bc7e0d6..36557ad208e3d 100644 --- a/drivers/dac/dac_handlers.c +++ b/drivers/dac/dac_handlers.c @@ -21,7 +21,7 @@ static inline int z_vrfy_dac_channel_setup(const struct device *dev, return z_impl_dac_channel_setup((const struct device *)dev, &channel_cfg); } -#include +#include static inline int z_vrfy_dac_write_value(const struct device *dev, uint8_t channel, uint32_t value) @@ -31,4 +31,4 @@ static inline int z_vrfy_dac_write_value(const struct device *dev, return z_impl_dac_write_value((const struct device *)dev, channel, value); } -#include +#include diff --git a/drivers/dma/dma_handlers.c b/drivers/dma/dma_handlers.c index d84c151015219..9ebce367482ea 100644 --- a/drivers/dma/dma_handlers.c +++ b/drivers/dma/dma_handlers.c @@ -16,11 +16,11 @@ static inline int z_vrfy_dma_start(const struct device *dev, uint32_t channel) K_OOPS(K_SYSCALL_DRIVER_DMA(dev, start)); return z_impl_dma_start((const struct device *)dev, channel); } -#include +#include static inline int z_vrfy_dma_stop(const struct device *dev, uint32_t channel) { K_OOPS(K_SYSCALL_DRIVER_DMA(dev, stop)); return z_impl_dma_stop((const struct device *)dev, channel); } -#include +#include diff --git a/drivers/eeprom/eeprom_handlers.c b/drivers/eeprom/eeprom_handlers.c index 9b1406a60043a..94a3d4f473ed0 100644 --- a/drivers/eeprom/eeprom_handlers.c +++ b/drivers/eeprom/eeprom_handlers.c @@ -16,7 +16,7 @@ static inline int z_vrfy_eeprom_read(const struct device *dev, off_t offset, (void *)data, len); } -#include +#include static inline int z_vrfy_eeprom_write(const struct device *dev, off_t offset, const void *data, size_t len) @@ -26,11 +26,11 @@ static inline int z_vrfy_eeprom_write(const struct device *dev, off_t offset, return z_impl_eeprom_write((const struct device *)dev, offset, (const void *)data, len); } -#include +#include static inline size_t z_vrfy_eeprom_get_size(const struct device *dev) { K_OOPS(K_SYSCALL_DRIVER_EEPROM(dev, size)); return z_impl_eeprom_get_size((const struct device *)dev); } -#include +#include diff --git a/drivers/entropy/entropy_handlers.c b/drivers/entropy/entropy_handlers.c index 76b7df3d0bd70..643aa77c16ad4 100644 --- a/drivers/entropy/entropy_handlers.c +++ b/drivers/entropy/entropy_handlers.c @@ -17,4 +17,4 @@ static inline int z_vrfy_entropy_get_entropy(const struct device *dev, (uint8_t *)buffer, len); } -#include +#include diff --git a/drivers/espi/espi_handlers.c b/drivers/espi/espi_handlers.c index c215838fd7951..703300adc6a44 100644 --- a/drivers/espi/espi_handlers.c +++ b/drivers/espi/espi_handlers.c @@ -19,7 +19,7 @@ static inline int z_vrfy_espi_config(const struct device *dev, return z_impl_espi_config(dev, &cfg_copy); } -#include +#include static inline bool z_vrfy_espi_get_channel_status(const struct device *dev, enum espi_channel ch) @@ -28,7 +28,7 @@ static inline bool z_vrfy_espi_get_channel_status(const struct device *dev, return z_impl_espi_get_channel_status(dev, ch); } -#include +#include static inline int z_vrfy_espi_read_lpc_request(const struct device *dev, enum lpc_peripheral_opcode op, @@ -44,7 +44,7 @@ static inline int z_vrfy_espi_read_lpc_request(const struct device *dev, return ret; } -#include +#include static inline int z_vrfy_espi_write_lpc_request(const struct device *dev, enum lpc_peripheral_opcode op, @@ -57,7 +57,7 @@ static inline int z_vrfy_espi_write_lpc_request(const struct device *dev, return z_impl_espi_write_lpc_request(dev, op, &data_copy); } -#include +#include static inline int z_vrfy_espi_send_vwire(const struct device *dev, enum espi_vwire_signal signal, @@ -67,7 +67,7 @@ static inline int z_vrfy_espi_send_vwire(const struct device *dev, return z_impl_espi_send_vwire(dev, signal, level); } -#include +#include static inline int z_vrfy_espi_receive_vwire(const struct device *dev, enum espi_vwire_signal signal, @@ -83,7 +83,7 @@ static inline int z_vrfy_espi_receive_vwire(const struct device *dev, return ret; } -#include +#include static inline int z_vrfy_espi_read_request(const struct device *dev, struct espi_request_packet *req) @@ -103,7 +103,7 @@ static inline int z_vrfy_espi_read_request(const struct device *dev, return ret; } -#include +#include static inline int z_vrfy_espi_write_request(const struct device *dev, struct espi_request_packet *req) @@ -120,7 +120,7 @@ static inline int z_vrfy_espi_write_request(const struct device *dev, return ret; } -#include +#include static inline int z_vrfy_espi_send_oob(const struct device *dev, struct espi_oob_packet *pckt) @@ -137,7 +137,7 @@ static inline int z_vrfy_espi_send_oob(const struct device *dev, return ret; } -#include +#include static inline int z_vrfy_espi_receive_oob(const struct device *dev, struct espi_oob_packet *pckt) @@ -156,7 +156,7 @@ static inline int z_vrfy_espi_receive_oob(const struct device *dev, return ret; } -#include +#include static inline int z_vrfy_espi_read_flash(const struct device *dev, struct espi_flash_packet *pckt) @@ -175,7 +175,7 @@ static inline int z_vrfy_espi_read_flash(const struct device *dev, return ret; } -#include +#include static inline int z_vrfy_espi_write_flash(const struct device *dev, struct espi_flash_packet *pckt) @@ -192,7 +192,7 @@ static inline int z_vrfy_espi_write_flash(const struct device *dev, return ret; } -#include +#include static inline int z_vrfy_espi_flash_erase(const struct device *dev, struct espi_flash_packet *pckt) @@ -209,4 +209,4 @@ static inline int z_vrfy_espi_flash_erase(const struct device *dev, return ret; } -#include +#include diff --git a/drivers/flash/flash_handlers.c b/drivers/flash/flash_handlers.c index 8c047adbaf4a6..6e47b10dbd383 100644 --- a/drivers/flash/flash_handlers.c +++ b/drivers/flash/flash_handlers.c @@ -16,7 +16,7 @@ static inline int z_vrfy_flash_read(const struct device *dev, off_t offset, (void *)data, len); } -#include +#include static inline int z_vrfy_flash_write(const struct device *dev, off_t offset, const void *data, size_t len) @@ -26,7 +26,7 @@ static inline int z_vrfy_flash_write(const struct device *dev, off_t offset, return z_impl_flash_write((const struct device *)dev, offset, (const void *)data, len); } -#include +#include static inline int z_vrfy_flash_erase(const struct device *dev, off_t offset, size_t size) @@ -34,21 +34,21 @@ static inline int z_vrfy_flash_erase(const struct device *dev, off_t offset, K_OOPS(K_SYSCALL_DRIVER_FLASH(dev, erase)); return z_impl_flash_erase((const struct device *)dev, offset, size); } -#include +#include static inline size_t z_vrfy_flash_get_write_block_size(const struct device *dev) { K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_FLASH)); return z_impl_flash_get_write_block_size(dev); } -#include +#include static inline const struct flash_parameters *z_vrfy_flash_get_parameters(const struct device *dev) { K_OOPS(K_SYSCALL_DRIVER_FLASH(dev, get_parameters)); return z_impl_flash_get_parameters(dev); } -#include +#include #ifdef CONFIG_FLASH_PAGE_LAYOUT static inline int z_vrfy_flash_get_page_info_by_offs(const struct device *dev, @@ -61,7 +61,7 @@ static inline int z_vrfy_flash_get_page_info_by_offs(const struct device *dev, offs, (struct flash_pages_info *)info); } -#include +#include static inline int z_vrfy_flash_get_page_info_by_idx(const struct device *dev, uint32_t idx, @@ -73,14 +73,14 @@ static inline int z_vrfy_flash_get_page_info_by_idx(const struct device *dev, idx, (struct flash_pages_info *)info); } -#include +#include static inline size_t z_vrfy_flash_get_page_count(const struct device *dev) { K_OOPS(K_SYSCALL_DRIVER_FLASH(dev, page_layout)); return z_impl_flash_get_page_count((const struct device *)dev); } -#include +#include #endif /* CONFIG_FLASH_PAGE_LAYOUT */ @@ -94,7 +94,7 @@ static inline int z_vrfy_flash_sfdp_read(const struct device *dev, K_OOPS(K_SYSCALL_MEMORY_WRITE(data, len)); return z_impl_flash_sfdp_read(dev, offset, data, len); } -#include +#include static inline int z_vrfy_flash_read_jedec_id(const struct device *dev, uint8_t *id) @@ -103,7 +103,7 @@ static inline int z_vrfy_flash_read_jedec_id(const struct device *dev, K_OOPS(K_SYSCALL_MEMORY_WRITE(id, 3)); return z_impl_flash_read_jedec_id(dev, id); } -#include +#include #endif /* CONFIG_FLASH_JESD216_API */ @@ -122,6 +122,6 @@ static inline int z_vrfy_flash_ex_op(const struct device *dev, uint16_t code, return z_impl_flash_ex_op(dev, code, in, out); } -#include +#include #endif /* CONFIG_FLASH_EX_OP_ENABLED */ diff --git a/drivers/flash/flash_simulator.c b/drivers/flash/flash_simulator.c index 12cd86078550c..effd53c1f2b30 100644 --- a/drivers/flash/flash_simulator.c +++ b/drivers/flash/flash_simulator.c @@ -491,6 +491,6 @@ void *z_vrfy_flash_simulator_get_memory(const struct device *dev, return z_impl_flash_simulator_get_memory(dev, mock_size); } -#include +#include #endif /* CONFIG_USERSPACE */ diff --git a/drivers/flash/nrf_qspi_nor.c b/drivers/flash/nrf_qspi_nor.c index b3a6fbb2ec1ff..81ccf123ce90d 100644 --- a/drivers/flash/nrf_qspi_nor.c +++ b/drivers/flash/nrf_qspi_nor.c @@ -1366,7 +1366,7 @@ void z_vrfy_nrf_qspi_nor_xip_enable(const struct device *dev, bool enable) z_impl_nrf_qspi_nor_xip_enable(dev, enable); } -#include +#include #endif /* CONFIG_USERSPACE */ static struct qspi_nor_data qspi_nor_dev_data = { diff --git a/drivers/fpga/fpga_shell.c b/drivers/fpga/fpga_shell.c index af1a28eb8e115..4afeba42ef97c 100644 --- a/drivers/fpga/fpga_shell.c +++ b/drivers/fpga/fpga_shell.c @@ -6,7 +6,7 @@ #include #include -#include +#include #include #include diff --git a/drivers/fuel_gauge/emul_fuel_gauge_syscall_handlers.c b/drivers/fuel_gauge/emul_fuel_gauge_syscall_handlers.c index 2382fcad77b40..538d93f84b6d3 100644 --- a/drivers/fuel_gauge/emul_fuel_gauge_syscall_handlers.c +++ b/drivers/fuel_gauge/emul_fuel_gauge_syscall_handlers.c @@ -14,7 +14,7 @@ static inline int z_vrfy_emul_fuel_gauge_is_battery_cutoff(const struct emul *ta return z_impl_emul_fuel_gauge_is_battery_cutoff(target, cutoff); } -#include +#include static inline int z_vrfy_emul_fuel_gauge_set_battery_charging(const struct emul *target, uint32_t uV, int uA) @@ -22,4 +22,4 @@ static inline int z_vrfy_emul_fuel_gauge_set_battery_charging(const struct emul return z_impl_emul_fuel_gauge_set_battery_charging(target, uV, uA); } -#include +#include diff --git a/drivers/fuel_gauge/fuel_gauge_syscall_handlers.c b/drivers/fuel_gauge/fuel_gauge_syscall_handlers.c index 312564c35a62f..75b93d3a53129 100644 --- a/drivers/fuel_gauge/fuel_gauge_syscall_handlers.c +++ b/drivers/fuel_gauge/fuel_gauge_syscall_handlers.c @@ -24,7 +24,7 @@ static inline int z_vrfy_fuel_gauge_get_prop(const struct device *dev, fuel_gaug return ret; } -#include +#include static inline int z_vrfy_fuel_gauge_get_props(const struct device *dev, fuel_gauge_prop_t *props, union fuel_gauge_prop_val *vals, size_t len) @@ -44,7 +44,7 @@ static inline int z_vrfy_fuel_gauge_get_props(const struct device *dev, fuel_gau return ret; } -#include +#include static inline int z_vrfy_fuel_gauge_set_prop(const struct device *dev, fuel_gauge_prop_t prop, union fuel_gauge_prop_val val) @@ -56,7 +56,7 @@ static inline int z_vrfy_fuel_gauge_set_prop(const struct device *dev, fuel_gaug return ret; } -#include +#include static inline int z_vrfy_fuel_gauge_set_props(const struct device *dev, fuel_gauge_prop_t *props, union fuel_gauge_prop_val *vals, size_t len) @@ -77,7 +77,7 @@ static inline int z_vrfy_fuel_gauge_set_props(const struct device *dev, fuel_gau return ret; } -#include +#include static inline int z_vrfy_fuel_gauge_get_buffer_prop(const struct device *dev, fuel_gauge_prop_t prop, void *dst, @@ -92,7 +92,7 @@ static inline int z_vrfy_fuel_gauge_get_buffer_prop(const struct device *dev, return ret; } -#include +#include static inline int z_vrfy_fuel_gauge_battery_cutoff(const struct device *dev) { @@ -101,4 +101,4 @@ static inline int z_vrfy_fuel_gauge_battery_cutoff(const struct device *dev) return z_impl_fuel_gauge_battery_cutoff(dev); } -#include +#include diff --git a/drivers/gpio/gpio_handlers.c b/drivers/gpio/gpio_handlers.c index 99fbc6f45d91c..405b54afeb333 100644 --- a/drivers/gpio/gpio_handlers.c +++ b/drivers/gpio/gpio_handlers.c @@ -16,7 +16,7 @@ static inline int z_vrfy_gpio_pin_configure(const struct device *port, pin, flags); } -#include +#include #ifdef CONFIG_GPIO_GET_CONFIG static inline int z_vrfy_gpio_pin_get_config(const struct device *port, @@ -28,7 +28,7 @@ static inline int z_vrfy_gpio_pin_get_config(const struct device *port, return z_impl_gpio_pin_get_config(port, pin, flags); } -#include +#include #endif static inline int z_vrfy_gpio_port_get_raw(const struct device *port, @@ -39,7 +39,7 @@ static inline int z_vrfy_gpio_port_get_raw(const struct device *port, return z_impl_gpio_port_get_raw((const struct device *)port, (gpio_port_value_t *)value); } -#include +#include static inline int z_vrfy_gpio_port_set_masked_raw(const struct device *port, gpio_port_pins_t mask, @@ -50,7 +50,7 @@ static inline int z_vrfy_gpio_port_set_masked_raw(const struct device *port, mask, value); } -#include +#include static inline int z_vrfy_gpio_port_set_bits_raw(const struct device *port, gpio_port_pins_t pins) @@ -59,7 +59,7 @@ static inline int z_vrfy_gpio_port_set_bits_raw(const struct device *port, return z_impl_gpio_port_set_bits_raw((const struct device *)port, pins); } -#include +#include static inline int z_vrfy_gpio_port_clear_bits_raw(const struct device *port, gpio_port_pins_t pins) @@ -68,7 +68,7 @@ static inline int z_vrfy_gpio_port_clear_bits_raw(const struct device *port, return z_impl_gpio_port_clear_bits_raw((const struct device *)port, pins); } -#include +#include static inline int z_vrfy_gpio_port_toggle_bits(const struct device *port, gpio_port_pins_t pins) @@ -76,7 +76,7 @@ static inline int z_vrfy_gpio_port_toggle_bits(const struct device *port, K_OOPS(K_SYSCALL_DRIVER_GPIO(port, port_toggle_bits)); return z_impl_gpio_port_toggle_bits((const struct device *)port, pins); } -#include +#include static inline int z_vrfy_gpio_pin_interrupt_configure(const struct device *port, gpio_pin_t pin, @@ -87,7 +87,7 @@ static inline int z_vrfy_gpio_pin_interrupt_configure(const struct device *port, pin, flags); } -#include +#include static inline int z_vrfy_gpio_get_pending_int(const struct device *dev) { @@ -95,7 +95,7 @@ static inline int z_vrfy_gpio_get_pending_int(const struct device *dev) return z_impl_gpio_get_pending_int((const struct device *)dev); } -#include +#include #ifdef CONFIG_GPIO_GET_DIRECTION static inline int z_vrfy_gpio_port_get_direction(const struct device *dev, gpio_port_pins_t map, @@ -114,5 +114,5 @@ static inline int z_vrfy_gpio_port_get_direction(const struct device *dev, gpio_ return z_impl_gpio_port_get_direction(dev, map, inputs, outputs); } -#include +#include #endif /* CONFIG_GPIO_GET_DIRECTION */ diff --git a/drivers/hwinfo/hwinfo_handlers.c b/drivers/hwinfo/hwinfo_handlers.c index a1eb9e2c830a9..fc39241ff3238 100644 --- a/drivers/hwinfo/hwinfo_handlers.c +++ b/drivers/hwinfo/hwinfo_handlers.c @@ -13,7 +13,7 @@ ssize_t z_vrfy_hwinfo_get_device_id(uint8_t *buffer, size_t length) return z_impl_hwinfo_get_device_id((uint8_t *)buffer, (size_t)length); } -#include +#include ssize_t z_vrfy_hwinfo_get_device_eui64(uint8_t *buffer) { @@ -21,7 +21,7 @@ ssize_t z_vrfy_hwinfo_get_device_eui64(uint8_t *buffer) return z_impl_hwinfo_get_device_eui64((uint8_t *)buffer); } -#include +#include int z_vrfy_hwinfo_get_reset_cause(uint32_t *cause) { @@ -33,14 +33,14 @@ int z_vrfy_hwinfo_get_reset_cause(uint32_t *cause) return ret; } -#include +#include int z_vrfy_hwinfo_clear_reset_cause(void) { return z_impl_hwinfo_clear_reset_cause(); } -#include +#include int z_vrfy_hwinfo_get_supported_reset_cause(uint32_t *supported) { @@ -52,4 +52,4 @@ int z_vrfy_hwinfo_get_supported_reset_cause(uint32_t *supported) return ret; } -#include +#include diff --git a/drivers/hwspinlock/hwspinlock_handlers.c b/drivers/hwspinlock/hwspinlock_handlers.c index 7064293be4bfe..dbb1a94f68ed9 100644 --- a/drivers/hwspinlock/hwspinlock_handlers.c +++ b/drivers/hwspinlock/hwspinlock_handlers.c @@ -13,7 +13,7 @@ static inline int z_vrfy_hwspinlock_trylock(const struct device *dev, uint32_t i return z_impl_hwspinlock_trylock(dev, id); } -#include +#include static inline void z_vrfy_hwspinlock_lock(const struct device *dev, uint32_t id) { @@ -21,7 +21,7 @@ static inline void z_vrfy_hwspinlock_lock(const struct device *dev, uint32_t id) z_impl_hwspinlock_lock(dev, id); } -#include +#include static inline void z_vrfy_hwspinlock_unlock(const struct device *dev, uint32_t id) { @@ -29,7 +29,7 @@ static inline void z_vrfy_hwspinlock_unlock(const struct device *dev, uint32_t i z_impl_hwspinlock_unlock(dev, id); } -#include +#include static inline uint32_t z_vrfy_hwspinlock_get_max_id(const struct device *dev) { @@ -37,4 +37,4 @@ static inline uint32_t z_vrfy_hwspinlock_get_max_id(const struct device *dev) return z_impl_hwspinlock_get_max_id(dev); } -#include +#include diff --git a/drivers/i2c/i2c_handlers.c b/drivers/i2c/i2c_handlers.c index 20ec2a6f5788c..e5b87bc2d4cdd 100644 --- a/drivers/i2c/i2c_handlers.c +++ b/drivers/i2c/i2c_handlers.c @@ -14,7 +14,7 @@ static inline int z_vrfy_i2c_configure(const struct device *dev, K_OOPS(K_SYSCALL_DRIVER_I2C(dev, configure)); return z_impl_i2c_configure((const struct device *)dev, dev_config); } -#include +#include static inline int z_vrfy_i2c_get_config(const struct device *dev, uint32_t *dev_config) @@ -24,7 +24,7 @@ static inline int z_vrfy_i2c_get_config(const struct device *dev, return z_impl_i2c_get_config(dev, dev_config); } -#include +#include static uint32_t copy_msgs_and_transfer(const struct device *dev, const struct i2c_msg *msgs, @@ -69,25 +69,25 @@ static inline int z_vrfy_i2c_transfer(const struct device *dev, (struct i2c_msg *)msgs, (uint8_t)num_msgs, (uint16_t)addr); } -#include +#include static inline int z_vrfy_i2c_target_driver_register(const struct device *dev) { K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_I2C)); return z_impl_i2c_target_driver_register(dev); } -#include +#include static inline int z_vrfy_i2c_target_driver_unregister(const struct device *dev) { K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_I2C)); return z_impl_i2c_target_driver_unregister(dev); } -#include +#include static inline int z_vrfy_i2c_recover_bus(const struct device *dev) { K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_I2C)); return z_impl_i2c_recover_bus(dev); } -#include +#include diff --git a/drivers/i2s/i2s_handlers.c b/drivers/i2s/i2s_handlers.c index 0ef1f6e6cd554..3f1c31a46c7aa 100644 --- a/drivers/i2s/i2s_handlers.c +++ b/drivers/i2s/i2s_handlers.c @@ -41,7 +41,7 @@ static inline int z_vrfy_i2s_configure(const struct device *dev, out: return ret; } -#include +#include static inline int z_vrfy_i2s_buf_read(const struct device *dev, void *buf, size_t *size) @@ -74,7 +74,7 @@ static inline int z_vrfy_i2s_buf_read(const struct device *dev, return ret; } -#include +#include static inline int z_vrfy_i2s_buf_write(const struct device *dev, void *buf, size_t size) @@ -111,7 +111,7 @@ static inline int z_vrfy_i2s_buf_write(const struct device *dev, return ret; } -#include +#include static inline int z_vrfy_i2s_trigger(const struct device *dev, enum i2s_dir dir, @@ -121,4 +121,4 @@ static inline int z_vrfy_i2s_trigger(const struct device *dev, return z_impl_i2s_trigger((const struct device *)dev, dir, cmd); } -#include +#include diff --git a/drivers/i3c/i3c_handlers.c b/drivers/i3c/i3c_handlers.c index a5d218992a332..99708eb7a83b2 100644 --- a/drivers/i3c/i3c_handlers.c +++ b/drivers/i3c/i3c_handlers.c @@ -35,7 +35,7 @@ static inline int z_vrfy_i3c_do_ccc(const struct device *dev, return z_impl_i3c_do_ccc(dev, payload); } -#include +#include static uint32_t copy_i3c_msgs_and_transfer(struct i3c_device_desc *target, const struct i3c_msg *msgs, @@ -79,4 +79,4 @@ static inline int z_vrfy_i3c_transfer(struct i3c_device_desc *target, (struct i3c_msg *)msgs, (uint8_t)num_msgs); } -#include +#include diff --git a/drivers/ipm/ipm_handlers.c b/drivers/ipm/ipm_handlers.c index 259644ae8d0e6..f049a090f1ee6 100644 --- a/drivers/ipm/ipm_handlers.c +++ b/drivers/ipm/ipm_handlers.c @@ -16,25 +16,25 @@ static inline int z_vrfy_ipm_send(const struct device *dev, int wait, return z_impl_ipm_send((const struct device *)dev, wait, id, (const void *)data, size); } -#include +#include static inline int z_vrfy_ipm_max_data_size_get(const struct device *dev) { K_OOPS(K_SYSCALL_DRIVER_IPM(dev, max_data_size_get)); return z_impl_ipm_max_data_size_get((const struct device *)dev); } -#include +#include static inline uint32_t z_vrfy_ipm_max_id_val_get(const struct device *dev) { K_OOPS(K_SYSCALL_DRIVER_IPM(dev, max_id_val_get)); return z_impl_ipm_max_id_val_get((const struct device *)dev); } -#include +#include static inline int z_vrfy_ipm_set_enabled(const struct device *dev, int enable) { K_OOPS(K_SYSCALL_DRIVER_IPM(dev, set_enabled)); return z_impl_ipm_set_enabled((const struct device *)dev, enable); } -#include +#include diff --git a/drivers/kscan/kscan_handlers.c b/drivers/kscan/kscan_handlers.c index 98809687430a8..81c97c19d04f7 100644 --- a/drivers/kscan/kscan_handlers.c +++ b/drivers/kscan/kscan_handlers.c @@ -15,7 +15,7 @@ static inline int z_vrfy_kscan_config(const struct device *dev, "callback cannot be set from user mode")); return z_impl_kscan_config((const struct device *)dev, callback_isr); } -#include +#include static inline int z_vrfy_kscan_disable_callback(const struct device *dev) { @@ -23,7 +23,7 @@ static inline int z_vrfy_kscan_disable_callback(const struct device *dev) return z_impl_kscan_disable_callback((const struct device *)dev); } -#include +#include static int z_vrfy_kscan_enable_callback(const struct device *dev) { @@ -31,4 +31,4 @@ static int z_vrfy_kscan_enable_callback(const struct device *dev) return z_impl_kscan_enable_callback((const struct device *)dev); } -#include +#include diff --git a/drivers/led/led_handlers.c b/drivers/led/led_handlers.c index a089846e6951e..5fde5e53c1b0d 100644 --- a/drivers/led/led_handlers.c +++ b/drivers/led/led_handlers.c @@ -14,7 +14,7 @@ static inline int z_vrfy_led_blink(const struct device *dev, uint32_t led, return z_impl_led_blink((const struct device *)dev, led, delay_on, delay_off); } -#include +#include static inline int z_vrfy_led_get_info(const struct device *dev, uint32_t led, const struct led_info **info) @@ -23,7 +23,7 @@ static inline int z_vrfy_led_get_info(const struct device *dev, uint32_t led, K_OOPS(K_SYSCALL_MEMORY_WRITE(info, sizeof(*info))); return z_impl_led_get_info(dev, led, info); } -#include +#include static inline int z_vrfy_led_set_brightness(const struct device *dev, uint32_t led, @@ -33,7 +33,7 @@ static inline int z_vrfy_led_set_brightness(const struct device *dev, return z_impl_led_set_brightness((const struct device *)dev, led, value); } -#include +#include static inline int z_vrfy_led_write_channels(const struct device *dev, uint32_t start_channel, @@ -43,7 +43,7 @@ z_vrfy_led_write_channels(const struct device *dev, uint32_t start_channel, K_OOPS(K_SYSCALL_MEMORY_READ(buf, num_channels)); return z_impl_led_write_channels(dev, start_channel, num_channels, buf); } -#include +#include static inline int z_vrfy_led_set_channel(const struct device *dev, uint32_t channel, uint8_t value) @@ -51,7 +51,7 @@ static inline int z_vrfy_led_set_channel(const struct device *dev, K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_LED)); return z_impl_led_set_channel(dev, channel, value); } -#include +#include static inline int z_vrfy_led_set_color(const struct device *dev, uint32_t led, uint8_t num_colors, const uint8_t *color) @@ -60,18 +60,18 @@ static inline int z_vrfy_led_set_color(const struct device *dev, uint32_t led, K_OOPS(K_SYSCALL_MEMORY_READ(color, num_colors)); return z_impl_led_set_color(dev, led, num_colors, color); } -#include +#include static inline int z_vrfy_led_on(const struct device *dev, uint32_t led) { K_OOPS(K_SYSCALL_DRIVER_LED(dev, on)); return z_impl_led_on((const struct device *)dev, led); } -#include +#include static inline int z_vrfy_led_off(const struct device *dev, uint32_t led) { K_OOPS(K_SYSCALL_DRIVER_LED(dev, off)); return z_impl_led_off((const struct device *)dev, led); } -#include +#include diff --git a/drivers/mbox/mbox_handlers.c b/drivers/mbox/mbox_handlers.c index 2340ab016b5b6..aca4fb9b38200 100644 --- a/drivers/mbox/mbox_handlers.c +++ b/drivers/mbox/mbox_handlers.c @@ -17,7 +17,7 @@ static inline int z_vrfy_mbox_send(const struct device *dev, return z_impl_mbox_send(dev, channel_id, msg); } -#include +#include static inline int z_vrfy_mbox_mtu_get(const struct device *dev) { @@ -25,7 +25,7 @@ static inline int z_vrfy_mbox_mtu_get(const struct device *dev) return z_impl_mbox_mtu_get(dev); } -#include +#include static inline uint32_t z_vrfy_mbox_max_channels_get(const struct device *dev) { @@ -33,7 +33,7 @@ static inline uint32_t z_vrfy_mbox_max_channels_get(const struct device *dev) return z_impl_mbox_max_channels_get(dev); } -#include +#include static inline int z_vrfy_mbox_set_enabled(const struct device *dev, mbox_channel_id_t channel_id, @@ -43,4 +43,4 @@ static inline int z_vrfy_mbox_set_enabled(const struct device *dev, return z_impl_mbox_set_enabled(dev, channel_id, enabled); } -#include +#include diff --git a/drivers/misc/devmux/devmux.c b/drivers/misc/devmux/devmux.c index 653236f903dea..675b635b5d081 100644 --- a/drivers/misc/devmux/devmux.c +++ b/drivers/misc/devmux/devmux.c @@ -94,7 +94,7 @@ ssize_t z_vrfy_devmux_select_get(const struct device *dev) { return z_impl_devmux_select_get(dev); } -#include +#include #endif int z_impl_devmux_select_set(struct device *dev, size_t index) @@ -124,7 +124,7 @@ int z_vrfy_devmux_select_set(struct device *dev, size_t index) { return z_impl_devmux_select_set(dev, index); } -#include +#include #endif static int devmux_init(struct device *const dev) diff --git a/drivers/misc/timeaware_gpio/timeaware_gpio_handlers.c b/drivers/misc/timeaware_gpio/timeaware_gpio_handlers.c index 1904db4218dad..0745db600a206 100644 --- a/drivers/misc/timeaware_gpio/timeaware_gpio_handlers.c +++ b/drivers/misc/timeaware_gpio/timeaware_gpio_handlers.c @@ -12,7 +12,7 @@ static inline int z_vrfy_tgpio_port_get_time(const struct device *port, uint64_t K_OOPS(Z_SYSCALL_MEMORY_WRITE(current_time, sizeof(uint64_t))); return z_impl_tgpio_port_get_time((const struct device *)port, (uint64_t *)current_time); } -#include +#include static inline int z_vrfy_tgpio_port_get_cycles_per_second(const struct device *port, uint32_t *cycles) @@ -22,7 +22,7 @@ static inline int z_vrfy_tgpio_port_get_cycles_per_second(const struct device *p return z_impl_tgpio_port_get_cycles_per_second((const struct device *)port, (uint32_t *)cycles); } -#include +#include static inline int z_vrfy_tgpio_pin_periodic_output(const struct device *port, uint32_t pin, uint64_t start_time, uint64_t repeat_interval, @@ -32,14 +32,14 @@ static inline int z_vrfy_tgpio_pin_periodic_output(const struct device *port, ui return z_impl_tgpio_pin_periodic_output((const struct device *)port, pin, start_time, repeat_interval, periodic_enable); } -#include +#include static inline int z_vrfy_tgpio_pin_disable(const struct device *port, uint32_t pin) { K_OOPS(Z_SYSCALL_DRIVER_TGPIO(port, pin_disable)); return z_impl_tgpio_pin_disable((const struct device *)port, pin); } -#include +#include static inline int z_vrfy_tgpio_pin_config_ext_timestamp(const struct device *port, uint32_t pin, uint32_t event_polarity) @@ -48,7 +48,7 @@ static inline int z_vrfy_tgpio_pin_config_ext_timestamp(const struct device *por return z_impl_tgpio_pin_config_ext_timestamp((const struct device *)port, pin, event_polarity); } -#include +#include static inline int z_vrfy_tgpio_pin_read_ts_ec(const struct device *port, uint32_t pin, uint64_t *timestamp, uint64_t *event_count) @@ -57,4 +57,4 @@ static inline int z_vrfy_tgpio_pin_read_ts_ec(const struct device *port, uint32_ return z_impl_tgpio_pin_read_ts_ec((const struct device *)port, pin, (uint64_t *)timestamp, (uint64_t *)event_count); } -#include +#include diff --git a/drivers/peci/peci_handlers.c b/drivers/peci/peci_handlers.c index 64947a8743d9f..c0f532a24cc09 100644 --- a/drivers/peci/peci_handlers.c +++ b/drivers/peci/peci_handlers.c @@ -15,7 +15,7 @@ static inline int z_vrfy_peci_config(const struct device *dev, return z_impl_peci_config(dev, bitrate); } -#include +#include static inline int z_vrfy_peci_enable(const struct device *dev) { @@ -23,7 +23,7 @@ static inline int z_vrfy_peci_enable(const struct device *dev) return z_impl_peci_enable(dev); } -#include +#include static inline int z_vrfy_peci_disable(const struct device *dev) { @@ -31,7 +31,7 @@ static inline int z_vrfy_peci_disable(const struct device *dev) return z_impl_peci_disable(dev); } -#include +#include static inline int z_vrfy_peci_transfer(const struct device *dev, struct peci_msg *msg) @@ -43,4 +43,4 @@ static inline int z_vrfy_peci_transfer(const struct device *dev, return z_impl_peci_transfer(dev, &msg_copy); } -#include +#include diff --git a/drivers/ps2/ps2_handlers.c b/drivers/ps2/ps2_handlers.c index 91835e85ea555..db93d93b8bbfb 100644 --- a/drivers/ps2/ps2_handlers.c +++ b/drivers/ps2/ps2_handlers.c @@ -15,14 +15,14 @@ static inline int z_vrfy_ps2_config(const struct device *dev, "callback not be set from user mode")); return z_impl_ps2_config(dev, callback_isr); } -#include +#include static inline int z_vrfy_ps2_write(const struct device *dev, uint8_t value) { K_OOPS(K_SYSCALL_DRIVER_PS2(dev, write)); return z_impl_ps2_write(dev, value); } -#include +#include static inline int z_vrfy_ps2_read(const struct device *dev, uint8_t *value) { @@ -30,18 +30,18 @@ static inline int z_vrfy_ps2_read(const struct device *dev, uint8_t *value) K_OOPS(K_SYSCALL_MEMORY_WRITE(value, sizeof(uint8_t))); return z_impl_ps2_read(dev, value); } -#include +#include static inline int z_vrfy_ps2_enable_callback(const struct device *dev) { K_OOPS(K_SYSCALL_DRIVER_PS2(dev, enable_callback)); return z_impl_ps2_enable_callback(dev); } -#include +#include static inline int z_vrfy_ps2_disable_callback(const struct device *dev) { K_OOPS(K_SYSCALL_DRIVER_PS2(dev, disable_callback)); return z_impl_ps2_disable_callback(dev); } -#include +#include diff --git a/drivers/ptp_clock/ptp_clock.c b/drivers/ptp_clock/ptp_clock.c index 0ac0e5c242f78..d0db19ca3a191 100644 --- a/drivers/ptp_clock/ptp_clock.c +++ b/drivers/ptp_clock/ptp_clock.c @@ -28,5 +28,5 @@ int z_vrfy_ptp_clock_get(const struct device *dev, return ret; } -#include +#include #endif /* CONFIG_USERSPACE */ diff --git a/drivers/pwm/pwm_handlers.c b/drivers/pwm/pwm_handlers.c index 3ffaaa61e465a..5c342a89068fc 100644 --- a/drivers/pwm/pwm_handlers.c +++ b/drivers/pwm/pwm_handlers.c @@ -16,7 +16,7 @@ static inline int z_vrfy_pwm_set_cycles(const struct device *dev, return z_impl_pwm_set_cycles((const struct device *)dev, channel, period, pulse, flags); } -#include +#include static inline int z_vrfy_pwm_get_cycles_per_sec(const struct device *dev, uint32_t channel, @@ -27,7 +27,7 @@ static inline int z_vrfy_pwm_get_cycles_per_sec(const struct device *dev, return z_impl_pwm_get_cycles_per_sec((const struct device *)dev, channel, (uint64_t *)cycles); } -#include +#include #ifdef CONFIG_PWM_CAPTURE @@ -37,7 +37,7 @@ static inline int z_vrfy_pwm_enable_capture(const struct device *dev, K_OOPS(K_SYSCALL_DRIVER_PWM(dev, enable_capture)); return z_impl_pwm_enable_capture((const struct device *)dev, channel); } -#include +#include static inline int z_vrfy_pwm_disable_capture(const struct device *dev, uint32_t channel) @@ -45,7 +45,7 @@ static inline int z_vrfy_pwm_disable_capture(const struct device *dev, K_OOPS(K_SYSCALL_DRIVER_PWM(dev, disable_capture)); return z_impl_pwm_disable_capture((const struct device *)dev, channel); } -#include +#include static inline int z_vrfy_pwm_capture_cycles(const struct device *dev, uint32_t channel, pwm_flags_t flags, @@ -75,6 +75,6 @@ static inline int z_vrfy_pwm_capture_cycles(const struct device *dev, return err; } -#include +#include #endif /* CONFIG_PWM_CAPTURE */ diff --git a/drivers/retained_mem/retained_mem_handlers.c b/drivers/retained_mem/retained_mem_handlers.c index d344e37b42c36..1d0035818576d 100644 --- a/drivers/retained_mem/retained_mem_handlers.c +++ b/drivers/retained_mem/retained_mem_handlers.c @@ -12,7 +12,7 @@ static inline ssize_t z_vrfy_retained_mem_size(const struct device *dev) K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_RETAINED_MEM)); return z_impl_retained_mem_size(dev); } -#include +#include static inline int z_vrfy_retained_mem_read(const struct device *dev, off_t offset, uint8_t *buffer, size_t size) @@ -21,7 +21,7 @@ static inline int z_vrfy_retained_mem_read(const struct device *dev, off_t offse K_OOPS(K_SYSCALL_MEMORY_WRITE(buffer, size)); return z_impl_retained_mem_read(dev, offset, buffer, size); } -#include +#include static inline int z_vrfy_retained_mem_write(const struct device *dev, off_t offset, const uint8_t *buffer, size_t size) @@ -30,11 +30,11 @@ static inline int z_vrfy_retained_mem_write(const struct device *dev, off_t offs K_OOPS(K_SYSCALL_MEMORY_READ(buffer, size)); return z_impl_retained_mem_write(dev, offset, buffer, size); } -#include +#include static inline int z_vrfy_retained_mem_clear(const struct device *dev) { K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_RETAINED_MEM)); return z_impl_retained_mem_clear(dev); } -#include +#include diff --git a/drivers/rtc/rtc_handlers.c b/drivers/rtc/rtc_handlers.c index 33bb907697110..499171de3a112 100644 --- a/drivers/rtc/rtc_handlers.c +++ b/drivers/rtc/rtc_handlers.c @@ -13,7 +13,7 @@ static inline int z_vrfy_rtc_set_time(const struct device *dev, const struct rtc K_OOPS(K_SYSCALL_MEMORY_READ(timeptr, sizeof(struct rtc_time))); return z_impl_rtc_set_time(dev, timeptr); } -#include +#include static inline int z_vrfy_rtc_get_time(const struct device *dev, struct rtc_time *timeptr) { @@ -21,7 +21,7 @@ static inline int z_vrfy_rtc_get_time(const struct device *dev, struct rtc_time K_OOPS(K_SYSCALL_MEMORY_WRITE(timeptr, sizeof(struct rtc_time))); return z_impl_rtc_get_time(dev, timeptr); } -#include +#include #ifdef CONFIG_RTC_ALARM static inline int z_vrfy_rtc_alarm_get_supported_fields(const struct device *dev, uint16_t id, @@ -31,7 +31,7 @@ static inline int z_vrfy_rtc_alarm_get_supported_fields(const struct device *dev K_OOPS(K_SYSCALL_MEMORY_WRITE(mask, sizeof(uint16_t))); return z_impl_rtc_alarm_get_supported_fields(dev, id, mask); } -#include +#include static inline int z_vrfy_rtc_alarm_set_time(const struct device *dev, uint16_t id, uint16_t mask, const struct rtc_time *timeptr) @@ -40,7 +40,7 @@ static inline int z_vrfy_rtc_alarm_set_time(const struct device *dev, uint16_t i K_OOPS(K_SYSCALL_MEMORY_READ(timeptr, sizeof(struct rtc_time))); return z_impl_rtc_alarm_set_time(dev, id, mask, timeptr); } -#include +#include static inline int z_vrfy_rtc_alarm_get_time(const struct device *dev, uint16_t id, uint16_t *mask, struct rtc_time *timeptr) @@ -50,14 +50,14 @@ static inline int z_vrfy_rtc_alarm_get_time(const struct device *dev, uint16_t i K_OOPS(K_SYSCALL_MEMORY_WRITE(timeptr, sizeof(struct rtc_time))); return z_impl_rtc_alarm_get_time(dev, id, mask, timeptr); } -#include +#include static inline int z_vrfy_rtc_alarm_is_pending(const struct device *dev, uint16_t id) { K_OOPS(K_SYSCALL_DRIVER_RTC(dev, alarm_is_pending)); return z_impl_rtc_alarm_is_pending(dev, id); } -#include +#include #endif /* CONFIG_RTC_ALARM */ #ifdef CONFIG_RTC_CALIBRATION @@ -67,7 +67,7 @@ static inline int z_vrfy_rtc_set_calibration(const struct device *dev, int32_t c return z_impl_rtc_set_calibration(dev, calibration); } -#include +#include static inline int z_vrfy_rtc_get_calibration(const struct device *dev, int32_t *calibration) { @@ -75,5 +75,5 @@ static inline int z_vrfy_rtc_get_calibration(const struct device *dev, int32_t * K_OOPS(K_SYSCALL_MEMORY_WRITE(calibration, sizeof(int32_t))); return z_impl_rtc_get_calibration(dev, calibration); } -#include +#include #endif /* CONFIG_RTC_CALIBRATION */ diff --git a/drivers/sensor/sensor_handlers.c b/drivers/sensor/sensor_handlers.c index 4643646c21557..ea82e20e9887e 100644 --- a/drivers/sensor/sensor_handlers.c +++ b/drivers/sensor/sensor_handlers.c @@ -17,7 +17,7 @@ static inline int z_vrfy_sensor_attr_set(const struct device *dev, return z_impl_sensor_attr_set((const struct device *)dev, chan, attr, (const struct sensor_value *)val); } -#include +#include static inline int z_vrfy_sensor_attr_get(const struct device *dev, enum sensor_channel chan, @@ -29,14 +29,14 @@ static inline int z_vrfy_sensor_attr_get(const struct device *dev, return z_impl_sensor_attr_get((const struct device *)dev, chan, attr, (struct sensor_value *)val); } -#include +#include static inline int z_vrfy_sensor_sample_fetch(const struct device *dev) { K_OOPS(K_SYSCALL_DRIVER_SENSOR(dev, sample_fetch)); return z_impl_sensor_sample_fetch((const struct device *)dev); } -#include +#include static inline int z_vrfy_sensor_sample_fetch_chan(const struct device *dev, enum sensor_channel type) @@ -45,7 +45,7 @@ static inline int z_vrfy_sensor_sample_fetch_chan(const struct device *dev, return z_impl_sensor_sample_fetch_chan((const struct device *)dev, type); } -#include +#include static inline int z_vrfy_sensor_channel_get(const struct device *dev, enum sensor_channel chan, @@ -56,7 +56,7 @@ static inline int z_vrfy_sensor_channel_get(const struct device *dev, return z_impl_sensor_channel_get((const struct device *)dev, chan, (struct sensor_value *)val); } -#include +#include #ifdef CONFIG_SENSOR_ASYNC_API static inline int z_vrfy_sensor_get_decoder(const struct device *dev, @@ -66,7 +66,7 @@ static inline int z_vrfy_sensor_get_decoder(const struct device *dev, K_OOPS(K_SYSCALL_MEMORY_READ(decoder, sizeof(struct sensor_decoder_api))); return z_impl_sensor_get_decoder(dev, decoder); } -#include +#include static inline int z_vrfy_sensor_reconfigure_read_iodev(struct rtio_iodev *iodev, const struct device *sensor, @@ -78,5 +78,5 @@ static inline int z_vrfy_sensor_reconfigure_read_iodev(struct rtio_iodev *iodev, K_OOPS(K_SYSCALL_MEMORY_READ(channels, sizeof(enum sensor_channel) * num_channels)); return z_impl_sensor_reconfigure_read_iodev(iodev, sensor, channels, num_channels); } -#include +#include #endif diff --git a/drivers/serial/uart_handlers.c b/drivers/serial/uart_handlers.c index 954592aca28b7..24707bde75478 100644 --- a/drivers/serial/uart_handlers.c +++ b/drivers/serial/uart_handlers.c @@ -22,7 +22,7 @@ } UART_SIMPLE(err_check) -#include +#include static inline int z_vrfy_uart_poll_in(const struct device *dev, unsigned char *p_char) @@ -31,7 +31,7 @@ static inline int z_vrfy_uart_poll_in(const struct device *dev, K_OOPS(K_SYSCALL_MEMORY_WRITE(p_char, sizeof(unsigned char))); return z_impl_uart_poll_in(dev, p_char); } -#include +#include static inline int z_vrfy_uart_poll_in_u16(const struct device *dev, uint16_t *p_u16) @@ -40,7 +40,7 @@ static inline int z_vrfy_uart_poll_in_u16(const struct device *dev, K_OOPS(K_SYSCALL_MEMORY_WRITE(p_u16, sizeof(uint16_t))); return z_impl_uart_poll_in_u16(dev, p_u16); } -#include +#include static inline void z_vrfy_uart_poll_out(const struct device *dev, unsigned char out_char) @@ -48,7 +48,7 @@ static inline void z_vrfy_uart_poll_out(const struct device *dev, K_OOPS(K_SYSCALL_DRIVER_UART(dev, poll_out)); z_impl_uart_poll_out((const struct device *)dev, out_char); } -#include +#include static inline void z_vrfy_uart_poll_out_u16(const struct device *dev, uint16_t out_u16) @@ -56,7 +56,7 @@ static inline void z_vrfy_uart_poll_out_u16(const struct device *dev, K_OOPS(K_SYSCALL_DRIVER_UART(dev, poll_out)); z_impl_uart_poll_out_u16((const struct device *)dev, out_u16); } -#include +#include #ifdef CONFIG_UART_USE_RUNTIME_CONFIGURE static inline int z_vrfy_uart_config_get(const struct device *dev, @@ -67,7 +67,7 @@ static inline int z_vrfy_uart_config_get(const struct device *dev, return z_impl_uart_config_get(dev, cfg); } -#include +#include static inline int z_vrfy_uart_configure(const struct device *dev, const struct uart_config *cfg) @@ -77,7 +77,7 @@ static inline int z_vrfy_uart_configure(const struct device *dev, return z_impl_uart_configure(dev, cfg); } -#include +#include #endif #ifdef CONFIG_UART_ASYNC_API @@ -94,7 +94,7 @@ static inline int z_vrfy_uart_tx(const struct device *dev, const uint8_t *buf, K_OOPS(K_SYSCALL_MEMORY_READ(buf, len)); return z_impl_uart_tx(dev, buf, len, timeout); } -#include +#include #ifdef CONFIG_UART_WIDE_DATA static inline int z_vrfy_uart_tx_u16(const struct device *dev, @@ -105,11 +105,11 @@ static inline int z_vrfy_uart_tx_u16(const struct device *dev, K_OOPS(K_SYSCALL_MEMORY_ARRAY_READ(buf, len, sizeof(uint16_t))); return z_impl_uart_tx_u16(dev, buf, len, timeout); } -#include +#include #endif UART_SIMPLE(tx_abort); -#include +#include static inline int z_vrfy_uart_rx_enable(const struct device *dev, uint8_t *buf, @@ -119,7 +119,7 @@ static inline int z_vrfy_uart_rx_enable(const struct device *dev, K_OOPS(K_SYSCALL_MEMORY_WRITE(buf, len)); return z_impl_uart_rx_enable(dev, buf, len, timeout); } -#include +#include #ifdef CONFIG_UART_WIDE_DATA static inline int z_vrfy_uart_rx_enable_u16(const struct device *dev, @@ -130,11 +130,11 @@ static inline int z_vrfy_uart_rx_enable_u16(const struct device *dev, K_OOPS(K_SYSCALL_MEMORY_ARRAY_WRITE(buf, len, sizeof(uint16_t))); return z_impl_uart_rx_enable_u16(dev, buf, len, timeout); } -#include +#include #endif UART_SIMPLE(rx_disable); -#include +#include #endif /* CONFIG_UART_ASYNC_API */ #ifdef CONFIG_UART_INTERRUPT_DRIVEN @@ -146,14 +146,14 @@ UART_SIMPLE_VOID(irq_err_enable) UART_SIMPLE_VOID(irq_err_disable) UART_SIMPLE(irq_is_pending) UART_SIMPLE(irq_update) -#include -#include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include +#include #endif /* CONFIG_UART_INTERRUPT_DRIVEN */ #ifdef CONFIG_UART_LINE_CTRL @@ -164,7 +164,7 @@ static inline int z_vrfy_uart_line_ctrl_set(const struct device *dev, return z_impl_uart_line_ctrl_set((const struct device *)dev, ctrl, val); } -#include +#include static inline int z_vrfy_uart_line_ctrl_get(const struct device *dev, uint32_t ctrl, uint32_t *val) @@ -174,7 +174,7 @@ static inline int z_vrfy_uart_line_ctrl_get(const struct device *dev, return z_impl_uart_line_ctrl_get((const struct device *)dev, ctrl, (uint32_t *)val); } -#include +#include #endif /* CONFIG_UART_LINE_CTRL */ #ifdef CONFIG_UART_DRV_CMD @@ -184,5 +184,5 @@ static inline int z_vrfy_uart_drv_cmd(const struct device *dev, uint32_t cmd, K_OOPS(K_SYSCALL_DRIVER_UART(dev, drv_cmd)); return z_impl_uart_drv_cmd((const struct device *)dev, cmd, p); } -#include +#include #endif /* CONFIG_UART_DRV_CMD */ diff --git a/drivers/smbus/smbus_handlers.c b/drivers/smbus/smbus_handlers.c index b9c45e76cf76b..77169fc662708 100644 --- a/drivers/smbus/smbus_handlers.c +++ b/drivers/smbus/smbus_handlers.c @@ -15,7 +15,7 @@ static inline int z_vrfy_smbus_configure(const struct device *dev, return z_impl_smbus_configure(dev, dev_config); } -#include +#include static inline int z_vrfy_smbus_get_config(const struct device *dev, uint32_t *dev_config) @@ -25,7 +25,7 @@ static inline int z_vrfy_smbus_get_config(const struct device *dev, return z_impl_smbus_get_config(dev, dev_config); } -#include +#include static inline int z_vrfy_smbus_quick(const struct device *dev, uint16_t addr, enum smbus_direction rw) @@ -34,7 +34,7 @@ static inline int z_vrfy_smbus_quick(const struct device *dev, uint16_t addr, return z_impl_smbus_quick(dev, addr, rw); } -#include +#include static inline int z_vrfy_smbus_byte_write(const struct device *dev, uint16_t addr, uint8_t byte) @@ -43,7 +43,7 @@ static inline int z_vrfy_smbus_byte_write(const struct device *dev, return z_impl_smbus_byte_write(dev, addr, byte); } -#include +#include static inline int z_vrfy_smbus_byte_read(const struct device *dev, uint16_t addr, uint8_t *byte) @@ -53,7 +53,7 @@ static inline int z_vrfy_smbus_byte_read(const struct device *dev, return z_impl_smbus_byte_read(dev, addr, byte); } -#include +#include static inline int z_vrfy_smbus_byte_data_write(const struct device *dev, uint16_t addr, uint8_t cmd, @@ -63,7 +63,7 @@ static inline int z_vrfy_smbus_byte_data_write(const struct device *dev, return z_impl_smbus_byte_data_write(dev, addr, cmd, byte); } -#include +#include static inline int z_vrfy_smbus_byte_data_read(const struct device *dev, uint16_t addr, uint8_t cmd, @@ -74,7 +74,7 @@ static inline int z_vrfy_smbus_byte_data_read(const struct device *dev, return z_impl_smbus_byte_data_read(dev, addr, cmd, byte); } -#include +#include static inline int z_vrfy_smbus_word_data_write(const struct device *dev, uint16_t addr, uint8_t cmd, @@ -84,7 +84,7 @@ static inline int z_vrfy_smbus_word_data_write(const struct device *dev, return z_impl_smbus_word_data_write(dev, addr, cmd, word); } -#include +#include static inline int z_vrfy_smbus_word_data_read(const struct device *dev, uint16_t addr, uint8_t cmd, @@ -95,7 +95,7 @@ static inline int z_vrfy_smbus_word_data_read(const struct device *dev, return z_impl_smbus_word_data_read(dev, addr, cmd, word); } -#include +#include static inline int z_vrfy_smbus_pcall(const struct device *dev, uint16_t addr, uint8_t cmd, @@ -106,7 +106,7 @@ static inline int z_vrfy_smbus_pcall(const struct device *dev, return z_impl_smbus_pcall(dev, addr, cmd, send_word, recv_word); } -#include +#include static inline int z_vrfy_smbus_block_write(const struct device *dev, uint16_t addr, uint8_t cmd, @@ -117,7 +117,7 @@ static inline int z_vrfy_smbus_block_write(const struct device *dev, return z_impl_smbus_block_write(dev, addr, cmd, count, buf); } -#include +#include static inline int z_vrfy_smbus_block_read(const struct device *dev, uint16_t addr, uint8_t cmd, @@ -128,7 +128,7 @@ static inline int z_vrfy_smbus_block_read(const struct device *dev, return z_impl_smbus_block_read(dev, addr, cmd, count, buf); } -#include +#include static inline int z_vrfy_smbus_block_pcall(const struct device *dev, uint16_t addr, uint8_t cmd, @@ -142,7 +142,7 @@ static inline int z_vrfy_smbus_block_pcall(const struct device *dev, return z_impl_smbus_block_pcall(dev, addr, cmd, snd_count, snd_buf, rcv_count, rcv_buf); } -#include +#include static inline int z_vrfy_smbus_smbalert_remove_cb(const struct device *dev, struct smbus_callback *cb) @@ -151,7 +151,7 @@ static inline int z_vrfy_smbus_smbalert_remove_cb(const struct device *dev, return z_impl_smbus_smbalert_remove_cb(dev, cb); } -#include +#include static inline int z_vrfy_smbus_host_notify_remove_cb(const struct device *dev, struct smbus_callback *cb) @@ -160,4 +160,4 @@ static inline int z_vrfy_smbus_host_notify_remove_cb(const struct device *dev, return z_impl_smbus_host_notify_remove_cb(dev, cb); } -#include +#include diff --git a/drivers/spi/spi_handlers.c b/drivers/spi/spi_handlers.c index 68b362b5ed285..7d010a1e3e990 100644 --- a/drivers/spi/spi_handlers.c +++ b/drivers/spi/spi_handlers.c @@ -114,7 +114,7 @@ static inline int z_vrfy_spi_transceive(const struct device *dev, &tx_bufs_copy, &rx_bufs_copy); } -#include +#include static inline int z_vrfy_spi_release(const struct device *dev, const struct spi_config *config) @@ -123,4 +123,4 @@ static inline int z_vrfy_spi_release(const struct device *dev, K_OOPS(K_SYSCALL_DRIVER_SPI(dev, release)); return z_impl_spi_release((const struct device *)dev, config); } -#include +#include diff --git a/drivers/virtualization/virt_ivshmem_handlers.c b/drivers/virtualization/virt_ivshmem_handlers.c index 821ab16f30407..4f22a4dadd8b4 100644 --- a/drivers/virtualization/virt_ivshmem_handlers.c +++ b/drivers/virtualization/virt_ivshmem_handlers.c @@ -16,7 +16,7 @@ static inline size_t z_vrfy_ivshmem_get_mem(const struct device *dev, return z_impl_ivshmem_get_mem(dev, memmap); } -#include +#include static inline uint32_t z_vrfy_ivshmem_get_id(const struct device *dev) { @@ -24,7 +24,7 @@ static inline uint32_t z_vrfy_ivshmem_get_id(const struct device *dev) return z_impl_ivshmem_get_id(dev); } -#include +#include static inline uint16_t z_vrfy_ivshmem_get_vectors(const struct device *dev) { @@ -32,7 +32,7 @@ static inline uint16_t z_vrfy_ivshmem_get_vectors(const struct device *dev) return z_impl_ivshmem_get_vectors(dev); } -#include +#include static inline int z_vrfy_ivshmem_int_peer(const struct device *dev, uint32_t peer_id, uint16_t vector) @@ -41,7 +41,7 @@ static inline int z_vrfy_ivshmem_int_peer(const struct device *dev, return z_impl_ivshmem_int_peer(dev, peer_id, vector); } -#include +#include static inline int z_vrfy_ivshmem_register_handler(const struct device *dev, struct k_poll_signal *signal, @@ -52,7 +52,7 @@ static inline int z_vrfy_ivshmem_register_handler(const struct device *dev, return z_impl_ivshmem_register_handler(dev, signal, vector); } -#include +#include #ifdef CONFIG_IVSHMEM_V2 @@ -64,7 +64,7 @@ static inline size_t z_vrfy_ivshmem_get_rw_mem_section(const struct device *dev, return z_impl_ivshmem_get_rw_mem_section(dev, memmap); } -#include +#include static inline size_t z_vrfy_ivshmem_get_output_mem_section(const struct device *dev, uint32_t peer_id, @@ -75,7 +75,7 @@ static inline size_t z_vrfy_ivshmem_get_output_mem_section(const struct device * return z_impl_ivshmem_get_output_mem_section(dev, peer_id, memmap); } -#include +#include static inline uint32_t z_vrfy_ivshmem_get_state(const struct device *dev, uint32_t peer_id) @@ -84,7 +84,7 @@ static inline uint32_t z_vrfy_ivshmem_get_state(const struct device *dev, return z_impl_ivshmem_get_state(dev, peer_id); } -#include +#include static inline int z_vrfy_ivshmem_set_state(const struct device *dev, uint32_t state) @@ -93,7 +93,7 @@ static inline int z_vrfy_ivshmem_set_state(const struct device *dev, return z_impl_ivshmem_set_state(dev, state); } -#include +#include static inline uint32_t z_vrfy_ivshmem_get_max_peers(const struct device *dev) { @@ -101,7 +101,7 @@ static inline uint32_t z_vrfy_ivshmem_get_max_peers(const struct device *dev) return z_impl_ivshmem_get_max_peers(dev); } -#include +#include static inline uint16_t z_vrfy_ivshmem_get_protocol(const struct device *dev) { @@ -109,7 +109,7 @@ static inline uint16_t z_vrfy_ivshmem_get_protocol(const struct device *dev) return z_impl_ivshmem_get_protocol(dev); } -#include +#include static inline int z_vrfy_ivshmem_enable_interrupts(const struct device *dev, bool enable) @@ -118,6 +118,6 @@ static inline int z_vrfy_ivshmem_enable_interrupts(const struct device *dev, return z_impl_ivshmem_enable_interrupts(dev, enable); } -#include +#include #endif /* CONFIG_IVSHMEM_V2 */ diff --git a/drivers/w1/w1_handlers.c b/drivers/w1/w1_handlers.c index f2299705a269b..db2fb4ee18721 100644 --- a/drivers/w1/w1_handlers.c +++ b/drivers/w1/w1_handlers.c @@ -13,7 +13,7 @@ static inline int z_vrfy_w1_reset_bus(const struct device *dev) return z_impl_w1_reset_bus((const struct device *)dev); } -#include +#include static inline int z_vrfy_w1_read_bit(const struct device *dev) { @@ -21,7 +21,7 @@ static inline int z_vrfy_w1_read_bit(const struct device *dev) return z_impl_w1_read_bit((const struct device *)dev); } -#include +#include static inline int z_vrfy_w1_write_bit(const struct device *dev, bool bit) { @@ -29,7 +29,7 @@ static inline int z_vrfy_w1_write_bit(const struct device *dev, bool bit) return z_impl_w1_write_bit((const struct device *)dev, bit); } -#include +#include static inline int z_vrfy_w1_read_byte(const struct device *dev) { @@ -37,7 +37,7 @@ static inline int z_vrfy_w1_read_byte(const struct device *dev) return z_impl_w1_read_byte((const struct device *)dev); } -#include +#include static inline int z_vrfy_w1_write_byte(const struct device *dev, uint8_t byte) { @@ -45,7 +45,7 @@ static inline int z_vrfy_w1_write_byte(const struct device *dev, uint8_t byte) return z_impl_w1_write_byte((const struct device *)dev, (uint8_t)byte); } -#include +#include static inline int z_vrfy_w1_read_block(const struct device *dev, uint8_t *buffer, size_t len) @@ -56,7 +56,7 @@ static inline int z_vrfy_w1_read_block(const struct device *dev, return z_impl_w1_read_block((const struct device *)dev, (uint8_t *)buffer, (size_t)len); } -#include +#include static inline int z_vrfy_w1_write_block(const struct device *dev, const uint8_t *buffer, size_t len) @@ -67,7 +67,7 @@ static inline int z_vrfy_w1_write_block(const struct device *dev, return z_impl_w1_write_block((const struct device *)dev, (const uint8_t *)buffer, (size_t)len); } -#include +#include static inline int z_vrfy_w1_change_bus_lock(const struct device *dev, bool lock) { @@ -75,7 +75,7 @@ static inline int z_vrfy_w1_change_bus_lock(const struct device *dev, bool lock) return z_impl_w1_change_bus_lock((const struct device *)dev, lock); } -#include +#include static inline int z_vrfy_w1_configure(const struct device *dev, enum w1_settings_type type, uint32_t value) @@ -84,7 +84,7 @@ static inline int z_vrfy_w1_configure(const struct device *dev, return z_impl_w1_configure(dev, type, value); } -#include +#include static inline size_t z_vrfy_w1_get_slave_count(const struct device *dev) { @@ -92,7 +92,7 @@ static inline size_t z_vrfy_w1_get_slave_count(const struct device *dev) return z_impl_w1_get_slave_count((const struct device *)dev); } -#include +#include #if CONFIG_W1_NET static inline int z_vrfy_w1_search_bus(const struct device *dev, @@ -112,5 +112,5 @@ static inline int z_vrfy_w1_search_bus(const struct device *dev, (void *)user_data); } -#include +#include #endif /* CONFIG_W1_NET */ diff --git a/drivers/watchdog/wdt_handlers.c b/drivers/watchdog/wdt_handlers.c index 2ac872f1379d7..727b51251eee5 100644 --- a/drivers/watchdog/wdt_handlers.c +++ b/drivers/watchdog/wdt_handlers.c @@ -13,7 +13,7 @@ static inline int z_vrfy_wdt_setup(const struct device *dev, uint8_t options) return z_impl_wdt_setup(dev, options); } -#include +#include static inline int z_vrfy_wdt_disable(const struct device *dev) { @@ -21,7 +21,7 @@ static inline int z_vrfy_wdt_disable(const struct device *dev) return z_impl_wdt_disable(dev); } -#include +#include static inline int z_vrfy_wdt_feed(const struct device *dev, int channel_id) { @@ -29,4 +29,4 @@ static inline int z_vrfy_wdt_feed(const struct device *dev, int channel_id) return z_impl_wdt_feed(dev, channel_id); } -#include +#include diff --git a/include/zephyr/arch/riscv/error.h b/include/zephyr/arch/riscv/error.h index a7c3e02b48297..208eafadbe502 100644 --- a/include/zephyr/arch/riscv/error.h +++ b/include/zephyr/arch/riscv/error.h @@ -42,7 +42,7 @@ extern "C" { __syscall void user_fault(unsigned int reason); -#include +#include #ifdef __cplusplus } diff --git a/include/zephyr/arch/x86/ia32/linker.ld b/include/zephyr/arch/x86/ia32/linker.ld index 0d1e67147c49a..69ff541232695 100644 --- a/include/zephyr/arch/x86/ia32/linker.ld +++ b/include/zephyr/arch/x86/ia32/linker.ld @@ -38,7 +38,7 @@ */ #include -#include +#include #include #include diff --git a/include/zephyr/arch/xtensa/arch.h b/include/zephyr/arch/xtensa/arch.h index b5638870b4ac6..41072c5c8320e 100644 --- a/include/zephyr/arch/xtensa/arch.h +++ b/include/zephyr/arch/xtensa/arch.h @@ -114,7 +114,7 @@ void xtensa_arch_kernel_oops(int reason_p, void *ssf); __syscall void xtensa_user_fault(unsigned int reason); -#include +#include /* internal routine documented in C file, needed by IRQ_CONNECT() macro */ void z_irq_priority_set(uint32_t irq, uint32_t prio, uint32_t flags); diff --git a/include/zephyr/arch/xtensa/arch_inlines.h b/include/zephyr/arch/xtensa/arch_inlines.h index 4e7b52002768a..e8ceb3c973399 100644 --- a/include/zephyr/arch/xtensa/arch_inlines.h +++ b/include/zephyr/arch/xtensa/arch_inlines.h @@ -11,7 +11,7 @@ #ifndef _ASMLANGUAGE #include -#include +#include /** * @brief Read a special register. diff --git a/include/zephyr/cache.h b/include/zephyr/cache.h index f5547f64afde2..9dbadb8d4ee8e 100644 --- a/include/zephyr/cache.h +++ b/include/zephyr/cache.h @@ -550,7 +550,7 @@ static ALWAYS_INLINE void sys_cache_flush(void *addr, size_t size) } #endif -#include +#include #ifdef __cplusplus } #endif diff --git a/include/zephyr/device.h b/include/zephyr/device.h index d2f2244cc0b8f..ddc69c17fd533 100644 --- a/include/zephyr/device.h +++ b/include/zephyr/device.h @@ -96,7 +96,7 @@ typedef int16_t device_handle_t; * size. * * The ordinal used in this name can be mapped to the path by - * examining zephyr/include/generated/devicetree_generated.h. + * examining zephyr/include/generated/zephyr/devicetree_generated.h. */ #define Z_DEVICE_DT_DEV_ID(node_id) _CONCAT(dts_ord_, DT_DEP_ORD(node_id)) @@ -1085,6 +1085,6 @@ DT_FOREACH_STATUS_OKAY_NODE(Z_MAYBE_DEVICE_DECLARE_INTERNAL) } #endif -#include +#include #endif /* ZEPHYR_INCLUDE_DEVICE_H_ */ diff --git a/include/zephyr/devicetree.h b/include/zephyr/devicetree.h index eb28dea874aca..c1c90220a1aa8 100644 --- a/include/zephyr/devicetree.h +++ b/include/zephyr/devicetree.h @@ -16,7 +16,7 @@ #ifndef DEVICETREE_H #define DEVICETREE_H -#include +#include #include #if !defined(_LINKER) && !defined(_ASMLANGUAGE) diff --git a/include/zephyr/drivers/adc.h b/include/zephyr/drivers/adc.h index 18357cbd01413..46e016e697569 100644 --- a/include/zephyr/drivers/adc.h +++ b/include/zephyr/drivers/adc.h @@ -984,6 +984,6 @@ static inline bool adc_is_ready_dt(const struct adc_dt_spec *spec) } #endif -#include +#include #endif /* ZEPHYR_INCLUDE_DRIVERS_ADC_H_ */ diff --git a/include/zephyr/drivers/auxdisplay.h b/include/zephyr/drivers/auxdisplay.h index de106f5016e03..a56c9b7699380 100644 --- a/include/zephyr/drivers/auxdisplay.h +++ b/include/zephyr/drivers/auxdisplay.h @@ -815,6 +815,6 @@ static inline int z_impl_auxdisplay_custom_command(const struct device *dev, * @} */ -#include +#include #endif /* ZEPHYR_INCLUDE_DRIVERS_AUXDISPLAY_H_ */ diff --git a/include/zephyr/drivers/bbram.h b/include/zephyr/drivers/bbram.h index 599a3588ac81a..30df6a5dd7d2b 100644 --- a/include/zephyr/drivers/bbram.h +++ b/include/zephyr/drivers/bbram.h @@ -261,6 +261,6 @@ int bbram_emul_set_power_state(const struct device *dev, bool failure); * @} */ -#include +#include #endif /* ZEPHYR_INCLUDE_DRIVERS_BBRAM_H */ diff --git a/include/zephyr/drivers/can.h b/include/zephyr/drivers/can.h index 3b0e323dff93e..bf3af29ede29e 100644 --- a/include/zephyr/drivers/can.h +++ b/include/zephyr/drivers/can.h @@ -1800,6 +1800,6 @@ static inline bool can_frame_matches_filter(const struct can_frame *frame, } #endif -#include +#include #endif /* ZEPHYR_INCLUDE_DRIVERS_CAN_H_ */ diff --git a/include/zephyr/drivers/charger.h b/include/zephyr/drivers/charger.h index 457eec939beb7..6c5ebae35df3e 100644 --- a/include/zephyr/drivers/charger.h +++ b/include/zephyr/drivers/charger.h @@ -405,6 +405,6 @@ static inline int z_impl_charger_charge_enable(const struct device *dev, const b } #endif /* __cplusplus */ -#include +#include #endif /* ZEPHYR_INCLUDE_DRIVERS_CHARGER_H_ */ diff --git a/include/zephyr/drivers/console/uart_mux.h b/include/zephyr/drivers/console/uart_mux.h index 56b7f80cabd7a..911372ce5784c 100644 --- a/include/zephyr/drivers/console/uart_mux.h +++ b/include/zephyr/drivers/console/uart_mux.h @@ -151,7 +151,7 @@ void uart_mux_enable(const struct device *dev); } #endif -#include +#include /** * @} diff --git a/include/zephyr/drivers/counter.h b/include/zephyr/drivers/counter.h index b21af71319fd8..0e14ade3b5172 100644 --- a/include/zephyr/drivers/counter.h +++ b/include/zephyr/drivers/counter.h @@ -678,6 +678,6 @@ static inline uint32_t z_impl_counter_get_guard_period(const struct device *dev, * @} */ -#include +#include #endif /* ZEPHYR_INCLUDE_DRIVERS_COUNTER_H_ */ diff --git a/include/zephyr/drivers/dac.h b/include/zephyr/drivers/dac.h index 57f61cce00b46..8e38432051ab3 100644 --- a/include/zephyr/drivers/dac.h +++ b/include/zephyr/drivers/dac.h @@ -131,6 +131,6 @@ static inline int z_impl_dac_write_value(const struct device *dev, } #endif -#include +#include #endif /* ZEPHYR_INCLUDE_DRIVERS_DAC_H_ */ diff --git a/include/zephyr/drivers/dma.h b/include/zephyr/drivers/dma.h index 36a5916b080cb..1338b9b131cd1 100644 --- a/include/zephyr/drivers/dma.h +++ b/include/zephyr/drivers/dma.h @@ -788,6 +788,6 @@ static inline uint32_t dma_burst_index(uint32_t burst) } #endif -#include +#include #endif /* ZEPHYR_INCLUDE_DRIVERS_DMA_H_ */ diff --git a/include/zephyr/drivers/eeprom.h b/include/zephyr/drivers/eeprom.h index 2ab4d1f608234..ff5b21cbd5c7f 100644 --- a/include/zephyr/drivers/eeprom.h +++ b/include/zephyr/drivers/eeprom.h @@ -139,6 +139,6 @@ static inline size_t z_impl_eeprom_get_size(const struct device *dev) * @} */ -#include +#include #endif /* ZEPHYR_INCLUDE_DRIVERS_EEPROM_H_ */ diff --git a/include/zephyr/drivers/emul_fuel_gauge.h b/include/zephyr/drivers/emul_fuel_gauge.h index 5abd7ec4f6ffb..e86c45a2f2bf6 100644 --- a/include/zephyr/drivers/emul_fuel_gauge.h +++ b/include/zephyr/drivers/emul_fuel_gauge.h @@ -93,7 +93,7 @@ static inline int z_impl_emul_fuel_gauge_is_battery_cutoff(const struct emul *ta } #endif -#include +#include /** * @} diff --git a/include/zephyr/drivers/entropy.h b/include/zephyr/drivers/entropy.h index dcb0c2d5ee547..de2d0f2c2d649 100644 --- a/include/zephyr/drivers/entropy.h +++ b/include/zephyr/drivers/entropy.h @@ -127,6 +127,6 @@ static inline int entropy_get_entropy_isr(const struct device *dev, * @} */ -#include +#include #endif /* ZEPHYR_INCLUDE_DRIVERS_ENTROPY_H_ */ diff --git a/include/zephyr/drivers/espi.h b/include/zephyr/drivers/espi.h index d2e64d9c5e480..05e5cda2251b4 100644 --- a/include/zephyr/drivers/espi.h +++ b/include/zephyr/drivers/espi.h @@ -1022,5 +1022,5 @@ static inline int espi_remove_callback(const struct device *dev, /** * @} */ -#include +#include #endif /* ZEPHYR_INCLUDE_ESPI_H_ */ diff --git a/include/zephyr/drivers/espi_saf.h b/include/zephyr/drivers/espi_saf.h index 31fc23c0808ee..d9a25a8d654f1 100644 --- a/include/zephyr/drivers/espi_saf.h +++ b/include/zephyr/drivers/espi_saf.h @@ -557,5 +557,5 @@ static inline int espi_saf_remove_callback(const struct device *dev, /** * @} */ -#include +#include #endif /* ZEPHYR_INCLUDE_ESPI_SAF_H_ */ diff --git a/include/zephyr/drivers/flash.h b/include/zephyr/drivers/flash.h index d26e521ce906d..beb8838d71e9e 100644 --- a/include/zephyr/drivers/flash.h +++ b/include/zephyr/drivers/flash.h @@ -513,6 +513,6 @@ static inline int z_impl_flash_ex_op(const struct device *dev, uint16_t code, * @} */ -#include +#include #endif /* ZEPHYR_INCLUDE_DRIVERS_FLASH_H_ */ diff --git a/include/zephyr/drivers/flash/flash_simulator.h b/include/zephyr/drivers/flash/flash_simulator.h index 0f7e3c5760e76..e1a201b62b3a4 100644 --- a/include/zephyr/drivers/flash/flash_simulator.h +++ b/include/zephyr/drivers/flash/flash_simulator.h @@ -34,6 +34,6 @@ __syscall void *flash_simulator_get_memory(const struct device *dev, } #endif -#include +#include #endif /* __ZEPHYR_INCLUDE_DRIVERS__FLASH_SIMULATOR_H__ */ diff --git a/include/zephyr/drivers/flash/nrf_qspi_nor.h b/include/zephyr/drivers/flash/nrf_qspi_nor.h index 2c3767ad350d1..87db5c75213f5 100644 --- a/include/zephyr/drivers/flash/nrf_qspi_nor.h +++ b/include/zephyr/drivers/flash/nrf_qspi_nor.h @@ -35,6 +35,6 @@ __syscall void nrf_qspi_nor_xip_enable(const struct device *dev, bool enable); } #endif -#include +#include #endif /* __ZEPHYR_INCLUDE_DRIVERS_FLASH_NRF_QSPI_NOR_H__ */ diff --git a/include/zephyr/drivers/fuel_gauge.h b/include/zephyr/drivers/fuel_gauge.h index f4274ea161b90..305e97b278ff4 100644 --- a/include/zephyr/drivers/fuel_gauge.h +++ b/include/zephyr/drivers/fuel_gauge.h @@ -416,6 +416,6 @@ static inline int z_impl_fuel_gauge_battery_cutoff(const struct device *dev) } #endif /* __cplusplus */ -#include +#include #endif /* ZEPHYR_INCLUDE_DRIVERS_BATTERY_H_ */ diff --git a/include/zephyr/drivers/gnss.h b/include/zephyr/drivers/gnss.h index 2c716a43a0602..2777691d7d5c4 100644 --- a/include/zephyr/drivers/gnss.h +++ b/include/zephyr/drivers/gnss.h @@ -493,6 +493,6 @@ static inline int z_impl_gnss_get_supported_systems(const struct device *dev, } #endif -#include +#include #endif /* ZEPHYR_INCLUDE_DRIVERS_GNSS_H_ */ diff --git a/include/zephyr/drivers/gpio.h b/include/zephyr/drivers/gpio.h index 1c5cd6e3390b1..30c845414cb10 100644 --- a/include/zephyr/drivers/gpio.h +++ b/include/zephyr/drivers/gpio.h @@ -1828,6 +1828,6 @@ static inline int z_impl_gpio_get_pending_int(const struct device *dev) } #endif -#include +#include #endif /* ZEPHYR_INCLUDE_DRIVERS_GPIO_H_ */ diff --git a/include/zephyr/drivers/hwinfo.h b/include/zephyr/drivers/hwinfo.h index 468356284be2c..5a53292b59a7a 100644 --- a/include/zephyr/drivers/hwinfo.h +++ b/include/zephyr/drivers/hwinfo.h @@ -171,6 +171,6 @@ int z_impl_hwinfo_get_supported_reset_cause(uint32_t *supported); } #endif -#include +#include #endif /* ZEPHYR_INCLUDE_DRIVERS_HWINFO_H_ */ diff --git a/include/zephyr/drivers/hwspinlock.h b/include/zephyr/drivers/hwspinlock.h index 9f9fd994ea25d..c6e5b480026b3 100644 --- a/include/zephyr/drivers/hwspinlock.h +++ b/include/zephyr/drivers/hwspinlock.h @@ -154,6 +154,6 @@ static inline uint32_t z_impl_hwspinlock_get_max_id(const struct device *dev) /** @} */ -#include +#include #endif /* ZEPHYR_INCLUDE_DRIVERS_HWSPINLOCK_H_ */ diff --git a/include/zephyr/drivers/i2c.h b/include/zephyr/drivers/i2c.h index 04b7d02ce15d8..240d61325a345 100644 --- a/include/zephyr/drivers/i2c.h +++ b/include/zephyr/drivers/i2c.h @@ -1634,6 +1634,6 @@ static inline int i2c_reg_update_byte_dt(const struct i2c_dt_spec *spec, * @} */ -#include +#include #endif /* ZEPHYR_INCLUDE_DRIVERS_I2C_H_ */ diff --git a/include/zephyr/drivers/i2s.h b/include/zephyr/drivers/i2s.h index 987744638ab48..0889a29148e1e 100644 --- a/include/zephyr/drivers/i2s.h +++ b/include/zephyr/drivers/i2s.h @@ -544,6 +544,6 @@ static inline int z_impl_i2s_trigger(const struct device *dev, } #endif -#include +#include #endif /* ZEPHYR_INCLUDE_DRIVERS_I2S_H_ */ diff --git a/include/zephyr/drivers/i3c.h b/include/zephyr/drivers/i3c.h index 5b93bdb23d56c..14604cbe8bd94 100644 --- a/include/zephyr/drivers/i3c.h +++ b/include/zephyr/drivers/i3c.h @@ -2132,6 +2132,6 @@ int i3c_device_basic_info_get(struct i3c_device_desc *target); * @} */ -#include +#include #endif /* ZEPHYR_INCLUDE_DRIVERS_I3C_H_ */ diff --git a/include/zephyr/drivers/ipm.h b/include/zephyr/drivers/ipm.h index 1d8ee204c4a9b..fe300921fb3c5 100644 --- a/include/zephyr/drivers/ipm.h +++ b/include/zephyr/drivers/ipm.h @@ -270,6 +270,6 @@ static inline void z_impl_ipm_complete(const struct device *ipmdev) * @} */ -#include +#include #endif /* ZEPHYR_INCLUDE_DRIVERS_IPM_H_ */ diff --git a/include/zephyr/drivers/kscan.h b/include/zephyr/drivers/kscan.h index 0c878df4ec3b6..96c7b933a49fd 100644 --- a/include/zephyr/drivers/kscan.h +++ b/include/zephyr/drivers/kscan.h @@ -139,6 +139,6 @@ static inline int z_impl_kscan_disable_callback(const struct device *dev) * @} */ -#include +#include #endif /* ZEPHYR_INCLUDE_DRIVERS_KB_SCAN_H_ */ diff --git a/include/zephyr/drivers/led.h b/include/zephyr/drivers/led.h index f63a779fa9f40..6de5c36230c50 100644 --- a/include/zephyr/drivers/led.h +++ b/include/zephyr/drivers/led.h @@ -338,6 +338,6 @@ static inline int z_impl_led_off(const struct device *dev, uint32_t led) } #endif -#include +#include #endif /* ZEPHYR_INCLUDE_DRIVERS_LED_H_ */ diff --git a/include/zephyr/drivers/mbox.h b/include/zephyr/drivers/mbox.h index f0ca6337bfbfa..3f8ffc6594760 100644 --- a/include/zephyr/drivers/mbox.h +++ b/include/zephyr/drivers/mbox.h @@ -486,6 +486,6 @@ static inline int mbox_max_channels_get_dt(const struct mbox_dt_spec *spec) } #endif -#include +#include #endif /* ZEPHYR_INCLUDE_DRIVERS_MBOX_H_ */ diff --git a/include/zephyr/drivers/mdio.h b/include/zephyr/drivers/mdio.h index fe165bcb991dd..bed1b7f73ccf2 100644 --- a/include/zephyr/drivers/mdio.h +++ b/include/zephyr/drivers/mdio.h @@ -237,6 +237,6 @@ static inline int z_impl_mdio_write_c45(const struct device *dev, uint8_t prtad, * @} */ -#include +#include #endif /* ZEPHYR_INCLUDE_DRIVERS_MDIO_H_ */ diff --git a/include/zephyr/drivers/misc/devmux/devmux.h b/include/zephyr/drivers/misc/devmux/devmux.h index 1772d719d96d6..8b01d633a94ce 100644 --- a/include/zephyr/drivers/misc/devmux/devmux.h +++ b/include/zephyr/drivers/misc/devmux/devmux.h @@ -85,6 +85,6 @@ __syscall int devmux_select_set(struct device *dev, size_t index); } #endif -#include +#include #endif /* INCLUDE_ZEPHYR_DRIVERS_MISC_DEVMUX_H_ */ diff --git a/include/zephyr/drivers/misc/timeaware_gpio/timeaware_gpio.h b/include/zephyr/drivers/misc/timeaware_gpio/timeaware_gpio.h index 2c805d923ae4b..ec6fd8c1924b8 100644 --- a/include/zephyr/drivers/misc/timeaware_gpio/timeaware_gpio.h +++ b/include/zephyr/drivers/misc/timeaware_gpio/timeaware_gpio.h @@ -190,6 +190,6 @@ static inline int z_impl_tgpio_pin_read_ts_ec(const struct device *dev, uint32_t } #endif -#include +#include #endif /* ZEPHYR_DRIVERS_MISC_TIMEAWARE_GPIO_TIMEAWARE_GPIO */ diff --git a/include/zephyr/drivers/peci.h b/include/zephyr/drivers/peci.h index 03970314b538c..ebc110706c53a 100644 --- a/include/zephyr/drivers/peci.h +++ b/include/zephyr/drivers/peci.h @@ -348,6 +348,6 @@ static inline int z_impl_peci_transfer(const struct device *dev, * @} */ -#include +#include #endif /* ZEPHYR_INCLUDE_DRIVERS_PECI_H_ */ diff --git a/include/zephyr/drivers/ps2.h b/include/zephyr/drivers/ps2.h index 80351c4466184..6060ba60478f4 100644 --- a/include/zephyr/drivers/ps2.h +++ b/include/zephyr/drivers/ps2.h @@ -172,6 +172,6 @@ static inline int z_impl_ps2_disable_callback(const struct device *dev) * @} */ -#include +#include #endif /* ZEPHYR_INCLUDE_DRIVERS_PS2_H_ */ diff --git a/include/zephyr/drivers/ptp_clock.h b/include/zephyr/drivers/ptp_clock.h index fb6cc8f5a51c6..176c7be8fd16a 100644 --- a/include/zephyr/drivers/ptp_clock.h +++ b/include/zephyr/drivers/ptp_clock.h @@ -101,6 +101,6 @@ static inline int ptp_clock_rate_adjust(const struct device *dev, double rate) } #endif -#include +#include #endif /* ZEPHYR_INCLUDE_DRIVERS_PTP_CLOCK_H_ */ diff --git a/include/zephyr/drivers/pwm.h b/include/zephyr/drivers/pwm.h index b8a4cbd12ee0a..4f21f41e87617 100644 --- a/include/zephyr/drivers/pwm.h +++ b/include/zephyr/drivers/pwm.h @@ -948,6 +948,6 @@ static inline bool pwm_is_ready_dt(const struct pwm_dt_spec *spec) * @} */ -#include +#include #endif /* ZEPHYR_INCLUDE_DRIVERS_PWM_H_ */ diff --git a/include/zephyr/drivers/reset.h b/include/zephyr/drivers/reset.h index c892b53007672..0bf2031b9ccf9 100644 --- a/include/zephyr/drivers/reset.h +++ b/include/zephyr/drivers/reset.h @@ -384,6 +384,6 @@ static inline int reset_line_toggle_dt(const struct reset_dt_spec *spec) } #endif -#include +#include #endif /* ZEPHYR_INCLUDE_DRIVERS_RESET_H_ */ diff --git a/include/zephyr/drivers/retained_mem.h b/include/zephyr/drivers/retained_mem.h index 7f7003c300b72..a7efafbc7d413 100644 --- a/include/zephyr/drivers/retained_mem.h +++ b/include/zephyr/drivers/retained_mem.h @@ -192,6 +192,6 @@ static inline int z_impl_retained_mem_clear(const struct device *dev) } #endif -#include +#include #endif /* ZEPHYR_INCLUDE_DRIVERS_RETAINED_MEM_ */ diff --git a/include/zephyr/drivers/rtc.h b/include/zephyr/drivers/rtc.h index ac5d5c0d35066..493bbf137d4ef 100644 --- a/include/zephyr/drivers/rtc.h +++ b/include/zephyr/drivers/rtc.h @@ -539,6 +539,6 @@ static inline struct tm *rtc_time_to_tm(struct rtc_time *timeptr) } #endif -#include +#include #endif /* ZEPHYR_INCLUDE_DRIVERS_RTC_H_ */ diff --git a/include/zephyr/drivers/rtc/maxim_ds3231.h b/include/zephyr/drivers/rtc/maxim_ds3231.h index 2e8b9fe60ec0e..1dd6be932b01a 100644 --- a/include/zephyr/drivers/rtc/maxim_ds3231.h +++ b/include/zephyr/drivers/rtc/maxim_ds3231.h @@ -596,6 +596,6 @@ int maxim_ds3231_check_alarms(const struct device *dev); #endif /* @todo this should be syscalls/drivers/rtc/maxim_ds3231.h */ -#include +#include #endif /* ZEPHYR_INCLUDE_DRIVERS_RTC_DS3231_H_ */ diff --git a/include/zephyr/drivers/sdhc.h b/include/zephyr/drivers/sdhc.h index 7934d059896bc..98f651cfeec0e 100644 --- a/include/zephyr/drivers/sdhc.h +++ b/include/zephyr/drivers/sdhc.h @@ -519,5 +519,5 @@ static inline int z_impl_sdhc_disable_interrupt(const struct device *dev, } #endif -#include +#include #endif /* ZEPHYR_INCLUDE_DRIVERS_SDHC_H_ */ diff --git a/include/zephyr/drivers/sensor.h b/include/zephyr/drivers/sensor.h index b227fd72002f8..e74c5aa14d5e8 100644 --- a/include/zephyr/drivers/sensor.h +++ b/include/zephyr/drivers/sensor.h @@ -1487,6 +1487,6 @@ DT_FOREACH_STATUS_OKAY_NODE(Z_MAYBE_SENSOR_DECODER_DECLARE_INTERNAL) } #endif -#include +#include #endif /* ZEPHYR_INCLUDE_DRIVERS_SENSOR_H_ */ diff --git a/include/zephyr/drivers/sip_svc/sip_svc_driver.h b/include/zephyr/drivers/sip_svc/sip_svc_driver.h index 2904986af3651..07b8f7f867541 100644 --- a/include/zephyr/drivers/sip_svc/sip_svc_driver.h +++ b/include/zephyr/drivers/sip_svc/sip_svc_driver.h @@ -349,6 +349,6 @@ static inline void z_impl_sip_svc_plat_free_async_memory(const struct device *de } -#include +#include #endif /* ZEPHYR_INCLUDE_SIP_SVC_DRIVER_H_ */ diff --git a/include/zephyr/drivers/smbus.h b/include/zephyr/drivers/smbus.h index da4a5c3a9364c..f0642d6d837e4 100644 --- a/include/zephyr/drivers/smbus.h +++ b/include/zephyr/drivers/smbus.h @@ -1092,6 +1092,6 @@ static inline int z_impl_smbus_block_pcall(const struct device *dev, * @} */ -#include +#include #endif /* ZEPHYR_INCLUDE_DRIVERS_SMBUS_H_ */ diff --git a/include/zephyr/drivers/spi.h b/include/zephyr/drivers/spi.h index be4e983990b4d..a24a63a209ad4 100644 --- a/include/zephyr/drivers/spi.h +++ b/include/zephyr/drivers/spi.h @@ -1307,6 +1307,6 @@ static inline int spi_release_dt(const struct spi_dt_spec *spec) * @} */ -#include +#include #endif /* ZEPHYR_INCLUDE_DRIVERS_SPI_H_ */ diff --git a/include/zephyr/drivers/syscon.h b/include/zephyr/drivers/syscon.h index a8c5750cc4e0e..6794b48eb64a2 100644 --- a/include/zephyr/drivers/syscon.h +++ b/include/zephyr/drivers/syscon.h @@ -160,6 +160,6 @@ static inline int z_impl_syscon_get_size(const struct device *dev, size_t *size) } #endif -#include +#include #endif /* ZEPHYR_INCLUDE_DRIVERS_SYSCON_H_ */ diff --git a/include/zephyr/drivers/uart.h b/include/zephyr/drivers/uart.h index 8db89e262f2b9..845949ea96401 100644 --- a/include/zephyr/drivers/uart.h +++ b/include/zephyr/drivers/uart.h @@ -1671,6 +1671,6 @@ static inline int z_impl_uart_drv_cmd(const struct device *dev, uint32_t cmd, * @} */ -#include +#include #endif /* ZEPHYR_INCLUDE_DRIVERS_UART_H_ */ diff --git a/include/zephyr/drivers/usb/usb_bc12.h b/include/zephyr/drivers/usb/usb_bc12.h index 57f47553388c4..791539141739f 100644 --- a/include/zephyr/drivers/usb/usb_bc12.h +++ b/include/zephyr/drivers/usb/usb_bc12.h @@ -184,6 +184,6 @@ static inline int z_impl_bc12_set_result_cb(const struct device *dev, bc12_callb * @} */ -#include +#include #endif /* ZEPHYR_INCLUDE_DRIVERS_USB_USB_BC12_H_ */ diff --git a/include/zephyr/drivers/virtualization/ivshmem.h b/include/zephyr/drivers/virtualization/ivshmem.h index 20bd1e42336eb..b0662d08d5524 100644 --- a/include/zephyr/drivers/virtualization/ivshmem.h +++ b/include/zephyr/drivers/virtualization/ivshmem.h @@ -340,6 +340,6 @@ static inline int z_impl_ivshmem_enable_interrupts(const struct device *dev, * @} */ -#include +#include #endif /* ZEPHYR_INCLUDE_DRIVERS_VIRTUALIZATION_IVSHMEM_H_ */ diff --git a/include/zephyr/drivers/w1.h b/include/zephyr/drivers/w1.h index ed691f6673370..a8301cda21b2a 100644 --- a/include/zephyr/drivers/w1.h +++ b/include/zephyr/drivers/w1.h @@ -720,6 +720,6 @@ static inline uint16_t w1_crc16(const uint16_t seed, const uint8_t *src, /** * @} */ -#include +#include #endif /* ZEPHYR_INCLUDE_DRIVERS_W1_H_ */ diff --git a/include/zephyr/drivers/watchdog.h b/include/zephyr/drivers/watchdog.h index 5c53d10bbc70a..fdeb9ef0c3489 100644 --- a/include/zephyr/drivers/watchdog.h +++ b/include/zephyr/drivers/watchdog.h @@ -253,6 +253,6 @@ static inline int z_impl_wdt_feed(const struct device *dev, int channel_id) /** @} */ -#include +#include #endif /* ZEPHYR_INCLUDE_DRIVERS_WATCHDOG_H_ */ diff --git a/include/zephyr/internal/syscall_handler.h b/include/zephyr/internal/syscall_handler.h index 091a60615f60f..62f1061843227 100644 --- a/include/zephyr/internal/syscall_handler.h +++ b/include/zephyr/internal/syscall_handler.h @@ -647,7 +647,7 @@ static inline int k_object_validation_check(struct k_object *ko, #define K_SYSCALL_OBJ_NEVER_INIT(ptr, type) \ K_SYSCALL_IS_OBJ(ptr, type, _OBJ_INIT_FALSE) -#include +#include #endif /* _ASMLANGUAGE */ diff --git a/include/zephyr/kernel.h b/include/zephyr/kernel.h index 06bbfa1e69178..f4b2cbe1bc2c1 100644 --- a/include/zephyr/kernel.h +++ b/include/zephyr/kernel.h @@ -6153,7 +6153,7 @@ void k_sys_runtime_stats_disable(void); #endif #include -#include +#include #endif /* !_ASMLANGUAGE */ diff --git a/include/zephyr/kernel/mm/demand_paging.h b/include/zephyr/kernel/mm/demand_paging.h index 343c10478b93c..f88f5c2067e93 100644 --- a/include/zephyr/kernel/mm/demand_paging.h +++ b/include/zephyr/kernel/mm/demand_paging.h @@ -203,7 +203,7 @@ __syscall void k_mem_paging_histogram_backing_store_page_in_get( __syscall void k_mem_paging_histogram_backing_store_page_out_get( struct k_mem_paging_histogram_t *hist); -#include +#include /** @} */ diff --git a/include/zephyr/linker/kobject-data.ld b/include/zephyr/linker/kobject-data.ld index 26720dbff3388..573680b235e7e 100644 --- a/include/zephyr/linker/kobject-data.ld +++ b/include/zephyr/linker/kobject-data.ld @@ -30,7 +30,7 @@ */ #if defined(LINKER_ZEPHYR_PREBUILT) -#include +#include #ifdef CONFIG_DYNAMIC_OBJECTS /* This is produced by gperf. Put a place holder here @@ -45,7 +45,7 @@ #endif /* LINKER_ZEPHYR_PREBUILT */ #if defined(LINKER_ZEPHYR_FINAL) -#include +#include #ifdef KOBJECT_DATA_ALIGN . = ALIGN(KOBJECT_DATA_ALIGN); diff --git a/include/zephyr/linker/kobject-priv-stacks.ld b/include/zephyr/linker/kobject-priv-stacks.ld index 0da28763a2bf8..53bd508927e68 100644 --- a/include/zephyr/linker/kobject-priv-stacks.ld +++ b/include/zephyr/linker/kobject-priv-stacks.ld @@ -20,7 +20,7 @@ */ #if defined(LINKER_ZEPHYR_PREBUILT) -#include +#include #ifdef KOBJECT_PRIV_STACKS_ALIGN . = ALIGN(KOBJECT_PRIV_STACKS_ALIGN); . = . + KOBJECT_PRIV_STACKS_SZ; @@ -28,7 +28,7 @@ #endif /* LINKER_ZEPHYR_PREBUILT */ #if defined(LINKER_ZEPHYR_FINAL) -#include +#include #ifdef KOBJECT_PRIV_STACKS_ALIGN . = ALIGN(KOBJECT_PRIV_STACKS_ALIGN); #endif diff --git a/include/zephyr/linker/kobject-rom.ld b/include/zephyr/linker/kobject-rom.ld index 02c31e89987c3..1bb6ee10c15d2 100644 --- a/include/zephyr/linker/kobject-rom.ld +++ b/include/zephyr/linker/kobject-rom.ld @@ -16,7 +16,7 @@ */ #if defined(LINKER_ZEPHYR_PREBUILT) -#include +#include #ifdef KOBJECT_RODATA_ALIGN . = ALIGN(KOBJECT_RODATA_ALIGN); @@ -29,7 +29,7 @@ #endif /* LINKER_ZEPHYR_PREBUILT */ #if defined(LINKER_ZEPHYR_FINAL) -#include +#include #ifdef KOBJECT_RODATA_ALIGN . = ALIGN(KOBJECT_RODATA_ALIGN); diff --git a/include/zephyr/linker/linker-defs.h b/include/zephyr/linker/linker-defs.h index ec37a3718d5e0..8a1db6da081f5 100644 --- a/include/zephyr/linker/linker-defs.h +++ b/include/zephyr/linker/linker-defs.h @@ -23,7 +23,7 @@ #include #include #include -#include +#include /* We need to dummy out DT_NODE_HAS_STATUS when building the unittests. * Including devicetree.h would require generating dummy header files diff --git a/include/zephyr/logging/log_ctrl.h b/include/zephyr/logging/log_ctrl.h index eb8cb5606556e..26d09589027be 100644 --- a/include/zephyr/logging/log_ctrl.h +++ b/include/zephyr/logging/log_ctrl.h @@ -301,7 +301,7 @@ int log_mem_get_max_usage(uint32_t *max); #define LOG_PROCESS() false #endif -#include +#include /** * @} diff --git a/include/zephyr/logging/log_msg.h b/include/zephyr/logging/log_msg.h index 2f6b3a04616d8..ed491c9e74229 100644 --- a/include/zephyr/logging/log_msg.h +++ b/include/zephyr/logging/log_msg.h @@ -857,7 +857,7 @@ static inline uint8_t *log_msg_get_package(struct log_msg *msg, size_t *len) * @} */ -#include +#include #ifdef __cplusplus } diff --git a/include/zephyr/mgmt/updatehub.h b/include/zephyr/mgmt/updatehub.h index 57e4b82b5dbe4..c37ba42390063 100644 --- a/include/zephyr/mgmt/updatehub.h +++ b/include/zephyr/mgmt/updatehub.h @@ -98,5 +98,5 @@ __syscall int updatehub_reboot(void); * @} */ -#include +#include #endif /* ZEPHYR_INCLUDE_MGMT_UPDATEHUB_H_ */ diff --git a/include/zephyr/net/ethernet.h b/include/zephyr/net/ethernet.h index f0d1b1b6e86c7..6376a36ee3c41 100644 --- a/include/zephyr/net/ethernet.h +++ b/include/zephyr/net/ethernet.h @@ -1334,6 +1334,6 @@ static inline bool net_eth_type_is_wifi(struct net_if *iface) } #endif -#include +#include #endif /* ZEPHYR_INCLUDE_NET_ETHERNET_H_ */ diff --git a/include/zephyr/net/net_if.h b/include/zephyr/net/net_if.h index b1a2ca8925a13..0b69dde2fe70d 100644 --- a/include/zephyr/net/net_if.h +++ b/include/zephyr/net/net_if.h @@ -3358,7 +3358,7 @@ struct net_if_api { } #endif -#include +#include /** * @} diff --git a/include/zephyr/net/net_ip.h b/include/zephyr/net/net_ip.h index 4764ba944569c..2e02744a72fa1 100644 --- a/include/zephyr/net/net_ip.h +++ b/include/zephyr/net/net_ip.h @@ -1805,7 +1805,7 @@ static inline int net_ipv6_pe_del_filter(struct in6_addr *addr) } #endif -#include +#include /** * @} diff --git a/include/zephyr/net/socket.h b/include/zephyr/net/socket.h index 1ec1a9a12dfb4..d8983e082ef3e 100644 --- a/include/zephyr/net/socket.h +++ b/include/zephyr/net/socket.h @@ -1378,7 +1378,7 @@ struct net_socket_register { } #endif -#include +#include /** * @} diff --git a/include/zephyr/net/socket_select.h b/include/zephyr/net/socket_select.h index 89a59aebc5e4f..23034d31d7903 100644 --- a/include/zephyr/net/socket_select.h +++ b/include/zephyr/net/socket_select.h @@ -153,7 +153,7 @@ static inline void FD_SET(int fd, zsock_fd_set *set) } #endif -#include +#include /** * @} diff --git a/include/zephyr/net/socket_service.h b/include/zephyr/net/socket_service.h index b1037bf07c3c3..c5060eb408585 100644 --- a/include/zephyr/net/socket_service.h +++ b/include/zephyr/net/socket_service.h @@ -241,7 +241,7 @@ void net_socket_service_foreach(net_socket_service_cb_t cb, void *user_data); } #endif -#include +#include /** * @} diff --git a/include/zephyr/random/random.h b/include/zephyr/random/random.h index bb7f502a3d1e5..293b8d00a8671 100644 --- a/include/zephyr/random/random.h +++ b/include/zephyr/random/random.h @@ -147,5 +147,5 @@ static inline uint64_t sys_rand64_get(void) * @} */ -#include +#include #endif /* ZEPHYR_INCLUDE_RANDOM_RANDOM_H_ */ diff --git a/include/zephyr/rtio/rtio.h b/include/zephyr/rtio/rtio.h index f5bb6fcd48402..75ab879f9499d 100644 --- a/include/zephyr/rtio/rtio.h +++ b/include/zephyr/rtio/rtio.h @@ -1485,6 +1485,6 @@ static inline int z_impl_rtio_submit(struct rtio *r, uint32_t wait_count) } #endif -#include +#include #endif /* ZEPHYR_INCLUDE_RTIO_RTIO_H_ */ diff --git a/include/zephyr/sys/atomic_c.h b/include/zephyr/sys/atomic_c.h index f1e23caf3625c..df36036a87738 100644 --- a/include/zephyr/sys/atomic_c.h +++ b/include/zephyr/sys/atomic_c.h @@ -85,7 +85,7 @@ __syscall atomic_val_t atomic_nand(atomic_t *target, atomic_val_t value); #define _REMOVE_DISABLE_SYSCALL_TRACING #endif -#include +#include #ifdef _REMOVE_DISABLE_SYSCALL_TRACING #undef DISABLE_SYSCALL_TRACING diff --git a/include/zephyr/sys/errno_private.h b/include/zephyr/sys/errno_private.h index 60df9622bb81d..5adba7bfc08b8 100644 --- a/include/zephyr/sys/errno_private.h +++ b/include/zephyr/sys/errno_private.h @@ -50,7 +50,7 @@ __syscall int *z_errno(void); #endif #if !defined(CONFIG_ERRNO_IN_TLS) && !defined(CONFIG_LIBC_ERRNO) -#include +#include #endif /* CONFIG_ERRNO_IN_TLS */ #endif /* ZEPHYR_INCLUDE_SYS_ERRNO_PRIVATE_H_ */ diff --git a/include/zephyr/sys/kobject.h b/include/zephyr/sys/kobject.h index 50577ac7c02d3..9fe9b5ad212c8 100644 --- a/include/zephyr/sys/kobject.h +++ b/include/zephyr/sys/kobject.h @@ -36,7 +36,7 @@ enum k_objects { * generated during build by gen_kobject_list.py. It includes * basic kernel objects (e.g. pipes and mutexes) and driver types. */ -#include +#include /** @endcond */ @@ -283,7 +283,7 @@ static inline void k_object_free(void *obj) /** @} */ -#include +#include #ifdef __cplusplus } #endif diff --git a/include/zephyr/sys/libc-hooks.h b/include/zephyr/sys/libc-hooks.h index e00efc6de2684..b9c38bb3c4ad5 100644 --- a/include/zephyr/sys/libc-hooks.h +++ b/include/zephyr/sys/libc-hooks.h @@ -109,7 +109,7 @@ extern struct k_mem_partition z_libc_partition; #endif #endif /* CONFIG_USERSPACE */ -#include +#include /* C library memory partitions */ #define Z_LIBC_DATA K_APP_DMEM(z_libc_partition) diff --git a/include/zephyr/sys/mutex.h b/include/zephyr/sys/mutex.h index 1a7968e83cbb5..e34cc90d8d908 100644 --- a/include/zephyr/sys/mutex.h +++ b/include/zephyr/sys/mutex.h @@ -128,7 +128,7 @@ static inline int sys_mutex_unlock(struct sys_mutex *mutex) return z_sys_mutex_kernel_unlock(mutex); } -#include +#include #else #include diff --git a/include/zephyr/sys/time_units.h b/include/zephyr/sys/time_units.h index e088099ef9137..f4deb93fb399f 100644 --- a/include/zephyr/sys/time_units.h +++ b/include/zephyr/sys/time_units.h @@ -2070,7 +2070,7 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) z_tmcvt_64(t, Z_HZ_ticks, Z_HZ_cyc, Z_CCYC, true, false) #if defined(CONFIG_TIMER_READS_ITS_FREQUENCY_AT_RUNTIME) -#include +#include #endif #undef TIME_CONSTEXPR diff --git a/include/zephyr/syscall.h b/include/zephyr/syscall.h index 73a3a648d2378..35cb36554a0a7 100644 --- a/include/zephyr/syscall.h +++ b/include/zephyr/syscall.h @@ -8,7 +8,7 @@ #ifndef ZEPHYR_INCLUDE_SYSCALL_H_ #define ZEPHYR_INCLUDE_SYSCALL_H_ -#include +#include #include #include diff --git a/include/zephyr/usb/usb_ch9.h b/include/zephyr/usb/usb_ch9.h index 8fe33f46b7171..dccc7445daa6f 100644 --- a/include/zephyr/usb/usb_ch9.h +++ b/include/zephyr/usb/usb_ch9.h @@ -12,7 +12,7 @@ * and follows, with few exceptions, the USB Specification 2.0. */ -#include +#include #include #include #include diff --git a/kernel/atomic_c.c b/kernel/atomic_c.c index c873192af74cb..70fff83edb640 100644 --- a/kernel/atomic_c.c +++ b/kernel/atomic_c.c @@ -112,7 +112,7 @@ bool z_vrfy_atomic_cas(atomic_t *target, atomic_val_t old_value, return z_impl_atomic_cas((atomic_t *)target, old_value, new_value); } -#include +#include #endif /* CONFIG_USERSPACE */ bool z_impl_atomic_ptr_cas(atomic_ptr_t *target, atomic_ptr_val_t old_value, @@ -142,7 +142,7 @@ static inline bool z_vrfy_atomic_ptr_cas(atomic_ptr_t *target, return z_impl_atomic_ptr_cas(target, old_value, new_value); } -#include +#include #endif /* CONFIG_USERSPACE */ /** @@ -280,7 +280,7 @@ static inline atomic_ptr_val_t z_vrfy_atomic_ptr_set(atomic_ptr_t *target, return z_impl_atomic_ptr_set(target, value); } -#include +#include #endif /* CONFIG_USERSPACE */ /** @@ -404,11 +404,11 @@ atomic_val_t z_impl_atomic_nand(atomic_t *target, atomic_val_t value) ATOMIC_SYSCALL_HANDLER_TARGET_VALUE(atomic_nand); #ifdef CONFIG_USERSPACE -#include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include #endif /* CONFIG_USERSPACE */ diff --git a/kernel/banner.c b/kernel/banner.c index dc2506fb9b152..d2a431edd9679 100644 --- a/kernel/banner.c +++ b/kernel/banner.c @@ -7,7 +7,7 @@ #include #include #include -#include +#include #if defined(CONFIG_BOOT_DELAY) && (CONFIG_BOOT_DELAY > 0) #define DELAY_STR STRINGIFY(CONFIG_BOOT_DELAY) diff --git a/kernel/busy_wait.c b/kernel/busy_wait.c index cb7c993437d0a..da0ea149e1028 100644 --- a/kernel/busy_wait.c +++ b/kernel/busy_wait.c @@ -52,5 +52,5 @@ static inline void z_vrfy_k_busy_wait(uint32_t usec_to_wait) { z_impl_k_busy_wait(usec_to_wait); } -#include +#include #endif /* CONFIG_USERSPACE */ diff --git a/kernel/condvar.c b/kernel/condvar.c index 2430523cdb905..b8d0df95341fc 100644 --- a/kernel/condvar.c +++ b/kernel/condvar.c @@ -38,7 +38,7 @@ int z_vrfy_k_condvar_init(struct k_condvar *condvar) K_OOPS(K_SYSCALL_OBJ_INIT(condvar, K_OBJ_CONDVAR)); return z_impl_k_condvar_init(condvar); } -#include +#include #endif /* CONFIG_USERSPACE */ int z_impl_k_condvar_signal(struct k_condvar *condvar) @@ -70,7 +70,7 @@ int z_vrfy_k_condvar_signal(struct k_condvar *condvar) K_OOPS(K_SYSCALL_OBJ(condvar, K_OBJ_CONDVAR)); return z_impl_k_condvar_signal(condvar); } -#include +#include #endif /* CONFIG_USERSPACE */ int z_impl_k_condvar_broadcast(struct k_condvar *condvar) @@ -103,7 +103,7 @@ int z_vrfy_k_condvar_broadcast(struct k_condvar *condvar) K_OOPS(K_SYSCALL_OBJ(condvar, K_OBJ_CONDVAR)); return z_impl_k_condvar_broadcast(condvar); } -#include +#include #endif /* CONFIG_USERSPACE */ int z_impl_k_condvar_wait(struct k_condvar *condvar, struct k_mutex *mutex, @@ -132,7 +132,7 @@ int z_vrfy_k_condvar_wait(struct k_condvar *condvar, struct k_mutex *mutex, K_OOPS(K_SYSCALL_OBJ(mutex, K_OBJ_MUTEX)); return z_impl_k_condvar_wait(condvar, mutex, timeout); } -#include +#include #endif /* CONFIG_USERSPACE */ #ifdef CONFIG_OBJ_CORE_CONDVAR diff --git a/kernel/device.c b/kernel/device.c index 4b19d247c0099..45806fc9e76c9 100644 --- a/kernel/device.c +++ b/kernel/device.c @@ -66,7 +66,7 @@ static inline const struct device *z_vrfy_device_get_binding(const char *name) return z_impl_device_get_binding(name_copy); } -#include +#include static inline bool z_vrfy_device_is_ready(const struct device *dev) { @@ -74,7 +74,7 @@ static inline bool z_vrfy_device_is_ready(const struct device *dev) return z_impl_device_is_ready(dev); } -#include +#include #endif /* CONFIG_USERSPACE */ size_t z_device_get_all_static(struct device const **devices) diff --git a/kernel/dynamic.c b/kernel/dynamic.c index 89f80933dd0f1..a9ec33d87bdc8 100644 --- a/kernel/dynamic.c +++ b/kernel/dynamic.c @@ -105,7 +105,7 @@ static inline k_thread_stack_t *z_vrfy_k_thread_stack_alloc(size_t size, int fla { return z_impl_k_thread_stack_alloc(size, flags); } -#include +#include #endif /* CONFIG_USERSPACE */ static void dyn_cb(const struct k_thread *thread, void *user_data) @@ -177,5 +177,5 @@ static inline int z_vrfy_k_thread_stack_free(k_thread_stack_t *stack) return z_impl_k_thread_stack_free(stack); } -#include +#include #endif /* CONFIG_USERSPACE */ diff --git a/kernel/errno.c b/kernel/errno.c index 645597f02c7ef..f268bb72fdf90 100644 --- a/kernel/errno.c +++ b/kernel/errno.c @@ -43,7 +43,7 @@ static inline int *z_vrfy_z_errno(void) { return z_impl_z_errno(); } -#include +#include #else int *z_impl_z_errno(void) diff --git a/kernel/events.c b/kernel/events.c index 082f418cbe054..d2950e43c4f23 100644 --- a/kernel/events.c +++ b/kernel/events.c @@ -71,7 +71,7 @@ void z_vrfy_k_event_init(struct k_event *event) K_OOPS(K_SYSCALL_OBJ_NEVER_INIT(event, K_OBJ_EVENT)); z_impl_k_event_init(event); } -#include +#include #endif /* CONFIG_USERSPACE */ /** @@ -190,7 +190,7 @@ uint32_t z_vrfy_k_event_post(struct k_event *event, uint32_t events) K_OOPS(K_SYSCALL_OBJ(event, K_OBJ_EVENT)); return z_impl_k_event_post(event, events); } -#include +#include #endif /* CONFIG_USERSPACE */ uint32_t z_impl_k_event_set(struct k_event *event, uint32_t events) @@ -204,7 +204,7 @@ uint32_t z_vrfy_k_event_set(struct k_event *event, uint32_t events) K_OOPS(K_SYSCALL_OBJ(event, K_OBJ_EVENT)); return z_impl_k_event_set(event, events); } -#include +#include #endif /* CONFIG_USERSPACE */ uint32_t z_impl_k_event_set_masked(struct k_event *event, uint32_t events, @@ -220,7 +220,7 @@ uint32_t z_vrfy_k_event_set_masked(struct k_event *event, uint32_t events, K_OOPS(K_SYSCALL_OBJ(event, K_OBJ_EVENT)); return z_impl_k_event_set_masked(event, events, events_mask); } -#include +#include #endif /* CONFIG_USERSPACE */ uint32_t z_impl_k_event_clear(struct k_event *event, uint32_t events) @@ -234,7 +234,7 @@ uint32_t z_vrfy_k_event_clear(struct k_event *event, uint32_t events) K_OOPS(K_SYSCALL_OBJ(event, K_OBJ_EVENT)); return z_impl_k_event_clear(event, events); } -#include +#include #endif /* CONFIG_USERSPACE */ static uint32_t k_event_wait_internal(struct k_event *event, uint32_t events, @@ -320,7 +320,7 @@ uint32_t z_vrfy_k_event_wait(struct k_event *event, uint32_t events, K_OOPS(K_SYSCALL_OBJ(event, K_OBJ_EVENT)); return z_impl_k_event_wait(event, events, reset, timeout); } -#include +#include #endif /* CONFIG_USERSPACE */ /** @@ -342,7 +342,7 @@ uint32_t z_vrfy_k_event_wait_all(struct k_event *event, uint32_t events, K_OOPS(K_SYSCALL_OBJ(event, K_OBJ_EVENT)); return z_impl_k_event_wait_all(event, events, reset, timeout); } -#include +#include #endif /* CONFIG_USERSPACE */ #ifdef CONFIG_OBJ_CORE_EVENT diff --git a/kernel/float.c b/kernel/float.c index 69e806d3cd6eb..fa81edf8829d7 100644 --- a/kernel/float.c +++ b/kernel/float.c @@ -35,13 +35,13 @@ static inline int z_vrfy_k_float_disable(struct k_thread *thread) K_OOPS(K_SYSCALL_OBJ(thread, K_OBJ_THREAD)); return z_impl_k_float_disable(thread); } -#include +#include static inline int z_vrfy_k_float_enable(struct k_thread *thread, unsigned int options) { K_OOPS(K_SYSCALL_OBJ(thread, K_OBJ_THREAD)); return z_impl_k_float_enable(thread, options); } -#include +#include #endif /* CONFIG_USERSPACE */ diff --git a/kernel/futex.c b/kernel/futex.c index 813ce0f62e3f0..86acc0c74a02f 100644 --- a/kernel/futex.c +++ b/kernel/futex.c @@ -60,7 +60,7 @@ static inline int z_vrfy_k_futex_wake(struct k_futex *futex, bool wake_all) return z_impl_k_futex_wake(futex, wake_all); } -#include +#include int z_impl_k_futex_wait(struct k_futex *futex, int expected, k_timeout_t timeout) @@ -98,4 +98,4 @@ static inline int z_vrfy_k_futex_wait(struct k_futex *futex, int expected, return z_impl_k_futex_wait(futex, expected, timeout); } -#include +#include diff --git a/kernel/include/kernel_offsets.h b/kernel/include/kernel_offsets.h index 41b310a08188d..a7b1f4e00d37f 100644 --- a/kernel/include/kernel_offsets.h +++ b/kernel/include/kernel_offsets.h @@ -10,7 +10,7 @@ #ifndef ZEPHYR_KERNEL_INCLUDE_KERNEL_OFFSETS_H_ #define ZEPHYR_KERNEL_INCLUDE_KERNEL_OFFSETS_H_ -#include +#include /* All of this is build time magic, but LCOV gets confused. Disable coverage * for this whole file. diff --git a/kernel/include/offsets_short.h b/kernel/include/offsets_short.h index 13e1afe6dfca8..373d7e02ec981 100644 --- a/kernel/include/offsets_short.h +++ b/kernel/include/offsets_short.h @@ -7,7 +7,7 @@ #ifndef ZEPHYR_KERNEL_INCLUDE_OFFSETS_SHORT_H_ #define ZEPHYR_KERNEL_INCLUDE_OFFSETS_SHORT_H_ -#include +#include #include /* kernel */ diff --git a/kernel/init.c b/kernel/init.c index 00765f5483a89..998cb938f1622 100644 --- a/kernel/init.c +++ b/kernel/init.c @@ -395,7 +395,7 @@ static inline int z_vrfy_device_init(const struct device *dev) return z_impl_device_init(dev); } -#include +#include #endif extern void boot_banner(void); diff --git a/kernel/msg_q.c b/kernel/msg_q.c index 5214902b1653b..0c461095c6b0d 100644 --- a/kernel/msg_q.c +++ b/kernel/msg_q.c @@ -97,7 +97,7 @@ int z_vrfy_k_msgq_alloc_init(struct k_msgq *msgq, size_t msg_size, return z_impl_k_msgq_alloc_init(msgq, msg_size, max_msgs); } -#include +#include #endif /* CONFIG_USERSPACE */ int k_msgq_cleanup(struct k_msgq *msgq) @@ -192,7 +192,7 @@ static inline int z_vrfy_k_msgq_put(struct k_msgq *msgq, const void *data, return z_impl_k_msgq_put(msgq, data, timeout); } -#include +#include #endif /* CONFIG_USERSPACE */ void z_impl_k_msgq_get_attrs(struct k_msgq *msgq, struct k_msgq_attrs *attrs) @@ -210,7 +210,7 @@ static inline void z_vrfy_k_msgq_get_attrs(struct k_msgq *msgq, K_OOPS(K_SYSCALL_MEMORY_WRITE(attrs, sizeof(struct k_msgq_attrs))); z_impl_k_msgq_get_attrs(msgq, attrs); } -#include +#include #endif /* CONFIG_USERSPACE */ int z_impl_k_msgq_get(struct k_msgq *msgq, void *data, k_timeout_t timeout) @@ -290,7 +290,7 @@ static inline int z_vrfy_k_msgq_get(struct k_msgq *msgq, void *data, return z_impl_k_msgq_get(msgq, data, timeout); } -#include +#include #endif /* CONFIG_USERSPACE */ int z_impl_k_msgq_peek(struct k_msgq *msgq, void *data) @@ -324,7 +324,7 @@ static inline int z_vrfy_k_msgq_peek(struct k_msgq *msgq, void *data) return z_impl_k_msgq_peek(msgq, data); } -#include +#include #endif /* CONFIG_USERSPACE */ int z_impl_k_msgq_peek_at(struct k_msgq *msgq, void *data, uint32_t idx) @@ -370,7 +370,7 @@ static inline int z_vrfy_k_msgq_peek_at(struct k_msgq *msgq, void *data, uint32_ return z_impl_k_msgq_peek_at(msgq, data, idx); } -#include +#include #endif /* CONFIG_USERSPACE */ void z_impl_k_msgq_purge(struct k_msgq *msgq) @@ -401,21 +401,21 @@ static inline void z_vrfy_k_msgq_purge(struct k_msgq *msgq) K_OOPS(K_SYSCALL_OBJ(msgq, K_OBJ_MSGQ)); z_impl_k_msgq_purge(msgq); } -#include +#include static inline uint32_t z_vrfy_k_msgq_num_free_get(struct k_msgq *msgq) { K_OOPS(K_SYSCALL_OBJ(msgq, K_OBJ_MSGQ)); return z_impl_k_msgq_num_free_get(msgq); } -#include +#include static inline uint32_t z_vrfy_k_msgq_num_used_get(struct k_msgq *msgq) { K_OOPS(K_SYSCALL_OBJ(msgq, K_OBJ_MSGQ)); return z_impl_k_msgq_num_used_get(msgq); } -#include +#include #endif /* CONFIG_USERSPACE */ diff --git a/kernel/mutex.c b/kernel/mutex.c index 3635e7624ca05..d60b08c4e81ba 100644 --- a/kernel/mutex.c +++ b/kernel/mutex.c @@ -76,7 +76,7 @@ static inline int z_vrfy_k_mutex_init(struct k_mutex *mutex) K_OOPS(K_SYSCALL_OBJ_INIT(mutex, K_OBJ_MUTEX)); return z_impl_k_mutex_init(mutex); } -#include +#include #endif /* CONFIG_USERSPACE */ static int32_t new_prio_for_inheritance(int32_t target, int32_t limit) @@ -205,7 +205,7 @@ static inline int z_vrfy_k_mutex_lock(struct k_mutex *mutex, K_OOPS(K_SYSCALL_OBJ(mutex, K_OBJ_MUTEX)); return z_impl_k_mutex_lock(mutex, timeout); } -#include +#include #endif /* CONFIG_USERSPACE */ int z_impl_k_mutex_unlock(struct k_mutex *mutex) @@ -289,7 +289,7 @@ static inline int z_vrfy_k_mutex_unlock(struct k_mutex *mutex) K_OOPS(K_SYSCALL_OBJ(mutex, K_OBJ_MUTEX)); return z_impl_k_mutex_unlock(mutex); } -#include +#include #endif /* CONFIG_USERSPACE */ #ifdef CONFIG_OBJ_CORE_MUTEX diff --git a/kernel/paging/statistics.c b/kernel/paging/statistics.c index 06e867cd218b1..c0617af47c074 100644 --- a/kernel/paging/statistics.c +++ b/kernel/paging/statistics.c @@ -105,7 +105,7 @@ void z_vrfy_k_mem_paging_stats_get(struct k_mem_paging_stats_t *stats) K_OOPS(K_SYSCALL_MEMORY_WRITE(stats, sizeof(*stats))); z_impl_k_mem_paging_stats_get(stats); } -#include +#include #endif /* CONFIG_USERSPACE */ #ifdef CONFIG_DEMAND_PAGING_THREAD_STATS @@ -129,7 +129,7 @@ void z_vrfy_k_mem_paging_thread_stats_get(struct k_thread *thread, K_OOPS(K_SYSCALL_MEMORY_WRITE(stats, sizeof(*stats))); z_impl_k_mem_paging_thread_stats_get(thread, stats); } -#include +#include #endif /* CONFIG_USERSPACE */ #endif /* CONFIG_DEMAND_PAGING_THREAD_STATS */ @@ -227,7 +227,7 @@ void z_vrfy_k_mem_paging_histogram_eviction_get( K_OOPS(K_SYSCALL_MEMORY_WRITE(hist, sizeof(*hist))); z_impl_k_mem_paging_histogram_eviction_get(hist); } -#include +#include static inline void z_vrfy_k_mem_paging_histogram_backing_store_page_in_get( @@ -236,7 +236,7 @@ void z_vrfy_k_mem_paging_histogram_backing_store_page_in_get( K_OOPS(K_SYSCALL_MEMORY_WRITE(hist, sizeof(*hist))); z_impl_k_mem_paging_histogram_backing_store_page_in_get(hist); } -#include +#include static inline void z_vrfy_k_mem_paging_histogram_backing_store_page_out_get( @@ -245,7 +245,7 @@ void z_vrfy_k_mem_paging_histogram_backing_store_page_out_get( K_OOPS(K_SYSCALL_MEMORY_WRITE(hist, sizeof(*hist))); z_impl_k_mem_paging_histogram_backing_store_page_out_get(hist); } -#include +#include #endif /* CONFIG_USERSPACE */ #endif /* CONFIG_DEMAND_PAGING_TIMING_HISTOGRAM */ diff --git a/kernel/pipes.c b/kernel/pipes.c index d91a4d6b7c1a5..a81393c508d1c 100644 --- a/kernel/pipes.c +++ b/kernel/pipes.c @@ -93,7 +93,7 @@ static inline int z_vrfy_k_pipe_alloc_init(struct k_pipe *pipe, size_t size) return z_impl_k_pipe_alloc_init(pipe, size); } -#include +#include #endif /* CONFIG_USERSPACE */ static inline void handle_poll_events(struct k_pipe *pipe) @@ -126,7 +126,7 @@ void z_vrfy_k_pipe_flush(struct k_pipe *pipe) z_impl_k_pipe_flush(pipe); } -#include +#include #endif /* CONFIG_USERSPACE */ void z_impl_k_pipe_buffer_flush(struct k_pipe *pipe) @@ -525,7 +525,7 @@ int z_vrfy_k_pipe_put(struct k_pipe *pipe, const void *data, bytes_to_write, bytes_written, min_xfer, timeout); } -#include +#include #endif /* CONFIG_USERSPACE */ static int pipe_get_internal(k_spinlock_key_t key, struct k_pipe *pipe, @@ -733,7 +733,7 @@ int z_vrfy_k_pipe_get(struct k_pipe *pipe, void *data, size_t bytes_to_read, bytes_to_read, bytes_read, min_xfer, timeout); } -#include +#include #endif /* CONFIG_USERSPACE */ size_t z_impl_k_pipe_read_avail(struct k_pipe *pipe) @@ -770,7 +770,7 @@ size_t z_vrfy_k_pipe_read_avail(struct k_pipe *pipe) return z_impl_k_pipe_read_avail(pipe); } -#include +#include #endif /* CONFIG_USERSPACE */ size_t z_impl_k_pipe_write_avail(struct k_pipe *pipe) @@ -807,7 +807,7 @@ size_t z_vrfy_k_pipe_write_avail(struct k_pipe *pipe) return z_impl_k_pipe_write_avail(pipe); } -#include +#include #endif /* CONFIG_USERSPACE */ #ifdef CONFIG_OBJ_CORE_PIPE diff --git a/kernel/poll.c b/kernel/poll.c index 185aba609c2e6..502e97537b9b6 100644 --- a/kernel/poll.c +++ b/kernel/poll.c @@ -434,7 +434,7 @@ static inline int z_vrfy_k_poll(struct k_poll_event *events, k_free(events_copy); K_OOPS(1); } -#include +#include #endif /* CONFIG_USERSPACE */ /* must be called with interrupts locked */ @@ -493,7 +493,7 @@ static inline void z_vrfy_k_poll_signal_init(struct k_poll_signal *sig) K_OOPS(K_SYSCALL_OBJ_INIT(sig, K_OBJ_POLL_SIGNAL)); z_impl_k_poll_signal_init(sig); } -#include +#include #endif /* CONFIG_USERSPACE */ void z_impl_k_poll_signal_reset(struct k_poll_signal *sig) @@ -521,7 +521,7 @@ void z_vrfy_k_poll_signal_check(struct k_poll_signal *sig, K_OOPS(K_SYSCALL_MEMORY_WRITE(result, sizeof(int))); z_impl_k_poll_signal_check(sig, signaled, result); } -#include +#include #endif /* CONFIG_USERSPACE */ int z_impl_k_poll_signal_raise(struct k_poll_signal *sig, int result) @@ -556,14 +556,14 @@ static inline int z_vrfy_k_poll_signal_raise(struct k_poll_signal *sig, K_OOPS(K_SYSCALL_OBJ(sig, K_OBJ_POLL_SIGNAL)); return z_impl_k_poll_signal_raise(sig, result); } -#include +#include static inline void z_vrfy_k_poll_signal_reset(struct k_poll_signal *sig) { K_OOPS(K_SYSCALL_OBJ(sig, K_OBJ_POLL_SIGNAL)); z_impl_k_poll_signal_reset(sig); } -#include +#include #endif /* CONFIG_USERSPACE */ diff --git a/kernel/queue.c b/kernel/queue.c index fcccde56f9310..a3c99d69e4062 100644 --- a/kernel/queue.c +++ b/kernel/queue.c @@ -75,7 +75,7 @@ static inline void z_vrfy_k_queue_init(struct k_queue *queue) K_OOPS(K_SYSCALL_OBJ_NEVER_INIT(queue, K_OBJ_QUEUE)); z_impl_k_queue_init(queue); } -#include +#include #endif /* CONFIG_USERSPACE */ static void prepare_thread_to_run(struct k_thread *thread, void *data) @@ -117,7 +117,7 @@ static inline void z_vrfy_k_queue_cancel_wait(struct k_queue *queue) K_OOPS(K_SYSCALL_OBJ(queue, K_OBJ_QUEUE)); z_impl_k_queue_cancel_wait(queue); } -#include +#include #endif /* CONFIG_USERSPACE */ static int32_t queue_insert(struct k_queue *queue, void *prev, void *data, @@ -220,7 +220,7 @@ static inline int32_t z_vrfy_k_queue_alloc_append(struct k_queue *queue, K_OOPS(K_SYSCALL_OBJ(queue, K_OBJ_QUEUE)); return z_impl_k_queue_alloc_append(queue, data); } -#include +#include #endif /* CONFIG_USERSPACE */ int32_t z_impl_k_queue_alloc_prepend(struct k_queue *queue, void *data) @@ -241,7 +241,7 @@ static inline int32_t z_vrfy_k_queue_alloc_prepend(struct k_queue *queue, K_OOPS(K_SYSCALL_OBJ(queue, K_OBJ_QUEUE)); return z_impl_k_queue_alloc_prepend(queue, data); } -#include +#include #endif /* CONFIG_USERSPACE */ int k_queue_append_list(struct k_queue *queue, void *head, void *tail) @@ -408,28 +408,28 @@ static inline void *z_vrfy_k_queue_get(struct k_queue *queue, K_OOPS(K_SYSCALL_OBJ(queue, K_OBJ_QUEUE)); return z_impl_k_queue_get(queue, timeout); } -#include +#include static inline int z_vrfy_k_queue_is_empty(struct k_queue *queue) { K_OOPS(K_SYSCALL_OBJ(queue, K_OBJ_QUEUE)); return z_impl_k_queue_is_empty(queue); } -#include +#include static inline void *z_vrfy_k_queue_peek_head(struct k_queue *queue) { K_OOPS(K_SYSCALL_OBJ(queue, K_OBJ_QUEUE)); return z_impl_k_queue_peek_head(queue); } -#include +#include static inline void *z_vrfy_k_queue_peek_tail(struct k_queue *queue) { K_OOPS(K_SYSCALL_OBJ(queue, K_OBJ_QUEUE)); return z_impl_k_queue_peek_tail(queue); } -#include +#include #endif /* CONFIG_USERSPACE */ diff --git a/kernel/sched.c b/kernel/sched.c index 98de4f73963aa..506ad57a141b2 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -521,7 +521,7 @@ static inline void z_vrfy_k_thread_suspend(struct k_thread *thread) K_OOPS(K_SYSCALL_OBJ(thread, K_OBJ_THREAD)); z_impl_k_thread_suspend(thread); } -#include +#include #endif /* CONFIG_USERSPACE */ void z_impl_k_thread_resume(struct k_thread *thread) @@ -550,7 +550,7 @@ static inline void z_vrfy_k_thread_resume(struct k_thread *thread) K_OOPS(K_SYSCALL_OBJ(thread, K_OBJ_THREAD)); z_impl_k_thread_resume(thread); } -#include +#include #endif /* CONFIG_USERSPACE */ static _wait_q_t *pended_on_thread(struct k_thread *thread) @@ -1025,7 +1025,7 @@ static inline void z_vrfy_k_thread_priority_set(k_tid_t thread, int prio) #endif /* CONFIG_USERSPACE_THREAD_MAY_RAISE_PRIORITY */ z_impl_k_thread_priority_set(thread, prio); } -#include +#include #endif /* CONFIG_USERSPACE */ #ifdef CONFIG_SCHED_DEADLINE @@ -1063,7 +1063,7 @@ static inline void z_vrfy_k_thread_deadline_set(k_tid_t tid, int deadline) z_impl_k_thread_deadline_set((k_tid_t)thread, deadline); } -#include +#include #endif /* CONFIG_USERSPACE */ #endif /* CONFIG_SCHED_DEADLINE */ @@ -1095,7 +1095,7 @@ static inline void z_vrfy_k_yield(void) { z_impl_k_yield(); } -#include +#include #endif /* CONFIG_USERSPACE */ static int32_t z_tick_sleep(k_ticks_t ticks) @@ -1173,7 +1173,7 @@ static inline int32_t z_vrfy_k_sleep(k_timeout_t timeout) { return z_impl_k_sleep(timeout); } -#include +#include #endif /* CONFIG_USERSPACE */ int32_t z_impl_k_usleep(int us) @@ -1197,7 +1197,7 @@ static inline int32_t z_vrfy_k_usleep(int us) { return z_impl_k_usleep(us); } -#include +#include #endif /* CONFIG_USERSPACE */ void z_impl_k_wakeup(k_tid_t thread) @@ -1236,7 +1236,7 @@ static inline void z_vrfy_k_wakeup(k_tid_t thread) K_OOPS(K_SYSCALL_OBJ(thread, K_OBJ_THREAD)); z_impl_k_wakeup(thread); } -#include +#include #endif /* CONFIG_USERSPACE */ k_tid_t z_impl_k_sched_current_thread_query(void) @@ -1262,7 +1262,7 @@ static inline k_tid_t z_vrfy_k_sched_current_thread_query(void) { return z_impl_k_sched_current_thread_query(); } -#include +#include #endif /* CONFIG_USERSPACE */ static inline void unpend_all(_wait_q_t *wait_q) @@ -1485,7 +1485,7 @@ static inline int z_vrfy_k_thread_join(struct k_thread *thread, return z_impl_k_thread_join(thread, timeout); } -#include +#include static inline void z_vrfy_k_thread_abort(k_tid_t thread) { @@ -1498,7 +1498,7 @@ static inline void z_vrfy_k_thread_abort(k_tid_t thread) z_impl_k_thread_abort((struct k_thread *)thread); } -#include +#include #endif /* CONFIG_USERSPACE */ /* diff --git a/kernel/sem.c b/kernel/sem.c index 0a8b861cfbec5..f2ae7a6cf78cb 100644 --- a/kernel/sem.c +++ b/kernel/sem.c @@ -79,7 +79,7 @@ int z_vrfy_k_sem_init(struct k_sem *sem, unsigned int initial_count, K_OOPS(K_SYSCALL_OBJ_INIT(sem, K_OBJ_SEM)); return z_impl_k_sem_init(sem, initial_count, limit); } -#include +#include #endif /* CONFIG_USERSPACE */ static inline bool handle_poll_events(struct k_sem *sem) @@ -126,7 +126,7 @@ static inline void z_vrfy_k_sem_give(struct k_sem *sem) K_OOPS(K_SYSCALL_OBJ(sem, K_OBJ_SEM)); z_impl_k_sem_give(sem); } -#include +#include #endif /* CONFIG_USERSPACE */ int z_impl_k_sem_take(struct k_sem *sem, k_timeout_t timeout) @@ -191,21 +191,21 @@ 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(sem, timeout); } -#include +#include static inline void z_vrfy_k_sem_reset(struct k_sem *sem) { K_OOPS(K_SYSCALL_OBJ(sem, K_OBJ_SEM)); z_impl_k_sem_reset(sem); } -#include +#include static inline unsigned int z_vrfy_k_sem_count_get(struct k_sem *sem) { K_OOPS(K_SYSCALL_OBJ(sem, K_OBJ_SEM)); return z_impl_k_sem_count_get(sem); } -#include +#include #endif /* CONFIG_USERSPACE */ diff --git a/kernel/stack.c b/kernel/stack.c index 5c2bae6f61ccd..e637cc3ba663b 100644 --- a/kernel/stack.c +++ b/kernel/stack.c @@ -74,7 +74,7 @@ static inline int32_t z_vrfy_k_stack_alloc_init(struct k_stack *stack, &total_size))); return z_impl_k_stack_alloc_init(stack, num_entries); } -#include +#include #endif /* CONFIG_USERSPACE */ int k_stack_cleanup(struct k_stack *stack) @@ -142,7 +142,7 @@ static inline int z_vrfy_k_stack_push(struct k_stack *stack, stack_data_t data) return z_impl_k_stack_push(stack, data); } -#include +#include #endif /* CONFIG_USERSPACE */ int z_impl_k_stack_pop(struct k_stack *stack, stack_data_t *data, @@ -197,7 +197,7 @@ static inline int z_vrfy_k_stack_pop(struct k_stack *stack, K_OOPS(K_SYSCALL_MEMORY_WRITE(data, sizeof(stack_data_t))); return z_impl_k_stack_pop(stack, data, timeout); } -#include +#include #endif /* CONFIG_USERSPACE */ #ifdef CONFIG_OBJ_CORE_STACK diff --git a/kernel/thread.c b/kernel/thread.c index 3b197743b09ac..7b458d1f8bb2e 100644 --- a/kernel/thread.c +++ b/kernel/thread.c @@ -90,7 +90,7 @@ static inline void z_vrfy_k_thread_custom_data_set(void *data) { z_impl_k_thread_custom_data_set(data); } -#include +#include #endif /* CONFIG_USERSPACE */ void *z_impl_k_thread_custom_data_get(void) @@ -103,7 +103,7 @@ static inline void *z_vrfy_k_thread_custom_data_get(void) { return z_impl_k_thread_custom_data_get(); } -#include +#include #endif /* CONFIG_USERSPACE */ #endif /* CONFIG_THREAD_CUSTOM_DATA */ @@ -118,7 +118,7 @@ static inline int z_vrfy_k_is_preempt_thread(void) { return z_impl_k_is_preempt_thread(); } -#include +#include #endif /* CONFIG_USERSPACE */ int z_impl_k_thread_priority_get(k_tid_t thread) @@ -132,7 +132,7 @@ static inline int z_vrfy_k_thread_priority_get(k_tid_t thread) K_OOPS(K_SYSCALL_OBJ(thread, K_OBJ_THREAD)); return z_impl_k_thread_priority_get(thread); } -#include +#include #endif /* CONFIG_USERSPACE */ int z_impl_k_thread_name_set(struct k_thread *thread, const char *value) @@ -183,7 +183,7 @@ static inline int z_vrfy_k_thread_name_set(struct k_thread *thread, const char * return -ENOSYS; #endif /* CONFIG_THREAD_NAME */ } -#include +#include #endif /* CONFIG_USERSPACE */ const char *k_thread_name_get(k_tid_t thread) @@ -304,7 +304,7 @@ static inline int z_vrfy_k_thread_name_copy(k_tid_t thread, return -ENOSYS; #endif /* CONFIG_THREAD_NAME */ } -#include +#include #endif /* CONFIG_USERSPACE */ #ifdef CONFIG_STACK_SENTINEL @@ -353,7 +353,7 @@ static inline void z_vrfy_k_thread_start(struct k_thread *thread) K_OOPS(K_SYSCALL_OBJ(thread, K_OBJ_THREAD)); return z_impl_k_thread_start(thread); } -#include +#include #endif /* CONFIG_USERSPACE */ #if defined(CONFIG_STACK_POINTER_RANDOM) && (CONFIG_STACK_POINTER_RANDOM != 0) @@ -741,7 +741,7 @@ k_tid_t z_vrfy_k_thread_create(struct k_thread *new_thread, return new_thread; } -#include +#include #endif /* CONFIG_USERSPACE */ void z_init_thread_base(struct _thread_base *thread_base, int priority, @@ -895,7 +895,7 @@ int z_vrfy_k_thread_stack_space_get(const struct k_thread *thread, return 0; } -#include +#include #endif /* CONFIG_USERSPACE */ #endif /* CONFIG_INIT_STACKS && CONFIG_THREAD_STACK_INFO */ @@ -906,7 +906,7 @@ static inline k_ticks_t z_vrfy_k_thread_timeout_remaining_ticks( K_OOPS(K_SYSCALL_OBJ(thread, K_OBJ_THREAD)); return z_impl_k_thread_timeout_remaining_ticks(thread); } -#include +#include static inline k_ticks_t z_vrfy_k_thread_timeout_expires_ticks( const struct k_thread *thread) @@ -914,7 +914,7 @@ static inline k_ticks_t z_vrfy_k_thread_timeout_expires_ticks( K_OOPS(K_SYSCALL_OBJ(thread, K_OBJ_THREAD)); return z_impl_k_thread_timeout_expires_ticks(thread); } -#include +#include #endif /* CONFIG_USERSPACE */ #ifdef CONFIG_INSTRUMENT_THREAD_SWITCHING diff --git a/kernel/timeout.c b/kernel/timeout.c index cf4a6d681d585..1a8a361457a14 100644 --- a/kernel/timeout.c +++ b/kernel/timeout.c @@ -32,7 +32,7 @@ static inline int z_vrfy_sys_clock_hw_cycles_per_sec_runtime_get(void) { return z_impl_sys_clock_hw_cycles_per_sec_runtime_get(); } -#include +#include #endif /* CONFIG_USERSPACE */ #endif /* CONFIG_TIMER_READS_ITS_FREQUENCY_AT_RUNTIME */ @@ -287,7 +287,7 @@ static inline int64_t z_vrfy_k_uptime_ticks(void) { return z_impl_k_uptime_ticks(); } -#include +#include #endif /* CONFIG_USERSPACE */ k_timepoint_t sys_timepoint_calc(k_timeout_t timeout) diff --git a/kernel/timer.c b/kernel/timer.c index 8eafbb4d7e34e..466cab6c4842f 100644 --- a/kernel/timer.c +++ b/kernel/timer.c @@ -188,7 +188,7 @@ static inline void z_vrfy_k_timer_start(struct k_timer *timer, K_OOPS(K_SYSCALL_OBJ(timer, K_OBJ_TIMER)); z_impl_k_timer_start(timer, duration, period); } -#include +#include #endif /* CONFIG_USERSPACE */ void z_impl_k_timer_stop(struct k_timer *timer) @@ -221,7 +221,7 @@ static inline void z_vrfy_k_timer_stop(struct k_timer *timer) K_OOPS(K_SYSCALL_OBJ(timer, K_OBJ_TIMER)); z_impl_k_timer_stop(timer); } -#include +#include #endif /* CONFIG_USERSPACE */ uint32_t z_impl_k_timer_status_get(struct k_timer *timer) @@ -241,7 +241,7 @@ static inline uint32_t z_vrfy_k_timer_status_get(struct k_timer *timer) K_OOPS(K_SYSCALL_OBJ(timer, K_OBJ_TIMER)); return z_impl_k_timer_status_get(timer); } -#include +#include #endif /* CONFIG_USERSPACE */ uint32_t z_impl_k_timer_status_sync(struct k_timer *timer) @@ -309,7 +309,7 @@ static inline uint32_t z_vrfy_k_timer_status_sync(struct k_timer *timer) K_OOPS(K_SYSCALL_OBJ(timer, K_OBJ_TIMER)); return z_impl_k_timer_status_sync(timer); } -#include +#include static inline k_ticks_t z_vrfy_k_timer_remaining_ticks( const struct k_timer *timer) @@ -317,7 +317,7 @@ static inline k_ticks_t z_vrfy_k_timer_remaining_ticks( K_OOPS(K_SYSCALL_OBJ(timer, K_OBJ_TIMER)); return z_impl_k_timer_remaining_ticks(timer); } -#include +#include static inline k_ticks_t z_vrfy_k_timer_expires_ticks( const struct k_timer *timer) @@ -325,14 +325,14 @@ static inline k_ticks_t z_vrfy_k_timer_expires_ticks( K_OOPS(K_SYSCALL_OBJ(timer, K_OBJ_TIMER)); return z_impl_k_timer_expires_ticks(timer); } -#include +#include static inline void *z_vrfy_k_timer_user_data_get(const struct k_timer *timer) { K_OOPS(K_SYSCALL_OBJ(timer, K_OBJ_TIMER)); return z_impl_k_timer_user_data_get(timer); } -#include +#include static inline void z_vrfy_k_timer_user_data_set(struct k_timer *timer, void *user_data) @@ -340,7 +340,7 @@ static inline void z_vrfy_k_timer_user_data_set(struct k_timer *timer, K_OOPS(K_SYSCALL_OBJ(timer, K_OBJ_TIMER)); z_impl_k_timer_user_data_set(timer, user_data); } -#include +#include #endif /* CONFIG_USERSPACE */ diff --git a/kernel/userspace.c b/kernel/userspace.c index 664971e2727e2..55432586fed09 100644 --- a/kernel/userspace.c +++ b/kernel/userspace.c @@ -94,7 +94,7 @@ const char *otype_to_str(enum k_objects otype) case K_OBJ_ANY: ret = "generic"; break; -#include +#include default: ret = "?"; break; @@ -192,7 +192,7 @@ static size_t obj_size_get(enum k_objects otype) size_t ret; switch (otype) { -#include +#include default: ret = sizeof(const struct device); break; diff --git a/kernel/userspace_handler.c b/kernel/userspace_handler.c index da4053b4bdbda..ab6e4f0623c7f 100644 --- a/kernel/userspace_handler.c +++ b/kernel/userspace_handler.c @@ -64,7 +64,7 @@ static inline void z_vrfy_k_object_access_grant(const void *object, object)); k_thread_perms_set(ko, thread); } -#include +#include static inline void z_vrfy_k_object_release(const void *object) { @@ -74,16 +74,16 @@ static inline void z_vrfy_k_object_release(const void *object) K_OOPS(K_SYSCALL_VERIFY_MSG(ko != NULL, "object %p access denied", object)); k_thread_perms_clear(ko, _current); } -#include +#include static inline void *z_vrfy_k_object_alloc(enum k_objects otype) { return z_impl_k_object_alloc(otype); } -#include +#include static inline void *z_vrfy_k_object_alloc_size(enum k_objects otype, size_t size) { return z_impl_k_object_alloc_size(otype, size); } -#include +#include diff --git a/kernel/version.c b/kernel/version.c index 799e555f1aaa5..029671f8259e0 100644 --- a/kernel/version.c +++ b/kernel/version.c @@ -5,7 +5,7 @@ */ #include -#include "version.h" /* generated by MAKE, at compile time */ +#include /* generated by MAKE, at compile time */ /** * @brief Return the kernel version of the present build diff --git a/lib/libc/arcmwdt/libc-hooks.c b/lib/libc/arcmwdt/libc-hooks.c index babf24ebda8c9..8e094d25975f0 100644 --- a/lib/libc/arcmwdt/libc-hooks.c +++ b/lib/libc/arcmwdt/libc-hooks.c @@ -59,7 +59,7 @@ static inline int z_vrfy_zephyr_write_stdout(const void *buf, int nbytes) K_OOPS(K_SYSCALL_MEMORY_READ(buf, nbytes)); return z_impl_zephyr_write_stdout(buf, nbytes); } -#include +#include #endif #ifndef CONFIG_POSIX_API diff --git a/lib/libc/minimal/source/stdout/stdout_console.c b/lib/libc/minimal/source/stdout/stdout_console.c index 33ea7ffaa66d8..e3d5a374a53d4 100644 --- a/lib/libc/minimal/source/stdout/stdout_console.c +++ b/lib/libc/minimal/source/stdout/stdout_console.c @@ -35,7 +35,7 @@ static inline int z_vrfy_zephyr_fputc(int c, FILE *stream) { return z_impl_zephyr_fputc(c, stream); } -#include +#include #endif int fputc(int c, FILE *stream) @@ -105,7 +105,7 @@ static inline size_t z_vrfy_zephyr_fwrite(const void *ZRESTRICT ptr, return z_impl_zephyr_fwrite((const void *ZRESTRICT)ptr, size, nitems, (FILE *ZRESTRICT)stream); } -#include +#include #endif size_t fwrite(const void *ZRESTRICT ptr, size_t size, size_t nitems, diff --git a/lib/libc/newlib/libc-hooks.c b/lib/libc/newlib/libc-hooks.c index 5e8629d441247..75a2859fb42a6 100644 --- a/lib/libc/newlib/libc-hooks.c +++ b/lib/libc/newlib/libc-hooks.c @@ -184,7 +184,7 @@ static inline int z_vrfy_zephyr_read_stdin(char *buf, int nbytes) K_OOPS(K_SYSCALL_MEMORY_WRITE(buf, nbytes)); return z_impl_zephyr_read_stdin((char *)buf, nbytes); } -#include +#include #endif int z_impl_zephyr_write_stdout(const void *buffer, int nbytes) @@ -207,7 +207,7 @@ static inline int z_vrfy_zephyr_write_stdout(const void *buf, int nbytes) K_OOPS(K_SYSCALL_MEMORY_READ(buf, nbytes)); return z_impl_zephyr_write_stdout((const void *)buf, nbytes); } -#include +#include #endif #ifndef CONFIG_POSIX_API diff --git a/lib/libc/picolibc/libc-hooks.c b/lib/libc/picolibc/libc-hooks.c index e7539bc5dfe11..cefb0d46ddd37 100644 --- a/lib/libc/picolibc/libc-hooks.c +++ b/lib/libc/picolibc/libc-hooks.c @@ -39,7 +39,7 @@ static inline int z_vrfy_zephyr_fputc(int c, FILE *stream) { return z_impl_zephyr_fputc(c, stream); } -#include +#include #endif static int picolibc_put(char a, FILE *f) diff --git a/lib/os/mutex.c b/lib/os/mutex.c index e1c6d7fb48f12..9bfcf6368dd99 100644 --- a/lib/os/mutex.c +++ b/lib/os/mutex.c @@ -50,7 +50,7 @@ static inline int z_vrfy_z_sys_mutex_kernel_lock(struct sys_mutex *mutex, return z_impl_z_sys_mutex_kernel_lock(mutex, timeout); } -#include +#include int z_impl_z_sys_mutex_kernel_unlock(struct sys_mutex *mutex) { @@ -71,4 +71,4 @@ static inline int z_vrfy_z_sys_mutex_kernel_unlock(struct sys_mutex *mutex) return z_impl_z_sys_mutex_kernel_unlock(mutex); } -#include +#include diff --git a/lib/os/printk.c b/lib/os/printk.c index 71a0d6aeac8b9..cb4073fed74af 100644 --- a/lib/os/printk.c +++ b/lib/os/printk.c @@ -178,7 +178,7 @@ static inline void z_vrfy_k_str_out(char *c, size_t n) K_OOPS(K_SYSCALL_MEMORY_READ(c, n)); z_impl_k_str_out((char *)c, n); } -#include +#include #endif /* CONFIG_USERSPACE */ /** diff --git a/lib/posix/options/clock.c b/lib/posix/options/clock.c index 48789ae49c254..68692b5ecd6f9 100644 --- a/lib/posix/options/clock.c +++ b/lib/posix/options/clock.c @@ -57,7 +57,7 @@ int z_vrfy___posix_clock_get_base(clockid_t clock_id, struct timespec *ts) K_OOPS(K_SYSCALL_MEMORY_WRITE(ts, sizeof(*ts))); return z_impl___posix_clock_get_base(clock_id, ts); } -#include +#include #endif int clock_gettime(clockid_t clock_id, struct timespec *ts) diff --git a/lib/posix/options/posix_clock.h b/lib/posix/options/posix_clock.h index a665f4ce06d90..f505dbc175271 100644 --- a/lib/posix/options/posix_clock.h +++ b/lib/posix/options/posix_clock.h @@ -14,6 +14,6 @@ __syscall int __posix_clock_get_base(clockid_t clock_id, struct timespec *ts); -#include +#include #endif diff --git a/lib/posix/options/uname.c b/lib/posix/options/uname.c index eb1d9a3f4630a..decba8dd01435 100644 --- a/lib/posix/options/uname.c +++ b/lib/posix/options/uname.c @@ -4,11 +4,11 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include "version.h" #include #include #include #include +#include #ifdef CONFIG_NET_HOSTNAME_ENABLE #define UTSNAME_NODENAME CONFIG_NET_HOSTNAME diff --git a/samples/posix/env/src/main.c b/samples/posix/env/src/main.c index 9385abce64412..9ae50c36cd1af 100644 --- a/samples/posix/env/src/main.c +++ b/samples/posix/env/src/main.c @@ -4,8 +4,6 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include "version.h" - #include #include #include @@ -15,6 +13,7 @@ #include #include +#include #ifdef BUILD_VERSION #define VERSION_BUILD STRINGIFY(BUILD_VERSION) diff --git a/samples/subsys/llext/edk/app/include/app_api.h b/samples/subsys/llext/edk/app/include/app_api.h index bc6cb49dca85e..73d8fe3133d84 100644 --- a/samples/subsys/llext/edk/app/include/app_api.h +++ b/samples/subsys/llext/edk/app/include/app_api.h @@ -34,5 +34,5 @@ extern "C" { } #endif -#include +#include #endif /* _TEST_EDK_H_ */ diff --git a/samples/subsys/llext/edk/app/src/pubsub.c b/samples/subsys/llext/edk/app/src/pubsub.c index fa7641be4616c..79719af1b2b91 100644 --- a/samples/subsys/llext/edk/app/src/pubsub.c +++ b/samples/subsys/llext/edk/app/src/pubsub.c @@ -151,7 +151,7 @@ static inline int z_vrfy_publish(enum Channels channel, void *data, return ret; } -#include +#include #endif int z_impl_receive(enum Channels channel, void *data, size_t data_len) @@ -182,7 +182,7 @@ static inline int z_vrfy_receive(enum Channels channel, void *data, return z_impl_receive(channel, data, data_len); } -#include +#include #endif int z_impl_register_subscriber(enum Channels channel, struct k_event *evt) @@ -218,5 +218,5 @@ static inline int z_vrfy_register_subscriber(enum Channels channel, return z_impl_register_subscriber(channel, evt); } -#include +#include #endif diff --git a/samples/subsys/shell/shell_module/src/main.c b/samples/subsys/shell/shell_module/src/main.c index a3248cc7dc34e..c7519c7485c65 100644 --- a/samples/subsys/shell/shell_module/src/main.c +++ b/samples/subsys/shell/shell_module/src/main.c @@ -6,7 +6,7 @@ #include #include -#include +#include #include #include #include diff --git a/samples/userspace/prod_consumer/src/app_syscall.c b/samples/userspace/prod_consumer/src/app_syscall.c index c1b630ba9f2ad..28090260c5a24 100644 --- a/samples/userspace/prod_consumer/src/app_syscall.c +++ b/samples/userspace/prod_consumer/src/app_syscall.c @@ -54,4 +54,4 @@ static int z_vrfy_magic_syscall(unsigned int *cookie) return ret; } -#include +#include diff --git a/samples/userspace/prod_consumer/src/app_syscall.h b/samples/userspace/prod_consumer/src/app_syscall.h index 7a6d1ff19b6c8..cda913ac6c588 100644 --- a/samples/userspace/prod_consumer/src/app_syscall.h +++ b/samples/userspace/prod_consumer/src/app_syscall.h @@ -8,6 +8,6 @@ __syscall int magic_syscall(unsigned int *cookie); -#include +#include #endif /* MAGIC_SYSCALL_H */ diff --git a/samples/userspace/prod_consumer/src/sample_driver.h b/samples/userspace/prod_consumer/src/sample_driver.h index 0f5eaecee5d40..88329313434aa 100644 --- a/samples/userspace/prod_consumer/src/sample_driver.h +++ b/samples/userspace/prod_consumer/src/sample_driver.h @@ -86,6 +86,6 @@ static inline int sample_driver_set_callback(const struct device *dev, return api->set_callback(dev, cb, context); } -#include +#include #endif diff --git a/samples/userspace/prod_consumer/src/sample_driver_handlers.c b/samples/userspace/prod_consumer/src/sample_driver_handlers.c index 89a4ff1204462..333204eac7966 100644 --- a/samples/userspace/prod_consumer/src/sample_driver_handlers.c +++ b/samples/userspace/prod_consumer/src/sample_driver_handlers.c @@ -17,7 +17,7 @@ int z_vrfy_sample_driver_state_set(const struct device *dev, bool active) return z_impl_sample_driver_state_set(dev, active); } -#include +#include int z_vrfy_sample_driver_write(const struct device *dev, void *buf) { @@ -31,4 +31,4 @@ int z_vrfy_sample_driver_write(const struct device *dev, void *buf) return z_impl_sample_driver_write(dev, buf); } -#include +#include diff --git a/scripts/build/gen_syscalls.py b/scripts/build/gen_syscalls.py index b6e332d45caef..84f6b546bde58 100755 --- a/scripts/build/gen_syscalls.py +++ b/scripts/build/gen_syscalls.py @@ -91,7 +91,7 @@ #include -#include +#include #include #include @@ -476,7 +476,7 @@ def main(): if mrsh and to_emit: syscall = typename_split(match_group[0])[1] mrsh_defs[syscall] = mrsh - mrsh_includes[syscall] = "#include " % fn + mrsh_includes[syscall] = "#include " % fn with open(args.syscall_dispatch, "w") as fp: table_entries.append("[K_SYSCALL_BAD] = handler_bad_syscall") diff --git a/soc/andestech/ae350/soc_irq.S b/soc/andestech/ae350/soc_irq.S index f057cd8804fcc..d5e28d307f5ac 100644 --- a/soc/andestech/ae350/soc_irq.S +++ b/soc/andestech/ae350/soc_irq.S @@ -6,7 +6,7 @@ #include "soc_v5.h" -#include +#include #include #ifdef CONFIG_RISCV_SOC_CONTEXT_SAVE diff --git a/soc/common/riscv-privileged/soc_irq.S b/soc/common/riscv-privileged/soc_irq.S index acf7e724aea47..21d6bd56f99df 100644 --- a/soc/common/riscv-privileged/soc_irq.S +++ b/soc/common/riscv-privileged/soc_irq.S @@ -9,7 +9,7 @@ * privileged architecture specification */ #include -#include +#include #include #include #include diff --git a/soc/espressif/esp32/gdbstub.c b/soc/espressif/esp32/gdbstub.c index c8913b7f5a27d..835c2ff51f72a 100644 --- a/soc/espressif/esp32/gdbstub.c +++ b/soc/espressif/esp32/gdbstub.c @@ -7,7 +7,7 @@ #include #include #include -#include +#include /* * Address Mappings From ESP32 Technical Reference Manual Version 4.5 diff --git a/soc/espressif/esp32c3/soc_irq.S b/soc/espressif/esp32c3/soc_irq.S index 6ce11ae6a8187..0a9e917f5087c 100644 --- a/soc/espressif/esp32c3/soc_irq.S +++ b/soc/espressif/esp32c3/soc_irq.S @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include +#include #include /* Exports */ diff --git a/soc/intel/intel_adsp/common/multiprocessing.c b/soc/intel/intel_adsp/common/multiprocessing.c index dfd7bd2106e7b..3797e283dd581 100644 --- a/soc/intel/intel_adsp/common/multiprocessing.c +++ b/soc/intel/intel_adsp/common/multiprocessing.c @@ -17,7 +17,7 @@ #include LOG_MODULE_REGISTER(soc_mp, CONFIG_SOC_LOG_LEVEL); -#include +#include #include #include #include diff --git a/soc/ite/ec/common/soc_irq.S b/soc/ite/ec/common/soc_irq.S index ceb0f3afecb7e..c0f78103ec42b 100644 --- a/soc/ite/ec/common/soc_irq.S +++ b/soc/ite/ec/common/soc_irq.S @@ -9,7 +9,7 @@ * privileged architecture specification */ #include -#include +#include #include #include #include diff --git a/soc/nordic/common/vpr/soc_context.S b/soc/nordic/common/vpr/soc_context.S index 82c8ecfe5985e..19d041dce6d3c 100644 --- a/soc/nordic/common/vpr/soc_context.S +++ b/soc/nordic/common/vpr/soc_context.S @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include +#include #include GTEXT(__soc_save_context) diff --git a/soc/openisa/rv32m1/soc_irq.S b/soc/openisa/rv32m1/soc_irq.S index d3059d2bd2809..8333faa4236ca 100644 --- a/soc/openisa/rv32m1/soc_irq.S +++ b/soc/openisa/rv32m1/soc_irq.S @@ -4,7 +4,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include +#include #include #include diff --git a/soc/telink/tlsr/tlsr951x/soc_irq.S b/soc/telink/tlsr/tlsr951x/soc_irq.S index ea43de3684bb6..76b3ac5a45dc6 100644 --- a/soc/telink/tlsr/tlsr951x/soc_irq.S +++ b/soc/telink/tlsr/tlsr951x/soc_irq.S @@ -4,7 +4,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include +#include #include #include diff --git a/subsys/bindesc/bindesc_version.c b/subsys/bindesc/bindesc_version.c index d1c3a905aa046..76111ca17bb8c 100644 --- a/subsys/bindesc/bindesc_version.c +++ b/subsys/bindesc/bindesc_version.c @@ -6,7 +6,7 @@ #include #include -#include +#include #if IS_ENABLED(CONFIG_BINDESC_KERNEL_VERSION_STRING) BINDESC_STR_DEFINE(kernel_version_string, BINDESC_ID_KERNEL_VERSION_STRING, @@ -34,7 +34,7 @@ BINDESC_UINT_DEFINE(kernel_version_number, BINDESC_ID_KERNEL_VERSION_NUMBER, #endif /* IS_ENABLED(CONFIG_BINDESC_KERNEL_VERSION_NUMBER) */ #if IS_ENABLED(HAS_APP_VERSION) -#include +#include #if IS_ENABLED(CONFIG_BINDESC_APP_VERSION_STRING) BINDESC_STR_DEFINE(app_version_string, BINDESC_ID_APP_VERSION_STRING, diff --git a/subsys/bluetooth/controller/hci/hci.c b/subsys/bluetooth/controller/hci/hci.c index 247a50959da9d..0edc10310cb0f 100644 --- a/subsys/bluetooth/controller/hci/hci.c +++ b/subsys/bluetooth/controller/hci/hci.c @@ -8,7 +8,7 @@ #include #include -#include +#include #include #include diff --git a/subsys/logging/log_core.c b/subsys/logging/log_core.c index 3e767092b762c..68e08547e98ea 100644 --- a/subsys/logging/log_core.c +++ b/subsys/logging/log_core.c @@ -458,7 +458,7 @@ void z_vrfy_log_panic(void) { z_impl_log_panic(); } -#include +#include #endif static bool msg_filter_check(struct log_backend const *backend, @@ -594,7 +594,7 @@ bool z_vrfy_log_process(void) { return z_impl_log_process(); } -#include +#include #endif uint32_t z_impl_log_buffered_cnt(void) @@ -607,7 +607,7 @@ uint32_t z_vrfy_log_buffered_cnt(void) { return z_impl_log_buffered_cnt(); } -#include +#include #endif void z_log_dropped(bool buffered) diff --git a/subsys/logging/log_mgmt.c b/subsys/logging/log_mgmt.c index ec6441379e37c..dbde3d24b44ce 100644 --- a/subsys/logging/log_mgmt.c +++ b/subsys/logging/log_mgmt.c @@ -498,7 +498,7 @@ uint32_t z_vrfy_log_filter_set(struct log_backend const *const backend, return z_impl_log_filter_set(NULL, domain_id, src_id, level); } -#include +#include #endif static void link_filter_set(const struct log_link *link, diff --git a/subsys/logging/log_msg.c b/subsys/logging/log_msg.c index 11a8a9735d36b..0d40c5b3155f3 100644 --- a/subsys/logging/log_msg.c +++ b/subsys/logging/log_msg.c @@ -337,7 +337,7 @@ static inline void z_vrfy_z_log_msg_static_create(const void *source, { return z_impl_z_log_msg_static_create(source, desc, package, data); } -#include +#include #endif void z_log_msg_runtime_vcreate(uint8_t domain_id, const void *source, diff --git a/subsys/mgmt/mcumgr/grp/os_mgmt/src/os_mgmt.c b/subsys/mgmt/mcumgr/grp/os_mgmt/src/os_mgmt.c index 9fc02f81661a8..e46c6aa8214aa 100644 --- a/subsys/mgmt/mcumgr/grp/os_mgmt/src/os_mgmt.c +++ b/subsys/mgmt/mcumgr/grp/os_mgmt/src/os_mgmt.c @@ -40,7 +40,7 @@ #if defined(CONFIG_MCUMGR_GRP_OS_INFO) || defined(CONFIG_MCUMGR_GRP_OS_BOOTLOADER_INFO) #include -#include +#include #if defined(CONFIG_MCUMGR_GRP_OS_INFO) #include #endif diff --git a/subsys/mgmt/mcumgr/transport/src/smp_shell.c b/subsys/mgmt/mcumgr/transport/src/smp_shell.c index 0660235ab69f9..669f46391e9dd 100644 --- a/subsys/mgmt/mcumgr/transport/src/smp_shell.c +++ b/subsys/mgmt/mcumgr/transport/src/smp_shell.c @@ -19,7 +19,7 @@ #include #include #include -#include +#include #include #include diff --git a/subsys/mgmt/updatehub/updatehub_handlers.c b/subsys/mgmt/updatehub/updatehub_handlers.c index 4d88973175815..498b0b59caea6 100644 --- a/subsys/mgmt/updatehub/updatehub_handlers.c +++ b/subsys/mgmt/updatehub/updatehub_handlers.c @@ -12,28 +12,28 @@ static inline void z_vrfy_updatehub_autohandler(void) { z_impl_updatehub_autohandler(); } -#include +#include static inline enum updatehub_response z_vrfy_updatehub_probe(void) { return z_impl_updatehub_probe(); } -#include +#include static inline enum updatehub_response z_vrfy_updatehub_update(void) { return z_impl_updatehub_update(); } -#include +#include static inline int z_vrfy_updatehub_confirm(void) { return z_impl_updatehub_confirm(); } -#include +#include static inline int z_vrfy_updatehub_reboot(void) { return z_impl_updatehub_reboot(); } -#include +#include diff --git a/subsys/net/ip/net_if.c b/subsys/net/ip/net_if.c index dc115aaf2c329..e1903668b8ddf 100644 --- a/subsys/net/ip/net_if.c +++ b/subsys/net/ip/net_if.c @@ -166,7 +166,7 @@ struct net_if *z_vrfy_net_if_get_by_index(int index) return iface; } -#include +#include #endif static inline void net_context_send_cb(struct net_context *context, @@ -1646,7 +1646,7 @@ static inline int z_vrfy_net_if_ipv6_addr_lookup_by_index( return z_impl_net_if_ipv6_addr_lookup_by_index(&addr_v6); } -#include +#include #endif /* To be called when interface comes up so that all the non-joined multicast @@ -2007,7 +2007,7 @@ bool z_vrfy_net_if_ipv6_addr_add_by_index(int index, vlifetime); } -#include +#include #endif /* CONFIG_USERSPACE */ bool z_impl_net_if_ipv6_addr_rm_by_index(int index, @@ -2040,7 +2040,7 @@ bool z_vrfy_net_if_ipv6_addr_rm_by_index(int index, return z_impl_net_if_ipv6_addr_rm_by_index(index, &addr_v6); } -#include +#include #endif /* CONFIG_USERSPACE */ void net_if_ipv6_addr_foreach(struct net_if *iface, net_if_ip_addr_cb_t cb, @@ -3844,7 +3844,7 @@ static inline int z_vrfy_net_if_ipv4_addr_lookup_by_index( return z_impl_net_if_ipv4_addr_lookup_by_index(&addr_v4); } -#include +#include #endif struct in_addr net_if_ipv4_get_netmask_by_addr(struct net_if *iface, @@ -4056,7 +4056,7 @@ bool z_vrfy_net_if_ipv4_set_netmask_by_index(int index, return z_impl_net_if_ipv4_set_netmask_by_index(index, &netmask_addr); } -#include +#include bool z_vrfy_net_if_ipv4_set_netmask_by_addr_by_index(int index, const struct in_addr *addr, @@ -4080,7 +4080,7 @@ bool z_vrfy_net_if_ipv4_set_netmask_by_addr_by_index(int index, &netmask_addr); } -#include +#include #endif /* CONFIG_USERSPACE */ void net_if_ipv4_set_gw(struct net_if *iface, const struct in_addr *gw) @@ -4132,7 +4132,7 @@ bool z_vrfy_net_if_ipv4_set_gw_by_index(int index, return z_impl_net_if_ipv4_set_gw_by_index(index, &gw_addr); } -#include +#include #endif /* CONFIG_USERSPACE */ static struct net_if_addr *ipv4_addr_find(struct net_if *iface, @@ -4295,7 +4295,7 @@ bool z_vrfy_net_if_ipv4_addr_add_by_index(int index, vlifetime); } -#include +#include #endif /* CONFIG_USERSPACE */ bool z_impl_net_if_ipv4_addr_rm_by_index(int index, @@ -4328,7 +4328,7 @@ bool z_vrfy_net_if_ipv4_addr_rm_by_index(int index, return (uint32_t)z_impl_net_if_ipv4_addr_rm_by_index(index, &addr_v4); } -#include +#include #endif /* CONFIG_USERSPACE */ void net_if_ipv4_addr_foreach(struct net_if *iface, net_if_ip_addr_cb_t cb, diff --git a/subsys/net/ip/utils.c b/subsys/net/ip/utils.c index 623bb2b89e22b..51048b0eeb6b6 100644 --- a/subsys/net/ip/utils.c +++ b/subsys/net/ip/utils.c @@ -340,7 +340,7 @@ char *z_vrfy_net_addr_ntop(sa_family_t family, const void *src, return dst; } -#include +#include #endif /* CONFIG_USERSPACE */ int z_impl_net_addr_pton(sa_family_t family, const char *src, @@ -512,7 +512,7 @@ int z_vrfy_net_addr_pton(sa_family_t family, const char *src, return 0; } -#include +#include #endif /* CONFIG_USERSPACE */ diff --git a/subsys/net/l2/ethernet/ethernet.c b/subsys/net/l2/ethernet/ethernet.c index 1f448d454efd1..76591856be890 100644 --- a/subsys/net/l2/ethernet/ethernet.c +++ b/subsys/net/l2/ethernet/ethernet.c @@ -869,7 +869,7 @@ static inline const struct device *z_vrfy_net_eth_get_ptp_clock_by_index(int ind { return z_impl_net_eth_get_ptp_clock_by_index(index); } -#include +#include #endif /* CONFIG_USERSPACE */ #else /* CONFIG_PTP_CLOCK */ const struct device *z_impl_net_eth_get_ptp_clock_by_index(int index) diff --git a/subsys/net/l2/openthread/openthread.c b/subsys/net/l2/openthread/openthread.c index d820e083d8b04..2ba600f35e99b 100644 --- a/subsys/net/l2/openthread/openthread.c +++ b/subsys/net/l2/openthread/openthread.c @@ -19,7 +19,7 @@ LOG_MODULE_REGISTER(net_l2_openthread, CONFIG_OPENTHREAD_L2_LOG_LEVEL); #include #include #include -#include +#include #include #include diff --git a/subsys/net/lib/sockets/getaddrinfo.c b/subsys/net/lib/sockets/getaddrinfo.c index 70e320017709d..b0c01ab50c1cb 100644 --- a/subsys/net/lib/sockets/getaddrinfo.c +++ b/subsys/net/lib/sockets/getaddrinfo.c @@ -346,7 +346,7 @@ static inline int z_vrfy_z_zsock_getaddrinfo_internal(const char *host, return ret; } -#include +#include #endif /* CONFIG_USERSPACE */ #endif /* defined(CONFIG_DNS_RESOLVER) */ diff --git a/subsys/net/lib/sockets/socketpair.c b/subsys/net/lib/sockets/socketpair.c index 417a3b34fb1f0..f02b91df45fba 100644 --- a/subsys/net/lib/sockets/socketpair.c +++ b/subsys/net/lib/sockets/socketpair.c @@ -357,7 +357,7 @@ int z_vrfy_zsock_socketpair(int family, int type, int proto, int *sv) return ret; } -#include +#include #endif /* CONFIG_USERSPACE */ /** diff --git a/subsys/net/lib/sockets/sockets.c b/subsys/net/lib/sockets/sockets.c index e75c0b0203fa7..454cd009fb5ff 100644 --- a/subsys/net/lib/sockets/sockets.c +++ b/subsys/net/lib/sockets/sockets.c @@ -110,7 +110,7 @@ void *z_vrfy_zsock_get_context_object(int sock) return z_impl_zsock_get_context_object(sock); } -#include +#include #endif static void zsock_received_cb(struct net_context *ctx, @@ -249,7 +249,7 @@ static inline int z_vrfy_zsock_socket(int family, int type, int proto) */ return z_impl_zsock_socket(family, type, proto); } -#include +#include #endif /* CONFIG_USERSPACE */ int zsock_close_ctx(struct net_context *ctx) @@ -308,7 +308,7 @@ static inline int z_vrfy_zsock_close(int sock) { return z_impl_zsock_close(sock); } -#include +#include #endif /* CONFIG_USERSPACE */ int z_impl_zsock_shutdown(int sock, int how) @@ -345,7 +345,7 @@ static inline int z_vrfy_zsock_shutdown(int sock, int how) { return z_impl_zsock_shutdown(sock, how); } -#include +#include #endif /* CONFIG_USERSPACE */ static void zsock_accepted_cb(struct net_context *new_ctx, @@ -487,7 +487,7 @@ static inline int z_vrfy_zsock_bind(int sock, const struct sockaddr *addr, return z_impl_zsock_bind(sock, (struct sockaddr *)&dest_addr_copy, addrlen); } -#include +#include #endif /* CONFIG_USERSPACE */ static void zsock_connected_cb(struct net_context *ctx, int status, void *user_data) @@ -566,7 +566,7 @@ int z_vrfy_zsock_connect(int sock, const struct sockaddr *addr, return z_impl_zsock_connect(sock, (struct sockaddr *)&dest_addr_copy, addrlen); } -#include +#include #endif /* CONFIG_USERSPACE */ int zsock_listen_ctx(struct net_context *ctx, int backlog) @@ -587,7 +587,7 @@ static inline int z_vrfy_zsock_listen(int sock, int backlog) { return z_impl_zsock_listen(sock, backlog); } -#include +#include #endif /* CONFIG_USERSPACE */ int zsock_accept_ctx(struct net_context *parent, struct sockaddr *addr, @@ -704,7 +704,7 @@ static inline int z_vrfy_zsock_accept(int sock, struct sockaddr *addr, return ret; } -#include +#include #endif /* CONFIG_USERSPACE */ #define WAIT_BUFS_INITIAL_MS 10 @@ -872,7 +872,7 @@ ssize_t z_vrfy_zsock_sendto(int sock, const void *buf, size_t len, int flags, dest_addr ? (struct sockaddr *)&dest_addr_copy : NULL, addrlen); } -#include +#include #endif /* CONFIG_USERSPACE */ size_t msghdr_non_empty_iov_count(const struct msghdr *msg) @@ -1024,7 +1024,7 @@ static inline ssize_t z_vrfy_zsock_sendmsg(int sock, return -1; } -#include +#include #endif /* CONFIG_USERSPACE */ static int sock_get_pkt_src_addr(struct net_pkt *pkt, @@ -1802,7 +1802,7 @@ ssize_t z_vrfy_zsock_recvfrom(int sock, void *buf, size_t max_len, int flags, return ret; } -#include +#include #endif /* CONFIG_USERSPACE */ ssize_t zsock_recvmsg_ctx(struct net_context *ctx, struct msghdr *msg, @@ -2017,7 +2017,7 @@ ssize_t z_vrfy_zsock_recvmsg(int sock, struct msghdr *msg, int flags) return -1; } -#include +#include #endif /* CONFIG_USERSPACE */ /* As this is limited function, we don't follow POSIX signature, with @@ -2051,7 +2051,7 @@ static inline int z_vrfy_zsock_fcntl_impl(int sock, int cmd, int flags) { return z_impl_zsock_fcntl_impl(sock, cmd, flags); } -#include +#include #endif int z_impl_zsock_ioctl_impl(int sock, unsigned long request, va_list args) @@ -2102,7 +2102,7 @@ static inline int z_vrfy_zsock_ioctl_impl(int sock, unsigned long request, va_li return z_impl_zsock_ioctl_impl(sock, request, args); } -#include +#include #endif static int zsock_poll_prepare_ctx(struct net_context *ctx, @@ -2402,7 +2402,7 @@ static inline int z_vrfy_zsock_poll(struct zsock_pollfd *fds, return ret; } -#include +#include #endif int z_impl_zsock_inet_pton(sa_family_t family, const char *src, void *dst) @@ -2441,7 +2441,7 @@ static inline int z_vrfy_zsock_inet_pton(sa_family_t family, return ret; } -#include +#include #endif static enum tcp_conn_option get_tcp_option(int optname) @@ -2788,7 +2788,7 @@ int z_vrfy_zsock_getsockopt(int sock, int level, int optname, return ret; } -#include +#include #endif /* CONFIG_USERSPACE */ static int ipv4_multicast_group(struct net_context *ctx, const void *optval, @@ -3393,7 +3393,7 @@ int z_vrfy_zsock_setsockopt(int sock, int level, int optname, return ret; } -#include +#include #endif /* CONFIG_USERSPACE */ int zsock_getpeername_ctx(struct net_context *ctx, struct sockaddr *addr, @@ -3477,7 +3477,7 @@ static inline int z_vrfy_zsock_getpeername(int sock, struct sockaddr *addr, return ret; } -#include +#include #endif /* CONFIG_USERSPACE */ int zsock_getsockname_ctx(struct net_context *ctx, struct sockaddr *addr, @@ -3563,7 +3563,7 @@ static inline int z_vrfy_zsock_getsockname(int sock, struct sockaddr *addr, return ret; } -#include +#include #endif /* CONFIG_USERSPACE */ static ssize_t sock_read_vmeth(void *obj, void *buffer, size_t count) diff --git a/subsys/net/lib/sockets/sockets_misc.c b/subsys/net/lib/sockets/sockets_misc.c index f16bfc8e96231..19e8155370f01 100644 --- a/subsys/net/lib/sockets/sockets_misc.c +++ b/subsys/net/lib/sockets/sockets_misc.c @@ -24,5 +24,5 @@ static inline int z_vrfy_zsock_gethostname(char *buf, size_t len) K_OOPS(K_SYSCALL_MEMORY_WRITE(buf, len)); return z_impl_zsock_gethostname(buf, len); } -#include +#include #endif diff --git a/subsys/net/lib/sockets/sockets_select.c b/subsys/net/lib/sockets/sockets_select.c index af88e51e7586c..49d61a2d28c65 100644 --- a/subsys/net/lib/sockets/sockets_select.c +++ b/subsys/net/lib/sockets/sockets_select.c @@ -284,5 +284,5 @@ static int z_vrfy_zsock_select(int nfds, zsock_fd_set *readfds, return ret; } -#include +#include #endif diff --git a/subsys/random/random_handlers.c b/subsys/random/random_handlers.c index 77bf068ed0d37..dc5fba5c47cb6 100644 --- a/subsys/random/random_handlers.c +++ b/subsys/random/random_handlers.c @@ -13,7 +13,7 @@ static inline void z_vrfy_sys_rand_get(void *dst, size_t len) z_impl_sys_rand_get(dst, len); } -#include +#include #ifdef CONFIG_CSPRNG_ENABLED static inline int z_vrfy_sys_csrand_get(void *dst, size_t len) @@ -22,5 +22,5 @@ static inline int z_vrfy_sys_csrand_get(void *dst, size_t len) return z_impl_sys_csrand_get(dst, len); } -#include +#include #endif diff --git a/subsys/rtio/rtio_handlers.c b/subsys/rtio/rtio_handlers.c index 3930d5bdee916..d3f3824614b57 100644 --- a/subsys/rtio/rtio_handlers.c +++ b/subsys/rtio/rtio_handlers.c @@ -57,7 +57,7 @@ static inline void z_vrfy_rtio_release_buffer(struct rtio *r, void *buff, uint32 K_OOPS(K_SYSCALL_OBJ(r, K_OBJ_RTIO)); z_impl_rtio_release_buffer(r, buff, buff_len); } -#include +#include static inline int z_vrfy_rtio_cqe_get_mempool_buffer(const struct rtio *r, struct rtio_cqe *cqe, uint8_t **buff, uint32_t *buff_len) @@ -68,13 +68,13 @@ static inline int z_vrfy_rtio_cqe_get_mempool_buffer(const struct rtio *r, struc K_OOPS(K_SYSCALL_MEMORY_READ(buff_len, sizeof(uint32_t))); return z_impl_rtio_cqe_get_mempool_buffer(r, cqe, buff, buff_len); } -#include +#include static inline int z_vrfy_rtio_sqe_cancel(struct rtio_sqe *sqe) { return z_impl_rtio_sqe_cancel(sqe); } -#include +#include static inline int z_vrfy_rtio_sqe_copy_in_get_handles(struct rtio *r, const struct rtio_sqe *sqes, struct rtio_sqe **handle, size_t sqe_count) @@ -107,7 +107,7 @@ static inline int z_vrfy_rtio_sqe_copy_in_get_handles(struct rtio *r, const stru /* Already copied *and* verified, no need to redo */ return z_impl_rtio_sqe_copy_in_get_handles(r, NULL, NULL, 0); } -#include +#include static inline int z_vrfy_rtio_cqe_copy_out(struct rtio *r, struct rtio_cqe *cqes, @@ -120,7 +120,7 @@ static inline int z_vrfy_rtio_cqe_copy_out(struct rtio *r, return z_impl_rtio_cqe_copy_out(r, cqes, cqe_count, timeout); } -#include +#include static inline int z_vrfy_rtio_submit(struct rtio *r, uint32_t wait_count) { @@ -132,4 +132,4 @@ static inline int z_vrfy_rtio_submit(struct rtio *r, uint32_t wait_count) return z_impl_rtio_submit(r, wait_count); } -#include +#include diff --git a/subsys/shell/modules/kernel_service.c b/subsys/shell/modules/kernel_service.c index 3d940ba5ee3d4..992a83f65b51c 100644 --- a/subsys/shell/modules/kernel_service.c +++ b/subsys/shell/modules/kernel_service.c @@ -5,7 +5,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include +#include #include #include diff --git a/subsys/testsuite/ztest/include/zephyr/ztest_error_hook.h b/subsys/testsuite/ztest/include/zephyr/ztest_error_hook.h index 6ebee086fc866..5d6ac64a9c1bd 100644 --- a/subsys/testsuite/ztest/include/zephyr/ztest_error_hook.h +++ b/subsys/testsuite/ztest/include/zephyr/ztest_error_hook.h @@ -76,7 +76,7 @@ void ztest_post_assert_fail_hook(void); #endif #if defined(CONFIG_ZTEST_FATAL_HOOK) || defined(CONFIG_ZTEST_ASSERT_HOOK) -#include +#include #endif #endif /* ZEPHYR_INCLUDE_ZTEST_FATAL_HOOK_H_ */ diff --git a/subsys/testsuite/ztest/include/zephyr/ztest_test.h b/subsys/testsuite/ztest/include/zephyr/ztest_test.h index b6bec89a0b810..2924de9c643a9 100644 --- a/subsys/testsuite/ztest/include/zephyr/ztest_test.h +++ b/subsys/testsuite/ztest/include/zephyr/ztest_test.h @@ -577,7 +577,7 @@ __syscall void sys_clock_tick_set(uint64_t tick); #endif #ifndef ZTEST_UNITTEST -#include +#include #endif #endif /* ZEPHYR_TESTSUITE_ZTEST_TEST_H_ */ diff --git a/subsys/testsuite/ztest/src/ztest.c b/subsys/testsuite/ztest/src/ztest.c index a3eba14e6162d..b9a6be291d0cc 100644 --- a/subsys/testsuite/ztest/src/ztest.c +++ b/subsys/testsuite/ztest/src/ztest.c @@ -289,10 +289,10 @@ void z_impl_z_test_1cpu_stop(void) #ifdef CONFIG_USERSPACE void z_vrfy_z_test_1cpu_start(void) { z_impl_z_test_1cpu_start(); } -#include +#include void z_vrfy_z_test_1cpu_stop(void) { z_impl_z_test_1cpu_stop(); } -#include +#include #endif /* CONFIG_USERSPACE */ #endif @@ -1135,13 +1135,13 @@ void z_vrfy___ztest_set_test_result(enum ztest_result new_result) { z_impl___ztest_set_test_result(new_result); } -#include +#include void z_vrfy___ztest_set_test_phase(enum ztest_phase new_phase) { z_impl___ztest_set_test_phase(new_phase); } -#include +#include #endif /* CONFIG_USERSPACE */ void ztest_verify_all_test_suites_ran(void) diff --git a/subsys/testsuite/ztest/src/ztest_error_hook.c b/subsys/testsuite/ztest/src/ztest_error_hook.c index 64dede71533ef..6982e96c7c552 100644 --- a/subsys/testsuite/ztest/src/ztest_error_hook.c +++ b/subsys/testsuite/ztest/src/ztest_error_hook.c @@ -38,7 +38,7 @@ static inline void z_vrfy_ztest_set_fault_valid(bool valid) { z_impl_ztest_set_fault_valid(valid); } -#include +#include #endif __weak void ztest_post_fatal_error_hook(unsigned int reason, @@ -100,7 +100,7 @@ static inline void z_vrfy_ztest_set_assert_valid(bool valid) { z_impl_ztest_set_assert_valid(valid); } -#include +#include #endif __weak void ztest_post_assert_fail_hook(void) diff --git a/tests/arch/arm/arm_interrupt/src/arm_interrupt.c b/tests/arch/arm/arm_interrupt/src/arm_interrupt.c index 1bbfe08bc0177..b569bbe1678a3 100644 --- a/tests/arch/arm/arm_interrupt/src/arm_interrupt.c +++ b/tests/arch/arm/arm_interrupt/src/arm_interrupt.c @@ -415,7 +415,7 @@ static inline void z_vrfy_test_arm_user_interrupt_syscall(void) { z_impl_test_arm_user_interrupt_syscall(); } -#include +#include ZTEST_USER(arm_interrupt, test_arm_user_interrupt) { diff --git a/tests/arch/arm/arm_interrupt/src/test_syscalls.h b/tests/arch/arm/arm_interrupt/src/test_syscalls.h index 5d85f7d4f87dd..1bef59e33aeaf 100644 --- a/tests/arch/arm/arm_interrupt/src/test_syscalls.h +++ b/tests/arch/arm/arm_interrupt/src/test_syscalls.h @@ -10,6 +10,6 @@ __syscall void test_arm_user_interrupt_syscall(void); -#include +#include #endif /* _TEST_SYSCALLS_H_ */ diff --git a/tests/arch/arm/arm_thread_swap/src/arm_syscalls.c b/tests/arch/arm/arm_thread_swap/src/arm_syscalls.c index e32de6ca72614..e1573bd1e39a6 100644 --- a/tests/arch/arm/arm_thread_swap/src/arm_syscalls.c +++ b/tests/arch/arm/arm_thread_swap/src/arm_syscalls.c @@ -66,7 +66,7 @@ static inline void z_vrfy_test_arm_user_syscall(void) { z_impl_test_arm_user_syscall(); } -#include +#include void arm_isr_handler(const void *args) @@ -271,7 +271,7 @@ static inline void z_vrfy_test_arm_cpu_write_reg(void) { z_impl_test_arm_cpu_write_reg(); } -#include +#include /** * @brief Test CPU scrubs registers after system call diff --git a/tests/arch/arm/arm_thread_swap/src/test_syscalls.h b/tests/arch/arm/arm_thread_swap/src/test_syscalls.h index 760ae3cbaa184..712db1670a4b4 100644 --- a/tests/arch/arm/arm_thread_swap/src/test_syscalls.h +++ b/tests/arch/arm/arm_thread_swap/src/test_syscalls.h @@ -11,6 +11,6 @@ __syscall void test_arm_user_syscall(void); __syscall void test_arm_cpu_write_reg(void); -#include +#include #endif /* _TEST_SYSCALLS_H_ */ diff --git a/tests/arch/x86/cpu_scrubs_regs/src/main.c b/tests/arch/x86/cpu_scrubs_regs/src/main.c index 6c27f73cd1b4e..3f4ea3fa078dc 100644 --- a/tests/arch/x86/cpu_scrubs_regs/src/main.c +++ b/tests/arch/x86/cpu_scrubs_regs/src/main.c @@ -54,7 +54,7 @@ static inline void z_vrfy_test_cpu_write_reg(void) { z_impl_test_cpu_write_reg(); } -#include +#include /** * @brief Test CPU scrubs registers after system call diff --git a/tests/arch/x86/cpu_scrubs_regs/src/test_syscalls.h b/tests/arch/x86/cpu_scrubs_regs/src/test_syscalls.h index 105ded868adae..5b6817de84616 100644 --- a/tests/arch/x86/cpu_scrubs_regs/src/test_syscalls.h +++ b/tests/arch/x86/cpu_scrubs_regs/src/test_syscalls.h @@ -10,6 +10,6 @@ __syscall void test_cpu_write_reg(void); -#include +#include #endif /* _TEST_SYSCALLS_H_ */ diff --git a/tests/arch/x86/pagetables/src/main.c b/tests/arch/x86/pagetables/src/main.c index aa3fde1fd9ffe..e42c4e3494ec8 100644 --- a/tests/arch/x86/pagetables/src/main.c +++ b/tests/arch/x86/pagetables/src/main.c @@ -238,7 +238,7 @@ void z_vrfy_dump_my_ptables(void) { z_impl_dump_my_ptables(); } -#include +#include #endif /* CONFIG_USERSPACE */ void dump_pagetables(void) diff --git a/tests/arch/x86/pagetables/src/main.h b/tests/arch/x86/pagetables/src/main.h index 2a7fa3f28b70c..7f7dd71f32242 100644 --- a/tests/arch/x86/pagetables/src/main.h +++ b/tests/arch/x86/pagetables/src/main.h @@ -8,6 +8,6 @@ __syscall void dump_my_ptables(void); -#include +#include #endif diff --git a/tests/benchmarks/app_kernel/src/master.c b/tests/benchmarks/app_kernel/src/master.c index ba0cf53a4f704..541be64040ccb 100644 --- a/tests/benchmarks/app_kernel/src/master.c +++ b/tests/benchmarks/app_kernel/src/master.c @@ -95,7 +95,7 @@ static timing_t z_vrfy_timing_timestamp_get(void) return z_impl_timing_timestamp_get(); } -#include +#include #endif /* diff --git a/tests/benchmarks/app_kernel/src/master.h b/tests/benchmarks/app_kernel/src/master.h index 9f9c902afa902..952961ff8afa0 100644 --- a/tests/benchmarks/app_kernel/src/master.h +++ b/tests/benchmarks/app_kernel/src/master.h @@ -126,6 +126,6 @@ extern struct k_mem_slab MAP1; __syscall void test_thread_priority_set(k_tid_t thread, int prio); __syscall timing_t timing_timestamp_get(void); -#include +#include #endif /* _MASTER_H */ diff --git a/tests/benchmarks/footprints/src/userspace.c b/tests/benchmarks/footprints/src/userspace.c index ef6a62cdeacdf..7e94a314fb890 100644 --- a/tests/benchmarks/footprints/src/userspace.c +++ b/tests/benchmarks/footprints/src/userspace.c @@ -32,7 +32,7 @@ static inline int z_vrfy_dummy_syscall(void) { return 0; } -#include +#include int z_impl_validation_overhead_syscall(void) { @@ -47,7 +47,7 @@ static inline int z_vrfy_validation_overhead_syscall(void) return status_0 || status_1; } -#include +#include void test_drop_to_user_mode_1(void *p1, void *p2, void *p3) diff --git a/tests/benchmarks/footprints/src/userspace.h b/tests/benchmarks/footprints/src/userspace.h index 5c682a3c57080..d85da725af588 100644 --- a/tests/benchmarks/footprints/src/userspace.h +++ b/tests/benchmarks/footprints/src/userspace.h @@ -10,6 +10,6 @@ __syscall int dummy_syscall(void); __syscall int validation_overhead_syscall(void); -#include +#include #endif /* _USERSPACE_H_ */ diff --git a/tests/benchmarks/latency_measure/src/timing_sc.c b/tests/benchmarks/latency_measure/src/timing_sc.c index 9397a258b5ab8..6b160e97bd31c 100644 --- a/tests/benchmarks/latency_measure/src/timing_sc.c +++ b/tests/benchmarks/latency_measure/src/timing_sc.c @@ -29,7 +29,7 @@ timing_t z_vrfy_timing_timestamp_get(void) { return z_impl_timing_timestamp_get(); } -#include +#include #endif static void start_thread_entry(void *p1, void *p2, void *p3) diff --git a/tests/benchmarks/latency_measure/src/timing_sc.h b/tests/benchmarks/latency_measure/src/timing_sc.h index 265d71f504809..5d08fac5a14d7 100644 --- a/tests/benchmarks/latency_measure/src/timing_sc.h +++ b/tests/benchmarks/latency_measure/src/timing_sc.h @@ -16,6 +16,6 @@ __syscall timing_t timing_timestamp_get(void); void timestamp_overhead_init(uint32_t num_iterations); uint64_t timestamp_overhead_adjustment(uint32_t options1, uint32_t options2); -#include +#include #endif diff --git a/tests/bluetooth/host/id/mocks/devicetree_generated.h b/tests/bluetooth/host/id/mocks/zephyr/devicetree_generated.h similarity index 100% rename from tests/bluetooth/host/id/mocks/devicetree_generated.h rename to tests/bluetooth/host/id/mocks/zephyr/devicetree_generated.h diff --git a/tests/bluetooth/host/id/mocks/syscalls/device.h b/tests/bluetooth/host/id/mocks/zephyr/syscalls/device.h similarity index 100% rename from tests/bluetooth/host/id/mocks/syscalls/device.h rename to tests/bluetooth/host/id/mocks/zephyr/syscalls/device.h diff --git a/tests/bluetooth/host/id/mocks/syscalls/mem_manage.h b/tests/bluetooth/host/id/mocks/zephyr/syscalls/mem_manage.h similarity index 100% rename from tests/bluetooth/host/id/mocks/syscalls/mem_manage.h rename to tests/bluetooth/host/id/mocks/zephyr/syscalls/mem_manage.h diff --git a/tests/boot/mcuboot_data_sharing/CMakeLists.txt b/tests/boot/mcuboot_data_sharing/CMakeLists.txt index 6bdbb43d36baf..ca9f150195099 100644 --- a/tests/boot/mcuboot_data_sharing/CMakeLists.txt +++ b/tests/boot/mcuboot_data_sharing/CMakeLists.txt @@ -27,4 +27,8 @@ include(${ZEPHYR_BASE}/cmake/modules/version.cmake) file(READ ${ZEPHYR_BASE}/version.h.in version_content) string(CONFIGURE "${version_content}" version_content) string(CONFIGURE "${version_content}" version_content) -file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/zephyr/include/generated/mcuboot_version.h "${version_content}") +file( + WRITE + ${CMAKE_CURRENT_BINARY_DIR}/zephyr/include/generated/zephyr/mcuboot_version.h + "${version_content}" +) diff --git a/tests/boot/mcuboot_data_sharing/src/main.c b/tests/boot/mcuboot_data_sharing/src/main.c index 1cf3954169b2e..f26da710fa16e 100644 --- a/tests/boot/mcuboot_data_sharing/src/main.c +++ b/tests/boot/mcuboot_data_sharing/src/main.c @@ -11,7 +11,7 @@ #include #include #include -#include +#include #define FLASH_SECTOR_SIZE 1024 #define FLASH_SECTOR_SIZE_KB 4 diff --git a/tests/kernel/common/src/main.c b/tests/kernel/common/src/main.c index e618d882094d4..352ae87ffeda9 100644 --- a/tests/kernel/common/src/main.c +++ b/tests/kernel/common/src/main.c @@ -8,7 +8,7 @@ #include #include #include -#include "version.h" +#include /** * @defgroup kernel_common_tests Common Tests diff --git a/tests/kernel/fatal/exception/src/main.c b/tests/kernel/fatal/exception/src/main.c index 30050d3ca3649..8d2cff2b1d9ef 100644 --- a/tests/kernel/fatal/exception/src/main.c +++ b/tests/kernel/fatal/exception/src/main.c @@ -225,7 +225,7 @@ static inline void z_vrfy_blow_up_priv_stack(void) { z_impl_blow_up_priv_stack(); } -#include +#include #endif /* CONFIG_USERSPACE */ #endif /* CONFIG_STACK_SENTINEL */ diff --git a/tests/kernel/fatal/exception/src/test_syscalls.h b/tests/kernel/fatal/exception/src/test_syscalls.h index 096547c35e835..a3bf55630906e 100644 --- a/tests/kernel/fatal/exception/src/test_syscalls.h +++ b/tests/kernel/fatal/exception/src/test_syscalls.h @@ -10,6 +10,6 @@ __syscall void blow_up_priv_stack(void); -#include +#include #endif /* _TEST_SYSCALLS_H_ */ diff --git a/tests/kernel/mem_protect/mem_protect/src/inherit.c b/tests/kernel/mem_protect/mem_protect/src/inherit.c index 8925535ef33cc..021fdf884fdd7 100644 --- a/tests/kernel/mem_protect/mem_protect/src/inherit.c +++ b/tests/kernel/mem_protect/mem_protect/src/inherit.c @@ -132,7 +132,7 @@ static inline struct k_heap *z_vrfy_ret_resource_pool_ptr(void) { return z_impl_ret_resource_pool_ptr(); } -#include +#include struct k_heap *child_heap_mem_ptr; struct k_heap *parent_heap_mem_ptr; diff --git a/tests/kernel/mem_protect/mem_protect/src/mem_protect.h b/tests/kernel/mem_protect/mem_protect/src/mem_protect.h index 4d5400bb1d6bb..db6d448219fe5 100644 --- a/tests/kernel/mem_protect/mem_protect/src/mem_protect.h +++ b/tests/kernel/mem_protect/mem_protect/src/mem_protect.h @@ -93,6 +93,6 @@ static inline void set_fault_valid(bool valid) __syscall struct k_heap *ret_resource_pool_ptr(void); -#include +#include #endif /* _TEST_SYSCALLS_H_ */ diff --git a/tests/kernel/mem_protect/syscalls/src/main.c b/tests/kernel/mem_protect/syscalls/src/main.c index 5ba99e2f72fb5..7d2b0568f96d0 100644 --- a/tests/kernel/mem_protect/syscalls/src/main.c +++ b/tests/kernel/mem_protect/syscalls/src/main.c @@ -63,7 +63,7 @@ static inline size_t z_vrfy_string_nlen(char *src, size_t maxlen, int *err) return ret; } -#include +#include int z_impl_string_alloc_copy(char *src) { @@ -89,7 +89,7 @@ static inline int z_vrfy_string_alloc_copy(char *src) return ret; } -#include +#include int z_impl_string_copy(char *src) { @@ -110,7 +110,7 @@ static inline int z_vrfy_string_copy(char *src) return z_impl_string_copy(kernel_buf); } -#include +#include /* Not actually used, but will copy wrong string if called by mistake instead * of the handler @@ -125,7 +125,7 @@ static inline int z_vrfy_to_copy(char *dest) { return k_usermode_to_copy((char *)dest, user_string, BUF_SIZE); } -#include +#include int z_impl_syscall_arg64(uint64_t arg) { @@ -139,7 +139,7 @@ static inline int z_vrfy_syscall_arg64(uint64_t arg) { return z_impl_syscall_arg64(arg); } -#include +#include /* Bigger 64 bit arg syscall to exercise marshalling 7+ words of * arguments (this one happens to need 9), and to test generation of @@ -166,7 +166,7 @@ static inline uint64_t z_vrfy_syscall_arg64_big(uint32_t arg1, uint32_t arg2, { return z_impl_syscall_arg64_big(arg1, arg2, arg3, arg4, arg5, arg6); } -#include +#include uint32_t z_impl_more_args(uint32_t arg1, uint32_t arg2, uint32_t arg3, uint32_t arg4, uint32_t arg5, uint32_t arg6, @@ -190,7 +190,7 @@ static inline uint32_t z_vrfy_more_args(uint32_t arg1, uint32_t arg2, { return z_impl_more_args(arg1, arg2, arg3, arg4, arg5, arg6, arg7); } -#include +#include /** * @brief Test to demonstrate usage of k_usermode_string_nlen() @@ -417,7 +417,7 @@ static inline bool z_vrfy_syscall_context(void) { return z_impl_syscall_context(); } -#include +#include void test_syscall_context_user(void *p1, void *p2, void *p3) { diff --git a/tests/kernel/mem_protect/syscalls/src/test_syscalls.h b/tests/kernel/mem_protect/syscalls/src/test_syscalls.h index 968928c54bf54..88f2c8e29f69d 100644 --- a/tests/kernel/mem_protect/syscalls/src/test_syscalls.h +++ b/tests/kernel/mem_protect/syscalls/src/test_syscalls.h @@ -27,6 +27,6 @@ __syscall uint32_t more_args(uint32_t arg1, uint32_t arg2, uint32_t arg3, uint32_t arg4, uint32_t arg5, uint32_t arg6, uint32_t arg7); -#include +#include #endif /* _TEST_SYSCALLS_H_ */ diff --git a/tests/kernel/mem_protect/userspace/src/main.c b/tests/kernel/mem_protect/userspace/src/main.c index d2b5842ee97ea..98510461e220c 100644 --- a/tests/kernel/mem_protect/userspace/src/main.c +++ b/tests/kernel/mem_protect/userspace/src/main.c @@ -1009,7 +1009,7 @@ static inline void z_vrfy_check_syscall_context(void) { return z_impl_check_syscall_context(); } -#include +#include ZTEST_USER(userspace, test_syscall_context) { diff --git a/tests/kernel/mem_protect/userspace/src/test_syscall.h b/tests/kernel/mem_protect/userspace/src/test_syscall.h index bc2a5d62b042e..f92b41a4e8f52 100644 --- a/tests/kernel/mem_protect/userspace/src/test_syscall.h +++ b/tests/kernel/mem_protect/userspace/src/test_syscall.h @@ -10,6 +10,6 @@ __syscall void missing_syscall(void); __syscall void check_syscall_context(void); -#include +#include #endif diff --git a/tests/kernel/threads/dynamic_thread/src/main.c b/tests/kernel/threads/dynamic_thread/src/main.c index f7e4a93d2db89..0fa88caee8cc0 100644 --- a/tests/kernel/threads/dynamic_thread/src/main.c +++ b/tests/kernel/threads/dynamic_thread/src/main.c @@ -156,7 +156,7 @@ ZTEST(thread_dynamic, test_thread_index_management) switch (K_OBJ_THREAD) { /** @cond keep_doxygen_away */ - #include + #include /** @endcond */ } blob = k_object_create_dynamic_aligned(16, ret); diff --git a/tests/kernel/threads/thread_stack/src/main.c b/tests/kernel/threads/thread_stack/src/main.c index ad14e92bdfb33..bc1684271cd20 100644 --- a/tests/kernel/threads/thread_stack/src/main.c +++ b/tests/kernel/threads/thread_stack/src/main.c @@ -46,7 +46,7 @@ static inline void z_vrfy_stack_info_get(char **start_addr, z_impl_stack_info_get(start_addr, size); } -#include +#include int z_impl_check_perms(void *addr, size_t size, int write) { @@ -57,7 +57,7 @@ static inline int z_vrfy_check_perms(void *addr, size_t size, int write) { return z_impl_check_perms((void *)addr, size, write); } -#include +#include #endif /* CONFIG_USERSPACE */ /* Global data structure with object information, used by diff --git a/tests/kernel/threads/thread_stack/src/test_syscall.h b/tests/kernel/threads/thread_stack/src/test_syscall.h index eb466dd79464f..a9bd7dbac1bc3 100644 --- a/tests/kernel/threads/thread_stack/src/test_syscall.h +++ b/tests/kernel/threads/thread_stack/src/test_syscall.h @@ -11,6 +11,6 @@ __syscall void stack_info_get(char **start_addr, size_t *size); #ifdef CONFIG_USERSPACE __syscall int check_perms(void *addr, size_t size, int write); #endif -#include +#include #endif diff --git a/tests/misc/llext-edk/include/app_api.h b/tests/misc/llext-edk/include/app_api.h index 5270bca687359..3bf1c112f3c49 100644 --- a/tests/misc/llext-edk/include/app_api.h +++ b/tests/misc/llext-edk/include/app_api.h @@ -18,5 +18,5 @@ __syscall int foo(int bar); } #endif -#include +#include #endif /* _TEST_EDK_H_ */ diff --git a/tests/misc/llext-edk/src/foo.c b/tests/misc/llext-edk/src/foo.c index 190dac2bea692..e7a3d221e0d0c 100644 --- a/tests/misc/llext-edk/src/foo.c +++ b/tests/misc/llext-edk/src/foo.c @@ -19,5 +19,5 @@ static inline int z_vrfy_foo(int bar) /* Nothing to verify */ return z_impl_foo(bar); } -#include +#include #endif diff --git a/tests/subsys/bindesc/definition/src/main.c b/tests/subsys/bindesc/definition/src/main.c index 487fa186790ba..a112cc377504c 100644 --- a/tests/subsys/bindesc/definition/src/main.c +++ b/tests/subsys/bindesc/definition/src/main.c @@ -6,7 +6,7 @@ #include #include -#include +#include #define STR_ID 1 #define UINT_ID 2 diff --git a/tests/subsys/llext/simple/src/syscalls_ext.h b/tests/subsys/llext/simple/src/syscalls_ext.h index 4d1b7fd43d9a7..85b7371b97f1f 100644 --- a/tests/subsys/llext/simple/src/syscalls_ext.h +++ b/tests/subsys/llext/simple/src/syscalls_ext.h @@ -16,4 +16,4 @@ __syscall int ext_syscall_ok(int a); */ __syscall void ext_syscall_fail(void); -#include +#include diff --git a/tests/subsys/llext/simple/src/test_llext_simple.c b/tests/subsys/llext/simple/src/test_llext_simple.c index f5e608d891285..2552844946e44 100644 --- a/tests/subsys/llext/simple/src/test_llext_simple.c +++ b/tests/subsys/llext/simple/src/test_llext_simple.c @@ -61,7 +61,7 @@ static inline int z_vrfy_ext_syscall_ok(int a) { return z_impl_ext_syscall_ok(a); } -#include +#include #endif /* CONFIG_USERSPACE */ diff --git a/tests/subsys/logging/log_benchmark/src/test_helpers.c b/tests/subsys/logging/log_benchmark/src/test_helpers.c index ad8b4f571bbfc..f4d5ca7e17208 100644 --- a/tests/subsys/logging/log_benchmark/src/test_helpers.c +++ b/tests/subsys/logging/log_benchmark/src/test_helpers.c @@ -31,7 +31,7 @@ static inline void z_vrfy_test_helpers_log_setup(void) { return z_impl_test_helpers_log_setup(); } -#include +#include #endif int z_impl_test_helpers_cycle_get(void) @@ -44,7 +44,7 @@ static inline int z_vrfy_test_helpers_cycle_get(void) { return z_impl_test_helpers_cycle_get(); } -#include +#include #endif bool z_impl_test_helpers_log_dropped_pending(void) @@ -57,5 +57,5 @@ static inline bool z_vrfy_test_helpers_log_dropped_pending(void) { return z_impl_test_helpers_log_dropped_pending(); } -#include +#include #endif diff --git a/tests/subsys/logging/log_benchmark/src/test_helpers.h b/tests/subsys/logging/log_benchmark/src/test_helpers.h index 0383d840c8b96..d2b0c2213d37b 100644 --- a/tests/subsys/logging/log_benchmark/src/test_helpers.h +++ b/tests/subsys/logging/log_benchmark/src/test_helpers.h @@ -12,6 +12,6 @@ __syscall void test_helpers_log_setup(void); __syscall int test_helpers_cycle_get(void); __syscall bool test_helpers_log_dropped_pending(void); -#include +#include #endif /* SRC_TEST_HELPERS_H__ */ diff --git a/tests/subsys/mgmt/mcumgr/cb_notifications/src/main.c b/tests/subsys/mgmt/mcumgr/cb_notifications/src/main.c index 99dee33e380e3..aa1bd143ed965 100644 --- a/tests/subsys/mgmt/mcumgr/cb_notifications/src/main.c +++ b/tests/subsys/mgmt/mcumgr/cb_notifications/src/main.c @@ -14,7 +14,7 @@ #include #include #include -#include +#include #include #include #include "smp_test_util.h" diff --git a/tests/subsys/mgmt/mcumgr/os_mgmt_info/src/build_date.c b/tests/subsys/mgmt/mcumgr/os_mgmt_info/src/build_date.c index 5674e338dfa28..a1503e0f9cf3f 100644 --- a/tests/subsys/mgmt/mcumgr/os_mgmt_info/src/build_date.c +++ b/tests/subsys/mgmt/mcumgr/os_mgmt_info/src/build_date.c @@ -18,7 +18,7 @@ #include #include #include -#include +#include #include #include "smp_test_util.h" diff --git a/tests/subsys/mgmt/mcumgr/os_mgmt_info/src/limited.c b/tests/subsys/mgmt/mcumgr/os_mgmt_info/src/limited.c index 613402e162427..9932d11b7a0a8 100644 --- a/tests/subsys/mgmt/mcumgr/os_mgmt_info/src/limited.c +++ b/tests/subsys/mgmt/mcumgr/os_mgmt_info/src/limited.c @@ -17,7 +17,7 @@ #include #include #include -#include +#include #include #include #include "smp_test_util.h" diff --git a/tests/subsys/mgmt/mcumgr/os_mgmt_info/src/main.c b/tests/subsys/mgmt/mcumgr/os_mgmt_info/src/main.c index bc86791b350aa..f1828856ebb80 100644 --- a/tests/subsys/mgmt/mcumgr/os_mgmt_info/src/main.c +++ b/tests/subsys/mgmt/mcumgr/os_mgmt_info/src/main.c @@ -17,7 +17,7 @@ #include #include #include -#include +#include #include #include #include "smp_test_util.h" diff --git a/tests/subsys/shell/shell_backend_uart/src/main.c b/tests/subsys/shell/shell_backend_uart/src/main.c index 0e5d2704eb405..2aa6d79460858 100644 --- a/tests/subsys/shell/shell_backend_uart/src/main.c +++ b/tests/subsys/shell/shell_backend_uart/src/main.c @@ -4,7 +4,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include +#include #include #include From 2d912d52a0423b0f913d7b23220d33b8f89c87ae Mon Sep 17 00:00:00 2001 From: Yong Cong Sin Date: Thu, 7 Dec 2023 16:28:43 +0800 Subject: [PATCH 1287/2849] doc: releases: add notes for namespaced generated headers Add migration notes for generated headers being namespaced to the `zephyr/` folder. Signed-off-by: Yong Cong Sin --- doc/releases/migration-guide-3.7.rst | 33 ++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/doc/releases/migration-guide-3.7.rst b/doc/releases/migration-guide-3.7.rst index fb7587ad1c587..4d3dd78a6df73 100644 --- a/doc/releases/migration-guide-3.7.rst +++ b/doc/releases/migration-guide-3.7.rst @@ -22,6 +22,39 @@ Build System out-of-tree SoCs and boards to be ported to the new model. See the :ref:`hw_model_v2` for more detailed information. (:github:`69607`) +* The following build-time generated headers: + + .. list-table:: + :header-rows: 1 + + * - Affected header files + * - ``app_version.h`` + * - ``cmake_intdef.h`` + * - ``core-isa-dM.h`` + * - ``devicetree_generated.h`` + * - ``driver-validation.h`` + * - ``kobj-types-enum.h`` + * - ``linker-kobject-prebuilt-data.h`` + * - ``linker-kobject-prebuilt-priv-stacks.h`` + * - ``linker-kobject-prebuilt-rodata.h`` + * - ``mcuboot_version.h`` + * - ``offsets.h`` + * - ``otype-to-size.h`` + * - ``otype-to-str.h`` + * - ``strerror_table.h`` + * - ``strsignal_table.h`` + * - ``syscall_list.h`` + * - ``version.h`` + * - ``zsr.h`` + + and syscall headers are now namespaced into the ``zephyr/`` folder. The change is largely + automated, and the script can be found in :github:`63973`. + For the time being, the compatibility Kconfig (:kconfig:option:`CONFIG_LEGACY_GENERATED_INCLUDE_PATH`) + is enabled by default so that downstream applications will continue to compile, a warning message + will be generated during CMake configuration time. + This Kconfig will be deprecated and eventually removed in the future, developers are advised to + update the include paths of these affected headers as soon as possible. + Kernel ****** From 0dac6c132bebc6a3a7ec194572efb3cde39e1377 Mon Sep 17 00:00:00 2001 From: Yong Cong Sin Date: Wed, 31 Jan 2024 11:12:46 +0800 Subject: [PATCH 1288/2849] build: namespace `autoconf.h` with `zephyr/` Namespace the generated `autoconf.h` file with `zephyr/`. Signed-off-by: Yong Cong Sin --- cmake/ide/eclipse_cdt4_generator_amendment.cmake | 2 +- cmake/modules/kconfig.cmake | 2 +- doc/releases/migration-guide-3.7.rst | 1 + modules/lvgl/lvgl_shell.c | 2 +- modules/trusted-firmware-m/nordic/include/RTE_Device.h | 2 +- modules/trusted-firmware-m/nordic/include/device_cfg.h | 2 +- scripts/kconfig/kconfiglib.py | 6 +++--- scripts/west_commands/sign.py | 2 +- soc/nxp/imxrt/imxrt5xx/f1/include/soc/memory.h | 2 +- 9 files changed, 11 insertions(+), 10 deletions(-) diff --git a/cmake/ide/eclipse_cdt4_generator_amendment.cmake b/cmake/ide/eclipse_cdt4_generator_amendment.cmake index 5fd32a2ddd3d9..36eca028335d5 100644 --- a/cmake/ide/eclipse_cdt4_generator_amendment.cmake +++ b/cmake/ide/eclipse_cdt4_generator_amendment.cmake @@ -46,7 +46,7 @@ # CMAKE_EXTRA_GENERATOR_CXX_SYSTEM_DEFINED_MACROS. # #3. The amendment function appends the defines from -# ${CMAKE_BINARY_DIR}/zephyr/include/generated/autoconf.h to +# ${CMAKE_BINARY_DIR}/zephyr/include/generated/zephyr/autoconf.h to # CMAKE_EXTRA_GENERATOR_C_SYSTEM_DEFINED_MACROS. # function(eclipse_cdt4_generator_amendment _param_defs) diff --git a/cmake/modules/kconfig.cmake b/cmake/modules/kconfig.cmake index 4606f71cc767c..56b73c716a280 100644 --- a/cmake/modules/kconfig.cmake +++ b/cmake/modules/kconfig.cmake @@ -9,7 +9,7 @@ include(python) # /zephyr/include/generated/autoconf.h. # A project may request a custom location by setting AUTOCONF_H explicitly before # calling 'find_package(Zephyr)' or loading this module. -set_ifndef(AUTOCONF_H ${PROJECT_BINARY_DIR}/include/generated/autoconf.h) +set_ifndef(AUTOCONF_H ${PROJECT_BINARY_DIR}/include/generated/zephyr/autoconf.h) # Re-configure (Re-execute all CMakeLists.txt code) when autoconf.h changes set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS ${AUTOCONF_H}) diff --git a/doc/releases/migration-guide-3.7.rst b/doc/releases/migration-guide-3.7.rst index 4d3dd78a6df73..47e996f529f53 100644 --- a/doc/releases/migration-guide-3.7.rst +++ b/doc/releases/migration-guide-3.7.rst @@ -29,6 +29,7 @@ Build System * - Affected header files * - ``app_version.h`` + * - ``autoconf.h`` * - ``cmake_intdef.h`` * - ``core-isa-dM.h`` * - ``devicetree_generated.h`` diff --git a/modules/lvgl/lvgl_shell.c b/modules/lvgl/lvgl_shell.c index e8ac27e22f906..42d5a5e7a2ac3 100644 --- a/modules/lvgl/lvgl_shell.c +++ b/modules/lvgl/lvgl_shell.c @@ -6,7 +6,7 @@ #include #include -#include +#include #ifdef CONFIG_LV_Z_MEM_POOL_SYS_HEAP #include "lvgl_mem.h" diff --git a/modules/trusted-firmware-m/nordic/include/RTE_Device.h b/modules/trusted-firmware-m/nordic/include/RTE_Device.h index ca886583fa925..0c5c498e43a27 100644 --- a/modules/trusted-firmware-m/nordic/include/RTE_Device.h +++ b/modules/trusted-firmware-m/nordic/include/RTE_Device.h @@ -7,7 +7,7 @@ #ifndef __RTE_DEVICE_H #define __RTE_DEVICE_H -#include +#include /* ARRAY_SIZE causes a conflict as it is defined both by TF-M and indirectly by devicetree.h */ #undef ARRAY_SIZE diff --git a/modules/trusted-firmware-m/nordic/include/device_cfg.h b/modules/trusted-firmware-m/nordic/include/device_cfg.h index 9b766a35eb956..84fdea0e1a9bf 100644 --- a/modules/trusted-firmware-m/nordic/include/device_cfg.h +++ b/modules/trusted-firmware-m/nordic/include/device_cfg.h @@ -7,7 +7,7 @@ #ifndef DEVICE_CFG_H__ #define DEVICE_CFG_H__ -#include +#include /* ARRAY_SIZE causes a conflict as it is defined both by TF-M and indirectly by devicetree.h */ #undef ARRAY_SIZE diff --git a/scripts/kconfig/kconfiglib.py b/scripts/kconfig/kconfiglib.py index bd541d07b42ae..f81979ec2c259 100644 --- a/scripts/kconfig/kconfiglib.py +++ b/scripts/kconfig/kconfiglib.py @@ -1419,7 +1419,7 @@ def load_allconfig(self, filename): def write_autoconf(self, filename=None, header=None): r""" Writes out symbol values as a C header file, matching the format used - by include/generated/autoconf.h in the kernel. + by include/generated/zephyr/autoconf.h in the kernel. The ordering of the #defines matches the one generated by write_config(). The order in the C implementation depends on the hash @@ -1434,7 +1434,7 @@ def write_autoconf(self, filename=None, header=None): Path to write header to. If None (the default), the path in the environment variable - KCONFIG_AUTOHEADER is used if set, and "include/generated/autoconf.h" + KCONFIG_AUTOHEADER is used if set, and "include/generated/zephyr/autoconf.h" otherwise. This is compatible with the C tools. header (default: None): @@ -1453,7 +1453,7 @@ def write_autoconf(self, filename=None, header=None): """ if filename is None: filename = os.getenv("KCONFIG_AUTOHEADER", - "include/generated/autoconf.h") + "include/generated/zephyr/autoconf.h") if self._write_if_changed(filename, self._autoconf_contents(header)): return "Kconfig header saved to '{}'".format(filename) diff --git a/scripts/west_commands/sign.py b/scripts/west_commands/sign.py index 71ad5c815bbfa..5f59facffbf7e 100644 --- a/scripts/west_commands/sign.py +++ b/scripts/west_commands/sign.py @@ -456,7 +456,7 @@ def preprocess_toml(self, config_dir, toml_basename, subdir): preproc_cmd += ['-I', str(self.sof_src_dir / 'src')] preproc_cmd += ['-imacros', - str(pathlib.Path('zephyr') / 'include' / 'generated' / 'autoconf.h')] + str(pathlib.Path('zephyr') / 'include' / 'generated' / 'zephyr' / 'autoconf.h')] preproc_cmd += ['-o', str(subdir / 'rimage_config.toml')] self.command.inf(quote_sh_list(preproc_cmd)) subprocess.run(preproc_cmd, check=True, cwd=self.build_dir) diff --git a/soc/nxp/imxrt/imxrt5xx/f1/include/soc/memory.h b/soc/nxp/imxrt/imxrt5xx/f1/include/soc/memory.h index af9e1888e1ca5..3eb14816bcc9c 100644 --- a/soc/nxp/imxrt/imxrt5xx/f1/include/soc/memory.h +++ b/soc/nxp/imxrt/imxrt5xx/f1/include/soc/memory.h @@ -5,7 +5,7 @@ #pragma once -#include +#include #define IRAM_BASE (CONFIG_RT595_ADSP_TEXT_MEM_ADDR) #define IRAM_SIZE (CONFIG_RT595_ADSP_TEXT_MEM_SIZE) From 3570408db556fbb53cd775ae3d2e44553e28cb31 Mon Sep 17 00:00:00 2001 From: Yong Cong Sin Date: Fri, 24 May 2024 22:09:31 +0800 Subject: [PATCH 1289/2849] build: namespace syscall sources to `zephyr/` Namespace the `syscall_dispatch.c` & `syscall_export_llext.c` to `zephyr/` as well Signed-off-by: Yong Cong Sin --- CMakeLists.txt | 8 ++++---- doc/kernel/usermode/syscalls.rst | 2 +- doc/releases/migration-guide-3.7.rst | 2 +- kernel/userspace.c | 2 +- subsys/llext/llext_export.c | 2 +- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7cb3ed7c7fb9e..c6b173501495f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -801,15 +801,15 @@ if(CONFIG_LEGACY_GENERATED_INCLUDE_PATH) ${CMAKE_CURRENT_BINARY_DIR}/include/generated/syscall_list.h) endif() -add_custom_command(OUTPUT include/generated/syscall_dispatch.c ${syscall_list_h} +add_custom_command(OUTPUT include/generated/zephyr/syscall_dispatch.c ${syscall_list_h} # Also, some files are written to include/generated/zephyr/syscalls/ COMMAND ${PYTHON_EXECUTABLE} ${ZEPHYR_BASE}/scripts/build/gen_syscalls.py --json-file ${syscalls_json} # Read this file --base-output include/generated/zephyr/syscalls # Write to this dir - --syscall-dispatch include/generated/syscall_dispatch.c # Write this file - --syscall-export-llext include/generated/syscall_export_llext.c + --syscall-dispatch include/generated/zephyr/syscall_dispatch.c # Write this file + --syscall-export-llext include/generated/zephyr/syscall_export_llext.c --syscall-list ${syscall_list_h} $<$:--gen-mrsh-files> ${SYSCALL_LONG_REGISTERS_ARG} @@ -2121,7 +2121,7 @@ add_custom_command( ${ZEPHYR_BASE}/scripts/build/gen_syscalls.py --json-file ${syscalls_json} # Read this file --base-output edk/include/generated/zephyr/syscalls # Write to this dir - --syscall-dispatch edk/include/generated/syscall_dispatch.c # Write this file + --syscall-dispatch edk/include/generated/zephyr/syscall_dispatch.c # Write this file --syscall-list ${edk_syscall_list_h} $<$:--userspace-only> ${SYSCALL_LONG_REGISTERS_ARG} diff --git a/doc/kernel/usermode/syscalls.rst b/doc/kernel/usermode/syscalls.rst index 1490a758db5e9..dd9838629d9b9 100644 --- a/doc/kernel/usermode/syscalls.rst +++ b/doc/kernel/usermode/syscalls.rst @@ -147,7 +147,7 @@ the project out directory under ``include/generated/``: of the API in uppercase, prefixed with ``K_SYSCALL_``. * An entry for the system call is created in the dispatch table - ``_k_syscall_table``, expressed in ``include/generated/syscall_dispatch.c`` + ``_k_syscall_table``, expressed in ``include/generated/zephyr/syscall_dispatch.c`` * This table only contains syscalls where their corresponding prototypes are declared in header files when diff --git a/doc/releases/migration-guide-3.7.rst b/doc/releases/migration-guide-3.7.rst index 47e996f529f53..8b9c876258e18 100644 --- a/doc/releases/migration-guide-3.7.rst +++ b/doc/releases/migration-guide-3.7.rst @@ -48,7 +48,7 @@ Build System * - ``version.h`` * - ``zsr.h`` - and syscall headers are now namespaced into the ``zephyr/`` folder. The change is largely + as well as syscall headers & sources are now namespaced into the ``zephyr/`` folder. The change is largely automated, and the script can be found in :github:`63973`. For the time being, the compatibility Kconfig (:kconfig:option:`CONFIG_LEGACY_GENERATED_INCLUDE_PATH`) is enabled by default so that downstream applications will continue to compile, a warning message diff --git a/kernel/userspace.c b/kernel/userspace.c index 55432586fed09..6fcfacee8b0ca 100644 --- a/kernel/userspace.c +++ b/kernel/userspace.c @@ -1014,4 +1014,4 @@ static uintptr_t handler_no_syscall(uintptr_t arg1, uintptr_t arg2, CODE_UNREACHABLE; /* LCOV_EXCL_LINE */ } -#include +#include diff --git a/subsys/llext/llext_export.c b/subsys/llext/llext_export.c index e5b5aa441ab00..d2d117ec6ffc5 100644 --- a/subsys/llext/llext_export.c +++ b/subsys/llext/llext_export.c @@ -16,4 +16,4 @@ EXPORT_SYMBOL(memcmp); EXPORT_SYMBOL(memcpy); EXPORT_SYMBOL(memset); -#include +#include From d7fe6e41d403d96c5b20dfb0a4c3beca4750e7aa Mon Sep 17 00:00:00 2001 From: Sadik Ozer Date: Fri, 19 Apr 2024 09:45:58 +0300 Subject: [PATCH 1290/2849] manifest: west.yml: Add ADI HAL as a new HAL module ADI HAL (Hardware Abstraction Layer) provides a low level peripheral configuration function. Signed-off-by: Sadik Ozer --- west.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/west.yml b/west.yml index 0fac1c4109fd6..215af86acd9de 100644 --- a/west.yml +++ b/west.yml @@ -136,6 +136,11 @@ manifest: path: modules/fs/fatfs groups: - fs + - name: hal_adi + revision: 674d10b0a1aad4cf4b7b90ca52dfd4a494ab9e52 + path: modules/hal/adi + groups: + - hal - name: hal_altera revision: 0d225ddd314379b32355a00fb669eacf911e750d path: modules/hal/altera From e0528e3852a20475bbc6301f321f818490aba739 Mon Sep 17 00:00:00 2001 From: Sadik Ozer Date: Thu, 2 May 2024 14:31:12 +0300 Subject: [PATCH 1291/2849] MAINTAINERS: Add hal_adi as a new HAL module This commit adds maintainers for hal_adi repository Signed-off-by: Sadik Ozer --- MAINTAINERS.yml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/MAINTAINERS.yml b/MAINTAINERS.yml index 88a9729467383..72a3da74d0293 100644 --- a/MAINTAINERS.yml +++ b/MAINTAINERS.yml @@ -4207,6 +4207,16 @@ West: labels: - "area: Storage" +"West project: hal_adi": + status: maintained + maintainers: + - MaureenHelm + collaborators: + - ozersa + files: [] + labels: + - "platform: ADI" + "West project: hal_altera": status: odd fixes collaborators: From 45df8963f145127acc1f54dfb84eee6b8fa2ce91 Mon Sep 17 00:00:00 2001 From: Sadik Ozer Date: Fri, 13 Oct 2023 16:04:13 +0300 Subject: [PATCH 1292/2849] drivers: Add MAX32690 clock control driver Clock control for MAX32690 Co-authored-by: Okan Sahin Signed-off-by: Sadik Ozer --- drivers/clock_control/CMakeLists.txt | 1 + drivers/clock_control/Kconfig | 2 + drivers/clock_control/Kconfig.max32 | 9 + drivers/clock_control/clock_control_max32.c | 158 ++++++++++++++++++ dts/bindings/clock/adi,max32-gcr.yaml | 36 ++++ .../clock_control/adi_max32_clock_control.h | 98 +++++++++++ .../dt-bindings/clock/adi_max32_clock.h | 25 +++ 7 files changed, 329 insertions(+) create mode 100644 drivers/clock_control/Kconfig.max32 create mode 100644 drivers/clock_control/clock_control_max32.c create mode 100644 dts/bindings/clock/adi,max32-gcr.yaml create mode 100644 include/zephyr/drivers/clock_control/adi_max32_clock_control.h create mode 100644 include/zephyr/dt-bindings/clock/adi_max32_clock.h diff --git a/drivers/clock_control/CMakeLists.txt b/drivers/clock_control/CMakeLists.txt index 596b07676e035..4cbd3ac47d6f0 100644 --- a/drivers/clock_control/CMakeLists.txt +++ b/drivers/clock_control/CMakeLists.txt @@ -76,3 +76,4 @@ if(CONFIG_CLOCK_CONTROL_RCAR_CPG_MSSR) endif() zephyr_library_sources_ifdef(CONFIG_CLOCK_CONTROL_AST10X0 clock_control_ast10x0.c) +zephyr_library_sources_ifdef(CONFIG_CLOCK_CONTROL_MAX32 clock_control_max32.c) diff --git a/drivers/clock_control/Kconfig b/drivers/clock_control/Kconfig index b0c6cf8de48c7..b1b64f4a3ca35 100644 --- a/drivers/clock_control/Kconfig +++ b/drivers/clock_control/Kconfig @@ -82,6 +82,8 @@ source "drivers/clock_control/Kconfig.agilex5" source "drivers/clock_control/Kconfig.renesas_ra" +source "drivers/clock_control/Kconfig.max32" + source "drivers/clock_control/Kconfig.ambiq" source "drivers/clock_control/Kconfig.pwm" diff --git a/drivers/clock_control/Kconfig.max32 b/drivers/clock_control/Kconfig.max32 new file mode 100644 index 0000000000000..30f8d9fda7a34 --- /dev/null +++ b/drivers/clock_control/Kconfig.max32 @@ -0,0 +1,9 @@ +# Copyright (c) 2023-2024 Analog Devices, Inc. +# SPDX-License-Identifier: Apache-2.0 + +config CLOCK_CONTROL_MAX32 + bool "MAX32 Clock Control Driver" + default y + depends on DT_HAS_ADI_MAX32_GCR_ENABLED + help + Enable clock control support for Analog Devices MAX32xxx/MAX78xxx SoC series. diff --git a/drivers/clock_control/clock_control_max32.c b/drivers/clock_control/clock_control_max32.c new file mode 100644 index 0000000000000..2cbed41bd23a8 --- /dev/null +++ b/drivers/clock_control/clock_control_max32.c @@ -0,0 +1,158 @@ +/* + * Copyright (c) 2023-2024 Analog Devices, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +#include + +#define DT_DRV_COMPAT adi_max32_gcr + +static inline int api_on(const struct device *dev, clock_control_subsys_t clkcfg) +{ + ARG_UNUSED(dev); + struct max32_perclk *perclk = (struct max32_perclk *)(clkcfg); + + switch (perclk->bus) { + case ADI_MAX32_CLOCK_BUS0: + MXC_SYS_ClockEnable((mxc_sys_periph_clock_t)perclk->bit); + break; + case ADI_MAX32_CLOCK_BUS1: + MXC_SYS_ClockEnable((mxc_sys_periph_clock_t)(perclk->bit + 32)); + break; + case ADI_MAX32_CLOCK_BUS2: + MXC_SYS_ClockEnable((mxc_sys_periph_clock_t)(perclk->bit + 64)); + break; + default: + return -EINVAL; + } + + return 0; +} + +static inline int api_off(const struct device *dev, clock_control_subsys_t clkcfg) +{ + ARG_UNUSED(dev); + struct max32_perclk *perclk = (struct max32_perclk *)(clkcfg); + + switch (perclk->bus) { + case ADI_MAX32_CLOCK_BUS0: + MXC_SYS_ClockDisable((mxc_sys_periph_clock_t)perclk->bit); + break; + case ADI_MAX32_CLOCK_BUS1: + MXC_SYS_ClockDisable((mxc_sys_periph_clock_t)(perclk->bit + 32)); + break; + case ADI_MAX32_CLOCK_BUS2: + MXC_SYS_ClockDisable((mxc_sys_periph_clock_t)(perclk->bit + 64)); + break; + default: + return -EINVAL; + } + + return 0; +} + +static int api_get_rate(const struct device *dev, clock_control_subsys_t clkcfg, uint32_t *rate) +{ + ARG_UNUSED(dev); + struct max32_perclk *perclk = (struct max32_perclk *)(clkcfg); + + switch (perclk->clk_src) { + case ADI_MAX32_PRPH_CLK_SRC_PCLK: + *rate = ADI_MAX32_PCLK_FREQ; + break; + case ADI_MAX32_PRPH_CLK_SRC_EXTCLK: + *rate = ADI_MAX32_CLK_EXTCLK_FREQ; + break; + case ADI_MAX32_PRPH_CLK_SRC_IBRO: + *rate = ADI_MAX32_CLK_IBRO_FREQ; + break; + case ADI_MAX32_PRPH_CLK_SRC_ERFO: + *rate = ADI_MAX32_CLK_ERFO_FREQ; + break; + case ADI_MAX32_PRPH_CLK_SRC_ERTCO: + *rate = ADI_MAX32_CLK_ERTCO_FREQ; + break; + case ADI_MAX32_PRPH_CLK_SRC_INRO: + *rate = ADI_MAX32_CLK_INRO_FREQ; + break; + case ADI_MAX32_PRPH_CLK_SRC_ISO: + *rate = ADI_MAX32_CLK_ISO_FREQ; + break; + case ADI_MAX32_PRPH_CLK_SRC_IBRO_DIV8: + *rate = ADI_MAX32_CLK_IBRO_FREQ / 8; + break; + default: + *rate = 0U; + /* Invalid parameters */ + return -EINVAL; + } + + return 0; +} + +static const struct clock_control_driver_api max32_clkctrl_api = { + .on = api_on, + .off = api_off, + .get_rate = api_get_rate, +}; + +static void setup_fixed_clocks(void) +{ +#if DT_NODE_HAS_COMPAT(DT_NODELABEL(clk_extclk), fixed_clock) + MXC_SYS_ClockSourceDisable(ADI_MAX32_CLK_EXTCLK); +#endif + +#if DT_NODE_HAS_STATUS(DT_NODELABEL(clk_ipo), okay) + MXC_SYS_ClockSourceEnable(ADI_MAX32_CLK_IPO); +#endif + +#if DT_NODE_HAS_STATUS(DT_NODELABEL(clk_erfo), okay) + MXC_SYS_ClockSourceEnable(ADI_MAX32_CLK_ERFO); +#endif + +#if DT_NODE_HAS_STATUS(DT_NODELABEL(clk_ibro), okay) + MXC_SYS_ClockSourceEnable(ADI_MAX32_CLK_IBRO); +#endif + +#if DT_NODE_HAS_STATUS(DT_NODELABEL(clk_iso), okay) + MXC_SYS_ClockSourceEnable(ADI_MAX32_CLK_ISO); +#endif + +#if DT_NODE_HAS_STATUS(DT_NODELABEL(clk_inro), okay) + MXC_SYS_ClockSourceEnable(ADI_MAX32_CLK_INRO); +#endif + +#if DT_NODE_HAS_STATUS(DT_NODELABEL(clk_ertco), okay) + MXC_SYS_ClockSourceEnable(ADI_MAX32_CLK_ERTCO); +#endif + +/* Some device does not support external clock */ +#if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(clk_extclk), fixed_clock, okay) + MXC_SYS_ClockSourceEnable(ADI_MAX32_CLK_EXTCLK); +#endif +} + +static int max32_clkctrl_init(const struct device *dev) +{ + ARG_UNUSED(dev); + + /* Setup fixed clocks if enabled */ + setup_fixed_clocks(); + + /* Setup device clock source */ + MXC_SYS_Clock_Select(ADI_MAX32_SYSCLK_SRC); + +#if DT_NODE_HAS_PROP(DT_NODELABEL(gcr), sysclk_prescaler) + /* Setup divider */ + Wrap_MXC_SYS_SetClockDiv(sysclk_prescaler(ADI_MAX32_SYSCLK_PRESCALER)); +#endif + + return 0; +} + +DEVICE_DT_INST_DEFINE(0, max32_clkctrl_init, NULL, NULL, NULL, PRE_KERNEL_1, + CONFIG_CLOCK_CONTROL_INIT_PRIORITY, &max32_clkctrl_api); diff --git a/dts/bindings/clock/adi,max32-gcr.yaml b/dts/bindings/clock/adi,max32-gcr.yaml new file mode 100644 index 0000000000000..be8049542293b --- /dev/null +++ b/dts/bindings/clock/adi,max32-gcr.yaml @@ -0,0 +1,36 @@ +# Copyright (c) 2023-2024 Analog Devices, Inc. +# SPDX-License-Identifier: Apache-2.0 + +description: MAX32 Global Control + +compatible: "adi,max32-gcr" + +include: [clock-controller.yaml, base.yaml] + +properties: + reg: + required: true + + "#clock-cells": + const: 2 + + sysclk-prescaler: + type: int + enum: + - 1 + - 2 + - 4 + - 8 + - 16 + - 32 + - 64 + - 128 + + description: | + SYSCLK prescaler. Defines actual core clock frequency SYSCLK + based on system frequency input. Some MAX32xxx devices does not + support this feature, check your device user guide before using it. + +clock-cells: + - offset + - bit diff --git a/include/zephyr/drivers/clock_control/adi_max32_clock_control.h b/include/zephyr/drivers/clock_control/adi_max32_clock_control.h new file mode 100644 index 0000000000000..2922b5e2c8861 --- /dev/null +++ b/include/zephyr/drivers/clock_control/adi_max32_clock_control.h @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2023-2024 Analog Devices, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_DRIVERS_CLOCK_CONTROL_ADI_MAX32_CLOCK_CONTROL_H_ +#define ZEPHYR_INCLUDE_DRIVERS_CLOCK_CONTROL_ADI_MAX32_CLOCK_CONTROL_H_ + +#include + +#include + +#include + +/** Driver structure definition */ + +struct max32_perclk { + uint32_t bus; + uint32_t bit; + + /* Peripheral clock source: + * Can be (see: adi_max32_clock.h file): + * + * ADI_MAX32_PRPH_CLK_SRC_PCLK + * ADI_MAX32_PRPH_CLK_SRC_EXTCLK + * ADI_MAX32_PRPH_CLK_SRC_IBRO + * ADI_MAX32_PRPH_CLK_SRC_ERFO + * ADI_MAX32_PRPH_CLK_SRC_ERTCO + * ADI_MAX32_PRPH_CLK_SRC_INRO + * ADI_MAX32_PRPH_CLK_SRC_ISO + * ADI_MAX32_PRPH_CLK_SRC_IBRO_DIV8 + */ + uint32_t clk_src; +}; + +/** Get prescaler value if it defined */ +#define ADI_MAX32_SYSCLK_PRESCALER DT_PROP_OR(DT_NODELABEL(gcr), sysclk_prescaler, 1) + +#define ADI_MAX32_CLK_IPO_FREQ DT_PROP(DT_NODELABEL(clk_ipo), clock_frequency) +#define ADI_MAX32_CLK_ERFO_FREQ DT_PROP(DT_NODELABEL(clk_erfo), clock_frequency) +#define ADI_MAX32_CLK_IBRO_FREQ DT_PROP(DT_NODELABEL(clk_ibro), clock_frequency) +#define ADI_MAX32_CLK_ISO_FREQ DT_PROP_OR(DT_NODELABEL(clk_iso), clock_frequency, 0) +#define ADI_MAX32_CLK_INRO_FREQ DT_PROP(DT_NODELABEL(clk_inro), clock_frequency) +#define ADI_MAX32_CLK_ERTCO_FREQ DT_PROP(DT_NODELABEL(clk_ertco), clock_frequency) +/* External clock may not be defined so _OR is used */ +#define ADI_MAX32_CLK_EXTCLK_FREQ DT_PROP_OR(DT_NODELABEL(clk_extclk), clock_frequency, 0) + +#define DT_GCR_CLOCKS_CTRL DT_CLOCKS_CTLR(DT_NODELABEL(gcr)) + +#if DT_SAME_NODE(DT_GCR_CLOCKS_CTRL, DT_NODELABEL(clk_ipo)) +#define ADI_MAX32_SYSCLK_SRC ADI_MAX32_CLK_IPO +#define ADI_MAX32_SYSCLK_FREQ (ADI_MAX32_CLK_IPO_FREQ / ADI_MAX32_SYSCLK_PRESCALER) +#endif +#if DT_SAME_NODE(DT_GCR_CLOCKS_CTRL, DT_NODELABEL(clk_erfo)) +#define ADI_MAX32_SYSCLK_SRC ADI_MAX32_CLK_ERFO +#define ADI_MAX32_SYSCLK_FREQ (ADI_MAX32_CLK_ERFO_FREQ / ADI_MAX32_SYSCLK_PRESCALER) +#endif +#if DT_SAME_NODE(DT_GCR_CLOCKS_CTRL, DT_NODELABEL(clk_ibro)) +#define ADI_MAX32_SYSCLK_SRC ADI_MAX32_CLK_IBRO +#define ADI_MAX32_SYSCLK_FREQ (ADI_MAX32_CLK_IBRO_FREQ / ADI_MAX32_SYSCLK_PRESCALER) +#endif +#if DT_SAME_NODE(DT_GCR_CLOCKS_CTRL, DT_NODELABEL(clk_iso)) +#define ADI_MAX32_SYSCLK_SRC ADI_MAX32_CLK_ISO +#define ADI_MAX32_SYSCLK_FREQ (ADI_MAX32_CLK_ISO_FREQ / ADI_MAX32_SYSCLK_PRESCALER) +#endif +#if DT_SAME_NODE(DT_GCR_CLOCKS_CTRL, DT_NODELABEL(clk_inro)) +#define ADI_MAX32_SYSCLK_SRC ADI_MAX32_CLK_INRO +#define ADI_MAX32_SYSCLK_FREQ (ADI_MAX32_CLK_INRO_FREQ / ADI_MAX32_SYSCLK_PRESCALER) +#endif +#if DT_SAME_NODE(DT_GCR_CLOCKS_CTRL, DT_NODELABEL(clk_ertco)) +#define ADI_MAX32_SYSCLK_SRC ADI_MAX32_CLK_ERTCO +#define ADI_MAX32_SYSCLK_FREQ (ADI_MAX32_CLK_ERTCO_FREQ / ADI_MAX32_SYSCLK_PRESCALER) +#endif +#if DT_SAME_NODE(DT_GCR_CLOCKS_CTRL, DT_NODELABEL(clk_extclk)) +#define ADI_MAX32_SYSCLK_SRC ADI_MAX32_CLK_EXTCLK +#define ADI_MAX32_SYSCLK_FREQ (ADI_MAX32_CLK_EXTCLK_FREQ / ADI_MAX32_SYSCLK_PRESCALER) +#endif + +#ifndef ADI_MAX32_SYSCLK_SRC +#define ADI_MAX32_SYSCLK_SRC ADI_MAX32_CLK_IPO +#define ADI_MAX32_SYSCLK_FREQ (ADI_MAX32_CLK_IPO_FREQ / ADI_MAX32_SYSCLK_PRESCALER) +#endif + +#define ADI_MAX32_PCLK_FREQ (ADI_MAX32_SYSCLK_FREQ / 2) + +#define ADI_MAX32_GET_PRPH_CLK_FREQ(clk_src) \ + ((clk_src) == ADI_MAX32_PRPH_CLK_SRC_PCLK ? ADI_MAX32_PCLK_FREQ \ + : (clk_src) == ADI_MAX32_PRPH_CLK_SRC_IBRO ? ADI_MAX32_CLK_IBRO_FREQ \ + : (clk_src) == ADI_MAX32_PRPH_CLK_SRC_ERFO ? ADI_MAX32_CLK_ERFO_FREQ \ + : (clk_src) == ADI_MAX32_PRPH_CLK_SRC_ERTCO ? ADI_MAX32_CLK_ERTCO_FREQ \ + : (clk_src) == ADI_MAX32_PRPH_CLK_SRC_INRO ? ADI_MAX32_CLK_INRO_FREQ \ + : (clk_src) == ADI_MAX32_PRPH_CLK_SRC_ISO ? ADI_MAX32_CLK_ISO_FREQ \ + : (clk_src) == ADI_MAX32_PRPH_CLK_SRC_IBRO_DIV8 ? (ADI_MAX32_CLK_IBRO_FREQ / 8) \ + : (clk_src) == ADI_MAX32_PRPH_CLK_SRC_EXTCLK ? ADI_MAX32_CLK_EXTCLK_FREQ \ + : 0) + +#endif /* ZEPHYR_INCLUDE_DRIVERS_CLOCK_CONTROL_ADI_MAX32_CLOCK_CONTROL_H_ */ diff --git a/include/zephyr/dt-bindings/clock/adi_max32_clock.h b/include/zephyr/dt-bindings/clock/adi_max32_clock.h new file mode 100644 index 0000000000000..44fb918c22e9b --- /dev/null +++ b/include/zephyr/dt-bindings/clock/adi_max32_clock.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2023-2024 Analog Devices, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_ADI_MAX32_CLOCK_H_ +#define ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_ADI_MAX32_CLOCK_H_ + +/** Peripheral clock register */ +#define ADI_MAX32_CLOCK_BUS0 0 +#define ADI_MAX32_CLOCK_BUS1 1 +#define ADI_MAX32_CLOCK_BUS2 2 + +/** Clock source for peripheral interfaces like UART, WDT... */ +#define ADI_MAX32_PRPH_CLK_SRC_PCLK 0 /* Peripheral clock */ +#define ADI_MAX32_PRPH_CLK_SRC_EXTCLK 1 /* External clock */ +#define ADI_MAX32_PRPH_CLK_SRC_IBRO 2 /* Internal Baud Rate Oscillator*/ +#define ADI_MAX32_PRPH_CLK_SRC_ERFO 3 /* External RF Oscillator */ +#define ADI_MAX32_PRPH_CLK_SRC_ERTCO 4 /* External RTC Oscillator */ +#define ADI_MAX32_PRPH_CLK_SRC_INRO 5 /* Internal Nano Ring Oscillator */ +#define ADI_MAX32_PRPH_CLK_SRC_ISO 6 /* Internal Secondary Oscillator */ +#define ADI_MAX32_PRPH_CLK_SRC_IBRO_DIV8 7 /* IBRO/8 */ + +#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_ADI_MAX32_CLOCK_H_ */ From f76256d2f19577eb2a7f334c55496a361474c2f8 Mon Sep 17 00:00:00 2001 From: Sadik Ozer Date: Fri, 13 Oct 2023 16:13:46 +0300 Subject: [PATCH 1293/2849] drivers: Add MAX32690 pinctrl driver Pincontrol driver for MAX32690 Co-authored-by: Okan Sahin Signed-off-by: Sadik Ozer --- drivers/pinctrl/CMakeLists.txt | 1 + drivers/pinctrl/Kconfig | 1 + drivers/pinctrl/Kconfig.max32 | 9 ++ drivers/pinctrl/pinctrl_max32.c | 114 ++++++++++++++++++ dts/bindings/pinctrl/adi,max32-pinctrl.yaml | 90 ++++++++++++++ .../dt-bindings/pinctrl/max32-pinctrl.h | 67 ++++++++++ soc/adi/max32/common/pinctrl_soc.h | 48 ++++++++ 7 files changed, 330 insertions(+) create mode 100644 drivers/pinctrl/Kconfig.max32 create mode 100644 drivers/pinctrl/pinctrl_max32.c create mode 100644 dts/bindings/pinctrl/adi,max32-pinctrl.yaml create mode 100644 include/zephyr/dt-bindings/pinctrl/max32-pinctrl.h create mode 100644 soc/adi/max32/common/pinctrl_soc.h diff --git a/drivers/pinctrl/CMakeLists.txt b/drivers/pinctrl/CMakeLists.txt index 91bbb8b3d5161..1dce91d597786 100644 --- a/drivers/pinctrl/CMakeLists.txt +++ b/drivers/pinctrl/CMakeLists.txt @@ -37,5 +37,6 @@ zephyr_library_sources_ifdef(CONFIG_PINCTRL_QUICKLOGIC_EOS_S3 pinctrl_eos_s3.c) zephyr_library_sources_ifdef(CONFIG_PINCTRL_MCI_IO_MUX pinctrl_mci_io_mux.c) zephyr_library_sources_ifdef(CONFIG_PINCTRL_ENE_KB1200 pinctrl_ene_kb1200.c) zephyr_library_sources_ifdef(CONFIG_PINCTRL_IMX_SCU pinctrl_imx_scu.c) +zephyr_library_sources_ifdef(CONFIG_PINCTRL_MAX32 pinctrl_max32.c) add_subdirectory(renesas) diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig index ab6ea86bcc9a8..b919fa0f169b0 100644 --- a/drivers/pinctrl/Kconfig +++ b/drivers/pinctrl/Kconfig @@ -65,6 +65,7 @@ source "drivers/pinctrl/Kconfig.eos_s3" source "drivers/pinctrl/Kconfig.mci_io_mux" source "drivers/pinctrl/Kconfig.ene" source "drivers/pinctrl/Kconfig.zynqmp" +source "drivers/pinctrl/Kconfig.max32" rsource "renesas/Kconfig" diff --git a/drivers/pinctrl/Kconfig.max32 b/drivers/pinctrl/Kconfig.max32 new file mode 100644 index 0000000000000..13d5ef77a1c06 --- /dev/null +++ b/drivers/pinctrl/Kconfig.max32 @@ -0,0 +1,9 @@ +# Copyright (c) 2023-2024 Analog Devices, Inc. +# SPDX-License-Identifier: Apache-2.0 + +config PINCTRL_MAX32 + bool "Analog Devices MAX32 MCUs pin controller driver" + default y + depends on DT_HAS_ADI_MAX32_PINCTRL_ENABLED + help + Pin controller driver support for max32 SoC series diff --git a/drivers/pinctrl/pinctrl_max32.c b/drivers/pinctrl/pinctrl_max32.c new file mode 100644 index 0000000000000..e9fcf65aa8591 --- /dev/null +++ b/drivers/pinctrl/pinctrl_max32.c @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2023-2024 Analog Devices, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +#include + +#define ADI_MAX32_GET_PORT_ADDR_OR_NONE(nodelabel) \ + IF_ENABLED(DT_NODE_EXISTS(DT_NODELABEL(nodelabel)), \ + (DT_REG_ADDR(DT_NODELABEL(nodelabel)),)) + +/** GPIO port addresses */ +static const uint32_t gpios[] = { + ADI_MAX32_GET_PORT_ADDR_OR_NONE(gpio0) + ADI_MAX32_GET_PORT_ADDR_OR_NONE(gpio1) + ADI_MAX32_GET_PORT_ADDR_OR_NONE(gpio2) + ADI_MAX32_GET_PORT_ADDR_OR_NONE(gpio3) + ADI_MAX32_GET_PORT_ADDR_OR_NONE(gpio4) + ADI_MAX32_GET_PORT_ADDR_OR_NONE(gpio5) +}; + +static int pinctrl_configure_pin(pinctrl_soc_pin_t soc_pin) +{ + uint32_t port; + uint32_t pin; + uint32_t afx; + int pincfg; + mxc_gpio_cfg_t gpio_cfg; + + port = MAX32_PINMUX_PORT(soc_pin.pinmux); + pin = MAX32_PINMUX_PIN(soc_pin.pinmux); + afx = MAX32_PINMUX_MODE(soc_pin.pinmux); + pincfg = soc_pin.pincfg; + + if (gpios[port] == 0) { + return -EINVAL; + } + + gpio_cfg.port = (mxc_gpio_regs_t *)gpios[port]; + gpio_cfg.mask = BIT(pin); + + if (pincfg & BIT(MAX32_BIAS_PULL_UP_SHIFT)) { + gpio_cfg.pad = MXC_GPIO_PAD_PULL_UP; + } else if (pincfg & BIT(MAX32_BIAS_PULL_DOWN_SHIFT)) { + gpio_cfg.pad = MXC_GPIO_PAD_PULL_DOWN; + } else { + gpio_cfg.pad = MXC_GPIO_PAD_NONE; + } + + if (pincfg & BIT(MAX32_INPUT_ENABLE_SHIFT)) { + gpio_cfg.func = MXC_GPIO_FUNC_IN; + } else if (pincfg & BIT(MAX32_OUTPUT_ENABLE_SHIFT)) { + gpio_cfg.func = MXC_GPIO_FUNC_OUT; + } else { + /* Add +1 to index match */ + gpio_cfg.func = (mxc_gpio_func_t)(afx + 1); + } + + if (pincfg & BIT(MAX32_POWER_SOURCE_SHIFT)) { + gpio_cfg.vssel = MXC_GPIO_VSSEL_VDDIOH; + } else { + gpio_cfg.vssel = MXC_GPIO_VSSEL_VDDIO; + } + + switch (pincfg & MAX32_GPIO_DRV_STRENGTH_MASK) { + case MAX32_GPIO_DRV_STRENGTH_1: + gpio_cfg.drvstr = MXC_GPIO_DRVSTR_1; + break; + case MAX32_GPIO_DRV_STRENGTH_2: + gpio_cfg.drvstr = MXC_GPIO_DRVSTR_2; + break; + case MAX32_GPIO_DRV_STRENGTH_3: + gpio_cfg.drvstr = MXC_GPIO_DRVSTR_3; + break; + default: + gpio_cfg.drvstr = MXC_GPIO_DRVSTR_0; + break; + } + + if (MXC_GPIO_Config(&gpio_cfg) != 0) { + return -ENOTSUP; + } + + if (pincfg & BIT(MAX32_OUTPUT_ENABLE_SHIFT)) { + if (pincfg & BIT(MAX32_OUTPUT_HIGH_SHIFT)) { + MXC_GPIO_OutSet(gpio_cfg.port, BIT(pin)); + } else { + MXC_GPIO_OutClr(gpio_cfg.port, BIT(pin)); + } + } + + return 0; +} + +int pinctrl_configure_pins(const pinctrl_soc_pin_t *pins, uint8_t pin_cnt, uintptr_t reg) +{ + ARG_UNUSED(reg); + + int ret; + + for (uint8_t i = 0U; i < pin_cnt; i++) { + ret = pinctrl_configure_pin(*pins++); + if (ret) { + return ret; + } + } + + return 0; +} diff --git a/dts/bindings/pinctrl/adi,max32-pinctrl.yaml b/dts/bindings/pinctrl/adi,max32-pinctrl.yaml new file mode 100644 index 0000000000000..d40926ca772b9 --- /dev/null +++ b/dts/bindings/pinctrl/adi,max32-pinctrl.yaml @@ -0,0 +1,90 @@ +# Copyright (c) 2023-2024 Analog Devices, Inc. +# SPDX-License-Identifier: Apache-2.0 + +description: | + MAX32 Pin controller Node + Based on pincfg-node.yaml binding. + + Note: `bias-disable` are default pin configurations. + +compatible: "adi,max32-pinctrl" + +include: base.yaml + +properties: + reg: + required: true + + +child-binding: + description: | + Base binding configuration for ADI MAX32xxx MCUs + + include: + - name: pincfg-node.yaml + property-allowlist: + - bias-disable + - bias-pull-down + - bias-pull-up + - output-low + - output-high + - input-enable + - output-enable + - power-source + - drive-strength + + properties: + pinmux: + required: true + type: int + description: | + Integer array, represents gpio pin number and mux setting. + These defines are calculated as: (pin<<8 | port<<4 | function<<0) + With: + - port: The gpio port index (0, 1, ...) + - pin: The pin offset within the port (0, 1, 2, ...) + - function: The function number, can be: + * 0 : GPIO + * 1 : Alternate Function 1 + * 2 : Alternate Function 2 + * 3 : Alternate Function 3 + * 4 : Alternate Function 4 + In case selected pin function is GPIO, pin is statically configured as + a plain input/output GPIO. Default configuration is input. Output value + can be configured by adding 'ouptut-low' or 'output-high' properties + to the pin configuration. + + To simplify the usage, macro is available to generate "pinmux" field. + This macro is available here: + -include/zephyr/dt-bindings/pinctrl/max32-pinctrl.h + Some examples of macro usage: + P0.9 set as alernate function 1 + { + pinmux = ; + }; + P0.9 set as alernate function 2 + { + pinmux = ; + }; + P0.9 set as GPIO output high + { + pinmux = ; + output-high; + }; + power-source: + enum: [0, 1] + description: | + GPIO Supply Voltage Select, Selects the voltage rail used for the pin. + 0 or MAX32_VSEL_VDDIO + 1 or MAX32_VSEL_VDDIOH + drive-strength: + default: 0 + enum: [0, 1, 2, 3] + description: | + There are 4 drive strength mode. + Mode 0: 1mA + Mode 1: 2mA + Mode 2: 4mA + Mode 3: 8mA + Default GPIO output drive strength is mode 0 for MAX32 MCUs. + For more information please take a look device user guide, datasheet. diff --git a/include/zephyr/dt-bindings/pinctrl/max32-pinctrl.h b/include/zephyr/dt-bindings/pinctrl/max32-pinctrl.h new file mode 100644 index 0000000000000..97a3ab76748d1 --- /dev/null +++ b/include/zephyr/dt-bindings/pinctrl/max32-pinctrl.h @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2023-2024 Analog Devices, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_PINCTRL_MAX32_PINCTRL_H_ +#define ZEPHYR_INCLUDE_DT_BINDINGS_PINCTRL_MAX32_PINCTRL_H_ + +/** + * @brief Pin modes + */ +#define MAX32_MODE_GPIO 0x00 +#define MAX32_MODE_AF1 0x01 +#define MAX32_MODE_AF2 0x02 +#define MAX32_MODE_AF3 0x03 +#define MAX32_MODE_AF4 0x04 +#define MAX32_MODE_AF5 0x05 + +/** + * @brief Mode, port, pin shift number + */ +#define MAX32_MODE_SHIFT 0U +#define MAX32_MODE_MASK 0x0FU +#define MAX32_PORT_SHIFT 4U +#define MAX32_PORT_MASK 0x0FU +#define MAX32_PIN_SHIFT 8U +#define MAX32_PIN_MASK 0xFFU + +/** + * @brief Pin configuration bit field. + * + * Fields: + * + * - mode [ 0 : 3 ] + * - port [ 4 : 7 ] + * - pin [ 8 : 15 ] + * + * @param port Port (0 .. 15) + * @param pin Pin (0..31) + * @param mode Mode (GPIO, AF1, AF2...). + */ +#define MAX32_PINMUX(port, pin, mode) \ + ((((port)&MAX32_PORT_MASK) << MAX32_PORT_SHIFT) | \ + (((pin)&MAX32_PIN_MASK) << MAX32_PIN_SHIFT) | \ + (((MAX32_MODE_##mode) & MAX32_MODE_MASK) << MAX32_MODE_SHIFT)) + +#define MAX32_PINMUX_PORT(pinmux) (((pinmux) >> MAX32_PORT_SHIFT) & MAX32_PORT_MASK) +#define MAX32_PINMUX_PIN(pinmux) (((pinmux) >> MAX32_PIN_SHIFT) & MAX32_PIN_MASK) +#define MAX32_PINMUX_MODE(pinmux) (((pinmux) >> MAX32_MODE_SHIFT) & MAX32_MODE_MASK) + +/* Selects the voltage rail used for the pin */ +#define MAX32_VSEL_VDDIO 0 +#define MAX32_VSEL_VDDIOH 1 + +/** + * @brief Pin configuration + */ +#define MAX32_INPUT_ENABLE_SHIFT 0x00 +#define MAX32_BIAS_PULL_UP_SHIFT 0x01 +#define MAX32_BIAS_PULL_DOWN_SHIFT 0x02 +#define MAX32_OUTPUT_ENABLE_SHIFT 0x03 +#define MAX32_POWER_SOURCE_SHIFT 0x04 +#define MAX32_OUTPUT_HIGH_SHIFT 0x05 +#define MAX32_DRV_STRENGTH_SHIFT 0x06 /* 2 bits */ + +#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_PINCTRL_MAX32_PINCTRL_H_ */ diff --git a/soc/adi/max32/common/pinctrl_soc.h b/soc/adi/max32/common/pinctrl_soc.h new file mode 100644 index 0000000000000..d9a56f422b2d0 --- /dev/null +++ b/soc/adi/max32/common/pinctrl_soc.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2023-2024 Analog Devices, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_SOC_ARM_ADI_MAX32_COMMON_PINCTRL_SOC_H_ +#define ZEPHYR_SOC_ARM_ADI_MAX32_COMMON_PINCTRL_SOC_H_ + +#include +#include + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct pinctrl_soc_pin { + uint32_t pinmux; + uint32_t pincfg; +} pinctrl_soc_pin_t; + +#define Z_PINCTRL_MAX32_PINMUX_INIT(node_id) DT_PROP(node_id, pinmux) + +#define Z_PINCTRL_MAX32_PINCFG_INIT(node) \ + ((DT_PROP_OR(node, input_enable, 0) << MAX32_INPUT_ENABLE_SHIFT) | \ + (DT_PROP_OR(node, output_enable, 0) << MAX32_OUTPUT_ENABLE_SHIFT) | \ + (DT_PROP_OR(node, bias_pull_up, 0) << MAX32_BIAS_PULL_UP_SHIFT) | \ + (DT_PROP_OR(node, bias_pull_down, 0) << MAX32_BIAS_PULL_DOWN_SHIFT) | \ + (DT_PROP_OR(node, power_source, 0) << MAX32_POWER_SOURCE_SHIFT) | \ + (DT_PROP_OR(node, output_high, 0) << MAX32_OUTPUT_HIGH_SHIFT) | \ + (DT_PROP_OR(node, drive_strength, 0) << MAX32_DRV_STRENGTH_SHIFT)) + +#define Z_PINCTRL_STATE_PIN_INIT(node_id, state_prop, idx) \ + {.pinmux = Z_PINCTRL_MAX32_PINMUX_INIT(DT_PROP_BY_IDX(node_id, state_prop, idx)), \ + .pincfg = Z_PINCTRL_MAX32_PINCFG_INIT(DT_PROP_BY_IDX(node_id, state_prop, idx))}, + +#define Z_PINCTRL_STATE_PINS_INIT(node_id, prop) \ + { \ + DT_FOREACH_PROP_ELEM(node_id, prop, Z_PINCTRL_STATE_PIN_INIT) \ + } + +#ifdef __cplusplus +} +#endif + +#endif /* ZEPHYR_SOC_ARM_ADI_MAX32_COMMON_PINCTRL_SOC_H_ */ From d6e17531259f2d11c07aaf6089eaed5b39032e82 Mon Sep 17 00:00:00 2001 From: Sadik Ozer Date: Wed, 15 May 2024 13:35:47 +0300 Subject: [PATCH 1294/2849] drivers: Add MAX32690 gpio driver GPIO driver for MAX32690 Co-authored-by: Okan Sahin Signed-off-by: Sadik Ozer --- drivers/gpio/CMakeLists.txt | 1 + drivers/gpio/Kconfig | 1 + drivers/gpio/Kconfig.max32 | 9 + drivers/gpio/gpio_max32.c | 268 ++++++++++++++++++ dts/bindings/gpio/adi,max32-gpio.yaml | 19 ++ .../zephyr/dt-bindings/gpio/adi-max32-gpio.h | 69 +++++ 6 files changed, 367 insertions(+) create mode 100644 drivers/gpio/Kconfig.max32 create mode 100644 drivers/gpio/gpio_max32.c create mode 100644 dts/bindings/gpio/adi,max32-gpio.yaml create mode 100644 include/zephyr/dt-bindings/gpio/adi-max32-gpio.h diff --git a/drivers/gpio/CMakeLists.txt b/drivers/gpio/CMakeLists.txt index 6e1cab6d2485e..e150c8c8ea3b1 100644 --- a/drivers/gpio/CMakeLists.txt +++ b/drivers/gpio/CMakeLists.txt @@ -39,6 +39,7 @@ zephyr_library_sources_ifdef(CONFIG_GPIO_KSCAN_ITE_IT8XXX2 gpio_kscan_ite_it8xxx zephyr_library_sources_ifdef(CONFIG_GPIO_LITEX gpio_litex.c) zephyr_library_sources_ifdef(CONFIG_GPIO_LMP90XXX gpio_lmp90xxx.c) zephyr_library_sources_ifdef(CONFIG_GPIO_LPC11U6X gpio_lpc11u6x.c) +zephyr_library_sources_ifdef(CONFIG_GPIO_MAX32 gpio_max32.c) zephyr_library_sources_ifdef(CONFIG_GPIO_MCHP_MSS gpio_mchp_mss.c) zephyr_library_sources_ifdef(CONFIG_GPIO_MCP230XX gpio_mcp230xx.c) zephyr_library_sources_ifdef(CONFIG_GPIO_MCP23S17 gpio_mcp23s17.c) diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index f9126fef8d970..b337ccba18b1e 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -129,6 +129,7 @@ source "drivers/gpio/Kconfig.it8xxx2" source "drivers/gpio/Kconfig.litex" source "drivers/gpio/Kconfig.lmp90xxx" source "drivers/gpio/Kconfig.lpc11u6x" +source "drivers/gpio/Kconfig.max32" source "drivers/gpio/Kconfig.mchp_mss" source "drivers/gpio/Kconfig.mcp23s17" source "drivers/gpio/Kconfig.mcp23xxx" diff --git a/drivers/gpio/Kconfig.max32 b/drivers/gpio/Kconfig.max32 new file mode 100644 index 0000000000000..6f0a5e7ef058f --- /dev/null +++ b/drivers/gpio/Kconfig.max32 @@ -0,0 +1,9 @@ +# Copyright (c) 2023-2024 Analog Devices, Inc. +# SPDX-License-Identifier: Apache-2.0 + +config GPIO_MAX32 + bool "GPIO Driver for MAX32 family of MCUs" + default y + depends on DT_HAS_ADI_MAX32_GPIO_ENABLED + help + Enable GPIO driver for MAX32 line of MCUs diff --git a/drivers/gpio/gpio_max32.c b/drivers/gpio/gpio_max32.c new file mode 100644 index 0000000000000..66f5d155a7a7a --- /dev/null +++ b/drivers/gpio/gpio_max32.c @@ -0,0 +1,268 @@ +/* + * Copyright (c) 2023-2024 Analog Devices, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include +#include + +#define DT_DRV_COMPAT adi_max32_gpio + +LOG_MODULE_REGISTER(gpio_max32, CONFIG_GPIO_LOG_LEVEL); + +struct max32_gpio_config { + struct gpio_driver_config common; + mxc_gpio_regs_t *regs; + const struct device *clock; + void (*irq_func)(void); + struct max32_perclk perclk; +}; + +struct max32_gpio_data { + struct gpio_driver_data common; + sys_slist_t cb_list; +}; + +static int api_port_get_raw(const struct device *dev, uint32_t *value) +{ + const struct max32_gpio_config *cfg = dev->config; + + *value = MXC_GPIO_InGet(cfg->regs, (unsigned int)-1); + return 0; +} + +static int api_port_set_masked_raw(const struct device *dev, gpio_port_pins_t mask, + gpio_port_value_t value) +{ + const struct max32_gpio_config *cfg = dev->config; + + MXC_GPIO_OutPut(cfg->regs, mask, value); + return 0; +} + +static int api_port_set_bits_raw(const struct device *dev, gpio_port_pins_t pins) +{ + const struct max32_gpio_config *cfg = dev->config; + + MXC_GPIO_OutSet(cfg->regs, pins); + return 0; +} + +static int api_port_clear_bits_raw(const struct device *dev, gpio_port_pins_t pins) +{ + const struct max32_gpio_config *cfg = dev->config; + + MXC_GPIO_OutClr(cfg->regs, pins); + return 0; +} + +static int api_port_toggle_bits(const struct device *dev, gpio_port_pins_t pins) +{ + const struct max32_gpio_config *cfg = dev->config; + + MXC_GPIO_OutToggle(cfg->regs, pins); + return 0; +} + +static int api_pin_configure(const struct device *dev, gpio_pin_t pin, gpio_flags_t flags) +{ + const struct max32_gpio_config *cfg = dev->config; + mxc_gpio_cfg_t gpio_cfg; + int ret; + + /* MAX32xxx MCUs does not support SINGLE_ENDED, open drain, mode */ + if (flags & GPIO_SINGLE_ENDED) { + return -ENOTSUP; + } + + gpio_cfg.port = cfg->regs; + gpio_cfg.mask = BIT(pin); + + if (flags & GPIO_PULL_UP) { + gpio_cfg.pad = MXC_GPIO_PAD_PULL_UP; + } else if (flags & GPIO_PULL_DOWN) { + gpio_cfg.pad = MXC_GPIO_PAD_PULL_DOWN; + } else if (flags & MAX32_GPIO_WEAK_PULL_UP) { + gpio_cfg.pad = MXC_GPIO_PAD_WEAK_PULL_UP; + } else if (flags & MAX32_GPIO_WEAK_PULL_DOWN) { + gpio_cfg.pad = MXC_GPIO_PAD_WEAK_PULL_DOWN; + } else { + gpio_cfg.pad = MXC_GPIO_PAD_NONE; + } + + if (flags & GPIO_OUTPUT) { + gpio_cfg.func = MXC_GPIO_FUNC_OUT; + } else if (flags & GPIO_INPUT) { + gpio_cfg.func = MXC_GPIO_FUNC_IN; + } else { + /* this case will not occur this function call for gpio mode in/out */ + gpio_cfg.func = MXC_GPIO_FUNC_ALT1; /* TODO: Think on it */ + } + + if (flags & MAX32_GPIO_VSEL_VDDIOH) { + gpio_cfg.vssel = MXC_GPIO_VSSEL_VDDIOH; + } else { + gpio_cfg.vssel = MXC_GPIO_VSSEL_VDDIO; + } + + switch (flags & MAX32_GPIO_DRV_STRENGTH_MASK) { + case MAX32_GPIO_DRV_STRENGTH_1: + gpio_cfg.drvstr = MXC_GPIO_DRVSTR_1; + break; + case MAX32_GPIO_DRV_STRENGTH_2: + gpio_cfg.drvstr = MXC_GPIO_DRVSTR_2; + break; + case MAX32_GPIO_DRV_STRENGTH_3: + gpio_cfg.drvstr = MXC_GPIO_DRVSTR_3; + break; + default: + gpio_cfg.drvstr = MXC_GPIO_DRVSTR_0; + break; + } + + ret = MXC_GPIO_Config(&gpio_cfg); + if (ret != 0) { + return -ENOTSUP; + } + + if (flags & GPIO_OUTPUT) { + if (flags & GPIO_OUTPUT_INIT_LOW) { + MXC_GPIO_OutClr(cfg->regs, BIT(pin)); + } else if (flags & GPIO_OUTPUT_INIT_HIGH) { + MXC_GPIO_OutSet(cfg->regs, BIT(pin)); + } + } + + return 0; +} + +static int api_pin_interrupt_configure(const struct device *dev, gpio_pin_t pin, + enum gpio_int_mode mode, enum gpio_int_trig trig) +{ + const struct max32_gpio_config *cfg = dev->config; + mxc_gpio_cfg_t gpio_cfg; + + gpio_cfg.port = cfg->regs; + gpio_cfg.mask = BIT(pin); + /* rest of the parameters not necessary */ + + if (mode == GPIO_INT_MODE_DISABLED) { + MXC_GPIO_DisableInt(cfg->regs, gpio_cfg.mask); + + /* clear interrupt flags */ + MXC_GPIO_ClearFlags(cfg->regs, (MXC_GPIO_GetFlags(cfg->regs) & gpio_cfg.mask)); + + return 0; + } + + switch (mode) { + case GPIO_INT_MODE_LEVEL: + if (trig == GPIO_INT_TRIG_LOW) { + MXC_GPIO_IntConfig(&gpio_cfg, MXC_GPIO_INT_LOW); + } else if (trig == GPIO_INT_TRIG_HIGH) { + MXC_GPIO_IntConfig(&gpio_cfg, MXC_GPIO_INT_HIGH); + } else if (trig == GPIO_INT_TRIG_BOTH) { + MXC_GPIO_IntConfig(&gpio_cfg, MXC_GPIO_INT_BOTH); + } else { + return -EINVAL; + } + break; + case GPIO_INT_MODE_EDGE: + if (trig == GPIO_INT_TRIG_LOW) { + MXC_GPIO_IntConfig(&gpio_cfg, MXC_GPIO_INT_FALLING); + } else if (trig == GPIO_INT_TRIG_HIGH) { + MXC_GPIO_IntConfig(&gpio_cfg, MXC_GPIO_INT_RISING); + } else if (trig == GPIO_INT_TRIG_BOTH) { + MXC_GPIO_IntConfig(&gpio_cfg, MXC_GPIO_INT_BOTH); + } else { + return -EINVAL; + } + break; + default: + return -EINVAL; + } + + cfg->irq_func(); + MXC_GPIO_EnableInt(cfg->regs, gpio_cfg.mask); + + return 0; +} + +static int api_manage_callback(const struct device *dev, struct gpio_callback *callback, bool set) +{ + struct max32_gpio_data *data = dev->data; + + return gpio_manage_callback(&(data->cb_list), callback, set); +} + +static const struct gpio_driver_api gpio_max32_driver = { + .pin_configure = api_pin_configure, + .port_get_raw = api_port_get_raw, + .port_set_masked_raw = api_port_set_masked_raw, + .port_set_bits_raw = api_port_set_bits_raw, + .port_clear_bits_raw = api_port_clear_bits_raw, + .port_toggle_bits = api_port_toggle_bits, + .pin_interrupt_configure = api_pin_interrupt_configure, + .manage_callback = api_manage_callback, +}; + +static void gpio_max32_isr(const void *param) +{ + const struct device *dev = param; + const struct max32_gpio_config *cfg = dev->config; + struct max32_gpio_data *data = dev->data; + + unsigned int flags = MXC_GPIO_GetFlags(cfg->regs); + /* clear interrupt flags */ + MXC_GPIO_ClearFlags(cfg->regs, flags); + + gpio_fire_callbacks(&(data->cb_list), dev, flags); +} + +static int gpio_max32_init(const struct device *dev) +{ + int ret = 0; + const struct max32_gpio_config *cfg = dev->config; + + if (cfg->clock != NULL) { + /* enable clock */ + ret = clock_control_on(cfg->clock, (clock_control_subsys_t)&cfg->perclk); + if (ret != 0) { + LOG_ERR("cannot enable GPIO clock"); + return ret; + } + } + + return ret; +} + +#define MAX32_GPIO_INIT(_num) \ + static void gpio_max32_irq_init_##_num(void) \ + { \ + IRQ_CONNECT(DT_INST_IRQN(_num), DT_INST_IRQ(_num, priority), gpio_max32_isr, \ + DEVICE_DT_INST_GET(_num), 0); \ + irq_enable(DT_INST_IRQN(_num)); \ + } \ + static struct max32_gpio_data max32_gpio_data_##_num; \ + static const struct max32_gpio_config max32_gpio_config_##_num = { \ + .common = \ + { \ + .port_pin_mask = GPIO_PORT_PIN_MASK_FROM_DT_INST(_num), \ + }, \ + .regs = (mxc_gpio_regs_t *)DT_INST_REG_ADDR(_num), \ + .irq_func = &gpio_max32_irq_init_##_num, \ + .clock = DEVICE_DT_GET_OR_NULL(DT_INST_CLOCKS_CTLR(_num)), \ + .perclk.bus = DT_INST_PHA_BY_IDX_OR(_num, clocks, 0, offset, 0), \ + .perclk.bit = DT_INST_PHA_BY_IDX_OR(_num, clocks, 1, bit, 0), \ + }; \ + DEVICE_DT_INST_DEFINE(_num, gpio_max32_init, NULL, &max32_gpio_data_##_num, \ + &max32_gpio_config_##_num, PRE_KERNEL_1, CONFIG_GPIO_INIT_PRIORITY, \ + (void *)&gpio_max32_driver); + +DT_INST_FOREACH_STATUS_OKAY(MAX32_GPIO_INIT) diff --git a/dts/bindings/gpio/adi,max32-gpio.yaml b/dts/bindings/gpio/adi,max32-gpio.yaml new file mode 100644 index 0000000000000..d903ff70cae10 --- /dev/null +++ b/dts/bindings/gpio/adi,max32-gpio.yaml @@ -0,0 +1,19 @@ +# Copyright (c) 2023-2024 Analog Devices, Inc. +# SPDX-License-Identifier: Apache-2.0 + +description: MAX32 GPIO + +compatible: "adi,max32-gpio" + +include: [gpio-controller.yaml, base.yaml] + +properties: + reg: + required: true + + "#gpio-cells": + const: 2 + +gpio-cells: + - pin + - flags diff --git a/include/zephyr/dt-bindings/gpio/adi-max32-gpio.h b/include/zephyr/dt-bindings/gpio/adi-max32-gpio.h new file mode 100644 index 0000000000000..bcc50cee8d4dd --- /dev/null +++ b/include/zephyr/dt-bindings/gpio/adi-max32-gpio.h @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2023-2024 Analog Devices, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ +#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_GPIO_ADI_MAX32_GPIO_H_ +#define ZEPHYR_INCLUDE_DT_BINDINGS_GPIO_ADI_MAX32_GPIO_H_ + +/** + * @brief MAX32-specific GPIO Flags + * @defgroup gpio_interface_max32 MAX32-specific GPIO Flags + * @ingroup gpio_interface + * @{ + */ + +/** + * @name MAX32 GPIO drive flags + * @brief MAX32 GPIO drive flags + * + * The drive flags are encoded in the 8 upper bits of @ref gpio_dt_flags_t as + * follows: + * + * - Bit 8: GPIO Supply Voltage Select + * Selects the voltage rail used for the pin. + * 0: VDDIO + * 1: VDDIOH + * + * - Bit 9: GPIO Drive Strength Select, + * MAX32_GPIO_DRV_STRENGTH_0 = 1mA + * MAX32_GPIO_DRV_STRENGTH_1 = 2mA + * MAX32_GPIO_DRV_STRENGTH_2 = 4mA + * MAX32_GPIO_DRV_STRENGTH_3 = 8mA + * + * - Bit 10: Weak pull up selection, Weak Pullup to VDDIO (1MOhm) + * 0: Disable + * 1: Enable + * + * - Bit 11: Weak pull down selection, Weak Pulldown to VDDIOH (1MOhm) + * 0: Disable + * 1: Enable + * @{ + */ + +/** GPIO Voltage Select */ +#define MAX32_GPIO_VSEL_POS (8U) +#define MAX32_GPIO_VSEL_MASK (0x01U << MAX32_GPIO_VSEL_POS) +#define MAX32_GPIO_VSEL_VDDIO (0U << MAX32_GPIO_VSEL_POS) +#define MAX32_GPIO_VSEL_VDDIOH (1U << MAX32_GPIO_VSEL_POS) + +/** GPIO Drive Strenght Select */ +#define MAX32_GPIO_DRV_STRENGTH_POS (9U) +#define MAX32_GPIO_DRV_STRENGTH_MASK (0x03U << MAX32_GPIO_DRV_STRENGTH_POS) +#define MAX32_GPIO_DRV_STRENGTH_0 (0U << MAX32_GPIO_DRV_STRENGTH_POS) +#define MAX32_GPIO_DRV_STRENGTH_1 (1U << MAX32_GPIO_DRV_STRENGTH_POS) +#define MAX32_GPIO_DRV_STRENGTH_2 (2U << MAX32_GPIO_DRV_STRENGTH_POS) +#define MAX32_GPIO_DRV_STRENGTH_3 (3U << MAX32_GPIO_DRV_STRENGTH_POS) + +/** GPIO bias weak pull up selection, to VDDIO (1MOhm) */ +#define MAX32_GPIO_WEAK_PULL_UP_POS (10U) +#define MAX32_GPIO_WEAK_PULL_UP (1U << MAX32_GPIO_WEAK_PULL_UP_POS) +/** GPIO bias weak pull down selection, to VDDIOH (1MOhm) */ +#define MAX32_GPIO_WEAK_PULL_DOWN_POS (11U) +#define MAX32_GPIO_WEAK_PULL_DOWN (1U << MAX32_GPIO_WEAK_PULL_DOWN_POS) + +/** @} */ + +/** @} */ + +#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_GPIO_ADI_MAX32_GPIO_H_ */ From c121f405fe553ee20331d32afcef4c2a3dc73671 Mon Sep 17 00:00:00 2001 From: Sadik Ozer Date: Wed, 15 May 2024 13:37:10 +0300 Subject: [PATCH 1295/2849] tests: drivers: gpio: Enable gpio driver tests for max32690evkit board Enable gpio driver test for max32690evkit Signed-off-by: Sadik Ozer --- .../boards/max32690evkit_max32690_m4.overlay | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 tests/drivers/gpio/gpio_basic_api/boards/max32690evkit_max32690_m4.overlay diff --git a/tests/drivers/gpio/gpio_basic_api/boards/max32690evkit_max32690_m4.overlay b/tests/drivers/gpio/gpio_basic_api/boards/max32690evkit_max32690_m4.overlay new file mode 100644 index 0000000000000..05dad16b30fb8 --- /dev/null +++ b/tests/drivers/gpio/gpio_basic_api/boards/max32690evkit_max32690_m4.overlay @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2023-2024 Analog Devices, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + resources { + compatible = "test-gpio-basic-api"; + out-gpios = <&gpio2 7 0>; + in-gpios = <&gpio2 8 0>; + }; +}; From 0480b2625b4492a2d58b5610c442aaa9cfe922c0 Mon Sep 17 00:00:00 2001 From: Sadik Ozer Date: Fri, 13 Oct 2023 16:19:45 +0300 Subject: [PATCH 1296/2849] drivers: Add MAX32690 uart driver UART driver for MAX32690 Co-authored-by: Okan Sahin Co-authored-by: Tahsin Mutlugun Signed-off-by: Sadik Ozer --- drivers/serial/CMakeLists.txt | 1 + drivers/serial/Kconfig | 2 + drivers/serial/Kconfig.max32 | 16 + drivers/serial/uart_max32.c | 453 ++++++++++++++++++++++++ dts/bindings/serial/adi,max32-uart.yaml | 36 ++ 5 files changed, 508 insertions(+) create mode 100644 drivers/serial/Kconfig.max32 create mode 100644 drivers/serial/uart_max32.c create mode 100644 dts/bindings/serial/adi,max32-uart.yaml diff --git a/drivers/serial/CMakeLists.txt b/drivers/serial/CMakeLists.txt index ef0133a5ca105..dc3e4208ff4de 100644 --- a/drivers/serial/CMakeLists.txt +++ b/drivers/serial/CMakeLists.txt @@ -69,6 +69,7 @@ zephyr_library_sources_ifdef(CONFIG_UART_EMUL uart_emul.c) zephyr_library_sources_ifdef(CONFIG_UART_NUMAKER uart_numaker.c) zephyr_library_sources_ifdef(CONFIG_UART_EFINIX_SAPPIHIRE uart_efinix_sapphire.c) zephyr_library_sources_ifdef(CONFIG_UART_SEDI uart_sedi.c) +zephyr_library_sources_ifdef(CONFIG_UART_MAX32 uart_max32.c) zephyr_library_sources_ifdef(CONFIG_UART_BCM2711_MU uart_bcm2711.c) zephyr_library_sources_ifdef(CONFIG_UART_INTEL_LW uart_intel_lw.c) zephyr_library_sources_ifdef(CONFIG_UART_RENESAS_RA uart_renesas_ra.c) diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index 91b79ce6dfad4..856b3f2eb89f6 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -266,6 +266,8 @@ source "drivers/serial/Kconfig.efinix_sapphire" source "drivers/serial/Kconfig.sedi" +source "drivers/serial/Kconfig.max32" + source "drivers/serial/Kconfig.bcm2711" source "drivers/serial/Kconfig.intel_lw" diff --git a/drivers/serial/Kconfig.max32 b/drivers/serial/Kconfig.max32 new file mode 100644 index 0000000000000..99b5c7b45ef50 --- /dev/null +++ b/drivers/serial/Kconfig.max32 @@ -0,0 +1,16 @@ +# MAX32 UART configuration + +# Copyright (c) 2023-2024 Analog Devices, Inc. +# SPDX-License-Identifier: Apache-2.0 + +config UART_MAX32 + bool "MAX32 MCU serial driver" + default y + depends on DT_HAS_ADI_MAX32_UART_ENABLED + select SERIAL_HAS_DRIVER + select SERIAL_SUPPORT_INTERRUPT + select PINCTRL + help + This option enables the UART driver for MAX32 family of + processors. + Say y if you wish to use serial port on MAX32 MCU. diff --git a/drivers/serial/uart_max32.c b/drivers/serial/uart_max32.c new file mode 100644 index 0000000000000..bd34f9e131f38 --- /dev/null +++ b/drivers/serial/uart_max32.c @@ -0,0 +1,453 @@ +/* + * Copyright (c) 2023-2024 Analog Devices, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include + +#include + +#define DT_DRV_COMPAT adi_max32_uart + +LOG_MODULE_REGISTER(uart_max32, CONFIG_UART_LOG_LEVEL); + +struct max32_uart_config { + mxc_uart_regs_t *regs; + const struct pinctrl_dev_config *pctrl; + const struct device *clock; + struct max32_perclk perclk; + struct uart_config uart_conf; +#ifdef CONFIG_UART_INTERRUPT_DRIVEN + uart_irq_config_func_t irq_config_func; +#endif /* CONFIG_UART_INTERRUPT_DRIVEN */ +}; + +struct max32_uart_data { +#ifdef CONFIG_UART_INTERRUPT_DRIVEN + uart_irq_callback_user_data_t cb; /* Interrupt callback */ + void *cb_data; /* Interrupt callback arg */ + uint32_t flags; /* Cached interrupt flags */ + uint32_t status; /* Cached status flags */ +#endif + struct uart_config conf; /* baudrate, stopbits, ... */ +}; + +#ifdef CONFIG_UART_INTERRUPT_DRIVEN +static void uart_max32_isr(const struct device *dev); +#endif + +static void api_poll_out(const struct device *dev, unsigned char c) +{ + const struct max32_uart_config *cfg = dev->config; + + MXC_UART_WriteCharacter(cfg->regs, c); +} + +static int api_poll_in(const struct device *dev, unsigned char *c) +{ + int val; + const struct max32_uart_config *cfg = dev->config; + + val = MXC_UART_ReadCharacterRaw(cfg->regs); + if (val >= 0) { + *c = (unsigned char)val; + } else { + return -1; + } + + return 0; +} + +static int api_err_check(const struct device *dev) +{ + int err = 0; + uint32_t flags; + const struct max32_uart_config *cfg = dev->config; + + flags = MXC_UART_GetFlags(cfg->regs); + + if (flags & ADI_MAX32_UART_ERROR_FRAMING) { + err |= UART_ERROR_FRAMING; + } + + if (flags & ADI_MAX32_UART_ERROR_PARITY) { + err |= UART_ERROR_PARITY; + } + + if (flags & ADI_MAX32_UART_ERROR_OVERRUN) { + err |= UART_ERROR_OVERRUN; + } + + return err; +} + +#ifdef CONFIG_UART_USE_RUNTIME_CONFIGURE + +static int api_configure(const struct device *dev, const struct uart_config *uart_cfg) +{ + int err; + const struct max32_uart_config *const cfg = dev->config; + mxc_uart_regs_t *regs = cfg->regs; + struct max32_uart_data *data = dev->data; + + /* + * Set parity + */ + if (data->conf.parity != uart_cfg->parity) { + mxc_uart_parity_t mxc_parity; + + switch (uart_cfg->parity) { + case UART_CFG_PARITY_NONE: + mxc_parity = ADI_MAX32_UART_CFG_PARITY_NONE; + break; + case UART_CFG_PARITY_ODD: + mxc_parity = ADI_MAX32_UART_CFG_PARITY_ODD; + break; + case UART_CFG_PARITY_EVEN: + mxc_parity = ADI_MAX32_UART_CFG_PARITY_EVEN; + break; + case UART_CFG_PARITY_MARK: +#if defined(ADI_MAX32_UART_CFG_PARITY_MARK) + mxc_parity = ADI_MAX32_UART_CFG_PARITY_MARK; + break; +#else + return -ENOTSUP; +#endif + case UART_CFG_PARITY_SPACE: +#if defined(ADI_MAX32_UART_CFG_PARITY_SPACE) + mxc_parity = ADI_MAX32_UART_CFG_PARITY_SPACE; + break; +#else + return -ENOTSUP; +#endif + default: + return -EINVAL; + } + + err = MXC_UART_SetParity(regs, mxc_parity); + if (err < 0) { + return -ENOTSUP; + } + /* incase of success keep configuration */ + data->conf.parity = uart_cfg->parity; + } + + /* + * Set stop bit + */ + if (data->conf.stop_bits != uart_cfg->stop_bits) { + if (uart_cfg->stop_bits == UART_CFG_STOP_BITS_1) { + err = MXC_UART_SetStopBits(regs, MXC_UART_STOP_1); + } else if (uart_cfg->stop_bits == UART_CFG_STOP_BITS_2) { + err = MXC_UART_SetStopBits(regs, MXC_UART_STOP_2); + } else { + return -ENOTSUP; + } + if (err < 0) { + return -ENOTSUP; + } + /* incase of success keep configuration */ + data->conf.stop_bits = uart_cfg->stop_bits; + } + + /* + * Set data bit + * Valid data for MAX32 is 5-6-7-8 + * Valid data for Zepyhr is 0-1-2-3 + * Added +5 to index match. + */ + if (data->conf.data_bits != uart_cfg->data_bits) { + err = MXC_UART_SetDataSize(regs, (5 + uart_cfg->data_bits)); + if (err < 0) { + return -ENOTSUP; + } + /* incase of success keep configuration */ + data->conf.data_bits = uart_cfg->data_bits; + } + + /* + * Set flow control + * Flow control not implemented yet so that only support no flow mode + */ + if (data->conf.flow_ctrl != uart_cfg->flow_ctrl) { + if (uart_cfg->flow_ctrl != UART_CFG_FLOW_CTRL_NONE) { + return -ENOTSUP; + } + data->conf.flow_ctrl = uart_cfg->flow_ctrl; + } + + /* + * Set baudrate + */ + if (data->conf.baudrate != uart_cfg->baudrate) { + err = Wrap_MXC_UART_SetFrequency(regs, uart_cfg->baudrate, cfg->perclk.clk_src); + if (err < 0) { + return -ENOTSUP; + } + /* In case of success keep configuration */ + data->conf.baudrate = uart_cfg->baudrate; + } + return 0; +} + +static int api_config_get(const struct device *dev, struct uart_config *uart_cfg) +{ + struct max32_uart_data *data = dev->data; + + /* copy configs from global setting */ + *uart_cfg = data->conf; + + return 0; +} + +#endif /* CONFIG_UART_USE_RUNTIME_CONFIGURE */ + +static int uart_max32_init(const struct device *dev) +{ + int ret; + const struct max32_uart_config *const cfg = dev->config; + mxc_uart_regs_t *regs = cfg->regs; + + if (!device_is_ready(cfg->clock)) { + LOG_ERR("Clock control device not ready"); + return -ENODEV; + } + + ret = MXC_UART_Shutdown(regs); + if (ret) { + return ret; + } + + ret = clock_control_on(cfg->clock, (clock_control_subsys_t)&cfg->perclk); + if (ret != 0) { + LOG_ERR("Cannot enable UART clock"); + return ret; + } + + ret = pinctrl_apply_state(cfg->pctrl, PINCTRL_STATE_DEFAULT); + if (ret) { + return ret; + } + + ret = api_configure(dev, &cfg->uart_conf); + if (ret) { + return ret; + } + + ret = Wrap_MXC_UART_Init(regs); + if (ret) { + return ret; + } + +#ifdef CONFIG_UART_INTERRUPT_DRIVEN + /* Clear any pending UART RX/TX interrupts */ + MXC_UART_ClearFlags(regs, (ADI_MAX32_UART_INT_RX | ADI_MAX32_UART_INT_TX)); + cfg->irq_config_func(dev); +#endif + + return ret; +} + +#ifdef CONFIG_UART_INTERRUPT_DRIVEN + +static int api_fifo_fill(const struct device *dev, const uint8_t *tx_data, int size) +{ + unsigned int num_tx = 0; + const struct max32_uart_config *cfg = dev->config; + + num_tx = MXC_UART_WriteTXFIFO(cfg->regs, (unsigned char *)tx_data, size); + + return (int)num_tx; +} + +static int api_fifo_read(const struct device *dev, uint8_t *rx_data, const int size) +{ + unsigned int num_rx = 0; + const struct max32_uart_config *cfg = dev->config; + + num_rx = MXC_UART_ReadRXFIFO(cfg->regs, (unsigned char *)rx_data, size); + if (num_rx == 0) { + MXC_UART_ClearFlags(cfg->regs, ADI_MAX32_UART_INT_RX); + } + + return num_rx; +} + +static void api_irq_tx_enable(const struct device *dev) +{ + const struct max32_uart_config *cfg = dev->config; + unsigned int key; + + MXC_UART_EnableInt(cfg->regs, ADI_MAX32_UART_INT_TX | ADI_MAX32_UART_INT_TX_OEM); + + key = irq_lock(); + uart_max32_isr(dev); + irq_unlock(key); +} + +static void api_irq_tx_disable(const struct device *dev) +{ + const struct max32_uart_config *cfg = dev->config; + + MXC_UART_DisableInt(cfg->regs, ADI_MAX32_UART_INT_TX | ADI_MAX32_UART_INT_TX_OEM); +} + +static int api_irq_tx_ready(const struct device *dev) +{ + struct max32_uart_data *const data = dev->data; + + return ((data->flags & (ADI_MAX32_UART_INT_TX | ADI_MAX32_UART_INT_TX_OEM)) || + !(data->status & MXC_F_UART_STATUS_TX_FULL)); +} + +static void api_irq_rx_enable(const struct device *dev) +{ + const struct max32_uart_config *cfg = dev->config; + + MXC_UART_EnableInt(cfg->regs, ADI_MAX32_UART_INT_RX); +} + +static void api_irq_rx_disable(const struct device *dev) +{ + const struct max32_uart_config *cfg = dev->config; + + MXC_UART_DisableInt(cfg->regs, ADI_MAX32_UART_INT_RX); +} + +static int api_irq_tx_complete(const struct device *dev) +{ + const struct max32_uart_config *cfg = dev->config; + + if (MXC_UART_GetActive(cfg->regs) == E_BUSY) { + return 0; + } else { + return 1; /* transmission completed */ + } +} + +static int api_irq_rx_ready(const struct device *dev) +{ + struct max32_uart_data *const data = dev->data; + + return (data->flags & ADI_MAX32_UART_INT_RX); +} + +static void api_irq_err_enable(const struct device *dev) +{ + const struct max32_uart_config *cfg = dev->config; + + MXC_UART_EnableInt(cfg->regs, ADI_MAX32_UART_ERROR_INTERRUPTS); +} + +static void api_irq_err_disable(const struct device *dev) +{ + const struct max32_uart_config *cfg = dev->config; + + MXC_UART_DisableInt(cfg->regs, ADI_MAX32_UART_ERROR_INTERRUPTS); +} + +static int api_irq_is_pending(const struct device *dev) +{ + struct max32_uart_data *const data = dev->data; + + return (data->flags & (ADI_MAX32_UART_INT_RX | ADI_MAX32_UART_INT_TX)); +} + +static int api_irq_update(const struct device *dev) +{ + struct max32_uart_data *const data = dev->data; + const struct max32_uart_config *const cfg = dev->config; + + data->flags = MXC_UART_GetFlags(cfg->regs); + data->status = MXC_UART_GetStatus(cfg->regs); + + MXC_UART_ClearFlags(cfg->regs, data->flags); + + return 1; +} + +static void api_irq_callback_set(const struct device *dev, uart_irq_callback_user_data_t cb, + void *cb_data) +{ + struct max32_uart_data *const data = dev->data; + + data->cb = cb; + data->cb_data = cb_data; +} + +static void uart_max32_isr(const struct device *dev) +{ + struct max32_uart_data *data = dev->data; + + if (data->cb) { + data->cb(dev, data->cb_data); + } +} + +#endif /* CONFIG_UART_INTERRUPT_DRIVEN */ + +static const struct uart_driver_api uart_max32_driver_api = { + .poll_in = api_poll_in, + .poll_out = api_poll_out, + .err_check = api_err_check, +#ifdef CONFIG_UART_USE_RUNTIME_CONFIGURE + .configure = api_configure, + .config_get = api_config_get, +#endif /* CONFIG_UART_USE_RUNTIME_CONFIGURE */ +#ifdef CONFIG_UART_INTERRUPT_DRIVEN + .fifo_fill = api_fifo_fill, + .fifo_read = api_fifo_read, + .irq_tx_enable = api_irq_tx_enable, + .irq_tx_disable = api_irq_tx_disable, + .irq_tx_ready = api_irq_tx_ready, + .irq_rx_enable = api_irq_rx_enable, + .irq_rx_disable = api_irq_rx_disable, + .irq_tx_complete = api_irq_tx_complete, + .irq_rx_ready = api_irq_rx_ready, + .irq_err_enable = api_irq_err_enable, + .irq_err_disable = api_irq_err_disable, + .irq_is_pending = api_irq_is_pending, + .irq_update = api_irq_update, + .irq_callback_set = api_irq_callback_set, +#endif /* CONFIG_UART_INTERRUPT_DRIVEN */ +}; + +#define MAX32_UART_INIT(_num) \ + PINCTRL_DT_INST_DEFINE(_num); \ + IF_ENABLED(CONFIG_UART_INTERRUPT_DRIVEN, \ + (static void uart_max32_irq_init_##_num(const struct device *dev) \ + { \ + IF_ENABLED( \ + CONFIG_UART_INTERRUPT_DRIVEN, \ + (IRQ_CONNECT(DT_INST_IRQN(_num), DT_INST_IRQ(_num, priority), \ + uart_max32_isr, DEVICE_DT_INST_GET(_num), 0); \ + irq_enable(DT_INST_IRQN(_num)))); \ + })); \ + static const struct max32_uart_config max32_uart_config_##_num = { \ + .regs = (mxc_uart_regs_t *)DT_INST_REG_ADDR(_num), \ + .pctrl = PINCTRL_DT_INST_DEV_CONFIG_GET(_num), \ + .clock = DEVICE_DT_GET(DT_INST_CLOCKS_CTLR(_num)), \ + .perclk.bus = DT_INST_CLOCKS_CELL(_num, offset), \ + .perclk.bit = DT_INST_CLOCKS_CELL(_num, bit), \ + .perclk.clk_src = \ + DT_INST_PROP_OR(_num, clock_source, ADI_MAX32_PRPH_CLK_SRC_PCLK), \ + .uart_conf.baudrate = DT_INST_PROP(_num, current_speed), \ + .uart_conf.parity = DT_INST_ENUM_IDX_OR(_num, parity, UART_CFG_PARITY_NONE), \ + .uart_conf.data_bits = DT_INST_ENUM_IDX(_num, data_bits), \ + .uart_conf.stop_bits = DT_INST_ENUM_IDX_OR(_num, stop_bits, UART_CFG_STOP_BITS_1), \ + .uart_conf.flow_ctrl = \ + DT_INST_PROP_OR(_num, hw_flow_control, UART_CFG_FLOW_CTRL_NONE), \ + IF_ENABLED(CONFIG_UART_INTERRUPT_DRIVEN, \ + (.irq_config_func = uart_max32_irq_init_##_num,))}; \ + static struct max32_uart_data max32_uart_data##_num = { \ + IF_ENABLED(CONFIG_UART_INTERRUPT_DRIVEN, (.cb = NULL,))}; \ + DEVICE_DT_INST_DEFINE(_num, uart_max32_init, NULL, &max32_uart_data##_num, \ + &max32_uart_config_##_num, PRE_KERNEL_1, \ + CONFIG_SERIAL_INIT_PRIORITY, (void *)&uart_max32_driver_api); + +DT_INST_FOREACH_STATUS_OKAY(MAX32_UART_INIT) diff --git a/dts/bindings/serial/adi,max32-uart.yaml b/dts/bindings/serial/adi,max32-uart.yaml new file mode 100644 index 0000000000000..c79543cf6b88e --- /dev/null +++ b/dts/bindings/serial/adi,max32-uart.yaml @@ -0,0 +1,36 @@ +# Copyright (c) 2023-2024 Analog Devices, Inc. +# SPDX-License-Identifier: Apache-2.0 + +description: MAX32 UART + +include: [uart-controller.yaml, pinctrl-device.yaml] + +compatible: "adi,max32-uart" + +properties: + reg: + required: true + + clocks: + required: true + + interrupts: + required: true + + pinctrl: + type: phandles + + clock-source: + type: int + enum: [0, 1, 2, 3, 4, 5] + description: | + Clock source to be used by the UART peripheral. The following options + are available: + - 0: "ADI_MAX32_PRPH_CLK_SRC_PCLK" Peripheral clock + - 1: "ADI_MAX32_PRPH_CLK_SRC_EXTCLK" External Clock + - 2: "ADI_MAX32_PRPH_CLK_SRC_IBRO" Internal Baud Rate Oscillator + - 3: "ADI_MAX32_PRPH_CLK_SRC_ERFO" External Radio Frequency Oscillator + - 4: "ADI_MAX32_PRPH_CLK_SRC_ERTCO" External Real-Time Clock Oscillator + - 5: "ADI_MAX32_PRPH_CLK_SRC_INRO" Internal Ring Oscillator + The target device might not support all option please take a look on + target device user guide From d33d5b3a7949e57e6bddb25f5fcf1f40a68e45d0 Mon Sep 17 00:00:00 2001 From: Sadik Ozer Date: Fri, 13 Oct 2023 16:23:57 +0300 Subject: [PATCH 1297/2849] soc: Add the MAX32690 SoC Added ADI MAX series soc, first partnumber is MAX32690 The family structure will be ADI_MAX MAX32xxx MAX32655 MAX32655EVKIT MAX32655FTHR MAX32666 MAX32666FTHR MAX32666FTHR2 MAX32690 MAX32690EVKIT MAX78xxx MAX78000 MAX78002 ... When MAX32 MCUs goes to sleep mode debugger could not access it and flashing fails, ARM_ON_ENTER_CPU_IDLE_HOOK prevent the CPU from actually entering sleep by skipping the WFE/WFI instruction. Due to ARM_ON_ENTER_CPU_IDLE_HOOK is not configurable at the user space, added a config wrapper as MAX32_ON_ENTER_CPU_IDLE_HOOK. If MAX32_ON_ENTER_CPU_IDLE_HOOK config being defined (default y) devicei will not goes to sleep mode in idle state. To disable it add below line in your configuration file CONFIG_MAX32_ON_ENTER_CPU_IDLE_HOOK=n MAX32690 has two core Cortex-M4 and Risc-V this commit adds M4 core support. Co-authored-by: Jason Murphy Signed-off-by: Sadik Ozer --- dts/arm/adi/max32/max32690-pinctrl.dtsi | 771 +++++++++++++++++++++++ dts/arm/adi/max32/max32690.dtsi | 123 ++++ dts/arm/adi/max32/max32xxx.dtsi | 162 +++++ soc/adi/max32/CMakeLists.txt | 8 + soc/adi/max32/Kconfig | 29 + soc/adi/max32/Kconfig.defconfig | 13 + soc/adi/max32/Kconfig.defconfig.max32690 | 14 + soc/adi/max32/Kconfig.soc | 21 + soc/adi/max32/soc.c | 41 ++ soc/adi/max32/soc.h | 17 + soc/adi/max32/soc.yml | 9 + 11 files changed, 1208 insertions(+) create mode 100644 dts/arm/adi/max32/max32690-pinctrl.dtsi create mode 100644 dts/arm/adi/max32/max32690.dtsi create mode 100644 dts/arm/adi/max32/max32xxx.dtsi create mode 100644 soc/adi/max32/CMakeLists.txt create mode 100644 soc/adi/max32/Kconfig create mode 100644 soc/adi/max32/Kconfig.defconfig create mode 100644 soc/adi/max32/Kconfig.defconfig.max32690 create mode 100644 soc/adi/max32/Kconfig.soc create mode 100644 soc/adi/max32/soc.c create mode 100644 soc/adi/max32/soc.h create mode 100644 soc/adi/max32/soc.yml diff --git a/dts/arm/adi/max32/max32690-pinctrl.dtsi b/dts/arm/adi/max32/max32690-pinctrl.dtsi new file mode 100644 index 0000000000000..18fab74ba2fcb --- /dev/null +++ b/dts/arm/adi/max32/max32690-pinctrl.dtsi @@ -0,0 +1,771 @@ +/* + * Copyright (c) 2023-2024 Analog Devices, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +/ { + soc { + pinctrl: pin-controller@40008000 { + + /omit-if-no-ref/ spixr_sdio0_p0_1: spixr_sdio0_p0_1 { + pinmux = ; + }; + + /omit-if-no-ref/ spixf_sdio0_p0_1: spixf_sdio0_p0_1 { + pinmux = ; + }; + + /omit-if-no-ref/ uart2c_tx_p0_1: uart2c_tx_p0_1 { + pinmux = ; + }; + + /omit-if-no-ref/ spixr_sdio2_p0_2: spixr_sdio2_p0_2 { + pinmux = ; + }; + + /omit-if-no-ref/ spixf_sdio2_p0_2: spixf_sdio2_p0_2 { + pinmux = ; + }; + + /omit-if-no-ref/ uart2c_cts_p0_2: uart2c_cts_p0_2 { + pinmux = ; + }; + + /omit-if-no-ref/ spixr_sck_p0_3: spixr_sck_p0_3 { + pinmux = ; + }; + + /omit-if-no-ref/ spixf_sck_p0_3: spixf_sck_p0_3 { + pinmux = ; + }; + + /omit-if-no-ref/ uart2c_rts_p0_3: uart2c_rts_p0_3 { + pinmux = ; + }; + + /omit-if-no-ref/ spixr_sdio3_p0_4: spixr_sdio3_p0_4 { + pinmux = ; + }; + + /omit-if-no-ref/ spixf_sdio3_p0_4: spixf_sdio3_p0_4 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr0c_ioa_p0_4: tmr0c_ioa_p0_4 { + pinmux = ; + }; + + /omit-if-no-ref/ spixr_sdio1_p0_5: spixr_sdio1_p0_5 { + pinmux = ; + }; + + /omit-if-no-ref/ spixf_sdio1_p0_5: spixf_sdio1_p0_5 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr2c_iob_p0_5: tmr2c_iob_p0_5 { + pinmux = ; + }; + + /omit-if-no-ref/ spixr_ss0_p0_6: spixr_ss0_p0_6 { + pinmux = ; + }; + + /omit-if-no-ref/ spixf_ss0_p0_6: spixf_ss0_p0_6 { + pinmux = ; + }; + + /omit-if-no-ref/ uart2c_rx_p0_6: uart2c_rx_p0_6 { + pinmux = ; + }; + + /omit-if-no-ref/ owm_pe_p0_7: owm_pe_p0_7 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr1b_ioa_p0_7: tmr1b_ioa_p0_7 { + pinmux = ; + }; + + /omit-if-no-ref/ owm_io_p0_8: owm_io_p0_8 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr1b_iob_p0_8: tmr1b_iob_p0_8 { + pinmux = ; + }; + + /omit-if-no-ref/ adc_clk_ext_p0_9: adc_clk_ext_p0_9 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr0c_ioan_p0_9: tmr0c_ioan_p0_9 { + pinmux = ; + }; + + /omit-if-no-ref/ adc_trig_a_p0_10: adc_trig_a_p0_10 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr0c_iobn_p0_10: tmr0c_iobn_p0_10 { + pinmux = ; + }; + + /omit-if-no-ref/ i2c1a_sda_p0_11: i2c1a_sda_p0_11 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr1c_ioan_p0_11: tmr1c_ioan_p0_11 { + pinmux = ; + }; + + /omit-if-no-ref/ i2c1a_scl_p0_12: i2c1a_scl_p0_12 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr1c_iobn_p0_12: tmr1c_iobn_p0_12 { + pinmux = ; + }; + + /omit-if-no-ref/ spi3a_ss1_p0_13: spi3a_ss1_p0_13 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr0b_ioa_p0_13: tmr0b_ioa_p0_13 { + pinmux = ; + }; + + /omit-if-no-ref/ i2c2c_sda_p0_13: i2c2c_sda_p0_13 { + pinmux = ; + }; + + /omit-if-no-ref/ spi3a_ss2_p0_14: spi3a_ss2_p0_14 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr0b_iob_p0_14: tmr0b_iob_p0_14 { + pinmux = ; + }; + + /omit-if-no-ref/ i2c2c_scl_p0_14: i2c2c_scl_p0_14 { + pinmux = ; + }; + + /omit-if-no-ref/ spi3a_sdio3_p0_15: spi3a_sdio3_p0_15 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr1c_ioa_p0_15: tmr1c_ioa_p0_15 { + pinmux = ; + }; + + /omit-if-no-ref/ spi3a_sck_p0_16: spi3a_sck_p0_16 { + pinmux = ; + }; + + /omit-if-no-ref/ spi3a_sdio2_p0_17: spi3a_sdio2_p0_17 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr1c_iob_p0_17: tmr1c_iob_p0_17 { + pinmux = ; + }; + + /omit-if-no-ref/ spi3a_ss0_p0_19: spi3a_ss0_p0_19 { + pinmux = ; + }; + + /omit-if-no-ref/ rv_tck_p0_19: rv_tck_p0_19 { + pinmux = ; + }; + + /omit-if-no-ref/ spi3a_miso_p0_20: spi3a_miso_p0_20 { + pinmux = ; + }; + + /omit-if-no-ref/ rv_tms_p0_20: rv_tms_p0_20 { + pinmux = ; + }; + + /omit-if-no-ref/ spi3a_mosi_p0_21: spi3a_mosi_p0_21 { + pinmux = ; + }; + + /omit-if-no-ref/ rv_tdi_p0_21: rv_tdi_p0_21 { + pinmux = ; + }; + + /omit-if-no-ref/ spi0a_ss0_p0_22: spi0a_ss0_p0_22 { + pinmux = ; + }; + + /omit-if-no-ref/ rv_tdo_p0_22: rv_tdo_p0_22 { + pinmux = ; + }; + + /omit-if-no-ref/ pt15_p0_23: pt15_p0_23 { + pinmux = ; + }; + + /omit-if-no-ref/ i2s0b_clkext_p0_23: i2s0b_clkext_p0_23 { + pinmux = ; + }; + + /omit-if-no-ref/ rxev0_p0_24: rxev0_p0_24 { + pinmux = ; + }; + + /omit-if-no-ref/ i2s0b_sck_p0_24: i2s0b_sck_p0_24 { + pinmux = ; + }; + + /omit-if-no-ref/ txevo_p0_25: txevo_p0_25 { + pinmux = ; + }; + + /omit-if-no-ref/ i2s0b_sdi_p0_25: i2s0b_sdi_p0_25 { + pinmux = ; + }; + + /omit-if-no-ref/ i2s0b_sdo_p0_26: i2s0b_sdo_p0_26 { + pinmux = ; + }; + + /omit-if-no-ref/ erfo_clk_out_p0_27: erfo_clk_out_p0_27 { + pinmux = ; + }; + + /omit-if-no-ref/ i2s0b_ws_p0_27: i2s0b_ws_p0_27 { + pinmux = ; + }; + + /omit-if-no-ref/ i2c0a_sda_p0_30: i2c0a_sda_p0_30 { + pinmux = ; + }; + + /omit-if-no-ref/ i2c0a_scl_p0_31: i2c0a_scl_p0_31 { + pinmux = ; + }; + + /omit-if-no-ref/ spi4a_ss0_p1_0: spi4a_ss0_p1_0 { + pinmux = ; + }; + + /omit-if-no-ref/ adc_trig_b_p1_0: adc_trig_b_p1_0 { + pinmux = ; + }; + + /omit-if-no-ref/ spi4a_mosi_p1_1: spi4a_mosi_p1_1 { + pinmux = ; + }; + + /omit-if-no-ref/ spi4a_miso_p1_2: spi4a_miso_p1_2 { + pinmux = ; + }; + + /omit-if-no-ref/ spi4a_sck_p1_3: spi4a_sck_p1_3 { + pinmux = ; + }; + + /omit-if-no-ref/ spi4a_sdio2_p1_4: spi4a_sdio2_p1_4 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr2b_ioa_p1_4: tmr2b_ioa_p1_4 { + pinmux = ; + }; + + /omit-if-no-ref/ spi4a_sdio3_p1_5: spi4a_sdio3_p1_5 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr2b_iob_p1_5: tmr2b_iob_p1_5 { + pinmux = ; + }; + + /omit-if-no-ref/ spi4a_ss1_p1_6: spi4a_ss1_p1_6 { + pinmux = ; + }; + + /omit-if-no-ref/ pt0_p1_6: pt0_p1_6 { + pinmux = ; + }; + + /omit-if-no-ref/ uart2a_cts_p1_7: uart2a_cts_p1_7 { + pinmux = ; + }; + + /omit-if-no-ref/ pt1_p1_7: pt1_p1_7 { + pinmux = ; + }; + + /omit-if-no-ref/ i2c2c_sda_p1_7: i2c2c_sda_p1_7 { + pinmux = ; + }; + + /omit-if-no-ref/ uart2a_rts_p1_8: uart2a_rts_p1_8 { + pinmux = ; + }; + + /omit-if-no-ref/ pt2_p1_8: pt2_p1_8 { + pinmux = ; + }; + + /omit-if-no-ref/ i2c2c_scl_p1_8: i2c2c_scl_p1_8 { + pinmux = ; + }; + + /omit-if-no-ref/ uart2a_rx_p1_9: uart2a_rx_p1_9 { + pinmux = ; + }; + + /omit-if-no-ref/ pt3_p1_9: pt3_p1_9 { + pinmux = ; + }; + + /omit-if-no-ref/ uart2a_tx_p1_10: uart2a_tx_p1_10 { + pinmux = ; + }; + + /omit-if-no-ref/ pt4_p1_10: pt4_p1_10 { + pinmux = ; + }; + + /omit-if-no-ref/ spi4a_ss2_p1_11: spi4a_ss2_p1_11 { + pinmux = ; + }; + + /omit-if-no-ref/ hyp_cs0n_p1_11: hyp_cs0n_p1_11 { + pinmux = ; + }; + + /omit-if-no-ref/ pt5_p1_12: pt5_p1_12 { + pinmux = ; + }; + + /omit-if-no-ref/ hyp_d0_p1_12: hyp_d0_p1_12 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr3a_ioa_p1_13: tmr3a_ioa_p1_13 { + pinmux = ; + }; + + /omit-if-no-ref/ hyp_d4_p1_13: hyp_d4_p1_13 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr3a_iob_p1_14: tmr3a_iob_p1_14 { + pinmux = ; + }; + + /omit-if-no-ref/ hyp_rwds_p1_14: hyp_rwds_p1_14 { + pinmux = ; + }; + + /omit-if-no-ref/ hyp_d1_p1_15: hyp_d1_p1_15 { + pinmux = ; + }; + + /omit-if-no-ref/ hyp_d5_p1_16: hyp_d5_p1_16 { + pinmux = ; + }; + + /omit-if-no-ref/ pt9_p1_17: pt9_p1_17 { + pinmux = ; + }; + + /omit-if-no-ref/ hyp_cs1n_p1_17: hyp_cs1n_p1_17 { + pinmux = ; + }; + + /omit-if-no-ref/ pt6_p1_18: pt6_p1_18 { + pinmux = ; + }; + + /omit-if-no-ref/ hyp_d6_p1_18: hyp_d6_p1_18 { + pinmux = ; + }; + + /omit-if-no-ref/ pt7_p1_19: pt7_p1_19 { + pinmux = ; + }; + + /omit-if-no-ref/ hyp_d2_p1_19: hyp_d2_p1_19 { + pinmux = ; + }; + + /omit-if-no-ref/ hyp_d3_p1_20: hyp_d3_p1_20 { + pinmux = ; + }; + + /omit-if-no-ref/ pt8_p1_21: pt8_p1_21 { + pinmux = ; + }; + + /omit-if-no-ref/ hyp_d7_p1_21: hyp_d7_p1_21 { + pinmux = ; + }; + + /omit-if-no-ref/ spi1a_ss0_p1_23: spi1a_ss0_p1_23 { + pinmux = ; + }; + + /omit-if-no-ref/ spi1a_ss2_p1_24: spi1a_ss2_p1_24 { + pinmux = ; + }; + + /omit-if-no-ref/ can0b_rx_p1_24: can0b_rx_p1_24 { + pinmux = ; + }; + + /omit-if-no-ref/ spi1a_ss1_p1_25: spi1a_ss1_p1_25 { + pinmux = ; + }; + + /omit-if-no-ref/ can0b_tx_p1_25: can0b_tx_p1_25 { + pinmux = ; + }; + + /omit-if-no-ref/ spi1a_sck_p1_26: spi1a_sck_p1_26 { + pinmux = ; + }; + + /omit-if-no-ref/ spi2a_ss2_p1_27: spi2a_ss2_p1_27 { + pinmux = ; + }; + + /omit-if-no-ref/ spi1a_miso_p1_28: spi1a_miso_p1_28 { + pinmux = ; + }; + + /omit-if-no-ref/ can1b_rx_p1_28: can1b_rx_p1_28 { + pinmux = ; + }; + + /omit-if-no-ref/ spi1a_mosi_p1_29: spi1a_mosi_p1_29 { + pinmux = ; + }; + + /omit-if-no-ref/ can1b_tx_p1_29: can1b_tx_p1_29 { + pinmux = ; + }; + + /omit-if-no-ref/ owm_pe_p1_30: owm_pe_p1_30 { + pinmux = ; + }; + + /omit-if-no-ref/ spi1b_sdio2_p1_30: spi1b_sdio2_p1_30 { + pinmux = ; + }; + + /omit-if-no-ref/ owm_io_p1_31: owm_io_p1_31 { + pinmux = ; + }; + + /omit-if-no-ref/ spi1b_sdio3_p1_31: spi1b_sdio3_p1_31 { + pinmux = ; + }; + + /omit-if-no-ref/ spi2a_ss1_p2_1: spi2a_ss1_p2_1 { + pinmux = ; + }; + + /omit-if-no-ref/ pt10_p2_1: pt10_p2_1 { + pinmux = ; + }; + + /omit-if-no-ref/ spi2a_sck_p2_2: spi2a_sck_p2_2 { + pinmux = ; + }; + + /omit-if-no-ref/ spi2a_miso_p2_3: spi2a_miso_p2_3 { + pinmux = ; + }; + + /omit-if-no-ref/ spi2a_mosi_p2_4: spi2a_mosi_p2_4 { + pinmux = ; + }; + + /omit-if-no-ref/ spi2a_ss0_p2_5: spi2a_ss0_p2_5 { + pinmux = ; + }; + + /omit-if-no-ref/ pt11_p2_5: pt11_p2_5 { + pinmux = ; + }; + + /omit-if-no-ref/ spi2b_sdio2_p2_6: spi2b_sdio2_p2_6 { + pinmux = ; + }; + + /omit-if-no-ref/ i2c0a_sda_p2_7: i2c0a_sda_p2_7 { + pinmux = ; + }; + + /omit-if-no-ref/ spi2b_sdio3_p2_7: spi2b_sdio3_p2_7 { + pinmux = ; + }; + + /omit-if-no-ref/ i2c0a_scl_p2_8: i2c0a_scl_p2_8 { + pinmux = ; + }; + + /omit-if-no-ref/ uart0a_cts_p2_9: uart0a_cts_p2_9 { + pinmux = ; + }; + + /omit-if-no-ref/ pt12_p2_9: pt12_p2_9 { + pinmux = ; + }; + + /omit-if-no-ref/ uart0a_rts_p2_10: uart0a_rts_p2_10 { + pinmux = ; + }; + + /omit-if-no-ref/ pt14_p2_10: pt14_p2_10 { + pinmux = ; + }; + + /omit-if-no-ref/ uart0a_rx_p2_11: uart0a_rx_p2_11 { + pinmux = ; + }; + + /omit-if-no-ref/ pt13_p2_11: pt13_p2_11 { + pinmux = ; + }; + + /omit-if-no-ref/ uart0a_tx_p2_12: uart0a_tx_p2_12 { + pinmux = ; + }; + + /omit-if-no-ref/ pt15_p2_12: pt15_p2_12 { + pinmux = ; + }; + + /omit-if-no-ref/ uart1a_cts_p2_13: uart1a_cts_p2_13 { + pinmux = ; + }; + + /omit-if-no-ref/ uart1a_rx_p2_14: uart1a_rx_p2_14 { + pinmux = ; + }; + + /omit-if-no-ref/ uart1a_rts_p2_15: uart1a_rts_p2_15 { + pinmux = ; + }; + + /omit-if-no-ref/ adc_hw_trig_c_p2_15: adc_hw_trig_c_p2_15 { + pinmux = ; + }; + + /omit-if-no-ref/ uart1a_tx_p2_16: uart1a_tx_p2_16 { + pinmux = ; + }; + + /omit-if-no-ref/ i2c1a_sda_p2_17: i2c1a_sda_p2_17 { + pinmux = ; + }; + + /omit-if-no-ref/ ble_ant_ctrl1_p2_17: ble_ant_ctrl1_p2_17 { + pinmux = ; + }; + + /omit-if-no-ref/ i2c1a_scl_p2_18: i2c1a_scl_p2_18 { + pinmux = ; + }; + + /omit-if-no-ref/ ble_ant_ctrl0_p2_18: ble_ant_ctrl0_p2_18 { + pinmux = ; + }; + + /omit-if-no-ref/ pt5_p2_20: pt5_p2_20 { + pinmux = ; + }; + + /omit-if-no-ref/ ble_ant_ctrl2_p2_20: ble_ant_ctrl2_p2_20 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr2c_ioa_p2_20: tmr2c_ioa_p2_20 { + pinmux = ; + }; + + /omit-if-no-ref/ pt7_p2_21: pt7_p2_21 { + pinmux = ; + }; + + /omit-if-no-ref/ ble_ant_ctrl3_p2_21: ble_ant_ctrl3_p2_21 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr2c_iob_p2_21: tmr2c_iob_p2_21 { + pinmux = ; + }; + + /omit-if-no-ref/ pt8_p2_22: pt8_p2_22 { + pinmux = ; + }; + + /omit-if-no-ref/ can0b_rx_p2_22: can0b_rx_p2_22 { + pinmux = ; + }; + + /omit-if-no-ref/ pt6_p2_23: pt6_p2_23 { + pinmux = ; + }; + + /omit-if-no-ref/ can0b_tx_p2_23: can0b_tx_p2_23 { + pinmux = ; + }; + + /omit-if-no-ref/ pt10_p2_24: pt10_p2_24 { + pinmux = ; + }; + + /omit-if-no-ref/ can1b_rx_p2_24: can1b_rx_p2_24 { + pinmux = ; + }; + + /omit-if-no-ref/ pt11_p2_25: pt11_p2_25 { + pinmux = ; + }; + + /omit-if-no-ref/ can1b_tx_p2_25: can1b_tx_p2_25 { + pinmux = ; + }; + + /omit-if-no-ref/ pt12_p2_26: pt12_p2_26 { + pinmux = ; + }; + + /omit-if-no-ref/ spi0b_ss1_p2_26: spi0b_ss1_p2_26 { + pinmux = ; + }; + + /omit-if-no-ref/ i2s0c_ws_p2_26: i2s0c_ws_p2_26 { + pinmux = ; + }; + + /omit-if-no-ref/ pt13_p2_27: pt13_p2_27 { + pinmux = ; + }; + + /omit-if-no-ref/ spi0b_miso_p2_27: spi0b_miso_p2_27 { + pinmux = ; + }; + + /omit-if-no-ref/ i2s0c_sdi_p2_27: i2s0c_sdi_p2_27 { + pinmux = ; + }; + + /omit-if-no-ref/ pt14_p2_28: pt14_p2_28 { + pinmux = ; + }; + + /omit-if-no-ref/ spi0b_mosi_p2_28: spi0b_mosi_p2_28 { + pinmux = ; + }; + + /omit-if-no-ref/ i2s0c_sdo_p2_28: i2s0c_sdo_p2_28 { + pinmux = ; + }; + + /omit-if-no-ref/ pt0_p2_29: pt0_p2_29 { + pinmux = ; + }; + + /omit-if-no-ref/ spi0b_sck_p2_29: spi0b_sck_p2_29 { + pinmux = ; + }; + + /omit-if-no-ref/ i2s0c_sck_p2_29: i2s0c_sck_p2_29 { + pinmux = ; + }; + + /omit-if-no-ref/ pt1_p2_30: pt1_p2_30 { + pinmux = ; + }; + + /omit-if-no-ref/ spi0b_sdio2_p2_30: spi0b_sdio2_p2_30 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr3c_ioa_p2_30: tmr3c_ioa_p2_30 { + pinmux = ; + }; + + /omit-if-no-ref/ pt2_p2_31: pt2_p2_31 { + pinmux = ; + }; + + /omit-if-no-ref/ spi0b_sdio3_p2_31: spi0b_sdio3_p2_31 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr3c_iob_p2_31: tmr3c_iob_p2_31 { + pinmux = ; + }; + + /omit-if-no-ref/ ain0_p3_0: ain0_p3_0 { + pinmux = ; + }; + + /omit-if-no-ref/ lpuart0b_rx_p3_0: lpuart0b_rx_p3_0 { + pinmux = ; + }; + + /omit-if-no-ref/ ain1_p3_1: ain1_p3_1 { + pinmux = ; + }; + + /omit-if-no-ref/ lpuart0b_tx_p3_1: lpuart0b_tx_p3_1 { + pinmux = ; + }; + + /omit-if-no-ref/ ain2_p3_2: ain2_p3_2 { + pinmux = ; + }; + + /omit-if-no-ref/ lpuart0b_cts_p3_2: lpuart0b_cts_p3_2 { + pinmux = ; + }; + + /omit-if-no-ref/ ain3_p3_3: ain3_p3_3 { + pinmux = ; + }; + + /omit-if-no-ref/ lpuart0b_rts_p3_3: lpuart0b_rts_p3_3 { + pinmux = ; + }; + + /omit-if-no-ref/ ain4_p3_4: ain4_p3_4 { + pinmux = ; + }; + + /omit-if-no-ref/ lptmr0b_ioa_p3_4: lptmr0b_ioa_p3_4 { + pinmux = ; + }; + + /omit-if-no-ref/ ain5_p3_5: ain5_p3_5 { + pinmux = ; + }; + + /omit-if-no-ref/ ain6_p3_6: ain6_p3_6 { + pinmux = ; + }; + + /omit-if-no-ref/ ain7_p3_7: ain7_p3_7 { + pinmux = ; + }; + + /omit-if-no-ref/ lptmr1b_ioa_p3_7: lptmr1b_ioa_p3_7 { + pinmux = ; + }; + + }; + }; +}; diff --git a/dts/arm/adi/max32/max32690.dtsi b/dts/arm/adi/max32/max32690.dtsi new file mode 100644 index 0000000000000..2bfef0e4be3cd --- /dev/null +++ b/dts/arm/adi/max32/max32690.dtsi @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2023-2024 Analog Devices, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +&clk_ipo { + clock-frequency = ; +}; + +&sram0 { + reg = <0x20000000 DT_SIZE_K(128)>; +}; + +&flash0 { + reg = <0x10000000 DT_SIZE_M(3)>; + erase-block-size = <16384>; +}; + +&gcr { + /delete-property/ sysclk-prescaler; +}; + +&pinctrl { + reg = <0x40008000 0x3220>; + + gpio2: gpio@4000a000 { + reg = <0x4000a000 0x1000>; + compatible = "adi,max32-gpio"; + gpio-controller; + #gpio-cells = <2>; + interrupts = <26 0>; + clocks = <&gcr ADI_MAX32_CLOCK_BUS0 2>; + status = "disabled"; + }; + + gpio3: gpio@40080400 { + reg = <0x40080400 0x200>; + compatible = "adi,max32-gpio"; + gpio-controller; + #gpio-cells = <2>; + interrupts = <58 0>; + clocks = <&gcr ADI_MAX32_CLOCK_BUS2 0>; + status = "disabled"; + }; + + gpio4: gpio@4000c000 { + reg = <0x4000c000 0x20>; + compatible = "adi,max32-gpio"; + gpio-controller; + #gpio-cells = <2>; + interrupts = <54 0>; + status = "disabled"; + }; +}; + +/* MAX32690 extra peripherals. */ +/ { + soc { + sram1: memory@20020000 { + compatible = "mmio-sram"; + reg = <0x20020000 DT_SIZE_K(128)>; + }; + + sram2: memory@20040000 { + compatible = "mmio-sram"; + reg = <0x20040000 DT_SIZE_K(128)>; + }; + + sram3: memory@20060000 { + compatible = "mmio-sram"; + reg = <0x20060000 DT_SIZE_K(128)>; + }; + + sram4: memory@20080000 { + compatible = "mmio-sram"; + reg = <0x20080000 DT_SIZE_K(128)>; + }; + + sram5: memory@200a0000 { + compatible = "mmio-sram"; + reg = <0x200a0000 DT_SIZE_K(128)>; + }; + + sram6: memory@200c0000 { + compatible = "mmio-sram"; + reg = <0x200c0000 DT_SIZE_K(64)>; + }; + + sram7: memory@200d0000 { + compatible = "mmio-sram"; + reg = <0x200d0000 DT_SIZE_K(64)>; + }; + + flc1: flash_controller@40029400 { + compatible = "adi,max32-flash-controller"; + reg = <0x40029400 0x400>; + + #address-cells = <1>; + #size-cells = <1>; + status = "okay"; + + flash1: flash@10080000 { + compatible = "soc-nv-flash"; + reg = <0x10080000 DT_SIZE_K(256)>; + write-block-size = <16>; + erase-block-size = <16384>; + }; + }; + + uart3: serial@40081400 { + compatible = "adi,max32-uart"; + reg = <0x40081400 0x400>; + clocks = <&gcr ADI_MAX32_CLOCK_BUS2 4>; + clock-source = ; + interrupts = <88 0>; + status = "disabled"; + }; + }; +}; diff --git a/dts/arm/adi/max32/max32xxx.dtsi b/dts/arm/adi/max32/max32xxx.dtsi new file mode 100644 index 0000000000000..64db703296029 --- /dev/null +++ b/dts/arm/adi/max32/max32xxx.dtsi @@ -0,0 +1,162 @@ +/* + * Copyright (c) 2023-2024 Analog Devices, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +#include + +/ { + chosen { + zephyr,flash-controller = &flc0; + }; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu0: cpu@0 { + device_type = "cpu"; + compatible = "arm,cortex-m4f"; + reg = <0>; + }; + }; + + clocks { + clk_ipo: clk_ipo { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = ; + status = "disabled"; + }; + + clk_iso: clk_iso { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = ; + status = "disabled"; + }; + + clk_inro: clk_inro { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = ; + status = "disabled"; + }; + + clk_ibro: clk_ibro { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <7372800>; + status = "disabled"; + }; + + clk_ertco: clk_ertco { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <32768>; + status = "disabled"; + }; + + clk_erfo: clk_erfo { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = ; + status = "disabled"; + }; + }; + + soc { + sram0: memory@20000000 { + compatible = "mmio-sram"; + reg = <0x20000000 DT_SIZE_K(32)>; + }; + + flc0: flash_controller@40029000 { + compatible = "flash-controller"; + reg = <0x40029000 0x400>; + + #address-cells = <1>; + #size-cells = <1>; + status = "okay"; + + flash0: flash@10000000 { + compatible = "soc-nv-flash"; + reg = <0x10000000 DT_SIZE_K(512)>; + write-block-size = <16>; + erase-block-size = <8192>; + }; + }; + + gcr: clock-controller@40000000 { + reg = <0x40000000 0x400>; + compatible = "adi,max32-gcr"; + #clock-cells = <2>; + clocks = <&clk_ipo>; + sysclk-prescaler = <1>; + status = "okay"; + }; + + pinctrl: pin-controller@40008000 { + compatible = "adi,max32-pinctrl"; + #address-cells = <1>; + #size-cells = <1>; + reg = <0x40008000 0x2000>; + + gpio0: gpio@40008000 { + reg = <0x40008000 0x1000>; + compatible = "adi,max32-gpio"; + gpio-controller; + #gpio-cells = <2>; + clocks = <&gcr ADI_MAX32_CLOCK_BUS0 0>; + interrupts = <24 0>; + status = "disabled"; + }; + + gpio1: gpio@40009000 { + reg = <0x40009000 0x1000>; + compatible = "adi,max32-gpio"; + gpio-controller; + #gpio-cells = <2>; + interrupts = <25 0>; + clocks = <&gcr ADI_MAX32_CLOCK_BUS0 1>; + status = "disabled"; + }; + }; + + uart0: serial@40042000 { + compatible = "adi,max32-uart"; + reg = <0x40042000 0x1000>; + clocks = <&gcr ADI_MAX32_CLOCK_BUS0 9>; + clock-source = ; + interrupts = <14 0>; + status = "disabled"; + }; + + uart1: serial@40043000 { + compatible = "adi,max32-uart"; + reg = <0x40043000 0x1000>; + clocks = <&gcr ADI_MAX32_CLOCK_BUS0 10>; + clock-source = ; + interrupts = <15 0>; + status = "disabled"; + }; + + uart2: serial@40044000 { + compatible = "adi,max32-uart"; + reg = <0x40044000 0x1000>; + clocks = <&gcr ADI_MAX32_CLOCK_BUS1 1>; + clock-source = ; + interrupts = <34 0>; + status = "disabled"; + }; + }; +}; + +&nvic { + arm,num-irq-priority-bits = <3>; +}; diff --git a/soc/adi/max32/CMakeLists.txt b/soc/adi/max32/CMakeLists.txt new file mode 100644 index 0000000000000..9941c670e8bc5 --- /dev/null +++ b/soc/adi/max32/CMakeLists.txt @@ -0,0 +1,8 @@ +# Copyright (c) 2023-2024 Analog Devices, Inc. +# SPDX-License-Identifier: Apache-2.0 + +zephyr_include_directories(${ZEPHYR_BASE}/drivers) +zephyr_include_directories(common) +zephyr_sources(soc.c) + +set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/arm/cortex_m/scripts/linker.ld CACHE INTERNAL "") diff --git a/soc/adi/max32/Kconfig b/soc/adi/max32/Kconfig new file mode 100644 index 0000000000000..d968c165af6de --- /dev/null +++ b/soc/adi/max32/Kconfig @@ -0,0 +1,29 @@ +# Analog Devices MAX32xxx MCU family + +# Copyright (c) 2023-2024 Analog Devices, Inc. +# SPDX-License-Identifier: Apache-2.0 + +config SOC_FAMILY_MAX32 + select ARM + select CPU_HAS_ARM_MPU + select CPU_HAS_FPU + select CPU_CORTEX_M_HAS_SYSTICK + select CLOCK_CONTROL + select BUILD_OUTPUT_HEX + +config SOC_MAX32690 + select CPU_CORTEX_M4 + +if SOC_FAMILY_MAX32 + +config MAX32_ON_ENTER_CPU_IDLE_HOOK + bool "CPU idle hook enable" + default y + imply ARM_ON_ENTER_CPU_IDLE_HOOK + help + Enables a hook (z_arm_on_enter_cpu_idle()) that is called when + the CPU is made idle (by k_cpu_idle() or k_cpu_atomic_idle()). + If needed, this hook can be used to prevent the CPU from actually + entering sleep by skipping the WFE/WFI instruction. + +endif # SOC_FAMILY_MAX32 diff --git a/soc/adi/max32/Kconfig.defconfig b/soc/adi/max32/Kconfig.defconfig new file mode 100644 index 0000000000000..eb33fc2daa95d --- /dev/null +++ b/soc/adi/max32/Kconfig.defconfig @@ -0,0 +1,13 @@ +# Analog Devices MAX32xxx MCU family + +# Copyright (c) 2023-2024 Analog Devices, Inc. +# SPDX-License-Identifier: Apache-2.0 + +if SOC_FAMILY_MAX32 + +rsource "Kconfig.defconfig.max32*" + +config SRAM_VECTOR_TABLE + default y + +endif # SOC_FAMILY_MAX32 diff --git a/soc/adi/max32/Kconfig.defconfig.max32690 b/soc/adi/max32/Kconfig.defconfig.max32690 new file mode 100644 index 0000000000000..a82759aff09f0 --- /dev/null +++ b/soc/adi/max32/Kconfig.defconfig.max32690 @@ -0,0 +1,14 @@ +# Analog Devices MAX32690 MCU + +# Copyright (c) 2023-2024 Analog Devices, Inc. +# SPDX-License-Identifier: Apache-2.0 + +if SOC_MAX32690 + +config SYS_CLOCK_HW_CYCLES_PER_SEC + default $(dt_node_int_prop_int,/clocks/clk_ipo,clock-frequency) + +config NUM_IRQS + default 112 + +endif # SOC_MAX32690 diff --git a/soc/adi/max32/Kconfig.soc b/soc/adi/max32/Kconfig.soc new file mode 100644 index 0000000000000..641af7c7576c8 --- /dev/null +++ b/soc/adi/max32/Kconfig.soc @@ -0,0 +1,21 @@ +# Analog Devices MAX32xxx MCU family + +# Copyright (c) 2023-2024 Analog Devices, Inc. +# SPDX-License-Identifier: Apache-2.0 + +config SOC_FAMILY_MAX32 + bool + +config SOC_FAMILY + default "max32" if SOC_FAMILY_MAX32 + +config SOC_MAX32690 + bool + select SOC_FAMILY_MAX32 + +config SOC_MAX32690_M4 + bool + select SOC_MAX32690 + +config SOC + default "max32690" if SOC_MAX32690 diff --git a/soc/adi/max32/soc.c b/soc/adi/max32/soc.c new file mode 100644 index 0000000000000..5c7f875d029b8 --- /dev/null +++ b/soc/adi/max32/soc.c @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2023-2024 Analog Devices, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * @brief System/hardware module for MAX32xxx MCUs + */ + +#include +#include + +#include + +#if defined(CONFIG_MAX32_ON_ENTER_CPU_IDLE_HOOK) +bool z_arm_on_enter_cpu_idle(void) +{ + /* Returning false prevent device goes to sleep mode */ + return false; +} +#endif + +/** + * @brief Perform basic hardware initialization at boot. + * + * This needs to be run from the very beginning. + * So the init priority has to be 0 (zero). + * + * @return 0 + */ +static int max32xxx_init(void) +{ + /* Apply device related preinit configuration */ + max32xx_system_init(); + + return 0; +} + +SYS_INIT(max32xxx_init, PRE_KERNEL_1, 0); diff --git a/soc/adi/max32/soc.h b/soc/adi/max32/soc.h new file mode 100644 index 0000000000000..fd785920a4a0b --- /dev/null +++ b/soc/adi/max32/soc.h @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2023-2024 Analog Devices, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file SoC configuration macros for the MAX32xxx family processors. + * + */ + +#ifndef _MAX32_SOC_H_ +#define _MAX32_SOC_H_ + +#include + +#endif /* _MAX32_SOC_H_ */ diff --git a/soc/adi/max32/soc.yml b/soc/adi/max32/soc.yml new file mode 100644 index 0000000000000..a5cba0de349b1 --- /dev/null +++ b/soc/adi/max32/soc.yml @@ -0,0 +1,9 @@ +# Copyright (c) 2023-2024 Analog Devices, Inc. +# SPDX-License-Identifier: Apache-2.0 + +family: +- name: max32 + socs: + - name: max32690 + cpuclusters: + - name: m4 From e31d66a183a903b63929bfecb4c382f3b1095ebc Mon Sep 17 00:00:00 2001 From: Sadik Ozer Date: Wed, 15 Nov 2023 20:44:00 +0300 Subject: [PATCH 1298/2849] boards: Add MAX32690EVKit board Added MAX32690EVKit board For more information about this board please check https://www.analog.com/ MAX32690 has two core, Cortex-M4 and Risc-V. Examples can be build by below command for cortex-m4 west build -b max32690evkit/max32690/m4 samples/hello_world As a shorthand, the soc may be omitted from the build command and keeping the corresponding forward slashes: west build -b max32690evkit//m4 samples/hello_world Co-authored-by: Jason Murphy Co-authored-by: Maureen Helm Signed-off-by: Sadik Ozer --- .../adi/max32690evkit/Kconfig.max32690evkit | 7 + boards/adi/max32690evkit/board.cmake | 9 + boards/adi/max32690evkit/board.yml | 8 + .../doc/img/max32690evkit_img1.jpg | Bin 0 -> 65533 bytes .../doc/img/max32690evkit_img2.jpg | Bin 0 -> 57117 bytes boards/adi/max32690evkit/doc/index.rst | 292 ++++++++++++++++++ .../max32690evkit_max32690_m4.dts | 87 ++++++ .../max32690evkit_max32690_m4.yaml | 13 + .../max32690evkit_max32690_m4_defconfig | 13 + 9 files changed, 429 insertions(+) create mode 100644 boards/adi/max32690evkit/Kconfig.max32690evkit create mode 100644 boards/adi/max32690evkit/board.cmake create mode 100644 boards/adi/max32690evkit/board.yml create mode 100644 boards/adi/max32690evkit/doc/img/max32690evkit_img1.jpg create mode 100644 boards/adi/max32690evkit/doc/img/max32690evkit_img2.jpg create mode 100644 boards/adi/max32690evkit/doc/index.rst create mode 100644 boards/adi/max32690evkit/max32690evkit_max32690_m4.dts create mode 100644 boards/adi/max32690evkit/max32690evkit_max32690_m4.yaml create mode 100644 boards/adi/max32690evkit/max32690evkit_max32690_m4_defconfig diff --git a/boards/adi/max32690evkit/Kconfig.max32690evkit b/boards/adi/max32690evkit/Kconfig.max32690evkit new file mode 100644 index 0000000000000..d475a30f4c894 --- /dev/null +++ b/boards/adi/max32690evkit/Kconfig.max32690evkit @@ -0,0 +1,7 @@ +# MAX32690 board configuration + +# Copyright (c) 2023-2024 Analog Devices, Inc. +# SPDX-License-Identifier: Apache-2.0 + +config BOARD_MAX32690EVKIT + select SOC_MAX32690_M4 if BOARD_MAX32690EVKIT_MAX32690_M4 diff --git a/boards/adi/max32690evkit/board.cmake b/boards/adi/max32690evkit/board.cmake new file mode 100644 index 0000000000000..443c84cc5e85a --- /dev/null +++ b/boards/adi/max32690evkit/board.cmake @@ -0,0 +1,9 @@ +# Copyright (c) 2023-2024 Analog Devices, Inc. +# SPDX-License-Identifier: Apache-2.0 + +board_runner_args(openocd --cmd-pre-init "source [find interface/cmsis-dap.cfg]") +board_runner_args(openocd --cmd-pre-init "source [find target/max32690.cfg]") +board_runner_args(jlink "--device=MAX32690" "--reset-after-load") + +include(${ZEPHYR_BASE}/boards/common/openocd.board.cmake) +include(${ZEPHYR_BASE}/boards/common/jlink.board.cmake) diff --git a/boards/adi/max32690evkit/board.yml b/boards/adi/max32690evkit/board.yml new file mode 100644 index 0000000000000..53f531e193b8e --- /dev/null +++ b/boards/adi/max32690evkit/board.yml @@ -0,0 +1,8 @@ +# Copyright (c) 2023-2024 Analog Devices, Inc. +# SPDX-License-Identifier: Apache-2.0 + +board: + name: max32690evkit + vendor: adi + socs: + - name: max32690 diff --git a/boards/adi/max32690evkit/doc/img/max32690evkit_img1.jpg b/boards/adi/max32690evkit/doc/img/max32690evkit_img1.jpg new file mode 100644 index 0000000000000000000000000000000000000000..7ecfdcb3b2665e46fedbdf01fb3303afbb23ae11 GIT binary patch literal 65533 zcmbTdWmKFo&@j5VyB2p@+?^Je;_mLSxLa{3?(V*ew765;S=^<#yA)bz`_b3Veee11 zpF7Vy*(6Ug=S(umWG1tJSO4w+uoYz$WC1WR007L}1Ni#~Kq=({a&@=%@UXU`vhbsF zaJ9B&bGNqqugbq0fCvEm{{SK)0wN+Z(iQlWP4sJzNH6B$Bq7hgW0RkP9v}n%i}yT zl8$K5wY(k|!5Y0vX&3~>La=1#l4FQ;hqWLE|1BaPrE!b7?Y(< z)eE-u3ymsmFJ(-lCKa>6@#ItPCG~qN=K{@jy`SA(yrO>rB`lfw-Yp9xdBUDZVqKH- zz)pjV2_e)h_G)ZF86EKjMQ4u@oZ0D~vV}AXA%iHI)WY)Q=2=hXwEE7GXw;TooT@y# z>d~P^gPC7NLL-(mo=Muae5⪚iD(UZ4OI%`QPd`%A9J*JCyp5=U4+G4wIMgN3Amq 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�X5S;==M(UN} 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

H_BFo}_QoI)hj;6I)yq<5p*t1X-a_ox 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 literal 0 HcmV?d00001 diff --git a/boards/adi/max32690evkit/doc/img/max32690evkit_img2.jpg b/boards/adi/max32690evkit/doc/img/max32690evkit_img2.jpg new file mode 100644 index 0000000000000000000000000000000000000000..24b665d288d8038f0e8abcd37d669ae26c67125b GIT binary patch literal 57117 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%0DZyE ztch=l<5RKS?Jt3PGy|3&HaIMU#L{F=crh0k4JOh=h;EZzyl7$7@Eq_NOX7O+td|7k zxs->);=#eJ+Ut%8>O=^7VvQdx5EZ^ynaElM7bw&pW2G8oaKNAFdM01jLa>%+leIGo z3uRLya@hLMX7PiU;pMNGNt@S?_TESQf&>RBQG6Ra#`S5E9QVSa^gQ^gHl4<%2CSLXJOmNwXB;whMuz z#FB}XCa=KwJB&L;Cbp(+@d7Tm#2(vUqlIbW`REfVa3mGc_c>uX)apd#|uc`jgMKaRgdsHL!w9MpP)s2#zON~L~W~(-|zM5Mqy)WPN{=zaKcq@$mz1E6~ zN)A83iNyjd_DrdXPH{?#tR<7CRp>NZJa51Xl5t4GB2n_wty~?rA+taL_NPg8L+?e( zhD4cC6;xK5G(0dfu#c_mh-nN^u|Cx9=D5`PldFc3EyDK3AD7VWoBJcSkk68$jb_EM z8tZ3 zh_VQU4@T9)yB%%oxLO#KvJH6Rq+XAA7Pt2sKbw&?43%s!*Wx(67-reBjT8v)z%n!> zb2K*hnmzsg#nLSs-hc2+%GsS)7`dg~7dv_^cu3#}J&VM�F@mpPDBnu(7v={eJ*# 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 Si4rBrCzp69Gt_JT$N$;2k!Owo literal 0 HcmV?d00001 diff --git a/boards/adi/max32690evkit/doc/index.rst b/boards/adi/max32690evkit/doc/index.rst new file mode 100644 index 0000000000000..176a34ce2ba85 --- /dev/null +++ b/boards/adi/max32690evkit/doc/index.rst @@ -0,0 +1,292 @@ +.. _max32690_evkit: + +MAX32690EVKIT +############# + +Overview +******** +The MAX32690 evaluation kit (EV kit) provides a platform for evaluating the capabilities +of the MAX32690 microcontroller, which is an advanced system-on-chip (SoC). +It features an Arm® Cortex®-M4F CPU for efficient computation of complex functions and +algorithms, and the latest generation Bluetooth® 5 Low Energy (Bluetooth LE) radio designed +for wearable and hearable fitness devices, portable and wearable wireless medical devices, +industrial sensors/networks, internet of things (IoT), and asset tracking. + +The Zephyr port is running on the MAX32690 MCU. + +.. image:: img/max32690evkit_img1.jpg + :align: center + :alt: MAX32690 EVKIT Front + +.. image:: img/max32690evkit_img2.jpg + :align: center + :alt: MAX32690 Back + +Hardware +******** + +- MAX32690 MCU: + + - Ultra-Efficient Microcontroller for Battery-Powered Applications + + - 120MHz Arm Cortex-M4 Processor with FPU + - 7.3728MHz and 60MHz Low-Power Oscillators + - External Crystal Support (32MHz required for BLE) + - 32.768kHz RTC Clock (Requires External Crystal) + - 8kHz Always-On Ultra-Low Power Oscillator + - 3MB Internal Flash, 1MB Internal SRAM (832kB ECC ON) + - TBDμW/MHz Executing from Cache at 1.1V + - 1.8V and 3.3V I/O with No Level Translators + - External Flash & SRAM Expansion Interfaces + + - Bluetooth 5.2 LE Radio + + - Dedicated, Ultra-Low-Power, 32-Bit RISC-V Coprocessor to Offload Timing-Critical Bluetooth Processing + - Fully Open-Source Bluetooth 5.2 Stack Available + - Supports AoA, AoD, LE Audio, and Mesh + - High-Throughput (2Mbps) Mode + - Long-Range (125kbps and 500kbps) Modes + - Rx Sensitivity: -97.5dBm; Tx Power: +4.5dBm + - Single-Ended Antenna Connection (50Ω) + + - Multiple Peripherals for System Control + + - 16-Channel DMA + - Up To Five Quad SPI Master (60MHz)/Slave (48MHz) + - Up To Four 1Mbaud UARTs with Flow Control + - Up To Two 1MHz I2C Master/Slave + - I2S Master/Slave + - Eight External Channel, 12-bit 1MSPS SAR ADC w/ on-die temperature sensor + - USB 2.0 Hi-Speed Device + - 16 Pulse Train Engines + - Up To Six 32-Bit Timers with 8mA High Drive + - Up To Two CAN 2.0 Controllers + - Up To Four Micro-Power Comparators + - 1-Wire Master + + - Security and Integrity​ + + - ChipDNA Physically Un-clonable Function (PUF) + - Modular Arithmetic Accelerator (MAA), True Random Number Generator (TRNG) + - Secure Nonvolatile Key Storage, SHA-256, AES-128/192/256 + - Secure Boot ROM + +- External devices connected to the MAX32690EVKIT: + + - Bluetooth SMA Connector with a Hinged 2.4GHz Whip Antenna + - 3-Pin Terminal Block for CAN Bus 2.0 + - Selectable On-Board High-Precision Voltage Reference + - On-Board HyperRAM + - Stereo Audio Codec with Line-In and Line-Out 3.5mm Jacks + - 128 x 128 (1.45in) Color TFT Display + - USB 2.0 Micro-B Interface to the MAX32690 + - USB 2.0 Micro-B to Serial UART + - Board Power Provided by either USB Port + - Jumpers to Enable Optional Pull-Up Resistors on I2C port + - All GPIOs Signals Accessed through 0.1in Headers + - Three Analog Inputs Accessed through 0.1in Headers with Optional Filtering + - SWD 10-Pin Header + - On-Board 3.3V, 1.8V, and 1.1V LDO Regulators + - Individual Power Measurement on All IC Rails through Jumpers + - Two General-Purpose LEDs and One GeneralPurpose Push Button Switch + + +Supported Features +================== + +Below interfaces are supported by Zephyr on MAX32690EVKIT. + ++-----------+------------+-------------------------------------+ +| Interface | Controller | Driver/Component | ++===========+============+=====================================+ +| NVIC | on-chip | nested vector interrupt controller | ++-----------+------------+-------------------------------------+ +| SYSTICK | on-chip | systick | ++-----------+------------+-------------------------------------+ +| CLOCK | on-chip | clock and reset control | ++-----------+------------+-------------------------------------+ +| GPIO | on-chip | gpio | ++-----------+------------+-------------------------------------+ +| UART | on-chip | serial | ++-----------+------------+-------------------------------------+ + + +Connections and IOs +=================== + ++-----------+---------------+---------------+--------------------------------------------------------------------------------------------------+ +| Name | Name | Settings | Description | ++===========+===============+===============+==================================================================================================+ +| JP1 | VREF | | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | 1-2 | | | Connects external voltage reference to VREF pin, must be enabled in software. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | Open | | | Disconnects external voltage reference. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | | ++-----------+---------------+---------------+--------------------------------------------------------------------------------------------------+ +| JP2 | I2C0 PU | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | 2-1 | | | Connects VDDIO (1V8) to I2C0 pull-up resistors. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | 2-3 | | | Connects VDDIOH (3V3) to I2C0 pull-up resistors. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | Open | | | Disconnects power from I2C0 pull-up resistors. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | | ++-----------+---------------+---------------+--------------------------------------------------------------------------------------------------+ +| JP3 | I2C0_SDA_PU | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | 1-2 | | | Connects pull-up to I2C0A_SDA (P2.7) sourced by I2C0 PU (JP2). | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | Open | | | Disconnects pull-up from I2C0A_SDA (P2.7) sourced by I2C0 PU (JP2). | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | | ++-----------+---------------+---------------+--------------------------------------------------------------------------------------------------+ +| JP4 | I2C0_SCL_PU | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | 1-2 | | | Connects pull-up to I2C0A_SCL (P2.8) sourced by I2C0 PU (JP2). | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | Open | | | Disconnects pull-up from I2C0A_SCL (P2.8) sourced by I2C0 PU (JP2). | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | | ++-----------+---------------+---------------+--------------------------------------------------------------------------------------------------+ +| JP5 | LED0 EN | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | 1-2 | | | Connects red LED D1 to P0.14. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | Open | | | Disconnects red LED D1 from P0.14. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | | ++-----------+---------------+---------------+--------------------------------------------------------------------------------------------------+ +| JP6 | LED1 EN | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | 1-2 | | | Connects green LED D2 to P2.12. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | Open | | | Disconnects green LED D2 from P2.12. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | | ++-----------+---------------+---------------+--------------------------------------------------------------------------------------------------+ +| JP7 | RX EN | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | 1-2 | | | Connects the USB - serial bridge to UART2A_RX (P1.9). | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | Open | | | Disconnects the USB - serial bridge from UART2A_RX (P1.9). | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | | ++-----------+---------------+---------------+--------------------------------------------------------------------------------------------------+ +| JP8 | TX EN | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | 1-2 | | | Connects the USB - serial bridge to UART2A_TX (P1.10). | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | Open | | | Disconnects the USB - serial bridge from UART2A_TX (P1.10). | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | | ++-----------+---------------+---------------+--------------------------------------------------------------------------------------------------+ +| JP9 | P1_7 SEL | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | 2-1 | | | Connects the USB - serial bridge to UART2A_CTS (P1.7). | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | 2-3 | | | Connects I2C2C_SDA (P1.7) to the codec. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | | ++-----------+---------------+---------------+--------------------------------------------------------------------------------------------------+ +| JP10 | P1_8 SEL | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | 2-1 | | | Connects the USB - serial bridge to UART2A_RTS (P1.8). | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | 2-3 | | | Connects I2C2C_SCL (P1.8) to the codec. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | | ++-----------+---------------+---------------+--------------------------------------------------------------------------------------------------+ +| JP11 | V_AUX SEL | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | 2-1 | | | Connects V_AUX to 1V8. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | 2-3 | | | Connects V_AUX to 3V3. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | | ++-----------+---------------+---------------+--------------------------------------------------------------------------------------------------+ +| JP12 | VDD3A EN | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | 1-2 | | | Connects 3V3 to VDD3A. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | Open | | | Disconnects 3V3 from VDD3A. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | | ++-----------+---------------+---------------+--------------------------------------------------------------------------------------------------+ +| JP13 | VDDIOH EN | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | 1-2 | | | Connects 3V3 to VDDIOH. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | Open | | | Disconnects 3V3 from VDDIOH. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | | ++-----------+---------------+---------------+--------------------------------------------------------------------------------------------------+ +| JP14 | VDDB EN | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | 1-2 | | | Connects a 3V3 LDO sourced by USB_VBUS (CN1) to VDDB. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | Open | | | Disconnects a 3V3 LDO sourced by USB_VBUS (CN1) from VDDB. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | | ++-----------+---------------+---------------+--------------------------------------------------------------------------------------------------+ +| JP15 | VDDA EN | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | 1-2 | | | Connects 1V8 to VDDA. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | Open | | | Disconnects 1V8 from VDDA. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | | ++-----------+---------------+---------------+--------------------------------------------------------------------------------------------------+ +| JP16 | VDDIO EN | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | 1-2 | | | Connects 1V8 to VDDIO. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | Open | | | Disconnects 1V8 from VDDIO. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | | ++-----------+---------------+---------------+--------------------------------------------------------------------------------------------------+ +| JP17 | VCORE EN | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | 1-2 | | | Connects 1V1 to VCORE. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | Open | | | Disconnects 1V1 from VCORE. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | | ++-----------+---------------+---------------+--------------------------------------------------------------------------------------------------+ +| JP18 | BLE LDO EN | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | 1-2 | | | Connects 1V4 to BLE_LDO. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | Open | | | Disconnects 1V4 from BLE_LDO. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | | ++-----------+---------------+---------------+--------------------------------------------------------------------------------------------------+ +| JH6 | ANALOG PORT3 | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | 1-2 | | | Connects LPUART0B_RX (P3.0) to the SWD connector. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | 3-4 | | | Connects LPUART0B_TX (P3.1) to the SWD connector. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | Open | | | Disconnects LPUART0B_RX (P3.0) and LPUART0B_TX (P3.1) from the SWD connector. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | | ++-----------+---------------+---------------+--------------------------------------------------------------------------------------------------+ + +Programming and Debugging +************************* + +Flashing +======== + +The MAX32690 MCU can be flashed by connecting an external debug probe to the +SWD port. SWD debug can be accessed through the Cortex 10-pin connector, J3. +Logic levels are fixed to VDDIO (1.8V). + +Once the debug probe is connected to your host computer, then you can simply run the +``west flash`` command to write a firmware image into flash. + +.. note:: + + This board uses OpenOCD as the default debug interface. You can also use + a Segger J-Link with Segger's native tooling by overriding the runner, + appending ``--runner jlink`` to your ``west`` command(s). The J-Link should + be connected to the standard 2*5 pin debug connector (JW3) using an + appropriate adapter board and cable. + +Debugging +========= + +Please refer to the `Flashing`_ section and run the ``west debug`` command +instead of ``west flash``. + +References +********** + +- `MAX32690EVKIT web page`_ + +.. _MAX32690EVKIT web page: + https://www.analog.com/en/design-center/evaluation-hardware-and-software/evaluation-boards-kits/MAX32690EVKIT.html diff --git a/boards/adi/max32690evkit/max32690evkit_max32690_m4.dts b/boards/adi/max32690evkit/max32690evkit_max32690_m4.dts new file mode 100644 index 0000000000000..424794d022aa6 --- /dev/null +++ b/boards/adi/max32690evkit/max32690evkit_max32690_m4.dts @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2023-2024 Analog Devices, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; + +#include +#include +#include + +/ { + model = "Analog Devices MAX32690EVKIT"; + compatible = "adi,max32690evkit"; + + chosen { + zephyr,console = &uart2; + zephyr,shell-uart = &uart2; + zephyr,sram = &sram0; + zephyr,flash = &flash0; + }; + + leds { + compatible = "gpio-leds"; + red_led: led_0 { + gpios = <&gpio0 14 GPIO_ACTIVE_LOW>; + label = "LED0"; + }; + green_led: led_1 { + gpios = <&gpio2 12 GPIO_ACTIVE_LOW>; + label = "LED1"; + }; + }; + + buttons { + compatible = "gpio-keys"; + pb0: pb0 { + gpios = <&gpio4 0 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>; + label = "SW2"; + }; + }; + + aliases { + led0 = &red_led; + led1 = &green_led; + sw0 = &pb0; + }; +}; + +&clk_ipo { + status = "okay"; +}; + +&clk_ibro { + status = "okay"; +}; + +&gpio0 { + status = "okay"; +}; + +&gpio1 { + status = "okay"; +}; + +&gpio2 { + status = "okay"; +}; + +&gpio3 { + status = "okay"; +}; + +&gpio4 { + status = "okay"; +}; + +&uart2 { + clock-source = ; + pinctrl-0 = <&uart2a_tx_p1_10 &uart2a_rx_p1_9>; + pinctrl-names = "default"; + current-speed = <115200>; + data-bits = <8>; + parity = "none"; + status = "okay"; +}; diff --git a/boards/adi/max32690evkit/max32690evkit_max32690_m4.yaml b/boards/adi/max32690evkit/max32690evkit_max32690_m4.yaml new file mode 100644 index 0000000000000..2fb7641658962 --- /dev/null +++ b/boards/adi/max32690evkit/max32690evkit_max32690_m4.yaml @@ -0,0 +1,13 @@ +identifier: max32690evkit/max32690/m4 +name: max32690evkit m4 +type: mcu +arch: arm +toolchain: + - zephyr + - gnuarmemb + - xtools +supported: + - gpio + - serial +ram: 1024 +flash: 3072 diff --git a/boards/adi/max32690evkit/max32690evkit_max32690_m4_defconfig b/boards/adi/max32690evkit/max32690evkit_max32690_m4_defconfig new file mode 100644 index 0000000000000..4fa0a46410634 --- /dev/null +++ b/boards/adi/max32690evkit/max32690evkit_max32690_m4_defconfig @@ -0,0 +1,13 @@ +# Copyright (c) 2023-2024 Analog Devices, Inc. +# SPDX-License-Identifier: Apache-2.0 + +# Enable GPIO +CONFIG_GPIO=y + +# Console +CONFIG_CONSOLE=y +CONFIG_UART_CONSOLE=y + +# Enable UART +CONFIG_SERIAL=y +CONFIG_UART_INTERRUPT_DRIVEN=y From 0767fd97f8fe69b9adff41dab8fbee1b22fe5143 Mon Sep 17 00:00:00 2001 From: Daniel DeGrasse Date: Tue, 28 May 2024 16:29:42 +0000 Subject: [PATCH 1299/2849] sd: sd_ops: fix DISK_IOCTL_CTRL_SYNC return code SD IOCTL handling for DISK_IOCTL_CTRL_SYNC was falling through to the default return statement, and returning an error when disk sync succeeded. Fix this issue by properly breaking in IOCTL handler. Signed-off-by: Daniel DeGrasse --- subsys/sd/sd_ops.c | 1 + 1 file changed, 1 insertion(+) diff --git a/subsys/sd/sd_ops.c b/subsys/sd/sd_ops.c index 54f5b1a360f14..9daa1f1f0c21f 100644 --- a/subsys/sd/sd_ops.c +++ b/subsys/sd/sd_ops.c @@ -794,6 +794,7 @@ int card_ioctl(struct sd_card *card, uint8_t cmd, void *buf) * cache flush is not required here */ ret = sdmmc_wait_ready(card); + break; default: ret = -ENOTSUP; } From 885d271e5721aef143fdec5ad73da70ab518bb3a Mon Sep 17 00:00:00 2001 From: Margherita Milani Date: Tue, 28 May 2024 16:52:33 +0200 Subject: [PATCH 1300/2849] drivers: sensor: si7006: fix redundant include in si7006 Remove redundant include of `zephyr/logging/log.h` in si7006.c. Signed-off-by: Margherita Milani --- drivers/sensor/silabs/si7006/si7006.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/sensor/silabs/si7006/si7006.c b/drivers/sensor/silabs/si7006/si7006.c index dc7c1b11ee5ae..86550a17f0d6a 100644 --- a/drivers/sensor/silabs/si7006/si7006.c +++ b/drivers/sensor/silabs/si7006/si7006.c @@ -13,12 +13,11 @@ #include #include #include -#include #include -#include #include #include #include "si7006.h" +#include LOG_MODULE_REGISTER(si7006, CONFIG_SENSOR_LOG_LEVEL); From 9e38bcc173b1590d2c60bf3182227d62bb3aadb8 Mon Sep 17 00:00:00 2001 From: Ravi Dondaputi Date: Mon, 27 May 2024 06:27:26 +0530 Subject: [PATCH 1301/2849] wifi: utils: Get correct channel count When channel range is configured in scan params, get the channel count from `chan_idx` instead of taking a difference of start and end of the channel range. The `difference` method fails in case of 5GHz band since channels may not be consecutive numbers. Signed-off-by: Ravi Dondaputi --- subsys/net/l2/wifi/wifi_utils.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/subsys/net/l2/wifi/wifi_utils.c b/subsys/net/l2/wifi/wifi_utils.c index 6293f6c55f41b..cc3cbb9951575 100644 --- a/subsys/net/l2/wifi/wifi_utils.c +++ b/subsys/net/l2/wifi/wifi_utils.c @@ -150,6 +150,7 @@ static int wifi_utils_get_all_chans_in_range(uint8_t chan_start, for (i = 0; i < ARRAY_SIZE(valid_5g_chans_20mhz); i++) { if (valid_5g_chans_20mhz[i] == chan_start) { start = true; + continue; } if (valid_5g_chans_20mhz[i] == chan_end) { @@ -368,10 +369,6 @@ int wifi_utils_parse_scan_chan(char *scan_chan_str, memset(chan_str, 0, sizeof(chan_str)); if (chan_start) { - if ((chan_idx + (chan_val - chan_start)) > max_channels) { - NET_ERR("Too many channels specified (%d)", max_channels); - return -EINVAL; - } if (wifi_utils_get_all_chans_in_range(chan_start, chan_val, band_chan, @@ -381,6 +378,10 @@ int wifi_utils_parse_scan_chan(char *scan_chan_str, return -EINVAL; } + if (chan_idx > max_channels) { + NET_ERR("Too many channels specified (%d)", max_channels); + return -EINVAL; + } chan_start = 0; } else { if (!wifi_utils_validate_chan(band, From 75165050f74415df78fdc2fa498f9dc31ff14363 Mon Sep 17 00:00:00 2001 From: Pisit Sawangvonganan Date: Sat, 25 May 2024 15:45:07 +0700 Subject: [PATCH 1302/2849] drivers: gpio: remove '&' when assigning `gpio_xxx_init` function Remove address-of operator ('&') when assigning `gpio_xxx_init` function pointer in `DEVICE_DT_INST_DEFINE` macro. This change aims to maintain consistency among the drivers in `drivers/gpio`, ensuring that all function pointer assignments follow the same pattern. Signed-off-by: Pisit Sawangvonganan --- drivers/gpio/gpio_ads114s0x.c | 2 +- drivers/gpio/gpio_ambiq.c | 2 +- drivers/gpio/gpio_axp192.c | 2 +- drivers/gpio/gpio_cc32xx.c | 2 +- drivers/gpio/gpio_davinci.c | 2 +- drivers/gpio/gpio_gd32.c | 2 +- drivers/gpio/gpio_lmp90xxx.c | 2 +- drivers/gpio/gpio_neorv32.c | 2 +- drivers/gpio/gpio_npm1300.c | 2 +- drivers/gpio/gpio_npm6001.c | 2 +- drivers/gpio/gpio_numaker.c | 2 +- drivers/gpio/gpio_sedi.c | 2 +- drivers/gpio/gpio_xlnx_axi.c | 2 +- 13 files changed, 13 insertions(+), 13 deletions(-) diff --git a/drivers/gpio/gpio_ads114s0x.c b/drivers/gpio/gpio_ads114s0x.c index 13f4f7f12669b..5c0cd261e2689 100644 --- a/drivers/gpio/gpio_ads114s0x.c +++ b/drivers/gpio/gpio_ads114s0x.c @@ -138,7 +138,7 @@ BUILD_ASSERT(CONFIG_GPIO_ADS114S0X_INIT_PRIORITY > CONFIG_ADC_INIT_PRIORITY, \ static struct gpio_ads114s0x_data gpio_ads114s0x_##id##_data; \ \ - DEVICE_DT_INST_DEFINE(id, &gpio_ads114s0x_init, NULL, &gpio_ads114s0x_##id##_data, \ + DEVICE_DT_INST_DEFINE(id, gpio_ads114s0x_init, NULL, &gpio_ads114s0x_##id##_data, \ &gpio_ads114s0x_##id##_cfg, POST_KERNEL, \ CONFIG_GPIO_ADS114S0X_INIT_PRIORITY, &gpio_ads114s0x_api); diff --git a/drivers/gpio/gpio_ambiq.c b/drivers/gpio/gpio_ambiq.c index 0c0f1db458c52..24e08a4057232 100644 --- a/drivers/gpio/gpio_ambiq.c +++ b/drivers/gpio/gpio_ambiq.c @@ -580,7 +580,7 @@ static const struct gpio_driver_api ambiq_gpio_drv_api = { .irq_num = DT_INST_IRQN(n), \ .cfg_func = ambiq_gpio_cfg_func_##n}; \ AMBIQ_GPIO_CONFIG_FUNC(n) \ - DEVICE_DT_INST_DEFINE(n, &ambiq_gpio_init, NULL, &ambiq_gpio_data_##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/drivers/gpio/gpio_axp192.c b/drivers/gpio/gpio_axp192.c index 5b1b41c758c45..661348bc1be3f 100644 --- a/drivers/gpio/gpio_axp192.c +++ b/drivers/gpio/gpio_axp192.c @@ -313,7 +313,7 @@ static int gpio_axp192_init(const struct device *dev) \ static struct gpio_axp192_data gpio_axp192_data##inst; \ \ - DEVICE_DT_INST_DEFINE(inst, &gpio_axp192_init, NULL, &gpio_axp192_data##inst, \ + DEVICE_DT_INST_DEFINE(inst, gpio_axp192_init, NULL, &gpio_axp192_data##inst, \ &gpio_axp192_config##inst, POST_KERNEL, \ CONFIG_GPIO_AXP192_INIT_PRIORITY, &gpio_axp192_api); diff --git a/drivers/gpio/gpio_cc32xx.c b/drivers/gpio/gpio_cc32xx.c index c575237003b54..88d2f7eee27fb 100644 --- a/drivers/gpio/gpio_cc32xx.c +++ b/drivers/gpio/gpio_cc32xx.c @@ -256,7 +256,7 @@ static const struct gpio_driver_api api_funcs = { } #define GPIO_CC32XX_DEVICE_INIT(n) \ - DEVICE_DT_INST_DEFINE(n, &gpio_cc32xx_a##n##_init, \ + DEVICE_DT_INST_DEFINE(n, gpio_cc32xx_a##n##_init, \ NULL, &gpio_cc32xx_a##n##_data, \ &gpio_cc32xx_a##n##_config, \ POST_KERNEL, CONFIG_GPIO_INIT_PRIORITY, \ diff --git a/drivers/gpio/gpio_davinci.c b/drivers/gpio/gpio_davinci.c index 205e0112cde8f..b3ff9d4b22984 100644 --- a/drivers/gpio/gpio_davinci.c +++ b/drivers/gpio/gpio_davinci.c @@ -191,7 +191,7 @@ static int gpio_davinci_init(const struct device *dev) static struct gpio_davinci_data gpio_davinci_##n##_data; \ \ DEVICE_DT_INST_DEFINE(n, \ - &gpio_davinci_init, \ + gpio_davinci_init, \ NULL, \ &gpio_davinci_##n##_data, \ &gpio_davinci_##n##_config, \ diff --git a/drivers/gpio/gpio_gd32.c b/drivers/gpio/gpio_gd32.c index 376c70f463f04..744f5e4a7768d 100644 --- a/drivers/gpio/gpio_gd32.c +++ b/drivers/gpio/gpio_gd32.c @@ -373,7 +373,7 @@ static int gpio_gd32_init(const struct device *port) \ static struct gpio_gd32_data gpio_gd32_data##n; \ \ - DEVICE_DT_INST_DEFINE(n, &gpio_gd32_init, NULL, &gpio_gd32_data##n, \ + DEVICE_DT_INST_DEFINE(n, gpio_gd32_init, NULL, &gpio_gd32_data##n, \ &gpio_gd32_config##n, PRE_KERNEL_1, \ CONFIG_GPIO_INIT_PRIORITY, &gpio_gd32_api); diff --git a/drivers/gpio/gpio_lmp90xxx.c b/drivers/gpio/gpio_lmp90xxx.c index 2514ef35211ce..55dd01de978f7 100644 --- a/drivers/gpio/gpio_lmp90xxx.c +++ b/drivers/gpio/gpio_lmp90xxx.c @@ -161,7 +161,7 @@ BUILD_ASSERT(CONFIG_GPIO_LMP90XXX_INIT_PRIORITY > static struct gpio_lmp90xxx_data gpio_lmp90xxx_##id##_data; \ \ DEVICE_DT_INST_DEFINE(id, \ - &gpio_lmp90xxx_init, \ + gpio_lmp90xxx_init, \ NULL, \ &gpio_lmp90xxx_##id##_data, \ &gpio_lmp90xxx_##id##_cfg, POST_KERNEL, \ diff --git a/drivers/gpio/gpio_neorv32.c b/drivers/gpio/gpio_neorv32.c index b14c51c147173..21bd6fe85ef63 100644 --- a/drivers/gpio/gpio_neorv32.c +++ b/drivers/gpio/gpio_neorv32.c @@ -221,7 +221,7 @@ static const struct gpio_driver_api neorv32_gpio_driver_api = { }; \ \ DEVICE_DT_INST_DEFINE(n, \ - &neorv32_gpio_init, \ + neorv32_gpio_init, \ NULL, \ &neorv32_gpio_##n##_data, \ &neorv32_gpio_##n##_config, \ diff --git a/drivers/gpio/gpio_npm1300.c b/drivers/gpio/gpio_npm1300.c index 0018530207d92..96725b61ddf3f 100644 --- a/drivers/gpio/gpio_npm1300.c +++ b/drivers/gpio/gpio_npm1300.c @@ -222,7 +222,7 @@ static int gpio_npm1300_init(const struct device *dev) \ static struct gpio_npm1300_data gpio_npm1300_data##n; \ \ - DEVICE_DT_INST_DEFINE(n, &gpio_npm1300_init, NULL, &gpio_npm1300_data##n, \ + DEVICE_DT_INST_DEFINE(n, gpio_npm1300_init, NULL, &gpio_npm1300_data##n, \ &gpio_npm1300_config##n, POST_KERNEL, \ CONFIG_GPIO_NPM1300_INIT_PRIORITY, &gpio_npm1300_api); diff --git a/drivers/gpio/gpio_npm6001.c b/drivers/gpio/gpio_npm6001.c index f722c4275d6e9..b69df1f369ae2 100644 --- a/drivers/gpio/gpio_npm6001.c +++ b/drivers/gpio/gpio_npm6001.c @@ -223,7 +223,7 @@ static int gpio_npm6001_init(const struct device *dev) \ static struct gpio_npm6001_data gpio_npm6001_data##n; \ \ - DEVICE_DT_INST_DEFINE(n, &gpio_npm6001_init, NULL, \ + DEVICE_DT_INST_DEFINE(n, gpio_npm6001_init, NULL, \ &gpio_npm6001_data##n, &gpio_npm6001_config##n, \ POST_KERNEL, CONFIG_GPIO_NPM6001_INIT_PRIORITY, \ &gpio_npm6001_api); diff --git a/drivers/gpio/gpio_numaker.c b/drivers/gpio/gpio_numaker.c index c88e0d498ce5f..a4fe054221782 100644 --- a/drivers/gpio/gpio_numaker.c +++ b/drivers/gpio/gpio_numaker.c @@ -265,7 +265,7 @@ static void gpio_numaker_isr(const struct device *dev) SYS_LockReg(); \ return err; \ } \ - DEVICE_DT_INST_DEFINE(n, &gpio_numaker_init##n, NULL, &gpio_numaker_data##n, \ + 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, \ &gpio_numaker_api); diff --git a/drivers/gpio/gpio_sedi.c b/drivers/gpio/gpio_sedi.c index 806ec422c95d8..d4d273d6d6d8a 100644 --- a/drivers/gpio/gpio_sedi.c +++ b/drivers/gpio/gpio_sedi.c @@ -331,7 +331,7 @@ static int gpio_sedi_init(const struct device *dev) }; \ PM_DEVICE_DEFINE(gpio_##n, gpio_sedi_pm_action); \ DEVICE_DT_INST_DEFINE(n, \ - &gpio_sedi_init, \ + gpio_sedi_init, \ PM_DEVICE_GET(gpio_##n), \ &gpio##n##_data, \ &gpio##n##_config, \ diff --git a/drivers/gpio/gpio_xlnx_axi.c b/drivers/gpio/gpio_xlnx_axi.c index f6ba2dd260610..4b50bf85cd6ec 100644 --- a/drivers/gpio/gpio_xlnx_axi.c +++ b/drivers/gpio/gpio_xlnx_axi.c @@ -450,7 +450,7 @@ static const struct gpio_driver_api gpio_xlnx_axi_driver_api = { irq_enable(DT_INST_IRQN(n)); \ })) \ \ - DEVICE_DT_INST_DEFINE(n, &gpio_xlnx_axi_init, NULL, &gpio_xlnx_axi_##n##_data, \ + DEVICE_DT_INST_DEFINE(n, gpio_xlnx_axi_init, NULL, &gpio_xlnx_axi_##n##_data, \ &gpio_xlnx_axi_##n##_config, PRE_KERNEL_1, \ CONFIG_GPIO_INIT_PRIORITY, &gpio_xlnx_axi_driver_api); From eae316ebc9ffad98b93291ebaca71a15e74fed1d Mon Sep 17 00:00:00 2001 From: Declan Snyder Date: Fri, 24 May 2024 12:19:15 -0500 Subject: [PATCH 1303/2849] dts: bindings: Rename nxp,kinetis-lptmr compat Rename nxp,kinetis-lptmr compat to nxp,lptmr. Because of concerns over breaking downstream users, keep support for the old compatible temporarily and make it clear it should be changed. Signed-off-by: Declan Snyder --- drivers/counter/Kconfig.mcux_lptmr | 13 ++++++++++++- drivers/counter/counter_mcux_lptmr.c | 5 +++++ dts/bindings/counter/nxp,kinetis-lptmr.yaml | 8 ++++++++ .../nxp,lptmr.yaml} | 4 ++-- 4 files changed, 27 insertions(+), 3 deletions(-) create mode 100644 dts/bindings/counter/nxp,kinetis-lptmr.yaml rename dts/bindings/{rtc/nxp,kinetis-lptmr.yaml => counter/nxp,lptmr.yaml} (89%) diff --git a/drivers/counter/Kconfig.mcux_lptmr b/drivers/counter/Kconfig.mcux_lptmr index 98bf35dec5caa..d6847a3ffbb4b 100644 --- a/drivers/counter/Kconfig.mcux_lptmr +++ b/drivers/counter/Kconfig.mcux_lptmr @@ -6,6 +6,17 @@ config COUNTER_MCUX_LPTMR bool "MCUX LPTMR driver" default y - depends on DT_HAS_NXP_KINETIS_LPTMR_ENABLED + depends on DT_HAS_NXP_LPTMR_ENABLED || \ + COUNTER_MCUX_KINETIS_LPTMR help Enable support for the MCUX Low Power Timer (LPTMR). + +config COUNTER_MCUX_KINETIS_LPTMR + bool "Deprecated DT compatible" + default y + depends on DT_HAS_NXP_KINETIS_LPTMR_ENABLED + select DEPRECATED + help + The compatible string "nxp,kinetis-lptmr" should + be swiched to "nxp,lptmr" in DT. The former will + be removed eventually. diff --git a/drivers/counter/counter_mcux_lptmr.c b/drivers/counter/counter_mcux_lptmr.c index 4e1007d9b4927..c24e60a2e0659 100644 --- a/drivers/counter/counter_mcux_lptmr.c +++ b/drivers/counter/counter_mcux_lptmr.c @@ -4,7 +4,12 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include +#if DT_HAS_COMPAT_STATUS_OKAY(nxp_kinetis_lptmr) #define DT_DRV_COMPAT nxp_kinetis_lptmr +#else +#define DT_DRV_COMPAT nxp_lptmr +#endif #include #include diff --git a/dts/bindings/counter/nxp,kinetis-lptmr.yaml b/dts/bindings/counter/nxp,kinetis-lptmr.yaml new file mode 100644 index 0000000000000..0188b103b1c20 --- /dev/null +++ b/dts/bindings/counter/nxp,kinetis-lptmr.yaml @@ -0,0 +1,8 @@ +# Copyright 2024 NXP +# SPDX-License-Identifier: Apache-2.0 + +description: Deprecated compatible for NXP LPTMR + +compatible: "nxp,kinetis-lptmr" + +include: nxp,lptmr.yaml diff --git a/dts/bindings/rtc/nxp,kinetis-lptmr.yaml b/dts/bindings/counter/nxp,lptmr.yaml similarity index 89% rename from dts/bindings/rtc/nxp,kinetis-lptmr.yaml rename to dts/bindings/counter/nxp,lptmr.yaml index f16451fc0a35a..13e38d76302f9 100644 --- a/dts/bindings/rtc/nxp,kinetis-lptmr.yaml +++ b/dts/bindings/counter/nxp,lptmr.yaml @@ -1,9 +1,9 @@ # Copyright (c) 2020 Vestas Wind Systems A/S # SPDX-License-Identifier: Apache-2.0 -description: Kinetis LPTMR +description: NXP LPTMR -compatible: "nxp,kinetis-lptmr" +compatible: "nxp,lptmr" include: rtc.yaml From 2cff570083d71d757ab4d69522cca20370d2f779 Mon Sep 17 00:00:00 2001 From: Declan Snyder Date: Fri, 24 May 2024 12:20:28 -0500 Subject: [PATCH 1304/2849] dts: nxp: Convert nxp,lptmr compats Convert compats in tree from nxp,kinetis-lptmr to nxp,lptmr string. Signed-off-by: Declan Snyder --- dts/arm/nxp/nxp_ke1xf.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dts/arm/nxp/nxp_ke1xf.dtsi b/dts/arm/nxp/nxp_ke1xf.dtsi index 6d2bacf26ea46..d47fd6cca5287 100644 --- a/dts/arm/nxp/nxp_ke1xf.dtsi +++ b/dts/arm/nxp/nxp_ke1xf.dtsi @@ -284,7 +284,7 @@ }; lptmr0: lptmr@40040000 { - compatible = "nxp,kinetis-lptmr"; + compatible = "nxp,lptmr"; reg = <0x40040000 0x1000>; interrupts = <58 0>; clock-frequency = <128000>; From ce7448b11ebb77655649428c99397572ba61d09e Mon Sep 17 00:00:00 2001 From: Declan Snyder Date: Fri, 24 May 2024 12:21:01 -0500 Subject: [PATCH 1305/2849] doc: migration-guilde-3.7: nxp,lptmr List change to nxp,lptmr compatible in migration guide. Signed-off-by: Declan Snyder --- 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 8b9c876258e18..547268260be35 100644 --- a/doc/releases/migration-guide-3.7.rst +++ b/doc/releases/migration-guide-3.7.rst @@ -149,6 +149,10 @@ Device Drivers and Devicetree }; }; +* The :dtcompatible:`nxp,kinetis-lptmr` compatible string has been changed to + :dtcompatible:`nxp,lptmr`. The old string will be usable for a short time, but + should be replaced for it will be removed in the future. + * Some of the driver API structs have been rename to have the required ``_driver_api`` suffix. (:github:`72182`) The following types have been renamed: From 0809b75b42e64b2a062666683c7572076b40d841 Mon Sep 17 00:00:00 2001 From: Johann Fischer Date: Fri, 24 May 2024 15:42:31 +0200 Subject: [PATCH 1306/2849] boards: remove test feature usb_cdc This test feature is not required and was only used as a dependency in the usb/console example. It is redundant since the sample already depends on usb_device. Signed-off-by: Johann Fischer --- boards/adafruit/feather/adafruit_feather_nrf52840.yaml | 1 - boards/adafruit/itsybitsy/adafruit_itsybitsy_nrf52840.yaml | 1 - boards/arduino/giga_r1/arduino_giga_r1_stm32h747xx_m7.yaml | 1 - boards/arduino/nano_33_ble/arduino_nano_33_ble.yaml | 1 - .../arduino/nano_33_ble/arduino_nano_33_ble_nrf52840_sense.yaml | 1 - boards/atmel/sam0/samd21_xpro/samd21_xpro.yaml | 1 - boards/atmel/sam0/saml21_xpro/saml21_xpro.yaml | 1 - boards/atmel/sam0/samr34_xpro/samr34_xpro.yaml | 1 - boards/lairdconnect/bl5340_dvk/bl5340_dvk_nrf5340_cpuapp.yaml | 1 - boards/lairdconnect/bl5340_dvk/bl5340_dvk_nrf5340_cpuapp_ns.yaml | 1 - boards/lairdconnect/bl654_usb/bl654_usb.yaml | 1 - boards/lairdconnect/pinnacle_100_dvk/pinnacle_100_dvk.yaml | 1 - .../nrf52840_mdk_usb_dongle/nrf52840_mdk_usb_dongle.yaml | 1 - boards/nordic/nrf21540dk/nrf21540dk_nrf52840.yaml | 1 - boards/nordic/nrf52840dk/nrf52840dk_nrf52840.yaml | 1 - boards/nordic/nrf52840dongle/nrf52840dongle_nrf52840.yaml | 1 - .../nordic/nrf5340_audio_dk/nrf5340_audio_dk_nrf5340_cpuapp.yaml | 1 - .../nrf5340_audio_dk/nrf5340_audio_dk_nrf5340_cpuapp_ns.yaml | 1 - boards/nordic/nrf5340dk/nrf5340dk_nrf5340_cpuapp.yaml | 1 - boards/nordic/nrf5340dk/nrf5340dk_nrf5340_cpuapp_ns.yaml | 1 - boards/nordic/thingy53/thingy53_nrf5340_cpuapp.yaml | 1 - boards/nordic/thingy53/thingy53_nrf5340_cpuapp_ns.yaml | 1 - boards/panasonic/pan1770_evb/pan1770_evb.yaml | 1 - boards/panasonic/pan1780_evb/pan1780_evb.yaml | 1 - boards/panasonic/pan1783/pan1783_evb_nrf5340_cpuapp.yaml | 1 - boards/panasonic/pan1783/pan1783a_evb_nrf5340_cpuapp.yaml | 1 - boards/panasonic/pan1783/pan1783a_pa_evb_nrf5340_cpuapp.yaml | 1 - boards/phytec/reel_board/reel_board_1.yaml | 1 - boards/phytec/reel_board/reel_board_nrf52840_2.yaml | 1 - boards/rak/rak4631/rak4631_nrf52840.yaml | 1 - boards/rak/rak5010/rak5010_nrf52840.yaml | 1 - boards/raytac/mdbt50q_db_33/raytac_mdbt50q_db_33_nrf52833.yaml | 1 - boards/raytac/mdbt50q_db_40/raytac_mdbt50q_db_40_nrf52840.yaml | 1 - .../raytac/mdbt53_db_40/raytac_mdbt53_db_40_nrf5340_cpuapp.yaml | 1 - .../mdbt53_db_40/raytac_mdbt53_db_40_nrf5340_cpuapp_ns.yaml | 1 - boards/seeed/wio_terminal/wio_terminal.yaml | 1 - boards/seeed/xiao_ble/xiao_ble.yaml | 1 - boards/seeed/xiao_ble/xiao_ble_nrf52840_sense.yaml | 1 - boards/st/nucleo_h745zi_q/nucleo_h745zi_q_stm32h745xx_m7.yaml | 1 - boards/st/stm32h747i_disco/stm32h747i_disco_stm32h747xx_m7.yaml | 1 - boards/u-blox/ubx_bmd340eval/ubx_bmd340eval_nrf52840.yaml | 1 - boards/u-blox/ubx_bmd345eval/ubx_bmd345eval_nrf52840.yaml | 1 - boards/u-blox/ubx_bmd380eval/ubx_bmd380eval_nrf52840.yaml | 1 - boards/u-blox/ubx_evkninab3/ubx_evkninab3_nrf52840.yaml | 1 - samples/subsys/usb/console/sample.yaml | 1 - 45 files changed, 45 deletions(-) diff --git a/boards/adafruit/feather/adafruit_feather_nrf52840.yaml b/boards/adafruit/feather/adafruit_feather_nrf52840.yaml index 487c78377a13b..332c29857db30 100644 --- a/boards/adafruit/feather/adafruit_feather_nrf52840.yaml +++ b/boards/adafruit/feather/adafruit_feather_nrf52840.yaml @@ -9,7 +9,6 @@ toolchain: supported: - adc - usb_device - - usb_cdc - ble - watchdog - counter diff --git a/boards/adafruit/itsybitsy/adafruit_itsybitsy_nrf52840.yaml b/boards/adafruit/itsybitsy/adafruit_itsybitsy_nrf52840.yaml index 3e571954bf1ab..9bf0ea72176c3 100644 --- a/boards/adafruit/itsybitsy/adafruit_itsybitsy_nrf52840.yaml +++ b/boards/adafruit/itsybitsy/adafruit_itsybitsy_nrf52840.yaml @@ -16,7 +16,6 @@ supported: - i2c - pwm - spi - - usb_cdc - usb_device - watchdog vendor: adafruit diff --git a/boards/arduino/giga_r1/arduino_giga_r1_stm32h747xx_m7.yaml b/boards/arduino/giga_r1/arduino_giga_r1_stm32h747xx_m7.yaml index cdcaeba7c77b2..b637d14017b44 100644 --- a/boards/arduino/giga_r1/arduino_giga_r1_stm32h747xx_m7.yaml +++ b/boards/arduino/giga_r1/arduino_giga_r1_stm32h747xx_m7.yaml @@ -14,6 +14,5 @@ supported: - arduino_spi - spi - memc - - usb_cdc - usb_device vendor: arduino diff --git a/boards/arduino/nano_33_ble/arduino_nano_33_ble.yaml b/boards/arduino/nano_33_ble/arduino_nano_33_ble.yaml index 733309555cb51..385d3bd1559cc 100644 --- a/boards/arduino/nano_33_ble/arduino_nano_33_ble.yaml +++ b/boards/arduino/nano_33_ble/arduino_nano_33_ble.yaml @@ -14,7 +14,6 @@ supported: - serial - spi - uart - - usb_cdc - usb_device - watchdog vendor: arduino diff --git a/boards/arduino/nano_33_ble/arduino_nano_33_ble_nrf52840_sense.yaml b/boards/arduino/nano_33_ble/arduino_nano_33_ble_nrf52840_sense.yaml index b8741e66b3575..6a80eaecf4814 100644 --- a/boards/arduino/nano_33_ble/arduino_nano_33_ble_nrf52840_sense.yaml +++ b/boards/arduino/nano_33_ble/arduino_nano_33_ble_nrf52840_sense.yaml @@ -14,7 +14,6 @@ supported: - serial - spi - uart - - usb_cdc - usb_device - watchdog vendor: arduino diff --git a/boards/atmel/sam0/samd21_xpro/samd21_xpro.yaml b/boards/atmel/sam0/samd21_xpro/samd21_xpro.yaml index d5e6a725003b5..c41c94432857c 100644 --- a/boards/atmel/sam0/samd21_xpro/samd21_xpro.yaml +++ b/boards/atmel/sam0/samd21_xpro/samd21_xpro.yaml @@ -20,7 +20,6 @@ supported: - pwm - spi - uart - - usb_cdc - usb_device - watchdog vendor: atmel diff --git a/boards/atmel/sam0/saml21_xpro/saml21_xpro.yaml b/boards/atmel/sam0/saml21_xpro/saml21_xpro.yaml index 3d531f6628718..be39f0dc5173e 100644 --- a/boards/atmel/sam0/saml21_xpro/saml21_xpro.yaml +++ b/boards/atmel/sam0/saml21_xpro/saml21_xpro.yaml @@ -20,7 +20,6 @@ supported: - pwm - spi - uart - - usb_cdc - usb_device - watchdog vendor: atmel diff --git a/boards/atmel/sam0/samr34_xpro/samr34_xpro.yaml b/boards/atmel/sam0/samr34_xpro/samr34_xpro.yaml index be66ff6cde536..488fba3bb324e 100644 --- a/boards/atmel/sam0/samr34_xpro/samr34_xpro.yaml +++ b/boards/atmel/sam0/samr34_xpro/samr34_xpro.yaml @@ -20,7 +20,6 @@ supported: - pwm - spi - uart - - usb_cdc - usb_device - watchdog vendor: atmel diff --git a/boards/lairdconnect/bl5340_dvk/bl5340_dvk_nrf5340_cpuapp.yaml b/boards/lairdconnect/bl5340_dvk/bl5340_dvk_nrf5340_cpuapp.yaml index 1b23d5f23ecb6..a4e91d78ab3f4 100644 --- a/boards/lairdconnect/bl5340_dvk/bl5340_dvk_nrf5340_cpuapp.yaml +++ b/boards/lairdconnect/bl5340_dvk/bl5340_dvk_nrf5340_cpuapp.yaml @@ -16,7 +16,6 @@ supported: - qspi - spi - uart - - usb_cdc - usb_device - watchdog vendor: lairdconnect diff --git a/boards/lairdconnect/bl5340_dvk/bl5340_dvk_nrf5340_cpuapp_ns.yaml b/boards/lairdconnect/bl5340_dvk/bl5340_dvk_nrf5340_cpuapp_ns.yaml index 087975c8d0da7..f9ad633de314b 100644 --- a/boards/lairdconnect/bl5340_dvk/bl5340_dvk_nrf5340_cpuapp_ns.yaml +++ b/boards/lairdconnect/bl5340_dvk/bl5340_dvk_nrf5340_cpuapp_ns.yaml @@ -15,7 +15,6 @@ supported: - pwm - spi - uart - - usb_cdc - usb_device - watchdog vendor: lairdconnect diff --git a/boards/lairdconnect/bl654_usb/bl654_usb.yaml b/boards/lairdconnect/bl654_usb/bl654_usb.yaml index 620275a516d5b..d927657dc7da7 100644 --- a/boards/lairdconnect/bl654_usb/bl654_usb.yaml +++ b/boards/lairdconnect/bl654_usb/bl654_usb.yaml @@ -8,7 +8,6 @@ toolchain: - xtools supported: - usb_device - - usb_cdc - ble - pwm - watchdog diff --git a/boards/lairdconnect/pinnacle_100_dvk/pinnacle_100_dvk.yaml b/boards/lairdconnect/pinnacle_100_dvk/pinnacle_100_dvk.yaml index 153fb6cab0863..c4bd8252d1947 100644 --- a/boards/lairdconnect/pinnacle_100_dvk/pinnacle_100_dvk.yaml +++ b/boards/lairdconnect/pinnacle_100_dvk/pinnacle_100_dvk.yaml @@ -16,7 +16,6 @@ supported: - i2c - pwm - spi - - usb_cdc - usb_device - watchdog - netif:modem diff --git a/boards/makerdiary/nrf52840_mdk_usb_dongle/nrf52840_mdk_usb_dongle.yaml b/boards/makerdiary/nrf52840_mdk_usb_dongle/nrf52840_mdk_usb_dongle.yaml index 5aac2cd57016e..e714e1cafb5ee 100644 --- a/boards/makerdiary/nrf52840_mdk_usb_dongle/nrf52840_mdk_usb_dongle.yaml +++ b/boards/makerdiary/nrf52840_mdk_usb_dongle/nrf52840_mdk_usb_dongle.yaml @@ -10,7 +10,6 @@ toolchain: - xtools supported: - usb_device - - usb_cdc - ble - watchdog - counter diff --git a/boards/nordic/nrf21540dk/nrf21540dk_nrf52840.yaml b/boards/nordic/nrf21540dk/nrf21540dk_nrf52840.yaml index a1bcc36e034d7..b84c5371d877b 100644 --- a/boards/nordic/nrf21540dk/nrf21540dk_nrf52840.yaml +++ b/boards/nordic/nrf21540dk/nrf21540dk_nrf52840.yaml @@ -18,7 +18,6 @@ supported: - i2c - pwm - spi - - usb_cdc - usb_device - watchdog - netif:openthread diff --git a/boards/nordic/nrf52840dk/nrf52840dk_nrf52840.yaml b/boards/nordic/nrf52840dk/nrf52840dk_nrf52840.yaml index 30a96d563c947..09723d66d5fde 100644 --- a/boards/nordic/nrf52840dk/nrf52840dk_nrf52840.yaml +++ b/boards/nordic/nrf52840dk/nrf52840dk_nrf52840.yaml @@ -21,7 +21,6 @@ supported: - i2s - pwm - spi - - usb_cdc - usb_device - watchdog - netif:openthread diff --git a/boards/nordic/nrf52840dongle/nrf52840dongle_nrf52840.yaml b/boards/nordic/nrf52840dongle/nrf52840dongle_nrf52840.yaml index 1e61b0e71e478..e5410c74c7111 100644 --- a/boards/nordic/nrf52840dongle/nrf52840dongle_nrf52840.yaml +++ b/boards/nordic/nrf52840dongle/nrf52840dongle_nrf52840.yaml @@ -11,7 +11,6 @@ toolchain: supported: - adc - usb_device - - usb_cdc - ble - pwm - spi 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 a4433e7e030cb..8d8e378179577 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 @@ -19,6 +19,5 @@ supported: - i2c - pwm - watchdog - - usb_cdc - usb_device vendor: nordic diff --git a/boards/nordic/nrf5340_audio_dk/nrf5340_audio_dk_nrf5340_cpuapp_ns.yaml b/boards/nordic/nrf5340_audio_dk/nrf5340_audio_dk_nrf5340_cpuapp_ns.yaml index 4194fc6357480..28a295758911b 100644 --- a/boards/nordic/nrf5340_audio_dk/nrf5340_audio_dk_nrf5340_cpuapp_ns.yaml +++ b/boards/nordic/nrf5340_audio_dk/nrf5340_audio_dk_nrf5340_cpuapp_ns.yaml @@ -14,6 +14,5 @@ supported: - spi - pwm - watchdog - - usb_cdc - usb_device vendor: nordic diff --git a/boards/nordic/nrf5340dk/nrf5340dk_nrf5340_cpuapp.yaml b/boards/nordic/nrf5340dk/nrf5340dk_nrf5340_cpuapp.yaml index 0a8bfabf5c468..c1e36526e1fec 100644 --- a/boards/nordic/nrf5340dk/nrf5340dk_nrf5340_cpuapp.yaml +++ b/boards/nordic/nrf5340dk/nrf5340dk_nrf5340_cpuapp.yaml @@ -14,7 +14,6 @@ supported: - i2s - pwm - watchdog - - usb_cdc - usb_device - netif:openthread - gpio diff --git a/boards/nordic/nrf5340dk/nrf5340dk_nrf5340_cpuapp_ns.yaml b/boards/nordic/nrf5340dk/nrf5340dk_nrf5340_cpuapp_ns.yaml index 4b311f76e25d6..664378db8872e 100644 --- a/boards/nordic/nrf5340dk/nrf5340dk_nrf5340_cpuapp_ns.yaml +++ b/boards/nordic/nrf5340dk/nrf5340dk_nrf5340_cpuapp_ns.yaml @@ -12,7 +12,6 @@ supported: - i2c - pwm - watchdog - - usb_cdc - usb_device - netif:openthread - gpio diff --git a/boards/nordic/thingy53/thingy53_nrf5340_cpuapp.yaml b/boards/nordic/thingy53/thingy53_nrf5340_cpuapp.yaml index fbc4eb335798a..bc3d8de14b639 100644 --- a/boards/nordic/thingy53/thingy53_nrf5340_cpuapp.yaml +++ b/boards/nordic/thingy53/thingy53_nrf5340_cpuapp.yaml @@ -13,7 +13,6 @@ supported: - i2c - pwm - watchdog - - usb_cdc - usb_device - netif:openthread vendor: nordic diff --git a/boards/nordic/thingy53/thingy53_nrf5340_cpuapp_ns.yaml b/boards/nordic/thingy53/thingy53_nrf5340_cpuapp_ns.yaml index b534406ea0760..a48325cb57f63 100644 --- a/boards/nordic/thingy53/thingy53_nrf5340_cpuapp_ns.yaml +++ b/boards/nordic/thingy53/thingy53_nrf5340_cpuapp_ns.yaml @@ -13,7 +13,6 @@ supported: - i2c - pwm - watchdog - - usb_cdc - usb_device - netif:openthread vendor: nordic diff --git a/boards/panasonic/pan1770_evb/pan1770_evb.yaml b/boards/panasonic/pan1770_evb/pan1770_evb.yaml index d19c0f4e33a5c..35ada5617cc54 100644 --- a/boards/panasonic/pan1770_evb/pan1770_evb.yaml +++ b/boards/panasonic/pan1770_evb/pan1770_evb.yaml @@ -25,7 +25,6 @@ supported: - i2s - pwm - spi - - usb_cdc - usb_device - watchdog - netif:openthread diff --git a/boards/panasonic/pan1780_evb/pan1780_evb.yaml b/boards/panasonic/pan1780_evb/pan1780_evb.yaml index 9f29b96007a7c..8833f01c3a233 100644 --- a/boards/panasonic/pan1780_evb/pan1780_evb.yaml +++ b/boards/panasonic/pan1780_evb/pan1780_evb.yaml @@ -25,7 +25,6 @@ supported: - i2s - pwm - spi - - usb_cdc - usb_device - watchdog - netif:openthread diff --git a/boards/panasonic/pan1783/pan1783_evb_nrf5340_cpuapp.yaml b/boards/panasonic/pan1783/pan1783_evb_nrf5340_cpuapp.yaml index 401745b33336b..771055b508a31 100644 --- a/boards/panasonic/pan1783/pan1783_evb_nrf5340_cpuapp.yaml +++ b/boards/panasonic/pan1783/pan1783_evb_nrf5340_cpuapp.yaml @@ -14,7 +14,6 @@ supported: - i2s - pwm - watchdog - - usb_cdc - usb_device - netif:openthread - gpio diff --git a/boards/panasonic/pan1783/pan1783a_evb_nrf5340_cpuapp.yaml b/boards/panasonic/pan1783/pan1783a_evb_nrf5340_cpuapp.yaml index f5a789788bfc2..3d9bea542288a 100644 --- a/boards/panasonic/pan1783/pan1783a_evb_nrf5340_cpuapp.yaml +++ b/boards/panasonic/pan1783/pan1783a_evb_nrf5340_cpuapp.yaml @@ -14,7 +14,6 @@ supported: - i2s - pwm - watchdog - - usb_cdc - usb_device - netif:openthread - gpio diff --git a/boards/panasonic/pan1783/pan1783a_pa_evb_nrf5340_cpuapp.yaml b/boards/panasonic/pan1783/pan1783a_pa_evb_nrf5340_cpuapp.yaml index dc5600a999a57..d9936750286a2 100644 --- a/boards/panasonic/pan1783/pan1783a_pa_evb_nrf5340_cpuapp.yaml +++ b/boards/panasonic/pan1783/pan1783a_pa_evb_nrf5340_cpuapp.yaml @@ -14,7 +14,6 @@ supported: - i2s - pwm - watchdog - - usb_cdc - usb_device - netif:openthread - gpio diff --git a/boards/phytec/reel_board/reel_board_1.yaml b/boards/phytec/reel_board/reel_board_1.yaml index 07b5087b6c6f5..b357f545511b1 100644 --- a/boards/phytec/reel_board/reel_board_1.yaml +++ b/boards/phytec/reel_board/reel_board_1.yaml @@ -13,7 +13,6 @@ supported: - spi - gpio - usb_device - - usb_cdc - ble - pwm - arduino_i2c diff --git a/boards/phytec/reel_board/reel_board_nrf52840_2.yaml b/boards/phytec/reel_board/reel_board_nrf52840_2.yaml index 7112c3fde8e16..e98f366b969e4 100644 --- a/boards/phytec/reel_board/reel_board_nrf52840_2.yaml +++ b/boards/phytec/reel_board/reel_board_nrf52840_2.yaml @@ -13,7 +13,6 @@ supported: - spi - gpio - usb_device - - usb_cdc - ble - pwm - arduino_i2c diff --git a/boards/rak/rak4631/rak4631_nrf52840.yaml b/boards/rak/rak4631/rak4631_nrf52840.yaml index 42c638ac35c71..f8b3e23582699 100644 --- a/boards/rak/rak4631/rak4631_nrf52840.yaml +++ b/boards/rak/rak4631/rak4631_nrf52840.yaml @@ -15,7 +15,6 @@ supported: - gpio - i2c - pwm - - usb_cdc - usb_device - watchdog - lora diff --git a/boards/rak/rak5010/rak5010_nrf52840.yaml b/boards/rak/rak5010/rak5010_nrf52840.yaml index 21b8e12297041..2b947436b2620 100644 --- a/boards/rak/rak5010/rak5010_nrf52840.yaml +++ b/boards/rak/rak5010/rak5010_nrf52840.yaml @@ -15,7 +15,6 @@ supported: - gpio - i2c - pwm - - usb_cdc - usb_device - watchdog vendor: rak diff --git a/boards/raytac/mdbt50q_db_33/raytac_mdbt50q_db_33_nrf52833.yaml b/boards/raytac/mdbt50q_db_33/raytac_mdbt50q_db_33_nrf52833.yaml index 673705fa1237b..e0698628e71a5 100644 --- a/boards/raytac/mdbt50q_db_33/raytac_mdbt50q_db_33_nrf52833.yaml +++ b/boards/raytac/mdbt50q_db_33/raytac_mdbt50q_db_33_nrf52833.yaml @@ -21,7 +21,6 @@ supported: - ieee802154 - pwm - spi - - usb_cdc - usb_device - watchdog - netif:openthread diff --git a/boards/raytac/mdbt50q_db_40/raytac_mdbt50q_db_40_nrf52840.yaml b/boards/raytac/mdbt50q_db_40/raytac_mdbt50q_db_40_nrf52840.yaml index 15ba012594ee8..cc99eab1a53a4 100644 --- a/boards/raytac/mdbt50q_db_40/raytac_mdbt50q_db_40_nrf52840.yaml +++ b/boards/raytac/mdbt50q_db_40/raytac_mdbt50q_db_40_nrf52840.yaml @@ -23,7 +23,6 @@ supported: - ieee802154 - pwm - spi - - usb_cdc - usb_device - watchdog - netif:openthread diff --git a/boards/raytac/mdbt53_db_40/raytac_mdbt53_db_40_nrf5340_cpuapp.yaml b/boards/raytac/mdbt53_db_40/raytac_mdbt53_db_40_nrf5340_cpuapp.yaml index f962784606bd3..44596dc8a5bc7 100644 --- a/boards/raytac/mdbt53_db_40/raytac_mdbt53_db_40_nrf5340_cpuapp.yaml +++ b/boards/raytac/mdbt53_db_40/raytac_mdbt53_db_40_nrf5340_cpuapp.yaml @@ -17,6 +17,5 @@ supported: - spi - uart - watchdog - - usb_cdc - usb_device - netif:openthread diff --git a/boards/raytac/mdbt53_db_40/raytac_mdbt53_db_40_nrf5340_cpuapp_ns.yaml b/boards/raytac/mdbt53_db_40/raytac_mdbt53_db_40_nrf5340_cpuapp_ns.yaml index 46fbe1ea1928e..d77e8d5c8f0f9 100644 --- a/boards/raytac/mdbt53_db_40/raytac_mdbt53_db_40_nrf5340_cpuapp_ns.yaml +++ b/boards/raytac/mdbt53_db_40/raytac_mdbt53_db_40_nrf5340_cpuapp_ns.yaml @@ -15,7 +15,6 @@ supported: - watchdog - spi - uart - - usb_cdc - usb_device - netif:openthread - gpio diff --git a/boards/seeed/wio_terminal/wio_terminal.yaml b/boards/seeed/wio_terminal/wio_terminal.yaml index e78e041719bc4..66a97ebefc01c 100644 --- a/boards/seeed/wio_terminal/wio_terminal.yaml +++ b/boards/seeed/wio_terminal/wio_terminal.yaml @@ -16,7 +16,6 @@ supported: - i2c - pwm - spi - - usb_cdc - usb_device - watchdog vendor: seeed diff --git a/boards/seeed/xiao_ble/xiao_ble.yaml b/boards/seeed/xiao_ble/xiao_ble.yaml index f8dfa743a86d0..3351b8f609e4d 100644 --- a/boards/seeed/xiao_ble/xiao_ble.yaml +++ b/boards/seeed/xiao_ble/xiao_ble.yaml @@ -17,7 +17,6 @@ supported: - i2s - pwm - spi - - usb_cdc - usb_device - watchdog - netif:openthread diff --git a/boards/seeed/xiao_ble/xiao_ble_nrf52840_sense.yaml b/boards/seeed/xiao_ble/xiao_ble_nrf52840_sense.yaml index dfb8bc4e8afb7..9de9481776ab7 100644 --- a/boards/seeed/xiao_ble/xiao_ble_nrf52840_sense.yaml +++ b/boards/seeed/xiao_ble/xiao_ble_nrf52840_sense.yaml @@ -17,7 +17,6 @@ supported: - i2s - pwm - spi - - usb_cdc - usb_device - watchdog - netif:openthread diff --git a/boards/st/nucleo_h745zi_q/nucleo_h745zi_q_stm32h745xx_m7.yaml b/boards/st/nucleo_h745zi_q/nucleo_h745zi_q_stm32h745xx_m7.yaml index 904e740e5edf4..06d192a68326b 100644 --- a/boards/st/nucleo_h745zi_q/nucleo_h745zi_q_stm32h745xx_m7.yaml +++ b/boards/st/nucleo_h745zi_q/nucleo_h745zi_q_stm32h745xx_m7.yaml @@ -17,6 +17,5 @@ supported: - i2c - pwm - netif:eth - - usb_cdc - usb_device vendor: st diff --git a/boards/st/stm32h747i_disco/stm32h747i_disco_stm32h747xx_m7.yaml b/boards/st/stm32h747i_disco/stm32h747i_disco_stm32h747xx_m7.yaml index e4b7d1b33345a..d566de9a4cad7 100644 --- a/boards/st/stm32h747i_disco/stm32h747i_disco_stm32h747xx_m7.yaml +++ b/boards/st/stm32h747i_disco/stm32h747i_disco_stm32h747xx_m7.yaml @@ -16,6 +16,5 @@ supported: - netif:eth - qspi - memc - - usb_cdc - usb_device vendor: st diff --git a/boards/u-blox/ubx_bmd340eval/ubx_bmd340eval_nrf52840.yaml b/boards/u-blox/ubx_bmd340eval/ubx_bmd340eval_nrf52840.yaml index be6ccd190a803..eeca79d1e5e43 100644 --- a/boards/u-blox/ubx_bmd340eval/ubx_bmd340eval_nrf52840.yaml +++ b/boards/u-blox/ubx_bmd340eval/ubx_bmd340eval_nrf52840.yaml @@ -20,7 +20,6 @@ supported: - pwm - spi - qspi - - usb_cdc - usb_device - watchdog - netif:openthread diff --git a/boards/u-blox/ubx_bmd345eval/ubx_bmd345eval_nrf52840.yaml b/boards/u-blox/ubx_bmd345eval/ubx_bmd345eval_nrf52840.yaml index fa53f794f09fa..f79940dbbbdf0 100644 --- a/boards/u-blox/ubx_bmd345eval/ubx_bmd345eval_nrf52840.yaml +++ b/boards/u-blox/ubx_bmd345eval/ubx_bmd345eval_nrf52840.yaml @@ -19,7 +19,6 @@ supported: - pwm - spi - qspi - - usb_cdc - usb_device - watchdog - netif:openthread diff --git a/boards/u-blox/ubx_bmd380eval/ubx_bmd380eval_nrf52840.yaml b/boards/u-blox/ubx_bmd380eval/ubx_bmd380eval_nrf52840.yaml index 15bb236585d4e..a794a4cac05ec 100644 --- a/boards/u-blox/ubx_bmd380eval/ubx_bmd380eval_nrf52840.yaml +++ b/boards/u-blox/ubx_bmd380eval/ubx_bmd380eval_nrf52840.yaml @@ -17,7 +17,6 @@ supported: - pwm - spi - qspi - - usb_cdc - usb_device - watchdog - netif:openthread diff --git a/boards/u-blox/ubx_evkninab3/ubx_evkninab3_nrf52840.yaml b/boards/u-blox/ubx_evkninab3/ubx_evkninab3_nrf52840.yaml index 90d292bc049e8..6e01ef035e8ee 100644 --- a/boards/u-blox/ubx_evkninab3/ubx_evkninab3_nrf52840.yaml +++ b/boards/u-blox/ubx_evkninab3/ubx_evkninab3_nrf52840.yaml @@ -18,7 +18,6 @@ supported: - i2c - pwm - spi - - usb_cdc - usb_device - watchdog - netif:openthread diff --git a/samples/subsys/usb/console/sample.yaml b/samples/subsys/usb/console/sample.yaml index 0a291d23a678a..4b590862b31fa 100644 --- a/samples/subsys/usb/console/sample.yaml +++ b/samples/subsys/usb/console/sample.yaml @@ -4,7 +4,6 @@ tests: sample.usb.console: depends_on: - usb_device - - usb_cdc tags: usb harness: console harness_config: From 5cfb4bd3f57530d8e00e945b51b45327036482e5 Mon Sep 17 00:00:00 2001 From: Arkadiusz Cholewinski Date: Mon, 20 May 2024 17:06:50 +0200 Subject: [PATCH 1307/2849] CI: Fix Coverage Analysis The coverage_analysis.py while generating report, duplicates files and functions of components. Signed-off-by: Arkadiusz Cholewinski --- scripts/ci/coverage/coverage_analysis.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/scripts/ci/coverage/coverage_analysis.py b/scripts/ci/coverage/coverage_analysis.py index 1d446aded7881..8238a5134e2be 100644 --- a/scripts/ci/coverage/coverage_analysis.py +++ b/scripts/ci/coverage/coverage_analysis.py @@ -274,7 +274,9 @@ def generate_json_report(self, coverage): "Name":i_fun['name'] } json_file['Uncovered_Functions'].append(json_uncovered_funciton) - json_files.append(json_file) + comp_exists = [x for x in json_files if x['Path'] == json_file['Path']] + if not comp_exists: + json_files.append(json_file) json_component['files']=json_files output_json['components'].append(json_component) else: From a9581c75d10573c53845c14aa4b5fe2e15403f3f Mon Sep 17 00:00:00 2001 From: Jeppe Odgaard Date: Thu, 16 May 2024 20:42:57 +0200 Subject: [PATCH 1308/2849] maintainers: add jeppenodgaard as sensor collaborator Add myself as collaborator to help with sensor PRs. Signed-off-by: Jeppe Odgaard --- MAINTAINERS.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/MAINTAINERS.yml b/MAINTAINERS.yml index 72a3da74d0293..3834b1768c66d 100644 --- a/MAINTAINERS.yml +++ b/MAINTAINERS.yml @@ -1818,6 +1818,7 @@ Release Notes: - yperess - tristan-google - ubieda + - jeppenodgaard files: - drivers/sensor/ - include/zephyr/drivers/sensor.h From 649d9d31af2c7c2033dcdf9b26a0bc01e851c96b Mon Sep 17 00:00:00 2001 From: Fredrik Gihl Date: Tue, 9 Apr 2024 19:39:14 +0200 Subject: [PATCH 1309/2849] drivers: w1: Ensure DQ pin is both input and output. Driver did not work on ESP32c3, by specifying pin to be output and input solve the issue. Improve documentation, to highlight that driver is requiring open-drain support. Signed-off-by: Fredrik Gihl --- drivers/w1/w1_zephyr_gpio.c | 2 +- dts/bindings/w1/zephyr,w1-gpio.yaml | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/w1/w1_zephyr_gpio.c b/drivers/w1/w1_zephyr_gpio.c index 1954436897585..bcab363494801 100644 --- a/drivers/w1/w1_zephyr_gpio.c +++ b/drivers/w1/w1_zephyr_gpio.c @@ -289,7 +289,7 @@ static int w1_gpio_init(const struct device *dev) if (gpio_is_ready_dt(spec)) { int ret = gpio_pin_configure_dt(spec, GPIO_OUTPUT_INACTIVE | GPIO_OPEN_DRAIN | - GPIO_PULL_UP); + GPIO_INPUT); if (ret < 0) { LOG_ERR("Failed to configure GPIO port %s pin %d", spec->port->name, spec->pin); diff --git a/dts/bindings/w1/zephyr,w1-gpio.yaml b/dts/bindings/w1/zephyr,w1-gpio.yaml index 46f4e684e01b7..d3b796f25c67f 100644 --- a/dts/bindings/w1/zephyr,w1-gpio.yaml +++ b/dts/bindings/w1/zephyr,w1-gpio.yaml @@ -19,6 +19,12 @@ description: | - w1 is pin 13 on gpio0. The gpio is active when the pin is high, is configured as an open-drain, and has a pull-up resistor. + Implementation details: + - Most drivers require the selected gpio to support open drain, this enables onewire + devices to lower the signal when the SOC set the signal high. + - Ensure pullup is strong enough (4.7K according to the specification). Standard pullup in + SOC are usually weak, and may not be strong enough. + compatible: "zephyr,w1-gpio" include: [w1-master.yaml] From 9baf77dd399cd96df5dea9b23f43211293bdb4e8 Mon Sep 17 00:00:00 2001 From: Ethan Lu Date: Mon, 27 May 2024 16:13:36 +1000 Subject: [PATCH 1310/2849] sensor: ms5837: fix compensate parameters for 30BA variant The previous parameters seems wrong if we refer to: https://www.te.com/usa-en/product-CAT-BLPS0017.html Signed-off-by: Ethan Lu --- drivers/sensor/meas/ms5837/ms5837.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/sensor/meas/ms5837/ms5837.c b/drivers/sensor/meas/ms5837/ms5837.c index 9e1cdbfd7d078..d07d23071aa54 100644 --- a/drivers/sensor/meas/ms5837/ms5837.c +++ b/drivers/sensor/meas/ms5837/ms5837.c @@ -75,17 +75,17 @@ static void ms5837_compensate_30(const struct device *dev, temp_sq = (int64_t)(data->temperature - 2000) * (data->temperature - 2000); if (data->temperature < 2000) { - Ti = (3ll * dT * dT) / (1ll << 23); - OFFi = (3ll * temp_sq) / 1ll; + Ti = (3ll * dT * dT) / (1ll << 33); + OFFi = (3ll * temp_sq) / (1ll << 1); SENSi = (5ll * temp_sq) / (1ll << 3); if (data->temperature < -1500) { temp_sq = (data->temperature + 1500) * (data->temperature + 1500); OFFi += 7ll * temp_sq; - SENSi += 5ll * temp_sq; + SENSi += 4ll * temp_sq; } } else { - Ti = (1ll * dT * dT) / (1ll << 37); + Ti = (2ll * dT * dT) / (1ll << 37); OFFi = temp_sq / (1ll << 4); SENSi = 0; } From 25138ff99c2a9f5958344a88f6cb146ec02cf85f Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Tue, 6 Feb 2024 15:22:45 +0000 Subject: [PATCH 1311/2849] storeage/stream_flash: Cache write_block_size to ctx on init The commit caches write_block_size and erase_value to stream flash context, at init, to avoid calling Flash API multiple times to get these values at various stages of code exectuion, at run-time. Signed-off-by: Dominik Ermel --- include/zephyr/storage/stream_flash.h | 2 ++ subsys/storage/stream/stream_flash.c | 14 ++++++++++---- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/include/zephyr/storage/stream_flash.h b/include/zephyr/storage/stream_flash.h index 40787d773d52a..6d969105b6eac 100644 --- a/include/zephyr/storage/stream_flash.h +++ b/include/zephyr/storage/stream_flash.h @@ -65,6 +65,8 @@ struct stream_flash_ctx { #ifdef CONFIG_STREAM_FLASH_ERASE off_t last_erased_page_start_offset; /* Last erased offset */ #endif + uint8_t erase_value; + uint8_t write_block_size; /* Offset/size device write alignment */ }; /** diff --git a/subsys/storage/stream/stream_flash.c b/subsys/storage/stream/stream_flash.c index 282b58f1eb903..e9b1a3dbc2722 100644 --- a/subsys/storage/stream/stream_flash.c +++ b/subsys/storage/stream/stream_flash.c @@ -128,10 +128,10 @@ static int flash_sync(struct stream_flash_ctx *ctx) } } - fill_length = flash_get_write_block_size(ctx->fdev); + fill_length = ctx->write_block_size; if (ctx->buf_bytes % fill_length) { fill_length -= ctx->buf_bytes % fill_length; - filler = flash_get_parameters(ctx->fdev)->erase_value; + filler = ctx->erase_value; memset(ctx->buf + ctx->buf_bytes, filler, fill_length); } else { @@ -249,6 +249,7 @@ int stream_flash_init(struct stream_flash_ctx *ctx, const struct device *fdev, uint8_t *buf, size_t buf_len, size_t offset, size_t size, stream_flash_callback_t cb) { + const struct flash_parameters *params; if (!ctx || !fdev || !buf) { return -EFAULT; } @@ -267,7 +268,10 @@ int stream_flash_init(struct stream_flash_ctx *ctx, const struct device *fdev, .total_size = 0 }; - if (buf_len % flash_get_write_block_size(fdev)) { + params = flash_get_parameters(fdev); + ctx->write_block_size = params->write_block_size; + + if (buf_len % ctx->write_block_size) { LOG_ERR("Buffer size is not aligned to minimal write-block-size"); return -EFAULT; } @@ -281,11 +285,12 @@ int stream_flash_init(struct stream_flash_ctx *ctx, const struct device *fdev, } if ((offset + size) > inspect_flash_ctx.total_size || - offset % flash_get_write_block_size(fdev)) { + offset % ctx->write_block_size) { LOG_ERR("Incorrect parameter"); return -EFAULT; } + ctx->fdev = fdev; ctx->buf = buf; ctx->buf_len = buf_len; @@ -299,6 +304,7 @@ int stream_flash_init(struct stream_flash_ctx *ctx, const struct device *fdev, #ifdef CONFIG_STREAM_FLASH_ERASE ctx->last_erased_page_start_offset = -1; #endif + ctx->erase_value = params->erase_value; return 0; } From 602c99379939af804906621ba97e7ea944310139 Mon Sep 17 00:00:00 2001 From: Yong Cong Sin Date: Sun, 26 May 2024 16:00:05 +0800 Subject: [PATCH 1312/2849] arch: riscv: stacktrace: fix cpuid type and optimize branch with compiler Change the type of `cpu_id` to `uint8_t` since that is the type of `arch_curr_cpu()->id`. Instead of using precompiler switch (`#ifdef CONFIG_SMP`), use if-else shorthand instead (`IS_ENABLED(CONFIG_SMP)`). Signed-off-by: Yong Cong Sin --- arch/riscv/core/stacktrace.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/arch/riscv/core/stacktrace.c b/arch/riscv/core/stacktrace.c index 9c6c013efaecc..ed0d4c1ba4709 100644 --- a/arch/riscv/core/stacktrace.c +++ b/arch/riscv/core/stacktrace.c @@ -49,13 +49,7 @@ static bool in_stack_bound(uintptr_t addr) 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 + uint8_t cpu_id = IS_ENABLED(CONFIG_SMP) ? arch_curr_cpu()->id : 0U; start = (uintptr_t)K_KERNEL_STACK_BUFFER(z_interrupt_stacks[cpu_id]); end = start + CONFIG_ISR_STACK_SIZE; From 6e8d9793365f23ac2ccfda30a8375a515937d4c6 Mon Sep 17 00:00:00 2001 From: Yong Cong Sin Date: Sun, 26 May 2024 16:02:26 +0800 Subject: [PATCH 1313/2849] arch: riscv: stacktrace: handle user threads Handle user threads stack bound validation in `in_stack_bound()` to get more accurate traces. If `CONFIG_PMP_POWER_OF_TWO_ALIGNMENT` is enabled: ``` +------------+ <- thread.arch.priv_stack_start | Guard | } Z_RISCV_STACK_GUARD_SIZE +------------+ | Priv Stack | } CONFIG_PRIVILEGED_STACK_SIZE +------------+ <- thread.arch.priv_stack_start + CONFIG_PRIVILEGED_STACK_SIZE + Z_RISCV_STACK_GUARD_SIZE ``` otherwise: ``` +------------+ <- thread.stack_obj | Guard | } Z_RISCV_STACK_GUARD_SIZE +------------+ | Priv Stack | } CONFIG_PRIVILEGED_STACK_SIZE +------------+ <- thread.stack_info.start | Thread | | stack | | | +............| | TLS | } thread.stack_info.delta +------------+ <- thread.stack_info.start + thread.stack_info.size ``` See: zephyr/include/zephyr/arch/riscv/arch.h Signed-off-by: Yong Cong Sin --- arch/riscv/core/stacktrace.c | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/arch/riscv/core/stacktrace.c b/arch/riscv/core/stacktrace.c index ed0d4c1ba4709..bc0063b3887fe 100644 --- a/arch/riscv/core/stacktrace.c +++ b/arch/riscv/core/stacktrace.c @@ -42,7 +42,7 @@ struct stackframe { LOG_ERR(" %2d: " SFP_FMT PR_REG " ra: " PR_REG, idx, sfp, ra) #endif -static bool in_stack_bound(uintptr_t addr) +static bool in_stack_bound(uintptr_t addr, const z_arch_esf_t *esf) { #ifdef CONFIG_THREAD_STACK_INFO uintptr_t start, end; @@ -54,8 +54,17 @@ static bool in_stack_bound(uintptr_t addr) 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 if (((esf->mstatus & MSTATUS_MPP) == PRV_U) && + ((_current->base.user_options & K_USER) != 0)) { + /* See: zephyr/include/zephyr/arch/riscv/arch.h */ + if (IS_ENABLED(CONFIG_PMP_POWER_OF_TWO_ALIGNMENT)) { + start = _current->arch.priv_stack_start - CONFIG_PRIVILEGED_STACK_SIZE; + end = _current->arch.priv_stack_start; + } else { + start = _current->stack_info.start - CONFIG_PRIVILEGED_STACK_SIZE; + end = _current->stack_info.start; + } +#endif /* CONFIG_USERSPACE */ } else { start = _current->stack_info.start; end = Z_STACK_PTR_ALIGN(_current->stack_info.start + _current->stack_info.size); @@ -64,6 +73,7 @@ static bool in_stack_bound(uintptr_t addr) return (addr >= start) && (addr < end); #else ARG_UNUSED(addr); + ARG_UNUSED(esf); return true; #endif /* CONFIG_THREAD_STACK_INFO */ } @@ -84,7 +94,7 @@ void z_riscv_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(fp);) { + for (int i = 0; (i < MAX_STACK_FRAMES) && (fp != 0U) && in_stack_bound(fp, esf);) { frame = (struct stackframe *)fp - 1; ra = frame->ra; if (in_text_region(ra)) { @@ -113,8 +123,8 @@ void z_riscv_unwind_stack(const z_arch_esf_t *esf) LOG_ERR("call trace:"); - for (int i = 0; - (i < MAX_STACK_FRAMES) && ((uintptr_t)ksp != 0U) && in_stack_bound((uintptr_t)ksp); + for (int i = 0; (i < MAX_STACK_FRAMES) && ((uintptr_t)ksp != 0U) && + in_stack_bound((uintptr_t)ksp, esf); ksp++) { ra = *ksp; if (in_text_region(ra)) { From 3efdbe6c0c8c01149e707711d6cfeac03c1f1e40 Mon Sep 17 00:00:00 2001 From: Tomi Fontanilles Date: Fri, 24 May 2024 15:09:02 +0300 Subject: [PATCH 1314/2849] modules: mbedtls: rename CONFIG_MBEDTLS_MAC_*_ENABLED and rm duplicates Remove the `_MAC` part because those Kconfig options enable only hash algorithms, nothing MAC-related, and the `_ENABLED` part to align the naming to the Mbed TLS defines (plus we don't need such a part). As a bonus, enabling SHA-256 does not automatically enable SHA-224 anymore. See the migration guide entries for more details on the practical changes. Signed-off-by: Tomi Fontanilles --- doc/releases/migration-guide-3.7.rst | 8 ++ drivers/crypto/Kconfig | 2 +- drivers/wifi/esp32/Kconfig.esp32 | 2 +- modules/hostap/Kconfig | 2 +- modules/mbedtls/Kconfig.tls-generic | 94 ++++++++----------- modules/mbedtls/configs/config-tls-generic.h | 24 ++--- samples/net/sockets/http_get/overlay-tls.conf | 3 +- subsys/mgmt/mcumgr/grp/fs_mgmt/CMakeLists.txt | 2 +- subsys/mgmt/mcumgr/grp/fs_mgmt/Kconfig | 2 +- subsys/net/l2/openthread/Kconfig | 4 +- subsys/net/lib/websocket/Kconfig | 2 +- subsys/storage/flash_map/Kconfig | 2 +- tests/benchmarks/mbedtls/prj.conf | 3 +- tests/net/socket/tls/prj.conf | 3 +- tests/subsys/mgmt/mcumgr/all_options/prj.conf | 2 +- .../configuration/all.conf | 2 +- .../configuration/sha256.conf | 2 +- 17 files changed, 77 insertions(+), 82 deletions(-) diff --git a/doc/releases/migration-guide-3.7.rst b/doc/releases/migration-guide-3.7.rst index 547268260be35..5a4402325f416 100644 --- a/doc/releases/migration-guide-3.7.rst +++ b/doc/releases/migration-guide-3.7.rst @@ -81,6 +81,14 @@ 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. +* The Kconfig options previously named `CONFIG_MBEDTLS_MAC_*_ENABLED` have been renamed. + The `_MAC` and `_ENABLED` parts have been removed from their names. +* The :kconfig:option:`CONFIG_MBEDTLS_HASH_ALL_ENABLED` Kconfig option has been fixed to actually + enable all the available hash algorithms. Previously, it used to only enable the SHA-2 ones. +* The `CONFIG_MBEDTLS_HASH_SHA*_ENABLED` Kconfig options have been removed. They were duplicates + of other Kconfig options which are now named `CONFIG_MBEDTLS_SHA*`. +* The `CONFIG_MBEDTLS_MAC_ALL_ENABLED` Kconfig option has been removed. Its equivalent is the + combination of :kconfig:option:`CONFIG_MBEDTLS_HASH_ALL_ENABLED` and :kconfig:option:`CONFIG_MBEDTLS_CMAC`. MCUboot ======= diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig index 451a524c810fc..27c35c9b1235d 100644 --- a/drivers/crypto/Kconfig +++ b/drivers/crypto/Kconfig @@ -52,7 +52,7 @@ config CRYPTO_MBEDTLS_SHIM bool "MbedTLS shim driver [EXPERIMENTAL]" select MBEDTLS select MBEDTLS_ENABLE_HEAP - select MBEDTLS_MAC_SHA512_ENABLED + select MBEDTLS_SHA512 select EXPERIMENTAL help Enable mbedTLS shim layer compliant with crypto APIs. You will need diff --git a/drivers/wifi/esp32/Kconfig.esp32 b/drivers/wifi/esp32/Kconfig.esp32 index 7760668b0bd21..2805f5b2ce48f 100644 --- a/drivers/wifi/esp32/Kconfig.esp32 +++ b/drivers/wifi/esp32/Kconfig.esp32 @@ -269,7 +269,7 @@ config ESP32_WIFI_MBEDTLS_CRYPTO select MBEDTLS_PKCS5_C select MBEDTLS_PK_WRITE_C select MBEDTLS_CIPHER_MODE_CTR_ENABLED - select MBEDTLS_MAC_CMAC_ENABLED + select MBEDTLS_CMAC select MBEDTLS_ZEPHYR_ENTROPY help Select this option to use MbedTLS crypto APIs which utilize hardware acceleration. diff --git a/modules/hostap/Kconfig b/modules/hostap/Kconfig index 473b6278055cf..490e70c0c7d67 100644 --- a/modules/hostap/Kconfig +++ b/modules/hostap/Kconfig @@ -114,7 +114,7 @@ config WIFI_NM_WPA_SUPPLICANT_CRYPTO select MBEDTLS_CIPHER_MODE_CBC_ENABLED select MBEDTLS_ECP_C select MBEDTLS_ECP_ALL_ENABLED - select MBEDTLS_MAC_CMAC_ENABLED + select MBEDTLS_CMAC select MBEDTLS_PKCS5_C select MBEDTLS_PK_WRITE_C select MBEDTLS_ECDH_C diff --git a/modules/mbedtls/Kconfig.tls-generic b/modules/mbedtls/Kconfig.tls-generic index b692c18e32359..c0a6fade6b992 100644 --- a/modules/mbedtls/Kconfig.tls-generic +++ b/modules/mbedtls/Kconfig.tls-generic @@ -12,15 +12,15 @@ menu "Supported TLS version" config MBEDTLS_TLS_VERSION_1_0 bool "Support for TLS 1.0" select MBEDTLS_CIPHER - select MBEDTLS_MAC_MD5_ENABLED - select MBEDTLS_MAC_SHA1_ENABLED + select MBEDTLS_MD5 + select MBEDTLS_SHA1 select MBEDTLS_MD config MBEDTLS_TLS_VERSION_1_1 bool "Support for TLS 1.1 (DTLS 1.0)" select MBEDTLS_CIPHER - select MBEDTLS_MAC_MD5_ENABLED - select MBEDTLS_MAC_SHA1_ENABLED + select MBEDTLS_MD5 + select MBEDTLS_SHA1 select MBEDTLS_MD config MBEDTLS_TLS_VERSION_1_2 @@ -206,25 +206,7 @@ config MBEDTLS_ECP_NIST_OPTIM endif -comment "Supported hash" - -config MBEDTLS_HASH_ALL_ENABLED - bool "All available hashes" - select MBEDTLS_HASH_SHA256_ENABLED - select MBEDTLS_HASH_SHA384_ENABLED - select MBEDTLS_HASH_SHA512_ENABLED - -config MBEDTLS_HASH_SHA256_ENABLED - bool "SHA224 and SHA256 hashes" - -config MBEDTLS_HASH_SHA384_ENABLED - bool "SHA384 hash" - select MBEDTLS_HASH_SHA512_ENABLED - -config MBEDTLS_HASH_SHA512_ENABLED - bool "SHA512 hash" - -comment "Supported cipher modes" +comment "Supported ciphers and cipher modes" config MBEDTLS_CIPHER_ALL_ENABLED bool "All available ciphers" @@ -297,55 +279,57 @@ config MBEDTLS_CIPHER_MODE_CTR_ENABLED config MBEDTLS_CHACHAPOLY_AEAD_ENABLED bool "ChaCha20-Poly1305 AEAD algorithm" - depends on MBEDTLS_CIPHER_CHACHA20_ENABLED || MBEDTLS_MAC_POLY1305_ENABLED + depends on MBEDTLS_CIPHER_CHACHA20_ENABLED && MBEDTLS_POLY1305 + +config MBEDTLS_CMAC + bool "CMAC (Cipher-based Message Authentication Code) mode for block ciphers." + depends on MBEDTLS_CIPHER_AES_ENABLED || MBEDTLS_CIPHER_DES_ENABLED -comment "Supported message authentication methods" +comment "Supported hash algorithms" -config MBEDTLS_MAC_ALL_ENABLED +config MBEDTLS_HASH_ALL_ENABLED bool "All available MAC methods" - select MBEDTLS_MAC_MD4_ENABLED - select MBEDTLS_MAC_MD5_ENABLED - select MBEDTLS_MAC_SHA1_ENABLED - select MBEDTLS_MAC_SHA256_ENABLED - select MBEDTLS_MAC_SHA384_ENABLED - select MBEDTLS_MAC_SHA512_ENABLED - select MBEDTLS_MAC_POLY1305_ENABLED - select MBEDTLS_MAC_CMAC_ENABLED - -config MBEDTLS_MAC_MD4_ENABLED + select MBEDTLS_MD4 + select MBEDTLS_MD5 + select MBEDTLS_SHA1 + select MBEDTLS_SHA224 + select MBEDTLS_SHA256 + select MBEDTLS_SHA384 + select MBEDTLS_SHA512 + select MBEDTLS_POLY1305 + +config MBEDTLS_MD4 bool "MD4 hash algorithm" -config MBEDTLS_MAC_MD5_ENABLED +config MBEDTLS_MD5 bool "MD5 hash algorithm" -config MBEDTLS_MAC_SHA1_ENABLED - bool "SHA1 hash algorithm" +config MBEDTLS_SHA1 + bool "SHA-1 hash algorithm" + +config MBEDTLS_SHA224 + bool "SHA-224 hash algorithm" -config MBEDTLS_MAC_SHA256_ENABLED - bool "SHA-224 and SHA-256 hash algorithms" +config MBEDTLS_SHA256 + bool "SHA-256 hash algorithm" default y config MBEDTLS_SHA256_SMALLER bool "Smaller SHA-256 implementation" - depends on MBEDTLS_MAC_SHA256_ENABLED + depends on MBEDTLS_SHA256 default y help - Enable an implementation of SHA-256 that has lower ROM footprint but also - lower performance + Enable an implementation of SHA-256 that has a + smaller ROM footprint but also lower performance. -config MBEDTLS_MAC_SHA384_ENABLED +config MBEDTLS_SHA384 bool "SHA-384 hash algorithm" - select MBEDTLS_MAC_SHA512_ENABLED -config MBEDTLS_MAC_SHA512_ENABLED +config MBEDTLS_SHA512 bool "SHA-512 hash algorithm" -config MBEDTLS_MAC_POLY1305_ENABLED - bool "Poly1305 MAC algorithm" - -config MBEDTLS_MAC_CMAC_ENABLED - bool "CMAC (Cipher-based Message Authentication Code) mode for block ciphers." - depends on MBEDTLS_CIPHER_AES_ENABLED || MBEDTLS_CIPHER_DES_ENABLED +config MBEDTLS_POLY1305 + bool "Poly1305 hash family" endmenu @@ -387,7 +371,7 @@ config MBEDTLS_HAVE_ASM config MBEDTLS_ENTROPY_ENABLED bool "MbedTLS generic entropy pool" - depends on MBEDTLS_MAC_SHA256_ENABLED || MBEDTLS_MAC_SHA384_ENABLED || MBEDTLS_MAC_SHA512_ENABLED + depends on MBEDTLS_SHA256 || MBEDTLS_SHA384 || MBEDTLS_SHA512 default y if MBEDTLS_ZEPHYR_ENTROPY config MBEDTLS_OPENTHREAD_OPTIMIZATIONS_ENABLED @@ -502,7 +486,7 @@ config MBEDTLS_PSA_CRYPTO_CLIENT config MBEDTLS_LMS bool "Support LMS signature schemes" depends on MBEDTLS_PSA_CRYPTO_CLIENT - depends on MBEDTLS_HASH_SHA256_ENABLED + depends on MBEDTLS_SHA256 select PSA_WANT_ALG_SHA_256 config MBEDTLS_SSL_DTLS_CONNECTION_ID diff --git a/modules/mbedtls/configs/config-tls-generic.h b/modules/mbedtls/configs/config-tls-generic.h index 45bc81f35f20c..c9f01db9bed5c 100644 --- a/modules/mbedtls/configs/config-tls-generic.h +++ b/modules/mbedtls/configs/config-tls-generic.h @@ -271,23 +271,25 @@ #define MBEDTLS_ECP_NIST_OPTIM #endif -/* Supported message authentication methods */ +/* Supported hash algorithms */ -#if defined(CONFIG_MBEDTLS_MAC_MD4_ENABLED) +#if defined(CONFIG_MBEDTLS_MD4) #define MBEDTLS_MD4_C #endif -#if defined(CONFIG_MBEDTLS_MAC_MD5_ENABLED) +#if defined(CONFIG_MBEDTLS_MD5) #define MBEDTLS_MD5_C #endif -#if defined(CONFIG_MBEDTLS_MAC_SHA1_ENABLED) +#if defined(CONFIG_MBEDTLS_SHA1) #define MBEDTLS_SHA1_C #endif -#if defined(CONFIG_MBEDTLS_MAC_SHA256_ENABLED) || \ - defined(CONFIG_MBEDTLS_HASH_SHA256_ENABLED) +#if defined(CONFIG_MBEDTLS_SHA224) #define MBEDTLS_SHA224_C +#endif + +#if defined(CONFIG_MBEDTLS_SHA256) #define MBEDTLS_SHA256_C #endif @@ -295,21 +297,19 @@ #define MBEDTLS_SHA256_SMALLER #endif -#if defined(CONFIG_MBEDTLS_MAC_SHA384_ENABLED) || \ - defined(CONFIG_MBEDTLS_HASH_SHA384_ENABLED) +#if defined(CONFIG_MBEDTLS_SHA384) #define MBEDTLS_SHA384_C #endif -#if defined(CONFIG_MBEDTLS_MAC_SHA512_ENABLED) || \ - defined(CONFIG_MBEDTLS_HASH_SHA512_ENABLED) +#if defined(CONFIG_MBEDTLS_SHA512) #define MBEDTLS_SHA512_C #endif -#if defined(CONFIG_MBEDTLS_MAC_POLY1305_ENABLED) +#if defined(CONFIG_MBEDTLS_POLY1305) #define MBEDTLS_POLY1305_C #endif -#if defined(CONFIG_MBEDTLS_MAC_CMAC_ENABLED) +#if defined(CONFIG_MBEDTLS_CMAC) #define MBEDTLS_CMAC_C #endif diff --git a/samples/net/sockets/http_get/overlay-tls.conf b/samples/net/sockets/http_get/overlay-tls.conf index 29bfc2372f853..0cf82f18cf857 100644 --- a/samples/net/sockets/http_get/overlay-tls.conf +++ b/samples/net/sockets/http_get/overlay-tls.conf @@ -6,6 +6,7 @@ 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_MBEDTLS_HASH_ALL_ENABLED=y +CONFIG_MBEDTLS_CMAC=y CONFIG_NET_SOCKETS_SOCKOPT_TLS=y diff --git a/subsys/mgmt/mcumgr/grp/fs_mgmt/CMakeLists.txt b/subsys/mgmt/mcumgr/grp/fs_mgmt/CMakeLists.txt index f25495d667c48..cd09c59d7a6aa 100644 --- a/subsys/mgmt/mcumgr/grp/fs_mgmt/CMakeLists.txt +++ b/subsys/mgmt/mcumgr/grp/fs_mgmt/CMakeLists.txt @@ -15,7 +15,7 @@ zephyr_library_sources_ifdef(CONFIG_MCUMGR_GRP_FS_CHECKSUM_IEEE_CRC32 src/fs_mgm zephyr_library_sources_ifdef(CONFIG_MCUMGR_GRP_FS_HASH_SHA256 src/fs_mgmt_hash_checksum_sha256.c) if(CONFIG_MCUMGR_GRP_FS_CHECKSUM_HASH AND CONFIG_MCUMGR_GRP_FS_HASH_SHA256) - if(CONFIG_MBEDTLS_MAC_SHA256_ENABLED) + if(CONFIG_MBEDTLS_SHA256) zephyr_library_link_libraries(mbedTLS) endif() endif() diff --git a/subsys/mgmt/mcumgr/grp/fs_mgmt/Kconfig b/subsys/mgmt/mcumgr/grp/fs_mgmt/Kconfig index 2bb7e74fb6309..013697225fcd4 100644 --- a/subsys/mgmt/mcumgr/grp/fs_mgmt/Kconfig +++ b/subsys/mgmt/mcumgr/grp/fs_mgmt/Kconfig @@ -125,7 +125,7 @@ config MCUMGR_GRP_FS_CHECKSUM_IEEE_CRC32 config MCUMGR_GRP_FS_HASH_SHA256 bool "SHA256 hash support" - depends on BUILD_WITH_TFM || MBEDTLS_MAC_SHA256_ENABLED + depends on BUILD_WITH_TFM || MBEDTLS_SHA256 select PSA_WANT_ALG_SHA_256 if BUILD_WITH_TFM help Enable SHA256 hash support for MCUmgr. diff --git a/subsys/net/l2/openthread/Kconfig b/subsys/net/l2/openthread/Kconfig index c75af2c5c255d..de7fb4a3aaa4e 100644 --- a/subsys/net/l2/openthread/Kconfig +++ b/subsys/net/l2/openthread/Kconfig @@ -181,9 +181,9 @@ config OPENTHREAD_MBEDTLS select MBEDTLS_ENABLE_HEAP select MBEDTLS_CIPHER_AES_ENABLED select MBEDTLS_CIPHER_CCM_ENABLED - select MBEDTLS_MAC_SHA256_ENABLED + select MBEDTLS_SHA256 select MBEDTLS_ENTROPY_ENABLED - select MBEDTLS_MAC_CMAC_ENABLED + select MBEDTLS_CMAC select MBEDTLS_CIPHER select MBEDTLS_MD select MBEDTLS_TLS_VERSION_1_2 if OPENTHREAD_COMMISSIONER || OPENTHREAD_JOINER diff --git a/subsys/net/lib/websocket/Kconfig b/subsys/net/lib/websocket/Kconfig index 20f6ca6b1fe35..c3aa3470f4421 100644 --- a/subsys/net/lib/websocket/Kconfig +++ b/subsys/net/lib/websocket/Kconfig @@ -9,7 +9,7 @@ config WEBSOCKET_CLIENT select HTTP_CLIENT select MBEDTLS select BASE64 - select MBEDTLS_MAC_SHA1_ENABLED if MBEDTLS_BUILTIN + select MBEDTLS_SHA1 if MBEDTLS_BUILTIN select EXPERIMENTAL help Enable Websocket client library. diff --git a/subsys/storage/flash_map/Kconfig b/subsys/storage/flash_map/Kconfig index 4c2d230e121c7..cbe5c1599b329 100644 --- a/subsys/storage/flash_map/Kconfig +++ b/subsys/storage/flash_map/Kconfig @@ -58,7 +58,7 @@ config FLASH_AREA_CHECK_INTEGRITY_MBEDTLS bool "Use MBEDTLS" select MBEDTLS select MBEDTLS_MD - select MBEDTLS_MAC_SHA256_ENABLED + select MBEDTLS_SHA256 select MBEDTLS_ENABLE_HEAP help Use MBEDTLS library to perform the integrity check. diff --git a/tests/benchmarks/mbedtls/prj.conf b/tests/benchmarks/mbedtls/prj.conf index 6339cd45b1736..ffc9e160d8e57 100644 --- a/tests/benchmarks/mbedtls/prj.conf +++ b/tests/benchmarks/mbedtls/prj.conf @@ -21,7 +21,8 @@ CONFIG_MBEDTLS_TLS_VERSION_1_2=y CONFIG_MBEDTLS_KEY_EXCHANGE_ALL_ENABLED=y CONFIG_MBEDTLS_CIPHER_ALL_ENABLED=y CONFIG_MBEDTLS_ECP_ALL_ENABLED=y -CONFIG_MBEDTLS_MAC_ALL_ENABLED=y +CONFIG_MBEDTLS_HASH_ALL_ENABLED=y +CONFIG_MBEDTLS_CMAC=y CONFIG_MBEDTLS_GENPRIME_ENABLED=y CONFIG_MBEDTLS_HMAC_DRBG_ENABLED=y CONFIG_MBEDTLS_ECDH_C=y diff --git a/tests/net/socket/tls/prj.conf b/tests/net/socket/tls/prj.conf index 94fb56a7142d4..514dc114925d5 100644 --- a/tests/net/socket/tls/prj.conf +++ b/tests/net/socket/tls/prj.conf @@ -47,4 +47,5 @@ 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 +CONFIG_MBEDTLS_HASH_ALL_ENABLED=y +CONFIG_MBEDTLS_CMAC=y diff --git a/tests/subsys/mgmt/mcumgr/all_options/prj.conf b/tests/subsys/mgmt/mcumgr/all_options/prj.conf index ed584f347629c..ba15113a9239c 100644 --- a/tests/subsys/mgmt/mcumgr/all_options/prj.conf +++ b/tests/subsys/mgmt/mcumgr/all_options/prj.conf @@ -5,7 +5,7 @@ # CONFIG_ZTEST=y CONFIG_MBEDTLS=y -CONFIG_MBEDTLS_MAC_SHA256_ENABLED=y +CONFIG_MBEDTLS_SHA256=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 53b017ba80a96..eff5b71007f86 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 @@ -6,4 +6,4 @@ CONFIG_MCUMGR_GRP_FS_CHECKSUM_IEEE_CRC32=y CONFIG_MCUMGR_GRP_FS_HASH_SHA256=y CONFIG_MBEDTLS=y -CONFIG_MBEDTLS_MAC_SHA256_ENABLED=y +CONFIG_MBEDTLS_SHA256=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 bf9bb9763c24a..5f85dda370851 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 @@ -6,4 +6,4 @@ CONFIG_MCUMGR_GRP_FS_CHECKSUM_IEEE_CRC32=n CONFIG_MCUMGR_GRP_FS_HASH_SHA256=y CONFIG_MBEDTLS=y -CONFIG_MBEDTLS_MAC_SHA256_ENABLED=y +CONFIG_MBEDTLS_SHA256=y From 7669b58d9dc2c3a094e91bd1f3007ac21d8d9f70 Mon Sep 17 00:00:00 2001 From: Tomi Fontanilles Date: Mon, 27 May 2024 10:32:59 +0300 Subject: [PATCH 1315/2849] samples: http_get: exclude native_posix in the CONFIG_POSIX_API=y build CONFIG_POSIX_API depends on !CONFIG_NATIVE_APPLICATION, which is incompatible with the native_posix platforms. Signed-off-by: Tomi Fontanilles --- samples/net/sockets/http_get/sample.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/samples/net/sockets/http_get/sample.yaml b/samples/net/sockets/http_get/sample.yaml index 4e454da50a7d7..c5849561c7431 100644 --- a/samples/net/sockets/http_get/sample.yaml +++ b/samples/net/sockets/http_get/sample.yaml @@ -15,6 +15,8 @@ tests: platform_exclude: - cc3220sf_launchxl - cc3235sf_launchxl + - native_posix + - native_posix/native/64 extra_configs: - CONFIG_POSIX_API=y sample.net.sockets.http_get.offload.simplelink: From b9a7c18ce4a34a96236b6d0d185211ab8311c135 Mon Sep 17 00:00:00 2001 From: Tomi Fontanilles Date: Mon, 27 May 2024 10:37:14 +0300 Subject: [PATCH 1316/2849] tests: mgmt: mcumgr: fs_mgmt_hash_supported: add unsupported platforms - `stm32h745i_disco/stm32h745xx/m4` says "#error Flash driver on M4 core is not supported yet". - `mpfs_icicle/polarfire/smp` fails in the compilation of the `spi_nor` flash driver. - `cyw920829m2evk_02` fails to build because of undeclared `cyhal_nvm_*()` functions. As a bonus, group the excluded platforms under the common part to avoid repeating them. Signed-off-by: Tomi Fontanilles --- .../fs_mgmt_hash_supported/testcase.yaml | 39 ++++++------------- 1 file changed, 12 insertions(+), 27 deletions(-) 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 fd0da3fd04799..efceb4abdf953 100644 --- a/tests/subsys/mgmt/mcumgr/fs_mgmt_hash_supported/testcase.yaml +++ b/tests/subsys/mgmt/mcumgr/fs_mgmt_hash_supported/testcase.yaml @@ -10,40 +10,25 @@ common: - fs_mgmt_hash_supported integration_platforms: - native_sim + platform_exclude: + - arduino_giga_r1/stm32h747xx/m4 + - arduino_portenta_h7/stm32h747xx/m4 + - lpcxpresso51u68 + - nucleo_h745zi_q/stm32h745xx/m4 + - stm32h747i_disco/stm32h747xx/m4 + - lpcxpresso55s69/lpc55s69/cpu1 + - mpfs_icicle + - mpfs_icicle/polarfire/smp + - apollo4p_evb + - stm32h745i_disco/stm32h745xx/m4 + - cyw920829m2evk_02 tests: mgmt.mcumgr.fs.mgmt.hash.supported.crc32: extra_args: > OVERLAY_CONFIG="configuration/crc32.conf" - platform_exclude: - - arduino_giga_r1/stm32h747xx/m4 - - arduino_portenta_h7/stm32h747xx/m4 - - 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" - platform_exclude: - - arduino_giga_r1/stm32h747xx/m4 - - arduino_portenta_h7/stm32h747xx/m4 - - 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" - platform_exclude: - - arduino_giga_r1/stm32h747xx/m4 - - arduino_portenta_h7/stm32h747xx/m4 - - lpcxpresso51u68 - - nucleo_h745zi_q/stm32h745xx/m4 - - stm32h747i_disco/stm32h747xx/m4 - - lpcxpresso55s69/lpc55s69/cpu1 - - mpfs_icicle - - apollo4p_evb From c8fda13b4c96e16e2ce2a762cc33f375946414cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fin=20Maa=C3=9F?= Date: Thu, 23 May 2024 12:00:22 +0200 Subject: [PATCH 1317/2849] drivers: interrupt_controller: litex: add prefix MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit add litex prefix to its interupt controller. Signed-off-by: Fin Maaß --- drivers/interrupt_controller/Kconfig | 2 +- drivers/interrupt_controller/intc_vexriscv_litex.c | 2 +- .../{vexriscv-intc0.yaml => litex,vexriscv-intc0.yaml} | 2 +- dts/riscv/riscv32-litex-vexriscv.dtsi | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) rename dts/bindings/interrupt-controller/{vexriscv-intc0.yaml => litex,vexriscv-intc0.yaml} (92%) diff --git a/drivers/interrupt_controller/Kconfig b/drivers/interrupt_controller/Kconfig index a956afdf1f602..d2bd166c96cdc 100644 --- a/drivers/interrupt_controller/Kconfig +++ b/drivers/interrupt_controller/Kconfig @@ -26,7 +26,7 @@ config SWERV_PIC config VEXRISCV_LITEX_IRQ bool "VexRiscv LiteX Interrupt controller" default y - depends on DT_HAS_VEXRISCV_INTC0_ENABLED + depends on DT_HAS_LITEX_VEXRISCV_INTC0_ENABLED help IRQ implementation for LiteX VexRiscv diff --git a/drivers/interrupt_controller/intc_vexriscv_litex.c b/drivers/interrupt_controller/intc_vexriscv_litex.c index 2d5d2233ab2e3..0356e848d22c6 100644 --- a/drivers/interrupt_controller/intc_vexriscv_litex.c +++ b/drivers/interrupt_controller/intc_vexriscv_litex.c @@ -4,7 +4,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -#define DT_DRV_COMPAT vexriscv_intc0 +#define DT_DRV_COMPAT litex_vexriscv_intc0 #include #include diff --git a/dts/bindings/interrupt-controller/vexriscv-intc0.yaml b/dts/bindings/interrupt-controller/litex,vexriscv-intc0.yaml similarity index 92% rename from dts/bindings/interrupt-controller/vexriscv-intc0.yaml rename to dts/bindings/interrupt-controller/litex,vexriscv-intc0.yaml index e370a774c5a63..3d1fd43deb7d6 100644 --- a/dts/bindings/interrupt-controller/vexriscv-intc0.yaml +++ b/dts/bindings/interrupt-controller/litex,vexriscv-intc0.yaml @@ -3,7 +3,7 @@ description: LiteX VexRiscV interrupt controller -compatible: "vexriscv-intc0" +compatible: "litex,vexriscv-intc0" include: [interrupt-controller.yaml, base.yaml] diff --git a/dts/riscv/riscv32-litex-vexriscv.dtsi b/dts/riscv/riscv32-litex-vexriscv.dtsi index 336a2feb00159..71b32e95b8886 100644 --- a/dts/riscv/riscv32-litex-vexriscv.dtsi +++ b/dts/riscv/riscv32-litex-vexriscv.dtsi @@ -35,7 +35,7 @@ compatible = "litex,vexriscv"; ranges; intc0: interrupt-controller@bc0 { - compatible = "vexriscv-intc0"; + compatible = "litex,vexriscv-intc0"; #address-cells = <0>; #interrupt-cells = <2>; interrupt-controller; From 858f25ce39756ba95b1cd251e9f64cdb9736c37e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fin=20Maa=C3=9F?= Date: Thu, 23 May 2024 12:05:13 +0200 Subject: [PATCH 1318/2849] maintainers: litex: add to maintainers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit move the litex part of the codeowners file over to maintainers and add me as colaborator. Signed-off-by: Fin Maaß --- CODEOWNERS | 6 ------ MAINTAINERS.yml | 23 +++++++++++++++++++++++ 2 files changed, 23 insertions(+), 6 deletions(-) diff --git a/CODEOWNERS b/CODEOWNERS index c6fe49d726396..ab9b5bd47559b 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -151,7 +151,6 @@ /drivers/*/*sam4l* @nandojve /drivers/*/*cc13xx_cc26xx* @bwitherspoon /drivers/*/*gd32* @nandojve -/drivers/*/*litex* @mateusz-holenko @kgugala @pgielda /drivers/*/*mcux* @mmahadevan108 @dleach02 /drivers/*/*stm32* @erwango @ABOSTM @FRASTM /drivers/*/*native_posix* @aescolar @daor-oti @@ -211,7 +210,6 @@ /drivers/entropy/*b91* @andy-liu-telink /drivers/entropy/*bt_hci* @JordanYates /drivers/entropy/*rv32m1* @dleach02 -/drivers/entropy/*litex* @mateusz-holenko @kgugala @pgielda /drivers/ethernet/*dwmac* @npitre /drivers/ethernet/*stm32* @Nukersson @lochej /drivers/ethernet/*w5500* @parthitce @@ -257,7 +255,6 @@ /drivers/i2c/i2c_test.c @mbolivar-ampere /drivers/i2c/*rcar* @aaillet /drivers/i2c/*kb1200* @ene-steven -/drivers/i2s/*litex* @mateusz-holenko @kgugala @pgielda /drivers/i2s/i2s_ll_stm32* @avisconti /drivers/i2s/*nrfx* @anangl /drivers/i3c/i3c_cdns.c @XenuIsWatching @@ -450,7 +447,6 @@ /dts/riscv/ite/ @ite /dts/riscv/microchip/microchip-miv.dtsi @galak /dts/riscv/openisa/rv32m1* @dleach02 -/dts/riscv/riscv32-litex-vexriscv.dtsi @mateusz-holenko @kgugala @pgielda /dts/riscv/starfive/ @rajnesh-kanwal @pfarwsi /dts/riscv/andes/andes_v5* @cwshu @kevinwang821020 @jimmyzhe /dts/riscv/niosv/ @sweeaun @@ -485,8 +481,6 @@ /dts/bindings/*/st* @erwango /dts/bindings/sensor/ams* @alexanderwachter /dts/bindings/*/sifive* @mateusz-holenko @kgugala @pgielda -/dts/bindings/*/litex* @mateusz-holenko @kgugala @pgielda -/dts/bindings/*/vexriscv* @mateusz-holenko @kgugala @pgielda /dts/bindings/*/andes* @cwshu @kevinwang821020 @jimmyzhe /dts/bindings/*/neorv32* @henrikbrixandersen /dts/bindings/*/*lan91c111* @sgrrzhf diff --git a/MAINTAINERS.yml b/MAINTAINERS.yml index 3834b1768c66d..e68df60cb58d9 100644 --- a/MAINTAINERS.yml +++ b/MAINTAINERS.yml @@ -3735,6 +3735,29 @@ Infineon Platforms: Infineon SOCs, dts files and related drivers. Infineon Proto, Pioneer, Eval and Relax boards. +LiteX Platforms: + status: maintained + maintainers: + - tgorochowik + - kgugala + - fkokosinski + collaborators: + - mateusz-holenko + - maass-hamburg + files: + - boards/enjoydigital/litex_vexriscv/ + - drivers/*/*litex* + - drivers/spi/spi_litespi* + - drivers/*/Kconfig.litex + - dts/bindings/*/litex* + - dts/riscv/riscv32-litex-vexriscv.dtsi + - include/zephyr/drivers/*/*litex* + - samples/boards/litex/ + - samples/drivers/*litex/ + - soc/litex/ + labels: + - "platform: LiteX" + Panasonic Platforms: status: maintained maintainers: From 7d5f2b6af3564e498409afbe23766586d6116f14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fin=20Maa=C3=9F?= Date: Fri, 24 May 2024 14:33:45 +0200 Subject: [PATCH 1319/2849] doc: migration-guide-3.7: rename litex compatible MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Mention the change of compatible of the LiteX VexRiscV interrupt controller. Signed-off-by: Fin Maaß --- 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 5a4402325f416..d39890f43cffa 100644 --- a/doc/releases/migration-guide-3.7.rst +++ b/doc/releases/migration-guide-3.7.rst @@ -73,6 +73,9 @@ Boards :kconfig:option:`CONFIG_I2C` is set. Users who need this setting enabled should set it in their project config file. (:github:`73067`) +* LiteX: Renamed the ``compatible`` of the LiteX VexRiscV interrupt controller node from + ``vexriscv-intc0`` to :dtcompatible:`litex,vexriscv-intc0`. (:github:`73211`) + Modules ******* From e34369ce31e5747603684031718b1cf429b365c4 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Wed, 22 May 2024 16:43:51 -0400 Subject: [PATCH 1320/2849] drivers/timer/apic_tsc: move to common code pattern Let's replicate a common code pattern for this to be abstracted more easily in the future. In addition to duplicating the correctness fixes implemented in the ARM and RISC-V drivers, this eliminates a couple large runtime divisions. Signed-off-by: Nicolas Pitre --- drivers/timer/apic_tsc.c | 115 +++++++++++++++++++++++++++++---------- 1 file changed, 85 insertions(+), 30 deletions(-) diff --git a/drivers/timer/apic_tsc.c b/drivers/timer/apic_tsc.c index 3c6ab1e0a6dff..f2951be965f61 100644 --- a/drivers/timer/apic_tsc.c +++ b/drivers/timer/apic_tsc.c @@ -16,8 +16,37 @@ #define IA32_TSC_DEADLINE_MSR 0x6e0 #define IA32_TSC_ADJUST_MSR 0x03b -#define CYC_PER_TICK (CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC \ - / (uint64_t) CONFIG_SYS_CLOCK_TICKS_PER_SEC) +#define CYC_PER_TICK (uint32_t)(CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC \ + / CONFIG_SYS_CLOCK_TICKS_PER_SEC) + +/* the unsigned long cast limits divisors 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)) struct apic_timer_lvt { uint8_t vector : 8; @@ -28,7 +57,9 @@ struct apic_timer_lvt { }; static struct k_spinlock lock; -static uint64_t last_announce; +static uint64_t last_cycle; +static uint64_t last_tick; +static uint32_t last_elapsed; static union { uint32_t val; struct apic_timer_lvt lvt; } lvt_reg; static ALWAYS_INLINE uint64_t rdtsc(void) @@ -39,41 +70,58 @@ static ALWAYS_INLINE uint64_t rdtsc(void) return lo + (((uint64_t)hi) << 32); } +static inline void wrmsr(int32_t msr, uint64_t val) +{ + uint32_t hi = (uint32_t) (val >> 32); + uint32_t lo = (uint32_t) val; + + __asm__ volatile("wrmsr" :: "d"(hi), "a"(lo), "c"(msr)); +} + static void isr(const void *arg) { ARG_UNUSED(arg); + k_spinlock_key_t key = k_spin_lock(&lock); - uint32_t ticks = (rdtsc() - last_announce) / CYC_PER_TICK; + uint64_t curr_cycle = rdtsc(); + uint64_t delta_cycles = curr_cycle - last_cycle; + uint32_t delta_ticks = (cycle_diff_t)delta_cycles / CYC_PER_TICK; - last_announce += ticks * CYC_PER_TICK; - k_spin_unlock(&lock, key); - sys_clock_announce(ticks); + last_cycle += (cycle_diff_t)delta_ticks * CYC_PER_TICK; + last_tick += delta_ticks; + last_elapsed = 0; if (!IS_ENABLED(CONFIG_TICKLESS_KERNEL)) { - sys_clock_set_timeout(1, false); - } -} + uint64_t next_cycle = last_cycle + CYC_PER_TICK; -static inline void wrmsr(int32_t msr, uint64_t val) -{ - uint32_t hi = (uint32_t) (val >> 32); - uint32_t lo = (uint32_t) val; + wrmsr(IA32_TSC_DEADLINE_MSR, next_cycle); + } - __asm__ volatile("wrmsr" :: "d"(hi), "a"(lo), "c"(msr)); + k_spin_unlock(&lock, key); + sys_clock_announce(delta_ticks); } void sys_clock_set_timeout(int32_t ticks, bool idle) { ARG_UNUSED(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); + if (!IS_ENABLED(CONFIG_TICKLESS_KERNEL)) { + return; + } - expires = last_announce + (((expires - last_announce + CYC_PER_TICK - 1) - / CYC_PER_TICK) * CYC_PER_TICK); + k_spinlock_key_t key = k_spin_lock(&lock); + 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; + } + } - /* The second condition is to catch the wraparound. + /* * Interpreted strictly, the IA SDM description of the * TSC_DEADLINE MSR implies that it will trigger an immediate * interrupt if we try to set an expiration across the 64 bit @@ -81,21 +129,28 @@ 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)) { - expires = UINT64_MAX; + if (next_cycle < last_cycle) { + next_cycle = UINT64_MAX; } + wrmsr(IA32_TSC_DEADLINE_MSR, next_cycle); - wrmsr(IA32_TSC_DEADLINE_MSR, expires); k_spin_unlock(&lock, key); } uint32_t sys_clock_elapsed(void) { + if (!IS_ENABLED(CONFIG_TICKLESS_KERNEL)) { + return 0; + } + k_spinlock_key_t key = k_spin_lock(&lock); - uint32_t ret = (rdtsc() - last_announce) / CYC_PER_TICK; + uint64_t curr_cycle = rdtsc(); + uint64_t delta_cycles = curr_cycle - last_cycle; + uint32_t delta_ticks = (cycle_diff_t)delta_cycles / CYC_PER_TICK; + last_elapsed = delta_ticks; k_spin_unlock(&lock, key); - return ret; + return delta_ticks; } uint32_t sys_clock_cycle_get_32(void) @@ -190,12 +245,12 @@ static int sys_clock_driver_init(void) */ __asm__ volatile("mfence" ::: "memory"); - last_announce = rdtsc(); - irq_enable(timer_irq()); - + last_tick = rdtsc() / CYC_PER_TICK; + last_cycle = last_tick * CYC_PER_TICK; if (!IS_ENABLED(CONFIG_TICKLESS_KERNEL)) { - sys_clock_set_timeout(1, false); + wrmsr(IA32_TSC_DEADLINE_MSR, last_cycle + CYC_PER_TICK); } + irq_enable(timer_irq()); return 0; } From 3c2e57c923c2329966f4797abebbdc18531b8e03 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Thu, 23 May 2024 17:27:18 -0400 Subject: [PATCH 1321/2849] drivers/timer/apic_tsc: use ICR as a fallback timeout event source This adds support for the local APIC in one-shot mode as the timeout event source for those cases where the CPU supports invariant TSC but no TSC deadline capability. It is presented as another timer choice. Existing Kconfig symbols were preserved to minimize board config disturbance. This hybrid approach was implemented kind of backward in the apic_timer driver but it is far cleaner to carry this here. Signed-off-by: Nicolas Pitre --- boards/intel/adl/Kconfig.defconfig | 2 + boards/intel/ehl/Kconfig.defconfig | 2 + boards/intel/rpl/Kconfig.defconfig | 2 + .../up_squared/Kconfig.defconfig | 2 + .../up_squared_pro_7000/Kconfig.defconfig | 2 + drivers/timer/CMakeLists.txt | 1 + drivers/timer/Kconfig.x86 | 26 +++--- drivers/timer/apic_tsc.c | 85 ++++++++++++++++--- soc/intel/apollo_lake/Kconfig.defconfig | 3 - 9 files changed, 100 insertions(+), 25 deletions(-) diff --git a/boards/intel/adl/Kconfig.defconfig b/boards/intel/adl/Kconfig.defconfig index 518f0c01ee2dc..3a6bcaf9ce02a 100644 --- a/boards/intel/adl/Kconfig.defconfig +++ b/boards/intel/adl/Kconfig.defconfig @@ -16,6 +16,8 @@ config SYS_CLOCK_HW_CYCLES_PER_SEC if APIC_TIMER config APIC_TIMER_IRQ default 24 +endif +if APIC_TIMER_TSC config APIC_TIMER_TSC_M default 3 config APIC_TIMER_TSC_N diff --git a/boards/intel/ehl/Kconfig.defconfig b/boards/intel/ehl/Kconfig.defconfig index 9e7dcf48a0458..8b8c89800dab2 100644 --- a/boards/intel/ehl/Kconfig.defconfig +++ b/boards/intel/ehl/Kconfig.defconfig @@ -27,6 +27,8 @@ config SYS_CLOCK_HW_CYCLES_PER_SEC if APIC_TIMER config APIC_TIMER_IRQ default 24 +endif +if APIC_TIMER_TSC config APIC_TIMER_TSC_M default 3 config APIC_TIMER_TSC_N diff --git a/boards/intel/rpl/Kconfig.defconfig b/boards/intel/rpl/Kconfig.defconfig index ca8a77426881b..4eb5d8c3126c7 100644 --- a/boards/intel/rpl/Kconfig.defconfig +++ b/boards/intel/rpl/Kconfig.defconfig @@ -17,6 +17,8 @@ config SYS_CLOCK_HW_CYCLES_PER_SEC if APIC_TIMER config APIC_TIMER_IRQ default 24 +endif +if APIC_TIMER_TSC config APIC_TIMER_TSC_M default 3 config APIC_TIMER_TSC_N diff --git a/boards/up-bridge-the-gap/up_squared/Kconfig.defconfig b/boards/up-bridge-the-gap/up_squared/Kconfig.defconfig index 78d041976f1ab..9c721cfcc320b 100644 --- a/boards/up-bridge-the-gap/up_squared/Kconfig.defconfig +++ b/boards/up-bridge-the-gap/up_squared/Kconfig.defconfig @@ -18,6 +18,8 @@ config SYS_CLOCK_HW_CYCLES_PER_SEC if APIC_TIMER config APIC_TIMER_IRQ default 24 +endif +if APIC_TIMER_TSC config APIC_TIMER_TSC_M default 3 config APIC_TIMER_TSC_N diff --git a/boards/up-bridge-the-gap/up_squared_pro_7000/Kconfig.defconfig b/boards/up-bridge-the-gap/up_squared_pro_7000/Kconfig.defconfig index 84744a7ea3af4..e7c98f9eddf5d 100644 --- a/boards/up-bridge-the-gap/up_squared_pro_7000/Kconfig.defconfig +++ b/boards/up-bridge-the-gap/up_squared_pro_7000/Kconfig.defconfig @@ -19,6 +19,8 @@ if APIC_TIMER config APIC_TIMER_IRQ default 24 +endif +if APIC_TIMER_TSC config APIC_TIMER_TSC_M default 3 config APIC_TIMER_TSC_N diff --git a/drivers/timer/CMakeLists.txt b/drivers/timer/CMakeLists.txt index c44acda2ae6c6..80f8431c4d0ff 100644 --- a/drivers/timer/CMakeLists.txt +++ b/drivers/timer/CMakeLists.txt @@ -6,6 +6,7 @@ zephyr_library_sources_ifdef(CONFIG_ALTERA_AVALON_TIMER altera_avalon_timer_hal. zephyr_library_sources_ifdef(CONFIG_AMBIQ_STIMER_TIMER ambiq_stimer.c) zephyr_library_sources_ifdef(CONFIG_APIC_TIMER apic_timer.c) zephyr_library_sources_ifdef(CONFIG_APIC_TSC_DEADLINE_TIMER apic_tsc.c) +zephyr_library_sources_ifdef(CONFIG_APIC_TIMER_TSC apic_tsc.c) zephyr_library_sources_ifdef(CONFIG_ARCV2_TIMER arcv2_timer0.c) zephyr_library_sources_ifdef(CONFIG_ARM_ARCH_TIMER arm_arch_timer.c) zephyr_library_sources_ifdef(CONFIG_INTEL_ADSP_TIMER intel_adsp_timer.c) diff --git a/drivers/timer/Kconfig.x86 b/drivers/timer/Kconfig.x86 index ea6d4a216b7d4..55dbf819ec875 100644 --- a/drivers/timer/Kconfig.x86 +++ b/drivers/timer/Kconfig.x86 @@ -51,6 +51,19 @@ config APIC_TSC_DEADLINE_TIMER choice for any x86 device with invariant TSC and TSC deadline capability. +config APIC_TIMER_TSC + bool "Local APIC timer using TSC time source" + depends on !SMP + select LOAPIC + select TICKLESS_CAPABLE + select TIMER_HAS_64BIT_CYCLE_COUNTER + help + If your CPU supports invariant TSC but no TSC deadline capability + then this choice will rely on the TSC as time source and the + local APIC in one-shot mode as the timeout event source. + You must know the ratio of the TSC frequency to the local APIC + timer frequency. + endchoice if APIC_TIMER @@ -66,14 +79,7 @@ config APIC_TIMER_IRQ user-configurable and almost certainly should be managed via a different mechanism. -config APIC_TIMER_TSC - bool "Use invariant TSC for sys_clock_cycle_get_32()" - select TIMER_HAS_64BIT_CYCLE_COUNTER - help - If your CPU supports invariant TSC, and you know the ratio of the - TSC frequency to CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC (the local APIC - timer frequency), then enable this for a much faster and more - accurate sys_clock_cycle_get_32(). +endif # APIC_TIMER if APIC_TIMER_TSC @@ -87,11 +93,9 @@ config APIC_TIMER_TSC_M endif # APIC_TIMER_TSC -endif # APIC_TIMER - config APIC_TIMER_IRQ_PRIORITY int "Local APIC timer interrupt priority" - depends on APIC_TIMER || APIC_TSC_DEADLINE_TIMER + depends on APIC_TIMER || APIC_TSC_DEADLINE_TIMER || APIC_TIMER_TSC default 4 help This option specifies the interrupt priority used by the diff --git a/drivers/timer/apic_tsc.c b/drivers/timer/apic_tsc.c index f2951be965f61..0c617a01ca789 100644 --- a/drivers/timer/apic_tsc.c +++ b/drivers/timer/apic_tsc.c @@ -13,6 +13,37 @@ #include #include +/* + * This driver is selected when either CONFIG_APIC_TIMER_TSC or + * CONFIG_APIC_TSC_DEADLINE_TIMER is selected. The later is preferred over + * the former when the TSC deadline comparator is available. + */ +BUILD_ASSERT((!IS_ENABLED(CONFIG_APIC_TIMER_TSC) && + IS_ENABLED(CONFIG_APIC_TSC_DEADLINE_TIMER)) || + (!IS_ENABLED(CONFIG_APIC_TSC_DEADLINE_TIMER) && + IS_ENABLED(CONFIG_APIC_TIMER_TSC)), + "one of CONFIG_APIC_TIMER_TSC or CONFIG_APIC_TSC_DEADLINE_TIMER must be set"); + +/* + * If the TSC deadline comparator is not supported then the ICR in one-shot + * mode is used as a fallback method to trigger the next timeout interrupt. + * Those config symbols must then be defined: + * + * CONFIG_APIC_TIMER_TSC_N= + * CONFIG_APIC_TIMER_TSC_M= + * + * These are set to indicate the ratio of the TSC frequency to the local + * APIC timer frequency. This can be found via CPUID 0x15 (n = EBX, m = EAX) + * on most CPUs. + */ +#ifdef CONFIG_APIC_TIMER_TSC +#define APIC_TIMER_TSC_M CONFIG_APIC_TIMER_TSC_M +#define APIC_TIMER_TSC_N CONFIG_APIC_TIMER_TSC_N +#else +#define APIC_TIMER_TSC_M 1 +#define APIC_TIMER_TSC_N 1 +#endif + #define IA32_TSC_DEADLINE_MSR 0x6e0 #define IA32_TSC_ADJUST_MSR 0x03b @@ -78,6 +109,22 @@ static inline void wrmsr(int32_t msr, uint64_t val) __asm__ volatile("wrmsr" :: "d"(hi), "a"(lo), "c"(msr)); } +static void set_trigger(uint64_t deadline) +{ + if (IS_ENABLED(CONFIG_APIC_TSC_DEADLINE_TIMER)) { + wrmsr(IA32_TSC_DEADLINE_MSR, deadline); + } else { + /* use the timer ICR to trigger next interrupt */ + uint64_t curr_cycle = rdtsc(); + uint64_t delta_cycles = deadline - MIN(deadline, curr_cycle); + uint64_t icr = (delta_cycles * APIC_TIMER_TSC_M) / APIC_TIMER_TSC_N; + + /* cap icr to 32 bits, and not zero */ + icr = CLAMP(icr, 1, UINT32_MAX); + x86_write_loapic(LOAPIC_TIMER_ICR, icr); + } +} + static void isr(const void *arg) { ARG_UNUSED(arg); @@ -94,7 +141,7 @@ static void isr(const void *arg) if (!IS_ENABLED(CONFIG_TICKLESS_KERNEL)) { uint64_t next_cycle = last_cycle + CYC_PER_TICK; - wrmsr(IA32_TSC_DEADLINE_MSR, next_cycle); + set_trigger(next_cycle); } k_spin_unlock(&lock, key); @@ -132,7 +179,7 @@ void sys_clock_set_timeout(int32_t ticks, bool idle) if (next_cycle < last_cycle) { next_cycle = UINT64_MAX; } - wrmsr(IA32_TSC_DEADLINE_MSR, next_cycle); + set_trigger(next_cycle); k_spin_unlock(&lock, key); } @@ -213,28 +260,44 @@ static int sys_clock_driver_init(void) #ifdef CONFIG_ASSERT uint32_t 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"); + if (IS_ENABLED(CONFIG_APIC_TSC_DEADLINE_TIMER)) { + ecx = 0; /* prevent compiler warning */ + __get_cpuid(CPUID_BASIC_INFO_1, &eax, &ebx, &ecx, &edx); + __ASSERT((ecx & BIT(24)) != 0, "No TSC Deadline support"); + } edx = 0; /* prevent compiler warning */ __get_cpuid(0x80000007, &eax, &ebx, &ecx, &edx); __ASSERT((edx & BIT(8)) != 0, "No Invariant TSC support"); - 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"); + if (IS_ENABLED(CONFIG_SMP)) { + 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 - clear_tsc_adjust(); + if (IS_ENABLED(CONFIG_SMP)) { + clear_tsc_adjust(); + } /* Timer interrupt number is runtime-fetched, so can't use * static IRQ_CONNECT() */ irq_connect_dynamic(timer_irq(), CONFIG_APIC_TIMER_IRQ_PRIORITY, isr, 0, 0); + if (IS_ENABLED(CONFIG_APIC_TIMER_TSC)) { + uint32_t timer_conf; + + timer_conf = x86_read_loapic(LOAPIC_TIMER_CONFIG); + timer_conf &= ~0x0f; /* clear divider bits */ + timer_conf |= 0x0b; /* divide by 1 */ + x86_write_loapic(LOAPIC_TIMER_CONFIG, timer_conf); + } + lvt_reg.val = x86_read_loapic(LOAPIC_TIMER); - lvt_reg.lvt.mode = TSC_DEADLINE; + lvt_reg.lvt.mode = IS_ENABLED(CONFIG_APIC_TSC_DEADLINE_TIMER) ? + TSC_DEADLINE : ONE_SHOT; lvt_reg.lvt.masked = 0; x86_write_loapic(LOAPIC_TIMER, lvt_reg.val); @@ -248,7 +311,7 @@ static int sys_clock_driver_init(void) last_tick = rdtsc() / CYC_PER_TICK; last_cycle = last_tick * CYC_PER_TICK; if (!IS_ENABLED(CONFIG_TICKLESS_KERNEL)) { - wrmsr(IA32_TSC_DEADLINE_MSR, last_cycle + CYC_PER_TICK); + set_trigger(last_cycle + CYC_PER_TICK); } irq_enable(timer_irq()); diff --git a/soc/intel/apollo_lake/Kconfig.defconfig b/soc/intel/apollo_lake/Kconfig.defconfig index 7ea881ce59eb1..ef062600dfadf 100644 --- a/soc/intel/apollo_lake/Kconfig.defconfig +++ b/soc/intel/apollo_lake/Kconfig.defconfig @@ -14,9 +14,6 @@ if APIC_TIMER config APIC_TIMER_IRQ default 24 -config APIC_TIMER_TSC - default y - endif # APIC_TIMER config X86_DYNAMIC_IRQ_STUBS From 99dcbdf9332dee504c136a1d35177a24a24a5ede Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Wed, 22 May 2024 17:59:30 -0400 Subject: [PATCH 1322/2849] drivers/timer/apic_timer: move to periodic mode This driver is impossible to make time-accurate using single-shot mode. Time accuracy may be obtained only by using periodic mode, meaning it is not tickless capable either. Let's simplify the code by only supporting periodic mode and strip out the TSC stuff. Any hardware with TSC capability should now use the apic-tsc driver instead. Signed-off-by: Nicolas Pitre --- drivers/timer/Kconfig.x86 | 4 +- drivers/timer/apic_timer.c | 184 ++++++------------------------------- 2 files changed, 28 insertions(+), 160 deletions(-) diff --git a/drivers/timer/Kconfig.x86 b/drivers/timer/Kconfig.x86 index 55dbf819ec875..436439838f6eb 100644 --- a/drivers/timer/Kconfig.x86 +++ b/drivers/timer/Kconfig.x86 @@ -26,10 +26,10 @@ config HPET_TIMER config APIC_TIMER bool "Local APIC timer" select LOAPIC - select TICKLESS_CAPABLE + select TIMER_HAS_64BIT_CYCLE_COUNTER select SYSTEM_CLOCK_LOCK_FREE_COUNT help - Use the x86 local APIC in one-shot mode as the system time + Use the x86 local APIC in periodic mode as the system time source. NOTE: this probably isn't what you want except on older or idiosyncratic hardware (or environments like qemu without complete APIC emulation). Modern hardware will work diff --git a/drivers/timer/apic_timer.c b/drivers/timer/apic_timer.c index cf28acb04d93e..2c16ba749000b 100644 --- a/drivers/timer/apic_timer.c +++ b/drivers/timer/apic_timer.c @@ -10,18 +10,14 @@ #include #include -BUILD_ASSERT(!IS_ENABLED(CONFIG_SMP), "APIC timer doesn't support SMP"); +BUILD_ASSERT(!IS_ENABLED(CONFIG_TICKLESS_KERNEL), "this is a tickfull driver"); /* * Overview: * * This driver enables the local APIC as the Zephyr system timer. It supports - * both legacy ("tickful") mode as well as TICKLESS_KERNEL. The driver will - * work with any APIC that has the ARAT "always running APIC timer" feature - * (CPUID 0x06, EAX bit 2); for the more accurate sys_clock_cycle_get_32(), - * the invariant TSC feature (CPUID 0x80000007: EDX bit 8) is also required. - * (Ultimately systems with invariant TSCs should use a TSC-based driver, - * and the TSC-related parts should be stripped from this implementation.) + * legacy ("tickful") mode only. The driver will work with any APIC that has + * the ARAT "always running APIC timer" feature (CPUID 0x06, EAX bit 2). * * Configuration: * @@ -31,15 +27,6 @@ BUILD_ASSERT(!IS_ENABLED(CONFIG_SMP), "APIC timer doesn't support SMP"); * * CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC= must contain the frequency seen * by the local APIC timer block (before it gets to the timer divider). - * - * CONFIG_APIC_TIMER_TSC=y enables the more accurate TSC-based cycle counter - * for sys_clock_cycle_get_32(). This also requires the next options be set. - * - * CONFIG_APIC_TIMER_TSC_N= - * CONFIG_APIC_TIMER_TSC_M= - * When CONFIG_APIC_TIMER_TSC=y, these are set to indicate the ratio of - * the TSC frequency to CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC. This can be - * found via CPUID 0x15 (n = EBX, m = EAX) on most CPUs. */ /* These should be merged into include/drivers/interrupt_controller/loapic.h. */ @@ -47,139 +34,24 @@ BUILD_ASSERT(!IS_ENABLED(CONFIG_SMP), "APIC timer doesn't support SMP"); #define DCR_DIVIDER_MASK 0x0000000F /* divider bits */ #define DCR_DIVIDER 0x0000000B /* divide by 1 */ #define LVT_MODE_MASK 0x00060000 /* timer mode bits */ -#define LVT_MODE 0x00000000 /* one-shot */ +#define LVT_MODE 0x00020000 /* periodic mode */ #if defined(CONFIG_TEST) const int32_t z_sys_timer_irq_for_test = CONFIG_APIC_TIMER_IRQ; #endif -/* - * CYCLES_PER_TICK must always be at least '2', otherwise MAX_TICKS - * will overflow int32_t, which is how 'ticks' are currently represented. - */ #define CYCLES_PER_TICK \ (CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC / CONFIG_SYS_CLOCK_TICKS_PER_SEC) -BUILD_ASSERT(CYCLES_PER_TICK >= 2, "APIC timer: bad CYCLES_PER_TICK"); - -/* max number of ticks we can load into the timer in one shot */ - -#define MAX_TICKS (0xFFFFFFFFU / CYCLES_PER_TICK) - -/* - * The spinlock protects all access to the local APIC timer registers, - * as well as 'total_cycles', 'last_announcement', and 'cached_icr'. - * - * One important invariant that must be observed: `total_cycles` + `cached_icr` - * is always an integral multiple of CYCLE_PER_TICK; this is, timer interrupts - * are only ever scheduled to occur at tick boundaries. - */ - -static struct k_spinlock lock; -static uint64_t total_cycles; -static uint32_t cached_icr = CYCLES_PER_TICK; +BUILD_ASSERT(CYCLES_PER_TICK >= 1, "APIC timer: bad CYCLES_PER_TICK"); -#ifdef CONFIG_TICKLESS_KERNEL - -static uint64_t last_announcement; /* last time we called sys_clock_announce() */ - -void sys_clock_set_timeout(int32_t n, bool idle) -{ - ARG_UNUSED(idle); - - uint32_t ccr; - int full_ticks; /* number of complete ticks we'll wait */ - uint32_t full_cycles; /* full_ticks represented as cycles */ - uint32_t partial_cycles; /* number of cycles to first tick boundary */ - - if (n < 1) { - full_ticks = 0; - } else if ((n == K_TICKS_FOREVER) || (n > MAX_TICKS)) { - full_ticks = MAX_TICKS - 1; - } else { - full_ticks = n - 1; - } - - full_cycles = full_ticks * CYCLES_PER_TICK; - - /* - * There's a wee race condition here. The timer may expire while - * we're busy reprogramming it; an interrupt will be queued at the - * local APIC and the ISR will be called too early, roughly right - * after we unlock, and not because the count we just programmed has - * counted down. Luckily this situation is easy to detect, which is - * why the ISR actually checks to be sure the CCR is 0 before acting. - */ - - k_spinlock_key_t key = k_spin_lock(&lock); - - ccr = x86_read_loapic(LOAPIC_TIMER_CCR); - total_cycles += (cached_icr - ccr); - partial_cycles = CYCLES_PER_TICK - (total_cycles % CYCLES_PER_TICK); - cached_icr = full_cycles + partial_cycles; - x86_write_loapic(LOAPIC_TIMER_ICR, cached_icr); - - k_spin_unlock(&lock, key); -} - -uint32_t sys_clock_elapsed(void) -{ - uint32_t ccr; - uint32_t ticks; - - k_spinlock_key_t key = k_spin_lock(&lock); - ccr = x86_read_loapic(LOAPIC_TIMER_CCR); - ticks = total_cycles - last_announcement; - ticks += cached_icr - ccr; - k_spin_unlock(&lock, key); - ticks /= CYCLES_PER_TICK; - - return ticks; -} +static volatile uint64_t total_cycles; static void isr(const void *arg) { ARG_UNUSED(arg); - uint32_t cycles; - int32_t ticks; - - k_spinlock_key_t key = k_spin_lock(&lock); - - /* - * If we get here and the CCR isn't zero, then this interrupt is - * stale: it was queued while sys_clock_set_timeout() was setting - * a new counter. Just ignore it. See above for more info. - */ - - if (x86_read_loapic(LOAPIC_TIMER_CCR) != 0) { - k_spin_unlock(&lock, key); - return; - } - - /* Restart the timer as early as possible to minimize drift... */ - x86_write_loapic(LOAPIC_TIMER_ICR, MAX_TICKS * CYCLES_PER_TICK); - - cycles = cached_icr; - cached_icr = MAX_TICKS * CYCLES_PER_TICK; - total_cycles += cycles; - ticks = (total_cycles - last_announcement) / CYCLES_PER_TICK; - last_announcement = total_cycles; - k_spin_unlock(&lock, key); - sys_clock_announce(ticks); -} - -#else - -static void isr(const void *arg) -{ - ARG_UNUSED(arg); - - k_spinlock_key_t key = k_spin_lock(&lock); total_cycles += CYCLES_PER_TICK; - x86_write_loapic(LOAPIC_TIMER_ICR, cached_icr); - k_spin_unlock(&lock, key); - sys_clock_announce(1); } @@ -188,36 +60,32 @@ uint32_t sys_clock_elapsed(void) return 0U; } -#endif /* CONFIG_TICKLESS_KERNEL */ - -#ifdef CONFIG_APIC_TIMER_TSC - -uint32_t sys_clock_cycle_get_32(void) +uint64_t sys_clock_cycle_get_64(void) { - uint64_t tsc = z_tsc_read(); - uint32_t cycles; - - cycles = (tsc * CONFIG_APIC_TIMER_TSC_M) / CONFIG_APIC_TIMER_TSC_N; - return cycles; + uint32_t ccr_1st, ccr_2nd; + uint64_t cycles; + + /* + * We may race with CCR reaching 0 and reloading, and the interrupt + * handler updating total_cycles. Let's make sure we sample everything + * away from this roll-over transition by ensuring consecutive CCR + * values are descending so we're sure the enclosed (volatile) + * total_cycles sample and CCR value are coherent with each other. + */ + do { + ccr_1st = x86_read_loapic(LOAPIC_TIMER_CCR); + cycles = total_cycles; + ccr_2nd = x86_read_loapic(LOAPIC_TIMER_CCR); + } while (ccr_2nd > ccr_1st); + + return cycles + (CYCLES_PER_TICK - ccr_2nd); } -#else - uint32_t sys_clock_cycle_get_32(void) { - uint32_t ret; - uint32_t ccr; - - k_spinlock_key_t key = k_spin_lock(&lock); - ccr = x86_read_loapic(LOAPIC_TIMER_CCR); - ret = total_cycles + (cached_icr - ccr); - k_spin_unlock(&lock, key); - - return ret; + return (uint32_t)sys_clock_cycle_get_64(); } -#endif - static int sys_clock_driver_init(void) { uint32_t val; @@ -239,7 +107,7 @@ static int sys_clock_driver_init(void) CONFIG_APIC_TIMER_IRQ_PRIORITY, isr, 0, 0); - x86_write_loapic(LOAPIC_TIMER_ICR, cached_icr); + x86_write_loapic(LOAPIC_TIMER_ICR, CYCLES_PER_TICK); irq_enable(CONFIG_APIC_TIMER_IRQ); return 0; From 054f453ea7bdb2fa81f28576c9d583aa5230f50a Mon Sep 17 00:00:00 2001 From: Tom Burdick Date: Tue, 14 May 2024 11:39:48 -0500 Subject: [PATCH 1323/2849] rtio: Callback chaining and testing Callbacks were a bit neglected in terms of test coverage, especially when used in chains. It was clear from the code that chained callbacks may not actually work, and callback ordering then was hard to verify. Test callbacks chained to transactions work as expected. The test iodev had built up some cruft over time and in the process showed a few bugs once callback chaining was fixed so the test iodev now better matches typical iodev implementations at this point. Cancellation testing now includes an added case for cancelling a the second submission in the chain prior to calling submit noting that no completions notifications should be given back for those. Signed-off-by: Tom Burdick --- subsys/rtio/rtio_executor.c | 96 ++++++++------ .../rtio/rtio_api/src/rtio_iodev_test.h | 117 ++++++++--------- .../subsys/rtio/rtio_api/src/test_rtio_api.c | 124 ++++++++++++++++-- 3 files changed, 221 insertions(+), 116 deletions(-) diff --git a/subsys/rtio/rtio_executor.c b/subsys/rtio/rtio_executor.c index 0f84d5aabf4de..13fd6a7e4ddf0 100644 --- a/subsys/rtio/rtio_executor.c +++ b/subsys/rtio/rtio_executor.c @@ -10,6 +10,23 @@ #include LOG_MODULE_REGISTER(rtio_executor, CONFIG_RTIO_LOG_LEVEL); +/** + * @brief Executor handled submissions + */ +static void rtio_executor_op(struct rtio_iodev_sqe *iodev_sqe) +{ + const struct rtio_sqe *sqe = &iodev_sqe->sqe; + + switch (sqe->op) { + case RTIO_OP_CALLBACK: + sqe->callback(iodev_sqe->r, sqe, sqe->arg0); + rtio_iodev_sqe_ok(iodev_sqe, 0); + break; + default: + rtio_iodev_sqe_err(iodev_sqe, -EINVAL); + } +} + /** * @brief Submit to an iodev a submission to work on * @@ -21,28 +38,17 @@ LOG_MODULE_REGISTER(rtio_executor, CONFIG_RTIO_LOG_LEVEL); static inline void rtio_iodev_submit(struct rtio_iodev_sqe *iodev_sqe) { if (FIELD_GET(RTIO_SQE_CANCELED, iodev_sqe->sqe.flags)) { - /* Canceled */ rtio_iodev_sqe_err(iodev_sqe, -ECANCELED); return; } - iodev_sqe->sqe.iodev->api->submit(iodev_sqe); -} - -/** - * @brief Executor handled submissions - */ -static void rtio_executor_op(struct rtio_iodev_sqe *iodev_sqe) -{ - const struct rtio_sqe *sqe = &iodev_sqe->sqe; - switch (sqe->op) { - case RTIO_OP_CALLBACK: - sqe->callback(iodev_sqe->r, sqe, sqe->arg0); - rtio_iodev_sqe_ok(iodev_sqe, 0); - break; - default: - rtio_iodev_sqe_err(iodev_sqe, -EINVAL); + /* No iodev means its an executor specific operation */ + if (iodev_sqe->sqe.iodev == NULL) { + rtio_executor_op(iodev_sqe); + return; } + + iodev_sqe->sqe.iodev->api->submit(iodev_sqe); } /** @@ -54,46 +60,52 @@ static void rtio_executor_op(struct rtio_iodev_sqe *iodev_sqe) */ void rtio_executor_submit(struct rtio *r) { + const uint16_t cancel_no_response = (RTIO_SQE_CANCELED | RTIO_SQE_NO_RESPONSE); struct rtio_mpsc_node *node = rtio_mpsc_pop(&r->sq); while (node != NULL) { struct rtio_iodev_sqe *iodev_sqe = CONTAINER_OF(node, struct rtio_iodev_sqe, q); - uint16_t canceled_mask = iodev_sqe->sqe.flags & RTIO_SQE_CANCELED; + /* If this submission was cancelled before submit, then generate no response */ + if (iodev_sqe->sqe.flags & RTIO_SQE_CANCELED) { + iodev_sqe->sqe.flags |= cancel_no_response; + } iodev_sqe->r = r; - if (iodev_sqe->sqe.iodev == NULL) { - rtio_executor_op(iodev_sqe); - } else { - struct rtio_iodev_sqe *curr = iodev_sqe, *next; + struct rtio_iodev_sqe *curr = iodev_sqe, *next; - /* Link up transaction or queue list if needed */ - while (curr->sqe.flags & (RTIO_SQE_TRANSACTION | RTIO_SQE_CHAINED)) { + /* Link up transaction or queue list if needed */ + while (curr->sqe.flags & (RTIO_SQE_TRANSACTION | RTIO_SQE_CHAINED)) { #ifdef CONFIG_ASSERT - bool transaction = iodev_sqe->sqe.flags & RTIO_SQE_TRANSACTION; - bool chained = iodev_sqe->sqe.flags & RTIO_SQE_CHAINED; + bool transaction = iodev_sqe->sqe.flags & RTIO_SQE_TRANSACTION; + bool chained = iodev_sqe->sqe.flags & RTIO_SQE_CHAINED; - __ASSERT(transaction != chained, - "Expected chained or transaction flag, not both"); + __ASSERT(transaction != chained, + "Expected chained or transaction flag, not both"); #endif - node = rtio_mpsc_pop(&iodev_sqe->r->sq); - next = CONTAINER_OF(node, struct rtio_iodev_sqe, q); - next->sqe.flags |= canceled_mask; - curr->next = next; - curr = next; - curr->r = r; - - __ASSERT( - curr != NULL, - "Expected a valid sqe following transaction or chain flag"); + node = rtio_mpsc_pop(&iodev_sqe->r->sq); + next = CONTAINER_OF(node, struct rtio_iodev_sqe, q); + + /* If the current submission was cancelled before submit, + * then cancel the next one and generate no response + */ + if (curr->sqe.flags & RTIO_SQE_CANCELED) { + next->sqe.flags |= cancel_no_response; } - - curr->next = NULL; + curr->next = next; + curr = next; curr->r = r; - rtio_iodev_submit(iodev_sqe); + __ASSERT( + curr != NULL, + "Expected a valid sqe following transaction or chain flag"); } + curr->next = NULL; + curr->r = r; + + rtio_iodev_submit(iodev_sqe); + node = rtio_mpsc_pop(&r->sq); } } @@ -160,7 +172,7 @@ static inline void rtio_executor_done(struct rtio_iodev_sqe *iodev_sqe, int resu } } while (sqe_flags & RTIO_SQE_TRANSACTION); - /* Curr should now be the last sqe in the transaction if that is what completed */ + /* curr should now be the last sqe in the transaction if that is what completed */ if (sqe_flags & RTIO_SQE_CHAINED) { rtio_iodev_submit(curr); } diff --git a/tests/subsys/rtio/rtio_api/src/rtio_iodev_test.h b/tests/subsys/rtio/rtio_api/src/rtio_iodev_test.h index 67a412d819ee4..f478ec695ccdb 100644 --- a/tests/subsys/rtio/rtio_api/src/rtio_iodev_test.h +++ b/tests/subsys/rtio/rtio_api/src/rtio_iodev_test.h @@ -16,7 +16,10 @@ struct rtio_iodev_test_data { /* k_timer for an asynchronous task */ struct k_timer timer; - /* Currently executing sqe */ + /* Queue of requests */ + struct rtio_mpsc io_q; + + /* Currently executing transaction */ struct rtio_iodev_sqe *txn_head; struct rtio_iodev_sqe *txn_curr; @@ -27,86 +30,76 @@ struct rtio_iodev_test_data { struct k_spinlock lock; }; -static void rtio_iodev_test_next(struct rtio_iodev *iodev) +static void rtio_iodev_test_next(struct rtio_iodev_test_data *data, bool completion) { - struct rtio_iodev_test_data *data = iodev->data; - /* The next section must be serialized to ensure single consumer semantics */ k_spinlock_key_t key = k_spin_lock(&data->lock); - if (data->txn_head != NULL) { + /* Already working on something, bail early */ + if (!completion && data->txn_head != NULL) { goto out; } - struct rtio_mpsc_node *next = rtio_mpsc_pop(&iodev->iodev_sq); + struct rtio_mpsc_node *next = rtio_mpsc_pop(&data->io_q); - if (next != NULL) { - struct rtio_iodev_sqe *next_sqe = CONTAINER_OF(next, struct rtio_iodev_sqe, q); + /* Nothing left to do, cleanup */ + if (next == NULL) { + data->txn_head = NULL; + data->txn_curr = NULL; + goto out; + } - TC_PRINT("next task in queue %p\n", (void *)next_sqe); + struct rtio_iodev_sqe *next_sqe = CONTAINER_OF(next, struct rtio_iodev_sqe, q); - data->txn_head = next_sqe; - data->txn_curr = next_sqe; - k_timer_start(&data->timer, K_MSEC(10), K_NO_WAIT); - } else { - TC_PRINT("no more tasks in the queue\n"); - } + data->txn_head = next_sqe; + data->txn_curr = next_sqe; + k_timer_start(&data->timer, K_MSEC(10), K_NO_WAIT); out: k_spin_unlock(&data->lock, key); } -static void rtio_iodev_timer_fn(struct k_timer *tm) +static void rtio_iodev_test_complete(struct rtio_iodev_test_data *data, int status) { - static struct rtio_iodev_sqe *last_iodev_sqe; - static int consecutive_sqes; - - struct rtio_iodev_test_data *data = CONTAINER_OF(tm, struct rtio_iodev_test_data, timer); - struct rtio_iodev_sqe *iodev_sqe = data->txn_curr; - struct rtio_iodev *iodev = (struct rtio_iodev *)data->txn_head->sqe.iodev; - - if (iodev_sqe == last_iodev_sqe) { - consecutive_sqes++; - } else { - consecutive_sqes = 0; + if (status < 0) { + rtio_iodev_sqe_err(data->txn_head, status); + rtio_iodev_test_next(data, true); } - last_iodev_sqe = iodev_sqe; - if (iodev_sqe->sqe.op == RTIO_OP_RX) { - uint8_t *buf; - uint32_t buf_len; + data->txn_curr = rtio_txn_next(data->txn_curr); + if (data->txn_curr) { + k_timer_start(&data->timer, K_MSEC(10), K_NO_WAIT); + return; + } - int rc = rtio_sqe_rx_buf(iodev_sqe, 16, 16, &buf, &buf_len); + rtio_iodev_sqe_ok(data->txn_head, status); + rtio_iodev_test_next(data, true); +} +static void rtio_iodev_timer_fn(struct k_timer *tm) +{ + struct rtio_iodev_test_data *data = CONTAINER_OF(tm, struct rtio_iodev_test_data, timer); + struct rtio_iodev_sqe *iodev_sqe = data->txn_curr; + uint8_t *buf; + uint32_t buf_len; + int rc; + + switch (iodev_sqe->sqe.op) { + case RTIO_OP_NOP: + rtio_iodev_test_complete(data, 0); + break; + case RTIO_OP_RX: + rc = rtio_sqe_rx_buf(iodev_sqe, 16, 16, &buf, &buf_len); if (rc != 0) { - iodev_sqe = data->txn_head; - data->txn_head = NULL; - data->txn_curr = NULL; - rtio_iodev_sqe_err(iodev_sqe, rc); - rtio_iodev_test_next(iodev); + rtio_iodev_test_complete(data, rc); return; } - - for (int i = 0; i < 16; ++i) { - buf[i] = ((uint8_t *)iodev_sqe->sqe.userdata)[i]; - } - } - - if (iodev_sqe->sqe.flags & RTIO_SQE_TRANSACTION) { - data->txn_curr = rtio_txn_next(data->txn_curr); - TC_PRINT("iodev_sqe %p marked transaction, next %p\n", iodev_sqe, data->txn_curr); - k_timer_start(tm, K_MSEC(10), K_NO_WAIT); - return; - } - - iodev_sqe = data->txn_head; - data->txn_head = NULL; - data->txn_curr = NULL; - rtio_iodev_test_next(iodev); - if (consecutive_sqes == 0) { - rtio_iodev_sqe_ok(iodev_sqe, 0); - } else { - rtio_iodev_sqe_err(iodev_sqe, consecutive_sqes); + /* For reads the test device copies from the given userdata */ + memcpy(buf, ((uint8_t *)iodev_sqe->sqe.userdata), 16); + rtio_iodev_test_complete(data, 0); + break; + default: + rtio_iodev_test_complete(data, -ENOTSUP); } } @@ -117,10 +110,10 @@ static void rtio_iodev_test_submit(struct rtio_iodev_sqe *iodev_sqe) atomic_inc(&data->submit_count); - /* The only safe operation is enqueuing */ - rtio_mpsc_push(&iodev->iodev_sq, &iodev_sqe->q); + /* The only safe operation is enqueuing without a lock */ + rtio_mpsc_push(&data->io_q, &iodev_sqe->q); - rtio_iodev_test_next(iodev); + rtio_iodev_test_next(data, false); } const struct rtio_iodev_api rtio_iodev_test_api = { @@ -131,7 +124,7 @@ void rtio_iodev_test_init(struct rtio_iodev *test) { struct rtio_iodev_test_data *data = test->data; - rtio_mpsc_init(&test->iodev_sq); + rtio_mpsc_init(&data->io_q); data->txn_head = NULL; data->txn_curr = NULL; k_timer_init(&data->timer, rtio_iodev_timer_fn, NULL); diff --git a/tests/subsys/rtio/rtio_api/src/test_rtio_api.c b/tests/subsys/rtio/rtio_api/src/test_rtio_api.c index 05fcb724db1d0..7a92859eba1dc 100644 --- a/tests/subsys/rtio/rtio_api/src/test_rtio_api.c +++ b/tests/subsys/rtio/rtio_api/src/test_rtio_api.c @@ -365,24 +365,46 @@ static void test_rtio_chain_cancel_(struct rtio *r) struct rtio_sqe *handle; /* Prepare the chain */ - TC_PRINT("1\n"); - k_msleep(20); rtio_sqe_prep_nop(&sqe[0], (struct rtio_iodev *)&iodev_test_simple, NULL); rtio_sqe_prep_nop(&sqe[1], (struct rtio_iodev *)&iodev_test_simple, NULL); sqe[0].flags |= RTIO_SQE_CHAINED; /* Copy the chain */ - TC_PRINT("2\n"); - k_msleep(20); rtio_sqe_copy_in_get_handles(r, sqe, &handle, 2); - TC_PRINT("3\n"); - k_msleep(20); rtio_sqe_cancel(handle); - TC_PRINT("Submitting 2 to RTIO\n"); k_msleep(20); rtio_submit(r, 0); - /* Check that we don't get a CQE */ + /* Check that we don't get cancelled completion notifications */ + zassert_equal(0, rtio_cqe_copy_out(r, &cqe, 1, K_MSEC(15))); + + /* Check that the SQE pool is empty by filling it all the way */ + for (int i = 0; i < SQE_POOL_SIZE; ++i) { + rtio_sqe_prep_nop(&sqe[i], (struct rtio_iodev *)&iodev_test_simple, NULL); + } + zassert_ok(rtio_sqe_copy_in(r, sqe, SQE_POOL_SIZE)); + + /* Since there's no good way to just reset the RTIO context, wait for the nops to finish */ + rtio_submit(r, SQE_POOL_SIZE); + for (int i = 0; i < SQE_POOL_SIZE; ++i) { + zassert_equal(1, rtio_cqe_copy_out(r, &cqe, 1, K_FOREVER)); + } + + /* Try cancelling the middle sqe in a chain */ + rtio_sqe_prep_nop(&sqe[0], (struct rtio_iodev *)&iodev_test_simple, NULL); + rtio_sqe_prep_nop(&sqe[1], (struct rtio_iodev *)&iodev_test_simple, NULL); + rtio_sqe_prep_nop(&sqe[2], (struct rtio_iodev *)&iodev_test_simple, NULL); + sqe[0].flags |= RTIO_SQE_CHAINED; + sqe[1].flags |= RTIO_SQE_CHAINED | RTIO_SQE_CANCELED; + + /* Copy in the first non cancelled sqe */ + rtio_sqe_copy_in_get_handles(r, sqe, &handle, 3); + rtio_submit(r, 1); + + /* Check that we get one completion no cancellation notifications */ + zassert_equal(1, rtio_cqe_copy_out(r, &cqe, 1, K_MSEC(15))); + + /* Check that we get no more completions for the cancelled submissions */ zassert_equal(0, rtio_cqe_copy_out(r, &cqe, 1, K_MSEC(15))); /* Check that the SQE pool is empty by filling it all the way */ @@ -488,7 +510,7 @@ static inline void test_rtio_simple_multishot_(struct rtio *r, int idx) TC_PRINT("Waiting for next cqe\n"); zassert_equal(1, rtio_cqe_copy_out(r, &cqe, 1, K_FOREVER)); - zassert_equal(1, cqe.result, "Result should be ok but got %d", cqe.result); + zassert_ok(cqe.result, "Result should be ok but got %d", cqe.result); zassert_equal_ptr(cqe.userdata, mempool_data, "Expected userdata back"); rtio_cqe_get_mempool_buffer(r, &cqe, &buffer, &buffer_len); rtio_release_buffer(r, buffer, buffer_len); @@ -538,9 +560,7 @@ void test_rtio_transaction_(struct rtio *r) sqe = rtio_sqe_acquire(r); zassert_not_null(sqe, "Expected a valid sqe"); - rtio_sqe_prep_nop(sqe, NULL, - &userdata[0]); - + rtio_sqe_prep_nop(sqe, NULL, &userdata[0]); sqe = rtio_sqe_acquire(r); zassert_not_null(sqe, "Expected a valid sqe"); @@ -632,6 +652,86 @@ ZTEST(rtio_api, test_rtio_throughput) _test_rtio_throughput(&r_throughput); } +RTIO_DEFINE(r_callback_chaining, SQE_POOL_SIZE, CQE_POOL_SIZE); +RTIO_IODEV_TEST_DEFINE(iodev_test_callback_chaining0); + +/** + * Callback for testing with + */ +void rtio_callback_chaining_cb(struct rtio *r, const struct rtio_sqe *sqe, void *arg0) +{ + TC_PRINT("chaining callback with userdata %p\n", arg0); +} + +/** + * @brief Test callback chaining requests + * + * Ensures that we can setup an RTIO context, enqueue a transaction of requests, + * receive completion events, and catch a callback at the end in the correct + * order + */ +void test_rtio_callback_chaining_(struct rtio *r) +{ + + int res; + int32_t userdata[4] = {0, 1, 2, 3}; + int32_t ordering[4] = { -1, -1, -1, -1}; + struct rtio_sqe *sqe; + struct rtio_cqe *cqe; + uintptr_t cq_count = atomic_get(&r->cq_count); + + rtio_iodev_test_init(&iodev_test_callback_chaining0); + + sqe = rtio_sqe_acquire(r); + zassert_not_null(sqe, "Expected a valid sqe"); + rtio_sqe_prep_callback(sqe, &rtio_callback_chaining_cb, sqe, &userdata[0]); + sqe->flags |= RTIO_SQE_CHAINED; + + sqe = rtio_sqe_acquire(r); + zassert_not_null(sqe, "Expected a valid sqe"); + rtio_sqe_prep_nop(sqe, &iodev_test_callback_chaining0, &userdata[1]); + sqe->flags |= RTIO_SQE_TRANSACTION; + + sqe = rtio_sqe_acquire(r); + zassert_not_null(sqe, "Expected a valid sqe"); + rtio_sqe_prep_nop(sqe, &iodev_test_callback_chaining0, &userdata[2]); + sqe->flags |= RTIO_SQE_CHAINED; + + sqe = rtio_sqe_acquire(r); + zassert_not_null(sqe, "Expected a valid sqe"); + rtio_sqe_prep_callback(sqe, &rtio_callback_chaining_cb, sqe, &userdata[3]); + + TC_PRINT("submitting\n"); + res = rtio_submit(r, 4); + TC_PRINT("checking cq, completions available, count at start %lu, current count %lu\n", + cq_count, atomic_get(&r->cq_count)); + zassert_ok(res, "Should return ok from rtio_execute"); + zassert_equal(atomic_get(&r->cq_count) - cq_count, 4, "Should have 4 pending completions"); + + for (int i = 0; i < 4; i++) { + TC_PRINT("consume %d\n", i); + cqe = rtio_cqe_consume(r); + zassert_not_null(cqe, "Expected a valid cqe"); + zassert_ok(cqe->result, "Result should be ok"); + + int32_t idx = *(int32_t *)cqe->userdata; + + TC_PRINT("userdata is %p, value %d\n", cqe->userdata, idx); + ordering[idx] = i; + + rtio_cqe_release(r, cqe); + } + + for (int i = 0; i < 4; i++) { + zassert_equal(ordering[i], i, + "Execpted ordering of completions to match submissions"); + } +} + +ZTEST(rtio_api, test_rtio_callback_chaining) +{ + test_rtio_callback_chaining_(&r_callback_chaining); +} static void *rtio_api_setup(void) { From c1400536548bb861c630f81d8aced864f1a85ca1 Mon Sep 17 00:00:00 2001 From: Ioannis Karachalios Date: Wed, 1 May 2024 12:57:48 +0300 Subject: [PATCH 1324/2849] drivers: i2c: smartbond: Add support for PM This commit should add all the functionality needed for the I2C driver to work when PM is enabled. Signed-off-by: Ioannis Karachalios --- .../da1469x_dk_pro-pinctrl.dtsi | 17 +++ .../renesas/da1469x_dk_pro/da1469x_dk_pro.dts | 6 +- .../dts/da1469x_dk_pro_lcdc.overlay | 2 +- drivers/i2c/i2c_smartbond.c | 116 +++++++++++++++++- 4 files changed, 134 insertions(+), 7 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 0a90af9a63cf4..032a2e0d53909 100644 --- a/boards/renesas/da1469x_dk_pro/da1469x_dk_pro-pinctrl.dtsi +++ b/boards/renesas/da1469x_dk_pro/da1469x_dk_pro-pinctrl.dtsi @@ -24,6 +24,15 @@ }; }; + /omit-if-no-ref/ i2c_sleep: i2c_sleep { + group1 { + pinmux = , + ; + bias-pull-up; + + }; + }; + i2c2_default: i2c2_default { group1 { pinmux = , @@ -32,6 +41,14 @@ }; }; + /omit-if-no-ref/ i2c2_sleep: i2c2_sleep { + group1 { + pinmux = , + ; + bias-pull-up; + }; + }; + display_controller_default: display_controller_default { group1 { pinmux = , diff --git a/boards/renesas/da1469x_dk_pro/da1469x_dk_pro.dts b/boards/renesas/da1469x_dk_pro/da1469x_dk_pro.dts index f4a3d1d674ee4..bc3c19d321583 100644 --- a/boards/renesas/da1469x_dk_pro/da1469x_dk_pro.dts +++ b/boards/renesas/da1469x_dk_pro/da1469x_dk_pro.dts @@ -153,13 +153,15 @@ zephyr_udc0: &usbd { &i2c { status = "okay"; pinctrl-0 = <&i2c_default>; - pinctrl-names = "default"; + pinctrl-1 = <&i2c_sleep>; + pinctrl-names = "default", "sleep"; }; &i2c2 { status = "okay"; pinctrl-0 = <&i2c2_default>; - pinctrl-names = "default"; + pinctrl-1 = <&i2c2_sleep>; + pinctrl-names = "default", "sleep"; }; &spi { 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 197882b5536f6..4b522837df93c 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 @@ -36,7 +36,7 @@ group1 { pinmux = , ; - bias-pull-down; + bias-pull-up; }; }; }; diff --git a/drivers/i2c/i2c_smartbond.c b/drivers/i2c/i2c_smartbond.c index d0b7ee20b453d..38fb9255ed135 100644 --- a/drivers/i2c/i2c_smartbond.c +++ b/drivers/i2c/i2c_smartbond.c @@ -11,6 +11,10 @@ #include #include #include +#include +#include +#include +#include #include LOG_MODULE_REGISTER(i2c_smartbond); @@ -31,8 +35,36 @@ struct i2c_smartbond_data { uint32_t transmit_cnt, receive_cnt; i2c_callback_t cb; void *userdata; +#if defined(CONFIG_PM_DEVICE) || defined(CONFIG_PM_DEVICE_RUNTIME) + ATOMIC_DEFINE(pm_policy_state_flag, 1); +#endif }; +static inline void i2c_smartbond_pm_policy_state_lock_get(struct i2c_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 I2C events. + */ + pm_policy_state_lock_get(PM_STATE_STANDBY, PM_ALL_SUBSTATES); + } +#endif +} + +static inline void i2c_smartbond_pm_policy_state_lock_put(struct i2c_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 I2C transactions are done. + */ + pm_policy_state_lock_put(PM_STATE_STANDBY, PM_ALL_SUBSTATES); + } +#endif +} + static int i2c_smartbond_configure(const struct device *dev, uint32_t dev_config) { const struct i2c_smartbond_cfg *config = dev->config; @@ -149,6 +181,7 @@ static inline void i2c_smartbond_set_target_address(const struct i2c_smartbond_c } else { config->regs->I2C_CON_REG &= ~(I2C_I2C_CON_REG_I2C_10BITADDR_MASTER_Msk); } + /* Change the Target Address */ config->regs->I2C_TAR_REG = ((config->regs->I2C_TAR_REG & ~I2C_I2C_TAR_REG_IC_TAR_Msk) | (addr & I2C_I2C_TAR_REG_IC_TAR_Msk)); @@ -294,6 +327,8 @@ static int i2c_smartbond_transfer(const struct device *dev, struct i2c_msg *msgs return ret; } + i2c_smartbond_pm_policy_state_lock_get(data); + for (; data->num_msgs > 0; data->num_msgs--, data->msgs++) { data->transmit_cnt = 0; data->receive_cnt = 0; @@ -323,6 +358,7 @@ static int i2c_smartbond_transfer(const struct device *dev, struct i2c_msg *msgs } finish: + i2c_smartbond_pm_policy_state_lock_put(data); return ret; } @@ -377,6 +413,8 @@ static int i2c_smartbond_transfer_cb(const struct device *dev, struct i2c_msg *m return ret; } + i2c_smartbond_pm_policy_state_lock_get(data); + i2c_smartbond_enable_msg_interrupts(config, data); LOG_INF("async transfer started"); @@ -441,6 +479,7 @@ static inline void i2c_smartbond_async_msg_done(const struct device *dev) data->cb = NULL; LOG_INF("async transfer finished"); cb(dev, 0, data->userdata); + i2c_smartbond_pm_policy_state_lock_put(data); } } @@ -493,7 +532,7 @@ static const struct i2c_driver_api i2c_smartbond_driver_api = { #endif }; -static int i2c_smartbond_init(const struct device *dev) +static int i2c_smartbond_resume(const struct device *dev) { const struct i2c_smartbond_cfg *config = dev->config; int err; @@ -515,7 +554,75 @@ static int i2c_smartbond_init(const struct device *dev) I2C_MODE_CONTROLLER | i2c_map_dt_bitrate(config->bitrate)); } +#if defined(CONFIG_PM_DEVICE) || defined(CONFIG_PM_DEVICE_RUNTIME) +static int i2c_smartbond_suspend(const struct device *dev) +{ + int ret; + const struct i2c_smartbond_cfg *config = dev->config; + + /* Disable the I2C digital block */ + config->regs->I2C_ENABLE_REG &= ~I2C_I2C_ENABLE_REG_I2C_EN_Msk; + /* Gate I2C clocking */ + CRG_COM->RESET_CLK_COM_REG = config->periph_clock_config; + + ret = pinctrl_apply_state(config->pcfg, PINCTRL_STATE_SLEEP); + if (ret < 0) { + LOG_WRN("Fialid to configure the I2C pins to inactive state"); + } + + return ret; +} + +static int i2c_smartbond_pm_action(const struct device *dev, + enum pm_device_action action) +{ + int ret = 0; + + switch (action) { + case PM_DEVICE_ACTION_RESUME: + /* + * Although the GPIO driver should already be initialized, make sure PD_COM + * is up and running before accessing the I2C block. + */ + da1469x_pd_acquire(MCU_PD_DOMAIN_COM); + ret = i2c_smartbond_resume(dev); + break; + case PM_DEVICE_ACTION_SUSPEND: + ret = i2c_smartbond_suspend(dev); + /* + * Once the I2C block is turned off its power domain can + * be released, as well. + */ + da1469x_pd_release(MCU_PD_DOMAIN_COM); + break; + default: + return -ENOTSUP; + } + + return ret; +} +#endif + + +static int i2c_smartbond_init(const struct device *dev) +{ + int ret; + +#ifdef CONFIG_PM_DEVICE_RUNTIME + /* Make sure device state is marked as suspended */ + pm_device_init_suspended(dev); + + ret = pm_device_runtime_enable(dev); +#else + da1469x_pd_acquire(MCU_PD_DOMAIN_COM); + ret = i2c_smartbond_resume(dev); +#endif + + return ret; +} + #define I2C_SMARTBOND_DEVICE(id) \ + PM_DEVICE_DT_INST_DEFINE(id, i2c_smartbond_pm_action); \ PINCTRL_DT_INST_DEFINE(id); \ static const struct i2c_smartbond_cfg i2c_smartbond_##id##_cfg = { \ .regs = (I2C_Type *)DT_INST_REG_ADDR(id), \ @@ -529,8 +636,9 @@ static int i2c_smartbond_init(const struct device *dev) I2C_SMARTBOND_CONFIGURE(id); \ return ret; \ } \ - I2C_DEVICE_DT_INST_DEFINE(id, i2c_smartbond_##id##_init, NULL, &i2c_smartbond_##id##_data, \ - &i2c_smartbond_##id##_cfg, POST_KERNEL, \ - CONFIG_I2C_INIT_PRIORITY, &i2c_smartbond_driver_api); + I2C_DEVICE_DT_INST_DEFINE(id, i2c_smartbond_##id##_init, PM_DEVICE_DT_INST_GET(id), \ + &i2c_smartbond_##id##_data, \ + &i2c_smartbond_##id##_cfg, POST_KERNEL, \ + CONFIG_I2C_INIT_PRIORITY, &i2c_smartbond_driver_api); DT_INST_FOREACH_STATUS_OKAY(I2C_SMARTBOND_DEVICE) From b1b61babecc6f51b5c4bf34cdccc45196b698efa Mon Sep 17 00:00:00 2001 From: Emil Gydesen Date: Mon, 27 May 2024 12:32:57 +0200 Subject: [PATCH 1325/2849] doc: Migration guide: Fix bad formatting for LE Audio The two items for LE Audio had some formatting issues. Signed-off-by: Emil Gydesen --- doc/releases/migration-guide-3.7.rst | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/doc/releases/migration-guide-3.7.rst b/doc/releases/migration-guide-3.7.rst index d39890f43cffa..4d40baa6f4e2b 100644 --- a/doc/releases/migration-guide-3.7.rst +++ b/doc/releases/migration-guide-3.7.rst @@ -428,11 +428,12 @@ Bluetooth Audio =============== * :kconfig:option:`CONFIG_BT_ASCS`, :kconfig:option:`CONFIG_BT_PERIPHERAL` and - :kconfig:option:`CONFIG_BT_ISO_PERIPHERAL` are not longer `select`ed automatically when + :kconfig:option:`CONFIG_BT_ISO_PERIPHERAL` are no longer enabled 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 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`) From ae0822d0bfd149558c968d32c7bc7ae11164ee8e Mon Sep 17 00:00:00 2001 From: Jakub Zymelka Date: Mon, 27 May 2024 11:15:44 +0200 Subject: [PATCH 1326/2849] tests: drivers: uart: Add nrf54l15/cpuflpr overlays to test scope Adding a separate overlay for nrf54l15 flpr is required because running tests on console uart fails. Signed-off-by: Jakub Zymelka --- .../nrf54l15pdk_nrf54l15_cpuflpr.overlay | 30 +++++++++++ .../nrf54l15pdk_nrf54l15_cpuflpr.overlay | 31 +++++++++++ ...4l15pdk_nrf54l15_cpuflpr_dual_uart.overlay | 51 +++++++++++++++++++ .../uart/uart_elementary/testcase.yaml | 16 ++++++ 4 files changed, 128 insertions(+) create mode 100644 tests/drivers/uart/uart_async_api/boards/nrf54l15pdk_nrf54l15_cpuflpr.overlay create mode 100644 tests/drivers/uart/uart_elementary/boards/nrf54l15pdk_nrf54l15_cpuflpr.overlay create mode 100644 tests/drivers/uart/uart_elementary/boards/nrf54l15pdk_nrf54l15_cpuflpr_dual_uart.overlay diff --git a/tests/drivers/uart/uart_async_api/boards/nrf54l15pdk_nrf54l15_cpuflpr.overlay b/tests/drivers/uart/uart_async_api/boards/nrf54l15pdk_nrf54l15_cpuflpr.overlay new file mode 100644 index 0000000000000..1b4f1c8f71e31 --- /dev/null +++ b/tests/drivers/uart/uart_async_api/boards/nrf54l15pdk_nrf54l15_cpuflpr.overlay @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&pinctrl { + uart21_default: uart21_default { + group1 { + psels = , + ; + }; + }; + + uart21_sleep: uart21_sleep { + group1 { + psels = , + ; + low-power-enable; + }; + }; +}; + +dut: &uart21 { + status = "okay"; + current-speed = <115200>; + pinctrl-0 = <&uart21_default>; + pinctrl-1 = <&uart21_sleep>; + pinctrl-names = "default", "sleep"; +}; diff --git a/tests/drivers/uart/uart_elementary/boards/nrf54l15pdk_nrf54l15_cpuflpr.overlay b/tests/drivers/uart/uart_elementary/boards/nrf54l15pdk_nrf54l15_cpuflpr.overlay new file mode 100644 index 0000000000000..cf481b7a16144 --- /dev/null +++ b/tests/drivers/uart/uart_elementary/boards/nrf54l15pdk_nrf54l15_cpuflpr.overlay @@ -0,0 +1,31 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +&pinctrl { + uart21_default: uart21_default { + group1 { + psels = , + , + , + ; + }; + }; + + uart21_sleep: uart21_sleep { + group1 { + psels = , + , + , + ; + low-power-enable; + }; + }; +}; + +dut: &uart21 { + status = "okay"; + current-speed = <115200>; + pinctrl-0 = <&uart21_default>; + pinctrl-1 = <&uart21_sleep>; + pinctrl-names = "default", "sleep"; + hw-flow-control; +}; diff --git a/tests/drivers/uart/uart_elementary/boards/nrf54l15pdk_nrf54l15_cpuflpr_dual_uart.overlay b/tests/drivers/uart/uart_elementary/boards/nrf54l15pdk_nrf54l15_cpuflpr_dual_uart.overlay new file mode 100644 index 0000000000000..2031f7a244413 --- /dev/null +++ b/tests/drivers/uart/uart_elementary/boards/nrf54l15pdk_nrf54l15_cpuflpr_dual_uart.overlay @@ -0,0 +1,51 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +&pinctrl { + uart21_default: uart21_default { + group1 { + psels = , + ; + bias-pull-up; + }; + }; + + uart21_sleep: uart21_sleep { + group1 { + psels = , + ; + low-power-enable; + }; + }; + + uart22_default: uart22_default { + group1 { + psels = , + ; + bias-pull-up; + }; + }; + + uart22_sleep: uart22_sleep { + group1 { + psels = , + ; + low-power-enable; + }; + }; +}; + +dut: &uart21 { + status = "okay"; + current-speed = <115200>; + pinctrl-0 = <&uart21_default>; + pinctrl-1 = <&uart21_sleep>; + pinctrl-names = "default", "sleep"; +}; + +dut_aux: &uart22 { + status = "okay"; + current-speed = <115200>; + pinctrl-0 = <&uart22_default>; + pinctrl-1 = <&uart22_sleep>; + pinctrl-names = "default", "sleep"; +}; diff --git a/tests/drivers/uart/uart_elementary/testcase.yaml b/tests/drivers/uart/uart_elementary/testcase.yaml index d8aa90d0536a6..e8f0184eff3bc 100644 --- a/tests/drivers/uart/uart_elementary/testcase.yaml +++ b/tests/drivers/uart/uart_elementary/testcase.yaml @@ -10,6 +10,7 @@ tests: platform_allow: - nrf54h20dk/nrf54h20/cpuapp - nrf54l15pdk/nrf54l15/cpuapp + - nrf54l15pdk/nrf54l15/cpuflpr - nrf5340dk/nrf5340/cpuapp drivers.uart.uart_elementary_dual_nrf54h: filter: CONFIG_SERIAL_SUPPORT_INTERRUPT @@ -41,3 +42,18 @@ tests: extra_configs: - CONFIG_DUAL_UART_TEST=y - CONFIG_SETUP_MISMATCH_TEST=y + drivers.uart.uart_elementary_dual_nrf54l_cpuflpr: + filter: CONFIG_SERIAL_SUPPORT_INTERRUPT + platform_allow: + - nrf54l15pdk/nrf54l15/cpuflpr + extra_args: DTC_OVERLAY_FILE="boards/nrf54l15pdk_nrf54l15_cpuflpr_dual_uart.overlay" + extra_configs: + - CONFIG_DUAL_UART_TEST=y + drivers.uart.uart_elementary_dual_setup_mismatch_nrf54l_cpuflpr: + filter: CONFIG_SERIAL_SUPPORT_INTERRUPT + platform_allow: + - nrf54l15pdk/nrf54l15/cpuflpr + extra_args: DTC_OVERLAY_FILE="boards/nrf54l15pdk_nrf54l15_cpuflpr_dual_uart.overlay" + extra_configs: + - CONFIG_DUAL_UART_TEST=y + - CONFIG_SETUP_MISMATCH_TEST=y From e17b3fd884c8090ae2a1e56d4c999103800254da Mon Sep 17 00:00:00 2001 From: Marcin Szymczyk Date: Thu, 23 May 2024 17:02:23 +0200 Subject: [PATCH 1327/2849] arch: riscv: implement `arch_irq_disconnect_dynamic` For SoC with `CONFIG_RISCV_RESERVED_IRQ_ISR_TABLES_OFFSET`, it should be taken into consideration when disconnecting IRQ. Signed-off-by: Marcin Szymczyk --- arch/riscv/core/irq_manage.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/arch/riscv/core/irq_manage.c b/arch/riscv/core/irq_manage.c index b60deceefab25..358b07534be69 100644 --- a/arch/riscv/core/irq_manage.c +++ b/arch/riscv/core/irq_manage.c @@ -9,6 +9,7 @@ #include #include #include +#include #ifdef CONFIG_RISCV_HAS_PLIC #include @@ -53,4 +54,17 @@ int arch_irq_connect_dynamic(unsigned int irq, unsigned int priority, #endif return irq; } + +#ifdef CONFIG_SHARED_INTERRUPTS +int arch_irq_disconnect_dynamic(unsigned int irq, unsigned int priority, + void (*routine)(const void *parameter), const void *parameter, + uint32_t flags) +{ + ARG_UNUSED(priority); + ARG_UNUSED(flags); + + return z_isr_uninstall(irq + CONFIG_RISCV_RESERVED_IRQ_ISR_TABLES_OFFSET, routine, + parameter); +} +#endif /* CONFIG_SHARED_INTERRUPTS */ #endif /* CONFIG_DYNAMIC_INTERRUPTS */ From 68c48cd1168e409cb64170f6fb5c7925e1e935f8 Mon Sep 17 00:00:00 2001 From: Marcin Szymczyk Date: Thu, 23 May 2024 17:03:40 +0200 Subject: [PATCH 1328/2849] tests: kernel: interrupt: account for table offset When verifying sw_isr_table, take into account custom offset, like `CONFIG_RISCV_RESERVED_IRQ_ISR_TABLES_OFFSET` in some RISC-V SoCs. Relates to #71948 and #73232. Signed-off-by: Marcin Szymczyk --- .../kernel/interrupt/src/dynamic_shared_irq.c | 38 +++++++++++-------- 1 file changed, 23 insertions(+), 15 deletions(-) diff --git a/tests/kernel/interrupt/src/dynamic_shared_irq.c b/tests/kernel/interrupt/src/dynamic_shared_irq.c index db7bc1a688ce5..a439bac278dea 100644 --- a/tests/kernel/interrupt/src/dynamic_shared_irq.c +++ b/tests/kernel/interrupt/src/dynamic_shared_irq.c @@ -97,6 +97,12 @@ static void *dynamic_shared_irq_suite_setup(void) return NULL; } +#if defined(CONFIG_RISCV_RESERVED_IRQ_ISR_TABLES_OFFSET) +#define TABLE_OFFSET CONFIG_RISCV_RESERVED_IRQ_ISR_TABLES_OFFSET +#else +#define TABLE_OFFSET 0 +#endif + static void dynamic_shared_irq_suite_before(void *data) { ARG_UNUSED(data); @@ -104,37 +110,39 @@ static void dynamic_shared_irq_suite_before(void *data) arch_irq_connect_dynamic(fixture.irq1, fixture.irq_priority, test_isr_0, 0, 0); - zassert_true(_sw_isr_table[fixture.irq1_table_idx].isr == test_isr_0, + zassert_true(_sw_isr_table[fixture.irq1_table_idx + TABLE_OFFSET].isr == test_isr_0, "wrong _sw_isr_table ISR at irq1"); - zassert_true(!_sw_isr_table[fixture.irq1_table_idx].arg, + zassert_true(!_sw_isr_table[fixture.irq1_table_idx + TABLE_OFFSET].arg, "wrong _sw_isr_table argument at irq1"); - zassert_true(!z_shared_sw_isr_table[fixture.irq1_table_idx].client_num, + zassert_true(!z_shared_sw_isr_table[fixture.irq1_table_idx + TABLE_OFFSET].client_num, "wrong client number at irq1"); arch_irq_connect_dynamic(fixture.irq1, fixture.irq_priority, test_isr_1, (void *)1, 0); - zassert_true(_sw_isr_table[fixture.irq1_table_idx].isr == z_shared_isr, + zassert_true(_sw_isr_table[fixture.irq1_table_idx + TABLE_OFFSET].isr == z_shared_isr, "wrong _sw_isr_table ISR at irq1"); - zassert_true(_sw_isr_table[fixture.irq1_table_idx].arg == - &z_shared_sw_isr_table[fixture.irq1_table_idx], + zassert_true(_sw_isr_table[fixture.irq1_table_idx + TABLE_OFFSET].arg == + &z_shared_sw_isr_table[fixture.irq1_table_idx + TABLE_OFFSET], "wrong _sw_isr_table argument at irq1"); - zassert_true(z_shared_sw_isr_table[fixture.irq1_table_idx].client_num == 2, + zassert_true(z_shared_sw_isr_table[fixture.irq1_table_idx + TABLE_OFFSET].client_num == 2, "wrong client number at irq1"); - zassert_true(client_exists_at_index(test_isr_0, 0, fixture.irq1_table_idx, 0), + zassert_true(client_exists_at_index(test_isr_0, 0, fixture.irq1_table_idx + TABLE_OFFSET, + 0), "unexpected client data for irq1, index 0"); - zassert_true(client_exists_at_index(test_isr_1, (void *)1, fixture.irq1_table_idx, 1), + zassert_true(client_exists_at_index(test_isr_1, (void *)1, + fixture.irq1_table_idx + TABLE_OFFSET, 1), "unexpected client data for irq1, index 1"); arch_irq_connect_dynamic(fixture.irq2, fixture.irq_priority, test_isr_2, (void *)2, 0); - zassert_true(_sw_isr_table[fixture.irq2_table_idx].isr == test_isr_2, + zassert_true(_sw_isr_table[fixture.irq2_table_idx + TABLE_OFFSET].isr == test_isr_2, "wrong _sw_isr_table ISR at irq2"); - zassert_true(_sw_isr_table[fixture.irq2_table_idx].arg == (void *)2, + zassert_true(_sw_isr_table[fixture.irq2_table_idx + TABLE_OFFSET].arg == (void *)2, "wrong _sw_isr_table argument at irq2"); - zassert_true(!z_shared_sw_isr_table[fixture.irq2_table_idx].client_num, + zassert_true(!z_shared_sw_isr_table[fixture.irq2_table_idx + TABLE_OFFSET].client_num, "wrong client number at irq2"); reset_test_vector(); @@ -191,11 +199,11 @@ ZTEST(shared_irq_feature, test_dynamic_shared_irq_disconnect_write) arch_irq_disconnect_dynamic(fixture.irq1, fixture.irq_priority, test_isr_0, 0, 0); - zassert_true(_sw_isr_table[fixture.irq1_table_idx].isr == test_isr_1, + zassert_true(_sw_isr_table[fixture.irq1_table_idx + TABLE_OFFSET].isr == test_isr_1, "wrong _sw_isr_table ISR at irq1"); - zassert_true(_sw_isr_table[fixture.irq1_table_idx].arg == (void *)1, + zassert_true(_sw_isr_table[fixture.irq1_table_idx + TABLE_OFFSET].arg == (void *)1, "wrong _sw_isr_table arg at irq1"); - zassert_true(!z_shared_sw_isr_table[fixture.irq1_table_idx].client_num, + zassert_true(!z_shared_sw_isr_table[fixture.irq1_table_idx + TABLE_OFFSET].client_num, "wrong client number at irq1"); irq_enable(fixture.irq1); From 88fb5e2edbbe1edf48778fbe1b0e3af51d51227b Mon Sep 17 00:00:00 2001 From: Henrik Brix Andersen Date: Mon, 27 May 2024 10:29:18 +0200 Subject: [PATCH 1329/2849] drivers: can: shell: print device name in RX path Include the device name when printing received CAN frames. This improves the user experience when working with multiple CAN controllers via the CAN shell. Signed-off-by: Henrik Brix Andersen --- doc/hardware/peripherals/can/shell.rst | 18 +++++++----- drivers/can/can_shell.c | 38 ++++++++++++++++++++++---- 2 files changed, 43 insertions(+), 13 deletions(-) diff --git a/doc/hardware/peripherals/can/shell.rst b/doc/hardware/peripherals/can/shell.rst index d10759ac30246..ed36379c55ffe 100644 --- a/doc/hardware/peripherals/can/shell.rst +++ b/doc/hardware/peripherals/can/shell.rst @@ -186,16 +186,20 @@ Received CAN frames matching the added filter(s) are printed to the shell. A few .. code-block:: console - # Flags ID Size Data bytes - -- 010 [8] 01 02 03 04 05 06 07 08 - B- 010 [08] 01 02 03 04 05 06 07 08 - BP 010 [03] 01 aa bb - -- 00000010 [0] - -- 010 [1] 20 - -- 010 [8] remote transmission request + # Dev Flags ID Size Data bytes + can0 -- 010 [8] 01 02 03 04 05 06 07 08 + can0 B- 010 [08] 01 02 03 04 05 06 07 08 + can0 BP 010 [03] 01 aa bb + can0 -- 00000010 [0] + can0 -- 010 [1] 20 + can0 -- 010 [8] remote transmission request The columns have the following meaning: +* Dev + + * Name of the device receiving the frame. + * Flags * ``B``: The frame has the CAN FD Baud Rate Switch (BRS) flag set. diff --git a/drivers/can/can_shell.c b/drivers/can/can_shell.c index d7c9fd4076dc8..aaed76b9fa572 100644 --- a/drivers/can/can_shell.c +++ b/drivers/can/can_shell.c @@ -20,6 +20,11 @@ struct can_shell_tx_event { int error; }; +struct can_shell_rx_event { + struct can_frame frame; + const struct device *dev; +}; + struct can_shell_mode_mapping { const char *name; can_mode_t mode; @@ -49,7 +54,8 @@ static struct k_poll_event can_shell_tx_msgq_events[] = { &can_shell_tx_msgq, 0) }; -CAN_MSGQ_DEFINE(can_shell_rx_msgq, CONFIG_CAN_SHELL_RX_QUEUE_SIZE); +K_MSGQ_DEFINE(can_shell_rx_msgq, sizeof(struct can_shell_rx_event), + CONFIG_CAN_SHELL_RX_QUEUE_SIZE, 4); const struct shell *can_shell_rx_msgq_sh; static struct k_work_poll can_shell_rx_msgq_work; static struct k_poll_event can_shell_rx_msgq_events[] = { @@ -62,7 +68,8 @@ static struct k_poll_event can_shell_rx_msgq_events[] = { static void can_shell_tx_msgq_triggered_work_handler(struct k_work *work); static void can_shell_rx_msgq_triggered_work_handler(struct k_work *work); -static void can_shell_print_frame(const struct shell *sh, const struct can_frame *frame) +static void can_shell_print_frame(const struct shell *sh, const struct device *dev, + const struct can_frame *frame) { uint8_t nbytes = can_dlc_to_bytes(frame->dlc); int i; @@ -72,6 +79,8 @@ static void can_shell_print_frame(const struct shell *sh, const struct can_frame shell_fprintf(sh, SHELL_NORMAL, "(%05d) ", frame->timestamp); #endif /* CONFIG_CAN_RX_TIMESTAMP */ + shell_fprintf(sh, SHELL_NORMAL, "%s ", dev->name); + #ifdef CONFIG_CAN_FD_MODE /* Flags */ shell_fprintf(sh, SHELL_NORMAL, "%c%c ", @@ -156,6 +165,23 @@ static void can_shell_tx_callback(const struct device *dev, int error, void *use } } +static void can_shell_rx_callback(const struct device *dev, struct can_frame *frame, + void *user_data) +{ + struct can_shell_rx_event event; + int err; + + ARG_UNUSED(user_data); + + event.frame = *frame; + event.dev = dev; + + err = k_msgq_put(&can_shell_rx_msgq, &event, K_NO_WAIT); + if (err != 0) { + LOG_ERR("CAN shell rx event queue full"); + } +} + static int can_shell_rx_msgq_poll_submit(const struct shell *sh) { int err; @@ -177,10 +203,10 @@ static int can_shell_rx_msgq_poll_submit(const struct shell *sh) static void can_shell_rx_msgq_triggered_work_handler(struct k_work *work) { - struct can_frame frame; + struct can_shell_rx_event event; - while (k_msgq_get(&can_shell_rx_msgq, &frame, K_NO_WAIT) == 0) { - can_shell_print_frame(can_shell_rx_msgq_sh, &frame); + while (k_msgq_get(&can_shell_rx_msgq, &event, K_NO_WAIT) == 0) { + can_shell_print_frame(can_shell_rx_msgq_sh, event.dev, &event.frame); } (void)can_shell_rx_msgq_poll_submit(can_shell_rx_msgq_sh); @@ -879,7 +905,7 @@ static int cmd_can_filter_add(const struct shell *sh, size_t argc, char **argv) (filter.flags & CAN_FILTER_IDE) != 0 ? 8 : 3, filter.id, (filter.flags & CAN_FILTER_IDE) != 0 ? 8 : 3, filter.mask); - err = can_add_rx_filter_msgq(dev, &can_shell_rx_msgq, &filter); + err = can_add_rx_filter(dev, can_shell_rx_callback, NULL, &filter); if (err < 0) { shell_error(sh, "failed to add filter (err %d)", err); return err; From 245c7db0da12893e6e1c8b035bc50a7ba58458a2 Mon Sep 17 00:00:00 2001 From: Ioannis Karachalios Date: Fri, 24 May 2024 14:58:39 +0300 Subject: [PATCH 1330/2849] drivers: display: smartbond: Update PM policy Since the display port should be enabled by default and sleep is bound to the blanking status, PM constraints should be acquired at initialization. Signed-off-by: Ioannis Karachalios --- drivers/display/display_renesas_lcdc.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/display/display_renesas_lcdc.c b/drivers/display/display_renesas_lcdc.c index 2467810861735..2131b9149d3cc 100644 --- a/drivers/display/display_renesas_lcdc.c +++ b/drivers/display/display_renesas_lcdc.c @@ -345,6 +345,10 @@ static int display_smartbond_init(const struct device *dev) #else /* Resume if either PM is not used at all or if PM without runtime is used. */ ret = display_smartbond_resume(dev); + if (ret == 0) { + /* Display port should be enabled at this moment and so sleep is not allowed. */ + lcdc_smartbond_pm_policy_state_lock_get(data); + } #endif return ret; From 63d4037e2fc9b9d941101a0918a2aba89b3f6ae4 Mon Sep 17 00:00:00 2001 From: Robert Lubos Date: Fri, 24 May 2024 10:43:53 +0200 Subject: [PATCH 1331/2849] samples: net: Exclude native_posix when socket service lib is used Socket service library uses eventfd, which does not work with native_posix platform, hence need to exclude it from samples that now rely on socket services. Signed-off-by: Robert Lubos --- samples/net/dns_resolve/sample.yaml | 3 +++ samples/net/sockets/big_http_download/sample.yaml | 3 +++ samples/net/sockets/http_get/sample.yaml | 3 +++ samples/posix/gettimeofday/sample.yaml | 3 +++ 4 files changed, 12 insertions(+) diff --git a/samples/net/dns_resolve/sample.yaml b/samples/net/dns_resolve/sample.yaml index f5808607b57f4..cafc9beac83f5 100644 --- a/samples/net/dns_resolve/sample.yaml +++ b/samples/net/dns_resolve/sample.yaml @@ -4,6 +4,9 @@ common: tags: - net - dns + platform_exclude: + - native_posix + - native_posix/native/64 sample: description: DNS resolver, mDNS and LLMNR responder name: DNS resolver and responder sample application diff --git a/samples/net/sockets/big_http_download/sample.yaml b/samples/net/sockets/big_http_download/sample.yaml index b8777a4e8711d..683b8c5c52c0d 100644 --- a/samples/net/sockets/big_http_download/sample.yaml +++ b/samples/net/sockets/big_http_download/sample.yaml @@ -9,6 +9,9 @@ common: tags: - net - socket + platform_exclude: + - native_posix + - native_posix/native/64 tests: sample.net.sockets.big_http_download: extra_configs: diff --git a/samples/net/sockets/http_get/sample.yaml b/samples/net/sockets/http_get/sample.yaml index c5849561c7431..7d6ab6951a080 100644 --- a/samples/net/sockets/http_get/sample.yaml +++ b/samples/net/sockets/http_get/sample.yaml @@ -8,6 +8,9 @@ common: tags: - net - socket + platform_exclude: + - native_posix + - native_posix/native/64 tests: sample.net.sockets.http_get: filter: not CONFIG_NET_SOCKETS_OFFLOAD and not CONFIG_NATIVE_LIBC diff --git a/samples/posix/gettimeofday/sample.yaml b/samples/posix/gettimeofday/sample.yaml index a71d29f09c50a..88748aab2a63f 100644 --- a/samples/posix/gettimeofday/sample.yaml +++ b/samples/posix/gettimeofday/sample.yaml @@ -10,6 +10,9 @@ common: tags: - posix - net + platform_exclude: + - native_posix + - native_posix/native/64 tests: sample.posix.gettimeofday: harness: net From 4db14f83e5a6b8d2e08623d2811b8bac08fd5c0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mo=C5=84?= Date: Tue, 21 May 2024 11:56:28 +0200 Subject: [PATCH 1332/2849] drivers: udc_dwc2: Fix timeouts when disabling endpoints MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Do not set NAK bit again for endpoints that already have NAK bit set. Do not wait for OUT endpoint 0 disable because it cannot be disabled by application (DOEPCTL0 EPDis bit is Read-Only). Disable endpoints before disabling interrupts because it is necessary to handle RXFLVL interrupt (in Slave mode) for GOUTNAKEFF to become active. Signed-off-by: Tomasz Moń --- drivers/usb/udc/udc_dwc2.c | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/drivers/usb/udc/udc_dwc2.c b/drivers/usb/udc/udc_dwc2.c index 2f43eb00a506f..33444d07e1edf 100644 --- a/drivers/usb/udc/udc_dwc2.c +++ b/drivers/usb/udc/udc_dwc2.c @@ -1258,6 +1258,16 @@ static void udc_dwc2_ep_disable(const struct device *dev, dxepctl_reg = dwc2_get_dxepctl_reg(dev, cfg->addr); dxepctl = sys_read32(dxepctl_reg); + if (dxepctl & USB_DWC2_DEPCTL_NAKSTS) { + /* Endpoint already sends forced NAKs. STALL if necessary. */ + if (stall) { + dxepctl |= USB_DWC2_DEPCTL_STALL; + sys_write32(dxepctl, dxepctl_reg); + } + + return; + } + if (USB_EP_DIR_IS_OUT(cfg->addr)) { mem_addr_t dctl_reg, gintsts_reg, doepint_reg; uint32_t dctl; @@ -1278,7 +1288,11 @@ static void udc_dwc2_ep_disable(const struct device *dev, dwc2_wait_for_bit(gintsts_reg, USB_DWC2_GINTSTS_GOUTNAKEFF); - dxepctl |= USB_DWC2_DEPCTL_EPENA | USB_DWC2_DEPCTL_EPDIS; + /* The application cannot disable control OUT endpoint 0. */ + if (ep_idx != 0) { + 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; @@ -1287,7 +1301,9 @@ static void udc_dwc2_ep_disable(const struct device *dev, } sys_write32(dxepctl, dxepctl_reg); - dwc2_wait_for_bit(doepint_reg, USB_DWC2_DOEPINT_EPDISBLD); + if (ep_idx != 0) { + dwc2_wait_for_bit(doepint_reg, USB_DWC2_DOEPINT_EPDISBLD); + } /* Clear Endpoint Disabled interrupt */ sys_write32(USB_DWC2_DIEPINT_EPDISBLD, doepint_reg); @@ -1712,9 +1728,6 @@ static int udc_dwc2_disable(const struct device *dev) 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); - if (udc_ep_disable_internal(dev, USB_CONTROL_EP_OUT)) { LOG_DBG("Failed to disable control endpoint"); return -EIO; @@ -1725,6 +1738,9 @@ static int udc_dwc2_disable(const struct device *dev) return -EIO; } + config->irq_disable_func(dev); + sys_clear_bits((mem_addr_t)&base->gahbcfg, USB_DWC2_GAHBCFG_GLBINTRMASK); + err = dwc2_quirk_disable(dev); if (err) { LOG_ERR("Quirk disable failed %d", err); From 2368623f32fde01e8421dd606162bd172f44b10d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mo=C5=84?= Date: Mon, 20 May 2024 14:12:06 +0200 Subject: [PATCH 1333/2849] drivers: udc_dwc2: Avoid IN endpoint dequeue race MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Flushing TxFIFO is racing with actual use of the TxFIFO. The software controls only one side of the race (flush trigger) while the host controls the other side. Therefore, locking interrupts before flushing TxFIFO is not protecting against the race condition. Disable the endpoint on dequeue to make sure that TxFIFO flushing won't conflict with host actions (because the endpoint would be forced to NAK the IN tokens before the TxFIFO is flushed). Signed-off-by: Tomasz Moń --- drivers/usb/udc/udc_dwc2.c | 83 +++++++++++++++++--------------------- 1 file changed, 38 insertions(+), 45 deletions(-) diff --git a/drivers/usb/udc/udc_dwc2.c b/drivers/usb/udc/udc_dwc2.c index 33444d07e1edf..98ded9e4b5de2 100644 --- a/drivers/usb/udc/udc_dwc2.c +++ b/drivers/usb/udc/udc_dwc2.c @@ -928,51 +928,6 @@ static void udc_dwc2_isr_handler(const struct device *dev) (void)dwc2_quirk_irq_clear(dev); } -static int udc_dwc2_ep_enqueue(const struct device *dev, - struct udc_ep_config *const cfg, - struct net_buf *const buf) -{ - struct dwc2_drv_event evt = { - .ep = cfg->addr, - .type = DWC2_DRV_EVT_XFER, - }; - - LOG_DBG("%p enqueue %x %p", dev, cfg->addr, buf); - udc_buf_put(cfg, buf); - - if (!cfg->stat.halted) { - k_msgq_put(&drv_msgq, &evt, K_NO_WAIT); - } - - return 0; -} - -static int udc_dwc2_ep_dequeue(const struct device *dev, - struct udc_ep_config *const cfg) -{ - unsigned int lock_key; - struct net_buf *buf; - - lock_key = irq_lock(); - - if (USB_EP_DIR_IS_IN(cfg->addr)) { - dwc2_flush_tx_fifo(dev, USB_EP_GET_IDX(cfg->addr)); - } - - buf = udc_buf_get_all(dev, cfg->addr); - if (buf) { - udc_submit_ep_event(dev, buf, -ECONNABORTED); - } - - irq_unlock(lock_key); - - udc_ep_set_busy(dev, cfg->addr, false); - - LOG_DBG("dequeue ep 0x%02x", cfg->addr); - - return 0; -} - static void dwc2_unset_unused_fifo(const struct device *dev) { struct udc_dwc2_data *const priv = udc_get_private(dev); @@ -1420,6 +1375,44 @@ static int udc_dwc2_ep_clear_halt(const struct device *dev, return 0; } +static int udc_dwc2_ep_enqueue(const struct device *dev, + struct udc_ep_config *const cfg, + struct net_buf *const buf) +{ + struct dwc2_drv_event evt = { + .ep = cfg->addr, + .type = DWC2_DRV_EVT_XFER, + }; + + LOG_DBG("%p enqueue %x %p", dev, cfg->addr, buf); + udc_buf_put(cfg, buf); + + if (!cfg->stat.halted) { + k_msgq_put(&drv_msgq, &evt, K_NO_WAIT); + } + + return 0; +} + +static int udc_dwc2_ep_dequeue(const struct device *dev, + struct udc_ep_config *const cfg) +{ + struct net_buf *buf; + + udc_dwc2_ep_disable(dev, cfg, false); + + buf = udc_buf_get_all(dev, cfg->addr); + if (buf) { + udc_submit_ep_event(dev, buf, -ECONNABORTED); + } + + udc_ep_set_busy(dev, cfg->addr, false); + + LOG_DBG("dequeue ep 0x%02x", cfg->addr); + + return 0; +} + static int udc_dwc2_set_address(const struct device *dev, const uint8_t addr) { struct usb_dwc2_reg *const base = dwc2_get_base(dev); From d1ca30e8f7070a96dbcaa8618c6c4a63dba74405 Mon Sep 17 00:00:00 2001 From: Tim Lin Date: Wed, 15 May 2024 17:13:00 +0800 Subject: [PATCH 1334/2849] ITE: drivers/pwm: Optimize the PWM set cycles It takes 11 CPU ticks to recalculate ctr and cxcprs at the same frequency. The previously calculated ctr and cxcprs can be stored at the same frequency without recalculation. Signed-off-by: Tim Lin --- drivers/pwm/pwm_ite_it8xxx2.c | 76 ++++++++++++++++++++++------------- 1 file changed, 48 insertions(+), 28 deletions(-) diff --git a/drivers/pwm/pwm_ite_it8xxx2.c b/drivers/pwm/pwm_ite_it8xxx2.c index 610815505636d..1e5e47f33507f 100644 --- a/drivers/pwm/pwm_ite_it8xxx2.c +++ b/drivers/pwm/pwm_ite_it8xxx2.c @@ -43,6 +43,12 @@ struct pwm_it8xxx2_cfg { const struct pinctrl_dev_config *pcfg; }; +struct pwm_it8xxx2_data { + uint32_t ctr; + uint32_t cxcprs; + uint32_t target_freq_prev; +}; + static void pwm_enable(const struct device *dev, int enabled) { const struct pwm_it8xxx2_cfg *config = dev->config; @@ -92,11 +98,12 @@ static int pwm_it8xxx2_set_cycles(const struct device *dev, { const struct pwm_it8xxx2_cfg *config = dev->config; struct pwm_it8xxx2_regs *const inst = config->base; + struct pwm_it8xxx2_data *data = dev->data; volatile uint8_t *reg_dcr = (uint8_t *)config->reg_dcr; volatile uint8_t *reg_pwmpol = (uint8_t *)config->reg_pwmpol; int ch = config->channel; int prs_sel = config->prs_sel; - uint32_t actual_freq = 0xffffffff, target_freq, deviation, cxcprs, ctr; + uint32_t actual_freq = 0xffffffff, target_freq, deviation; uint64_t pwm_clk_src; /* Select PWM inverted polarity (ex. active-low pulse) */ @@ -162,48 +169,59 @@ static int pwm_it8xxx2_set_cycles(const struct device *dev, * CTRx[7:0] value 00h results in a divisor 1 * CTRx[7:0] value FFh results in a divisor 256 */ - for (ctr = 0xFF; ctr >= PWM_CTRX_MIN; ctr--) { - cxcprs = (((uint32_t) pwm_clk_src) / (ctr + 1) / target_freq); - /* - * Make sure cxcprs isn't zero, or we will have - * divide-by-zero on calculating actual_freq. - */ - if (cxcprs != 0) { - actual_freq = ((uint32_t) pwm_clk_src) / (ctr + 1) / cxcprs; - if (abs(actual_freq - target_freq) < deviation) { - /* CxCPRS[15:0] = cxcprs - 1 */ - cxcprs--; - break; + if (target_freq != data->target_freq_prev) { + uint32_t ctr, cxcprs; + + for (ctr = 0xFF; ctr >= PWM_CTRX_MIN; ctr--) { + cxcprs = (((uint32_t) pwm_clk_src) / (ctr + 1) / target_freq); + /* + * Make sure cxcprs isn't zero, or we will have + * divide-by-zero on calculating actual_freq. + */ + if (cxcprs != 0) { + actual_freq = ((uint32_t) pwm_clk_src) / (ctr + 1) / cxcprs; + if (abs(actual_freq - target_freq) < deviation) { + /* CxCPRS[15:0] = cxcprs - 1 */ + cxcprs--; + break; + } } } - } - if (cxcprs > UINT16_MAX) { - LOG_ERR("PWM prescaler CxCPRS only support 2 bytes !"); - return -EINVAL; + if (cxcprs > UINT16_MAX) { + LOG_ERR("PWM prescaler CxCPRS only support 2 bytes !"); + return -EINVAL; + } + + /* Store ctr and cxcprs with successful frequency change */ + data->ctr = ctr; + data->cxcprs = cxcprs; } /* Set PWM prescaler clock divide and cycle time register */ if (prs_sel == PWM_PRESCALER_C4) { - inst->C4CPRS = cxcprs & 0xFF; - inst->C4MCPRS = (cxcprs >> 8) & 0xFF; - inst->CTR1 = ctr; + inst->C4CPRS = data->cxcprs & 0xFF; + inst->C4MCPRS = (data->cxcprs >> 8) & 0xFF; + inst->CTR1 = data->ctr; } else if (prs_sel == PWM_PRESCALER_C6) { - inst->C6CPRS = cxcprs & 0xFF; - inst->C6MCPRS = (cxcprs >> 8) & 0xFF; - inst->CTR2 = ctr; + inst->C6CPRS = data->cxcprs & 0xFF; + inst->C6MCPRS = (data->cxcprs >> 8) & 0xFF; + inst->CTR2 = data->ctr; } else if (prs_sel == PWM_PRESCALER_C7) { - inst->C7CPRS = cxcprs & 0xFF; - inst->C7MCPRS = (cxcprs >> 8) & 0xFF; - inst->CTR3 = ctr; + inst->C7CPRS = data->cxcprs & 0xFF; + inst->C7MCPRS = (data->cxcprs >> 8) & 0xFF; + inst->CTR3 = data->ctr; } /* Set PWM channel duty cycle register */ - *reg_dcr = (ctr * pulse_cycles) / period_cycles; + *reg_dcr = (data->ctr * pulse_cycles) / period_cycles; /* PWM channel clock source not gating */ pwm_enable(dev, 1); + /* Store the frequency to be compared */ + data->target_freq_prev = target_freq; + LOG_DBG("clock source freq %d, target freq %d", (uint32_t) pwm_clk_src, target_freq); @@ -277,10 +295,12 @@ static const struct pwm_driver_api pwm_it8xxx2_api = { .pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(inst), \ }; \ \ + static struct pwm_it8xxx2_data pwm_it8xxx2_data_##inst; \ + \ DEVICE_DT_INST_DEFINE(inst, \ &pwm_it8xxx2_init, \ NULL, \ - NULL, \ + &pwm_it8xxx2_data_##inst, \ &pwm_it8xxx2_cfg_##inst, \ PRE_KERNEL_1, \ CONFIG_PWM_INIT_PRIORITY, \ From 2f272b2d7987a158a0e799e272b1226a92ba1069 Mon Sep 17 00:00:00 2001 From: Johann Fischer Date: Mon, 20 May 2024 12:26:01 +0200 Subject: [PATCH 1335/2849] usb: device_next: fix BOS descriptor request Return protocol error if bcdUSB is less than 0x0201. Fix typo in number of capabilities. Fixes: b0d7d70834ab ("usb: device_next: add initial BOS support") Signed-off-by: Johann Fischer --- subsys/usb/device_next/usbd_ch9.c | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/subsys/usb/device_next/usbd_ch9.c b/subsys/usb/device_next/usbd_ch9.c index 0553c16dcf8f1..2b58d6b5bdf8f 100644 --- a/subsys/usb/device_next/usbd_ch9.c +++ b/subsys/usb/device_next/usbd_ch9.c @@ -708,7 +708,7 @@ static void desc_fill_bos_root(struct usbd_contex *const uds_ctx, 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; + root->bNumDeviceCaps++; } } } @@ -717,10 +717,28 @@ 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_device_descriptor *dev_dsc; struct usb_bos_descriptor bos; struct usbd_desc_node *desc_nd; size_t len; + switch (usbd_bus_speed(uds_ctx)) { + case USBD_SPEED_FS: + dev_dsc = uds_ctx->fs_desc; + break; + case USBD_SPEED_HS: + dev_dsc = uds_ctx->hs_desc; + break; + default: + errno = -ENOTSUP; + return 0; + } + + if (sys_le16_to_cpu(dev_dsc->bcdUSB) < 0x0201U) { + errno = -ENOTSUP; + return 0; + } + desc_fill_bos_root(uds_ctx, &bos); len = MIN(net_buf_tailroom(buf), MIN(setup->wLength, bos.wTotalLength)); From 71ed2e4b02b98e26263c80ebdd96a5771cab591b Mon Sep 17 00:00:00 2001 From: Jerzy Kasenberg Date: Mon, 20 May 2024 10:49:00 +0200 Subject: [PATCH 1336/2849] drivers: spi: Add power management Smartbond SPI Code adds pm action function that stores SPI configuration before PD_COM is allowed to be turned off. PM_DEVICE_RUNTIME scheme is also supported Signed-off-by: Jerzy Kasenberg --- .../da14695_dk_usb-pinctrl.dtsi | 16 +++ .../renesas/da14695_dk_usb/da14695_dk_usb.dts | 6 +- .../da1469x_dk_pro-pinctrl.dtsi | 16 +++ .../renesas/da1469x_dk_pro/da1469x_dk_pro.dts | 6 +- drivers/spi/spi_smartbond.c | 114 +++++++++++++++++- 5 files changed, 151 insertions(+), 7 deletions(-) diff --git a/boards/renesas/da14695_dk_usb/da14695_dk_usb-pinctrl.dtsi b/boards/renesas/da14695_dk_usb/da14695_dk_usb-pinctrl.dtsi index d16ad945fa855..1db25444b6cd6 100644 --- a/boards/renesas/da14695_dk_usb/da14695_dk_usb-pinctrl.dtsi +++ b/boards/renesas/da14695_dk_usb/da14695_dk_usb-pinctrl.dtsi @@ -52,6 +52,14 @@ }; }; + /omit-if-no-ref/ spi_sleep: spi_sleep { + group1 { + pinmux = , + , + ; + }; + }; + spi_controller: spi_controller { group1 { pinmux = < SMARTBOND_PINMUX(SPI_CLK, 0, 21) >, @@ -64,6 +72,14 @@ }; }; + /omit-if-no-ref/ spi2_sleep: spi2_sleep { + group1 { + pinmux = , + , + ; + }; + }; + spi2_controller: spi2_controller { group1 { pinmux = < SMARTBOND_PINMUX(SPI2_CLK, 1, 3) >, diff --git a/boards/renesas/da14695_dk_usb/da14695_dk_usb.dts b/boards/renesas/da14695_dk_usb/da14695_dk_usb.dts index eff5299dcff60..4e86ee9221b9b 100644 --- a/boards/renesas/da14695_dk_usb/da14695_dk_usb.dts +++ b/boards/renesas/da14695_dk_usb/da14695_dk_usb.dts @@ -201,13 +201,15 @@ zephyr_udc0: &usbd { &spi { status = "okay"; pinctrl-0 = <&spi_controller>; - pinctrl-names = "default"; + pinctrl-1 = <&spi_sleep>; + pinctrl-names = "default", "sleep"; }; &spi2 { status = "okay"; pinctrl-0 = <&spi2_controller>; - pinctrl-names = "default"; + pinctrl-1 = <&spi2_sleep>; + pinctrl-names = "default", "sleep"; }; mikrobus_1_i2c: &i2c {}; 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 032a2e0d53909..50396701632a8 100644 --- a/boards/renesas/da1469x_dk_pro/da1469x_dk_pro-pinctrl.dtsi +++ b/boards/renesas/da1469x_dk_pro/da1469x_dk_pro-pinctrl.dtsi @@ -79,6 +79,14 @@ }; }; + /omit-if-no-ref/ spi_sleep: spi_sleep { + group1 { + pinmux = , + , + ; + }; + }; + spi_controller: spi_controller { group1 { pinmux = , @@ -91,6 +99,14 @@ }; }; + /omit-if-no-ref/ spi2_sleep: spi2_sleep { + group1 { + pinmux = , + , + ; + }; + }; + spi2_controller: spi2_controller { group1 { pinmux = < SMARTBOND_PINMUX(SPI2_CLK, 1, 3) >, diff --git a/boards/renesas/da1469x_dk_pro/da1469x_dk_pro.dts b/boards/renesas/da1469x_dk_pro/da1469x_dk_pro.dts index bc3c19d321583..3b09fe4e0615a 100644 --- a/boards/renesas/da1469x_dk_pro/da1469x_dk_pro.dts +++ b/boards/renesas/da1469x_dk_pro/da1469x_dk_pro.dts @@ -167,11 +167,13 @@ zephyr_udc0: &usbd { &spi { status = "okay"; pinctrl-0 = <&spi_controller>; - pinctrl-names = "default"; + pinctrl-1 = <&spi_sleep>; + pinctrl-names = "default", "sleep"; }; &spi2 { status = "okay"; pinctrl-0 = <&spi2_controller>; - pinctrl-names = "default"; + pinctrl-1 = <&spi2_sleep>; + pinctrl-names = "default", "sleep"; }; diff --git a/drivers/spi/spi_smartbond.c b/drivers/spi/spi_smartbond.c index 7f44c0f29aaf0..730a3b37a9db4 100644 --- a/drivers/spi/spi_smartbond.c +++ b/drivers/spi/spi_smartbond.c @@ -15,8 +15,12 @@ LOG_MODULE_REGISTER(spi_smartbond); #include #include #include +#include +#include +#include #include +#include #define DIVN_CLK 32000000 /* divN_clk 32MHz */ #define SCLK_FREQ_2MHZ (DIVN_CLK / 14) /* 2.285714MHz*/ @@ -33,6 +37,10 @@ struct spi_smartbond_cfg { struct spi_smartbond_data { struct spi_context ctx; uint8_t dfs; +#if defined(CONFIG_PM_DEVICE) + ATOMIC_DEFINE(pm_policy_state_flag, 1); + uint32_t spi_ctrl_reg; +#endif }; static inline void spi_smartbond_enable(const struct spi_smartbond_cfg *cfg, bool enable) @@ -106,6 +114,31 @@ static inline int spi_smartbond_set_word_size(const struct spi_smartbond_cfg *cf return 0; } +static inline void spi_smartbond_pm_policy_state_lock_get(struct spi_smartbond_data *data) +{ +#if defined(CONFIG_PM_DEVICE) + if (atomic_test_and_set_bit(data->pm_policy_state_flag, 0) == 0) { + /* + * Prevent the SoC from entering the normal sleep state as PDC does not support + * waking up the application core following SPI events. + */ + pm_policy_state_lock_get(PM_STATE_STANDBY, PM_ALL_SUBSTATES); + } +#endif +} + +static inline void spi_smartbond_pm_policy_state_lock_put(struct spi_smartbond_data *data) +{ +#if defined(CONFIG_PM_DEVICE) + if (atomic_test_and_clear_bit(data->pm_policy_state_flag, 0) == 1) { + /* + * Allow the SoC to enter the normal sleep state once SPI transactions are done. + */ + pm_policy_state_lock_put(PM_STATE_STANDBY, PM_ALL_SUBSTATES); + } +#endif +} + static int spi_smartbond_configure(const struct spi_smartbond_cfg *cfg, struct spi_smartbond_data *data, const struct spi_config *spi_cfg) @@ -113,6 +146,9 @@ static int spi_smartbond_configure(const struct spi_smartbond_cfg *cfg, int rc; if (spi_context_configured(&data->ctx, spi_cfg)) { +#ifdef CONFIG_PM_DEVICE + spi_smartbond_enable(cfg, true); +#endif return 0; } @@ -182,6 +218,8 @@ static int spi_smartbond_transceive(const struct device *dev, const struct spi_c uint32_t bitmask; int rc; + spi_smartbond_pm_policy_state_lock_get(data); + spi_context_lock(&data->ctx, false, NULL, NULL, spi_cfg); rc = spi_smartbond_configure(cfg, data, spi_cfg); if (rc == 0) { @@ -211,6 +249,8 @@ static int spi_smartbond_transceive(const struct device *dev, const struct spi_c spi_context_cs_control(ctx, false); spi_context_release(&data->ctx, rc); + spi_smartbond_pm_policy_state_lock_put(data); + return rc; } #ifdef CONFIG_SPI_ASYNC @@ -247,7 +287,7 @@ static const struct spi_driver_api spi_smartbond_driver_api = { .release = spi_smartbond_release, }; -static int spi_smartbond_init(const struct device *dev) +static int spi_smartbond_resume(const struct device *dev) { const struct spi_smartbond_cfg *cfg = dev->config; struct spi_smartbond_data *data = dev->data; @@ -273,6 +313,69 @@ static int spi_smartbond_init(const struct device *dev) return 0; } +#if defined(CONFIG_PM_DEVICE) +static int spi_smartbond_suspend(const struct device *dev) +{ + int ret; + const struct spi_smartbond_cfg *config = dev->config; + struct spi_smartbond_data *data = dev->data; + + data->spi_ctrl_reg = config->regs->SPI_CTRL_REG; + /* Disable the SPI digital block */ + config->regs->SPI_CTRL_REG &= ~SPI_SPI_CTRL_REG_SPI_EN_CTRL_Msk; + /* Gate SPI clocking */ + CRG_COM->RESET_CLK_COM_REG = config->periph_clock_config; + + ret = pinctrl_apply_state(config->pcfg, PINCTRL_STATE_SLEEP); + if (ret < 0) { + LOG_WRN("Failed to configure the SPI pins to inactive state"); + } + + return ret; +} + +static int spi_smartbond_pm_action(const struct device *dev, + enum pm_device_action action) +{ + int ret; + + switch (action) { + case PM_DEVICE_ACTION_RESUME: + da1469x_pd_acquire(MCU_PD_DOMAIN_COM); + ret = spi_smartbond_resume(dev); + break; + case PM_DEVICE_ACTION_SUSPEND: + ret = spi_smartbond_suspend(dev); + da1469x_pd_release(MCU_PD_DOMAIN_COM); + break; + default: + ret = -ENOTSUP; + } + + return ret; +} +#endif + +static int spi_smartbond_init(const struct device *dev) +{ + int ret; + struct spi_smartbond_data *data = dev->data; + +#ifdef CONFIG_PM_DEVICE_RUNTIME + /* Make sure device state is marked as suspended */ + pm_device_init_suspended(dev); + + ret = pm_device_runtime_enable(dev); + +#else + da1469x_pd_acquire(MCU_PD_DOMAIN_COM); + ret = spi_smartbond_resume(dev); +#endif + spi_context_unlock_unconditionally(&data->ctx); + + return ret; +} + #define SPI_SMARTBOND_DEVICE(id) \ PINCTRL_DT_INST_DEFINE(id); \ static const struct spi_smartbond_cfg spi_smartbond_##id##_cfg = { \ @@ -284,8 +387,13 @@ static int spi_smartbond_init(const struct device *dev) SPI_CONTEXT_INIT_LOCK(spi_smartbond_##id##_data, ctx), \ SPI_CONTEXT_INIT_SYNC(spi_smartbond_##id##_data, ctx), \ SPI_CONTEXT_CS_GPIOS_INITIALIZE(DT_DRV_INST(id), ctx)}; \ - DEVICE_DT_INST_DEFINE(id, spi_smartbond_init, NULL, &spi_smartbond_##id##_data, \ - &spi_smartbond_##id##_cfg, POST_KERNEL, CONFIG_SPI_INIT_PRIORITY, \ + PM_DEVICE_DT_INST_DEFINE(id, spi_smartbond_pm_action); \ + DEVICE_DT_INST_DEFINE(id, \ + spi_smartbond_init, \ + PM_DEVICE_DT_INST_GET(id), \ + &spi_smartbond_##id##_data, \ + &spi_smartbond_##id##_cfg, \ + POST_KERNEL, CONFIG_SPI_INIT_PRIORITY, \ &spi_smartbond_driver_api); DT_INST_FOREACH_STATUS_OKAY(SPI_SMARTBOND_DEVICE) From ef533e2144629f9d6e19a49216aa1d3f7ec928aa Mon Sep 17 00:00:00 2001 From: Chaitanya Tata Date: Thu, 16 May 2024 21:47:35 +0530 Subject: [PATCH 1337/2849] tests: spi_loopback: Fix high RAM usage Display diff of contents for large buffers is not quite helpful and takes up huge RAM, and if a board has less RAM then this causes the test module build failures. So, disable display of diff and just log a failure, small buffer tests can be used to debug such basic issues and large buffer tests can act as a smoke test for debugging other issues. This saves about 80K of RAM. Fixes #72792. Signed-off-by: Chaitanya Tata --- tests/drivers/spi/spi_loopback/src/spi.c | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/tests/drivers/spi/spi_loopback/src/spi.c b/tests/drivers/spi/spi_loopback/src/spi.c index ea76f8e4f7bb1..f091f436396f1 100644 --- a/tests/drivers/spi/spi_loopback/src/spi.c +++ b/tests/drivers/spi/spi_loopback/src/spi.c @@ -88,9 +88,6 @@ static uint8_t buffer_print_rx[BUF_SIZE * 5 + 1]; static uint8_t buffer_print_tx2[BUF2_SIZE * 5 + 1]; static uint8_t buffer_print_rx2[BUF2_SIZE * 5 + 1]; -static uint8_t large_buffer_print_tx[BUF3_SIZE * 5 + 1]; -static uint8_t large_buffer_print_rx[BUF3_SIZE * 5 + 1]; - static void to_display_format(const uint8_t *src, size_t size, char *dst) { size_t i; @@ -558,10 +555,6 @@ static int spi_complete_large_transfers(struct spi_dt_spec *spec) } if (memcmp(large_buffer_tx, large_buffer_rx, BUF3_SIZE)) { - to_display_format(large_buffer_tx, BUF3_SIZE, large_buffer_print_tx); - to_display_format(large_buffer_rx, BUF3_SIZE, large_buffer_print_rx); - LOG_ERR("Large Buffer contents are different: %s", large_buffer_print_tx); - LOG_ERR(" vs: %s", large_buffer_print_rx); zassert_false(1, "Large Buffer contents are different"); return -1; } @@ -691,10 +684,6 @@ static int spi_async_call(struct spi_dt_spec *spec) } if (memcmp(large_buffer_tx, large_buffer_rx, BUF3_SIZE)) { - to_display_format(large_buffer_tx, BUF3_SIZE, large_buffer_print_tx); - to_display_format(large_buffer_rx, BUF3_SIZE, large_buffer_print_rx); - LOG_ERR("Buffer 3 contents are different: %s", large_buffer_print_tx); - LOG_ERR(" vs: %s", large_buffer_print_rx); zassert_false(1, "Buffer 3 contents are different"); return -1; } From f451201228531de98364a04130365598563a1dca Mon Sep 17 00:00:00 2001 From: Tomi Fontanilles Date: Fri, 10 May 2024 14:10:49 +0300 Subject: [PATCH 1338/2849] manifest: trusted-firmware-m: update to 2.1.0 Update TF-M to version 2.1.0. Signed-off-by: Tomi Fontanilles --- doc/releases/release-notes-3.7.rst | 10 +++++++++- doc/services/tfm/overview.rst | 2 +- submanifests/optional.yaml | 2 +- west.yml | 4 ++-- 4 files changed, 13 insertions(+), 5 deletions(-) diff --git a/doc/releases/release-notes-3.7.rst b/doc/releases/release-notes-3.7.rst index 121bf88467e78..32c52d19fa3fb 100644 --- a/doc/releases/release-notes-3.7.rst +++ b/doc/releases/release-notes-3.7.rst @@ -13,6 +13,8 @@ Major enhancements with this release include: 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 +* Trusted Firmware-M (TF-M) 2.1.0 and Mbed TLS 3.6.0 have been integrated into Zephyr. + Both of these versions are LTS releases. 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`. @@ -378,7 +380,7 @@ Libraries / Subsystems * Crypto - * MbedTLS was updated to 3.6.0. Release notes can be found at: + * Mbed TLS was updated to 3.6.0. Release notes can be found at: https://github.com/Mbed-TLS/mbedtls/releases/tag/v3.6.0 * Random @@ -419,6 +421,12 @@ HALs MCUboot ******* +Trusted Firmware-M +****************** + +* TF-M was updated to 2.1.0. Release notes can be found at: + https://tf-m-user-guide.trustedfirmware.org/releases/2.1.0.html + zcbor ***** diff --git a/doc/services/tfm/overview.rst b/doc/services/tfm/overview.rst index ef71b53a113a0..8ecbd5946d864 100644 --- a/doc/services/tfm/overview.rst +++ b/doc/services/tfm/overview.rst @@ -8,7 +8,7 @@ It defines and implements an architecture and a set of software components that aim to address some of the main security concerns in IoT products. Zephyr RTOS has been PSA Certified since Zephyr 2.0.0 with TF-M 1.0, and -is currently integrated with TF-M 2.0.0. +is currently integrated with TF-M 2.1.0. What Does TF-M Offer? ********************* diff --git a/submanifests/optional.yaml b/submanifests/optional.yaml index 82007d5ae263b..db5f6c392b8f1 100644 --- a/submanifests/optional.yaml +++ b/submanifests/optional.yaml @@ -40,7 +40,7 @@ manifest: groups: - optional - name: tf-m-tests - revision: 85f533a4aa5b4fe31247676a923db7453eb4429c + revision: d552e4f18b92032bd335d5e3aa312f6acd82a83b path: modules/tee/tf-m/tf-m-tests remote: upstream groups: diff --git a/west.yml b/west.yml index 215af86acd9de..1b5a60846f738 100644 --- a/west.yml +++ b/west.yml @@ -282,7 +282,7 @@ manifest: revision: 2b498e6f36d6b82ae1da12c8b7742e318624ecf5 path: modules/lib/gui/lvgl - name: mbedtls - revision: 3217c450180fd5e817601c6f479116de69e57461 + revision: c0cb49ffd24b4068a91425b74505b35ed0e81038 path: modules/crypto/mbedtls groups: - crypto @@ -327,7 +327,7 @@ manifest: groups: - crypto - name: trusted-firmware-m - revision: 785d87492490069b62170159fcf21c385f90f4eb + revision: bdc4df1734b870de43237d56eb1b2a7af016ee95 path: modules/tee/tf-m/trusted-firmware-m groups: - tee From 9ad1a7c8d29018b7ab0163f57d4a9fdcd8b56451 Mon Sep 17 00:00:00 2001 From: Tomi Fontanilles Date: Wed, 15 May 2024 17:04:08 +0300 Subject: [PATCH 1339/2849] modules: tf-m: disable tf-m-tests revision checks Permanently disable the revision checks made in the tf-m-tests repository that were introduced with TF-M 2.1.0. They fail because the expected upstream tags are not found in Zephyr's tf-m-tests. Signed-off-by: Tomi Fontanilles --- modules/trusted-firmware-m/CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/modules/trusted-firmware-m/CMakeLists.txt b/modules/trusted-firmware-m/CMakeLists.txt index 5e551777080ff..9d6c85df41f7f 100644 --- a/modules/trusted-firmware-m/CMakeLists.txt +++ b/modules/trusted-firmware-m/CMakeLists.txt @@ -228,6 +228,8 @@ if (CONFIG_BUILD_WITH_TFM) list(APPEND TFM_CMAKE_ARGS -DCONFIG_TFM_ENABLE_FP=OFF) endif() + list(APPEND TFM_CMAKE_ARGS -DTFM_TESTS_REVISION_CHECKS=OFF) + file(MAKE_DIRECTORY ${TFM_BINARY_DIR}) add_custom_target(tfm_cmake DEPENDS ${TFM_BINARY_DIR}/CMakeCache.txt From 2c575190bba29c7b26db67edffd798464bbe8b95 Mon Sep 17 00:00:00 2001 From: Tomi Fontanilles Date: Fri, 17 May 2024 14:03:56 +0300 Subject: [PATCH 1340/2849] Revert "tf-m: Silence harmless version warning" This reverts commit 33786b55abc783cfed3a80dd0197eca26730baef. Reverting it because the upstream PR has been abandoned, and this extra CMake variable is causing the warning "Manually-specified variables were not used by the project". As of now the version warning doesn't come up. Signed-off-by: Tomi Fontanilles --- modules/trusted-firmware-m/CMakeLists.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/modules/trusted-firmware-m/CMakeLists.txt b/modules/trusted-firmware-m/CMakeLists.txt index 9d6c85df41f7f..bd95d7857106e 100644 --- a/modules/trusted-firmware-m/CMakeLists.txt +++ b/modules/trusted-firmware-m/CMakeLists.txt @@ -243,7 +243,6 @@ if (CONFIG_BUILD_WITH_TFM) -DCMAKE_BUILD_TYPE=${TFM_CMAKE_BUILD_TYPE} -DTFM_PLATFORM=${CONFIG_TFM_BOARD} -DCONFIG_TFM_BUILD_LOG_QUIET=ON - -DSILENCE_TFM_VERSION_WARNING=ON -DCONFIG_TFM_MEMORY_USAGE_QUIET=OFF -DPython3_EXECUTABLE=${Python3_EXECUTABLE} ${TFM_CMAKE_ARGS} From a8ec15294f896bb1d45e557c9a45f987dfececd9 Mon Sep 17 00:00:00 2001 From: Tomi Fontanilles Date: Tue, 21 May 2024 10:21:02 +0300 Subject: [PATCH 1341/2849] samples: tfm_psa_test: fix CMake logs Remove TF-M version number and explicit mention of the available test suites; one was missing. Signed-off-by: Tomi Fontanilles --- samples/tfm_integration/tfm_psa_test/CMakeLists.txt | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/samples/tfm_integration/tfm_psa_test/CMakeLists.txt b/samples/tfm_integration/tfm_psa_test/CMakeLists.txt index 0d11c021627fb..a46893a98e5a6 100644 --- a/samples/tfm_integration/tfm_psa_test/CMakeLists.txt +++ b/samples/tfm_integration/tfm_psa_test/CMakeLists.txt @@ -29,7 +29,7 @@ if (CONFIG_TFM_PSA_TEST_INITIAL_ATTESTATION AND CONFIG_TFM_QCBOR_PATH STREQUAL " # or only allow it when 'QCBOR_PATH' is set to a local path where QCBOR has # been manually downloaded by the user before starting the build. message(FATAL_ERROR "CONFIG_TFM_PSA_TEST_INITIAL_ATTESTATION is not available " - "with TF-M 2.0.0 due to licensing issues with a dependent library. This " + "with TF-M due to licensing issues with a dependent library. This " "restriction will be removed once licensing issues have been resolved." ) endif() @@ -50,11 +50,7 @@ set(TFM_PSA_TEST_SUITE INITIAL_ATTESTATION) endif() if (NOT DEFINED TFM_PSA_TEST_SUITE) - message(FATAL_ERROR "Please define witch test suite to run: - CONFIG_TFM_PSA_TEST_CRYPTO - CONFIG_TFM_PSA_TEST_PROTECTED_STORAGE - CONFIG_TFM_PSA_TEST_STORAGE - CONFIG_TFM_PSA_TEST_INITIAL_ATTESTATION") + message(FATAL_ERROR "Please define a test suite to run. Refer to the README to see the available test suites.") endif() set(TEST_PSA_API "${TFM_PSA_TEST_SUITE}") From 925d2ca052e5aa372372e4898f73c97e3915c45b Mon Sep 17 00:00:00 2001 From: Tomi Fontanilles Date: Tue, 21 May 2024 13:51:55 +0300 Subject: [PATCH 1342/2849] modules: tf-m: fix unused CMake variable warning Define and pass down PSA_ARCH_TESTS_PATH only in the sample that needs it (tfm_psa_test). Otherwise, it provokes a CMake warning because the variable does not get used in TF-M. Signed-off-by: Tomi Fontanilles --- modules/trusted-firmware-m/CMakeLists.txt | 3 --- samples/tfm_integration/tfm_psa_test/CMakeLists.txt | 4 ++-- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/modules/trusted-firmware-m/CMakeLists.txt b/modules/trusted-firmware-m/CMakeLists.txt index bd95d7857106e..f3bfc574cc028 100644 --- a/modules/trusted-firmware-m/CMakeLists.txt +++ b/modules/trusted-firmware-m/CMakeLists.txt @@ -135,8 +135,6 @@ if (CONFIG_BUILD_WITH_TFM) set(TFM_BINARY_DIR ${CMAKE_BINARY_DIR}/tfm) - set(PSA_ARCH_TESTS_PATH ${ZEPHYR_CURRENT_MODULE_DIR}/../psa-arch-tests) - set(TFM_INTERFACE_SOURCE_DIR ${TFM_BINARY_DIR}/api_ns/interface/src) set(TFM_INTERFACE_INCLUDE_DIR ${TFM_BINARY_DIR}/api_ns/interface/include) set(TFM_INTERFACE_LIB_DIR ${TFM_BINARY_DIR}/api_ns/interface/lib) @@ -248,7 +246,6 @@ if (CONFIG_BUILD_WITH_TFM) ${TFM_CMAKE_ARGS} $> -DMBEDCRYPTO_PATH=$>,$,${ZEPHYR_MBEDTLS_MODULE_DIR}> - -DPSA_ARCH_TESTS_PATH=${PSA_ARCH_TESTS_PATH} ${ZEPHYR_TRUSTED_FIRMWARE_M_MODULE_DIR} WORKING_DIRECTORY ${TFM_BINARY_DIR} COMMAND_EXPAND_LISTS diff --git a/samples/tfm_integration/tfm_psa_test/CMakeLists.txt b/samples/tfm_integration/tfm_psa_test/CMakeLists.txt index a46893a98e5a6..f195f0d79d0d9 100644 --- a/samples/tfm_integration/tfm_psa_test/CMakeLists.txt +++ b/samples/tfm_integration/tfm_psa_test/CMakeLists.txt @@ -22,7 +22,7 @@ get_target_property(TFM_TOOLCHAIN_PREFIX tfm TFM_TOOLCHAIN_PREFIX) get_target_property(TFM_TOOLCHAIN_NS_FILE tfm TFM_TOOLCHAIN_NS_FILE) set(TFM_TEST_REPO_PATH ${ZEPHYR_TRUSTED_FIRMWARE_M_MODULE_DIR}/../tf-m-tests) -set(TFM_PSA_ARCHTEST_REPO_PATH ${ZEPHYR_TRUSTED_FIRMWARE_M_MODULE_DIR}/../psa-arch-tests) +set(PSA_ARCH_TESTS_PATH ${ZEPHYR_TRUSTED_FIRMWARE_M_MODULE_DIR}/../psa-arch-tests) if (CONFIG_TFM_PSA_TEST_INITIAL_ATTESTATION AND CONFIG_TFM_QCBOR_PATH STREQUAL "") # TODO: Remove this when QCBOR licensing issues w/t_cose have been resolved, @@ -56,7 +56,7 @@ set(TEST_PSA_API "${TFM_PSA_TEST_SUITE}") set_property(TARGET zephyr_property_target APPEND PROPERTY TFM_CMAKE_OPTIONS - -DPSA_ARCH_TESTS_PATH=${TFM_PSA_ARCHTEST_REPO_PATH} + -DPSA_ARCH_TESTS_PATH=${PSA_ARCH_TESTS_PATH} ) set_property(TARGET zephyr_property_target From c294069b7d547df9334249332e3a6273525511a6 Mon Sep 17 00:00:00 2001 From: Tomi Fontanilles Date: Tue, 21 May 2024 16:14:02 +0300 Subject: [PATCH 1343/2849] modules: tf-m: restore check on CONFIG_TFM_PARTITION_INITIAL_ATTESTATION Restore the check that was introduced in cd8d4ccad55544b38637632e747a3b00a8c01016 and removed in cac7f4058ff3668b67fdb2c972ee9bb2fee1bfb5, rather than checking only CONFIG_TFM_PSA_TEST_INITIAL_ATTESTATION in the tfm_psa_test sample. Signed-off-by: Tomi Fontanilles --- modules/trusted-firmware-m/CMakeLists.txt | 10 ++++++++++ modules/trusted-firmware-m/Kconfig.tfm | 1 + modules/trusted-firmware-m/Kconfig.tfm.partitions | 1 - samples/tfm_integration/tfm_psa_test/CMakeLists.txt | 11 ----------- 4 files changed, 11 insertions(+), 12 deletions(-) diff --git a/modules/trusted-firmware-m/CMakeLists.txt b/modules/trusted-firmware-m/CMakeLists.txt index f3bfc574cc028..0824a7589023a 100644 --- a/modules/trusted-firmware-m/CMakeLists.txt +++ b/modules/trusted-firmware-m/CMakeLists.txt @@ -199,6 +199,16 @@ if (CONFIG_BUILD_WITH_TFM) message(FATAL_ERROR "Unsupported ZEPHYR_TOOLCHAIN_VARIANT: ${ZEPHYR_TOOLCHAIN_VARIANT}") endif() + if (CONFIG_TFM_PARTITION_INITIAL_ATTESTATION AND CONFIG_TFM_QCBOR_PATH STREQUAL "") + # TODO: Remove this when QCBOR licensing issues w/t_cose have been resolved, + # or only allow it when 'QCBOR_PATH' is set to a local path where QCBOR has + # been manually downloaded by the user before starting the build. + message(FATAL_ERROR "CONFIG_TFM_PARTITION_INITIAL_ATTESTATION is not available " + "with TF-M due to licensing issues with a dependent library. This " + "restriction will be removed once licensing issues have been resolved." + ) + endif() + string(REPLACE "toolchain" "toolchain_ns" TFM_TOOLCHAIN_NS_FILE ${TFM_TOOLCHAIN_FILE}) if(CONFIG_BOARD_LPCXPRESSO55S69_LPC55S69_CPU0_NS) diff --git a/modules/trusted-firmware-m/Kconfig.tfm b/modules/trusted-firmware-m/Kconfig.tfm index e8f860fa2f646..3f3fbfff161e6 100644 --- a/modules/trusted-firmware-m/Kconfig.tfm +++ b/modules/trusted-firmware-m/Kconfig.tfm @@ -393,6 +393,7 @@ config TFM_PSA_TEST_STORAGE config TFM_PSA_TEST_INITIAL_ATTESTATION bool "Initial attestation tests" depends on MAIN_STACK_SIZE >= 4096 + select TFM_PARTITION_INITIAL_ATTESTATION help Enable the PSA Initial Attestation test suite. diff --git a/modules/trusted-firmware-m/Kconfig.tfm.partitions b/modules/trusted-firmware-m/Kconfig.tfm.partitions index 67b46f5328ba9..1e45ad144ca6d 100644 --- a/modules/trusted-firmware-m/Kconfig.tfm.partitions +++ b/modules/trusted-firmware-m/Kconfig.tfm.partitions @@ -45,7 +45,6 @@ config TFM_PARTITION_INITIAL_ATTESTATION bool "Secure partition 'Initial Attestation'" depends on TFM_PARTITION_CRYPTO depends on TFM_INITIAL_ATTESTATION_KEY - default n help Setting this option will cause '-DTFM_PARTITION_INITIAL_ATTESTATION' to be passed to the TF-M build system. Look at 'config_default.cmake' diff --git a/samples/tfm_integration/tfm_psa_test/CMakeLists.txt b/samples/tfm_integration/tfm_psa_test/CMakeLists.txt index f195f0d79d0d9..03f55dccad136 100644 --- a/samples/tfm_integration/tfm_psa_test/CMakeLists.txt +++ b/samples/tfm_integration/tfm_psa_test/CMakeLists.txt @@ -24,17 +24,6 @@ get_target_property(TFM_TOOLCHAIN_NS_FILE tfm TFM_TOOLCHAIN_NS_FILE) set(TFM_TEST_REPO_PATH ${ZEPHYR_TRUSTED_FIRMWARE_M_MODULE_DIR}/../tf-m-tests) set(PSA_ARCH_TESTS_PATH ${ZEPHYR_TRUSTED_FIRMWARE_M_MODULE_DIR}/../psa-arch-tests) -if (CONFIG_TFM_PSA_TEST_INITIAL_ATTESTATION AND CONFIG_TFM_QCBOR_PATH STREQUAL "") -# TODO: Remove this when QCBOR licensing issues w/t_cose have been resolved, -# or only allow it when 'QCBOR_PATH' is set to a local path where QCBOR has -# been manually downloaded by the user before starting the build. -message(FATAL_ERROR "CONFIG_TFM_PSA_TEST_INITIAL_ATTESTATION is not available " - "with TF-M due to licensing issues with a dependent library. This " - "restriction will be removed once licensing issues have been resolved." - ) -endif() - - set(TFM_TEST_DIR "${TFM_TEST_REPO_PATH}/tests_psa_arch/spe/partitions") set(PSA_ARCH_TESTS_CONFIG_FILE "${TFM_TEST_REPO_PATH}/tests_psa_arch/spe/config/config_test_psa_api.cmake") if (CONFIG_TFM_PSA_TEST_CRYPTO) From 1eaa14090cd0f3dcc9c2c931d80cc5aa42967684 Mon Sep 17 00:00:00 2001 From: Tomi Fontanilles Date: Wed, 22 May 2024 15:25:05 +0300 Subject: [PATCH 1344/2849] modules: tf-m: support MCUboot signature types other than RSA-3072 With TF-M updated to 2.1.0 it now makes the signature type default to EC-P256 for the mps2/an521/cpu0/ns board. So far Zephyr had only supported and assumed that it was RSA-3072. This brings support for other signature types, and changes the global default to EC-P256. The switch from RSA-3072 to EC-P256 reduces the flash usage by ~3.3KB while having a negligible impact on RAM usage (increase of ~70 bytes) when compiling the tfm_psa_test sample on mps2/an521/cpu0/ns and nrf9160dk/nrf9160/ns without explicit optimizations. The TFM_KEY_FILE_{S,NS} Kconfig options are moved inside an `if TFM_BL2` as they are only used if MCUboot is included in TF-M. The TF-M CMake variables MCUBOOT_KEY_{S,NS} are now set so that it's possible to use signing keys located elsewhere than the default location. Signed-off-by: Tomi Fontanilles --- doc/releases/migration-guide-3.7.rst | 8 +++++ doc/releases/release-notes-3.7.rst | 4 +++ modules/trusted-firmware-m/CMakeLists.txt | 19 ++++++++++ modules/trusted-firmware-m/Kconfig.tfm | 43 ++++++++++++----------- 4 files changed, 53 insertions(+), 21 deletions(-) diff --git a/doc/releases/migration-guide-3.7.rst b/doc/releases/migration-guide-3.7.rst index 4d40baa6f4e2b..a9f6515161c86 100644 --- a/doc/releases/migration-guide-3.7.rst +++ b/doc/releases/migration-guide-3.7.rst @@ -96,6 +96,14 @@ MbedTLS MCUboot ======= +Trusted Firmware-M +================== + +* The default MCUboot signature type has been changed from RSA-3072 to EC-P256. + This affects builds that have MCUboot enabled in TF-M (:kconfig:option:`CONFIG_TFM_BL2`). + If you wish to keep using RSA-3072, you need to set :kconfig:option:`CONFIG_TFM_MCUBOOT_SIGNATURE_TYPE` + to `"RSA-3072"`. Otherwise, make sure to have your own signing keys of the signature type in use. + zcbor ===== diff --git a/doc/releases/release-notes-3.7.rst b/doc/releases/release-notes-3.7.rst index 32c52d19fa3fb..fb33ab257029a 100644 --- a/doc/releases/release-notes-3.7.rst +++ b/doc/releases/release-notes-3.7.rst @@ -427,6 +427,10 @@ Trusted Firmware-M * TF-M was updated to 2.1.0. Release notes can be found at: https://tf-m-user-guide.trustedfirmware.org/releases/2.1.0.html +* Support for MCUboot signature types other than RSA-3072 has been added. + The type can be chosen with the :kconfig:option:`CONFIG_TFM_MCUBOOT_SIGNATURE_TYPE` Kconfig option. + Using EC-P256, the new default, reduces flash usage by several KBs compared to RSA. + zcbor ***** diff --git a/modules/trusted-firmware-m/CMakeLists.txt b/modules/trusted-firmware-m/CMakeLists.txt index 0824a7589023a..b3d836490d618 100644 --- a/modules/trusted-firmware-m/CMakeLists.txt +++ b/modules/trusted-firmware-m/CMakeLists.txt @@ -35,6 +35,25 @@ if (CONFIG_BUILD_WITH_TFM) list(APPEND TFM_CMAKE_ARGS -DBL2=TRUE) list(APPEND TFM_CMAKE_ARGS -DMCUBOOT_IMAGE_VERSION_S=${CONFIG_TFM_IMAGE_VERSION_S}) list(APPEND TFM_CMAKE_ARGS -DMCUBOOT_IMAGE_VERSION_NS=${CONFIG_TFM_IMAGE_VERSION_NS}) + list(APPEND TFM_CMAKE_ARGS -DMCUBOOT_SIGNATURE_TYPE=${CONFIG_TFM_MCUBOOT_SIGNATURE_TYPE}) + + # TF-M's config/check_config.cmake requires MCUBOOT_BUILTIN_KEY=OFF for RSA + # and MCUBOOT_USE_PSA_CRYPTO for EC-P. The others are dependencies needed + # for either the build or the boot to succeed. + if (${CONFIG_TFM_MCUBOOT_SIGNATURE_TYPE} MATCHES "^RSA") + list(APPEND TFM_CMAKE_ARGS -DMCUBOOT_BUILTIN_KEY=OFF) + list(APPEND TFM_CMAKE_ARGS -DMCUBOOT_HW_KEY=ON) + elseif (${CONFIG_TFM_MCUBOOT_SIGNATURE_TYPE} MATCHES "^EC-P") + list(APPEND TFM_CMAKE_ARGS -DMCUBOOT_USE_PSA_CRYPTO=ON) + list(APPEND TFM_CMAKE_ARGS -DMCUBOOT_BUILTIN_KEY=ON) + list(APPEND TFM_CMAKE_ARGS -DMCUBOOT_HW_KEY=OFF) + endif() + + foreach(SUFFIX IN ITEMS "S" "NS") + string(CONFIGURE ${CONFIG_TFM_KEY_FILE_${SUFFIX}} CONFIG_TFM_KEY_FILE_${SUFFIX}) + list(APPEND TFM_CMAKE_ARGS -DMCUBOOT_KEY_${SUFFIX}=${CONFIG_TFM_KEY_FILE_${SUFFIX}}) + endforeach() + else() list(APPEND TFM_CMAKE_ARGS -DBL2=FALSE) endif() diff --git a/modules/trusted-firmware-m/Kconfig.tfm b/modules/trusted-firmware-m/Kconfig.tfm index 3f3fbfff161e6..5e8511947cfff 100644 --- a/modules/trusted-firmware-m/Kconfig.tfm +++ b/modules/trusted-firmware-m/Kconfig.tfm @@ -53,27 +53,8 @@ menuconfig BUILD_WITH_TFM if BUILD_WITH_TFM -config TFM_KEY_FILE_S - string "Path to private key used to sign secure firmware images." - depends on BUILD_WITH_TFM - default "${ZEPHYR_TRUSTED_FIRMWARE_M_MODULE_DIR}/bl2/ext/mcuboot/root-RSA-3072.pem" - help - The path and filename for the .pem file containing the private key - that should be used by the BL2 bootloader when signing secure - firmware images. - -config TFM_KEY_FILE_NS - string "Path to private key used to sign non-secure firmware images." - depends on BUILD_WITH_TFM - default "${ZEPHYR_TRUSTED_FIRMWARE_M_MODULE_DIR}/bl2/ext/mcuboot/root-RSA-3072_1.pem" - help - The path and filename for the .pem file containing the private key - that should be used by the BL2 bootloader when signing non-secure - firmware images. - config TFM_PROFILE string - depends on BUILD_WITH_TFM default "profile_small" if TFM_PROFILE_TYPE_SMALL default "profile_medium" if TFM_PROFILE_TYPE_MEDIUM default "profile_medium_arotless" if TFM_PROFILE_TYPE_AROTLESS @@ -85,7 +66,6 @@ config TFM_PROFILE choice TFM_PROFILE_TYPE prompt "TF-M build profile" - depends on BUILD_WITH_TFM default TFM_PROFILE_TYPE_NOT_SET help The TF-M build profile selection. Can be empty (not set), @@ -134,7 +114,6 @@ endchoice config TFM_ISOLATION_LEVEL int "Isolation level setting." if (TFM_PROFILE_TYPE_NOT_SET && TFM_IPC) range 1 3 - depends on BUILD_WITH_TFM default 1 if TFM_PROFILE_TYPE_SMALL || !TFM_IPC default 2 if TFM_PROFILE_TYPE_MEDIUM default 3 if TFM_PROFILE_TYPE_LARGE @@ -259,6 +238,28 @@ config TFM_CONNECTION_BASED_SERVICE_API if TFM_BL2 +config TFM_MCUBOOT_SIGNATURE_TYPE + string "The signature type used to sign the secure and non-secure firmware images." + default "EC-P256" + help + Available types: RSA-2048, RSA-3072, EC-P256, EC-P384. + +config TFM_KEY_FILE_S + string "Path to private key used to sign secure firmware images." + default "${ZEPHYR_TRUSTED_FIRMWARE_M_MODULE_DIR}/bl2/ext/mcuboot/root-${CONFIG_TFM_MCUBOOT_SIGNATURE_TYPE}.pem" + help + The path and filename for the .pem file containing the private key + that should be used by the BL2 bootloader when signing secure + firmware images. + +config TFM_KEY_FILE_NS + string "Path to private key used to sign non-secure firmware images." + default "${ZEPHYR_TRUSTED_FIRMWARE_M_MODULE_DIR}/bl2/ext/mcuboot/root-${CONFIG_TFM_MCUBOOT_SIGNATURE_TYPE}_1.pem" + help + The path and filename for the .pem file containing the private key + that should be used by the BL2 bootloader when signing non-secure + firmware images. + config TFM_MCUBOOT_IMAGE_NUMBER int "Granularity of FW updates of TFM and app" range 1 2 From 6eccdb965a53804f6e0b153ad1083690142bdf2e Mon Sep 17 00:00:00 2001 From: Tomi Fontanilles Date: Thu, 23 May 2024 15:01:56 +0300 Subject: [PATCH 1345/2849] samples: psa_crypto: fix setting of TF-M's CRYPTO_ENGINE_BUF_SIZE It used to be set as a CMake variable, but TF-M's build system does not look at such a variable. Instead, define an additional configuration header file that defines CRYPTO_ENGINE_BUF_SIZE, and pass it to TF-M's build system. Signed-off-by: Tomi Fontanilles --- samples/tfm_integration/psa_crypto/CMakeLists.txt | 6 ++---- samples/tfm_integration/psa_crypto/prj.conf | 2 +- .../user-tls-conf.h => configs/config_mbedtls.h} | 0 .../psa_crypto/src/configs/config_tfm.h | 10 ++++++++++ samples/tfm_integration/psa_crypto/src/main.c | 2 ++ samples/tfm_integration/psa_crypto/src/psa_crypto.c | 2 +- 6 files changed, 16 insertions(+), 6 deletions(-) rename samples/tfm_integration/psa_crypto/src/{tls_config/user-tls-conf.h => configs/config_mbedtls.h} (100%) create mode 100644 samples/tfm_integration/psa_crypto/src/configs/config_tfm.h diff --git a/samples/tfm_integration/psa_crypto/CMakeLists.txt b/samples/tfm_integration/psa_crypto/CMakeLists.txt index f8ef1eca23fb7..8a91d138de7b8 100644 --- a/samples/tfm_integration/psa_crypto/CMakeLists.txt +++ b/samples/tfm_integration/psa_crypto/CMakeLists.txt @@ -19,11 +19,9 @@ target_include_directories(app PRIVATE $/api_ns/interface/include ) -# In TF-M, default value of CRYPTO_ENGINE_BUF_SIZE is 0x2080. It causes -# insufficient memory failure while verifying signature. Increase it to 0x2400. set_property(TARGET zephyr_property_target APPEND PROPERTY TFM_CMAKE_OPTIONS - -DCRYPTO_ENGINE_BUF_SIZE=0x2400 + -DPROJECT_CONFIG_HEADER_FILE=${CMAKE_CURRENT_SOURCE_DIR}/src/configs/config_tfm.h ) -zephyr_include_directories(${APPLICATION_SOURCE_DIR}/src/tls_config) +zephyr_include_directories(${APPLICATION_SOURCE_DIR}/src/configs) diff --git a/samples/tfm_integration/psa_crypto/prj.conf b/samples/tfm_integration/psa_crypto/prj.conf index a7ac8db8f2e14..67972d960ae6a 100644 --- a/samples/tfm_integration/psa_crypto/prj.conf +++ b/samples/tfm_integration/psa_crypto/prj.conf @@ -26,7 +26,7 @@ CONFIG_MBEDTLS_BUILTIN=y CONFIG_MBEDTLS_ENABLE_HEAP=y CONFIG_MBEDTLS_HEAP_SIZE=32768 CONFIG_MBEDTLS_USER_CONFIG_ENABLE=y -CONFIG_MBEDTLS_USER_CONFIG_FILE="user-tls-conf.h" +CONFIG_MBEDTLS_USER_CONFIG_FILE="config_mbedtls.h" CONFIG_MBEDTLS_PSA_CRYPTO_C=y CONFIG_MBEDTLS_ENTROPY_ENABLED=y diff --git a/samples/tfm_integration/psa_crypto/src/tls_config/user-tls-conf.h b/samples/tfm_integration/psa_crypto/src/configs/config_mbedtls.h similarity index 100% rename from samples/tfm_integration/psa_crypto/src/tls_config/user-tls-conf.h rename to samples/tfm_integration/psa_crypto/src/configs/config_mbedtls.h diff --git a/samples/tfm_integration/psa_crypto/src/configs/config_tfm.h b/samples/tfm_integration/psa_crypto/src/configs/config_tfm.h new file mode 100644 index 0000000000000..38b24d6e78ce1 --- /dev/null +++ b/samples/tfm_integration/psa_crypto/src/configs/config_tfm.h @@ -0,0 +1,10 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* In TF-M the default value of CRYPTO_ENGINE_BUF_SIZE is 0x2080. + * It causes insufficient memory failure while verifying signature. + */ +#define CRYPTO_ENGINE_BUF_SIZE 0x2400 diff --git a/samples/tfm_integration/psa_crypto/src/main.c b/samples/tfm_integration/psa_crypto/src/main.c index a354cf97f1479..1fd0888d8ce8a 100644 --- a/samples/tfm_integration/psa_crypto/src/main.c +++ b/samples/tfm_integration/psa_crypto/src/main.c @@ -44,5 +44,7 @@ int main(void) /* Dump any queued log messages, and wait for system events. */ al_dump_log(); + LOG_INF("Done."); + return 0; } diff --git a/samples/tfm_integration/psa_crypto/src/psa_crypto.c b/samples/tfm_integration/psa_crypto/src/psa_crypto.c index b94edcd8b2afc..6a934c1c15e3c 100644 --- a/samples/tfm_integration/psa_crypto/src/psa_crypto.c +++ b/samples/tfm_integration/psa_crypto/src/psa_crypto.c @@ -510,7 +510,7 @@ void crp_generate_csr(void) LOG_INF("Certificate Signing Request in JSON:\n"); al_dump_log(); - printf("%s\n", json_encoded_buf); + printf("%s\n\n", json_encoded_buf); /* Close the key to free up the volatile slot. */ status = al_psa_status( From 03d86fc7c77b00f26fd4fe82f00ea27500694d0c Mon Sep 17 00:00:00 2001 From: Tomi Fontanilles Date: Thu, 23 May 2024 16:28:13 +0300 Subject: [PATCH 1346/2849] boards: st: b_u585_iot02a: stick to RSA signature type in TF-M's MCUboot The default has been changed to EC-P256, but there are issues with this board when TF-M is compiled with MCUBOOT_USE_PSA_CRYPTO (required by EC-P256) because of its integration in TF-M. Do not enable PSA crypto on this board for the time being. Signed-off-by: Tomi Fontanilles --- .../st/b_u585i_iot02a/b_u585i_iot02a_stm32u585xx_ns_defconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/boards/st/b_u585i_iot02a/b_u585i_iot02a_stm32u585xx_ns_defconfig b/boards/st/b_u585i_iot02a/b_u585i_iot02a_stm32u585xx_ns_defconfig index 2141cc748f8a1..8dd715679bb04 100644 --- a/boards/st/b_u585i_iot02a/b_u585i_iot02a_stm32u585xx_ns_defconfig +++ b/boards/st/b_u585i_iot02a/b_u585i_iot02a_stm32u585xx_ns_defconfig @@ -19,3 +19,5 @@ CONFIG_PINCTRL=y CONFIG_ARM_TRUSTZONE_M=y CONFIG_RUNTIME_NMI=y CONFIG_TRUSTED_EXECUTION_NONSECURE=y + +CONFIG_TFM_MCUBOOT_SIGNATURE_TYPE="RSA-3072" From b4d8b44d0fbb40973c3ce7d59b78f69e001a5d1a Mon Sep 17 00:00:00 2001 From: Alberto Escolar Piedras Date: Wed, 29 May 2024 09:15:46 +0200 Subject: [PATCH 1347/2849] tests settings/file: Add missing overlay for native_sim//64 native_sim//64 is one of the allowed platforms but lacks an overlay which causes the test to fail to build. Let's fix it. Signed-off-by: Alberto Escolar Piedras --- .../settings/file/boards/native_sim_native_64.overlay | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 tests/subsys/settings/file/boards/native_sim_native_64.overlay diff --git a/tests/subsys/settings/file/boards/native_sim_native_64.overlay b/tests/subsys/settings/file/boards/native_sim_native_64.overlay new file mode 100644 index 0000000000000..91647f82e208d --- /dev/null +++ b/tests/subsys/settings/file/boards/native_sim_native_64.overlay @@ -0,0 +1,6 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include "native_sim.overlay" From 20cb4c31cac44c24a63be0f36c6c47d5edb93a48 Mon Sep 17 00:00:00 2001 From: Piotr Narajowski Date: Wed, 3 Apr 2024 17:15:19 +0200 Subject: [PATCH 1348/2849] bluetooth: tester: refactor CSIP btp command Refactor CSIP btp commands by removing the 'count' parameter from set_coordinator_lock and set_coordinator_release functions. If we want to support lock/release procedure on subset of set members in the future, 'count' param doesn't indicate a specific set member. Instead, introduce 'address_count' and 'addr' array params, although their usage is not yet implemented. Signed-off-by: Piotr Narajowski --- tests/bluetooth/tester/src/btp/btp_csip.h | 6 ++- tests/bluetooth/tester/src/btp_csip.c | 57 +++++++++++++++++++++-- 2 files changed, 58 insertions(+), 5 deletions(-) diff --git a/tests/bluetooth/tester/src/btp/btp_csip.h b/tests/bluetooth/tester/src/btp/btp_csip.h index bfc5bcf085fa9..362f1bafd7516 100644 --- a/tests/bluetooth/tester/src/btp/btp_csip.h +++ b/tests/bluetooth/tester/src/btp/btp_csip.h @@ -25,12 +25,14 @@ struct btp_csip_start_ordered_access_cmd { #define BTP_CSIP_SET_COORDINATOR_LOCK 0x04 struct btp_csip_set_coordinator_lock_cmd { - uint8_t count; + uint8_t addr_cnt; + bt_addr_le_t addr[]; } __packed; #define BTP_CSIP_SET_COORDINATOR_RELEASE 0x05 struct btp_csip_set_coordinator_release_cmd { - uint8_t count; + uint8_t addr_cnt; + bt_addr_le_t addr[]; } __packed; /* CSIP Events */ diff --git a/tests/bluetooth/tester/src/btp_csip.c b/tests/bluetooth/tester/src/btp_csip.c index 497a313e5a287..62df2c717176c 100644 --- a/tests/bluetooth/tester/src/btp_csip.c +++ b/tests/bluetooth/tester/src/btp_csip.c @@ -16,6 +16,7 @@ LOG_MODULE_REGISTER(LOG_MODULE_NAME, CONFIG_BTTESTER_LOG_LEVEL); const struct bt_csip_set_coordinator_set_member *btp_csip_set_members[CONFIG_BT_MAX_CONN]; static const struct bt_csip_set_coordinator_csis_inst *cur_csis_inst; static struct bt_csip_set_coordinator_svc_inst *csip_inst; +static uint8_t members_count; static uint8_t btp_csip_supported_commands(const void *cmd, uint16_t cmd_len, void *rsp, uint16_t *rsp_len) @@ -189,15 +190,53 @@ static uint8_t btp_csip_discover(const void *cmd, uint16_t cmd_len, return BTP_STATUS_VAL(err); } +static int get_available_members(const struct bt_csip_set_coordinator_set_member **members) +{ + members_count = 0; + + if (cur_csis_inst == NULL) { + LOG_ERR("No CISP instance available"); + return BTP_STATUS_FAILED; + } + + for (size_t i = 0; i < (size_t)ARRAY_SIZE(btp_csip_set_members); i++) { + if (btp_csip_set_members[i] == NULL) { + continue; + } + + members[members_count++] = btp_csip_set_members[i]; + } + + if (members_count == 0) { + LOG_ERR("No set members available"); + return BTP_STATUS_FAILED; + } + + return BTP_STATUS_SUCCESS; +} + static uint8_t btp_csip_set_coordinator_lock(const void *cmd, uint16_t cmd_len, void *rsp, uint16_t *rsp_len) { + const struct bt_csip_set_coordinator_set_member *members[ARRAY_SIZE(btp_csip_set_members)]; const struct btp_csip_set_coordinator_lock_cmd *cp = cmd; int err; + int rc; LOG_DBG(""); - err = bt_csip_set_coordinator_lock(btp_csip_set_members, cp->count, &cur_csis_inst->info); + if (cp->addr_cnt != 0) { + /* TODO: add support for lock request procedure on subset of set members */ + return BTP_STATUS_FAILED; + } + + rc = get_available_members(members); + + if (rc) { + return BTP_STATUS_FAILED; + } + + err = bt_csip_set_coordinator_lock(members, members_count, &cur_csis_inst->info); if (err) { LOG_DBG("Failed to lock set members"); @@ -210,13 +249,25 @@ static uint8_t btp_csip_set_coordinator_lock(const void *cmd, uint16_t cmd_len, static uint8_t btp_csip_set_coordinator_release(const void *cmd, uint16_t cmd_len, void *rsp, uint16_t *rsp_len) { + const struct bt_csip_set_coordinator_set_member *members[ARRAY_SIZE(btp_csip_set_members)]; const struct btp_csip_set_coordinator_release_cmd *cp = cmd; int err; + int rc; LOG_DBG(""); - err = bt_csip_set_coordinator_release(btp_csip_set_members, cp->count, - &cur_csis_inst->info); + if (cp->addr_cnt != 0) { + /* TODO: add support for lock release procedure on subset of set members */ + return BTP_STATUS_FAILED; + } + + rc = get_available_members(members); + + if (rc) { + return BTP_STATUS_FAILED; + } + + err = bt_csip_set_coordinator_release(members, members_count, &cur_csis_inst->info); if (err) { LOG_DBG("Failed to release set members"); From 766a5ea5742d6645163a225ed8d96151119832dc Mon Sep 17 00:00:00 2001 From: Ren Chen Date: Fri, 24 Nov 2023 14:41:57 -0600 Subject: [PATCH 1349/2849] drivers: udc: add IT82xx2 USB device controller driver Add UDC driver for IT82xx2 SoC. This commit passes tests with 1. samples/subsys/usb/cdc_acm/ 2. samples/subsys/usb/console/ 3. The extend endpoint test with CDC ACM tool 4. USB suspend/resume detection Signed-off-by: Ren Chen --- drivers/usb/udc/CMakeLists.txt | 1 + drivers/usb/udc/Kconfig | 1 + drivers/usb/udc/Kconfig.it82xx2 | 27 + drivers/usb/udc/udc_it82xx2.c | 1477 +++++++++++++++++++++++++++++++ 4 files changed, 1506 insertions(+) create mode 100644 drivers/usb/udc/Kconfig.it82xx2 create mode 100644 drivers/usb/udc/udc_it82xx2.c diff --git a/drivers/usb/udc/CMakeLists.txt b/drivers/usb/udc/CMakeLists.txt index ebca5f6427753..2dd77536b2663 100644 --- a/drivers/usb/udc/CMakeLists.txt +++ b/drivers/usb/udc/CMakeLists.txt @@ -12,3 +12,4 @@ zephyr_library_sources_ifdef(CONFIG_UDC_KINETIS udc_kinetis.c) zephyr_library_sources_ifdef(CONFIG_UDC_SKELETON udc_skeleton.c) zephyr_library_sources_ifdef(CONFIG_UDC_VIRTUAL udc_virtual.c) zephyr_library_sources_ifdef(CONFIG_UDC_STM32 udc_stm32.c) +zephyr_library_sources_ifdef(CONFIG_UDC_IT82XX2 udc_it82xx2.c) diff --git a/drivers/usb/udc/Kconfig b/drivers/usb/udc/Kconfig index 5b19a3385ad9f..b407e1212b562 100644 --- a/drivers/usb/udc/Kconfig +++ b/drivers/usb/udc/Kconfig @@ -53,5 +53,6 @@ source "drivers/usb/udc/Kconfig.kinetis" source "drivers/usb/udc/Kconfig.skeleton" source "drivers/usb/udc/Kconfig.virtual" source "drivers/usb/udc/Kconfig.stm32" +source "drivers/usb/udc/Kconfig.it82xx2" endif # UDC_DRIVER diff --git a/drivers/usb/udc/Kconfig.it82xx2 b/drivers/usb/udc/Kconfig.it82xx2 new file mode 100644 index 0000000000000..649b2531d10db --- /dev/null +++ b/drivers/usb/udc/Kconfig.it82xx2 @@ -0,0 +1,27 @@ +# Copyright (c) 2023 ITE Corporation. +# SPDX-License-Identifier: Apache-2.0 + +config UDC_IT82XX2 + bool "IT82XX2 USB device controller driver" + default y + depends on DT_HAS_ITE_IT82XX2_USB_ENABLED + help + IT82xx2 USB device controller driver. + +if UDC_IT82XX2 + +config UDC_IT82xx2_EVENT_COUNT + int "UDC IT82xx2 event count" + range 4 64 + default 8 + help + IT82xx2 event count. + +config UDC_IT82xx2_STACK_SIZE + int "IT82xx2 UDC driver internal thread stack size" + default 1024 + help + Size of the stack used in the driver for IT82xx2 USBD ISR event + handling. + +endif # UDC_IT82XX2 diff --git a/drivers/usb/udc/udc_it82xx2.c b/drivers/usb/udc/udc_it82xx2.c new file mode 100644 index 0000000000000..70209f11e1770 --- /dev/null +++ b/drivers/usb/udc/udc_it82xx2.c @@ -0,0 +1,1477 @@ +/* + * Copyright (c) 2023 ITE Technology Corporation. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "udc_common.h" + +#include +#include +#include +#include +#include +#include +#include +LOG_MODULE_REGISTER(udc_it82xx2, CONFIG_UDC_DRIVER_LOG_LEVEL); + +#define DT_DRV_COMPAT ite_it82xx2_usb + +#define IT8XXX2_IS_EXTEND_ENDPOINT(n) (USB_EP_GET_IDX(n) >= 4) + +/* Shared FIFO number including FIFO_1/2/3 */ +#define SHARED_FIFO_NUM 3 + +/* The related definitions of the register dc_line_status: 0x51 */ +#define RX_LINE_STATE_MASK (RX_LINE_FULL_SPD | RX_LINE_LOW_SPD) +#define RX_LINE_LOW_SPD 0x02 +#define RX_LINE_FULL_SPD 0x01 +#define RX_LINE_RESET 0x00 + +#define DC_ADDR_NULL 0x00 +#define DC_ADDR_MASK 0x7F + +/* EPN Extend Control 2 Register Mask Definition */ +#define COMPLETED_TRANS 0xF0 + +/* The related definitions of the register EP STATUS: + * 0x41/0x45/0x49/0x4D + */ +#define EP_STATUS_ERROR 0x0F + +/* ENDPOINT[3..0]_CONTROL_REG */ +#define ENDPOINT_EN BIT(0) +#define ENDPOINT_RDY BIT(1) + +/* The bit definitions of the register EP RX/TX FIFO Control: + * EP_RX_FIFO_CONTROL: 0X64/0x84/0xA4/0xC4 + * EP_TX_FIFO_CONTROL: 0X74/0x94/0xB4/0xD4 + */ +#define FIFO_FORCE_EMPTY BIT(0) + +/* The bit definitions of the register Host/Device Control: 0XE0 */ +#define RESET_CORE BIT(1) + +/* ENDPOINT[3..0]_STATUS_REG */ +#define DC_STALL_SENT BIT(5) + +/* DC_INTERRUPT_STATUS_REG */ +#define DC_TRANS_DONE BIT(0) +#define DC_RESET_EVENT BIT(2) +#define DC_SOF_RECEIVED BIT(3) +#define DC_NAK_SENT_INT BIT(4) + +/* DC_CONTROL_REG */ +#define DC_GLOBAL_ENABLE BIT(0) +#define DC_TX_LINE_STATE_DM BIT(1) +#define DC_DIRECT_CONTROL BIT(3) +#define DC_FULL_SPEED_LINE_POLARITY BIT(4) +#define DC_FULL_SPEED_LINE_RATE BIT(5) +#define DC_CONNECT_TO_HOST BIT(6) /* internal pull-up */ + +/* Bit [1:0] represents the TRANSACTION_TYPE as follows: */ +enum it82xx2_transaction_types { + DC_SETUP_TRANS = 0, + DC_IN_TRANS, + DC_OUTDATA_TRANS, + DC_ALL_TRANS +}; + +enum it82xx2_event_type { + IT82xx2_EVT_XFER, + IT82xx2_EVT_SETUP_TOKEN, + IT82xx2_EVT_OUT_TOKEN, + IT82xx2_EVT_IN_TOKEN, +}; + +struct it82xx2_ep_event { + sys_snode_t node; + const struct device *dev; + uint8_t ep; + enum it82xx2_event_type event; +}; + +K_MSGQ_DEFINE(evt_msgq, sizeof(struct it82xx2_ep_event), + CONFIG_UDC_IT82xx2_EVENT_COUNT, sizeof(uint32_t)); + +struct usb_it8xxx2_wuc { + /* WUC control device structure */ + const struct device *dev; + /* WUC pin mask */ + uint8_t mask; +}; + +struct it82xx2_data { + const struct device *dev; + + struct k_fifo fifo; + struct k_work_delayable suspended_work; + + struct k_thread thread_data; + struct k_sem suspended_sem; + + /* FIFO_1/2/3 ready status */ + bool fifo_ready[SHARED_FIFO_NUM]; + + /* FIFO_1/2/3 semaphore */ + struct k_sem fifo_sem[SHARED_FIFO_NUM]; + + /* Record if the previous transaction of endpoint0 is STALL */ + bool stall_is_sent; +}; + +struct usb_it82xx2_config { + struct usb_it82xx2_regs *const base; + const struct pinctrl_dev_config *pcfg; + const struct usb_it8xxx2_wuc wuc; + uint8_t usb_irq; + uint8_t wu_irq; + struct udc_ep_config *ep_cfg_in; + struct udc_ep_config *ep_cfg_out; + void (*make_thread)(const struct device *dev); +}; + +enum it82xx2_ep_ctrl { + EP_IN_DIRECTION_SET, + EP_IOS_ENABLE, + EP_ENABLE, + EP_DATA_SEQ_1, + EP_DATA_SEQ_TOGGLE, + EP_READY_ENABLE, +}; + +static inline void ep_set_halt(const struct device *dev, const uint8_t ep_idx, const bool enable) +{ + const struct usb_it82xx2_config *config = dev->config; + struct usb_it82xx2_regs *const usb_regs = config->base; + struct it82xx2_usb_ep_regs *ep_regs = usb_regs->usb_ep_regs; + union epn0n1_extend_ctrl_reg *ext_ctrl; + uint8_t idx = (ep_idx - 4) / 2; + + ext_ctrl = usb_regs->fifo_regs[EP_EXT_REGS_9X].ext_4_15.epn0n1_ext_ctrl; + if (IT8XXX2_IS_EXTEND_ENDPOINT(ep_idx)) { + if (ep_idx % 2) { + ext_ctrl[idx].fields.epn1_send_stall_bit = enable; + } else { + ext_ctrl[idx].fields.epn0_send_stall_bit = enable; + } + } else { + ep_regs[ep_idx].ep_ctrl.fields.send_stall_bit = enable; + } +} + +static volatile void *it82xx2_get_ext_ctrl(const struct device *dev, const uint8_t ep_idx, + const enum it82xx2_ep_ctrl ctrl) +{ + uint8_t idx; + const struct usb_it82xx2_config *config = dev->config; + struct usb_it82xx2_regs *const usb_regs = config->base; + union epn0n1_extend_ctrl_reg *epn0n1_ext_ctrl = + usb_regs->fifo_regs[EP_EXT_REGS_9X].ext_4_15.epn0n1_ext_ctrl; + struct epn_ext_ctrl_regs *ext_ctrl = + usb_regs->fifo_regs[EP_EXT_REGS_DX].ext_0_3.epn_ext_ctrl; + + if (ctrl == EP_IN_DIRECTION_SET || ctrl == EP_ENABLE) { + idx = ((ep_idx - 4) % 3) + 1; + return &ext_ctrl[idx].epn_ext_ctrl1; + } + + idx = (ep_idx - 4) / 2; + return &epn0n1_ext_ctrl[idx]; +} + +static int it82xx2_usb_extend_ep_ctrl(const struct device *dev, const uint8_t ep, + const enum it82xx2_ep_ctrl ctrl, const bool enable) +{ + const struct usb_it82xx2_config *config = dev->config; + struct usb_it82xx2_regs *const usb_regs = config->base; + struct epn_ext_ctrl_regs *ext_ctrl = + usb_regs->fifo_regs[EP_EXT_REGS_DX].ext_0_3.epn_ext_ctrl; + volatile union epn_extend_ctrl1_reg *epn_ext_ctrl1 = NULL; + volatile union epn0n1_extend_ctrl_reg *epn0n1_ext_ctrl = NULL; + const uint8_t ep_idx = USB_EP_GET_IDX(ep); + + if (ctrl == EP_IN_DIRECTION_SET || ctrl == EP_ENABLE) { + epn_ext_ctrl1 = it82xx2_get_ext_ctrl(dev, ep_idx, ctrl); + } else { + epn0n1_ext_ctrl = it82xx2_get_ext_ctrl(dev, ep_idx, ctrl); + } + + switch (ctrl) { + case EP_IOS_ENABLE: + if (ep_idx % 2) { + epn0n1_ext_ctrl->fields.epn1_iso_enable_bit = enable; + } else { + epn0n1_ext_ctrl->fields.epn0_iso_enable_bit = enable; + } + break; + case EP_DATA_SEQ_1: + if (ep_idx % 2) { + epn0n1_ext_ctrl->fields.epn1_outdata_sequence_bit = enable; + } else { + epn0n1_ext_ctrl->fields.epn0_outdata_sequence_bit = enable; + } + break; + case EP_DATA_SEQ_TOGGLE: + if (!enable) { + break; + } + if (ep_idx % 2) { + if (epn0n1_ext_ctrl->fields.epn1_outdata_sequence_bit) { + epn0n1_ext_ctrl->fields.epn1_outdata_sequence_bit = 0; + } else { + epn0n1_ext_ctrl->fields.epn1_outdata_sequence_bit = 1; + } + } else { + if (epn0n1_ext_ctrl->fields.epn0_outdata_sequence_bit) { + epn0n1_ext_ctrl->fields.epn0_outdata_sequence_bit = 0; + } else { + epn0n1_ext_ctrl->fields.epn0_outdata_sequence_bit = 1; + } + } + break; + case EP_IN_DIRECTION_SET: + if (((ep_idx - 4) / 3 == 0)) { + epn_ext_ctrl1->fields.epn0_direction_bit = enable; + } else if (((ep_idx - 4) / 3 == 1)) { + epn_ext_ctrl1->fields.epn3_direction_bit = enable; + } else if (((ep_idx - 4) / 3 == 2)) { + epn_ext_ctrl1->fields.epn6_direction_bit = enable; + } else if (((ep_idx - 4) / 3 == 3)) { + epn_ext_ctrl1->fields.epn9_direction_bit = enable; + } else { + LOG_ERR("Invalid endpoint 0x%x for control type 0x%x", ep, ctrl); + return -EINVAL; + } + break; + case EP_ENABLE: + if (((ep_idx - 4) / 3 == 0)) { + epn_ext_ctrl1->fields.epn0_enable_bit = enable; + } else if (((ep_idx - 4) / 3 == 1)) { + epn_ext_ctrl1->fields.epn3_enable_bit = enable; + } else if (((ep_idx - 4) / 3 == 2)) { + epn_ext_ctrl1->fields.epn6_enable_bit = enable; + } else if (((ep_idx - 4) / 3 == 3)) { + epn_ext_ctrl1->fields.epn9_enable_bit = enable; + } else { + LOG_ERR("Invalid endpoint 0x%x for control type 0x%x", ep, ctrl); + return -EINVAL; + } + break; + case EP_READY_ENABLE: + int idx = ((ep_idx - 4) % 3) + 1; + + (enable) ? (ext_ctrl[idx].epn_ext_ctrl2 |= BIT((ep_idx - 4) / 3)) + : (ext_ctrl[idx].epn_ext_ctrl2 &= ~BIT((ep_idx - 4) / 3)); + break; + default: + LOG_ERR("Unknown control type 0x%x", ctrl); + return -EINVAL; + } + + return 0; +} + +static int it82xx2_usb_ep_ctrl(const struct device *dev, uint8_t ep, enum it82xx2_ep_ctrl ctrl, + bool enable) +{ + const struct usb_it82xx2_config *config = dev->config; + struct usb_it82xx2_regs *const usb_regs = config->base; + struct it82xx2_usb_ep_regs *ep_regs = usb_regs->usb_ep_regs; + const uint8_t ep_idx = USB_EP_GET_IDX(ep); + + if (IT8XXX2_IS_EXTEND_ENDPOINT(ep_idx)) { + return -EINVAL; + } + + switch (ctrl) { + case EP_IN_DIRECTION_SET: + ep_regs[ep_idx].ep_ctrl.fields.direction_bit = enable; + break; + case EP_IOS_ENABLE: + ep_regs[ep_idx].ep_ctrl.fields.iso_enable_bit = enable; + break; + case EP_ENABLE: + ep_regs[ep_idx].ep_ctrl.fields.enable_bit = enable; + break; + case EP_READY_ENABLE: + ep_regs[ep_idx].ep_ctrl.fields.ready_bit = enable; + break; + case EP_DATA_SEQ_1: + ep_regs[ep_idx].ep_ctrl.fields.outdata_sequence_bit = enable; + break; + case EP_DATA_SEQ_TOGGLE: + if (!enable) { + break; + } + if (ep_regs[ep_idx].ep_ctrl.fields.outdata_sequence_bit) { + ep_regs[ep_idx].ep_ctrl.fields.outdata_sequence_bit = 0; + } else { + ep_regs[ep_idx].ep_ctrl.fields.outdata_sequence_bit = 1; + } + break; + default: + LOG_ERR("Unknown control type 0x%x", ctrl); + return -EINVAL; + } + return 0; +} + +static int it82xx2_usb_set_ep_ctrl(const struct device *dev, uint8_t ep, enum it82xx2_ep_ctrl ctrl, + bool enable) +{ + const uint8_t ep_idx = USB_EP_GET_IDX(ep); + int ret = 0; + + if (IT8XXX2_IS_EXTEND_ENDPOINT(ep_idx)) { + ret = it82xx2_usb_extend_ep_ctrl(dev, ep, ctrl, enable); + } else { + ret = it82xx2_usb_ep_ctrl(dev, ep, ctrl, enable); + } + return ret; +} + +/* Standby(deep doze) mode enable/disable */ +static void it82xx2_enable_standby_state(bool enable) +{ + if (enable) { + pm_policy_state_lock_put(PM_STATE_STANDBY, PM_ALL_SUBSTATES); + } else { + pm_policy_state_lock_get(PM_STATE_STANDBY, PM_ALL_SUBSTATES); + } +} + +/* Wake-up interrupt (USB D+) Enable/Disable */ +static void it82xx2_enable_wu_irq(const struct device *dev, bool enable) +{ + const struct usb_it82xx2_config *config = dev->config; + + /* Clear pending interrupt */ + it8xxx2_wuc_clear_status(config->wuc.dev, config->wuc.mask); + + if (enable) { + irq_enable(config->wu_irq); + } else { + irq_disable(config->wu_irq); + } +} + +static void it82xx2_wu_isr(const void *arg) +{ + const struct device *dev = arg; + + it82xx2_enable_wu_irq(dev, false); + it82xx2_enable_standby_state(false); + LOG_DBG("USB D+ (WU) Triggered"); +} + +static void it8xxx2_usb_dc_wuc_init(const struct device *dev) +{ + const struct usb_it82xx2_config *config = dev->config; + + /* Initializing the WUI */ + it8xxx2_wuc_set_polarity(config->wuc.dev, config->wuc.mask, WUC_TYPE_EDGE_FALLING); + it8xxx2_wuc_clear_status(config->wuc.dev, config->wuc.mask); + + /* Enabling the WUI */ + it8xxx2_wuc_enable(config->wuc.dev, config->wuc.mask); + + /* Connect WU (USB D+) interrupt but make it disabled initially */ + irq_connect_dynamic(config->wu_irq, 0, it82xx2_wu_isr, dev, 0); +} + +/* The ep_fifo_res[ep_idx % SHARED_FIFO_NUM] where the SHARED_FIFO_NUM is 3 represents the + * EP mapping because when (ep_idx % SHARED_FIFO_NUM) is 3, it actually means the EP0. + */ +static const uint8_t ep_fifo_res[SHARED_FIFO_NUM] = {3, 1, 2}; + +static int it82xx2_usb_fifo_ctrl(const struct device *dev, uint8_t ep) +{ + const uint8_t ep_idx = USB_EP_GET_IDX(ep); + const struct usb_it82xx2_config *config = dev->config; + struct usb_it82xx2_regs *const usb_regs = config->base; + volatile uint8_t *ep_fifo_ctrl = usb_regs->fifo_regs[EP_EXT_REGS_BX].fifo_ctrl.ep_fifo_ctrl; + uint8_t fifon_ctrl = (ep_fifo_res[ep_idx % SHARED_FIFO_NUM] - 1) * 2; + int ret = 0; + + if (ep_idx == 0) { + LOG_ERR("Invalid endpoint 0x%x", ep); + return -EINVAL; + } + + if (USB_EP_DIR_IS_IN(ep)) { + if (ep_idx < 8) { + ep_fifo_ctrl[fifon_ctrl] = BIT(ep_idx); + ep_fifo_ctrl[fifon_ctrl + 1] = 0x0; + } else { + ep_fifo_ctrl[fifon_ctrl] = 0x0; + ep_fifo_ctrl[fifon_ctrl + 1] = BIT(ep_idx - 8); + } + } else if (USB_EP_DIR_IS_OUT(ep)) { + if (ep_idx < 8) { + ep_fifo_ctrl[fifon_ctrl] |= BIT(ep_idx); + } else { + ep_fifo_ctrl[fifon_ctrl + 1] |= BIT(ep_idx - 8); + } + } else { + LOG_ERR("Failed to set fifo control register for ep 0x%x", ep); + ret = -EINVAL; + } + + return ret; +} + +static void it82xx2_event_submit(const struct device *dev, const uint8_t ep, + const enum it82xx2_event_type event) +{ + struct it82xx2_ep_event evt; + + evt.dev = dev; + evt.ep = ep; + evt.event = event; + k_msgq_put(&evt_msgq, &evt, K_NO_WAIT); +} + +static int it82xx2_ep_enqueue(const struct device *dev, struct udc_ep_config *const cfg, + struct net_buf *const buf) +{ + udc_buf_put(cfg, buf); + + it82xx2_event_submit(dev, cfg->addr, IT82xx2_EVT_XFER); + return 0; +} + +static int it82xx2_ep_dequeue(const struct device *dev, struct udc_ep_config *const cfg) +{ + const uint8_t ep_idx = USB_EP_GET_IDX(cfg->addr); + const struct usb_it82xx2_config *config = dev->config; + struct usb_it82xx2_regs *const usb_regs = config->base; + struct it82xx2_usb_ep_fifo_regs *ff_regs = usb_regs->fifo_regs; + struct net_buf *buf; + unsigned int lock_key; + uint8_t fifo_idx; + + fifo_idx = ep_idx > 0 ? ep_fifo_res[ep_idx % SHARED_FIFO_NUM] : 0; + lock_key = irq_lock(); + if (USB_EP_DIR_IS_IN(cfg->addr)) { + ff_regs[fifo_idx].ep_tx_fifo_ctrl = FIFO_FORCE_EMPTY; + } else { + ff_regs[fifo_idx].ep_rx_fifo_ctrl = FIFO_FORCE_EMPTY; + } + irq_unlock(lock_key); + + buf = udc_buf_get_all(dev, cfg->addr); + if (buf) { + udc_submit_ep_event(dev, buf, -ECONNABORTED); + } + + udc_ep_set_busy(dev, cfg->addr, false); + + return 0; +} + +static inline void ctrl_ep_stall_workaround(const struct device *dev) +{ + const struct usb_it82xx2_config *config = dev->config; + struct usb_it82xx2_regs *const usb_regs = config->base; + struct it82xx2_usb_ep_regs *ep_regs = usb_regs->usb_ep_regs; + struct gctrl_it8xxx2_regs *const gctrl_regs = GCTRL_IT8XXX2_REGS_BASE; + struct it82xx2_data *priv = udc_get_private(dev); + unsigned int lock_key; + uint32_t idx = 0; + + priv->stall_is_sent = true; + lock_key = irq_lock(); + ep_set_halt(dev, 0, true); + it82xx2_usb_set_ep_ctrl(dev, 0, EP_READY_ENABLE, true); + + /* It82xx2 does not support clearing the STALL bit by hardware; instead, the STALL bit need + * to be cleared by firmware. The SETUP token will be STALLed, which isn't compliant to + * USB specification, if firmware clears the STALL bit too late. Due to this hardware + * limitations, device controller polls to check if the stall bit has been transmitted for + * 3ms and then disables it after responsing STALLed. + */ + while (idx < 198 && !(ep_regs[0].ep_status & DC_STALL_SENT)) { + /* wait 15.15us */ + gctrl_regs->GCTRL_WNCKR = 0; + idx++; + } + + if (idx < 198) { + ep_set_halt(dev, 0, false); + } + irq_unlock(lock_key); +} + +static int it82xx2_ep_set_halt(const struct device *dev, struct udc_ep_config *const cfg) +{ + const uint8_t ep_idx = USB_EP_GET_IDX(cfg->addr); + + if (ep_idx == 0) { + ctrl_ep_stall_workaround(dev); + } else { + ep_set_halt(dev, ep_idx, true); + it82xx2_usb_set_ep_ctrl(dev, ep_idx, EP_READY_ENABLE, true); + } + + LOG_DBG("Endpoint 0x%x is halted", cfg->addr); + + return 0; +} + +static int it82xx2_ep_clear_halt(const struct device *dev, struct udc_ep_config *const cfg) +{ + const uint8_t ep_idx = USB_EP_GET_IDX(cfg->addr); + + ep_set_halt(dev, ep_idx, false); + + LOG_DBG("Endpoint 0x%x clear halted", cfg->addr); + + return 0; +} + +static int it82xx2_ep_enable(const struct device *dev, struct udc_ep_config *const cfg) +{ + const uint8_t ep_idx = USB_EP_GET_IDX(cfg->addr); + + /* Configure endpoint */ + if (ep_idx != 0) { + if (USB_EP_DIR_IS_IN(cfg->addr)) { + it82xx2_usb_set_ep_ctrl(dev, ep_idx, EP_IN_DIRECTION_SET, true); + } else { + it82xx2_usb_set_ep_ctrl(dev, ep_idx, EP_IN_DIRECTION_SET, false); + it82xx2_usb_fifo_ctrl(dev, cfg->addr); + } + + switch (cfg->attributes & USB_EP_TRANSFER_TYPE_MASK) { + case USB_EP_TYPE_BULK: + __fallthrough; + case USB_EP_TYPE_INTERRUPT: + it82xx2_usb_set_ep_ctrl(dev, ep_idx, EP_IOS_ENABLE, false); + break; + case USB_EP_TYPE_ISO: + it82xx2_usb_set_ep_ctrl(dev, ep_idx, EP_IOS_ENABLE, true); + break; + case USB_EP_TYPE_CONTROL: + __fallthrough; + default: + return -ENOTSUP; + } + } + + if (IT8XXX2_IS_EXTEND_ENDPOINT(ep_idx)) { + uint8_t fifo_idx; + + fifo_idx = ep_fifo_res[ep_idx % SHARED_FIFO_NUM]; + it82xx2_usb_set_ep_ctrl(dev, fifo_idx, EP_ENABLE, true); + } + + it82xx2_usb_set_ep_ctrl(dev, ep_idx, EP_ENABLE, true); + + LOG_DBG("Endpoint 0x%02x is enabled", cfg->addr); + + return 0; +} + +static int it82xx2_ep_disable(const struct device *dev, struct udc_ep_config *const cfg) +{ + const uint8_t ep_idx = USB_EP_GET_IDX(cfg->addr); + + it82xx2_usb_set_ep_ctrl(dev, ep_idx, EP_ENABLE, false); + + LOG_DBG("Endpoint 0x%02x is disabled", cfg->addr); + + return 0; +} + +static int it82xx2_host_wakeup(const struct device *dev) +{ + struct it82xx2_data *priv = udc_get_private(dev); + const struct usb_it82xx2_config *config = dev->config; + struct usb_it82xx2_regs *const usb_regs = config->base; + int ret; + + if (udc_is_suspended(dev)) { + usb_regs->dc_control = DC_GLOBAL_ENABLE | DC_FULL_SPEED_LINE_POLARITY | + DC_FULL_SPEED_LINE_RATE | DC_DIRECT_CONTROL | + DC_TX_LINE_STATE_DM | DC_CONNECT_TO_HOST; + + /* The remote wakeup device must hold the resume signal for */ + /* at least 1 ms but for no more than 15 ms */ + k_msleep(2); + + usb_regs->dc_control = DC_GLOBAL_ENABLE | DC_FULL_SPEED_LINE_POLARITY | + DC_FULL_SPEED_LINE_RATE | DC_CONNECT_TO_HOST; + + ret = k_sem_take(&priv->suspended_sem, K_MSEC(500)); + if (ret < 0) { + LOG_ERR("Failed to wake up host"); + } + } + + return 0; +} + +static int it82xx2_set_address(const struct device *dev, const uint8_t addr) +{ + const struct usb_it82xx2_config *config = dev->config; + struct usb_it82xx2_regs *const usb_regs = config->base; + + usb_regs->dc_address = addr & DC_ADDR_MASK; + + LOG_DBG("Set usb address 0x%02x", addr); + + return 0; +} + +static int it82xx2_usb_dc_ip_init(const struct device *dev) +{ + const struct usb_it82xx2_config *config = dev->config; + struct usb_it82xx2_regs *const usb_regs = config->base; + + /* reset usb controller */ + usb_regs->host_device_control = RESET_CORE; + k_msleep(1); + usb_regs->port0_misc_control &= ~(PULL_DOWN_EN); + usb_regs->port1_misc_control &= ~(PULL_DOWN_EN); + + /* clear reset bit */ + usb_regs->host_device_control = 0; + + usb_regs->dc_interrupt_status = DC_TRANS_DONE | DC_RESET_EVENT | DC_SOF_RECEIVED; + + usb_regs->dc_interrupt_mask = 0x00; + usb_regs->dc_interrupt_mask = DC_TRANS_DONE | DC_RESET_EVENT | DC_SOF_RECEIVED; + + usb_regs->dc_address = DC_ADDR_NULL; + + return 0; +} + +static void it82xx2_enable_sof_int(const struct device *dev, bool enable) +{ + const struct usb_it82xx2_config *config = dev->config; + struct usb_it82xx2_regs *const usb_regs = config->base; + + usb_regs->dc_interrupt_status = DC_SOF_RECEIVED; + if (enable) { + usb_regs->dc_interrupt_mask |= DC_SOF_RECEIVED; + } else { + usb_regs->dc_interrupt_mask &= ~DC_SOF_RECEIVED; + } +} + +void it82xx2_dc_reset(const struct device *dev) +{ + const struct usb_it82xx2_config *config = dev->config; + struct usb_it82xx2_regs *const usb_regs = config->base; + struct it82xx2_usb_ep_regs *ep_regs = usb_regs->usb_ep_regs; + struct it82xx2_usb_ep_fifo_regs *ff_regs = usb_regs->fifo_regs; + struct it82xx2_data *priv = udc_get_private(dev); + + for (uint8_t ep_idx = 0; ep_idx < 4; ep_idx++) { + ff_regs[ep_idx].ep_rx_fifo_ctrl = FIFO_FORCE_EMPTY; + ff_regs[ep_idx].ep_tx_fifo_ctrl = FIFO_FORCE_EMPTY; + } + + ep_regs[0].ep_ctrl.value = ENDPOINT_EN; + usb_regs->dc_address = DC_ADDR_NULL; + usb_regs->dc_interrupt_status = DC_NAK_SENT_INT | DC_SOF_RECEIVED; + + priv->fifo_ready[0] = false; + priv->fifo_ready[1] = false; + priv->fifo_ready[2] = false; + k_sem_give(&priv->fifo_sem[0]); + k_sem_give(&priv->fifo_sem[1]); + k_sem_give(&priv->fifo_sem[2]); +} + +static int it82xx2_xfer_in_data(const struct device *dev, uint8_t ep, struct net_buf *buf) +{ + const uint8_t ep_idx = USB_EP_GET_IDX(ep); + const struct usb_it82xx2_config *config = dev->config; + struct usb_it82xx2_regs *const usb_regs = config->base; + struct it82xx2_usb_ep_fifo_regs *ff_regs = usb_regs->fifo_regs; + struct it82xx2_data *priv = udc_get_private(dev); + struct udc_ep_config *ep_cfg = udc_get_ep_cfg(dev, ep); + uint8_t fifo_idx; + size_t len; + + fifo_idx = ep_idx > 0 ? ep_fifo_res[ep_idx % SHARED_FIFO_NUM] : 0; + if (ep_idx == 0) { + ff_regs[ep_idx].ep_tx_fifo_ctrl = FIFO_FORCE_EMPTY; + } else { + k_sem_take(&priv->fifo_sem[fifo_idx - 1], K_FOREVER); + it82xx2_usb_fifo_ctrl(dev, ep); + } + + len = MIN(buf->len, ep_cfg->mps); + + for (size_t i = 0; i < len; i++) { + ff_regs[fifo_idx].ep_tx_fifo_data = buf->data[i]; + } + + if (IT8XXX2_IS_EXTEND_ENDPOINT(ep_idx)) { + it82xx2_usb_extend_ep_ctrl(dev, ep_idx, EP_READY_ENABLE, true); + } + it82xx2_usb_set_ep_ctrl(dev, fifo_idx, EP_READY_ENABLE, true); + + if (ep_idx != 0) { + priv->fifo_ready[fifo_idx - 1] = true; + } + + LOG_DBG("Writed %d packets to endpoint%d tx fifo", buf->len, ep_idx); + + return 0; +} + +static int it82xx2_xfer_out_data(const struct device *dev, uint8_t ep, struct net_buf *buf) +{ + const struct usb_it82xx2_config *config = dev->config; + struct usb_it82xx2_regs *const usb_regs = config->base; + struct it82xx2_usb_ep_regs *ep_regs = usb_regs->usb_ep_regs; + struct it82xx2_usb_ep_fifo_regs *ff_regs = usb_regs->fifo_regs; + const uint8_t ep_idx = USB_EP_GET_IDX(ep); + uint8_t fifo_idx; + size_t len; + + fifo_idx = ep_idx > 0 ? ep_fifo_res[ep_idx % SHARED_FIFO_NUM] : 0; + if (ep_regs[fifo_idx].ep_status & EP_STATUS_ERROR) { + LOG_WRN("endpoint%d error status 0x%02x", ep_idx, ep_regs[fifo_idx].ep_status); + return -EINVAL; + } + + len = (uint16_t)ff_regs[fifo_idx].ep_rx_fifo_dcnt_lsb + + (((uint16_t)ff_regs[fifo_idx].ep_rx_fifo_dcnt_msb) << 8); + + len = MIN(net_buf_tailroom(buf), len); + uint8_t *data_ptr = net_buf_tail(buf); + + for (size_t idx = 0; idx < len; idx++) { + data_ptr[idx] = ff_regs[fifo_idx].ep_rx_fifo_data; + } + + net_buf_add(buf, len); + + return 0; +} + +static int work_handler_xfer_continue(const struct device *dev, uint8_t ep, struct net_buf *buf) +{ + int ret = 0; + + if (USB_EP_DIR_IS_OUT(ep)) { + const uint8_t ep_idx = USB_EP_GET_IDX(ep); + struct it82xx2_data *priv = udc_get_private(dev); + uint8_t fifo_idx; + + fifo_idx = ep_idx > 0 ? ep_fifo_res[ep_idx % SHARED_FIFO_NUM] : 0; + it82xx2_usb_set_ep_ctrl(dev, ep_idx, EP_READY_ENABLE, true); + if (IT8XXX2_IS_EXTEND_ENDPOINT(ep_idx)) { + it82xx2_usb_set_ep_ctrl(dev, fifo_idx, EP_READY_ENABLE, true); + } + if (ep_idx != 0) { + priv->fifo_ready[fifo_idx - 1] = true; + } + } else { + ret = it82xx2_xfer_in_data(dev, ep, buf); + } + + return ret; +} + +static int work_handler_xfer_next(const struct device *dev, uint8_t ep) +{ + struct net_buf *buf; + + buf = udc_buf_peek(dev, ep); + if (buf == NULL) { + return -ENODATA; + } + + return work_handler_xfer_continue(dev, ep, buf); +} + +/* + * Allocate buffer and initiate a new control OUT transfer, + * use successive buffer descriptor when next is true. + */ +static int it82xx2_ctrl_feed_dout(const struct device *dev, const size_t length) +{ + struct udc_ep_config *cfg = udc_get_ep_cfg(dev, USB_CONTROL_EP_OUT); + struct net_buf *buf; + + buf = udc_ctrl_alloc(dev, USB_CONTROL_EP_OUT, length); + if (buf == NULL) { + return -ENOMEM; + } + udc_buf_put(cfg, buf); + + it82xx2_usb_set_ep_ctrl(dev, 0, EP_READY_ENABLE, true); + + return 0; +} + +static bool it82xx2_fake_token(const struct device *dev, uint8_t ep, uint8_t token_type) +{ + struct it82xx2_data *priv = udc_get_private(dev); + const uint8_t ep_idx = USB_EP_GET_IDX(ep); + uint8_t fifo_idx; + bool is_fake = true; + + if (ep_idx == 0) { + switch (token_type) { + case DC_IN_TRANS: + if (priv->stall_is_sent) { + return true; + } + is_fake = !udc_ctrl_stage_is_data_in(dev) && + !udc_ctrl_stage_is_status_in(dev) && + !udc_ctrl_stage_is_no_data(dev); + break; + case DC_OUTDATA_TRANS: + is_fake = !udc_ctrl_stage_is_data_out(dev) && + !udc_ctrl_stage_is_status_out(dev); + break; + default: + LOG_ERR("Invalid token type"); + break; + } + } else { + fifo_idx = ep_fifo_res[ep_idx % SHARED_FIFO_NUM]; + + if (!priv->fifo_ready[fifo_idx - 1]) { + is_fake = true; + } else { + priv->fifo_ready[fifo_idx - 1] = false; + is_fake = false; + } + } + + return is_fake; +} + +static inline int work_handler_in(const struct device *dev, uint8_t ep) +{ + struct it82xx2_data *priv = udc_get_private(dev); + struct udc_ep_config *ep_cfg; + struct net_buf *buf; + uint8_t fifo_idx; + int err = 0; + + if (it82xx2_fake_token(dev, ep, DC_IN_TRANS)) { + return 0; + } + + if (ep != USB_CONTROL_EP_IN) { + fifo_idx = ep_fifo_res[USB_EP_GET_IDX(ep) % SHARED_FIFO_NUM]; + k_sem_give(&priv->fifo_sem[fifo_idx - 1]); + } + + buf = udc_buf_peek(dev, ep); + if (buf == NULL) { + return -ENODATA; + } + ep_cfg = udc_get_ep_cfg(dev, ep); + + net_buf_pull(buf, MIN(buf->len, ep_cfg->mps)); + + it82xx2_usb_set_ep_ctrl(dev, ep, EP_DATA_SEQ_TOGGLE, true); + + if (buf->len) { + work_handler_xfer_continue(dev, ep, buf); + return 0; + } + + if (udc_ep_buf_has_zlp(buf)) { + work_handler_xfer_continue(dev, ep, buf); + udc_ep_buf_clear_zlp(buf); + return 0; + } + + buf = udc_buf_get(dev, ep); + if (buf == NULL) { + return -ENODATA; + } + + udc_ep_set_busy(dev, ep, false); + + if (ep == USB_CONTROL_EP_IN) { + if (udc_ctrl_stage_is_status_in(dev) || udc_ctrl_stage_is_no_data(dev)) { + /* Status stage finished, notify upper layer */ + udc_ctrl_submit_status(dev, buf); + } + + /* Update to next stage of control transfer */ + udc_ctrl_update_stage(dev, buf); + + if (udc_ctrl_stage_is_status_out(dev)) { + /* + * IN transfer finished, release buffer, + * Feed control OUT buffer for status stage. + */ + net_buf_unref(buf); + return it82xx2_ctrl_feed_dout(dev, 0U); + } + return err; + } + + return udc_submit_ep_event(dev, buf, 0); +} + +static inline int work_handler_setup(const struct device *dev, uint8_t ep) +{ + struct it82xx2_data *priv = udc_get_private(dev); + struct net_buf *buf; + int err = 0; + + if (udc_ctrl_stage_is_status_out(dev)) { + /* out -> setup */ + buf = udc_buf_get(dev, USB_CONTROL_EP_OUT); + if (buf) { + udc_ep_set_busy(dev, USB_CONTROL_EP_OUT, false); + net_buf_unref(buf); + } + } + + if (udc_ctrl_stage_is_status_in(dev) || udc_ctrl_stage_is_no_data(dev)) { + /* in -> setup */ + work_handler_in(dev, USB_CONTROL_EP_IN); + } + + buf = udc_ctrl_alloc(dev, USB_CONTROL_EP_OUT, sizeof(struct usb_setup_packet)); + if (buf == NULL) { + LOG_ERR("Failed to allocate buffer"); + return -ENOMEM; + } + + udc_ep_buf_set_setup(buf); + it82xx2_xfer_out_data(dev, ep, buf); + if (buf->len != sizeof(struct usb_setup_packet)) { + LOG_DBG("buffer length %d read from chip", buf->len); + net_buf_unref(buf); + return 0; + } + + priv->stall_is_sent = false; + LOG_HEXDUMP_DBG(buf->data, buf->len, "setup:"); + + udc_ctrl_update_stage(dev, buf); + + it82xx2_usb_set_ep_ctrl(dev, ep, EP_DATA_SEQ_1, true); + + if (udc_ctrl_stage_is_data_out(dev)) { + /* Allocate and feed buffer for data OUT stage */ + LOG_DBG("s:%p|feed for -out-", buf); + err = it82xx2_ctrl_feed_dout(dev, udc_data_stage_length(buf)); + if (err == -ENOMEM) { + err = udc_submit_ep_event(dev, buf, err); + } + } else if (udc_ctrl_stage_is_data_in(dev)) { + udc_ctrl_submit_s_in_status(dev); + } else { + udc_ctrl_submit_s_status(dev); + } + + return err; +} + +static inline int work_handler_out(const struct device *dev, uint8_t ep) +{ + struct net_buf *buf; + int err = 0; + + const uint8_t ep_idx = USB_EP_GET_IDX(ep); + const struct usb_it82xx2_config *config = dev->config; + struct usb_it82xx2_regs *const usb_regs = config->base; + struct it82xx2_usb_ep_fifo_regs *ff_regs = usb_regs->fifo_regs; + struct udc_ep_config *ep_cfg; + uint8_t fifo_idx; + size_t len; + + if (it82xx2_fake_token(dev, ep, DC_OUTDATA_TRANS)) { + return 0; + } + + buf = udc_buf_get(dev, ep); + if (buf == NULL) { + return -ENODATA; + } + + udc_ep_set_busy(dev, ep, false); + + fifo_idx = ep_idx > 0 ? ep_fifo_res[ep_idx % SHARED_FIFO_NUM] : 0; + len = (uint16_t)ff_regs[fifo_idx].ep_rx_fifo_dcnt_lsb + + (((uint16_t)ff_regs[fifo_idx].ep_rx_fifo_dcnt_msb) << 8); + + if (ep == USB_CONTROL_EP_OUT) { + if (udc_ctrl_stage_is_status_out(dev) && len != 0) { + LOG_DBG("Handle early setup token"); + /* Notify upper layer */ + udc_ctrl_submit_status(dev, buf); + /* Update to next stage of control transfer */ + udc_ctrl_update_stage(dev, buf); + return 0; + } + } + + ep_cfg = udc_get_ep_cfg(dev, ep); + if (len > ep_cfg->mps) { + LOG_ERR("Failed to handle this packet due to the packet size"); + return -ENOBUFS; + } + + it82xx2_xfer_out_data(dev, ep, buf); + + if (ep == USB_CONTROL_EP_OUT) { + if (udc_ctrl_stage_is_status_out(dev)) { + /* Status stage finished, notify upper layer */ + udc_ctrl_submit_status(dev, buf); + } + + /* Update to next stage of control transfer */ + udc_ctrl_update_stage(dev, buf); + + if (udc_ctrl_stage_is_status_in(dev)) { + it82xx2_usb_set_ep_ctrl(dev, ep, EP_DATA_SEQ_1, true); + err = udc_ctrl_submit_s_out_status(dev, buf); + } + } else { + err = udc_submit_ep_event(dev, buf, 0); + } + + return err; +} + +static void xfer_work_handler(const struct device *dev) +{ + while (true) { + struct it82xx2_ep_event evt; + int err = 0; + + k_msgq_get(&evt_msgq, &evt, K_FOREVER); + + switch (evt.event) { + case IT82xx2_EVT_SETUP_TOKEN: + err = work_handler_setup(evt.dev, evt.ep); + break; + case IT82xx2_EVT_IN_TOKEN: + err = work_handler_in(evt.dev, evt.ep); + break; + case IT82xx2_EVT_OUT_TOKEN: + err = work_handler_out(evt.dev, evt.ep); + break; + case IT82xx2_EVT_XFER: + break; + default: + LOG_ERR("Unknown event type 0x%x", evt.event); + err = -EINVAL; + break; + } + + if (err) { + udc_submit_event(evt.dev, UDC_EVT_ERROR, err); + } + + if (evt.ep != USB_CONTROL_EP_OUT && !udc_ep_is_busy(evt.dev, evt.ep)) { + if (work_handler_xfer_next(evt.dev, evt.ep) == 0) { + udc_ep_set_busy(evt.dev, evt.ep, true); + } + } + } +} + +static inline bool it82xx2_check_ep0_stall(const struct device *dev, const uint8_t ep_idx, + const uint8_t transtype) +{ + const struct usb_it82xx2_config *config = dev->config; + struct usb_it82xx2_regs *const usb_regs = config->base; + struct it82xx2_usb_ep_regs *ep_regs = usb_regs->usb_ep_regs; + struct it82xx2_usb_ep_fifo_regs *ff_regs = usb_regs->fifo_regs; + + if (ep_idx != 0) { + return false; + } + + /* Check if the stall bit is set */ + if (ep_regs[ep_idx].ep_ctrl.fields.send_stall_bit) { + ep_set_halt(dev, ep_idx, false); + if (transtype == DC_SETUP_TRANS) { + ff_regs[ep_idx].ep_rx_fifo_ctrl = FIFO_FORCE_EMPTY; + } + LOG_ERR("Cleared stall bit"); + return true; + } + + /* Check if the IN transaction is STALL */ + if ((transtype == DC_IN_TRANS) && (ep_regs[ep_idx].ep_status & DC_STALL_SENT)) { + return true; + } + + return false; +} + +static void it82xx2_usb_xfer_done(const struct device *dev) +{ + const struct usb_it82xx2_config *config = dev->config; + struct usb_it82xx2_regs *const usb_regs = config->base; + struct it82xx2_usb_ep_regs *ep_regs = usb_regs->usb_ep_regs; + struct epn_ext_ctrl_regs *epn_ext_ctrl = + usb_regs->fifo_regs[EP_EXT_REGS_DX].ext_0_3.epn_ext_ctrl; + + for (uint8_t fifo_idx = 0; fifo_idx < 4; fifo_idx++) { + uint8_t ep, ep_idx, ep_ctrl, transtype; + + ep_ctrl = ep_regs[fifo_idx].ep_ctrl.value; + transtype = ep_regs[fifo_idx].ep_transtype_sts & DC_ALL_TRANS; + + if (!(ep_ctrl & ENDPOINT_EN) || (ep_ctrl & ENDPOINT_RDY)) { + continue; + } + + if (fifo_idx == 0) { + ep_idx = 0; + if (it82xx2_check_ep0_stall(dev, ep_idx, transtype)) { + continue; + } + } else { + ep_idx = (epn_ext_ctrl[fifo_idx].epn_ext_ctrl2 & COMPLETED_TRANS) >> 4; + if (ep_idx == 0) { + continue; + } + } + + switch (transtype) { + case DC_SETUP_TRANS: + /* SETUP transaction done */ + if (ep_idx != 0) { + break; + } + it82xx2_event_submit(dev, ep_idx, IT82xx2_EVT_SETUP_TOKEN); + break; + case DC_IN_TRANS: + /* IN transaction done */ + ep = USB_EP_DIR_IN | ep_idx; + it82xx2_event_submit(dev, ep, IT82xx2_EVT_IN_TOKEN); + break; + case DC_OUTDATA_TRANS: + /* OUT transaction done */ + ep = USB_EP_DIR_OUT | ep_idx; + it82xx2_event_submit(dev, ep, IT82xx2_EVT_OUT_TOKEN); + break; + default: + LOG_ERR("Unknown transaction type"); + break; + } + } +} + +static void it82xx2_usb_dc_isr(const void *arg) +{ + const struct device *dev = arg; + const struct usb_it82xx2_config *config = dev->config; + struct usb_it82xx2_regs *const usb_regs = config->base; + struct it82xx2_data *priv = udc_get_private(dev); + + uint8_t status = usb_regs->dc_interrupt_status & + usb_regs->dc_interrupt_mask; /* mask non enable int */ + + /* reset event */ + if (status & DC_RESET_EVENT) { + if ((usb_regs->dc_line_status & RX_LINE_STATE_MASK) == RX_LINE_RESET) { + it82xx2_dc_reset(dev); + usb_regs->dc_interrupt_status = DC_RESET_EVENT; + + udc_submit_event(dev, UDC_EVT_RESET, 0); + return; + } + usb_regs->dc_interrupt_status = DC_RESET_EVENT; + } + + /* sof received */ + if (status & DC_SOF_RECEIVED) { + it82xx2_enable_sof_int(dev, false); + k_work_reschedule(&priv->suspended_work, K_MSEC(5)); + } + + /* transaction done */ + if (status & DC_TRANS_DONE) { + /* clear interrupt before new transaction */ + usb_regs->dc_interrupt_status = DC_TRANS_DONE; + if (udc_is_suspended(dev) && udc_is_enabled(dev)) { + udc_set_suspended(dev, false); + udc_submit_event(dev, UDC_EVT_RESUME, 0); + k_sem_give(&priv->suspended_sem); + } + it82xx2_usb_xfer_done(dev); + return; + } +} + +static void suspended_handler(struct k_work *item) +{ + struct k_work_delayable *dwork = k_work_delayable_from_work(item); + struct it82xx2_data *priv = CONTAINER_OF(dwork, struct it82xx2_data, suspended_work); + const struct device *dev = priv->dev; + const struct usb_it82xx2_config *config = dev->config; + struct usb_it82xx2_regs *const usb_regs = config->base; + + if (usb_regs->dc_interrupt_status & DC_SOF_RECEIVED) { + usb_regs->dc_interrupt_status = DC_SOF_RECEIVED; + if (udc_is_suspended(dev) && udc_is_enabled(dev)) { + udc_set_suspended(dev, false); + udc_submit_event(dev, UDC_EVT_RESUME, 0); + k_sem_give(&priv->suspended_sem); + } + k_work_reschedule(&priv->suspended_work, K_MSEC(5)); + return; + } + + it82xx2_enable_sof_int(dev, true); + + if (!udc_is_suspended(dev) && udc_is_enabled(dev)) { + udc_set_suspended(dev, true); + udc_submit_event(dev, UDC_EVT_SUSPEND, 0); + it82xx2_enable_wu_irq(dev, true); + it82xx2_enable_standby_state(true); + + k_sem_reset(&priv->suspended_sem); + } +} + +static int it82xx2_enable(const struct device *dev) +{ + const struct usb_it82xx2_config *config = dev->config; + struct usb_it82xx2_regs *const usb_regs = config->base; + struct it82xx2_data *priv = udc_get_private(dev); + + k_sem_init(&priv->suspended_sem, 0, 1); + k_work_init_delayable(&priv->suspended_work, suspended_handler); + + /* Initialize FIFO ready status */ + priv->fifo_ready[0] = false; + priv->fifo_ready[1] = false; + priv->fifo_ready[2] = false; + + /* Initialize FIFO semaphore */ + k_sem_init(&priv->fifo_sem[0], 1, 1); + k_sem_init(&priv->fifo_sem[1], 1, 1); + k_sem_init(&priv->fifo_sem[2], 1, 1); + + usb_regs->dc_control = DC_GLOBAL_ENABLE | DC_FULL_SPEED_LINE_POLARITY | + DC_FULL_SPEED_LINE_RATE | DC_CONNECT_TO_HOST; + + /* Enable USB D+ and USB interrupts */ + it82xx2_enable_wu_irq(dev, true); + irq_enable(config->usb_irq); + + return 0; +} + +static int it82xx2_disable(const struct device *dev) +{ + const struct usb_it82xx2_config *config = dev->config; + struct usb_it82xx2_regs *const usb_regs = config->base; + + irq_disable(config->usb_irq); + + /* stop pull-up D+ D-*/ + usb_regs->dc_control &= ~DC_CONNECT_TO_HOST; + + return 0; +} + +static int it82xx2_init(const struct device *dev) +{ + const struct usb_it82xx2_config *config = dev->config; + struct gctrl_it8xxx2_regs *const gctrl_regs = GCTRL_IT8XXX2_REGS_BASE; + int ret; + + /* + * Disable USB debug path , prevent CPU enter + * JTAG mode and then reset by USB command. + */ + gctrl_regs->GCTRL_MCCR &= ~(IT8XXX2_GCTRL_MCCR_USB_EN); + gctrl_regs->gctrl_pmer2 |= IT8XXX2_GCTRL_PMER2_USB_PAD_EN; + + it82xx2_usb_dc_ip_init(dev); + + ret = udc_ep_enable_internal(dev, USB_CONTROL_EP_OUT, USB_EP_TYPE_CONTROL, + config->ep_cfg_out[0].caps.mps, 0); + if (ret) { + LOG_ERR("Failed to enable ep 0x%02x", USB_CONTROL_EP_OUT); + return ret; + } + + ret = udc_ep_enable_internal(dev, USB_CONTROL_EP_IN, USB_EP_TYPE_CONTROL, + config->ep_cfg_in[0].caps.mps, 0); + if (ret) { + LOG_ERR("Failed to enable ep 0x%02x", USB_CONTROL_EP_IN); + return ret; + } + return 0; +} + +static int it82xx2_shutdown(const struct device *dev) +{ + 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; + } + + return 0; +} + +static int it82xx2_lock(const struct device *dev) +{ + return udc_lock_internal(dev, K_FOREVER); +} + +static int it82xx2_unlock(const struct device *dev) +{ + return udc_unlock_internal(dev); +} + +static const struct udc_api it82xx2_api = { + .ep_enqueue = it82xx2_ep_enqueue, + .ep_dequeue = it82xx2_ep_dequeue, + .ep_set_halt = it82xx2_ep_set_halt, + .ep_clear_halt = it82xx2_ep_clear_halt, + .ep_try_config = NULL, + .ep_enable = it82xx2_ep_enable, + .ep_disable = it82xx2_ep_disable, + .host_wakeup = it82xx2_host_wakeup, + .set_address = it82xx2_set_address, + .enable = it82xx2_enable, + .disable = it82xx2_disable, + .init = it82xx2_init, + .shutdown = it82xx2_shutdown, + .lock = it82xx2_lock, + .unlock = it82xx2_unlock, +}; + +static int it82xx2_usb_driver_preinit(const struct device *dev) +{ + const struct usb_it82xx2_config *config = dev->config; + struct udc_data *data = dev->data; + struct it82xx2_data *priv = udc_get_private(dev); + int err; + + k_mutex_init(&data->mutex); + k_fifo_init(&priv->fifo); + + err = pinctrl_apply_state(config->pcfg, PINCTRL_STATE_DEFAULT); + if (err < 0) { + LOG_ERR("Failed to configure usb pins"); + return err; + } + + for (int i = 0; i < MAX_NUM_ENDPOINTS; i++) { + config->ep_cfg_out[i].caps.out = 1; + if (i == 0) { + config->ep_cfg_out[i].caps.control = 1; + config->ep_cfg_out[i].caps.mps = USB_CONTROL_EP_MPS; + } else if ((i % 3) == 2) { + 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 = 64; + } + + config->ep_cfg_out[i].addr = USB_EP_DIR_OUT | i; + err = udc_register_ep(dev, &config->ep_cfg_out[i]); + if (err != 0) { + LOG_ERR("Failed to register endpoint"); + return err; + } + } + + for (int i = 0; i < MAX_NUM_ENDPOINTS; i++) { + config->ep_cfg_in[i].caps.in = 1; + if (i == 0) { + config->ep_cfg_in[i].caps.control = 1; + config->ep_cfg_in[i].caps.mps = USB_CONTROL_EP_MPS; + } else if ((i % 3) != 2) { + 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 = 64; + } + + config->ep_cfg_in[i].addr = USB_EP_DIR_IN | i; + err = udc_register_ep(dev, &config->ep_cfg_in[i]); + if (err != 0) { + LOG_ERR("Failed to register endpoint"); + return err; + } + } + + data->caps.rwup = true; + data->caps.mps0 = UDC_MPS0_64; + + priv->dev = dev; + + config->make_thread(dev); + + /* Initializing WU (USB D+) */ + it8xxx2_usb_dc_wuc_init(dev); + + /* Connect USB interrupt */ + irq_connect_dynamic(config->usb_irq, 0, it82xx2_usb_dc_isr, dev, 0); + + return 0; +} + +#define IT82xx2_USB_DEVICE_DEFINE(n) \ + K_KERNEL_STACK_DEFINE(udc_it82xx2_stack_##n, CONFIG_UDC_IT82xx2_STACK_SIZE); \ + \ + static void udc_it82xx2_thread_##n(void *dev, void *arg1, void *arg2) \ + { \ + ARG_UNUSED(arg1); \ + ARG_UNUSED(arg2); \ + xfer_work_handler(dev); \ + } \ + \ + static void udc_it82xx2_make_thread_##n(const struct device *dev) \ + { \ + struct it82xx2_data *priv = udc_get_private(dev); \ + \ + k_thread_create(&priv->thread_data, udc_it82xx2_stack_##n, \ + K_THREAD_STACK_SIZEOF(udc_it82xx2_stack_##n), \ + udc_it82xx2_thread_##n, (void *)dev, NULL, NULL, K_PRIO_COOP(8), \ + 0, K_NO_WAIT); \ + k_thread_name_set(&priv->thread_data, dev->name); \ + } \ + \ + PINCTRL_DT_INST_DEFINE(n); \ + \ + static struct udc_ep_config ep_cfg_out[MAX_NUM_ENDPOINTS]; \ + static struct udc_ep_config ep_cfg_in[MAX_NUM_ENDPOINTS]; \ + \ + static struct usb_it82xx2_config udc_cfg_##n = { \ + .base = (struct usb_it82xx2_regs *)DT_INST_REG_ADDR(n), \ + .pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n), \ + .wuc = {.dev = IT8XXX2_DEV_WUC(0, n), .mask = IT8XXX2_DEV_WUC_MASK(0, n)}, \ + .usb_irq = DT_INST_IRQ_BY_IDX(n, 0, irq), \ + .wu_irq = DT_INST_IRQ_BY_IDX(n, 1, irq), \ + .ep_cfg_in = ep_cfg_out, \ + .ep_cfg_out = ep_cfg_in, \ + .make_thread = udc_it82xx2_make_thread_##n, \ + }; \ + \ + static struct it82xx2_data priv_data_##n = {}; \ + \ + static struct udc_data udc_data_##n = { \ + .mutex = Z_MUTEX_INITIALIZER(udc_data_##n.mutex), \ + .priv = &priv_data_##n, \ + }; \ + \ + DEVICE_DT_INST_DEFINE(n, it82xx2_usb_driver_preinit, NULL, &udc_data_##n, &udc_cfg_##n, \ + POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEVICE, &it82xx2_api); + +DT_INST_FOREACH_STATUS_OKAY(IT82xx2_USB_DEVICE_DEFINE) From 197a4b2f5fb20325a633d0f2b09a66869ac96a63 Mon Sep 17 00:00:00 2001 From: Marcin Niestroj Date: Thu, 23 May 2024 14:49:08 +0200 Subject: [PATCH 1350/2849] samples: net: http_get: fix typo in sections names in sample.yaml Just do: s/sample.get/sample.net/. Signed-off-by: Marcin Niestroj --- samples/net/sockets/http_get/sample.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/samples/net/sockets/http_get/sample.yaml b/samples/net/sockets/http_get/sample.yaml index 7d6ab6951a080..94f7cd6f8ddd9 100644 --- a/samples/net/sockets/http_get/sample.yaml +++ b/samples/net/sockets/http_get/sample.yaml @@ -30,7 +30,7 @@ tests: - socket - offload - simplelink - sample.get.sockets.http_get.nsos.http: + sample.net.sockets.http_get.nsos.http: harness: console harness_config: type: multi_line @@ -43,7 +43,7 @@ tests: - native_sim - native_sim/native/64 extra_args: OVERLAY_CONFIG="overlay-nsos.conf" - sample.get.sockets.http_get.nsos.https: + sample.net.sockets.http_get.nsos.https: harness: console harness_config: type: multi_line From 180c22a4fcbae1d2f640200d3a11bb36e132998a Mon Sep 17 00:00:00 2001 From: Ajay Parida Date: Tue, 28 May 2024 14:52:15 +0530 Subject: [PATCH 1351/2849] net: wifi: shell: Support to print name Support to print name of the argument along with the value. Signed-off-by: Ajay Parida --- subsys/net/l2/wifi/wifi_shell.c | 47 +++++++++++++++++++-------------- 1 file changed, 27 insertions(+), 20 deletions(-) diff --git a/subsys/net/l2/wifi/wifi_shell.c b/subsys/net/l2/wifi/wifi_shell.c index ab2637a1271a3..7bdd98016501a 100644 --- a/subsys/net/l2/wifi/wifi_shell.c +++ b/subsys/net/l2/wifi/wifi_shell.c @@ -75,7 +75,8 @@ struct wifi_ap_sta_node { }; static struct wifi_ap_sta_node sta_list[CONFIG_WIFI_SHELL_MAX_AP_STA]; -static bool parse_number(const struct shell *sh, long *param, char *str, long min, long max) +static bool parse_number(const struct shell *sh, long *param, char *str, + char *pname, long min, long max) { char *endptr; char *str_tmp = str; @@ -94,7 +95,13 @@ static bool parse_number(const struct shell *sh, long *param, char *str, long mi } if ((num) < (min) || (num) > (max)) { - PR_WARNING("Value out of range: %s, (%ld-%ld)", str_tmp, min, max); + if (pname) { + PR_WARNING("%s value out of range: %s, (%ld-%ld)", + pname, str_tmp, min, max); + } else { + PR_WARNING("Value out of range: %s, (%ld-%ld)", + str_tmp, min, max); + } return false; } *param = num; @@ -1067,12 +1074,12 @@ static int cmd_wifi_twt_setup_quick(const struct shell *sh, size_t argc, params.setup.trigger = 0; params.setup.announce = 0; - if (!parse_number(sh, &value, argv[idx++], 1, WIFI_MAX_TWT_WAKE_INTERVAL_US)) { + if (!parse_number(sh, &value, argv[idx++], NULL, 1, WIFI_MAX_TWT_WAKE_INTERVAL_US)) { return -EINVAL; } params.setup.twt_wake_interval = (uint32_t)value; - if (!parse_number(sh, &value, argv[idx++], 1, WIFI_MAX_TWT_INTERVAL_US)) { + if (!parse_number(sh, &value, argv[idx++], NULL, 1, WIFI_MAX_TWT_INTERVAL_US)) { return -EINVAL; } params.setup.twt_interval = (uint64_t)value; @@ -1105,59 +1112,59 @@ static int cmd_wifi_twt_setup(const struct shell *sh, size_t argc, params.operation = WIFI_TWT_SETUP; - if (!parse_number(sh, &value, argv[idx++], WIFI_TWT_INDIVIDUAL, + if (!parse_number(sh, &value, argv[idx++], NULL, WIFI_TWT_INDIVIDUAL, WIFI_TWT_WAKE_TBTT)) { return -EINVAL; } params.negotiation_type = (enum wifi_twt_negotiation_type)value; - if (!parse_number(sh, &value, argv[idx++], WIFI_TWT_SETUP_CMD_REQUEST, + if (!parse_number(sh, &value, argv[idx++], NULL, WIFI_TWT_SETUP_CMD_REQUEST, WIFI_TWT_SETUP_CMD_DEMAND)) { return -EINVAL; } params.setup_cmd = (enum wifi_twt_setup_cmd)value; - if (!parse_number(sh, &value, argv[idx++], 1, 255)) { + if (!parse_number(sh, &value, argv[idx++], NULL, 1, 255)) { return -EINVAL; } params.dialog_token = (uint8_t)value; - if (!parse_number(sh, &value, argv[idx++], 0, (WIFI_MAX_TWT_FLOWS - 1))) { + if (!parse_number(sh, &value, argv[idx++], NULL, 0, (WIFI_MAX_TWT_FLOWS - 1))) { return -EINVAL; } params.flow_id = (uint8_t)value; - if (!parse_number(sh, &value, argv[idx++], 0, 1)) { + if (!parse_number(sh, &value, argv[idx++], NULL, 0, 1)) { return -EINVAL; } params.setup.responder = (bool)value; - if (!parse_number(sh, &value, argv[idx++], 0, 1)) { + if (!parse_number(sh, &value, argv[idx++], NULL, 0, 1)) { return -EINVAL; } params.setup.trigger = (bool)value; - if (!parse_number(sh, &value, argv[idx++], 0, 1)) { + if (!parse_number(sh, &value, argv[idx++], NULL, 0, 1)) { return -EINVAL; } params.setup.implicit = (bool)value; - if (!parse_number(sh, &value, argv[idx++], 0, 1)) { + if (!parse_number(sh, &value, argv[idx++], NULL, 0, 1)) { return -EINVAL; } params.setup.announce = (bool)value; - if (!parse_number(sh, &value, argv[idx++], 1, WIFI_MAX_TWT_WAKE_INTERVAL_US)) { + if (!parse_number(sh, &value, argv[idx++], NULL, 1, WIFI_MAX_TWT_WAKE_INTERVAL_US)) { return -EINVAL; } params.setup.twt_wake_interval = (uint32_t)value; - if (!parse_number(sh, &value, argv[idx++], 1, WIFI_MAX_TWT_INTERVAL_US)) { + if (!parse_number(sh, &value, argv[idx++], NULL, 1, WIFI_MAX_TWT_INTERVAL_US)) { return -EINVAL; } params.setup.twt_interval = (uint64_t)value; - if (!parse_number(sh, &value, argv[idx++], 0, WIFI_MAX_TWT_WAKE_AHEAD_DURATION_US)) { + if (!parse_number(sh, &value, argv[idx++], NULL, 0, WIFI_MAX_TWT_WAKE_AHEAD_DURATION_US)) { return -EINVAL; } params.setup.twt_wake_ahead_duration = (uint32_t)value; @@ -1190,24 +1197,24 @@ static int cmd_wifi_twt_teardown(const struct shell *sh, size_t argc, params.operation = WIFI_TWT_TEARDOWN; - if (!parse_number(sh, &value, argv[idx++], WIFI_TWT_INDIVIDUAL, + if (!parse_number(sh, &value, argv[idx++], NULL, WIFI_TWT_INDIVIDUAL, WIFI_TWT_WAKE_TBTT)) { return -EINVAL; } params.negotiation_type = (enum wifi_twt_negotiation_type)value; - if (!parse_number(sh, &value, argv[idx++], WIFI_TWT_SETUP_CMD_REQUEST, + if (!parse_number(sh, &value, argv[idx++], NULL, WIFI_TWT_SETUP_CMD_REQUEST, WIFI_TWT_SETUP_CMD_DEMAND)) { return -EINVAL; } params.setup_cmd = (enum wifi_twt_setup_cmd)value; - if (!parse_number(sh, &value, argv[idx++], 1, 255)) { + if (!parse_number(sh, &value, argv[idx++], NULL, 1, 255)) { return -EINVAL; } params.dialog_token = (uint8_t)value; - if (!parse_number(sh, &value, argv[idx++], 0, (WIFI_MAX_TWT_FLOWS - 1))) { + if (!parse_number(sh, &value, argv[idx++], NULL, 0, (WIFI_MAX_TWT_FLOWS - 1))) { return -EINVAL; } params.flow_id = (uint8_t)value; @@ -1441,7 +1448,7 @@ static int cmd_wifi_listen_interval(const struct shell *sh, size_t argc, char *a context.sh = sh; - if (!parse_number(sh, &interval, argv[1], + if (!parse_number(sh, &interval, argv[1], NULL, WIFI_LISTEN_INTERVAL_MIN, WIFI_LISTEN_INTERVAL_MAX)) { return -EINVAL; From c6d1a91372082028b3e153a1246fde6f113eda80 Mon Sep 17 00:00:00 2001 From: Ajay Parida Date: Wed, 8 May 2024 12:50:48 +0530 Subject: [PATCH 1352/2849] net: wifi_mgmt: Support to configure AP mode parameter Support to set BSS parameter at compile and run time. Added support to configure `max_inactivity` BSS parameter. Station inactivity timeout is the period for which AP may keep a client in associated state while there is no traffic from that particular client. If a non-zero value is set, AP may choose to disassociate the client after the timeout. Signed-off-by: Ajay Parida --- include/zephyr/net/wifi.h | 6 +++ include/zephyr/net/wifi_mgmt.h | 30 ++++++++++++++- subsys/net/l2/wifi/Kconfig | 9 +++++ subsys/net/l2/wifi/wifi_mgmt.c | 25 +++++++++++++ subsys/net/l2/wifi/wifi_shell.c | 65 +++++++++++++++++++++++++++++++++ 5 files changed, 133 insertions(+), 2 deletions(-) diff --git a/include/zephyr/net/wifi.h b/include/zephyr/net/wifi.h index 5f47209b83fc6..ab00980a69cce 100644 --- a/include/zephyr/net/wifi.h +++ b/include/zephyr/net/wifi.h @@ -494,6 +494,12 @@ static inline const char *wifi_ps_get_config_err_code_str(int16_t err_no) return ""; } +/** @brief Wi-Fi AP mode configuration parameter */ +enum wifi_ap_config_param { + /** Used for AP mode configuration parameter ap_max_inactivity */ + WIFI_AP_CONFIG_PARAM_MAX_INACTIVITY = BIT(0), +}; + #ifdef __cplusplus } #endif diff --git a/include/zephyr/net/wifi_mgmt.h b/include/zephyr/net/wifi_mgmt.h index 8c2b61fa93640..910ee030651f0 100644 --- a/include/zephyr/net/wifi_mgmt.h +++ b/include/zephyr/net/wifi_mgmt.h @@ -88,7 +88,8 @@ enum net_request_wifi_cmd { NET_REQUEST_WIFI_CMD_VERSION, /** Set RTS threshold */ NET_REQUEST_WIFI_CMD_RTS_THRESHOLD, - + /** Configure AP parameter */ + NET_REQUEST_WIFI_CMD_AP_CONFIG_PARAM, /** @cond INTERNAL_HIDDEN */ NET_REQUEST_WIFI_CMD_MAX /** @endcond */ @@ -190,6 +191,12 @@ NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_WIFI_VERSION); NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_WIFI_RTS_THRESHOLD); +/** Request a Wi-Fi AP parameters configuration */ +#define NET_REQUEST_WIFI_AP_CONFIG_PARAM \ + (_NET_WIFI_BASE | NET_REQUEST_WIFI_CMD_AP_CONFIG_PARAM) + +NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_WIFI_AP_CONFIG_PARAM); + /** @brief Wi-Fi management events */ enum net_event_wifi_cmd { /** Scan results available */ @@ -746,6 +753,18 @@ struct wifi_channel_info { enum wifi_mgmt_op oper; }; +/** @cond INTERNAL_HIDDEN */ +#define WIFI_AP_STA_MAX_INACTIVITY (LONG_MAX - 1) +/** @endcond */ + +/** @brief Wi-Fi AP configuration parameter */ +struct wifi_ap_config_params { + /** Parameter used to identify the different AP parameters */ + enum wifi_ap_config_param type; + /** Parameter used for setting maximum inactivity duration for stations */ + uint32_t max_inactivity; +}; + #include /** Scan result callback @@ -919,7 +938,14 @@ struct wifi_mgmt_ops { * @return 0 if ok, < 0 if error */ int (*set_rts_threshold)(const struct device *dev, unsigned int rts_threshold); - + /** Configure AP parameter + * + * @param dev Pointer to the device structure for the driver instance. + * @param params AP mode parameter configuration parameter info + * + * @return 0 if ok, < 0 if error + */ + int (*ap_config_params)(const struct device *dev, struct wifi_ap_config_params *params); }; /** Wi-Fi management offload API */ diff --git a/subsys/net/l2/wifi/Kconfig b/subsys/net/l2/wifi/Kconfig index 2816be56d746d..0ad0858fab21a 100644 --- a/subsys/net/l2/wifi/Kconfig +++ b/subsys/net/l2/wifi/Kconfig @@ -93,3 +93,12 @@ module-str = Log level for Wi-Fi Network manager module module-help = Enables using the Wi-Fi Network managers to manage the Wi-Fi network interfaces. source "subsys/net/Kconfig.template.log_config.net" endif # WIFI_NM + +config WIFI_MGMT_AP_STA_INACTIVITY_TIMEOUT + int "Station inactivity timeout in seconds" + default 300 + help + Station inactivity timeout is the period for which AP may keep a client + in associated state while there is no traffic from that particular + client. If a non-zero value is set, AP may choose to disassociate the + client after the timeout. diff --git a/subsys/net/l2/wifi/wifi_mgmt.c b/subsys/net/l2/wifi/wifi_mgmt.c index 51e76aec5fbe2..b6f4a6cd2c6fa 100644 --- a/subsys/net/l2/wifi/wifi_mgmt.c +++ b/subsys/net/l2/wifi/wifi_mgmt.c @@ -435,6 +435,31 @@ static int wifi_ap_sta_disconnect(uint32_t mgmt_request, struct net_if *iface, NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_WIFI_AP_STA_DISCONNECT, wifi_ap_sta_disconnect); +static int wifi_ap_config_params(uint32_t mgmt_request, struct net_if *iface, + void *data, size_t len) +{ + const struct device *dev = net_if_get_device(iface); + const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_api(iface); + struct wifi_ap_config_params *params = data; + + if (dev == NULL) { + return -ENODEV; + } + + if (wifi_mgmt_api == NULL || + wifi_mgmt_api->ap_config_params == NULL) { + return -ENOTSUP; + } + + if (!data || len != sizeof(*params)) { + return -EINVAL; + } + + return wifi_mgmt_api->ap_config_params(dev, params); +} + +NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_WIFI_AP_CONFIG_PARAM, wifi_ap_config_params); + static int wifi_iface_status(uint32_t mgmt_request, struct net_if *iface, void *data, size_t len) { diff --git a/subsys/net/l2/wifi/wifi_shell.c b/subsys/net/l2/wifi/wifi_shell.c index 7bdd98016501a..87930f7cbafed 100644 --- a/subsys/net/l2/wifi/wifi_shell.c +++ b/subsys/net/l2/wifi/wifi_shell.c @@ -1370,6 +1370,65 @@ static int cmd_wifi_ap_sta_disconnect(const struct shell *sh, size_t argc, return 0; } +static int wifi_ap_config_args_to_params(const struct shell *sh, size_t argc, char *argv[], + struct wifi_ap_config_params *params) +{ + struct getopt_state *state; + int opt; + static struct option long_options[] = {{"max_inactivity", required_argument, 0, 'i'}, + {"help", no_argument, 0, 'h'}, + {0, 0, 0, 0}}; + int opt_index = 0; + long val; + + while ((opt = getopt_long(argc, argv, "i:h", long_options, &opt_index)) != -1) { + state = getopt_state_get(); + switch (opt) { + case 'i': + if (!parse_number(sh, &val, optarg, "max_inactivity", + 0, WIFI_AP_STA_MAX_INACTIVITY)) { + return -EINVAL; + } + params->max_inactivity = (uint32_t)val; + params->type |= WIFI_AP_CONFIG_PARAM_MAX_INACTIVITY; + break; + case 'h': + shell_help(sh); + return SHELL_CMD_HELP_PRINTED; + default: + PR_ERROR("Invalid option %c\n", optopt); + shell_help(sh); + return SHELL_CMD_HELP_PRINTED; + } + } + + return 0; +} + +static int cmd_wifi_ap_config_params(const struct shell *sh, size_t argc, + char *argv[]) +{ + struct net_if *iface = net_if_get_first_wifi(); + struct wifi_ap_config_params ap_config_params = { 0 }; + int ret = -1; + + context.sh = sh; + + if (wifi_ap_config_args_to_params(sh, argc, argv, &ap_config_params)) { + return -ENOEXEC; + } + + ret = net_mgmt(NET_REQUEST_WIFI_AP_CONFIG_PARAM, iface, + &ap_config_params, sizeof(struct wifi_ap_config_params)); + if (ret) { + PR_WARNING("Setting AP parameter failed: %s\n", + strerror(-ret)); + return -ENOEXEC; + } + + return 0; +} + static int cmd_wifi_reg_domain(const struct shell *sh, size_t argc, char *argv[]) { @@ -1893,6 +1952,12 @@ SHELL_STATIC_SUBCMD_SET_CREATE(wifi_cmd_ap, "\n", cmd_wifi_ap_sta_disconnect, 2, 0), + SHELL_CMD_ARG(config, NULL, + "Configure AP parameters.\n" + "-i --max_inactivity=

uart:~$ gatt exchange-mtu - uart:~$ bap discover sink - uart:~$ bap connect sink 0 + uart:~$ bap discover source + uart:~$ bap config source 0 + uart:~$ bap qos + uart:~$ bap enable + uart:~$ bap connect + uart:~$ bap start Disconnect and release: @@ -479,8 +483,7 @@ parameters. Enable ****** -The :code:`enable` command attempts to enable the stream previously configured, -if the remote peer accepts then the ISO connection procedure is also initiated. +The :code:`enable` command attempts to enable the stream previously configured. .. csv-table:: State Machine Transitions :header: "Depends", "Allowed States", "Next States" @@ -493,17 +496,33 @@ if the remote peer accepts then the ISO connection procedure is also initiated. uart:~$ bap enable [context] uart:~$ bap enable Media +Connect +******* + +The :code:`connect` command attempts to connect the stream previously configured. +Sink streams will have to be started by the unicast server, and source streams will have to be +started by the unicast client. + +.. csv-table:: State Machine Transitions + :header: "Depends", "Allowed States", "Next States" + :widths: auto + + "qos/enable","qos-configured/enabling","qos-configured/enabling" + +.. code-block:: console + + uart:~$ bap connect + Start ***** -The :code:`start` command is only necessary when acting as a sink as it -indicates to the source the stack is ready to start receiving data. +The :code:`start` command is only necessary when starting a source stream. .. csv-table:: State Machine Transitions :header: "Depends", "Allowed States", "Next States" :widths: auto - "enable","enabling","streaming" + "enable/connect","enabling","streaming" .. code-block:: console diff --git a/doc/releases/migration-guide-3.7.rst b/doc/releases/migration-guide-3.7.rst index 6c170c300ce8b..0fa08a6af9db0 100644 --- a/doc/releases/migration-guide-3.7.rst +++ b/doc/releases/migration-guide-3.7.rst @@ -447,6 +447,10 @@ Bluetooth Audio This needs to be added to all instances of CAP discovery callback functions defined. (:github:`72797`) +* :c:func:`bt_bap_stream_start` no longer connects the CIS. To connect the CIS, + the :c:func:`bt_bap_stream_connect` shall now be called before :c:func:`bt_bap_stream_start`. + (:github:`73032`) + * All occurrences of ``set_sirk`` have been changed to just ``sirk`` as the ``s`` in ``sirk`` stands for set. (:github:`73413`) diff --git a/include/zephyr/bluetooth/audio/bap.h b/include/zephyr/bluetooth/audio/bap.h index 4e67d59487785..32d9840c5be5b 100644 --- a/include/zephyr/bluetooth/audio/bap.h +++ b/include/zephyr/bluetooth/audio/bap.h @@ -2,7 +2,7 @@ * @brief Header for Bluetooth BAP. * * Copyright (c) 2020 Bose Corporation - * Copyright (c) 2021-2023 Nordic Semiconductor ASA + * Copyright (c) 2021-2024 Nordic Semiconductor ASA * * SPDX-License-Identifier: Apache-2.0 */ @@ -715,20 +715,43 @@ int bt_bap_stream_metadata(struct bt_bap_stream *stream, const uint8_t meta[], s */ int bt_bap_stream_disable(struct bt_bap_stream *stream); +/** + * @brief Connect unicast audio stream + * + * This procedure is used by a unicast client to connect the connected isochronous stream (CIS) + * associated with the audio stream. If two audio streams share a CIS, then this only needs to be + * done once for those streams. This can only be done for streams in the QoS configured or enabled + * states. + * + * The bt_bap_stream_ops.connected() callback will be called on the streams once this has finished. + * + * This shall only be called for unicast streams, and only as the unicast client + * (@kconfig{CONFIG_BT_BAP_UNICAST_CLIENT}). + * + * @param stream Stream object + * + * @retval 0 in case of success + * @retval -EINVAL if the stream, endpoint, ISO channel or connection is NULL + * @retval -EBADMSG if the stream or ISO channel is in an invalid state for connection + * @retval -EOPNOTSUPP if the role of the stream is not @ref BT_HCI_ROLE_CENTRAL + * @retval -EALREADY if the ISO channel is already connecting or connected + * @retval -EBUSY if another ISO channel is connecting + * @retval -ENOEXEC if otherwise rejected by the ISO layer + */ +int bt_bap_stream_connect(struct bt_bap_stream *stream); + /** * @brief Start Audio Stream * * This procedure is used by a unicast client or unicast server to make a stream start streaming. * - * For the unicast client, this will connect the CIS for the stream before - * sending the start command. + * For the unicast client, this will send the receiver start ready command to the unicast server for + * @ref BT_AUDIO_DIR_SOURCE ASEs. The CIS is required to be connected first by + * bt_bap_stream_connect() before the command can be sent. * - * For the unicast server, this will put a @ref BT_AUDIO_DIR_SINK stream into the streaming state if - * the CIS is connected (initialized by the unicast client). If the CIS is not connected yet, the - * stream will go into the streaming state as soon as the CIS is connected. - * @ref BT_AUDIO_DIR_SOURCE streams will go into the streaming state when the unicast client sends - * the Receiver Start Ready operation, which will trigger the @ref bt_bap_unicast_server_cb.start() - * callback. + * For the unicast server, this will execute the receiver start ready command on the unicast server + * for @ref BT_AUDIO_DIR_SINK ASEs. If the CIS is not connected yet, the stream will go into the + * streaming state as soon as the CIS is connected. * * This shall only be called for unicast streams. * diff --git a/samples/bluetooth/bap_unicast_client/src/main.c b/samples/bluetooth/bap_unicast_client/src/main.c index 170808db24a9b..96b36094b6ccd 100644 --- a/samples/bluetooth/bap_unicast_client/src/main.c +++ b/samples/bluetooth/bap_unicast_client/src/main.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2023 Nordic Semiconductor ASA + * Copyright (c) 2021-2024 Nordic Semiconductor ASA * * SPDX-License-Identifier: Apache-2.0 */ @@ -59,6 +59,7 @@ static K_SEM_DEFINE(sem_stream_configured, 0, 1); static K_SEM_DEFINE(sem_stream_qos, 0, ARRAY_SIZE(sinks) + ARRAY_SIZE(sources)); static K_SEM_DEFINE(sem_stream_enabled, 0, 1); static K_SEM_DEFINE(sem_stream_started, 0, 1); +static K_SEM_DEFINE(sem_stream_connected, 0, 1); #define AUDIO_DATA_TIMEOUT_US 1000000UL /* Send data every 1 second */ @@ -518,9 +519,9 @@ static void stream_enabled(struct bt_bap_stream *stream) k_sem_give(&sem_stream_enabled); } -static void stream_started(struct bt_bap_stream *stream) +static void stream_connected_cb(struct bt_bap_stream *stream) { - printk("Audio Stream %p started\n", stream); + printk("Audio Stream %p connected\n", stream); /* Reset sequence number for sinks */ for (size_t i = 0U; i < configured_sink_stream_count; i++) { @@ -530,6 +531,13 @@ static void stream_started(struct bt_bap_stream *stream) } } + k_sem_give(&sem_stream_connected); +} + +static void stream_started(struct bt_bap_stream *stream) +{ + printk("Audio Stream %p started\n", stream); + k_sem_give(&sem_stream_started); } @@ -576,7 +584,8 @@ static struct bt_bap_stream_ops stream_ops = { .disabled = stream_disabled, .stopped = stream_stopped, .released = stream_released, - .recv = stream_recv + .recv = stream_recv, + .connected = stream_connected_cb, }; static void add_remote_source(struct bt_bap_ep *ep) @@ -1018,17 +1027,62 @@ static int enable_streams(void) return 0; } -static int start_streams(void) +static int connect_streams(void) { for (size_t i = 0U; i < configured_stream_count; i++) { int err; - err = bt_bap_stream_start(&streams[i]); - if (err != 0) { + k_sem_reset(&sem_stream_connected); + + err = bt_bap_stream_connect(&streams[i]); + if (err == -EALREADY) { + /* We have already connected a paired stream */ + continue; + } else if (err != 0) { printk("Unable to start stream: %d\n", err); return err; } + err = k_sem_take(&sem_stream_connected, K_FOREVER); + if (err != 0) { + printk("failed to take sem_stream_connected (err %d)\n", err); + return err; + } + } + + return 0; +} + +static enum bt_audio_dir stream_dir(const struct bt_bap_stream *stream) +{ + struct bt_bap_ep_info ep_info; + int err; + + err = bt_bap_ep_get_info(stream->ep, &ep_info); + if (err != 0) { + printk("Failed to get ep info for %p: %d\n", stream, err); + __ASSERT_NO_MSG(false); + + return 0; + } + + return ep_info.dir; +} + +static int start_streams(void) +{ + for (size_t i = 0U; i < configured_stream_count; i++) { + struct bt_bap_stream *stream = &streams[i]; + int err; + + if (stream_dir(stream) == BT_AUDIO_DIR_SOURCE) { + err = bt_bap_stream_start(&streams[i]); + if (err != 0) { + printk("Unable to start stream: %d\n", err); + return err; + } + } /* Sink streams are started by the unicast server */ + err = k_sem_take(&sem_stream_started, K_FOREVER); if (err != 0) { printk("failed to take sem_stream_started (err %d)\n", err); @@ -1051,6 +1105,7 @@ static void reset_data(void) k_sem_reset(&sem_stream_qos); k_sem_reset(&sem_stream_enabled); k_sem_reset(&sem_stream_started); + k_sem_reset(&sem_stream_connected); configured_sink_stream_count = 0; configured_source_stream_count = 0; @@ -1131,6 +1186,13 @@ int main(void) } printk("Streams enabled\n"); + printk("Connecting streams\n"); + err = connect_streams(); + if (err != 0) { + return 0; + } + printk("Streams connected\n"); + printk("Starting streams\n"); err = start_streams(); if (err != 0) { diff --git a/samples/bluetooth/tmap_peripheral/src/bap_unicast_sr.c b/samples/bluetooth/tmap_peripheral/src/bap_unicast_sr.c index 523b3e1d82aee..5e3ce9566f167 100644 --- a/samples/bluetooth/tmap_peripheral/src/bap_unicast_sr.c +++ b/samples/bluetooth/tmap_peripheral/src/bap_unicast_sr.c @@ -1,7 +1,7 @@ /** @file * @brief Bluetooth Basic Audio Profile (BAP) Unicast Server role. * - * Copyright (c) 2021-2023 Nordic Semiconductor ASA + * Copyright (c) 2021-2024 Nordic Semiconductor ASA * Copyright (c) 2022 Codecoup * Copyright (c) 2023 NXP * @@ -293,10 +293,23 @@ static void stream_recv(struct bt_bap_stream *stream, const struct bt_iso_recv_i static void stream_enabled(struct bt_bap_stream *stream) { - const int err = bt_bap_stream_start(stream); + struct bt_bap_ep_info ep_info; + int err; + err = bt_bap_ep_get_info(stream->ep, &ep_info); if (err != 0) { - printk("Failed to start stream %p: %d", stream, err); + printk("Failed to get ep info: %d\n", err); + return; + } + + /* The unicast server is responsible for starting the sink streams */ + if (ep_info.dir == BT_AUDIO_DIR_SINK) { + /* Automatically do the receiver start ready operation */ + err = bt_bap_stream_start(stream); + + if (err != 0) { + printk("Failed to start stream %p: %d", stream, err); + } } } diff --git a/subsys/bluetooth/audio/bap_stream.c b/subsys/bluetooth/audio/bap_stream.c index 6ac3fd8c5f527..0894af516a1b3 100644 --- a/subsys/bluetooth/audio/bap_stream.c +++ b/subsys/bluetooth/audio/bap_stream.c @@ -2,7 +2,7 @@ /* * Copyright (c) 2020 Intel Corporation - * Copyright (c) 2021-2023 Nordic Semiconductor ASA + * Copyright (c) 2021-2024 Nordic Semiconductor ASA * * SPDX-License-Identifier: Apache-2.0 */ @@ -476,6 +476,8 @@ int bt_bap_stream_disconnect(struct bt_bap_stream *stream) iso_chan = bt_bap_stream_iso_chan_get(stream); if (iso_chan == NULL || iso_chan->iso == NULL) { + LOG_DBG("Not connected"); + return -ENOTCONN; } @@ -720,6 +722,40 @@ int bt_bap_stream_reconfig(struct bt_bap_stream *stream, return 0; } +#if defined(CONFIG_BT_BAP_UNICAST_CLIENT) +int bt_bap_stream_connect(struct bt_bap_stream *stream) +{ + uint8_t state; + + LOG_DBG("stream %p ep %p", stream, stream == NULL ? NULL : stream->ep); + + CHECKIF(stream == NULL || stream->ep == NULL || stream->conn == NULL) { + LOG_DBG("Invalid stream"); + return -EINVAL; + } + + /* Valid only after the CIS ID has been assigned in QoS configured state and while we are + * not streaming + */ + state = stream->ep->status.state; + switch (state) { + case BT_BAP_EP_STATE_QOS_CONFIGURED: + case BT_BAP_EP_STATE_ENABLING: + break; + default: + LOG_ERR("Invalid state: %s", bt_bap_ep_state_str(state)); + return -EBADMSG; + } + + /* Only a unicast client can connect a stream */ + if (conn_get_role(stream->conn) == BT_HCI_ROLE_CENTRAL) { + return bt_bap_unicast_client_connect(stream); + } else { + return -EOPNOTSUPP; + } +} +#endif /* CONFIG_BT_BAP_UNICAST_CLIENT */ + int bt_bap_stream_start(struct bt_bap_stream *stream) { uint8_t state; diff --git a/subsys/bluetooth/audio/bap_unicast_client.c b/subsys/bluetooth/audio/bap_unicast_client.c index b6c579d423b59..3de389618f4fe 100644 --- a/subsys/bluetooth/audio/bap_unicast_client.c +++ b/subsys/bluetooth/audio/bap_unicast_client.c @@ -324,17 +324,6 @@ static void unicast_client_ep_iso_connected(struct bt_bap_ep *ep) if (stream_ops != NULL && stream_ops->connected != NULL) { stream_ops->connected(stream); } - - if (ep->receiver_ready && ep->dir == BT_AUDIO_DIR_SOURCE) { - const int err = unicast_client_send_start(ep); - - if (err != 0) { - LOG_DBG("Failed to send start: %d", err); - - /* TBD: Should we release the stream then? */ - ep->receiver_ready = false; - } - } } static void unicast_client_iso_connected(struct bt_iso_chan *chan) @@ -577,6 +566,8 @@ static void unicast_client_ep_idle_state(struct bt_bap_ep *ep) struct bt_bap_stream *stream = ep->stream; const struct bt_bap_stream_ops *ops; + ep->receiver_ready = false; + if (stream == NULL) { return; } @@ -662,6 +653,8 @@ static void unicast_client_ep_config_state(struct bt_bap_ep *ep, struct net_buf_ struct bt_bap_stream *stream; void *cc; + ep->receiver_ready = false; + if (client_ep->release_requested) { LOG_DBG("Released was requested, change local state to idle"); ep->reason = BT_HCI_ERR_LOCALHOST_TERM_CONN; @@ -736,6 +729,8 @@ static void unicast_client_ep_qos_state(struct bt_bap_ep *ep, struct net_buf_sim struct bt_ascs_ase_status_qos *qos; struct bt_bap_stream *stream; + ep->receiver_ready = false; + if (buf->len < sizeof(*qos)) { LOG_ERR("QoS status too short"); return; @@ -920,6 +915,8 @@ static void unicast_client_ep_disabling_state(struct bt_bap_ep *ep, struct net_b struct bt_ascs_ase_status_disable *disable; struct bt_bap_stream *stream; + ep->receiver_ready = false; + if (buf->len < sizeof(*disable)) { LOG_ERR("Disabling status too short"); return; @@ -947,6 +944,8 @@ static void unicast_client_ep_releasing_state(struct bt_bap_ep *ep, struct net_b { struct bt_bap_stream *stream; + ep->receiver_ready = false; + stream = ep->stream; if (stream == NULL) { LOG_ERR("No stream active for endpoint"); @@ -1020,7 +1019,6 @@ static void unicast_client_ep_set_status(struct bt_bap_ep *ep, struct net_buf_si switch (status->state) { case BT_BAP_EP_STATE_IDLE: - ep->receiver_ready = false; unicast_client_ep_idle_state(ep); break; case BT_BAP_EP_STATE_CODEC_CONFIGURED: @@ -1041,8 +1039,6 @@ static void unicast_client_ep_set_status(struct bt_bap_ep *ep, struct net_buf_si return; } - ep->receiver_ready = false; - unicast_client_ep_config_state(ep, buf); break; case BT_BAP_EP_STATE_QOS_CONFIGURED: @@ -1083,8 +1079,6 @@ static void unicast_client_ep_set_status(struct bt_bap_ep *ep, struct net_buf_si } } - ep->receiver_ready = false; - unicast_client_ep_qos_state(ep, buf, old_state); break; case BT_BAP_EP_STATE_ENABLING: @@ -1141,8 +1135,6 @@ static void unicast_client_ep_set_status(struct bt_bap_ep *ep, struct net_buf_si return; } - ep->receiver_ready = false; - unicast_client_ep_disabling_state(ep, buf); break; case BT_BAP_EP_STATE_RELEASING: @@ -1170,8 +1162,6 @@ static void unicast_client_ep_set_status(struct bt_bap_ep *ep, struct net_buf_si return; } - ep->receiver_ready = false; - unicast_client_ep_releasing_state(ep, buf); break; } @@ -2251,34 +2241,6 @@ static int unicast_client_cig_terminate(struct bt_bap_unicast_group *group) return bt_iso_cig_terminate(group->cig); } -static int unicast_client_stream_connect(struct bt_bap_stream *stream) -{ - struct bt_iso_connect_param param; - struct bt_iso_chan *iso_chan; - - iso_chan = bt_bap_stream_iso_chan_get(stream); - - LOG_DBG("stream %p iso %p", stream, iso_chan); - - if (stream == NULL || iso_chan == NULL) { - return -EINVAL; - } - - param.acl = stream->conn; - param.iso_chan = iso_chan; - - switch (iso_chan->state) { - case BT_ISO_STATE_DISCONNECTED: - return bt_iso_chan_connect(¶m, 1); - case BT_ISO_STATE_CONNECTING: - return -EBUSY; - case BT_ISO_STATE_CONNECTED: - return -EALREADY; - default: - return bt_iso_chan_connect(¶m, 1); - } -} - static int unicast_group_add_iso(struct bt_bap_unicast_group *group, struct bt_bap_iso *iso) { struct bt_iso_chan **chan_slot = NULL; @@ -3019,6 +2981,55 @@ int bt_bap_unicast_client_metadata(struct bt_bap_stream *stream, const uint8_t m return bt_bap_unicast_client_ep_send(stream->conn, ep, buf); } +int bt_bap_unicast_client_connect(struct bt_bap_stream *stream) +{ + struct bt_iso_connect_param param; + struct bt_iso_chan *iso_chan; + enum bt_iso_state iso_state; + + LOG_DBG("stream %p", stream); + + if (stream == NULL) { + LOG_DBG("stream is NULL"); + + return -EINVAL; + } + + iso_chan = bt_bap_stream_iso_chan_get(stream); + if (iso_chan == NULL) { + LOG_DBG("iso_chan is NULL"); + + return -EINVAL; + } + + LOG_DBG("stream %p iso %p", stream, iso_chan); + + param.acl = stream->conn; + param.iso_chan = iso_chan; + + iso_state = iso_chan->state; + if (iso_state == BT_ISO_STATE_DISCONNECTED) { + const int err = bt_iso_chan_connect(¶m, 1); + + if (err == 0 || err == -EBUSY) { /* Expected / known return values */ + return err; + } + + /* unknown return value*/ + LOG_DBG("Unexpected err %d from bt_iso_chan_connect", err); + + return -ENOEXEC; + } else if (iso_state == BT_ISO_STATE_CONNECTING || iso_state == BT_ISO_STATE_CONNECTED) { + LOG_DBG("iso_chan %p already connecting or connected (%u)", iso_chan, iso_state); + + return -EALREADY; + } + + LOG_DBG("iso_chan %p in invalid state state (%u), cannot connect", iso_chan, iso_state); + + return -EBADMSG; +} + int bt_bap_unicast_client_start(struct bt_bap_stream *stream) { struct bt_bap_ep *ep = stream->ep; @@ -3032,37 +3043,21 @@ int bt_bap_unicast_client_start(struct bt_bap_stream *stream) return -ENOTCONN; } - /* If an ASE is in the Enabling state, and if the Unicast Client has - * not yet established a CIS for that ASE, the Unicast Client shall - * attempt to establish a CIS by using the Connected Isochronous Stream - * Central Establishment procedure. - */ - err = unicast_client_stream_connect(stream); - if (err == 0) { - if (ep->dir == BT_AUDIO_DIR_SOURCE) { - /* Set bool and wait for ISO to be connected to send the - * receiver start ready - */ - ep->receiver_ready = true; - } - } else if (err == -EALREADY) { - LOG_DBG("ISO %p already connected", bt_bap_stream_iso_chan_get(stream)); + /* As per the ASCS spec, only source streams can be started by the client */ + if (ep->dir == BT_AUDIO_DIR_SINK) { + LOG_DBG("Stream %p is not a source stream", stream); - if (ep->dir == BT_AUDIO_DIR_SOURCE) { - ep->receiver_ready = true; + return -EINVAL; + } - err = unicast_client_send_start(ep); - if (err != 0) { - LOG_DBG("Failed to send start: %d", err); + ep->receiver_ready = true; - /* TBD: Should we release the stream then? */ - ep->receiver_ready = false; + err = unicast_client_send_start(ep); + if (err != 0) { + LOG_DBG("Failed to send start: %d", err); - return err; - } - } - } else { - LOG_DBG("unicast_client_stream_connect failed: %d", err); + /* TBD: Should we release the stream then? */ + ep->receiver_ready = false; return err; } diff --git a/subsys/bluetooth/audio/bap_unicast_client_internal.h b/subsys/bluetooth/audio/bap_unicast_client_internal.h index c6ada94863fa1..56542365ac62d 100644 --- a/subsys/bluetooth/audio/bap_unicast_client_internal.h +++ b/subsys/bluetooth/audio/bap_unicast_client_internal.h @@ -20,6 +20,7 @@ int bt_bap_unicast_client_metadata(struct bt_bap_stream *stream, const uint8_t m int bt_bap_unicast_client_disable(struct bt_bap_stream *stream); int bt_bap_unicast_client_start(struct bt_bap_stream *stream); +int bt_bap_unicast_client_connect(struct bt_bap_stream *stream); int bt_bap_unicast_client_stop(struct bt_bap_stream *stream); diff --git a/subsys/bluetooth/audio/cap_common.c b/subsys/bluetooth/audio/cap_common.c index 18249f1f96780..56e7741d2ee0f 100644 --- a/subsys/bluetooth/audio/cap_common.c +++ b/subsys/bluetooth/audio/cap_common.c @@ -1,11 +1,26 @@ /* - * Copyright (c) 2023 Nordic Semiconductor ASA + * Copyright (c) 2023-2024 Nordic Semiconductor ASA * * SPDX-License-Identifier: Apache-2.0 */ - +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include #include +#include #include +#include #include "cap_internal.h" #include "csip_internal.h" @@ -30,6 +45,8 @@ void bt_cap_common_clear_active_proc(void) void bt_cap_common_start_proc(enum bt_cap_common_proc_type proc_type, size_t proc_cnt) { + LOG_DBG("Setting proc to %d for %zu streams", proc_type, proc_cnt); + atomic_set_bit(active_proc.proc_state_flags, BT_CAP_COMMON_PROC_STATE_ACTIVE); active_proc.proc_cnt = proc_cnt; active_proc.proc_type = proc_type; @@ -40,6 +57,8 @@ void bt_cap_common_start_proc(enum bt_cap_common_proc_type proc_type, size_t pro #if defined(CONFIG_BT_CAP_INITIATOR_UNICAST) void bt_cap_common_set_subproc(enum bt_cap_common_subproc_type subproc_type) { + LOG_DBG("Setting subproc to %d", subproc_type); + active_proc.proc_done_cnt = 0U; active_proc.proc_initiated_cnt = 0U; active_proc.subproc_type = subproc_type; @@ -103,6 +122,8 @@ void bt_cap_common_abort_proc(struct bt_conn *conn, int err) return; } + LOG_DBG("Aborting proc %d for %p: %d", active_proc.proc_type, (void *)conn, err); + active_proc.err = err; active_proc.failed_conn = conn; atomic_set_bit(active_proc.proc_state_flags, BT_CAP_COMMON_PROC_STATE_ABORTED); diff --git a/subsys/bluetooth/audio/cap_initiator.c b/subsys/bluetooth/audio/cap_initiator.c index 55fd6886689c9..3fd5199d5c73d 100644 --- a/subsys/bluetooth/audio/cap_initiator.c +++ b/subsys/bluetooth/audio/cap_initiator.c @@ -1,21 +1,35 @@ /* - * Copyright (c) 2022-2023 Nordic Semiconductor ASA + * Copyright (c) 2022-2024 Nordic Semiconductor ASA * * SPDX-License-Identifier: Apache-2.0 */ -#include -#include +#include +#include +#include +#include + +#include #include +#include #include +#include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include + #include "cap_internal.h" #include "ccid_internal.h" #include "csip_internal.h" #include "bap_endpoint.h" -#include - LOG_MODULE_REGISTER(bt_cap_initiator, CONFIG_BT_CAP_INITIATOR_LOG_LEVEL); #include "common/bt_str.h" @@ -313,6 +327,285 @@ int bt_cap_initiator_broadcast_get_base(struct bt_cap_broadcast_source *broadcas #if defined(CONFIG_BT_BAP_UNICAST_CLIENT) +static enum bt_bap_ep_state stream_get_state(const struct bt_bap_stream *bap_stream) +{ + struct bt_bap_ep_info ep_info; + int err; + + err = bt_bap_ep_get_info(bap_stream->ep, &ep_info); + if (err != 0) { + LOG_DBG("Failed to get endpoint info %p: %d", bap_stream, err); + + return BT_BAP_EP_STATE_IDLE; + } + + return ep_info.state; +} + +static bool stream_is_in_state(const struct bt_bap_stream *bap_stream, enum bt_bap_ep_state state) +{ + if (bap_stream->conn == NULL) { + return state == BT_BAP_EP_STATE_IDLE; + } + + return stream_get_state(bap_stream) == state; +} + +static bool stream_is_dir(const struct bt_bap_stream *bap_stream, enum bt_audio_dir dir) +{ + struct bt_bap_ep_info ep_info; + int err; + + if (bap_stream->conn == NULL) { + return false; + } + + err = bt_bap_ep_get_info(bap_stream->ep, &ep_info); + if (err != 0) { + LOG_DBG("Failed to get endpoint info %p: %d", bap_stream, err); + + return false; + } + + return ep_info.dir == dir; +} + +static bool iso_is_in_state(const struct bt_cap_stream *cap_stream, enum bt_iso_state state) +{ + const struct bt_bap_stream *bap_stream = &cap_stream->bap_stream; + struct bt_bap_ep_info ep_info; + int err; + + err = bt_bap_ep_get_info(bap_stream->ep, &ep_info); + if (err != 0) { + LOG_DBG("Failed to get endpoint info %p: %d", bap_stream, err); + + return false; + } + + if (ep_info.iso_chan == NULL) { + return state == BT_ISO_STATE_DISCONNECTED; + } + + return state == ep_info.iso_chan->state; +} + +/** + * @brief Gets the next stream for the active procedure. + * + * Returns NULL if all streams are in the right state for the current step + */ +static struct bt_cap_initiator_proc_param * +get_proc_param_by_cap_stream(struct bt_cap_common_proc *active_proc, + const struct bt_cap_stream *cap_stream) +{ + for (size_t i = 0U; i < active_proc->proc_cnt; i++) { + if (active_proc->proc_param.initiator[i].stream == cap_stream) { + return &active_proc->proc_param.initiator[i]; + } + } + + return NULL; +} + +static void update_proc_done_cnt(struct bt_cap_common_proc *active_proc) +{ + const enum bt_cap_common_subproc_type subproc_type = active_proc->subproc_type; + const enum bt_cap_common_proc_type proc_type = active_proc->proc_type; + size_t proc_done_cnt = 0U; + + if (proc_type == BT_CAP_COMMON_PROC_TYPE_START) { + /* To support state changes by the server, we cannot rely simply on the number of + * BAP procedures we have initiated. For the start and stop CAP procedures we use + * the states to determine how far we are. + */ + for (size_t i = 0U; i < active_proc->proc_cnt; i++) { + const struct bt_cap_initiator_proc_param *proc_param; + struct bt_cap_stream *cap_stream; + struct bt_bap_stream *bap_stream; + enum bt_bap_ep_state state; + + proc_param = &active_proc->proc_param.initiator[i]; + cap_stream = proc_param->stream; + bap_stream = &cap_stream->bap_stream; + + state = stream_get_state(bap_stream); + + switch (subproc_type) { + case BT_CAP_COMMON_SUBPROC_TYPE_CODEC_CONFIG: + if (state > BT_BAP_EP_STATE_IDLE) { + proc_done_cnt++; + } + break; + case BT_CAP_COMMON_SUBPROC_TYPE_QOS_CONFIG: + if (state > BT_BAP_EP_STATE_CODEC_CONFIGURED) { + proc_done_cnt++; + } else if (state < BT_BAP_EP_STATE_CODEC_CONFIGURED) { + /* Unexpected state - Abort */ + bt_cap_common_abort_proc(bap_stream->conn, -EBADMSG); + } + break; + case BT_CAP_COMMON_SUBPROC_TYPE_ENABLE: + if (state > BT_BAP_EP_STATE_QOS_CONFIGURED) { + proc_done_cnt++; + } else if (state < BT_BAP_EP_STATE_QOS_CONFIGURED) { + /* Unexpected state - Abort */ + bt_cap_common_abort_proc(bap_stream->conn, -EBADMSG); + } + break; + case BT_CAP_COMMON_SUBPROC_TYPE_CONNECT: + if (state < BT_BAP_EP_STATE_ENABLING) { + /* Unexpected state - Abort */ + bt_cap_common_abort_proc(bap_stream->conn, -EBADMSG); + } else if (proc_param->start.connected) { + proc_done_cnt++; + } + break; + case BT_CAP_COMMON_SUBPROC_TYPE_START: + if (state > BT_BAP_EP_STATE_ENABLING) { + proc_done_cnt++; + } else if (state < BT_BAP_EP_STATE_ENABLING || + !iso_is_in_state(cap_stream, BT_ISO_STATE_CONNECTED)) { + /* Unexpected state - Abort */ + bt_cap_common_abort_proc(bap_stream->conn, -EBADMSG); + } + break; + default: + __ASSERT(false, "Invalid subproc %d for %d", subproc_type, + proc_type); + } + } + } else if (proc_type == BT_CAP_COMMON_PROC_TYPE_STOP) { + /* To support state changes by the server, we cannot rely simply on the number of + * BAP procedures we have initiated. For the start and stop CAP procedures we use + * the states to determine how far we are. + */ + for (size_t i = 0U; i < active_proc->proc_cnt; i++) { + const struct bt_cap_initiator_proc_param *proc_param; + struct bt_cap_stream *cap_stream; + struct bt_bap_stream *bap_stream; + enum bt_bap_ep_state state; + + proc_param = &active_proc->proc_param.initiator[i]; + cap_stream = proc_param->stream; + bap_stream = &cap_stream->bap_stream; + + state = stream_get_state(bap_stream); + + switch (subproc_type) { + case BT_CAP_COMMON_SUBPROC_TYPE_RELEASE: + if (state == BT_BAP_EP_STATE_IDLE || + state == BT_BAP_EP_STATE_CODEC_CONFIGURED) { + proc_done_cnt++; + } + break; + default: + __ASSERT(false, "Invalid subproc %d for %d", subproc_type, + proc_type); + } + } + } else if (proc_type == BT_CAP_COMMON_PROC_TYPE_UPDATE) { + /* For metadata we cannot check the states for all streams, as it does not trigger a + * state change + */ + const struct bt_cap_initiator_proc_param *proc_param; + struct bt_cap_stream *cap_stream; + struct bt_bap_stream *bap_stream; + enum bt_bap_ep_state state; + + proc_param = &active_proc->proc_param.initiator[active_proc->proc_done_cnt]; + cap_stream = proc_param->stream; + bap_stream = &cap_stream->bap_stream; + + state = stream_get_state(bap_stream); + + switch (subproc_type) { + case BT_CAP_COMMON_SUBPROC_TYPE_META_UPDATE: + if (state == BT_BAP_EP_STATE_ENABLING || + state == BT_BAP_EP_STATE_STREAMING) { + proc_done_cnt = active_proc->proc_done_cnt + 1U; + } else { + /* Unexpected state - Abort */ + bt_cap_common_abort_proc(bap_stream->conn, -EBADMSG); + } + break; + default: + __ASSERT(false, "Invalid subproc %d for %d", subproc_type, proc_type); + } + } + + active_proc->proc_done_cnt = proc_done_cnt; + + LOG_DBG("proc %d subproc %d: %zu/%zu", proc_type, subproc_type, active_proc->proc_done_cnt, + active_proc->proc_cnt); +} + +/** + * @brief Gets the next stream for the active procedure. + * + * Returns NULL if all streams are in the right state for the current step + */ +static struct bt_cap_initiator_proc_param * +get_next_proc_param(struct bt_cap_common_proc *active_proc) +{ + const enum bt_cap_common_subproc_type subproc_type = active_proc->subproc_type; + + for (size_t i = 0U; i < active_proc->proc_cnt; i++) { + struct bt_cap_initiator_proc_param *proc_param; + struct bt_cap_stream *cap_stream; + struct bt_bap_stream *bap_stream; + + proc_param = &active_proc->proc_param.initiator[i]; + cap_stream = proc_param->stream; + bap_stream = &cap_stream->bap_stream; + + switch (subproc_type) { + case BT_CAP_COMMON_SUBPROC_TYPE_CODEC_CONFIG: + if (stream_is_in_state(bap_stream, BT_BAP_EP_STATE_IDLE)) { + return proc_param; + } + break; + case BT_CAP_COMMON_SUBPROC_TYPE_QOS_CONFIG: + if (stream_is_in_state(bap_stream, BT_BAP_EP_STATE_CODEC_CONFIGURED)) { + return proc_param; + } + break; + case BT_CAP_COMMON_SUBPROC_TYPE_ENABLE: + if (stream_is_in_state(bap_stream, BT_BAP_EP_STATE_QOS_CONFIGURED)) { + return proc_param; + } + break; + case BT_CAP_COMMON_SUBPROC_TYPE_CONNECT: + if (stream_is_in_state(bap_stream, BT_BAP_EP_STATE_ENABLING) && + !proc_param->start.connected) { + return proc_param; + } + break; + case BT_CAP_COMMON_SUBPROC_TYPE_START: + if (stream_is_in_state(bap_stream, BT_BAP_EP_STATE_ENABLING)) { + /* TODO: Add check for connected */ + return proc_param; + } + break; + case BT_CAP_COMMON_SUBPROC_TYPE_META_UPDATE: + if (stream_is_in_state(bap_stream, BT_BAP_EP_STATE_ENABLING) || + stream_is_in_state(bap_stream, BT_BAP_EP_STATE_STREAMING)) { + return proc_param; + } + break; + case BT_CAP_COMMON_SUBPROC_TYPE_RELEASE: + if (!stream_is_in_state(bap_stream, BT_BAP_EP_STATE_IDLE)) { + return proc_param; + } + break; + default: + break; + } + } + + return NULL; +} + static void bt_cap_initiator_discover_complete(struct bt_conn *conn, int err, const struct bt_csip_set_coordinator_set_member *member, @@ -522,7 +815,15 @@ static int cap_initiator_unicast_audio_configure( bt_cap_common_start_proc(BT_CAP_COMMON_PROC_TYPE_START, param->count); bt_cap_common_set_subproc(BT_CAP_COMMON_SUBPROC_TYPE_CODEC_CONFIG); - proc_param = &active_proc->proc_param.initiator[0]; + proc_param = get_next_proc_param(active_proc); + if (proc_param == NULL) { + /* If proc_param is NULL then this step is a no-op and we can skip to the next step + */ + bt_cap_initiator_codec_configured(active_proc->proc_param.initiator[0].stream); + + return 0; + } + bap_stream = &proc_param->stream->bap_stream; codec_cfg = proc_param->start.codec_cfg; conn = proc_param->start.conn; @@ -571,6 +872,8 @@ void bt_cap_initiator_codec_configured(struct bt_cap_stream *cap_stream) return; } + LOG_DBG("cap_stream %p", cap_stream); + if (bt_cap_common_subproc_is_type(BT_CAP_COMMON_SUBPROC_TYPE_RELEASE)) { /* When releasing a stream, it may go into the codec configured state if * the unicast server caches the configuration - We treat it as a release @@ -581,7 +884,7 @@ void bt_cap_initiator_codec_configured(struct bt_cap_stream *cap_stream) /* Unexpected callback - Abort */ bt_cap_common_abort_proc(cap_stream->bap_stream.conn, -EBADMSG); } else { - active_proc->proc_done_cnt++; + update_proc_done_cnt(active_proc); LOG_DBG("Stream %p configured (%zu/%zu streams done)", cap_stream, active_proc->proc_done_cnt, active_proc->proc_cnt); @@ -596,20 +899,20 @@ void bt_cap_initiator_codec_configured(struct bt_cap_stream *cap_stream) } if (!bt_cap_common_proc_is_done()) { - const size_t proc_done_cnt = active_proc->proc_done_cnt; struct bt_cap_stream *next_cap_stream; + struct bt_bap_stream *next_bap_stream; struct bt_audio_codec_cfg *codec_cfg; - struct bt_bap_stream *bap_stream; struct bt_conn *conn; struct bt_bap_ep *ep; int err; - proc_param = &active_proc->proc_param.initiator[proc_done_cnt]; + proc_param = get_next_proc_param(active_proc); + __ASSERT(proc_param != NULL, "proc is not done, but could not get next proc_param"); next_cap_stream = proc_param->stream; conn = proc_param->start.conn; ep = proc_param->start.ep; codec_cfg = proc_param->start.codec_cfg; - bap_stream = &next_cap_stream->bap_stream; + next_bap_stream = &next_cap_stream->bap_stream; active_proc->proc_initiated_cnt++; /* Since BAP operations may require a write long or a read long on the notification, @@ -618,7 +921,7 @@ void bt_cap_initiator_codec_configured(struct bt_cap_stream *cap_stream) * TODO: We should always be able to do one per ACL, so there is room for * optimization. */ - err = bt_bap_stream_config(conn, bap_stream, ep, codec_cfg); + err = bt_bap_stream_config(conn, next_bap_stream, ep, codec_cfg); if (err != 0) { LOG_DBG("Failed to config stream %p: %d", next_cap_stream, err); @@ -663,9 +966,17 @@ void bt_cap_initiator_codec_configured(struct bt_cap_stream *cap_stream) /* All streams in the procedure share the same unicast group, so we just * use the reference from the first stream */ - proc_param = &active_proc->proc_param.initiator[0]; - unicast_group = (struct bt_bap_unicast_group *)proc_param->stream->bap_stream.group; bt_cap_common_set_subproc(BT_CAP_COMMON_SUBPROC_TYPE_QOS_CONFIG); + proc_param = get_next_proc_param(active_proc); + if (proc_param == NULL) { + /* If proc_param is NULL then this step is a no-op and we can skip to the next step + */ + bt_cap_initiator_qos_configured(active_proc->proc_param.initiator[0].stream); + + return; + } + + unicast_group = (struct bt_bap_unicast_group *)proc_param->stream->bap_stream.group; for (size_t i = 0U; i < ARRAY_SIZE(conns); i++) { int err; @@ -709,11 +1020,13 @@ void bt_cap_initiator_qos_configured(struct bt_cap_stream *cap_stream) return; } + LOG_DBG("cap_stream %p", cap_stream); + if (!bt_cap_common_subproc_is_type(BT_CAP_COMMON_SUBPROC_TYPE_QOS_CONFIG)) { /* Unexpected callback - Abort */ bt_cap_common_abort_proc(cap_stream->bap_stream.conn, -EBADMSG); } else { - active_proc->proc_done_cnt++; + update_proc_done_cnt(active_proc); LOG_DBG("Stream %p QoS configured (%zu/%zu streams done)", cap_stream, active_proc->proc_done_cnt, active_proc->proc_cnt); @@ -733,7 +1046,15 @@ void bt_cap_initiator_qos_configured(struct bt_cap_stream *cap_stream) } bt_cap_common_set_subproc(BT_CAP_COMMON_SUBPROC_TYPE_ENABLE); - proc_param = &active_proc->proc_param.initiator[0]; + proc_param = get_next_proc_param(active_proc); + if (proc_param == NULL) { + /* If proc_param is NULL then this step is a no-op and we can skip to the next step + */ + bt_cap_initiator_enabled(active_proc->proc_param.initiator[0].stream); + + return; + } + next_cap_stream = proc_param->stream; bap_stream = &next_cap_stream->bap_stream; active_proc->proc_initiated_cnt++; @@ -764,11 +1085,13 @@ void bt_cap_initiator_enabled(struct bt_cap_stream *cap_stream) return; } + LOG_DBG("cap_stream %p", cap_stream); + if (!bt_cap_common_subproc_is_type(BT_CAP_COMMON_SUBPROC_TYPE_ENABLE)) { /* Unexpected callback - Abort */ bt_cap_common_abort_proc(cap_stream->bap_stream.conn, -EBADMSG); } else { - active_proc->proc_done_cnt++; + update_proc_done_cnt(active_proc); LOG_DBG("Stream %p enabled (%zu/%zu streams done)", cap_stream, active_proc->proc_done_cnt, active_proc->proc_cnt); @@ -783,9 +1106,13 @@ void bt_cap_initiator_enabled(struct bt_cap_stream *cap_stream) } if (!bt_cap_common_proc_is_done()) { - struct bt_cap_stream *next_cap_stream = - active_proc->proc_param.initiator[active_proc->proc_done_cnt].stream; - struct bt_bap_stream *next_bap_stream = &next_cap_stream->bap_stream; + struct bt_cap_stream *next_cap_stream; + struct bt_bap_stream *next_bap_stream; + + proc_param = get_next_proc_param(active_proc); + __ASSERT(proc_param != NULL, "proc is not done, but could not get next proc_param"); + next_cap_stream = proc_param->stream; + next_bap_stream = &next_cap_stream->bap_stream; active_proc->proc_initiated_cnt++; @@ -807,17 +1134,27 @@ void bt_cap_initiator_enabled(struct bt_cap_stream *cap_stream) return; } - bt_cap_common_set_subproc(BT_CAP_COMMON_SUBPROC_TYPE_START); - proc_param = &active_proc->proc_param.initiator[0]; + bt_cap_common_set_subproc(BT_CAP_COMMON_SUBPROC_TYPE_CONNECT); + proc_param = get_next_proc_param(active_proc); + if (proc_param == NULL) { + /* If proc_param is NULL then this step is a no-op and we can skip to the next step + */ + bt_cap_initiator_connected(active_proc->proc_param.initiator[0].stream); + + return; + } + bap_stream = &proc_param->stream->bap_stream; - /* Since BAP operations may require a write long or a read long on the notification, we - * cannot assume that we can do multiple streams at once, thus do it one at a time. - * TODO: We should always be able to do one per ACL, so there is room for optimization. - */ - err = bt_bap_stream_start(bap_stream); - if (err != 0) { - LOG_DBG("Failed to start stream %p: %d", proc_param->stream, err); + err = bt_bap_stream_connect(bap_stream); + if (err == -EALREADY) { + /* If the stream is already connected we can just call the callback directly + * NOTE: It's important that we do not do any additional functionality after + * calling this + */ + bt_cap_initiator_connected(proc_param->stream); + } else if (err != 0) { + LOG_DBG("Failed to connect stream %p: %d", proc_param->stream, err); /* End and mark procedure as aborted. * If we have sent any requests over air, we will abort @@ -825,75 +1162,174 @@ void bt_cap_initiator_enabled(struct bt_cap_stream *cap_stream) */ bt_cap_common_abort_proc(bap_stream->conn, err); cap_initiator_unicast_audio_proc_complete(); - - return; } } -void bt_cap_initiator_started(struct bt_cap_stream *cap_stream) +void bt_cap_initiator_connected(struct bt_cap_stream *cap_stream) { struct bt_cap_common_proc *active_proc = bt_cap_common_get_active_proc(); + struct bt_cap_initiator_proc_param *proc_param; + struct bt_bap_stream *bap_stream; + int err; if (!bt_cap_common_stream_in_active_proc(cap_stream)) { /* State change happened outside of a procedure; ignore */ return; } - if (!bt_cap_common_subproc_is_type(BT_CAP_COMMON_SUBPROC_TYPE_START)) { + LOG_DBG("cap_stream %p", cap_stream); + + if (!bt_cap_common_subproc_is_type(BT_CAP_COMMON_SUBPROC_TYPE_CONNECT)) { /* Unexpected callback - Abort */ bt_cap_common_abort_proc(cap_stream->bap_stream.conn, -EBADMSG); } else { - active_proc->proc_done_cnt++; + proc_param = get_proc_param_by_cap_stream(active_proc, cap_stream); + __ASSERT_NO_MSG(proc_param != NULL); - LOG_DBG("Stream %p started (%zu/%zu streams done)", cap_stream, + /* Sets connected before update_proc_done_cnt as that is the only way to can track + * the CIS state change + */ + proc_param->start.connected = true; + update_proc_done_cnt(active_proc); + + LOG_DBG("Stream %p connected (%zu/%zu streams done)", cap_stream, active_proc->proc_done_cnt, active_proc->proc_cnt); } - /* Since bt_bap_stream_start connects the ISO, we can, at this point, - * only do this one by one due to a restriction in the ISO layer - * (maximum 1 outstanding ISO connection request at any one time). - */ + if (bt_cap_common_proc_is_aborted()) { + if (bt_cap_common_proc_all_handled()) { + cap_initiator_unicast_audio_proc_complete(); + } + + return; + } + if (!bt_cap_common_proc_is_done()) { - struct bt_cap_stream *next_cap_stream = - active_proc->proc_param.initiator[active_proc->proc_done_cnt].stream; - struct bt_bap_stream *bap_stream = &next_cap_stream->bap_stream; - int err; + struct bt_cap_stream *next_cap_stream; + struct bt_bap_stream *next_bap_stream; + + proc_param = get_next_proc_param(active_proc); + __ASSERT(proc_param != NULL, "proc is not done, but could not get next proc_param"); + next_cap_stream = proc_param->stream; + next_bap_stream = &next_cap_stream->bap_stream; + + active_proc->proc_initiated_cnt++; - /* Not yet finished, start next */ + err = bt_bap_stream_connect(next_bap_stream); + if (err == 0 || err == -EALREADY) { + /* Pending connected - wait for connected callback */ + } else if (err != 0) { + LOG_DBG("Failed to connect stream %p: %d", next_cap_stream, err); + + bt_cap_common_abort_proc(next_bap_stream->conn, err); + cap_initiator_unicast_audio_proc_complete(); + } + + return; + } + + /* All streams connected - Start sending the receiver start ready for all source + * ASEs. For sink ASEs it is the responsibility of the unicast server to do the + * receiver start ready operation. If there are no source ASEs then we just wait. + */ + bt_cap_common_set_subproc(BT_CAP_COMMON_SUBPROC_TYPE_START); + proc_param = get_next_proc_param(active_proc); + if (proc_param == NULL) { + /* If proc_param is NULL then this step is a no-op and we can skip to the next step + */ + bt_cap_initiator_started(active_proc->proc_param.initiator[0].stream); + + return; + } + + bap_stream = &proc_param->stream->bap_stream; + if (stream_is_dir(bap_stream, BT_AUDIO_DIR_SOURCE)) { + /* Since BAP operations may require a write long or a read long on the notification, + * we cannot assume that we can do multiple streams at once, thus do it one at a + * time. + * TODO: We should always be able to do one per ACL, so there is room for + * optimization. + */ err = bt_bap_stream_start(bap_stream); if (err != 0) { - LOG_DBG("Failed to start stream %p: %d", next_cap_stream, err); + LOG_DBG("Failed to start stream %p: %d", proc_param->stream, err); - /* End and mark procedure as aborted. - * If we have sent any requests over air, we will abort - * once all sent requests has completed - */ bt_cap_common_abort_proc(bap_stream->conn, err); cap_initiator_unicast_audio_proc_complete(); + + return; } - } else { - cap_initiator_unicast_audio_proc_complete(); } } -static bool can_update_metadata(const struct bt_bap_stream *bap_stream) +void bt_cap_initiator_started(struct bt_cap_stream *cap_stream) { - struct bt_bap_ep_info ep_info; - int err; + struct bt_cap_common_proc *active_proc = bt_cap_common_get_active_proc(); - if (bap_stream->conn == NULL) { - return false; + LOG_DBG("cap_stream %p", cap_stream); + + if (!bt_cap_common_stream_in_active_proc(cap_stream)) { + /* State change happened outside of a procedure; ignore */ + return; } - err = bt_bap_ep_get_info(bap_stream->ep, &ep_info); - if (err != 0) { - LOG_DBG("Failed to get endpoint info %p: %d", bap_stream, err); + /* Streams may go into the streaming state while we are connecting or starting them */ + if (!bt_cap_common_subproc_is_type(BT_CAP_COMMON_SUBPROC_TYPE_START) && + !bt_cap_common_subproc_is_type(BT_CAP_COMMON_SUBPROC_TYPE_CONNECT)) { + /* Unexpected callback - Abort */ + bt_cap_common_abort_proc(cap_stream->bap_stream.conn, -EBADMSG); + } else { + update_proc_done_cnt(active_proc); - return false; + LOG_DBG("Stream %p started (%zu/%zu streams done)", cap_stream, + active_proc->proc_done_cnt, active_proc->proc_cnt); } - return ep_info.state == BT_BAP_EP_STATE_ENABLING || - ep_info.state == BT_BAP_EP_STATE_STREAMING; + if (!bt_cap_common_proc_is_done()) { + struct bt_cap_initiator_proc_param *proc_param; + struct bt_cap_stream *next_cap_stream; + struct bt_bap_stream *next_bap_stream; + + proc_param = get_next_proc_param(active_proc); + __ASSERT(proc_param != NULL, "proc is not done, but could not get next proc_param"); + next_cap_stream = proc_param->stream; + next_bap_stream = &next_cap_stream->bap_stream; + + if (stream_is_dir(next_bap_stream, BT_AUDIO_DIR_SOURCE)) { + int err; + + /* Since BAP operations may require a write long or a read long on + * the notification, we cannot assume that we can do multiple + * streams at once, thus do it one at a time. + * TODO: We should always be able to do one per ACL, so there is + * room for optimization. + */ + err = bt_bap_stream_start(next_bap_stream); + if (err != 0) { + LOG_DBG("Failed to start stream %p: %d", next_cap_stream, err); + + /* End and mark procedure as aborted. + * If we have sent any requests over air, we will abort + * once all sent requests has completed + */ + bt_cap_common_abort_proc(next_bap_stream->conn, err); + cap_initiator_unicast_audio_proc_complete(); + + return; + } + } /* else await notifications from server */ + + /* Return to await for response from server */ + return; + } + + cap_initiator_unicast_audio_proc_complete(); +} + +static bool can_update_metadata(const struct bt_bap_stream *bap_stream) +{ + return stream_is_in_state(bap_stream, BT_BAP_EP_STATE_ENABLING) || + stream_is_in_state(bap_stream, BT_BAP_EP_STATE_STREAMING); } static bool valid_unicast_audio_update_param(const struct bt_cap_unicast_audio_update_param *param) @@ -1019,7 +1455,7 @@ int bt_cap_initiator_unicast_audio_update(const struct bt_cap_unicast_audio_upda bt_cap_common_start_proc(BT_CAP_COMMON_PROC_TYPE_UPDATE, param->count); bt_cap_common_set_subproc(BT_CAP_COMMON_SUBPROC_TYPE_META_UPDATE); - proc_param = &active_proc->proc_param.initiator[0]; + proc_param = get_next_proc_param(active_proc); bap_stream = &proc_param->stream->bap_stream; meta_len = proc_param->meta_update.meta_len; meta = proc_param->meta_update.meta; @@ -1062,7 +1498,7 @@ void bt_cap_initiator_metadata_updated(struct bt_cap_stream *cap_stream) /* Unexpected callback - Abort */ bt_cap_common_abort_proc(cap_stream->bap_stream.conn, -EBADMSG); } else { - active_proc->proc_done_cnt++; + update_proc_done_cnt(active_proc); LOG_DBG("Stream %p QoS metadata updated (%zu/%zu streams done)", cap_stream, active_proc->proc_done_cnt, active_proc->proc_cnt); @@ -1116,21 +1552,11 @@ void bt_cap_initiator_metadata_updated(struct bt_cap_stream *cap_stream) static bool can_release(const struct bt_bap_stream *bap_stream) { - struct bt_bap_ep_info ep_info; - int err; - if (bap_stream->conn == NULL) { return false; } - err = bt_bap_ep_get_info(bap_stream->ep, &ep_info); - if (err != 0) { - LOG_DBG("Failed to get endpoint info %p: %d", bap_stream, err); - - return false; - } - - return ep_info.state != BT_BAP_EP_STATE_IDLE; + return !stream_is_in_state(bap_stream, BT_BAP_EP_STATE_IDLE); } static bool valid_unicast_audio_stop_param(const struct bt_cap_unicast_audio_stop_param *param) @@ -1244,7 +1670,7 @@ int bt_cap_initiator_unicast_audio_stop(const struct bt_cap_unicast_audio_stop_p * not match the order in the parameters, and the CSIP ordered access * procedure should be used. */ - proc_param = &active_proc->proc_param.initiator[0]; + proc_param = get_next_proc_param(active_proc); bap_stream = &proc_param->stream->bap_stream; active_proc->proc_initiated_cnt++; @@ -1271,7 +1697,7 @@ void bt_cap_initiator_released(struct bt_cap_stream *cap_stream) /* Unexpected callback - Abort */ bt_cap_common_abort_proc(cap_stream->bap_stream.conn, -EBADMSG); } else { - active_proc->proc_done_cnt++; + update_proc_done_cnt(active_proc); LOG_DBG("Stream %p released (%zu/%zu streams done)", cap_stream, active_proc->proc_done_cnt, active_proc->proc_cnt); @@ -1292,9 +1718,9 @@ void bt_cap_initiator_released(struct bt_cap_stream *cap_stream) int err; active_proc->proc_initiated_cnt++; - /* Since BAP operations may require a write long or a read long on the notification, - * we cannot assume that we can do multiple streams at once, thus do it one at a - * time. + /* Since BAP operations may require a write long or a read long on the + * notification, we cannot assume that we can do multiple streams at once, + * thus do it one at a time. * TODO: We should always be able to do one per ACL, so there is room for * optimization. */ diff --git a/subsys/bluetooth/audio/cap_internal.h b/subsys/bluetooth/audio/cap_internal.h index e201657bcad7b..e460fce98dcdd 100644 --- a/subsys/bluetooth/audio/cap_internal.h +++ b/subsys/bluetooth/audio/cap_internal.h @@ -1,11 +1,17 @@ /* Bluetooth Audio Common Audio Profile internal header */ /* - * Copyright (c) 2022-2023 Nordic Semiconductor ASA + * Copyright (c) 2022-2024 Nordic Semiconductor ASA * * SPDX-License-Identifier: Apache-2.0 */ +#include +#include + +#include +#include +#include #include #include #include @@ -20,6 +26,7 @@ void bt_cap_initiator_codec_configured(struct bt_cap_stream *cap_stream); void bt_cap_initiator_qos_configured(struct bt_cap_stream *cap_stream); void bt_cap_initiator_enabled(struct bt_cap_stream *cap_stream); void bt_cap_initiator_started(struct bt_cap_stream *cap_stream); +void bt_cap_initiator_connected(struct bt_cap_stream *cap_stream); void bt_cap_initiator_metadata_updated(struct bt_cap_stream *cap_stream); void bt_cap_initiator_released(struct bt_cap_stream *cap_stream); void bt_cap_stream_ops_register_bap(struct bt_cap_stream *cap_stream); @@ -49,6 +56,7 @@ enum bt_cap_common_subproc_type { BT_CAP_COMMON_SUBPROC_TYPE_CODEC_CONFIG, BT_CAP_COMMON_SUBPROC_TYPE_QOS_CONFIG, BT_CAP_COMMON_SUBPROC_TYPE_ENABLE, + BT_CAP_COMMON_SUBPROC_TYPE_CONNECT, BT_CAP_COMMON_SUBPROC_TYPE_START, BT_CAP_COMMON_SUBPROC_TYPE_META_UPDATE, BT_CAP_COMMON_SUBPROC_TYPE_RELEASE, @@ -61,6 +69,7 @@ struct bt_cap_initiator_proc_param { struct bt_conn *conn; struct bt_bap_ep *ep; struct bt_audio_codec_cfg *codec_cfg; + bool connected; } start; struct { /** Codec Specific Capabilities Metadata count */ diff --git a/subsys/bluetooth/audio/cap_stream.c b/subsys/bluetooth/audio/cap_stream.c index c2999534f8173..46009b36a4771 100644 --- a/subsys/bluetooth/audio/cap_stream.c +++ b/subsys/bluetooth/audio/cap_stream.c @@ -1,18 +1,48 @@ /* - * Copyright (c) 2022-2023 Nordic Semiconductor ASA + * Copyright (c) 2022-2024 Nordic Semiconductor ASA * * SPDX-License-Identifier: Apache-2.0 */ +#include +#include +#include +#include + +#include +#include #include +#include +#include +#include +#include #include +#include +#include #include "cap_internal.h" -#include - LOG_MODULE_REGISTER(bt_cap_stream, CONFIG_BT_CAP_STREAM_LOG_LEVEL); +static bool is_cap_initiator_unicast(struct bt_bap_stream *bap_stream) +{ + if (IS_ENABLED(CONFIG_BT_CAP_INITIATOR) && IS_ENABLED(CONFIG_BT_BAP_UNICAST_CLIENT)) { + struct bt_conn_info info; + int err; + + if (bap_stream->conn == NULL) { + return false; + } + + err = bt_conn_get_info(bap_stream->conn, &info); + if (err == 0 && info.role == BT_HCI_ROLE_CENTRAL) { + return true; + } + } + + return false; +} + #if defined(CONFIG_BT_BAP_UNICAST) static void cap_stream_configured_cb(struct bt_bap_stream *bap_stream, const struct bt_audio_codec_qos_pref *pref) @@ -24,7 +54,7 @@ static void cap_stream_configured_cb(struct bt_bap_stream *bap_stream, LOG_DBG("%p", cap_stream); - if (IS_ENABLED(CONFIG_BT_CAP_INITIATOR)) { + if (is_cap_initiator_unicast(bap_stream)) { bt_cap_initiator_codec_configured(cap_stream); } @@ -42,7 +72,7 @@ static void cap_stream_qos_set_cb(struct bt_bap_stream *bap_stream) LOG_DBG("%p", cap_stream); - if (IS_ENABLED(CONFIG_BT_CAP_INITIATOR)) { + if (is_cap_initiator_unicast(bap_stream)) { bt_cap_initiator_qos_configured(cap_stream); } @@ -60,7 +90,7 @@ static void cap_stream_enabled_cb(struct bt_bap_stream *bap_stream) LOG_DBG("%p", cap_stream); - if (IS_ENABLED(CONFIG_BT_CAP_INITIATOR)) { + if (is_cap_initiator_unicast(bap_stream)) { bt_cap_initiator_enabled(cap_stream); } @@ -78,7 +108,7 @@ static void cap_stream_metadata_updated_cb(struct bt_bap_stream *bap_stream) LOG_DBG("%p", cap_stream); - if (IS_ENABLED(CONFIG_BT_CAP_INITIATOR)) { + if (is_cap_initiator_unicast(bap_stream)) { bt_cap_initiator_metadata_updated(cap_stream); } @@ -110,7 +140,10 @@ static void cap_stream_released_cb(struct bt_bap_stream *bap_stream) LOG_DBG("%p", cap_stream); - if (IS_ENABLED(CONFIG_BT_CAP_INITIATOR)) { + /* Here we cannot use is_cap_initiator_unicast as bap_stream->conn is NULL, so fall back to + * a more generic, less accurate check + */ + if (IS_ENABLED(CONFIG_BT_CAP_INITIATOR) && IS_ENABLED(CONFIG_BT_BAP_UNICAST_CLIENT)) { bt_cap_initiator_released(cap_stream); } @@ -130,7 +163,7 @@ static void cap_stream_started_cb(struct bt_bap_stream *bap_stream) LOG_DBG("%p", cap_stream); - if (IS_ENABLED(CONFIG_BT_CAP_INITIATOR) && IS_ENABLED(CONFIG_BT_BAP_UNICAST)) { + if (is_cap_initiator_unicast(bap_stream)) { bt_cap_initiator_started(cap_stream); } @@ -188,6 +221,10 @@ static void cap_stream_connected_cb(struct bt_bap_stream *bap_stream) CONTAINER_OF(bap_stream, struct bt_cap_stream, bap_stream); struct bt_bap_stream_ops *ops = cap_stream->ops; + if (is_cap_initiator_unicast(bap_stream)) { + bt_cap_initiator_connected(cap_stream); + } + if (ops != NULL && ops->connected != NULL) { ops->connected(bap_stream); } diff --git a/subsys/bluetooth/audio/shell/bap.c b/subsys/bluetooth/audio/shell/bap.c index b045ecbcda4c6..b560ba3c714df 100644 --- a/subsys/bluetooth/audio/shell/bap.c +++ b/subsys/bluetooth/audio/shell/bap.c @@ -1550,6 +1550,24 @@ static int cmd_stop(const struct shell *sh, size_t argc, char *argv[]) return 0; } + +static int cmd_connect(const struct shell *sh, size_t argc, char *argv[]) +{ + int err; + + if (default_stream == NULL) { + shell_error(sh, "No stream selected"); + return -ENOEXEC; + } + + err = bt_bap_stream_connect(default_stream); + if (err) { + shell_error(sh, "Unable to connect stream"); + return -ENOEXEC; + } + + return 0; +} #endif /* CONFIG_BT_BAP_UNICAST_CLIENT */ static int cmd_metadata(const struct shell *sh, size_t argc, char *argv[]) @@ -3949,6 +3967,7 @@ SHELL_STATIC_SUBCMD_SET_CREATE( cmd_config, 3, 4), SHELL_CMD_ARG(stream_qos, NULL, "interval [framing] [latency] [pd] [sdu] [phy] [rtn]", cmd_stream_qos, 2, 6), + SHELL_CMD_ARG(connect, NULL, "Connect the CIS of the stream", cmd_connect, 1, 0), SHELL_CMD_ARG(qos, NULL, "Send QoS configure for Unicast Group", cmd_qos, 1, 0), SHELL_CMD_ARG(enable, NULL, "[context]", cmd_enable, 1, 1), SHELL_CMD_ARG(stop, NULL, NULL, cmd_stop, 1, 0), diff --git a/tests/bluetooth/audio/mocks/src/bap_unicast_client.c b/tests/bluetooth/audio/mocks/src/bap_unicast_client.c index 58933b85197a3..ef9ac1328b80e 100644 --- a/tests/bluetooth/audio/mocks/src/bap_unicast_client.c +++ b/tests/bluetooth/audio/mocks/src/bap_unicast_client.c @@ -44,6 +44,12 @@ int bt_bap_unicast_client_disable(struct bt_bap_stream *stream) return 0; } +int bt_bap_unicast_client_connect(struct bt_bap_stream *stream) +{ + zassert_unreachable("Unexpected call to '%s()' occurred", __func__); + return 0; +} + int bt_bap_unicast_client_start(struct bt_bap_stream *stream) { zassert_unreachable("Unexpected call to '%s()' occurred", __func__); diff --git a/tests/bluetooth/tester/src/btp_bap_unicast.c b/tests/bluetooth/tester/src/btp_bap_unicast.c index 06b9219697c48..a7df01c543f81 100644 --- a/tests/bluetooth/tester/src/btp_bap_unicast.c +++ b/tests/bluetooth/tester/src/btp_bap_unicast.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include "bap_endpoint.h" @@ -636,6 +637,26 @@ static void stream_started(struct bt_bap_stream *stream) btp_send_ascs_ase_state_changed_ev(stream->conn, u_stream->ase_id, info.state); } +static void stream_connected(struct bt_bap_stream *stream) +{ + struct bt_conn_info conn_info; + struct bt_bap_ep_info ep_info; + int err; + + LOG_DBG("Connected stream %p", stream); + + (void)bt_bap_ep_get_info(stream->ep, &ep_info); + (void)bt_conn_get_info(stream->conn, &conn_info); + if (conn_info.role == BT_HCI_ROLE_CENTRAL && ep_info.dir == BT_AUDIO_DIR_SOURCE) { + /* Automatically do the receiver start ready operation for source ASEs as the client + */ + err = bt_bap_stream_start(stream); + if (err != 0) { + LOG_ERR("Failed to start stream %p", stream); + } + } +} + static void stream_stopped(struct bt_bap_stream *stream, uint8_t reason) { struct btp_bap_unicast_stream *u_stream = stream_bap_to_unicast(stream); @@ -703,6 +724,7 @@ static struct bt_bap_stream_ops stream_ops = { .stopped = stream_stopped, .recv = stream_recv, .sent = stream_sent, + .connected = stream_connected, }; struct btp_bap_unicast_stream *btp_bap_unicast_stream_alloc( @@ -1419,7 +1441,7 @@ uint8_t btp_ascs_receiver_start_ready(const void *cmd, uint16_t cmd_len, LOG_DBG("Starting stream %p, ep %u, dir %u", bap_stream, cp->ase_id, info.dir); while (true) { - err = bt_bap_stream_start(bap_stream); + err = bt_bap_stream_connect(bap_stream); if (err == -EBUSY) { /* TODO: How to determine if a controller is ready again after * bt_bap_stream_start? In AC 6(i) tests the PTS sends Receiver Start Ready @@ -1427,8 +1449,8 @@ uint8_t btp_ascs_receiver_start_ready(const void *cmd, uint16_t cmd_len, */ k_sleep(K_MSEC(1000)); continue; - } else if (err != 0) { - LOG_DBG("Could not start stream: %d", err); + } else if (err != 0 && err != -EALREADY) { + LOG_DBG("Could not connect stream: %d", err); return BTP_STATUS_FAILED; } diff --git a/tests/bsim/bluetooth/audio/prj.conf b/tests/bsim/bluetooth/audio/prj.conf index 90e5924bf6cb5..ac1809dbf20d5 100644 --- a/tests/bsim/bluetooth/audio/prj.conf +++ b/tests/bsim/bluetooth/audio/prj.conf @@ -159,6 +159,7 @@ CONFIG_BT_PBP=y # DEBUGGING CONFIG_LOG=y +CONFIG_BT_ISO_LOG_LEVEL_DBG=y CONFIG_LOG_FUNC_NAME_PREFIX_ERR=y CONFIG_LOG_FUNC_NAME_PREFIX_WRN=y CONFIG_BT_VCP_VOL_REND_LOG_LEVEL_DBG=y diff --git a/tests/bsim/bluetooth/audio/src/bap_unicast_client_test.c b/tests/bsim/bluetooth/audio/src/bap_unicast_client_test.c index e2cacc854af31..ac4e459f4f1b9 100644 --- a/tests/bsim/bluetooth/audio/src/bap_unicast_client_test.c +++ b/tests/bsim/bluetooth/audio/src/bap_unicast_client_test.c @@ -752,16 +752,16 @@ static void metadata_update_streams(size_t stream_cnt) } } -static int start_stream(struct bt_bap_stream *stream) +static int connect_stream(struct bt_bap_stream *stream) { int err; UNSET_FLAG(flag_stream_started); do { - err = bt_bap_stream_start(stream); - if (err == -EBUSY) { - k_sleep(BAP_STREAM_RETRY_WAIT); + err = bt_bap_stream_connect(stream); + if (err == -EALREADY) { + SET_FLAG(flag_stream_started); } else if (err != 0) { FAIL("Could not start stream %p: %d\n", stream, err); return err; @@ -773,7 +773,7 @@ static int start_stream(struct bt_bap_stream *stream) return 0; } -static void start_streams(void) +static void connect_streams(void) { struct bt_bap_stream *source_stream; struct bt_bap_stream *sink_stream; @@ -788,20 +788,20 @@ static void start_streams(void) UNSET_FLAG(flag_stream_connected); if (sink_stream != NULL) { - const int err = start_stream(sink_stream); + const int err = connect_stream(sink_stream); if (err != 0) { - FAIL("Unable to start sink: %d", err); + FAIL("Unable to connect sink: %d", err); return; } } if (source_stream != NULL) { - const int err = start_stream(source_stream); + const int err = connect_stream(source_stream); if (err != 0) { - FAIL("Unable to start source stream: %d", err); + FAIL("Unable to connect source stream: %d", err); return; } @@ -810,6 +810,44 @@ static void start_streams(void) WAIT_FOR_FLAG(flag_stream_connected); } +static int start_stream(struct bt_bap_stream *stream) +{ + int err; + + UNSET_FLAG(flag_stream_started); + + do { + err = bt_bap_stream_start(stream); + if (err == -EBUSY) { + k_sleep(BAP_STREAM_RETRY_WAIT); + } else if (err != 0) { + FAIL("Could not start stream %p: %d\n", stream, err); + return err; + } + } while (err == -EBUSY); + + WAIT_FOR_FLAG(flag_stream_started); + + return 0; +} + +static void start_streams(void) +{ + struct bt_bap_stream *source_stream; + + source_stream = pair_params[0].rx_param == NULL ? NULL : pair_params[0].rx_param->stream; + + if (source_stream != NULL) { + const int err = start_stream(source_stream); + + if (err != 0) { + FAIL("Unable to start source stream: %d", err); + + return; + } + } +} + static void transceive_streams(void) { struct bt_bap_stream *source_stream; @@ -1051,6 +1089,9 @@ static void test_main(void) printk("Metadata update streams\n"); metadata_update_streams(stream_cnt); + printk("Connecting streams\n"); + connect_streams(); + printk("Starting streams\n"); start_streams(); @@ -1109,6 +1150,9 @@ static void test_main_acl_disconnect(void) printk("Metadata update streams\n"); metadata_update_streams(stream_cnt); + printk("Connecting streams\n"); + connect_streams(); + printk("Starting streams\n"); start_streams(); From b76fde64a1b30b7aede4d3f8c9d428c7ed4f34fb Mon Sep 17 00:00:00 2001 From: frei tycho Date: Fri, 17 May 2024 13:13:47 +0000 Subject: [PATCH 1582/2849] include: kernel: added missing parenthesis - added missing parenthesis around macro argument expansion Signed-off-by: frei tycho --- include/zephyr/kernel.h | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/include/zephyr/kernel.h b/include/zephyr/kernel.h index f4b2cbe1bc2c1..a6cf1ca352db3 100644 --- a/include/zephyr/kernel.h +++ b/include/zephyr/kernel.h @@ -375,7 +375,7 @@ FUNC_NORETURN void k_thread_user_mode_enter(k_thread_entry_t entry, * @param ... list of kernel object pointers */ #define k_thread_access_grant(thread, ...) \ - FOR_EACH_FIXED_ARG(k_object_access_grant, (;), thread, __VA_ARGS__) + FOR_EACH_FIXED_ARG(k_object_access_grant, (;), (thread), __VA_ARGS__) /** * @brief Assign a resource memory pool to a thread @@ -2772,10 +2772,10 @@ struct k_stack { #define Z_STACK_INITIALIZER(obj, stack_buffer, stack_num_entries) \ { \ - .wait_q = Z_WAIT_Q_INIT(&obj.wait_q), \ - .base = stack_buffer, \ - .next = stack_buffer, \ - .top = stack_buffer + stack_num_entries, \ + .wait_q = Z_WAIT_Q_INIT(&(obj).wait_q), \ + .base = (stack_buffer), \ + .next = (stack_buffer), \ + .top = (stack_buffer) + (stack_num_entries), \ } /** @@ -2935,7 +2935,7 @@ struct k_mutex { */ #define Z_MUTEX_INITIALIZER(obj) \ { \ - .wait_q = Z_WAIT_Q_INIT(&obj.wait_q), \ + .wait_q = Z_WAIT_Q_INIT(&(obj).wait_q), \ .owner = NULL, \ .lock_count = 0, \ .owner_orig_prio = K_LOWEST_APPLICATION_THREAD_PRIO, \ @@ -3124,9 +3124,9 @@ struct k_sem { #define Z_SEM_INITIALIZER(obj, initial_count, count_limit) \ { \ - .wait_q = Z_WAIT_Q_INIT(&obj.wait_q), \ - .count = initial_count, \ - .limit = count_limit, \ + .wait_q = Z_WAIT_Q_INIT(&(obj).wait_q), \ + .count = (initial_count), \ + .limit = (count_limit), \ Z_POLL_EVENT_OBJ_INIT(obj) \ } @@ -3896,7 +3896,7 @@ struct k_work { }; #define Z_WORK_INITIALIZER(work_handler) { \ - .handler = work_handler, \ + .handler = (work_handler), \ } /** @brief A structure used to submit work after a delay. */ @@ -3913,7 +3913,7 @@ struct k_work_delayable { #define Z_WORK_DELAYABLE_INITIALIZER(work_handler) { \ .work = { \ - .handler = work_handler, \ + .handler = (work_handler), \ .flags = K_WORK_DELAYABLE, \ }, \ } @@ -4130,7 +4130,7 @@ struct k_work_user { #define Z_WORK_USER_INITIALIZER(work_handler) \ { \ ._reserved = NULL, \ - .handler = work_handler, \ + .handler = (work_handler), \ .flags = 0 \ } #endif From 8d344cc9d8484767f4d72a0835b5e12a614b5e58 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mo=C5=84?= Date: Wed, 29 May 2024 14:06:25 +0200 Subject: [PATCH 1583/2849] usb: device_next: Rename usbd_contex to usbd_context MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add the missing "t" to struct usbd_contex. No functional changes. Signed-off-by: Tomasz Moń --- cmake/linker_script/common/common-ram.cmake | 2 +- include/zephyr/usb/usbd.h | 66 +++++++++---------- samples/bluetooth/hci_usb/src/main.c | 2 +- samples/subsys/usb/cdc_acm/src/main.c | 4 +- samples/subsys/usb/common/sample_usbd.h | 2 +- samples/subsys/usb/common/sample_usbd_init.c | 8 +-- samples/subsys/usb/console/src/main.c | 2 +- samples/subsys/usb/hid-keyboard/src/main.c | 2 +- samples/subsys/usb/hid-mouse/src/main.c | 2 +- samples/subsys/usb/mass/src/main.c | 2 +- .../usb/uac2_explicit_feedback/src/main.c | 2 +- subsys/usb/device_next/class/bt_hci.c | 6 +- subsys/usb/device_next/class/loopback.c | 2 +- subsys/usb/device_next/class/usbd_cdc_acm.c | 12 ++-- subsys/usb/device_next/class/usbd_cdc_ecm.c | 12 ++-- subsys/usb/device_next/class/usbd_hid.c | 2 +- subsys/usb/device_next/class/usbd_msc.c | 6 +- subsys/usb/device_next/class/usbd_uac2.c | 6 +- subsys/usb/device_next/usbd_ch9.c | 56 ++++++++-------- subsys/usb/device_next/usbd_ch9.h | 20 +++--- subsys/usb/device_next/usbd_class.c | 22 +++---- subsys/usb/device_next/usbd_class.h | 12 ++-- subsys/usb/device_next/usbd_config.c | 20 +++--- subsys/usb/device_next/usbd_config.h | 8 +-- subsys/usb/device_next/usbd_core.c | 14 ++-- subsys/usb/device_next/usbd_data.ld | 2 +- subsys/usb/device_next/usbd_desc.c | 8 +-- subsys/usb/device_next/usbd_desc.h | 4 +- subsys/usb/device_next/usbd_device.c | 28 ++++---- subsys/usb/device_next/usbd_device.h | 18 ++--- subsys/usb/device_next/usbd_endpoint.c | 18 ++--- subsys/usb/device_next/usbd_init.c | 10 +-- subsys/usb/device_next/usbd_init.h | 2 +- subsys/usb/device_next/usbd_interface.c | 10 +-- subsys/usb/device_next/usbd_interface.h | 6 +- subsys/usb/device_next/usbd_msg.c | 10 +-- subsys/usb/device_next/usbd_msg.h | 4 +- subsys/usb/device_next/usbd_shell.c | 6 +- 38 files changed, 209 insertions(+), 209 deletions(-) diff --git a/cmake/linker_script/common/common-ram.cmake b/cmake/linker_script/common/common-ram.cmake index 266f3285b1196..4e160b58ea6a0 100644 --- a/cmake/linker_script/common/common-ram.cmake +++ b/cmake/linker_script/common/common-ram.cmake @@ -116,7 +116,7 @@ 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 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_context 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() diff --git a/include/zephyr/usb/usbd.h b/include/zephyr/usb/usbd.h index 6d697c88869f9..7afc27656ee9d 100644 --- a/include/zephyr/usb/usbd.h +++ b/include/zephyr/usb/usbd.h @@ -199,7 +199,7 @@ struct usbd_status { enum usbd_speed speed : 2; }; -struct usbd_contex; +struct usbd_context; /** * @brief Callback type definition for USB device message delivery @@ -212,7 +212,7 @@ struct usbd_contex; * @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, +typedef void (*usbd_msg_cb_t)(struct usbd_context *const ctx, const struct usbd_msg *const msg); /** @@ -221,7 +221,7 @@ typedef void (*usbd_msg_cb_t)(struct usbd_contex *const ctx, * Main structure that organizes all descriptors, configuration, * and interfaces. An UDC device must be assigned to this structure. */ -struct usbd_contex { +struct usbd_context { /** Name of the USB device */ const char *name; /** Access mutex */ @@ -320,7 +320,7 @@ struct usbd_class_data { /** Name of the USB device class instance */ const char *name; /** Pointer to USB device stack context structure */ - struct usbd_contex *uds_ctx; + struct usbd_context *uds_ctx; /** Pointer to device support class API */ const struct usbd_class_api *api; /** Supported vendor request table, can be NULL */ @@ -368,7 +368,7 @@ struct usbd_class_node { * * @return Pointer to USB device runtime context */ -static inline struct usbd_contex *usbd_class_get_ctx(const struct usbd_class_data *const c_data) +static inline struct usbd_context *usbd_class_get_ctx(const struct usbd_class_data *const c_data) { return c_data->uds_ctx; } @@ -423,7 +423,7 @@ static inline void *usbd_class_get_private(const struct usbd_class_data *const c .iSerialNumber = 0, \ .bNumConfigurations = 0, \ }; \ - static STRUCT_SECTION_ITERABLE(usbd_contex, device_name) = { \ + static STRUCT_SECTION_ITERABLE(usbd_context, device_name) = { \ .name = STRINGIFY(device_name), \ .dev = uhc_dev, \ .fs_desc = &fs_desc_##device_name, \ @@ -609,7 +609,7 @@ static inline void *usbd_class_get_private(const struct usbd_class_data *const c * * @return 0 on success, other values on fail. */ -int usbd_add_descriptor(struct usbd_contex *uds_ctx, +int usbd_add_descriptor(struct usbd_context *uds_ctx, struct usbd_desc_node *dn); /** @@ -639,7 +639,7 @@ void usbd_remove_descriptor(struct usbd_desc_node *const desc_nd); * * @return 0 on success, other values on fail. */ -int usbd_add_configuration(struct usbd_contex *uds_ctx, +int usbd_add_configuration(struct usbd_context *uds_ctx, const enum usbd_speed speed, struct usbd_config_node *cd); @@ -664,7 +664,7 @@ int usbd_add_configuration(struct usbd_contex *uds_ctx, * * @return 0 on success, other values on fail. */ -int usbd_register_class(struct usbd_contex *uds_ctx, +int usbd_register_class(struct usbd_context *uds_ctx, const char *name, const enum usbd_speed speed, uint8_t cfg); @@ -682,7 +682,7 @@ int usbd_register_class(struct usbd_contex *uds_ctx, * * @return 0 on success, other values on fail. */ -int usbd_unregister_class(struct usbd_contex *uds_ctx, +int usbd_unregister_class(struct usbd_context *uds_ctx, const char *name, const enum usbd_speed speed, uint8_t cfg); @@ -694,7 +694,7 @@ int usbd_unregister_class(struct usbd_contex *uds_ctx, * * @return 0 on success, other values on fail. */ -int usbd_msg_register_cb(struct usbd_contex *const uds_ctx, +int usbd_msg_register_cb(struct usbd_context *const uds_ctx, const usbd_msg_cb_t cb); /** @@ -710,7 +710,7 @@ int usbd_msg_register_cb(struct usbd_contex *const uds_ctx, * * @return 0 on success, other values on fail. */ -int usbd_init(struct usbd_contex *uds_ctx); +int usbd_init(struct usbd_context *uds_ctx); /** * @brief Enable the USB device support and registered class instances @@ -721,7 +721,7 @@ int usbd_init(struct usbd_contex *uds_ctx); * * @return 0 on success, other values on fail. */ -int usbd_enable(struct usbd_contex *uds_ctx); +int usbd_enable(struct usbd_context *uds_ctx); /** * @brief Disable the USB device support @@ -732,7 +732,7 @@ int usbd_enable(struct usbd_contex *uds_ctx); * * @return 0 on success, other values on fail. */ -int usbd_disable(struct usbd_contex *uds_ctx); +int usbd_disable(struct usbd_context *uds_ctx); /** * @brief Shutdown the USB device support @@ -743,7 +743,7 @@ int usbd_disable(struct usbd_contex *uds_ctx); * * @return 0 on success, other values on fail. */ -int usbd_shutdown(struct usbd_contex *const uds_ctx); +int usbd_shutdown(struct usbd_context *const uds_ctx); /** * @brief Halt endpoint @@ -753,7 +753,7 @@ int usbd_shutdown(struct usbd_contex *const uds_ctx); * * @return 0 on success, or error from udc_ep_set_halt() */ -int usbd_ep_set_halt(struct usbd_contex *uds_ctx, uint8_t ep); +int usbd_ep_set_halt(struct usbd_context *uds_ctx, uint8_t ep); /** * @brief Clear endpoint halt @@ -763,7 +763,7 @@ int usbd_ep_set_halt(struct usbd_contex *uds_ctx, uint8_t ep); * * @return 0 on success, or error from udc_ep_clear_halt() */ -int usbd_ep_clear_halt(struct usbd_contex *uds_ctx, uint8_t ep); +int usbd_ep_clear_halt(struct usbd_context *uds_ctx, uint8_t ep); /** * @brief Checks whether the endpoint is halted. @@ -773,7 +773,7 @@ int usbd_ep_clear_halt(struct usbd_contex *uds_ctx, uint8_t ep); * * @return true if endpoint is halted, false otherwise */ -bool usbd_ep_is_halted(struct usbd_contex *uds_ctx, uint8_t ep); +bool usbd_ep_is_halted(struct usbd_context *uds_ctx, uint8_t ep); /** * @brief Allocate buffer for USB device request @@ -799,7 +799,7 @@ struct net_buf *usbd_ep_buf_alloc(const struct usbd_class_data *const c_data, * * @return 0 on success, all other values should be treated as error. */ -int usbd_ep_ctrl_enqueue(struct usbd_contex *const uds_ctx, +int usbd_ep_ctrl_enqueue(struct usbd_context *const uds_ctx, struct net_buf *const buf); /** @@ -823,7 +823,7 @@ int usbd_ep_enqueue(const struct usbd_class_data *const c_data, * * @return 0 on success, or error from udc_ep_dequeue() */ -int usbd_ep_dequeue(struct usbd_contex *uds_ctx, const uint8_t ep); +int usbd_ep_dequeue(struct usbd_context *uds_ctx, const uint8_t ep); /** * @brief Free USB device request buffer @@ -835,7 +835,7 @@ int usbd_ep_dequeue(struct usbd_contex *uds_ctx, const uint8_t ep); * * @return 0 on success, all other values should be treated as error. */ -int usbd_ep_buf_free(struct usbd_contex *uds_ctx, struct net_buf *buf); +int usbd_ep_buf_free(struct usbd_context *uds_ctx, struct net_buf *buf); /** * @brief Checks whether the USB device controller is suspended. @@ -844,14 +844,14 @@ int usbd_ep_buf_free(struct usbd_contex *uds_ctx, struct net_buf *buf); * * @return true if endpoint is halted, false otherwise */ -bool usbd_is_suspended(struct usbd_contex *uds_ctx); +bool usbd_is_suspended(struct usbd_context *uds_ctx); /** * @brief Initiate the USB remote wakeup (TBD) * * @return 0 on success, other values on fail. */ -int usbd_wakeup_request(struct usbd_contex *uds_ctx); +int usbd_wakeup_request(struct usbd_context *uds_ctx); /** * @brief Get actual device speed @@ -860,7 +860,7 @@ int usbd_wakeup_request(struct usbd_contex *uds_ctx); * * @return Actual device speed */ -enum usbd_speed usbd_bus_speed(const struct usbd_contex *const uds_ctx); +enum usbd_speed usbd_bus_speed(const struct usbd_context *const uds_ctx); /** * @brief Get highest speed supported by the controller @@ -869,7 +869,7 @@ enum usbd_speed usbd_bus_speed(const struct usbd_contex *const uds_ctx); * * @return Highest supported speed */ -enum usbd_speed usbd_caps_speed(const struct usbd_contex *const uds_ctx); +enum usbd_speed usbd_caps_speed(const struct usbd_context *const uds_ctx); /** * @brief Set USB device descriptor value bcdUSB @@ -880,7 +880,7 @@ enum usbd_speed usbd_caps_speed(const struct usbd_contex *const uds_ctx); * * @return 0 on success, other values on fail. */ -int usbd_device_set_bcd(struct usbd_contex *const uds_ctx, +int usbd_device_set_bcd(struct usbd_context *const uds_ctx, const enum usbd_speed speed, const uint16_t bcd); /** @@ -891,7 +891,7 @@ int usbd_device_set_bcd(struct usbd_contex *const uds_ctx, * * @return 0 on success, other values on fail. */ -int usbd_device_set_vid(struct usbd_contex *const uds_ctx, +int usbd_device_set_vid(struct usbd_context *const uds_ctx, const uint16_t vid); /** @@ -902,7 +902,7 @@ int usbd_device_set_vid(struct usbd_contex *const uds_ctx, * * @return 0 on success, other values on fail. */ -int usbd_device_set_pid(struct usbd_contex *const uds_ctx, +int usbd_device_set_pid(struct usbd_context *const uds_ctx, const uint16_t pid); /** @@ -916,7 +916,7 @@ int usbd_device_set_pid(struct usbd_contex *const uds_ctx, * * @return 0 on success, other values on fail. */ -int usbd_device_set_code_triple(struct usbd_contex *const uds_ctx, +int usbd_device_set_code_triple(struct usbd_context *const uds_ctx, const enum usbd_speed speed, const uint8_t base_class, const uint8_t subclass, const uint8_t protocol); @@ -931,7 +931,7 @@ int usbd_device_set_code_triple(struct usbd_contex *const uds_ctx, * * @return 0 on success, other values on fail. */ -int usbd_config_attrib_rwup(struct usbd_contex *const uds_ctx, +int usbd_config_attrib_rwup(struct usbd_context *const uds_ctx, const enum usbd_speed speed, const uint8_t cfg, const bool enable); @@ -945,7 +945,7 @@ int usbd_config_attrib_rwup(struct usbd_contex *const uds_ctx, * * @return 0 on success, other values on fail. */ -int usbd_config_attrib_self(struct usbd_contex *const uds_ctx, +int usbd_config_attrib_self(struct usbd_context *const uds_ctx, const enum usbd_speed speed, const uint8_t cfg, const bool enable); @@ -959,7 +959,7 @@ int usbd_config_attrib_self(struct usbd_contex *const uds_ctx, * * @return 0 on success, other values on fail. */ -int usbd_config_maxpower(struct usbd_contex *const uds_ctx, +int usbd_config_maxpower(struct usbd_context *const uds_ctx, const enum usbd_speed speed, const uint8_t cfg, const uint8_t power); @@ -975,7 +975,7 @@ int usbd_config_maxpower(struct usbd_contex *const uds_ctx, * * @return true if controller can detect VBUS state change, false otherwise */ -bool usbd_can_detect_vbus(struct usbd_contex *const uds_ctx); +bool usbd_can_detect_vbus(struct usbd_context *const uds_ctx); /** * @} diff --git a/samples/bluetooth/hci_usb/src/main.c b/samples/bluetooth/hci_usb/src/main.c index c27af0e56db3e..18c7f0d5edc51 100644 --- a/samples/bluetooth/hci_usb/src/main.c +++ b/samples/bluetooth/hci_usb/src/main.c @@ -14,7 +14,7 @@ static int enable_usb_device_next(void) { - struct usbd_contex *sample_usbd = sample_usbd_init_device(NULL); + struct usbd_context *sample_usbd = sample_usbd_init_device(NULL); if (sample_usbd == NULL) { printk("Failed to initialize USB device"); diff --git a/samples/subsys/usb/cdc_acm/src/main.c b/samples/subsys/usb/cdc_acm/src/main.c index 91f7a8db7f7af..4dffe7cee6dae 100644 --- a/samples/subsys/usb/cdc_acm/src/main.c +++ b/samples/subsys/usb/cdc_acm/src/main.c @@ -49,10 +49,10 @@ static inline void print_baudrate(const struct device *dev) } #if defined(CONFIG_USB_DEVICE_STACK_NEXT) -static struct usbd_contex *sample_usbd; +static struct usbd_context *sample_usbd; K_SEM_DEFINE(dtr_sem, 0, 1); -static void sample_msg_cb(struct usbd_contex *const ctx, const struct usbd_msg *msg) +static void sample_msg_cb(struct usbd_context *const ctx, const struct usbd_msg *msg) { LOG_INF("USBD message: %s", usbd_msg_type_string(msg->type)); diff --git a/samples/subsys/usb/common/sample_usbd.h b/samples/subsys/usb/common/sample_usbd.h index fe7de6be3f29b..11779fef3f5e9 100644 --- a/samples/subsys/usb/common/sample_usbd.h +++ b/samples/subsys/usb/common/sample_usbd.h @@ -27,6 +27,6 @@ * It returns the configured and initialized USB device context on success, * otherwise it returns NULL. */ -struct usbd_contex *sample_usbd_init_device(usbd_msg_cb_t msg_cb); +struct usbd_context *sample_usbd_init_device(usbd_msg_cb_t msg_cb); #endif /* ZEPHYR_SAMPLES_SUBSYS_USB_COMMON_SAMPLE_USBD_H */ diff --git a/samples/subsys/usb/common/sample_usbd_init.c b/samples/subsys/usb/common/sample_usbd_init.c index 1a712819c5711..14fd43993e664 100644 --- a/samples/subsys/usb/common/sample_usbd_init.c +++ b/samples/subsys/usb/common/sample_usbd_init.c @@ -51,7 +51,7 @@ static const struct usb_bos_capability_lpm bos_cap_lpm = { USBD_DESC_BOS_DEFINE(sample_usbext, sizeof(bos_cap_lpm), &bos_cap_lpm); -static int register_fs_classes(struct usbd_contex *uds_ctx) +static int register_fs_classes(struct usbd_context *uds_ctx) { int err = 0; @@ -71,7 +71,7 @@ static int register_fs_classes(struct usbd_contex *uds_ctx) return err; } -static int register_hs_classes(struct usbd_contex *uds_ctx) +static int register_hs_classes(struct usbd_context *uds_ctx) { int err = 0; @@ -91,7 +91,7 @@ static int register_hs_classes(struct usbd_contex *uds_ctx) return err; } -static int sample_add_configuration(struct usbd_contex *uds_ctx, +static int sample_add_configuration(struct usbd_context *uds_ctx, const enum usbd_speed speed, struct usbd_config_node *config) { @@ -131,7 +131,7 @@ static int sample_add_configuration(struct usbd_contex *uds_ctx, return 0; } -struct usbd_contex *sample_usbd_init_device(usbd_msg_cb_t msg_cb) +struct usbd_context *sample_usbd_init_device(usbd_msg_cb_t msg_cb) { int err; diff --git a/samples/subsys/usb/console/src/main.c b/samples/subsys/usb/console/src/main.c index a248d74d98ebd..538e768614a23 100644 --- a/samples/subsys/usb/console/src/main.c +++ b/samples/subsys/usb/console/src/main.c @@ -16,7 +16,7 @@ BUILD_ASSERT(DT_NODE_HAS_COMPAT(DT_CHOSEN(zephyr_console), zephyr_cdc_acm_uart), "Console device is not ACM CDC UART device"); #if defined(CONFIG_USB_DEVICE_STACK_NEXT) -static struct usbd_contex *sample_usbd; +static struct usbd_context *sample_usbd; static int enable_usb_device_next(void) { diff --git a/samples/subsys/usb/hid-keyboard/src/main.c b/samples/subsys/usb/hid-keyboard/src/main.c index 1a2a146a5a95c..393edfcf06af3 100644 --- a/samples/subsys/usb/hid-keyboard/src/main.c +++ b/samples/subsys/usb/hid-keyboard/src/main.c @@ -143,7 +143,7 @@ struct hid_device_ops kb_ops = { int main(void) { - struct usbd_contex *sample_usbd; + struct usbd_context *sample_usbd; const struct device *hid_dev; int ret; diff --git a/samples/subsys/usb/hid-mouse/src/main.c b/samples/subsys/usb/hid-mouse/src/main.c index c42a96ed47408..28b27877acbaf 100644 --- a/samples/subsys/usb/hid-mouse/src/main.c +++ b/samples/subsys/usb/hid-mouse/src/main.c @@ -99,7 +99,7 @@ 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; + struct usbd_context *sample_usbd; int err; sample_usbd = sample_usbd_init_device(NULL); diff --git a/samples/subsys/usb/mass/src/main.c b/samples/subsys/usb/mass/src/main.c index 0161db85b1f60..51718a9dc8595 100644 --- a/samples/subsys/usb/mass/src/main.c +++ b/samples/subsys/usb/mass/src/main.c @@ -36,7 +36,7 @@ FS_LITTLEFS_DECLARE_DEFAULT_CONFIG(storage); static struct fs_mount_t fs_mnt; #if defined(CONFIG_USB_DEVICE_STACK_NEXT) -static struct usbd_contex *sample_usbd; +static struct usbd_context *sample_usbd; #if CONFIG_DISK_DRIVER_RAM USBD_DEFINE_MSC_LUN(RAM, "Zephyr", "RAMDisk", "0.00"); diff --git a/samples/subsys/usb/uac2_explicit_feedback/src/main.c b/samples/subsys/usb/uac2_explicit_feedback/src/main.c index 4770560886b09..a09cb2d5d85c4 100644 --- a/samples/subsys/usb/uac2_explicit_feedback/src/main.c +++ b/samples/subsys/usb/uac2_explicit_feedback/src/main.c @@ -255,7 +255,7 @@ static struct usb_i2s_ctx main_ctx; int main(void) { const struct device *dev = DEVICE_DT_GET(DT_NODELABEL(uac2_headphones)); - struct usbd_contex *sample_usbd; + struct usbd_context *sample_usbd; struct i2s_config config; int ret; diff --git a/subsys/usb/device_next/class/bt_hci.c b/subsys/usb/device_next/class/bt_hci.c index 7c1c727d8b895..fb45713440d41 100644 --- a/subsys/usb/device_next/class/bt_hci.c +++ b/subsys/usb/device_next/class/bt_hci.c @@ -134,7 +134,7 @@ static uint8_t bt_hci_get_int_in(struct usbd_class_data *const c_data) static uint8_t bt_hci_get_bulk_in(struct usbd_class_data *const c_data) { - struct usbd_contex *uds_ctx = usbd_class_get_ctx(c_data); + struct usbd_context *uds_ctx = usbd_class_get_ctx(c_data); struct bt_hci_data *data = usbd_class_get_private(c_data); struct usbd_bt_hci_desc *desc = data->desc; @@ -147,7 +147,7 @@ static uint8_t bt_hci_get_bulk_in(struct usbd_class_data *const c_data) static uint8_t bt_hci_get_bulk_out(struct usbd_class_data *const c_data) { - struct usbd_contex *uds_ctx = usbd_class_get_ctx(c_data); + struct usbd_context *uds_ctx = usbd_class_get_ctx(c_data); struct bt_hci_data *data = usbd_class_get_private(c_data); struct usbd_bt_hci_desc *desc = data->desc; @@ -370,7 +370,7 @@ static int bt_hci_acl_out_cb(struct usbd_class_data *const c_data, static int bt_hci_request(struct usbd_class_data *const c_data, struct net_buf *buf, int err) { - struct usbd_contex *uds_ctx = usbd_class_get_ctx(c_data); + struct usbd_context *uds_ctx = usbd_class_get_ctx(c_data); struct bt_hci_data *hci_data = usbd_class_get_private(c_data); struct udc_buf_info *bi; diff --git a/subsys/usb/device_next/class/loopback.c b/subsys/usb/device_next/class/loopback.c index edddb867f5563..8a9688dde5384 100644 --- a/subsys/usb/device_next/class/loopback.c +++ b/subsys/usb/device_next/class/loopback.c @@ -112,7 +112,7 @@ static int lb_control_to_dev(struct usbd_class_data *c_data, static int lb_request_handler(struct usbd_class_data *c_data, struct net_buf *buf, int err) { - struct usbd_contex *uds_ctx = usbd_class_get_ctx(c_data); + struct usbd_context *uds_ctx = usbd_class_get_ctx(c_data); struct udc_buf_info *bi = NULL; bi = (struct udc_buf_info *)net_buf_user_data(buf); diff --git a/subsys/usb/device_next/class/usbd_cdc_acm.c b/subsys/usb/device_next/class/usbd_cdc_acm.c index 17e493424e0ee..ad34e7332fec6 100644 --- a/subsys/usb/device_next/class/usbd_cdc_acm.c +++ b/subsys/usb/device_next/class/usbd_cdc_acm.c @@ -143,7 +143,7 @@ static ALWAYS_INLINE bool check_wq_ctx(const struct device *dev) static uint8_t cdc_acm_get_int_in(struct usbd_class_data *const c_data) { - struct usbd_contex *uds_ctx = usbd_class_get_ctx(c_data); + struct usbd_context *uds_ctx = usbd_class_get_ctx(c_data); const struct device *dev = usbd_class_get_private(c_data); struct cdc_acm_uart_data *data = dev->data; struct usbd_cdc_acm_desc *desc = data->desc; @@ -157,7 +157,7 @@ static uint8_t cdc_acm_get_int_in(struct usbd_class_data *const c_data) static uint8_t cdc_acm_get_bulk_in(struct usbd_class_data *const c_data) { - struct usbd_contex *uds_ctx = usbd_class_get_ctx(c_data); + struct usbd_context *uds_ctx = usbd_class_get_ctx(c_data); const struct device *dev = usbd_class_get_private(c_data); struct cdc_acm_uart_data *data = dev->data; struct usbd_cdc_acm_desc *desc = data->desc; @@ -171,7 +171,7 @@ static uint8_t cdc_acm_get_bulk_in(struct usbd_class_data *const c_data) static uint8_t cdc_acm_get_bulk_out(struct usbd_class_data *const c_data) { - struct usbd_contex *uds_ctx = usbd_class_get_ctx(c_data); + struct usbd_context *uds_ctx = usbd_class_get_ctx(c_data); const struct device *dev = usbd_class_get_private(c_data); struct cdc_acm_uart_data *data = dev->data; struct usbd_cdc_acm_desc *desc = data->desc; @@ -185,7 +185,7 @@ static uint8_t cdc_acm_get_bulk_out(struct usbd_class_data *const c_data) static size_t cdc_acm_get_bulk_mps(struct usbd_class_data *const c_data) { - struct usbd_contex *uds_ctx = usbd_class_get_ctx(c_data); + struct usbd_context *uds_ctx = usbd_class_get_ctx(c_data); if (usbd_bus_speed(uds_ctx) == USBD_SPEED_HS) { return 512U; @@ -197,7 +197,7 @@ static size_t cdc_acm_get_bulk_mps(struct usbd_class_data *const c_data) static int usbd_cdc_acm_request(struct usbd_class_data *const c_data, struct net_buf *buf, int err) { - struct usbd_contex *uds_ctx = usbd_class_get_ctx(c_data); + struct usbd_context *uds_ctx = usbd_class_get_ctx(c_data); const struct device *dev = usbd_class_get_private(c_data); struct cdc_acm_uart_data *data = dev->data; struct udc_buf_info *bi; @@ -421,7 +421,7 @@ static int usbd_cdc_acm_ctd(struct usbd_class_data *const c_data, const struct usb_setup_packet *const setup, const struct net_buf *const buf) { - struct usbd_contex *uds_ctx = usbd_class_get_ctx(c_data); + struct usbd_context *uds_ctx = usbd_class_get_ctx(c_data); const struct device *dev = usbd_class_get_private(c_data); struct cdc_acm_uart_data *data = dev->data; size_t len; diff --git a/subsys/usb/device_next/class/usbd_cdc_ecm.c b/subsys/usb/device_next/class/usbd_cdc_ecm.c index 7b3305bf34385..d23c1dd3fe759 100644 --- a/subsys/usb/device_next/class/usbd_cdc_ecm.c +++ b/subsys/usb/device_next/class/usbd_cdc_ecm.c @@ -102,7 +102,7 @@ static uint8_t cdc_ecm_get_ctrl_if(struct cdc_ecm_eth_data *const data) static uint8_t cdc_ecm_get_int_in(struct usbd_class_data *const c_data) { - struct usbd_contex *uds_ctx = usbd_class_get_ctx(c_data); + struct usbd_context *uds_ctx = usbd_class_get_ctx(c_data); const struct device *dev = usbd_class_get_private(c_data); struct cdc_ecm_eth_data *data = dev->data; struct usbd_cdc_ecm_desc *desc = data->desc; @@ -116,7 +116,7 @@ static uint8_t cdc_ecm_get_int_in(struct usbd_class_data *const c_data) static uint8_t cdc_ecm_get_bulk_in(struct usbd_class_data *const c_data) { - struct usbd_contex *uds_ctx = usbd_class_get_ctx(c_data); + struct usbd_context *uds_ctx = usbd_class_get_ctx(c_data); const struct device *dev = usbd_class_get_private(c_data); struct cdc_ecm_eth_data *data = dev->data; struct usbd_cdc_ecm_desc *desc = data->desc; @@ -130,7 +130,7 @@ static uint8_t cdc_ecm_get_bulk_in(struct usbd_class_data *const c_data) static uint16_t cdc_ecm_get_bulk_in_mps(struct usbd_class_data *const c_data) { - struct usbd_contex *uds_ctx = usbd_class_get_ctx(c_data); + struct usbd_context *uds_ctx = usbd_class_get_ctx(c_data); if (usbd_bus_speed(uds_ctx) == USBD_SPEED_HS) { return 512U; @@ -141,7 +141,7 @@ static uint16_t cdc_ecm_get_bulk_in_mps(struct usbd_class_data *const c_data) static uint8_t cdc_ecm_get_bulk_out(struct usbd_class_data *const c_data) { - struct usbd_contex *uds_ctx = usbd_class_get_ctx(c_data); + struct usbd_context *uds_ctx = usbd_class_get_ctx(c_data); const struct device *dev = usbd_class_get_private(c_data); struct cdc_ecm_eth_data *data = dev->data; struct usbd_cdc_ecm_desc *desc = data->desc; @@ -283,7 +283,7 @@ static int cdc_ecm_acl_out_cb(struct usbd_class_data *const c_data, static int usbd_cdc_ecm_request(struct usbd_class_data *const c_data, struct net_buf *buf, int err) { - struct usbd_contex *uds_ctx = usbd_class_get_ctx(c_data); + struct usbd_context *uds_ctx = usbd_class_get_ctx(c_data); const struct device *dev = usbd_class_get_private(c_data); struct cdc_ecm_eth_data *data = dev->data; struct udc_buf_info *bi; @@ -442,7 +442,7 @@ static int usbd_cdc_ecm_ctd(struct usbd_class_data *const c_data, static int usbd_cdc_ecm_init(struct usbd_class_data *const c_data) { - struct usbd_contex *uds_ctx = usbd_class_get_ctx(c_data); + struct usbd_context *uds_ctx = usbd_class_get_ctx(c_data); const struct device *dev = usbd_class_get_private(c_data); struct cdc_ecm_eth_data *const data = dev->data; struct usbd_cdc_ecm_desc *desc = data->desc; diff --git a/subsys/usb/device_next/class/usbd_hid.c b/subsys/usb/device_next/class/usbd_hid.c index befdc9db9ccc9..6fef55df27f39 100644 --- a/subsys/usb/device_next/class/usbd_hid.c +++ b/subsys/usb/device_next/class/usbd_hid.c @@ -98,7 +98,7 @@ static inline uint8_t hid_get_out_ep(struct usbd_class_data *const c_data) 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); + struct usbd_context *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; diff --git a/subsys/usb/device_next/class/usbd_msc.c b/subsys/usb/device_next/class/usbd_msc.c index 1cf23170b1a7f..a608a2da61adb 100644 --- a/subsys/usb/device_next/class/usbd_msc.c +++ b/subsys/usb/device_next/class/usbd_msc.c @@ -146,7 +146,7 @@ static struct net_buf *msc_buf_alloc(const uint8_t ep) static uint8_t msc_get_bulk_in(struct usbd_class_data *const c_data) { - struct usbd_contex *uds_ctx = usbd_class_get_ctx(c_data); + struct usbd_context *uds_ctx = usbd_class_get_ctx(c_data); struct msc_bot_ctx *ctx = usbd_class_get_private(c_data); struct msc_bot_desc *desc = ctx->desc; @@ -159,7 +159,7 @@ static uint8_t msc_get_bulk_in(struct usbd_class_data *const c_data) static uint8_t msc_get_bulk_out(struct usbd_class_data *const c_data) { - struct usbd_contex *uds_ctx = usbd_class_get_ctx(c_data); + struct usbd_context *uds_ctx = usbd_class_get_ctx(c_data); struct msc_bot_ctx *ctx = usbd_class_get_private(c_data); struct msc_bot_desc *desc = ctx->desc; @@ -566,7 +566,7 @@ static void msc_send_csw(struct msc_bot_ctx *ctx) static void usbd_msc_handle_request(struct usbd_class_data *c_data, struct net_buf *buf, int err) { - struct usbd_contex *uds_ctx = usbd_class_get_ctx(c_data); + struct usbd_context *uds_ctx = usbd_class_get_ctx(c_data); struct msc_bot_ctx *ctx = usbd_class_get_private(c_data); struct udc_buf_info *bi; diff --git a/subsys/usb/device_next/class/usbd_uac2.c b/subsys/usb/device_next/class/usbd_uac2.c index 46a28951a8abc..ab1d9d849b0aa 100644 --- a/subsys/usb/device_next/class/usbd_uac2.c +++ b/subsys/usb/device_next/class/usbd_uac2.c @@ -337,7 +337,7 @@ static void write_explicit_feedback(struct usbd_class_data *const c_data, uint8_t ep, uint8_t terminal) { const struct device *dev = usbd_class_get_private(c_data); - struct usbd_contex *uds_ctx = usbd_class_get_ctx(c_data); + struct usbd_context *uds_ctx = usbd_class_get_ctx(c_data); struct uac2_ctx *ctx = dev->data; struct net_buf *buf; struct udc_buf_info *bi; @@ -382,7 +382,7 @@ void uac2_update(struct usbd_class_data *const c_data, uint8_t iface, uint8_t alternate) { const struct device *dev = usbd_class_get_private(c_data); - struct usbd_contex *uds_ctx = usbd_class_get_ctx(c_data); + struct usbd_context *uds_ctx = usbd_class_get_ctx(c_data); const struct uac2_cfg *cfg = dev->config; struct uac2_ctx *ctx = dev->data; const struct usb_association_descriptor *iad; @@ -568,7 +568,7 @@ static int uac2_request(struct usbd_class_data *const c_data, struct net_buf *bu const struct device *dev = usbd_class_get_private(c_data); const struct uac2_cfg *cfg = dev->config; struct uac2_ctx *ctx = dev->data; - struct usbd_contex *uds_ctx = usbd_class_get_ctx(c_data); + struct usbd_context *uds_ctx = usbd_class_get_ctx(c_data); struct udc_buf_info *bi; uint8_t ep, terminal; uint16_t mps; diff --git a/subsys/usb/device_next/usbd_ch9.c b/subsys/usb/device_next/usbd_ch9.c index e6f2287283162..d3eebcaccc5bd 100644 --- a/subsys/usb/device_next/usbd_ch9.c +++ b/subsys/usb/device_next/usbd_ch9.c @@ -29,7 +29,7 @@ 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, +static int nonstd_request(struct usbd_context *const uds_ctx, struct net_buf *const dbuf); static bool reqtype_is_to_host(const struct usb_setup_packet *const setup) @@ -42,18 +42,18 @@ static bool reqtype_is_to_device(const struct usb_setup_packet *const setup) return !reqtype_is_to_host(setup); } -static void ch9_set_ctrl_type(struct usbd_contex *const uds_ctx, +static void ch9_set_ctrl_type(struct usbd_context *const uds_ctx, const int type) { uds_ctx->ch9_data.ctrl_type = type; } -static int ch9_get_ctrl_type(struct usbd_contex *const uds_ctx) +static int ch9_get_ctrl_type(struct usbd_context *const uds_ctx) { return uds_ctx->ch9_data.ctrl_type; } -static int post_status_stage(struct usbd_contex *const uds_ctx) +static int post_status_stage(struct usbd_context *const uds_ctx) { struct usb_setup_packet *setup = usbd_get_setup_pkt(uds_ctx); int ret = 0; @@ -80,7 +80,7 @@ static int post_status_stage(struct usbd_contex *const uds_ctx) return ret; } -static int sreq_set_address(struct usbd_contex *const uds_ctx) +static int sreq_set_address(struct usbd_context *const uds_ctx) { struct usb_setup_packet *setup = usbd_get_setup_pkt(uds_ctx); struct udc_device_caps caps = udc_caps(uds_ctx->dev); @@ -123,7 +123,7 @@ static int sreq_set_address(struct usbd_contex *const uds_ctx) return 0; } -static int sreq_set_configuration(struct usbd_contex *const uds_ctx) +static int sreq_set_configuration(struct usbd_context *const uds_ctx) { struct usb_setup_packet *setup = usbd_get_setup_pkt(uds_ctx); const enum usbd_speed speed = usbd_bus_speed(uds_ctx); @@ -174,7 +174,7 @@ static int sreq_set_configuration(struct usbd_contex *const uds_ctx) return ret; } -static int sreq_set_interface(struct usbd_contex *const uds_ctx) +static int sreq_set_interface(struct usbd_context *const uds_ctx) { struct usb_setup_packet *setup = usbd_get_setup_pkt(uds_ctx); int ret; @@ -210,7 +210,7 @@ static int sreq_set_interface(struct usbd_contex *const uds_ctx) return ret; } -static void sreq_feature_halt_notify(struct usbd_contex *const uds_ctx, +static void sreq_feature_halt_notify(struct usbd_context *const uds_ctx, const uint8_t ep, const bool halted) { struct usbd_class_node *c_nd = usbd_class_get_by_ep(uds_ctx, ep); @@ -220,7 +220,7 @@ static void sreq_feature_halt_notify(struct usbd_contex *const uds_ctx, } } -static int sreq_clear_feature(struct usbd_contex *const uds_ctx) +static int sreq_clear_feature(struct usbd_context *const uds_ctx) { struct usb_setup_packet *setup = usbd_get_setup_pkt(uds_ctx); uint8_t ep = setup->wIndex; @@ -275,7 +275,7 @@ static int sreq_clear_feature(struct usbd_contex *const uds_ctx) return ret; } -static int set_feature_test_mode(struct usbd_contex *const uds_ctx) +static int set_feature_test_mode(struct usbd_context *const uds_ctx) { struct usb_setup_packet *setup = usbd_get_setup_pkt(uds_ctx); uint8_t mode = SF_TEST_MODE_SELECTOR(setup->wIndex); @@ -296,7 +296,7 @@ static int set_feature_test_mode(struct usbd_contex *const uds_ctx) return 0; } -static int sreq_set_feature(struct usbd_contex *const uds_ctx) +static int sreq_set_feature(struct usbd_context *const uds_ctx) { struct usb_setup_packet *setup = usbd_get_setup_pkt(uds_ctx); uint8_t ep = setup->wIndex; @@ -358,7 +358,7 @@ static int sreq_set_feature(struct usbd_contex *const uds_ctx) return ret; } -static int std_request_to_device(struct usbd_contex *const uds_ctx, +static int std_request_to_device(struct usbd_context *const uds_ctx, struct net_buf *const buf) { struct usb_setup_packet *setup = usbd_get_setup_pkt(uds_ctx); @@ -389,7 +389,7 @@ static int std_request_to_device(struct usbd_contex *const uds_ctx, return ret; } -static int sreq_get_status(struct usbd_contex *const uds_ctx, +static int sreq_get_status(struct usbd_context *const uds_ctx, struct net_buf *const buf) { struct usb_setup_packet *setup = usbd_get_setup_pkt(uds_ctx); @@ -449,7 +449,7 @@ static int sreq_get_status(struct usbd_contex *const uds_ctx, * This function handles configuration and USB2.0 other-speed-configuration * descriptor type requests. */ -static int sreq_get_desc_cfg(struct usbd_contex *const uds_ctx, +static int sreq_get_desc_cfg(struct usbd_context *const uds_ctx, struct net_buf *const buf, const uint8_t idx, const bool other_cfg) @@ -601,7 +601,7 @@ static void string_ascii7_to_utf16le(struct usbd_desc_node *const dn, } } -static int sreq_get_desc_dev(struct usbd_contex *const uds_ctx, +static int sreq_get_desc_dev(struct usbd_context *const uds_ctx, struct net_buf *const buf) { struct usb_setup_packet *setup = usbd_get_setup_pkt(uds_ctx); @@ -627,7 +627,7 @@ static int sreq_get_desc_dev(struct usbd_contex *const uds_ctx, return 0; } -static int sreq_get_desc_str(struct usbd_contex *const uds_ctx, +static int sreq_get_desc_str(struct usbd_context *const uds_ctx, struct net_buf *const buf, const uint8_t idx) { struct usb_setup_packet *setup = usbd_get_setup_pkt(uds_ctx); @@ -659,7 +659,7 @@ static int sreq_get_desc_str(struct usbd_contex *const uds_ctx, return 0; } -static int sreq_get_dev_qualifier(struct usbd_contex *const uds_ctx, +static int sreq_get_dev_qualifier(struct usbd_context *const uds_ctx, struct net_buf *const buf) { struct usb_setup_packet *setup = usbd_get_setup_pkt(uds_ctx); @@ -696,7 +696,7 @@ 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, +static void desc_fill_bos_root(struct usbd_context *const uds_ctx, struct usb_bos_descriptor *const root) { struct usbd_desc_node *desc_nd; @@ -714,7 +714,7 @@ static void desc_fill_bos_root(struct usbd_contex *const uds_ctx, } } -static int sreq_get_desc_bos(struct usbd_contex *const uds_ctx, +static int sreq_get_desc_bos(struct usbd_context *const uds_ctx, struct net_buf *const buf) { struct usb_setup_packet *setup = usbd_get_setup_pkt(uds_ctx); @@ -769,7 +769,7 @@ static int sreq_get_desc_bos(struct usbd_contex *const uds_ctx, return 0; } -static int sreq_get_descriptor(struct usbd_contex *const uds_ctx, +static int sreq_get_descriptor(struct usbd_context *const uds_ctx, struct net_buf *const buf) { struct usb_setup_packet *setup = usbd_get_setup_pkt(uds_ctx); @@ -812,7 +812,7 @@ static int sreq_get_descriptor(struct usbd_contex *const uds_ctx, return 0; } -static int sreq_get_configuration(struct usbd_contex *const uds_ctx, +static int sreq_get_configuration(struct usbd_context *const uds_ctx, struct net_buf *const buf) { @@ -840,7 +840,7 @@ static int sreq_get_configuration(struct usbd_contex *const uds_ctx, return 0; } -static int sreq_get_interface(struct usbd_contex *const uds_ctx, +static int sreq_get_interface(struct usbd_context *const uds_ctx, struct net_buf *const buf) { struct usb_setup_packet *setup = usbd_get_setup_pkt(uds_ctx); @@ -885,7 +885,7 @@ static int sreq_get_interface(struct usbd_contex *const uds_ctx, return 0; } -static int std_request_to_host(struct usbd_contex *const uds_ctx, +static int std_request_to_host(struct usbd_context *const uds_ctx, struct net_buf *const buf) { struct usb_setup_packet *setup = usbd_get_setup_pkt(uds_ctx); @@ -913,7 +913,7 @@ static int std_request_to_host(struct usbd_contex *const uds_ctx, return ret; } -static int nonstd_request(struct usbd_contex *const uds_ctx, +static int nonstd_request(struct usbd_context *const uds_ctx, struct net_buf *const dbuf) { struct usb_setup_packet *setup = usbd_get_setup_pkt(uds_ctx); @@ -947,7 +947,7 @@ static int nonstd_request(struct usbd_contex *const uds_ctx, return ret; } -static int handle_setup_request(struct usbd_contex *const uds_ctx, +static int handle_setup_request(struct usbd_context *const uds_ctx, struct net_buf *const buf) { struct usb_setup_packet *setup = usbd_get_setup_pkt(uds_ctx); @@ -987,7 +987,7 @@ static int handle_setup_request(struct usbd_contex *const uds_ctx, return ret; } -static int ctrl_xfer_get_setup(struct usbd_contex *const uds_ctx, +static int ctrl_xfer_get_setup(struct usbd_context *const uds_ctx, struct net_buf *const buf) { struct usb_setup_packet *setup = usbd_get_setup_pkt(uds_ctx); @@ -1061,7 +1061,7 @@ static struct net_buf *spool_data_out(struct net_buf *const buf) return NULL; } -int usbd_handle_ctrl_xfer(struct usbd_contex *const uds_ctx, +int usbd_handle_ctrl_xfer(struct usbd_context *const uds_ctx, struct net_buf *const buf, const int err) { struct usb_setup_packet *setup = usbd_get_setup_pkt(uds_ctx); @@ -1193,7 +1193,7 @@ int usbd_handle_ctrl_xfer(struct usbd_contex *const uds_ctx, return ret; } -int usbd_init_control_pipe(struct usbd_contex *const uds_ctx) +int usbd_init_control_pipe(struct usbd_context *const uds_ctx) { uds_ctx->ch9_data.state = USBD_STATE_DEFAULT; ch9_set_ctrl_type(uds_ctx, CTRL_AWAIT_SETUP_DATA); diff --git a/subsys/usb/device_next/usbd_ch9.h b/subsys/usb/device_next/usbd_ch9.h index 657e492f33adf..168baa024d7e2 100644 --- a/subsys/usb/device_next/usbd_ch9.h +++ b/subsys/usb/device_next/usbd_ch9.h @@ -16,7 +16,7 @@ * * @return true if USB device is in default state, false otherwise */ -static inline bool usbd_state_is_default(const struct usbd_contex *const uds_ctx) +static inline bool usbd_state_is_default(const struct usbd_context *const uds_ctx) { return (uds_ctx->ch9_data.state == USBD_STATE_DEFAULT) ? true : false; } @@ -28,7 +28,7 @@ static inline bool usbd_state_is_default(const struct usbd_contex *const uds_ctx * * @return true if USB device is in address state, false otherwise */ -static inline bool usbd_state_is_address(const struct usbd_contex *const uds_ctx) +static inline bool usbd_state_is_address(const struct usbd_context *const uds_ctx) { return (uds_ctx->ch9_data.state == USBD_STATE_ADDRESS) ? true : false; } @@ -40,7 +40,7 @@ static inline bool usbd_state_is_address(const struct usbd_contex *const uds_ctx * * @return true if USB device is in configured state, false otherwise */ -static inline bool usbd_state_is_configured(const struct usbd_contex *const uds_ctx) +static inline bool usbd_state_is_configured(const struct usbd_context *const uds_ctx) { return (uds_ctx->ch9_data.state == USBD_STATE_CONFIGURED) ? true : false; } @@ -52,7 +52,7 @@ static inline bool usbd_state_is_configured(const struct usbd_contex *const uds_ * * @return current configuration value */ -static inline uint8_t usbd_get_config_value(const struct usbd_contex *const uds_ctx) +static inline uint8_t usbd_get_config_value(const struct usbd_context *const uds_ctx) { return uds_ctx->ch9_data.configuration; } @@ -63,7 +63,7 @@ static inline uint8_t usbd_get_config_value(const struct usbd_contex *const uds_ * @param[in] uds_ctx Pointer to a device context * @param[in] value New configuration value */ -static inline void usbd_set_config_value(struct usbd_contex *const uds_ctx, +static inline void usbd_set_config_value(struct usbd_context *const uds_ctx, const uint8_t value) { uds_ctx->ch9_data.configuration = value; @@ -78,7 +78,7 @@ static inline void usbd_set_config_value(struct usbd_contex *const uds_ctx, * * @return 0 on success, other values on fail. */ -static inline int usbd_get_alt_value(const struct usbd_contex *const uds_ctx, +static inline int usbd_get_alt_value(const struct usbd_context *const uds_ctx, const uint8_t iface, uint8_t *const alt) { @@ -100,7 +100,7 @@ static inline int usbd_get_alt_value(const struct usbd_contex *const uds_ctx, * * @return 0 on success, other values on fail. */ -static inline int usbd_set_alt_value(struct usbd_contex *const uds_ctx, +static inline int usbd_set_alt_value(struct usbd_context *const uds_ctx, const uint8_t iface, const uint8_t alt) { @@ -121,7 +121,7 @@ static inline int usbd_set_alt_value(struct usbd_contex *const uds_ctx, * @return Pointer to last received setup packet */ static inline struct usb_setup_packet * -usbd_get_setup_pkt(struct usbd_contex *const uds_ctx) +usbd_get_setup_pkt(struct usbd_context *const uds_ctx) { return &uds_ctx->ch9_data.setup; } @@ -135,7 +135,7 @@ usbd_get_setup_pkt(struct usbd_contex *const uds_ctx) * * @return 0 on success, other values on fail. */ -int usbd_handle_ctrl_xfer(struct usbd_contex *uds_ctx, +int usbd_handle_ctrl_xfer(struct usbd_context *uds_ctx, struct net_buf *buf, int err); /** @@ -145,7 +145,7 @@ int usbd_handle_ctrl_xfer(struct usbd_contex *uds_ctx, * * @return 0 on success, other values on fail. */ -int usbd_init_control_pipe(struct usbd_contex *uds_ctx); +int usbd_init_control_pipe(struct usbd_context *uds_ctx); #endif /* ZEPHYR_INCLUDE_USBD_CH9_H */ diff --git a/subsys/usb/device_next/usbd_class.c b/subsys/usb/device_next/usbd_class.c index 4217019b51474..265bffbe947a2 100644 --- a/subsys/usb/device_next/usbd_class.c +++ b/subsys/usb/device_next/usbd_class.c @@ -44,7 +44,7 @@ size_t usbd_class_desc_len(struct usbd_class_data *const c_data, } struct usbd_class_node * -usbd_class_get_by_config(struct usbd_contex *const uds_ctx, +usbd_class_get_by_config(struct usbd_context *const uds_ctx, const enum usbd_speed speed, const uint8_t cnum, const uint8_t inum) @@ -67,7 +67,7 @@ usbd_class_get_by_config(struct usbd_contex *const uds_ctx, } struct usbd_class_node * -usbd_class_get_by_iface(struct usbd_contex *const uds_ctx, +usbd_class_get_by_iface(struct usbd_context *const uds_ctx, const uint8_t inum) { struct usbd_class_node *c_nd; @@ -87,7 +87,7 @@ usbd_class_get_by_iface(struct usbd_contex *const uds_ctx, return NULL; } -static bool xfer_owner_exist(struct usbd_contex *const uds_ctx, +static bool xfer_owner_exist(struct usbd_context *const uds_ctx, struct usbd_config_node *const cfg_nd, struct net_buf *const buf) { @@ -114,7 +114,7 @@ static bool xfer_owner_exist(struct usbd_contex *const uds_ctx, return false; } -int usbd_class_handle_xfer(struct usbd_contex *const uds_ctx, +int usbd_class_handle_xfer(struct usbd_context *const uds_ctx, struct net_buf *const buf, const int err) { @@ -137,7 +137,7 @@ int usbd_class_handle_xfer(struct usbd_contex *const uds_ctx, } struct usbd_class_node * -usbd_class_get_by_ep(struct usbd_contex *const uds_ctx, +usbd_class_get_by_ep(struct usbd_context *const uds_ctx, const uint8_t ep) { struct usbd_class_node *c_nd; @@ -175,7 +175,7 @@ usbd_class_get_by_ep(struct usbd_contex *const uds_ctx, } struct usbd_class_node * -usbd_class_get_by_req(struct usbd_contex *const uds_ctx, +usbd_class_get_by_req(struct usbd_context *const uds_ctx, const uint8_t request) { struct usbd_config_node *cfg_nd; @@ -229,7 +229,7 @@ usbd_class_node_get(const char *name, const enum usbd_speed speed) return NULL; } -static int usbd_class_append(struct usbd_contex *const uds_ctx, +static int usbd_class_append(struct usbd_context *const uds_ctx, struct usbd_class_node *const c_nd, const enum usbd_speed speed, const uint8_t cfg) @@ -246,7 +246,7 @@ static int usbd_class_append(struct usbd_contex *const uds_ctx, return 0; } -static int usbd_class_remove(struct usbd_contex *const uds_ctx, +static int usbd_class_remove(struct usbd_context *const uds_ctx, struct usbd_class_node *const c_nd, const enum usbd_speed speed, const uint8_t cfg) @@ -265,7 +265,7 @@ static int usbd_class_remove(struct usbd_contex *const uds_ctx, return 0; } -int usbd_class_remove_all(struct usbd_contex *const uds_ctx, +int usbd_class_remove_all(struct usbd_context *const uds_ctx, const enum usbd_speed speed, const uint8_t cfg) { @@ -292,7 +292,7 @@ int usbd_class_remove_all(struct usbd_contex *const uds_ctx, * All the functions below are part of public USB device support API. */ -int usbd_register_class(struct usbd_contex *const uds_ctx, +int usbd_register_class(struct usbd_context *const uds_ctx, const char *name, const enum usbd_speed speed, const uint8_t cfg) { @@ -340,7 +340,7 @@ int usbd_register_class(struct usbd_contex *const uds_ctx, return ret; } -int usbd_unregister_class(struct usbd_contex *const uds_ctx, +int usbd_unregister_class(struct usbd_context *const uds_ctx, const char *name, const enum usbd_speed speed, const uint8_t cfg) { diff --git a/subsys/usb/device_next/usbd_class.h b/subsys/usb/device_next/usbd_class.h index e89470cb0e013..4952af53d0e62 100644 --- a/subsys/usb/device_next/usbd_class.h +++ b/subsys/usb/device_next/usbd_class.h @@ -18,7 +18,7 @@ * * @return usbd_class_request() return value */ -int usbd_class_handle_xfer(struct usbd_contex *const uds_ctx, +int usbd_class_handle_xfer(struct usbd_context *const uds_ctx, struct net_buf *const buf, const int err); @@ -47,7 +47,7 @@ size_t usbd_class_desc_len(struct usbd_class_data *const c_data, * * @return Class c_nd pointer or NULL */ -struct usbd_class_node *usbd_class_get_by_iface(struct usbd_contex *uds_ctx, +struct usbd_class_node *usbd_class_get_by_iface(struct usbd_context *uds_ctx, uint8_t i_n); /** @@ -60,7 +60,7 @@ struct usbd_class_node *usbd_class_get_by_iface(struct usbd_contex *uds_ctx, * * @return Class c_nd pointer or NULL */ -struct usbd_class_node *usbd_class_get_by_config(struct usbd_contex *uds_ctx, +struct usbd_class_node *usbd_class_get_by_config(struct usbd_context *uds_ctx, const enum usbd_speed speed, uint8_t cnum, uint8_t inum); @@ -75,7 +75,7 @@ struct usbd_class_node *usbd_class_get_by_config(struct usbd_contex *uds_ctx, * * @return Class c_nd pointer or NULL */ -struct usbd_class_node *usbd_class_get_by_ep(struct usbd_contex *uds_ctx, +struct usbd_class_node *usbd_class_get_by_ep(struct usbd_context *uds_ctx, uint8_t ep); /** @@ -92,7 +92,7 @@ struct usbd_class_node *usbd_class_get_by_ep(struct usbd_contex *uds_ctx, * * @return Class c_nd pointer or NULL */ -struct usbd_class_node *usbd_class_get_by_req(struct usbd_contex *uds_ctx, +struct usbd_class_node *usbd_class_get_by_req(struct usbd_context *uds_ctx, uint8_t request); /** @@ -104,7 +104,7 @@ struct usbd_class_node *usbd_class_get_by_req(struct usbd_contex *uds_ctx, * * @return 0 on success, other values on fail. */ -int usbd_class_remove_all(struct usbd_contex *const uds_ctx, +int usbd_class_remove_all(struct usbd_context *const uds_ctx, const enum usbd_speed speed, const uint8_t cfg); diff --git a/subsys/usb/device_next/usbd_config.c b/subsys/usb/device_next/usbd_config.c index 6162c4c14612d..25a2a082bc7e2 100644 --- a/subsys/usb/device_next/usbd_config.c +++ b/subsys/usb/device_next/usbd_config.c @@ -16,7 +16,7 @@ #include LOG_MODULE_REGISTER(usbd_cfg, CONFIG_USBD_LOG_LEVEL); -static sys_slist_t *usbd_configs(struct usbd_contex *uds_ctx, +static sys_slist_t *usbd_configs(struct usbd_context *uds_ctx, const enum usbd_speed speed) { switch (speed) { @@ -29,7 +29,7 @@ static sys_slist_t *usbd_configs(struct usbd_contex *uds_ctx, } } -struct usbd_config_node *usbd_config_get(struct usbd_contex *const uds_ctx, +struct usbd_config_node *usbd_config_get(struct usbd_context *const uds_ctx, const enum usbd_speed speed, const uint8_t cfg) { @@ -45,7 +45,7 @@ struct usbd_config_node *usbd_config_get(struct usbd_contex *const uds_ctx, } struct usbd_config_node * -usbd_config_get_current(struct usbd_contex *const uds_ctx) +usbd_config_get_current(struct usbd_context *const uds_ctx) { if (!usbd_state_is_configured(uds_ctx)) { LOG_INF("No configuration set (Address state?)"); @@ -71,7 +71,7 @@ static void usbd_config_classes_enable(struct usbd_config_node *const cfg_nd, } /* Reset configuration to addressed state, shutdown all endpoints */ -static int usbd_config_reset(struct usbd_contex *const uds_ctx) +static int usbd_config_reset(struct usbd_context *const uds_ctx) { struct usbd_config_node *cfg_nd; int ret = 0; @@ -92,7 +92,7 @@ static int usbd_config_reset(struct usbd_contex *const uds_ctx) return ret; } -bool usbd_config_exist(struct usbd_contex *const uds_ctx, +bool usbd_config_exist(struct usbd_context *const uds_ctx, const enum usbd_speed speed, const uint8_t cfg) { @@ -103,7 +103,7 @@ bool usbd_config_exist(struct usbd_contex *const uds_ctx, return (config != NULL) ? true : false; } -int usbd_config_set(struct usbd_contex *const uds_ctx, +int usbd_config_set(struct usbd_context *const uds_ctx, const uint8_t new_cfg) { struct usbd_config_node *cfg_nd; @@ -143,7 +143,7 @@ int usbd_config_set(struct usbd_contex *const uds_ctx, * All the functions below are part of public USB device support API. */ -int usbd_config_attrib_rwup(struct usbd_contex *const uds_ctx, +int usbd_config_attrib_rwup(struct usbd_context *const uds_ctx, const enum usbd_speed speed, const uint8_t cfg, const bool enable) { @@ -185,7 +185,7 @@ int usbd_config_attrib_rwup(struct usbd_contex *const uds_ctx, return ret; } -int usbd_config_attrib_self(struct usbd_contex *const uds_ctx, +int usbd_config_attrib_self(struct usbd_context *const uds_ctx, const enum usbd_speed speed, const uint8_t cfg, const bool enable) { @@ -219,7 +219,7 @@ int usbd_config_attrib_self(struct usbd_contex *const uds_ctx, return ret; } -int usbd_config_maxpower(struct usbd_contex *const uds_ctx, +int usbd_config_maxpower(struct usbd_context *const uds_ctx, const enum usbd_speed speed, const uint8_t cfg, const uint8_t power) { @@ -249,7 +249,7 @@ int usbd_config_maxpower(struct usbd_contex *const uds_ctx, return ret; } -int usbd_add_configuration(struct usbd_contex *const uds_ctx, +int usbd_add_configuration(struct usbd_context *const uds_ctx, const enum usbd_speed speed, struct usbd_config_node *const cfg_nd) { diff --git a/subsys/usb/device_next/usbd_config.h b/subsys/usb/device_next/usbd_config.h index f042446f4a12d..6e1aac8b7629e 100644 --- a/subsys/usb/device_next/usbd_config.h +++ b/subsys/usb/device_next/usbd_config.h @@ -47,7 +47,7 @@ static inline void usbd_config_set_value(const struct usbd_config_node *const cf * * @return pointer to configuration node or NULL if does not exist */ -struct usbd_config_node *usbd_config_get(struct usbd_contex *uds_ctx, +struct usbd_config_node *usbd_config_get(struct usbd_context *uds_ctx, const enum usbd_speed speed, uint8_t cfg); @@ -60,7 +60,7 @@ struct usbd_config_node *usbd_config_get(struct usbd_contex *uds_ctx, * * @return pointer to configuration node or NULL if does not exist */ -struct usbd_config_node *usbd_config_get_current(struct usbd_contex *uds_ctx); +struct usbd_config_node *usbd_config_get_current(struct usbd_context *uds_ctx); /** * @brief Check whether a configuration exist @@ -71,7 +71,7 @@ struct usbd_config_node *usbd_config_get_current(struct usbd_contex *uds_ctx); * * @return True if a configuration exist. */ -bool usbd_config_exist(struct usbd_contex *const uds_ctx, +bool usbd_config_exist(struct usbd_context *const uds_ctx, const enum usbd_speed speed, const uint8_t cfg); @@ -87,6 +87,6 @@ bool usbd_config_exist(struct usbd_contex *const uds_ctx, * * @return 0 on success, other values on fail. */ -int usbd_config_set(struct usbd_contex *uds_ctx, uint8_t new_cfg); +int usbd_config_set(struct usbd_context *uds_ctx, uint8_t new_cfg); #endif /* ZEPHYR_INCLUDE_USBD_CONFIG_H */ diff --git a/subsys/usb/device_next/usbd_core.c b/subsys/usb/device_next/usbd_core.c index 40999b0f7e4fa..4bdebd6fc6877 100644 --- a/subsys/usb/device_next/usbd_core.c +++ b/subsys/usb/device_next/usbd_core.c @@ -37,7 +37,7 @@ static int usbd_event_carrier(const struct device *dev, return k_msgq_put(&usbd_msgq, event, K_NO_WAIT); } -static int event_handler_ep_request(struct usbd_contex *const uds_ctx, +static int event_handler_ep_request(struct usbd_context *const uds_ctx, const struct udc_event *const event) { struct udc_buf_info *bi; @@ -59,7 +59,7 @@ static int event_handler_ep_request(struct usbd_contex *const uds_ctx, return ret; } -static void usbd_class_bcast_event(struct usbd_contex *const uds_ctx, +static void usbd_class_bcast_event(struct usbd_context *const uds_ctx, struct udc_event *const event) { struct usbd_config_node *cfg_nd; @@ -92,7 +92,7 @@ static void usbd_class_bcast_event(struct usbd_contex *const uds_ctx, } } -static int event_handler_bus_reset(struct usbd_contex *const uds_ctx) +static int event_handler_bus_reset(struct usbd_context *const uds_ctx) { enum udc_bus_speed udc_speed; int ret; @@ -131,7 +131,7 @@ static int event_handler_bus_reset(struct usbd_contex *const uds_ctx) } -static ALWAYS_INLINE void usbd_event_handler(struct usbd_contex *const uds_ctx, +static ALWAYS_INLINE void usbd_event_handler(struct usbd_context *const uds_ctx, struct udc_event *const event) { int err = 0; @@ -192,7 +192,7 @@ static void usbd_thread(void *p1, void *p2, void *p3) while (true) { k_msgq_get(&usbd_msgq, &event, K_FOREVER); - STRUCT_SECTION_FOREACH(usbd_contex, uds_ctx) { + STRUCT_SECTION_FOREACH(usbd_context, uds_ctx) { if (uds_ctx->dev == event.dev) { usbd_event_handler(uds_ctx, &event); } @@ -200,7 +200,7 @@ static void usbd_thread(void *p1, void *p2, void *p3) } } -int usbd_device_init_core(struct usbd_contex *const uds_ctx) +int usbd_device_init_core(struct usbd_context *const uds_ctx) { int ret; @@ -221,7 +221,7 @@ int usbd_device_init_core(struct usbd_contex *const uds_ctx) return ret; } -int usbd_device_shutdown_core(struct usbd_contex *const uds_ctx) +int usbd_device_shutdown_core(struct usbd_context *const uds_ctx) { struct usbd_config_node *cfg_nd; int ret; diff --git a/subsys/usb/device_next/usbd_data.ld b/subsys/usb/device_next/usbd_data.ld index 403820314224d..2c672d7224f0d 100644 --- a/subsys/usb/device_next/usbd_data.ld +++ b/subsys/usb/device_next/usbd_data.ld @@ -1,5 +1,5 @@ #include -ITERABLE_SECTION_RAM(usbd_contex, Z_LINK_ITERABLE_SUBALIGN) +ITERABLE_SECTION_RAM(usbd_context, Z_LINK_ITERABLE_SUBALIGN) ITERABLE_SECTION_RAM(usbd_class_fs, Z_LINK_ITERABLE_SUBALIGN) ITERABLE_SECTION_RAM(usbd_class_hs, Z_LINK_ITERABLE_SUBALIGN) diff --git a/subsys/usb/device_next/usbd_desc.c b/subsys/usb/device_next/usbd_desc.c index ecc8e57259a46..158cdb1ba22fc 100644 --- a/subsys/usb/device_next/usbd_desc.c +++ b/subsys/usb/device_next/usbd_desc.c @@ -28,7 +28,7 @@ static inline bool desc_type_equal(const struct usbd_desc_node *const a, * does not care about index zero for the language string descriptor, * so if it is not added first, the device will be non-compliant. */ -static int desc_add_and_update_idx(struct usbd_contex *const uds_ctx, +static int desc_add_and_update_idx(struct usbd_context *const uds_ctx, struct usbd_desc_node *const new_nd) { struct usbd_desc_node *tmp_nd; @@ -80,7 +80,7 @@ static int desc_add_and_update_idx(struct usbd_contex *const uds_ctx, return 0; } -struct usbd_desc_node *usbd_get_descriptor(struct usbd_contex *const uds_ctx, +struct usbd_desc_node *usbd_get_descriptor(struct usbd_context *const uds_ctx, const uint8_t type, const uint8_t idx) { struct usbd_desc_node *desc_nd; @@ -102,7 +102,7 @@ struct usbd_desc_node *usbd_get_descriptor(struct usbd_contex *const uds_ctx, return NULL; } -int usbd_desc_remove_all(struct usbd_contex *const uds_ctx) +int usbd_desc_remove_all(struct usbd_context *const uds_ctx) { struct usbd_desc_node *tmp; sys_dnode_t *node; @@ -115,7 +115,7 @@ int usbd_desc_remove_all(struct usbd_contex *const uds_ctx) return 0; } -int usbd_add_descriptor(struct usbd_contex *const uds_ctx, +int usbd_add_descriptor(struct usbd_context *const uds_ctx, struct usbd_desc_node *const desc_nd) { struct usb_device_descriptor *hs_desc, *fs_desc; diff --git a/subsys/usb/device_next/usbd_desc.h b/subsys/usb/device_next/usbd_desc.h index 623e92e90c4a3..55e937c19d9df 100644 --- a/subsys/usb/device_next/usbd_desc.h +++ b/subsys/usb/device_next/usbd_desc.h @@ -20,7 +20,7 @@ * * @return pointer to descriptor node or NULL if not found. */ -struct usbd_desc_node *usbd_get_descriptor(struct usbd_contex *const uds_ctx, +struct usbd_desc_node *usbd_get_descriptor(struct usbd_context *const uds_ctx, const uint8_t type, const uint8_t idx); /** @@ -34,6 +34,6 @@ struct usbd_desc_node *usbd_get_descriptor(struct usbd_contex *const uds_ctx, * * @return 0 on success, other values on fail. */ -int usbd_desc_remove_all(struct usbd_contex *const uds_ctx); +int usbd_desc_remove_all(struct usbd_context *const uds_ctx); #endif /* ZEPHYR_INCLUDE_USBD_DESC_H */ diff --git a/subsys/usb/device_next/usbd_device.c b/subsys/usb/device_next/usbd_device.c index 9057e439040b8..86570a1267585 100644 --- a/subsys/usb/device_next/usbd_device.c +++ b/subsys/usb/device_next/usbd_device.c @@ -20,12 +20,12 @@ LOG_MODULE_REGISTER(usbd_dev, CONFIG_USBD_LOG_LEVEL); * All the functions below are part of public USB device support API. */ -enum usbd_speed usbd_bus_speed(const struct usbd_contex *const uds_ctx) +enum usbd_speed usbd_bus_speed(const struct usbd_context *const uds_ctx) { return uds_ctx->status.speed; } -enum usbd_speed usbd_caps_speed(const struct usbd_contex *const uds_ctx) +enum usbd_speed usbd_caps_speed(const struct usbd_context *const uds_ctx) { struct udc_device_caps caps = udc_caps(uds_ctx->dev); @@ -38,7 +38,7 @@ enum usbd_speed usbd_caps_speed(const struct usbd_contex *const uds_ctx) } static struct usb_device_descriptor * -get_device_descriptor(struct usbd_contex *const uds_ctx, +get_device_descriptor(struct usbd_context *const uds_ctx, const enum usbd_speed speed) { switch (speed) { @@ -52,7 +52,7 @@ get_device_descriptor(struct usbd_contex *const uds_ctx, } } -int usbd_device_set_bcd(struct usbd_contex *const uds_ctx, +int usbd_device_set_bcd(struct usbd_context *const uds_ctx, const enum usbd_speed speed, const uint16_t bcd) { struct usb_device_descriptor *desc; @@ -73,7 +73,7 @@ int usbd_device_set_bcd(struct usbd_contex *const uds_ctx, return ret; } -int usbd_device_set_vid(struct usbd_contex *const uds_ctx, +int usbd_device_set_vid(struct usbd_context *const uds_ctx, const uint16_t vid) { struct usb_device_descriptor *fs_desc, *hs_desc; @@ -97,7 +97,7 @@ int usbd_device_set_vid(struct usbd_contex *const uds_ctx, return ret; } -int usbd_device_set_pid(struct usbd_contex *const uds_ctx, +int usbd_device_set_pid(struct usbd_context *const uds_ctx, const uint16_t pid) { struct usb_device_descriptor *fs_desc, *hs_desc; @@ -121,7 +121,7 @@ int usbd_device_set_pid(struct usbd_contex *const uds_ctx, return ret; } -int usbd_device_set_code_triple(struct usbd_contex *const uds_ctx, +int usbd_device_set_code_triple(struct usbd_context *const uds_ctx, const enum usbd_speed speed, const uint8_t base_class, const uint8_t subclass, const uint8_t protocol) @@ -146,7 +146,7 @@ int usbd_device_set_code_triple(struct usbd_contex *const uds_ctx, return ret; } -int usbd_wakeup_request(struct usbd_contex *const uds_ctx) +int usbd_wakeup_request(struct usbd_context *const uds_ctx) { struct udc_device_caps caps = udc_caps(uds_ctx->dev); int ret = 0; @@ -173,12 +173,12 @@ int usbd_wakeup_request(struct usbd_contex *const uds_ctx) return ret; } -bool usbd_is_suspended(struct usbd_contex *uds_ctx) +bool usbd_is_suspended(struct usbd_context *uds_ctx) { return uds_ctx->status.suspended; } -int usbd_init(struct usbd_contex *const uds_ctx) +int usbd_init(struct usbd_context *const uds_ctx) { int ret; @@ -221,7 +221,7 @@ int usbd_init(struct usbd_contex *const uds_ctx) return ret; } -int usbd_enable(struct usbd_contex *const uds_ctx) +int usbd_enable(struct usbd_context *const uds_ctx) { int ret; @@ -258,7 +258,7 @@ int usbd_enable(struct usbd_contex *const uds_ctx) return ret; } -int usbd_disable(struct usbd_contex *const uds_ctx) +int usbd_disable(struct usbd_context *const uds_ctx) { int ret; @@ -286,7 +286,7 @@ int usbd_disable(struct usbd_contex *const uds_ctx) return ret; } -int usbd_shutdown(struct usbd_contex *const uds_ctx) +int usbd_shutdown(struct usbd_context *const uds_ctx) { int ret; @@ -304,7 +304,7 @@ int usbd_shutdown(struct usbd_contex *const uds_ctx) return 0; } -bool usbd_can_detect_vbus(struct usbd_contex *const uds_ctx) +bool usbd_can_detect_vbus(struct usbd_context *const uds_ctx) { const struct udc_device_caps caps = udc_caps(uds_ctx->dev); diff --git a/subsys/usb/device_next/usbd_device.h b/subsys/usb/device_next/usbd_device.h index f125345fb4e43..76c7ed7ee9aaf 100644 --- a/subsys/usb/device_next/usbd_device.h +++ b/subsys/usb/device_next/usbd_device.h @@ -18,7 +18,7 @@ * * @return bNumConfigurations value */ -static inline uint8_t usbd_get_num_configs(const struct usbd_contex *const uds_ctx, +static inline uint8_t usbd_get_num_configs(const struct usbd_context *const uds_ctx, const enum usbd_speed speed) { struct usb_device_descriptor *desc; @@ -42,7 +42,7 @@ static inline uint8_t usbd_get_num_configs(const struct usbd_contex *const uds_c * @param[in] speed Speed for which the bNumConfigurations should be set * @param[in] value new bNumConfigurations value */ -static inline void usbd_set_num_configs(struct usbd_contex *const uds_ctx, +static inline void usbd_set_num_configs(struct usbd_context *const uds_ctx, const enum usbd_speed speed, const uint8_t value) { @@ -66,7 +66,7 @@ static inline void usbd_set_num_configs(struct usbd_contex *const uds_ctx, * * @return true if USB device is in enabled, false otherwise */ -static inline bool usbd_is_enabled(const struct usbd_contex *const uds_ctx) +static inline bool usbd_is_enabled(const struct usbd_context *const uds_ctx) { return uds_ctx->status.enabled; } @@ -78,7 +78,7 @@ static inline bool usbd_is_enabled(const struct usbd_contex *const uds_ctx) * * @return true if USB device is in enabled, false otherwise */ -static inline bool usbd_is_initialized(const struct usbd_contex *const uds_ctx) +static inline bool usbd_is_initialized(const struct usbd_context *const uds_ctx) { return uds_ctx->status.initialized; } @@ -89,7 +89,7 @@ static inline bool usbd_is_initialized(const struct usbd_contex *const uds_ctx) * @param[in] uds_ctx Pointer to a device context * @param[in] value new suspended value */ -static inline void usbd_status_suspended(struct usbd_contex *const uds_ctx, +static inline void usbd_status_suspended(struct usbd_context *const uds_ctx, const bool value) { uds_ctx->status.suspended = value; @@ -100,7 +100,7 @@ static inline void usbd_status_suspended(struct usbd_contex *const uds_ctx, * * @param[in] node Pointer to a device context */ -static inline void usbd_device_lock(struct usbd_contex *const uds_ctx) +static inline void usbd_device_lock(struct usbd_context *const uds_ctx) { k_mutex_lock(&uds_ctx->mutex, K_FOREVER); } @@ -110,7 +110,7 @@ static inline void usbd_device_lock(struct usbd_contex *const uds_ctx) * * @param[in] node Pointer to a device context */ -static inline void usbd_device_unlock(struct usbd_contex *const uds_ctx) +static inline void usbd_device_unlock(struct usbd_context *const uds_ctx) { k_mutex_unlock(&uds_ctx->mutex); } @@ -122,7 +122,7 @@ static inline void usbd_device_unlock(struct usbd_contex *const uds_ctx) * * @return 0 on success, other values on fail. */ -int usbd_device_init_core(struct usbd_contex *uds_ctx); +int usbd_device_init_core(struct usbd_context *uds_ctx); /** * @brief Shutdown USB device stack core @@ -131,6 +131,6 @@ int usbd_device_init_core(struct usbd_contex *uds_ctx); * * @return 0 on success, other values on fail. */ -int usbd_device_shutdown_core(struct usbd_contex *const uds_ctx); +int usbd_device_shutdown_core(struct usbd_context *const uds_ctx); #endif /* ZEPHYR_INCLUDE_USBD_DEVICE_H */ diff --git a/subsys/usb/device_next/usbd_endpoint.c b/subsys/usb/device_next/usbd_endpoint.c index fa68313ce8db0..5d49e0df8ea80 100644 --- a/subsys/usb/device_next/usbd_endpoint.c +++ b/subsys/usb/device_next/usbd_endpoint.c @@ -55,7 +55,7 @@ int usbd_ep_disable(const struct device *dev, return ret; } -static void usbd_ep_ctrl_set_zlp(struct usbd_contex *const uds_ctx, +static void usbd_ep_ctrl_set_zlp(struct usbd_context *const uds_ctx, struct net_buf *const buf) { struct usb_setup_packet *setup = usbd_get_setup_pkt(uds_ctx); @@ -86,7 +86,7 @@ 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. */ -int usbd_ep_ctrl_enqueue(struct usbd_contex *const uds_ctx, +int usbd_ep_ctrl_enqueue(struct usbd_context *const uds_ctx, struct net_buf *const buf) { struct udc_buf_info *bi; @@ -112,7 +112,7 @@ int usbd_ep_ctrl_enqueue(struct usbd_contex *const uds_ctx, struct net_buf *usbd_ep_buf_alloc(const struct usbd_class_data *const c_data, const uint8_t ep, const size_t size) { - struct usbd_contex *uds_ctx = usbd_class_get_ctx(c_data); + struct usbd_context *uds_ctx = usbd_class_get_ctx(c_data); return udc_ep_buf_alloc(uds_ctx->dev, ep, size); } @@ -120,7 +120,7 @@ struct net_buf *usbd_ep_buf_alloc(const struct usbd_class_data *const c_data, int usbd_ep_enqueue(const struct usbd_class_data *const c_data, struct net_buf *const buf) { - struct usbd_contex *uds_ctx = usbd_class_get_ctx(c_data); + struct usbd_context *uds_ctx = usbd_class_get_ctx(c_data); struct udc_buf_info *bi = udc_get_buf_info(buf); if (USB_EP_DIR_IS_IN(bi->ep)) { @@ -134,17 +134,17 @@ int usbd_ep_enqueue(const struct usbd_class_data *const c_data, return udc_ep_enqueue(uds_ctx->dev, buf); } -int usbd_ep_buf_free(struct usbd_contex *const uds_ctx, struct net_buf *buf) +int usbd_ep_buf_free(struct usbd_context *const uds_ctx, struct net_buf *buf) { return udc_ep_buf_free(uds_ctx->dev, buf); } -int usbd_ep_dequeue(struct usbd_contex *const uds_ctx, const uint8_t ep) +int usbd_ep_dequeue(struct usbd_context *const uds_ctx, const uint8_t ep) { return udc_ep_dequeue(uds_ctx->dev, ep); } -int usbd_ep_set_halt(struct usbd_contex *const uds_ctx, const uint8_t ep) +int usbd_ep_set_halt(struct usbd_context *const uds_ctx, const uint8_t ep) { struct usbd_ch9_data *ch9_data = &uds_ctx->ch9_data; int ret; @@ -160,7 +160,7 @@ int usbd_ep_set_halt(struct usbd_contex *const uds_ctx, const uint8_t ep) return ret; } -int usbd_ep_clear_halt(struct usbd_contex *const uds_ctx, const uint8_t ep) +int usbd_ep_clear_halt(struct usbd_context *const uds_ctx, const uint8_t ep) { struct usbd_ch9_data *ch9_data = &uds_ctx->ch9_data; int ret; @@ -176,7 +176,7 @@ int usbd_ep_clear_halt(struct usbd_contex *const uds_ctx, const uint8_t ep) return ret; } -bool usbd_ep_is_halted(struct usbd_contex *const uds_ctx, const uint8_t ep) +bool usbd_ep_is_halted(struct usbd_context *const uds_ctx, const uint8_t ep) { struct usbd_ch9_data *ch9_data = &uds_ctx->ch9_data; diff --git a/subsys/usb/device_next/usbd_init.c b/subsys/usb/device_next/usbd_init.c index ad0245a4c1784..69de723b2217d 100644 --- a/subsys/usb/device_next/usbd_init.c +++ b/subsys/usb/device_next/usbd_init.c @@ -62,7 +62,7 @@ static int assign_ep_addr(const struct device *dev, } /* Unassign all endpoint of a class instance based on class_ep_bm */ -static int unassign_eps(struct usbd_contex *const uds_ctx, +static int unassign_eps(struct usbd_context *const uds_ctx, uint32_t *const config_ep_bm, uint32_t *const class_ep_bm) { @@ -108,7 +108,7 @@ static int unassign_eps(struct usbd_contex *const uds_ctx, * We use config_ep_bm variable as map for assigned endpoint for an * USB device configuration. */ -static int init_configuration_inst(struct usbd_contex *const uds_ctx, +static int init_configuration_inst(struct usbd_context *const uds_ctx, const enum usbd_speed speed, struct usbd_class_node *const c_nd, uint32_t *const config_ep_bm, @@ -191,7 +191,7 @@ static int init_configuration_inst(struct usbd_contex *const uds_ctx, * * Iterate on a list of all classes in a configuration */ -static int init_configuration(struct usbd_contex *const uds_ctx, +static int init_configuration(struct usbd_context *const uds_ctx, const enum usbd_speed speed, struct usbd_config_node *const cfg_nd) { @@ -243,7 +243,7 @@ static int init_configuration(struct usbd_contex *const uds_ctx, return 0; } -static void usbd_init_update_fs_mps0(struct usbd_contex *const uds_ctx) +static void usbd_init_update_fs_mps0(struct usbd_context *const uds_ctx) { struct udc_device_caps caps = udc_caps(uds_ctx->dev); struct usb_device_descriptor *desc = uds_ctx->fs_desc; @@ -264,7 +264,7 @@ static void usbd_init_update_fs_mps0(struct usbd_contex *const uds_ctx) } } -int usbd_init_configurations(struct usbd_contex *const uds_ctx) +int usbd_init_configurations(struct usbd_context *const uds_ctx) { struct usbd_config_node *cfg_nd; diff --git a/subsys/usb/device_next/usbd_init.h b/subsys/usb/device_next/usbd_init.h index 8f5fb574df862..25ea0fbdb038c 100644 --- a/subsys/usb/device_next/usbd_init.h +++ b/subsys/usb/device_next/usbd_init.h @@ -20,6 +20,6 @@ * * @return 0 on success, other values on fail. */ -int usbd_init_configurations(struct usbd_contex *const uds_ctx); +int usbd_init_configurations(struct usbd_context *const uds_ctx); #endif /* ZEPHYR_INCLUDE_USBD_INIT_H */ diff --git a/subsys/usb/device_next/usbd_interface.c b/subsys/usb/device_next/usbd_interface.c index 1e49a259d1e3f..c5d817acef194 100644 --- a/subsys/usb/device_next/usbd_interface.c +++ b/subsys/usb/device_next/usbd_interface.c @@ -22,7 +22,7 @@ enum ep_op { EP_OP_DOWN, /* Disable endpoint and update endpoints bitmap */ }; -static int handle_ep_op(struct usbd_contex *const uds_ctx, +static int handle_ep_op(struct usbd_context *const uds_ctx, const enum ep_op op, struct usb_ep_descriptor *const ed, uint32_t *const ep_bm) @@ -50,7 +50,7 @@ static int handle_ep_op(struct usbd_contex *const uds_ctx, return ret; } -static int usbd_interface_modify(struct usbd_contex *const uds_ctx, +static int usbd_interface_modify(struct usbd_context *const uds_ctx, struct usbd_class_node *const c_nd, const enum ep_op op, const uint8_t iface, @@ -107,7 +107,7 @@ static int usbd_interface_modify(struct usbd_contex *const uds_ctx, return found_iface ? 0 : -ENODATA; } -int usbd_interface_shutdown(struct usbd_contex *const uds_ctx, +int usbd_interface_shutdown(struct usbd_context *const uds_ctx, struct usbd_config_node *const cfg_nd) { struct usbd_class_node *c_nd; @@ -139,7 +139,7 @@ int usbd_interface_shutdown(struct usbd_contex *const uds_ctx, return 0; } -int usbd_interface_default(struct usbd_contex *const uds_ctx, +int usbd_interface_default(struct usbd_context *const uds_ctx, const enum usbd_speed speed, struct usbd_config_node *const cfg_nd) { @@ -165,7 +165,7 @@ int usbd_interface_default(struct usbd_contex *const uds_ctx, return 0; } -int usbd_interface_set(struct usbd_contex *const uds_ctx, +int usbd_interface_set(struct usbd_context *const uds_ctx, const uint8_t iface, const uint8_t alt) { diff --git a/subsys/usb/device_next/usbd_interface.h b/subsys/usb/device_next/usbd_interface.h index bbeaf6f26f75d..140d716b09eee 100644 --- a/subsys/usb/device_next/usbd_interface.h +++ b/subsys/usb/device_next/usbd_interface.h @@ -17,7 +17,7 @@ * * @return 0 on success, other values on fail. */ -int usbd_interface_shutdown(struct usbd_contex *const uds_ctx, +int usbd_interface_shutdown(struct usbd_context *const uds_ctx, struct usbd_config_node *const cfg_nd); /** @@ -31,7 +31,7 @@ int usbd_interface_shutdown(struct usbd_contex *const uds_ctx, * * @return 0 on success, other values on fail. */ -int usbd_interface_default(struct usbd_contex *const uds_ctx, +int usbd_interface_default(struct usbd_context *const uds_ctx, const enum usbd_speed speed, struct usbd_config_node *const cfg_nd); @@ -46,7 +46,7 @@ int usbd_interface_default(struct usbd_contex *const uds_ctx, * * @return 0 on success, other values on fail. */ -int usbd_interface_set(struct usbd_contex *uds_ctx, +int usbd_interface_set(struct usbd_context *uds_ctx, const uint8_t iface, const uint8_t alternate); diff --git a/subsys/usb/device_next/usbd_msg.c b/subsys/usb/device_next/usbd_msg.c index b70b85928f4c0..8ecb9dfe763f6 100644 --- a/subsys/usb/device_next/usbd_msg.c +++ b/subsys/usb/device_next/usbd_msg.c @@ -22,14 +22,14 @@ static sys_slist_t msg_list; struct usbd_msg_pkt { sys_snode_t node; - struct usbd_contex *ctx; + struct usbd_context *ctx; struct usbd_msg msg; }; K_MEM_SLAB_DEFINE_STATIC(usbd_msg_slab, sizeof(struct usbd_msg_pkt), CONFIG_USBD_MSG_SLAB_COUNT, sizeof(void *)); -static inline void usbd_msg_pub(struct usbd_contex *const ctx, +static inline void usbd_msg_pub(struct usbd_context *const ctx, const struct usbd_msg msg) { struct usbd_msg_pkt *m_pkt; @@ -87,7 +87,7 @@ static void msg_work_handler(struct k_work *work) } } -int usbd_msg_register_cb(struct usbd_contex *const uds_ctx, +int usbd_msg_register_cb(struct usbd_context *const uds_ctx, const usbd_msg_cb_t cb) { int ret = 0; @@ -107,7 +107,7 @@ int usbd_msg_register_cb(struct usbd_contex *const uds_ctx, return ret; } -void usbd_msg_pub_simple(struct usbd_contex *const ctx, +void usbd_msg_pub_simple(struct usbd_context *const ctx, const enum usbd_msg_type type, const int status) { const struct usbd_msg msg = { @@ -120,7 +120,7 @@ void usbd_msg_pub_simple(struct usbd_contex *const ctx, } } -void usbd_msg_pub_device(struct usbd_contex *const ctx, +void usbd_msg_pub_device(struct usbd_context *const ctx, const enum usbd_msg_type type, const struct device *const dev) { const struct usbd_msg msg = { diff --git a/subsys/usb/device_next/usbd_msg.h b/subsys/usb/device_next/usbd_msg.h index becbd2551bbab..9aedcac8ade16 100644 --- a/subsys/usb/device_next/usbd_msg.h +++ b/subsys/usb/device_next/usbd_msg.h @@ -16,7 +16,7 @@ * @param[in] type Message type * @param[in] status Status or error code */ -void usbd_msg_pub_simple(struct usbd_contex *const ctx, +void usbd_msg_pub_simple(struct usbd_context *const ctx, const enum usbd_msg_type type, const int status); /** @@ -26,7 +26,7 @@ void usbd_msg_pub_simple(struct usbd_contex *const ctx, * @param[in] type Message type * @param[in] dev Pointer to a device structure */ -void usbd_msg_pub_device(struct usbd_contex *const ctx, +void usbd_msg_pub_device(struct usbd_context *const ctx, const enum usbd_msg_type type, const struct device *const dev); #endif /* ZEPHYR_INCLUDE_USBD_MSG_H */ diff --git a/subsys/usb/device_next/usbd_shell.c b/subsys/usb/device_next/usbd_shell.c index 86e571177d7f5..173a2a076270e 100644 --- a/subsys/usb/device_next/usbd_shell.c +++ b/subsys/usb/device_next/usbd_shell.c @@ -49,7 +49,7 @@ USBD_DESC_SERIAL_NUMBER_DEFINE(sn); USBD_DEVICE_DEFINE(sh_uds_ctx, DEVICE_DT_GET(DT_NODELABEL(zephyr_udc0)), 0x2fe3, 0xffff); -static struct usbd_contex *my_uds_ctx = &sh_uds_ctx; +static struct usbd_context *my_uds_ctx = &sh_uds_ctx; static enum usbd_speed current_cmd_speed = USBD_SPEED_FS; static int cmd_wakeup_request(const struct shell *sh, @@ -269,7 +269,7 @@ static int cmd_usbd_shutdown(const struct shell *sh, static int cmd_select(const struct shell *sh, size_t argc, char **argv) { - STRUCT_SECTION_FOREACH(usbd_contex, ctx) { + STRUCT_SECTION_FOREACH(usbd_context, ctx) { if (strcmp(argv[1], ctx->name) == 0) { my_uds_ctx = ctx; shell_print(sh, @@ -546,7 +546,7 @@ static void device_context_lookup(size_t idx, struct shell_static_entry *entry) entry->help = NULL; entry->subcmd = NULL; - STRUCT_SECTION_FOREACH(usbd_contex, ctx) { + STRUCT_SECTION_FOREACH(usbd_context, ctx) { if ((ctx->name != NULL) && (strlen(ctx->name) != 0)) { if (match_idx == idx) { entry->syntax = ctx->name; From 6305c17d6e4b92b574f4a3b37e717a2e8b373be6 Mon Sep 17 00:00:00 2001 From: Maureen Helm Date: Sat, 1 Jun 2024 13:51:24 -0500 Subject: [PATCH 1584/2849] manifest: Update hal_adi to pick up newlib compatibility fix Updates the hal_adi module to pick up a fix for building with newlib. Signed-off-by: Maureen Helm --- west.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/west.yml b/west.yml index 1d8c79fc3d166..dc048e90c7628 100644 --- a/west.yml +++ b/west.yml @@ -137,7 +137,7 @@ manifest: groups: - fs - name: hal_adi - revision: 674d10b0a1aad4cf4b7b90ca52dfd4a494ab9e52 + revision: 2858da5ab4a7a01cde48a41818a1a6693529f68d path: modules/hal/adi groups: - hal From 8edbbdf332cd35b9713547e37788a9f5908fbf56 Mon Sep 17 00:00:00 2001 From: Henrik Brix Andersen Date: Mon, 3 Jun 2024 13:08:22 +0200 Subject: [PATCH 1585/2849] dts: bindings: can: loopback: the CAN loopback driver supports CAN FD The CAN loopback driver supports CAN FD. Change the binding to reflect this. No functional changes. Signed-off-by: Henrik Brix Andersen --- dts/bindings/can/zephyr,can-loopback.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dts/bindings/can/zephyr,can-loopback.yaml b/dts/bindings/can/zephyr,can-loopback.yaml index 531c6d965bf8c..af93433bf041b 100644 --- a/dts/bindings/can/zephyr,can-loopback.yaml +++ b/dts/bindings/can/zephyr,can-loopback.yaml @@ -5,4 +5,4 @@ description: Zephyr emulated CAN loopback controller compatible: "zephyr,can-loopback" -include: can-controller.yaml +include: can-fd-controller.yaml From 64e9ba3742b749731db18b3fa4013b98b6757096 Mon Sep 17 00:00:00 2001 From: Henrik Brix Andersen Date: Mon, 3 Jun 2024 13:09:27 +0200 Subject: [PATCH 1586/2849] dts: bindings: can: native linux: the CAN Linux driver supports CAN FD The native Linux CAN driver supports CAN FD. Change the binding to reflect this. No functional changes. Signed-off-by: Henrik Brix Andersen --- dts/bindings/can/zephyr,native-linux-can.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dts/bindings/can/zephyr,native-linux-can.yaml b/dts/bindings/can/zephyr,native-linux-can.yaml index 4175617403b34..b854984ece08a 100644 --- a/dts/bindings/can/zephyr,native-linux-can.yaml +++ b/dts/bindings/can/zephyr,native-linux-can.yaml @@ -5,7 +5,7 @@ description: Zephyr CAN driver using Linux SocketCAN compatible: "zephyr,native-linux-can" -include: can-controller.yaml +include: can-fd-controller.yaml properties: host-interface: From 5bd1689ac8eb52f2951eb1d4ad4820ed95aa8d1f Mon Sep 17 00:00:00 2001 From: Francois Ramu Date: Mon, 3 Jun 2024 11:11:58 +0200 Subject: [PATCH 1587/2849] boards: st: stm32c0116_dk defines the select pin with zephyr,code Define the select_key with the correct zephyr,code which is Signed-off-by: Francois Ramu --- boards/st/stm32c0116_dk/stm32c0116_dk.dts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/boards/st/stm32c0116_dk/stm32c0116_dk.dts b/boards/st/stm32c0116_dk/stm32c0116_dk.dts index f9791268886a9..79b4db1fa2583 100644 --- a/boards/st/stm32c0116_dk/stm32c0116_dk.dts +++ b/boards/st/stm32c0116_dk/stm32c0116_dk.dts @@ -53,7 +53,7 @@ select_key { press-thresholds-mv = <0>; - zephyr,code = ; + zephyr,code = ; }; left_key { From 68adc77cbdb168838e76a63412dd1fb71d7d1c57 Mon Sep 17 00:00:00 2001 From: Alberto Escolar Piedras Date: Mon, 3 Jun 2024 11:08:23 +0200 Subject: [PATCH 1588/2849] boards nrf_bsim: Add NVIC_GetEnableIRQ() Provide a replacement for CMSIS' NVIC_GetEnableIRQ() as some applications use it. Signed-off-by: Alberto Escolar Piedras --- boards/native/nrf_bsim/common/cmsis/cmsis.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/boards/native/nrf_bsim/common/cmsis/cmsis.c b/boards/native/nrf_bsim/common/cmsis/cmsis.c index 1694bc1da3406..e80aea6b4ff60 100644 --- a/boards/native/nrf_bsim/common/cmsis/cmsis.c +++ b/boards/native/nrf_bsim/common/cmsis/cmsis.c @@ -35,6 +35,11 @@ void NVIC_EnableIRQ(IRQn_Type IRQn) hw_irq_ctrl_enable_irq(CONFIG_NATIVE_SIMULATOR_MCU_N, IRQn); } +uint32_t NVIC_GetEnableIRQ(IRQn_Type IRQn) +{ + return hw_irq_ctrl_is_irq_enabled(CONFIG_NATIVE_SIMULATOR_MCU_N, IRQn); +} + void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) { hw_irq_ctrl_prio_set(CONFIG_NATIVE_SIMULATOR_MCU_N, IRQn, priority); From 92002b2dff24a923cae5c6ab5b00a4dcbb25c624 Mon Sep 17 00:00:00 2001 From: Emil Gydesen Date: Thu, 30 May 2024 14:48:25 +0200 Subject: [PATCH 1589/2849] Bluetooth: CAP: Implement bt_cap_initiator_unregister_cb Implement function to unregisterd the CAP initiator callbacks. Signed-off-by: Emil Gydesen --- include/zephyr/bluetooth/audio/cap.h | 10 ++++++++++ subsys/bluetooth/audio/cap_initiator.c | 17 +++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/include/zephyr/bluetooth/audio/cap.h b/include/zephyr/bluetooth/audio/cap.h index 6bf5e1b018e12..c5c4bbea6e8ae 100644 --- a/include/zephyr/bluetooth/audio/cap.h +++ b/include/zephyr/bluetooth/audio/cap.h @@ -296,6 +296,16 @@ struct bt_cap_unicast_audio_stop_param { */ int bt_cap_initiator_register_cb(const struct bt_cap_initiator_cb *cb); +/** + * @brief Unregister Common Audio Profile Initiator callbacks + * + * @param cb The callback structure that was previously registered. + * + * @retval 0 Success + * @retval -EINVAL @p cb is NULL or @p cb was not registered + */ +int bt_cap_initiator_unregister_cb(const struct bt_cap_initiator_cb *cb); + /** * @brief Setup and start unicast audio streams for a set of devices. * diff --git a/subsys/bluetooth/audio/cap_initiator.c b/subsys/bluetooth/audio/cap_initiator.c index 3fd5199d5c73d..61257e8a013e5 100644 --- a/subsys/bluetooth/audio/cap_initiator.c +++ b/subsys/bluetooth/audio/cap_initiator.c @@ -53,6 +53,23 @@ int bt_cap_initiator_register_cb(const struct bt_cap_initiator_cb *cb) return 0; } +int bt_cap_initiator_unregister_cb(const struct bt_cap_initiator_cb *cb) +{ + CHECKIF(cb == NULL) { + LOG_DBG("cb is NULL"); + return -EINVAL; + } + + CHECKIF(cap_cb != cb) { + LOG_DBG("cb is not registered"); + return -EINVAL; + } + + cap_cb = NULL; + + return 0; +} + struct valid_metadata_param { bool stream_context_found; bool valid; From 435b72dc18c8f959163e38d87ba133d7a4c17d1b Mon Sep 17 00:00:00 2001 From: Luca Burelli Date: Wed, 29 May 2024 17:40:27 +0200 Subject: [PATCH 1590/2849] llext: add a test for the pre_located feature This test checks that the pre_located feature works as expected. It creates a new extension that is manually relocated to a specific address via the add_llext_command() CMake function invoking a custom linker command. The test then loads the extension setting the pre_located option and checks that the symbol is resolved properly. Signed-off-by: Luca Burelli --- tests/subsys/llext/simple/CMakeLists.txt | 25 ++++++++++------- .../subsys/llext/simple/src/pre_located_ext.c | 19 +++++++++++++ .../llext/simple/src/test_llext_simple.c | 27 +++++++++++++++++++ 3 files changed, 62 insertions(+), 9 deletions(-) create mode 100644 tests/subsys/llext/simple/src/pre_located_ext.c diff --git a/tests/subsys/llext/simple/CMakeLists.txt b/tests/subsys/llext/simple/CMakeLists.txt index 2a677470f6666..2337b3a80c93c 100644 --- a/tests/subsys/llext/simple/CMakeLists.txt +++ b/tests/subsys/llext/simple/CMakeLists.txt @@ -23,6 +23,10 @@ if(CONFIG_ARM) endif() endif() +if (CONFIG_LLEXT_TYPE_ELF_RELOCATABLE AND CONFIG_XTENSA) + list(APPEND ext_names pre_located) +endif() + # generate extension targets foreach extension given by 'ext_names' foreach(ext_name ${ext_names}) set(ext_src ${PROJECT_SOURCE_DIR}/src/${ext_name}_ext.c) @@ -45,12 +49,15 @@ if(NOT CONFIG_LLEXT_TYPE_ELF_OBJECT) ) endif() -# Add a dummy custom processing command to test add_llext_command -get_target_property(proc_in_file hello_world_ext lib_output) -get_target_property(proc_out_file hello_world_ext pkg_input) -add_llext_command( - TARGET hello_world_ext - POST_BUILD - COMMAND echo "dummy patching ${proc_in_file} to create ${proc_out_file}" - COMMAND ${CMAKE_COMMAND} -E copy ${proc_in_file} ${proc_out_file} -) +if (CONFIG_LLEXT_TYPE_ELF_RELOCATABLE AND CONFIG_XTENSA) + # Manually fix the pre_located extension's text address at a multiple of 4 + get_target_property(pre_located_target pre_located_ext lib_target) + get_target_property(pre_located_file pre_located_ext pkg_input) + add_llext_command( + TARGET pre_located_ext + POST_BUILD + COMMAND ${CMAKE_C_COMPILER} + -Wl,-r -Wl,-Ttext=0xbada110c -nostdlib -nodefaultlibs -nostartfiles + $ -o ${pre_located_file} + ) +endif() diff --git a/tests/subsys/llext/simple/src/pre_located_ext.c b/tests/subsys/llext/simple/src/pre_located_ext.c new file mode 100644 index 0000000000000..1308c8d662fc6 --- /dev/null +++ b/tests/subsys/llext/simple/src/pre_located_ext.c @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2024 Arduino SA. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* + * This file contains a simple test extension that defines an entry point + * in the .text section. The entry point is never called, but the symbol + * address is fixed via a linker call and then checked by the test. + */ + +#include + +void test_entry(void) +{ + /* This function is never called */ +} +LL_EXTENSION_SYMBOL(test_entry); diff --git a/tests/subsys/llext/simple/src/test_llext_simple.c b/tests/subsys/llext/simple/src/test_llext_simple.c index 2552844946e44..68b318f5e1c80 100644 --- a/tests/subsys/llext/simple/src/test_llext_simple.c +++ b/tests/subsys/llext/simple/src/test_llext_simple.c @@ -237,6 +237,33 @@ static LLEXT_CONST uint8_t multi_file_ext[] __aligned(4) = { LLEXT_LOAD_UNLOAD(multi_file, true, NULL) #endif +#if defined(CONFIG_LLEXT_TYPE_ELF_RELOCATABLE) && defined(CONFIG_XTENSA) +static LLEXT_CONST uint8_t pre_located_ext[] __aligned(4) = { + #include "pre_located.inc" +}; + +ZTEST(llext, test_pre_located) +{ + struct llext_buf_loader buf_loader = + LLEXT_BUF_LOADER(pre_located_ext, ARRAY_SIZE(pre_located_ext)); + struct llext_loader *loader = &buf_loader.loader; + struct llext_load_param ldr_parm = LLEXT_LOAD_PARAM_DEFAULT; + struct llext *ext = NULL; + const void *test_entry_fn; + int res; + + /* load the extension trying to respect the addresses in the ELF */ + ldr_parm.pre_located = true; + res = llext_load(loader, "pre_located", &ext, &ldr_parm); + zassert_ok(res, "load should succeed"); + + /* check the function address is the expected one */ + test_entry_fn = llext_find_sym(&ext->exp_tab, "test_entry"); + zassert_equal(test_entry_fn, (void *)0xbada110c, "test_entry should be at 0xbada110c"); + + llext_unload(&ext); +} +#endif /* * Ensure that EXPORT_SYMBOL does indeed provide a symbol and a valid address From 05ad2565fadbece12c9a59967fa7dc945acd5ae2 Mon Sep 17 00:00:00 2001 From: Joel Guittet Date: Mon, 27 May 2024 15:14:46 +0200 Subject: [PATCH 1591/2849] llext: add _POSIX_C_SOURCE definition to build shell Fix implicit-function-declaration warning while building the llext shell. Signed-off-by: Joel Guittet --- subsys/llext/CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/subsys/llext/CMakeLists.txt b/subsys/llext/CMakeLists.txt index b129dc7f94314..d08e1c8aee0e3 100644 --- a/subsys/llext/CMakeLists.txt +++ b/subsys/llext/CMakeLists.txt @@ -1,5 +1,7 @@ if(CONFIG_LLEXT) zephyr_library() + # For strnlen() + zephyr_library_compile_definitions(-D_POSIX_C_SOURCE=200809L) zephyr_library_sources(llext.c llext_export.c buf_loader.c) zephyr_library_sources_ifdef(CONFIG_LLEXT_SHELL shell.c) endif() From 8aa6ae43ce47a990d81ea06d84fa26a584d16a30 Mon Sep 17 00:00:00 2001 From: Mathieu Choplain Date: Mon, 6 May 2024 13:03:26 +0200 Subject: [PATCH 1592/2849] llext: add support for SLID-based linking This commit introduces support for an alternate linking method in the LLEXT subsystem, called "SLID" (short for Symbol Link Identifier), enabled by the CONFIG_LLEXT_EXPORT_BUILTINS_BY_SLID Kconfig option. SLID-based linking uses a unique identifier (integer) to identify exported symbols, instead of using the symbol name as done currently. This approach provides several benefits: * linking is faster because the comparison operation to determine whether we found the correct symbol in the export table is now an integer compare, instead of a string compare * binary size is reduced as symbol names can be dropped from the binary * confidentiality is improved as a side-effect, as symbol names are no longer present in the binary Signed-off-by: Mathieu Choplain --- CMakeLists.txt | 15 + boards/qemu/x86/qemu_x86_tiny.ld | 4 + cmake/llext-edk.cmake | 5 + cmake/modules/extensions.cmake | 20 + include/zephyr/arch/arc/v2/linker.ld | 4 + .../arch/arm/cortex_a_r/scripts/linker.ld | 4 + .../arch/arm/cortex_m/scripts/linker.ld | 4 + include/zephyr/arch/arm64/scripts/linker.ld | 4 + include/zephyr/arch/mips/linker.ld | 4 + include/zephyr/arch/nios2/linker.ld | 4 + include/zephyr/arch/posix/linker.ld | 4 + include/zephyr/arch/riscv/common/linker.ld | 4 + include/zephyr/arch/sparc/linker.ld | 4 + include/zephyr/arch/x86/ia32/linker.ld | 4 + include/zephyr/arch/x86/intel64/linker.ld | 3 + include/zephyr/linker/llext-sections.ld | 19 + include/zephyr/llext/symbol.h | 27 +- scripts/build/llext_inject_slids.py | 196 +++++++++ scripts/build/llext_prepare_exptab.py | 377 ++++++++++++++++++ scripts/build/llext_slidlib.py | 65 +++ soc/andestech/ae350/linker.ld | 4 + soc/cdns/dc233c/include/xtensa-dc233c.ld | 4 + .../include/xtensa-sample-controller.ld | 4 + soc/espressif/esp32/default.ld | 4 + soc/espressif/esp32/default_appcpu.ld | 4 + soc/espressif/esp32c3/default.ld | 4 + soc/espressif/esp32s2/default.ld | 4 + soc/espressif/esp32s3/default.ld | 4 + soc/espressif/esp32s3/default_appcpu.ld | 4 + soc/infineon/cat1b/cyw20829/linker.ld | 4 + soc/intel/intel_adsp/ace/ace-link.ld | 4 + .../cavs/include/xtensa-cavs-linker.ld | 4 + soc/ite/ec/it8xxx2/linker.ld | 4 + soc/nxp/imx/imx8/adsp/linker.ld | 4 + soc/nxp/imx/imx8m/adsp/linker.ld | 4 + soc/nxp/imx/imx8ulp/adsp/linker.ld | 4 + soc/nxp/imx/imx8x/adsp/linker.ld | 4 + soc/nxp/imx/imx9/a55/linker.ld | 4 + soc/nxp/imxrt/imxrt5xx/f1/linker.ld | 4 + soc/openisa/rv32m1/linker.ld | 4 + soc/st/stm32/stm32mp1x/linker.ld | 5 + subsys/llext/Kconfig | 15 + subsys/llext/llext.c | 28 +- .../llext/simple/src/test_llext_simple.c | 21 +- tests/subsys/llext/simple/testcase.yaml | 68 ++++ 45 files changed, 981 insertions(+), 7 deletions(-) create mode 100644 include/zephyr/linker/llext-sections.ld create mode 100755 scripts/build/llext_inject_slids.py create mode 100755 scripts/build/llext_prepare_exptab.py create mode 100755 scripts/build/llext_slidlib.py diff --git a/CMakeLists.txt b/CMakeLists.txt index c6b173501495f..05c50b119bc41 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1888,6 +1888,21 @@ if(CONFIG_BUILD_OUTPUT_INFO_HEADER) ) endif() +if (CONFIG_LLEXT AND CONFIG_LLEXT_EXPORT_BUILTINS_BY_SLID) + #slidgen must be the first post-build command to be executed + #on the Zephyr ELF to ensure that all other commands, such as + #binary file generation, are operating on a preparated ELF. + list(PREPEND + post_build_commands + COMMAND ${PYTHON_EXECUTABLE} + ${ZEPHYR_BASE}/scripts/build/llext_prepare_exptab.py + --elf-file ${PROJECT_BINARY_DIR}/${KERNEL_ELF_NAME} + --slid-listing ${PROJECT_BINARY_DIR}/slid_listing.txt + -vvv + ) + +endif() + if(NOT CMAKE_C_COMPILER_ID STREQUAL "ARMClang") set(check_init_priorities_input $,${BYPRODUCT_KERNEL_EXE_NAME},${BYPRODUCT_KERNEL_ELF_NAME}> diff --git a/boards/qemu/x86/qemu_x86_tiny.ld b/boards/qemu/x86/qemu_x86_tiny.ld index 3b3ecde113cc3..1b635f331ee37 100644 --- a/boards/qemu/x86/qemu_x86_tiny.ld +++ b/boards/qemu/x86/qemu_x86_tiny.ld @@ -254,6 +254,10 @@ SECTIONS #include +#ifdef CONFIG_LLEXT +#include +#endif + /DISCARD/ : { *(.plt) diff --git a/cmake/llext-edk.cmake b/cmake/llext-edk.cmake index 9501133f3ab38..da9c33b127f3b 100644 --- a/cmake/llext-edk.cmake +++ b/cmake/llext-edk.cmake @@ -31,6 +31,11 @@ cmake_minimum_required(VERSION 3.20.0) +if (CONFIG_LLEXT_EXPORT_BUILTINS_BY_SLID) + message(FATAL_ERROR + "The LLEXT EDK is not compatible with CONFIG_LLEXT_EXPORT_BUILTINS_BY_SLID.") +endif() + set(llext_edk ${PROJECT_BINARY_DIR}/${llext_edk_name}) set(llext_edk_inc ${llext_edk}/include) diff --git a/cmake/modules/extensions.cmake b/cmake/modules/extensions.cmake index 2c1e1c6635542..9fe387e238815 100644 --- a/cmake/modules/extensions.cmake +++ b/cmake/modules/extensions.cmake @@ -5431,6 +5431,23 @@ function(add_llext_target target_name) COMMAND_EXPAND_LISTS ) + # LLEXT ELF processing for importing via SLID + # + # This command must be executed as last step of the packaging process, + # to ensure that the ELF processed for binary generation contains SLIDs. + # If executed too early, it is possible that some tools executed to modify + # the ELF file (e.g., strip) undo the work performed here. + if (CONFIG_LLEXT_EXPORT_BUILTINS_BY_SLID) + set(slid_inject_cmd + ${PYTHON_EXECUTABLE} + ${ZEPHYR_BASE}/scripts/build/llext_inject_slids.py + --elf-file ${llext_pkg_output} + -vvv + ) + else() + set(slid_inject_cmd ${CMAKE_COMMAND} -E true) + endif() + # Type-specific packaging of the built binary file into an .llext file if(CONFIG_LLEXT_TYPE_ELF_OBJECT) @@ -5438,6 +5455,7 @@ function(add_llext_target target_name) add_custom_command( OUTPUT ${llext_pkg_output} COMMAND ${CMAKE_COMMAND} -E copy ${llext_pkg_input} ${llext_pkg_output} + COMMAND ${slid_inject_cmd} DEPENDS ${llext_proc_target} ${llext_pkg_input} ) @@ -5453,6 +5471,7 @@ function(add_llext_target target_name) $${llext_pkg_input} $${llext_pkg_output} $ + COMMAND ${slid_inject_cmd} DEPENDS ${llext_proc_target} ${llext_pkg_input} ) @@ -5467,6 +5486,7 @@ function(add_llext_target target_name) $${llext_pkg_input} $${llext_pkg_output} $ + COMMAND ${slid_inject_cmd} DEPENDS ${llext_proc_target} ${llext_pkg_input} ) diff --git a/include/zephyr/arch/arc/v2/linker.ld b/include/zephyr/arch/arc/v2/linker.ld index a7751d961194e..c65aa5a648412 100644 --- a/include/zephyr/arch/arc/v2/linker.ld +++ b/include/zephyr/arch/arc/v2/linker.ld @@ -81,6 +81,10 @@ SECTIONS { #include +#ifdef CONFIG_LLEXT +#include +#endif + GROUP_START(ROMABLE_REGION) SECTION_PROLOGUE(_TEXT_SECTION_NAME,,ALIGN(1024)) { diff --git a/include/zephyr/arch/arm/cortex_a_r/scripts/linker.ld b/include/zephyr/arch/arm/cortex_a_r/scripts/linker.ld index 947c18de31349..cffe2f3856e00 100644 --- a/include/zephyr/arch/arm/cortex_a_r/scripts/linker.ld +++ b/include/zephyr/arch/arm/cortex_a_r/scripts/linker.ld @@ -98,6 +98,10 @@ SECTIONS { #include +#ifdef CONFIG_LLEXT +#include +#endif + /* * .plt and .iplt are here according to 'arm-zephyr-elf-ld --verbose', * before text section. diff --git a/include/zephyr/arch/arm/cortex_m/scripts/linker.ld b/include/zephyr/arch/arm/cortex_m/scripts/linker.ld index 88598cf5790eb..094e4a5303f97 100644 --- a/include/zephyr/arch/arm/cortex_m/scripts/linker.ld +++ b/include/zephyr/arch/arm/cortex_m/scripts/linker.ld @@ -113,6 +113,10 @@ SECTIONS #include +#ifdef CONFIG_LLEXT +#include +#endif + /* * .plt and .iplt are here according to 'arm-zephyr-elf-ld --verbose', * before text section. diff --git a/include/zephyr/arch/arm64/scripts/linker.ld b/include/zephyr/arch/arm64/scripts/linker.ld index 5a8e1404a98ae..d2f573520c12a 100644 --- a/include/zephyr/arch/arm64/scripts/linker.ld +++ b/include/zephyr/arch/arm64/scripts/linker.ld @@ -77,6 +77,10 @@ SECTIONS #include +#ifdef CONFIG_LLEXT +#include +#endif + /* * .plt and .iplt are here according to 'arm-zephyr-elf-ld --verbose', * before text section. diff --git a/include/zephyr/arch/mips/linker.ld b/include/zephyr/arch/mips/linker.ld index cbff890822c72..f7479c23e36b5 100644 --- a/include/zephyr/arch/mips/linker.ld +++ b/include/zephyr/arch/mips/linker.ld @@ -46,6 +46,10 @@ SECTIONS #include +#ifdef CONFIG_LLEXT +#include +#endif + SECTION_PROLOGUE(_VECTOR_SECTION_NAME,,) { . = ALIGN(0x1000); diff --git a/include/zephyr/arch/nios2/linker.ld b/include/zephyr/arch/nios2/linker.ld index f7ba64088fc6e..d65805ba7cf1e 100644 --- a/include/zephyr/arch/nios2/linker.ld +++ b/include/zephyr/arch/nios2/linker.ld @@ -85,6 +85,10 @@ SECTIONS #include +#ifdef CONFIG_LLEXT +#include +#endif + /* * .plt and .iplt are here according to * 'nios2-zephyr-elf-ld --verbose', before text section. diff --git a/include/zephyr/arch/posix/linker.ld b/include/zephyr/arch/posix/linker.ld index 06dfb3254f172..0943546c0c7b0 100644 --- a/include/zephyr/arch/posix/linker.ld +++ b/include/zephyr/arch/posix/linker.ld @@ -21,6 +21,10 @@ SECTIONS { +#ifdef CONFIG_LLEXT +#include +#endif + SECTION_PROLOGUE(rom_start,,) { /* Located in generated directory. This file is populated by the diff --git a/include/zephyr/arch/riscv/common/linker.ld b/include/zephyr/arch/riscv/common/linker.ld index ccb16cc2c670b..8ef264b9f1a64 100644 --- a/include/zephyr/arch/riscv/common/linker.ld +++ b/include/zephyr/arch/riscv/common/linker.ld @@ -122,6 +122,10 @@ SECTIONS #include +#ifdef CONFIG_LLEXT +#include +#endif + /* * The .plt and .iplt are here according to * 'riscv32-zephyr-elf-ld --verbose', before text section. diff --git a/include/zephyr/arch/sparc/linker.ld b/include/zephyr/arch/sparc/linker.ld index 725339ef0b7cd..ccf333d4863c4 100644 --- a/include/zephyr/arch/sparc/linker.ld +++ b/include/zephyr/arch/sparc/linker.ld @@ -23,6 +23,10 @@ SECTIONS #include +#ifdef CONFIG_LLEXT +#include +#endif + __rom_region_start = .; SECTION_PROLOGUE(_TEXT_SECTION_NAME,,) diff --git a/include/zephyr/arch/x86/ia32/linker.ld b/include/zephyr/arch/x86/ia32/linker.ld index 69ff541232695..e796b3c3e85f7 100644 --- a/include/zephyr/arch/x86/ia32/linker.ld +++ b/include/zephyr/arch/x86/ia32/linker.ld @@ -77,6 +77,10 @@ SECTIONS #include +#ifdef CONFIG_LLEXT +#include +#endif + /DISCARD/ : { *(.plt) diff --git a/include/zephyr/arch/x86/intel64/linker.ld b/include/zephyr/arch/x86/intel64/linker.ld index 8949b94e657fd..1bc014570c638 100644 --- a/include/zephyr/arch/x86/intel64/linker.ld +++ b/include/zephyr/arch/x86/intel64/linker.ld @@ -236,4 +236,7 @@ SECTIONS .shstrtab 0 : { *(.shstrtab) } #endif +#ifdef CONFIG_LLEXT + #include +#endif } diff --git a/include/zephyr/linker/llext-sections.ld b/include/zephyr/linker/llext-sections.ld new file mode 100644 index 0000000000000..b8cc32e3d1bf1 --- /dev/null +++ b/include/zephyr/linker/llext-sections.ld @@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + + /* + * Special section used by LLEXT if CONFIG_LLEXT_EXPORT_BUILTINS_BY_SLID + * is enabled. Declare this section to prevent it from being considered orphan. + * + * This section is used to temporarily save the exported symbols' names in the + * Zephyr ELF for post-processing, but it is not included in the final binary. + * + * NOTE: This section MUST start at address 0, as the post-processing scripts + * assume that the address of any data in this section (i.e., symbol names) is + * strictly equivalent to the offset inside the section. + */ +#ifdef CONFIG_LLEXT_EXPORT_BUILTINS_BY_SLID + SECTION_PROLOGUE(llext_exports_strtab, 0 (COPY), ) + { + KEEP(*(llext_exports_strtab)) + } +#endif diff --git a/include/zephyr/llext/symbol.h b/include/zephyr/llext/symbol.h index e42dc37c9efa4..b9d5c6138a893 100644 --- a/include/zephyr/llext/symbol.h +++ b/include/zephyr/llext/symbol.h @@ -10,6 +10,7 @@ #include #include #include +#include #ifdef __cplusplus extern "C" { @@ -27,14 +28,27 @@ extern "C" { * Symbols may be named function or global objects that have been exported * for linking. These constant symbols are useful in the base image * as they may be placed in ROM. + * + * @note When updating this structure, make sure to also update the + * 'scripts/build/llext_prepare_exptab.py' build script. */ struct llext_const_symbol { - /** Name of symbol */ - const char *const name; + /** At build time, we always write to 'name'. + * At runtime, which field is used depends + * on CONFIG_LLEXT_EXPORT_BUILTINS_BY_SLID. + */ + union { + /** Name of symbol */ + const char *const name; + + /** Symbol Link Identifier */ + const uintptr_t slid; + }; /** Address of symbol */ const void *const addr; }; +BUILD_ASSERT(sizeof(struct llext_const_symbol) == 2 * sizeof(uintptr_t)); /** * @brief Symbols are named memory addresses @@ -75,10 +89,19 @@ struct llext_symtable { * * @param x Symbol to export to extensions */ +#ifdef CONFIG_LLEXT_EXPORT_BUILTINS_BY_SLID +#define EXPORT_SYMBOL(x) \ + static const char Z_GENERIC_SECTION("llext_exports_strtab") __used \ + x ## _sym_name[] = STRINGIFY(x); \ + static const STRUCT_SECTION_ITERABLE(llext_const_symbol, x ## _sym) = { \ + .name = x ## _sym_name, .addr = (const void *)&x, \ + } +#else #define EXPORT_SYMBOL(x) \ static const STRUCT_SECTION_ITERABLE(llext_const_symbol, x ## _sym) = { \ .name = STRINGIFY(x), .addr = (const void *)&x, \ } +#endif /** * @brief Exports a symbol from an extension to the base image diff --git a/scripts/build/llext_inject_slids.py b/scripts/build/llext_inject_slids.py new file mode 100755 index 0000000000000..19e87edba9338 --- /dev/null +++ b/scripts/build/llext_inject_slids.py @@ -0,0 +1,196 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 STMicroelectronics +# SPDX-License-Identifier: Apache-2.0 + +"""Injects SLIDs in LLEXT ELFs' symbol tables. + +When Kconfig option CONFIG_LLEXT_EXPORT_BUILTINS_BY_SLID is enabled, +all imports from the Zephyr kernel & application are resolved using +SLIDs instead of symbol names. This script stores the SLID of all +imported symbols in their associated entry in the ELF symbol table +to allow the LLEXT subsystem to link it properly at runtime. + +Note that this script is idempotent in theory. However, to prevent +any catastrophic problem, the script will abort if the 'st_value' +field of the `ElfX_Sym` structure is found to be non-zero, which is +the case after one invocation. For this reason, in practice, the script +cannot actually be executed twice on the same ELF file. +""" + +import argparse +import logging +import shutil +import sys + +from elftools.elf.elffile import ELFFile +from elftools.elf.sections import SymbolTableSection + +import llext_slidlib + +class LLEXTSymtabPreparator(): + def __init__(self, elf_path, log): + self.log = log + self.elf_path = elf_path + self.elf_fd = open(elf_path, "rb+") + self.elf = ELFFile(self.elf_fd) + + def _find_symtab(self): + supported_symtab_sections = [ + ".symtab", + ".dynsym", + ] + + symtab = None + for section_name in supported_symtab_sections: + symtab = self.elf.get_section_by_name(section_name) + if not isinstance(symtab, SymbolTableSection): + self.log.debug(f"section {section_name} not found.") + else: + self.log.info(f"processing '{section_name}' symbol table...") + self.log.debug(f"(symbol table is at file offset 0x{symtab['sh_offset']:X})") + break + return symtab + + def _find_imports_in_symtab(self, symtab): + i = 0 + imports = [] + for sym in symtab.iter_symbols(): + #Check if symbol is an import + if sym.entry['st_info']['type'] == 'STT_NOTYPE' and \ + sym.entry['st_info']['bind'] == 'STB_GLOBAL' and \ + sym.entry['st_shndx'] == 'SHN_UNDEF': + + self.log.debug(f"found imported symbol '{sym.name}' at index {i}") + imports.append((i, sym)) + + i += 1 + return imports + + def _prepare_inner(self): + #1) Locate the symbol table + symtab = self._find_symtab() + if symtab is None: + self.log.error("no symbol table found in file") + return 1 + + #2) Find imported symbols in symbol table + imports = self._find_imports_in_symtab(symtab) + self.log.info(f"LLEXT has {len(imports)} import(s)") + + #3) Write SLIDs in each symbol's 'st_value' field + def make_stvalue_reader_writer(): + byteorder = "little" if self.elf.little_endian else "big" + if self.elf.elfclass == 32: + sizeof_Elf_Sym = 0x10 #sizeof(Elf32_Sym) + offsetof_st_value = 0x4 #offsetof(Elf32_Sym, st_value) + sizeof_st_value = 0x4 #sizeof(Elf32_Sym.st_value) + else: + sizeof_Elf_Sym = 0x18 + offsetof_st_value = 0x8 + sizeof_st_value = 0x8 + + def seek(symidx): + self.elf_fd.seek( + symtab['sh_offset'] + + symidx * sizeof_Elf_Sym + + offsetof_st_value) + + def reader(symbol_index): + seek(symbol_index) + return int.from_bytes(self.elf_fd.read(sizeof_st_value), byteorder) + + def writer(symbol_index, st_value): + seek(symbol_index) + self.elf_fd.write(int.to_bytes(st_value, sizeof_st_value, byteorder)) + + return reader, writer + + rd_st_val, wr_st_val = make_stvalue_reader_writer() + slid_size = self.elf.elfclass // 8 + + for (index, symbol) in imports: + slid = llext_slidlib.generate_slid(symbol.name, slid_size) + slid_as_str = llext_slidlib.format_slid(slid, slid_size) + msg = f"{symbol.name} -> {slid_as_str}" + + self.log.info(msg) + + # Make sure we're not overwriting something actually important + original_st_value = rd_st_val(index) + if original_st_value != 0: + self.log.error(f"unexpected non-zero st_value for symbol {symbol.name}") + return 1 + + wr_st_val(index, slid) + + return 0 + + def prepare_llext(self): + res = self._prepare_inner() + self.elf_fd.close() + return res + +# Disable duplicate code warning for the code that follows, +# as it is expected for these functions to be similar. +# pylint: disable=duplicate-code +def _parse_args(argv): + """Parse the command line arguments.""" + parser = argparse.ArgumentParser( + description=__doc__, + formatter_class=argparse.RawDescriptionHelpFormatter, + allow_abbrev=False) + + parser.add_argument("-f", "--elf-file", required=True, + help="LLEXT ELF file to process") + parser.add_argument("-o", "--output-file", + help=("Additional output file where processed ELF " + "will be copied")) + parser.add_argument("-sl", "--slid-listing", + help="write the SLID listing to a file") + parser.add_argument("-v", "--verbose", action="count", + help=("enable verbose output, can be used multiple times " + "to increase verbosity level")) + parser.add_argument("--always-succeed", action="store_true", + help="always exit with a return code of 0, used for testing") + + return parser.parse_args(argv) + +def _init_log(verbose): + """Initialize a logger object.""" + log = logging.getLogger(__file__) + + console = logging.StreamHandler() + console.setFormatter(logging.Formatter("%(levelname)s: %(message)s")) + log.addHandler(console) + + if verbose and verbose > 1: + log.setLevel(logging.DEBUG) + elif verbose and verbose > 0: + log.setLevel(logging.INFO) + else: + log.setLevel(logging.WARNING) + + return log + +def main(argv=None): + args = _parse_args(argv) + + log = _init_log(args.verbose) + + log.info(f"inject_slids_in_llext: {args.elf_file}") + + preparator = LLEXTSymtabPreparator(args.elf_file, log) + + res = preparator.prepare_llext() + + if args.always_succeed: + return 0 + + if res == 0 and args.output_file: + shutil.copy(args.elf_file, args.output_file) + + return res + +if __name__ == "__main__": + sys.exit(main(sys.argv[1:])) diff --git a/scripts/build/llext_prepare_exptab.py b/scripts/build/llext_prepare_exptab.py new file mode 100755 index 0000000000000..c659709af17e6 --- /dev/null +++ b/scripts/build/llext_prepare_exptab.py @@ -0,0 +1,377 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 STMicroelectronics +# SPDX-License-Identifier: Apache-2.0 + +""" +Script to prepare the LLEXT exports table of a Zephyr ELF + +This script performs compile-time processing of the LLEXT exports +table for usage at runtime by the LLEXT subsystem code. The table +is a special section filled with 'llext_const_symbol' structures +generated by the EXPORT_SYMBOL macro. + +Currently, the preparatory work consists mostly of sorting the +exports table to allow usage of binary search algorithms at runtime. +If CONFIG_LLEXT_EXPORT_BUILTINS_BY_SLID option is enabled, SLIDs +of all exported functions are also injected in the export table by +this script. (In this case, the preparation process is destructive) +""" + +import llext_slidlib + +from elftools.elf.elffile import ELFFile +from elftools.elf.sections import Section + +import argparse +import logging +import pathlib +import struct +import sys + +#!!!!! WARNING !!!!! +# +#These constants MUST be kept in sync with the linker scripts +#and the EXPORT_SYMBOL macro located in 'subsys/llext/llext.h'. +#Otherwise, the LLEXT subsystem will be broken! +# +#!!!!! WARNING !!!!! + +LLEXT_EXPORT_TABLE_SECTION_NAME = "llext_const_symbol_area" +LLEXT_EXPORT_NAMES_SECTION_NAME = "llext_exports_strtab" + +def _llext_const_symbol_struct(ptr_size: int, endianness: str): + """ + ptr_size -- Platform pointer size in bytes + endianness -- Platform endianness ('little'/'big') + """ + endspec = "<" if endianness == 'little' else ">" + if ptr_size == 4: + ptrspec = "I" + elif ptr_size == 8: + ptrspec = "Q" + + # struct llext_const_symbol + # contains just two pointers. + lcs_spec = endspec + 2 * ptrspec + return struct.Struct(lcs_spec) + +#ELF Shdr flag applied to the export table section, to indicate +#the section has already been prepared by this script. This is +#mostly a security measure to prevent the script from running +#twice on the same ELF file, which can result in catastrophic +#failures if SLID-based linking is enabled (in this case, the +#preparation process is destructive). +# +#This flag is part of the SHF_MASKOS mask, of which all bits +#are "reserved for operating system-specific semantics". +#See: https://refspecs.linuxbase.org/elf/gabi4+/ch4.sheader.html +SHF_LLEXT_PREPARATION_DONE = 0x08000000 + +class SectionDescriptor(): + """ELF Section descriptor + + This is a wrapper class around pyelftools' "Section" object. + """ + def __init__(self, elffile, section_name): + self.name = section_name + self.section = elffile.get_section_by_name(section_name) + if not isinstance(self.section, Section): + raise KeyError(f"section {section_name} not found") + + self.shdr_index = elffile.get_section_index(section_name) + self.shdr_offset = elffile['e_shoff'] + \ + self.shdr_index * elffile['e_shentsize'] + self.size = self.section['sh_size'] + self.flags = self.section['sh_flags'] + self.offset = self.section['sh_offset'] + +class LLEXTExptabManipulator(): + """Class used to wrap the LLEXT export table manipulation.""" + def __init__(self, elf_fd, exptab_file_offset, lcs_struct, exports_count): + self.fd = elf_fd + self.exports_count = exports_count + self.base_offset = exptab_file_offset + self.lcs_struct = lcs_struct + + def _seek_to_sym(self, index): + self.fd.seek(self.base_offset + index * self.lcs_struct.size) + + def __getitem__(self, index): + if not isinstance(index, int): + raise TypeError(f"invalid type {type(index)} for index") + + if index >= self.exports_count: + raise IndexError(f"index {index} is out of bounds (max {self.exports_count})") + + self._seek_to_sym(index) + return self.lcs_struct.unpack(self.fd.read(self.lcs_struct.size)) + + def __setitem__(self, index, item): + if not isinstance(index, int): + raise TypeError(f"invalid type {type(index)} for index") + + if index >= self.exports_count: + raise IndexError(f"index {index} is out of bounds (max {self.exports_count})") + + (addr_or_slid, sym_addr) = item + + self._seek_to_sym(index) + self.fd.write(self.lcs_struct.pack(addr_or_slid, sym_addr)) + +class ZephyrElfExptabPreparator(): + """Prepares the LLEXT export table of a Zephyr ELF. + + Attributes: + elf_path: path to the Zephyr ELF to prepare + log: a logging.Logger object + slid_listing_path: path to the file where SLID listing should be saved + """ + def __init__(self, elf_path: str, log: logging.Logger, slid_listing_path: str | None): + self.elf_path = elf_path + self.elf_fd = open(self.elf_path, 'rb+') + self.elf = ELFFile(self.elf_fd) + self.log = log + + # Lazy-open the SLID listing file to ensure it is only created when necessary + self.slid_listing_path = slid_listing_path + self.slid_listing_fd = None + + def _prepare_exptab_for_slid_linking(self): + """ + IMPLEMENTATION NOTES: + In the linker script, we declare the export names table + as starting at address 0. Thanks to this, all "pointers" + to that section are equal to the offset inside the section. + Also note that symbol names are always NUL-terminated. + + The export table is sorted by SLID in ASCENDING order. + """ + def read_symbol_name(name_ptr): + raw_name = b'' + self.elf_fd.seek(self.expstrtab_section.offset + name_ptr) + + c = self.elf_fd.read(1) + while c != b'\0': + raw_name += c + c = self.elf_fd.read(1) + + return raw_name.decode("utf-8") + + #1) Load the export table + exports_list = [] + for (name_ptr, export_address) in self.exptab_manipulator: + export_name = read_symbol_name(name_ptr) + exports_list.append((export_name, export_address)) + + #2) Generate the SLID for all exports + collided = False + sorted_exptab = dict() + for export_name, export_addr in exports_list: + slid = llext_slidlib.generate_slid(export_name, self.ptrsize) + + collision = sorted_exptab.get(slid) + if collision: + #Don't abort immediately on collision: if there are others, we want to log them all. + self.log.error(f"SLID collision: {export_name} and {collision[0]} have the same SLID 0x{slid:X}") + collided = True + else: + sorted_exptab[slid] = (export_name, export_addr) + + if collided: + return 1 + + #3) Sort the export table (order specified above) + sorted_exptab = dict(sorted(sorted_exptab.items())) + + #4) Write the updated export table to ELF, and dump + #to SLID listing if requested by caller + if self.slid_listing_path: + self.slid_listing_fd = open(self.slid_listing_path, "w") + + def slidlist_write(msg): + if self.slid_listing_fd: + self.slid_listing_fd.write(msg + "\n") + + slidlist_write(f"/* SLID listing generated by {__file__} */") + slidlist_write("//") + slidlist_write("// This file contains the 'SLID -> name' mapping for all") + slidlist_write("// symbols exported to LLEXT by this Zephyr executable.") + slidlist_write("") + + self.log.info("SLID -> export name mapping:") + + i = 0 + for (slid, name_and_symaddr) in sorted_exptab.items(): + slid_as_str = llext_slidlib.format_slid(slid, self.ptrsize) + msg = f"{slid_as_str} -> {name_and_symaddr[0]}" + self.log.info(msg) + slidlist_write(msg) + + self.exptab_manipulator[i] = (slid, name_and_symaddr[1]) + i += 1 + + if self.slid_listing_fd: + self.slid_listing_fd.close() + + return 0 + + def _prepare_exptab_for_str_linking(self): + #TODO: sort the export table by symbol + # name to allow binary search too + # + # Plan of action: + # 1) Locate in which section the names are located + # 2) Load the export table and resolve names + # 3) Sort the exports by name + # WARN: THIS MUST USE THE SAME SORTING RULES + # AS LLEXT CODE OR DICHOTOMIC SEARCH WILL BREAK + # Using a custom sorting function might be required. + # 4) Write back the updated export table + # + # N.B.: reusing part of the code in _prepare_elf_for_slid_linking + # might be possible and desireable. + # + # As of writing, this function will never be called as this script + # is only called if CONFIG_LLEXT_EXPORT_BUILTINS_BY_SLID is enabled, + # which makes _prepare_exptab_for_slid_linking be called instead. + # + self.log.warn(f"_prepare_exptab_for_str_linking: do nothing") + return 0 + + def _set_prep_done_shdr_flag(self): + #Offset and size of the 'sh_flags' member of + #the Elf_Shdr structure. The offset does not + #change between ELF32 and ELF64. Size in both + #is equal to pointer size (4 bytes for ELF32, + #8 bytes for ELF64). + SHF_OFFSET = 8 + SHF_SIZE = self.ptrsize + + off = self.exptab_section.shdr_offset + SHF_OFFSET + + #Read existing sh_flags, set the PREPARATION_DONE flag + #and write back the new value. + self.elf_fd.seek(off) + sh_flags = int.from_bytes(self.elf_fd.read(SHF_SIZE), self.endianness) + + sh_flags |= SHF_LLEXT_PREPARATION_DONE + + self.elf_fd.seek(off) + self.elf_fd.write(int.to_bytes(sh_flags, self.ptrsize, self.endianness)) + + def _prepare_inner(self): + # Locate the export table section + try: + self.exptab_section = SectionDescriptor( + self.elf, LLEXT_EXPORT_TABLE_SECTION_NAME) + except KeyError as e: + self.log.error(e.args[0]) + return 1 + + # Abort if the ELF has already been processed + if (self.exptab_section.flags & SHF_LLEXT_PREPARATION_DONE) != 0: + self.log.warning("exptab section flagged with LLEXT_PREPARATION_DONE " + "- not preparing again") + return 0 + + # Get the struct.Struct for export table entry + self.ptrsize = self.elf.elfclass // 8 + self.endianness = 'little' if self.elf.little_endian else 'big' + self.lcs_struct = _llext_const_symbol_struct(self.ptrsize, self.endianness) + + # Verify that the export table size is coherent + if (self.exptab_section.size % self.lcs_struct.size) != 0: + self.log.error(f"export table size (0x{self.exptab_section.size:X}) " + f"not aligned to 'llext_const_symbol' size (0x{self.lcs_struct.size:X})") + return 1 + + # Create the export table manipulator + num_exports = self.exptab_section.size // self.lcs_struct.size + self.exptab_manipulator = LLEXTExptabManipulator( + self.elf_fd, self.exptab_section.offset, self.lcs_struct, num_exports) + + # Attempt to locate the export names section + try: + self.expstrtab_section = SectionDescriptor( + self.elf, LLEXT_EXPORT_NAMES_SECTION_NAME) + except KeyError: + self.expstrtab_section = None + + self.log.debug(f"exports table section at file offset 0x{self.exptab_section.offset:X}") + if self.expstrtab_section: + self.log.debug(f"exports strtab section at file offset 0x{self.expstrtab_section.offset:X}") + else: + self.log.debug("no exports strtab section in ELF") + self.log.info(f"{num_exports} symbols are exported to LLEXTs by this ELF") + + # Perform the export table preparation + if self.expstrtab_section: + res = self._prepare_exptab_for_slid_linking() + else: + res = self._prepare_exptab_for_str_linking() + + if res == 0: # Add the "prepared" flag to export table section + self._set_prep_done_shdr_flag() + + def prepare_elf(self): + res = self._prepare_inner() + self.elf_fd.close() + return res + +# pylint: disable=duplicate-code +def _parse_args(argv): + """Parse the command line arguments.""" + parser = argparse.ArgumentParser( + description=__doc__, + formatter_class=argparse.RawDescriptionHelpFormatter, + allow_abbrev=False) + + parser.add_argument("-f", "--elf-file", default=pathlib.Path("build", "zephyr", "zephyr.elf"), + help="ELF file to process") + parser.add_argument("-sl", "--slid-listing", + help=("write the SLID listing to a file (only useful" + "when CONFIG_LLEXT_EXPORT_BUILTINS_BY_SLID is enabled) ")) + parser.add_argument("-v", "--verbose", action="count", + help=("enable verbose output, can be used multiple times " + "to increase verbosity level")) + parser.add_argument("--always-succeed", action="store_true", + help="always exit with a return code of 0, used for testing") + + return parser.parse_args(argv) + +def _init_log(verbose): + """Initialize a logger object.""" + log = logging.getLogger(__file__) + + console = logging.StreamHandler() + console.setFormatter(logging.Formatter("%(levelname)s: %(message)s")) + log.addHandler(console) + + if verbose and verbose > 1: + log.setLevel(logging.DEBUG) + elif verbose and verbose > 0: + log.setLevel(logging.INFO) + else: + log.setLevel(logging.WARNING) + + return log + +def main(argv=None): + args = _parse_args(argv) + + log = _init_log(args.verbose) + + log.info(f"prepare_llext_exptab: {args.elf_file}") + + preparator = ZephyrElfExptabPreparator(args.elf_file, log, args.slid_listing) + + res = preparator.prepare_elf() + + if args.always_succeed: + return 0 + + return res + +if __name__ == "__main__": + sys.exit(main(sys.argv[1:])) diff --git a/scripts/build/llext_slidlib.py b/scripts/build/llext_slidlib.py new file mode 100755 index 0000000000000..99157c526dcc3 --- /dev/null +++ b/scripts/build/llext_slidlib.py @@ -0,0 +1,65 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 STMicroelectronics +# SPDX-License-Identifier: Apache-2.0 + +""" +This file implements the Symbol Link Identifer (SLID) +generation code, for use by the LLEXT subsystem. +SLID-based linking is enabled by the Kconfig +option 'CONFIG_LLEXT_EXPORT_BUILTINS_BY_SLID'. + +When executed as a script, this file can be used as +an interactive prompt to calculate the SLID of arbitrary +symbols, which can be useful for debugging purposes. + +IMPLEMENTATION NOTES: + Currently, SLIDs are generated by taking the first + [pointer size] bytes of the symbol name's SHA-256 + hash, taken in big-endian order. + + This ordering provides one advantage: the 32-bit + SLID for an export is present in the top 32 bits of + the 64-bit SLID for the same export. +""" + +from hashlib import sha256 + +def generate_slid(symbol_name: str, slid_size: int) -> int: + """ + Generates the Symbol Link Identifier (SLID) for a symbol. + + symbol_name: Name of the symbol for which to generate a SLID + slid_side: Size of the SLID in bytes (4/8) + """ + if slid_size not in (4, 8): + raise AssertionError(f"Invalid SLID size {slid_size}") + + m = sha256() + m.update(symbol_name.encode("utf-8")) + hash = m.digest() + return int.from_bytes(hash[0:slid_size], byteorder='big', signed=False) + +def format_slid(slid: int, slid_size: int) -> str: + if slid_size == 4: + fmt = f"0x{slid:08X}" + elif slid_size == 8: + fmt = f"0x{slid:016X}" + return fmt + +def repl(): + while True: + sym_name = input("Symbol name? ") + slid32 = generate_slid(sym_name, 4) + slid64 = generate_slid(sym_name, 8) + print(f" 32-bit SLID for '{sym_name}': {format_slid(slid32, 4)}") + print(f" 64-bit SLID for '{sym_name}': {format_slid(slid64, 8)}") + print() + +if __name__ == "__main__": + print("LLEXT SLID calculation REPL") + print("Press ^C to exit.") + try: + repl() + except KeyboardInterrupt: + print() diff --git a/soc/andestech/ae350/linker.ld b/soc/andestech/ae350/linker.ld index 9098aa2072fab..9419856a499cd 100644 --- a/soc/andestech/ae350/linker.ld +++ b/soc/andestech/ae350/linker.ld @@ -92,6 +92,10 @@ SECTIONS #include +#ifdef CONFIG_LLEXT +#include +#endif + /* * The .plt and .iplt are here according to * 'riscv32-zephyr-elf-ld --verbose', before text section. diff --git a/soc/cdns/dc233c/include/xtensa-dc233c.ld b/soc/cdns/dc233c/include/xtensa-dc233c.ld index 87ad18b54246c..6ca6297963323 100644 --- a/soc/cdns/dc233c/include/xtensa-dc233c.ld +++ b/soc/cdns/dc233c/include/xtensa-dc233c.ld @@ -113,6 +113,10 @@ SECTIONS #include +#ifdef CONFIG_LLEXT +#include +#endif + #ifdef CONFIG_GEN_ISR_TABLES #include #endif diff --git a/soc/cdns/xtensa_sample_controller/include/xtensa-sample-controller.ld b/soc/cdns/xtensa_sample_controller/include/xtensa-sample-controller.ld index 842ec8141f4a8..bd93a0861b479 100644 --- a/soc/cdns/xtensa_sample_controller/include/xtensa-sample-controller.ld +++ b/soc/cdns/xtensa_sample_controller/include/xtensa-sample-controller.ld @@ -177,6 +177,10 @@ SECTIONS #include +#ifdef CONFIG_LLEXT +#include +#endif + #ifdef CONFIG_GEN_ISR_TABLES #include #endif diff --git a/soc/espressif/esp32/default.ld b/soc/espressif/esp32/default.ld index 338a90b99643b..4e07ecf46de35 100644 --- a/soc/espressif/esp32/default.ld +++ b/soc/espressif/esp32/default.ld @@ -152,6 +152,10 @@ SECTIONS #include +#ifdef CONFIG_LLEXT + #include +#endif + /* --- RTC BEGIN --- */ /* RTC fast memory holds RTC wake stub code, diff --git a/soc/espressif/esp32/default_appcpu.ld b/soc/espressif/esp32/default_appcpu.ld index a28399f57c4fd..57a35c474509a 100644 --- a/soc/espressif/esp32/default_appcpu.ld +++ b/soc/espressif/esp32/default_appcpu.ld @@ -55,6 +55,10 @@ SECTIONS { #include +#ifdef CONFIG_LLEXT +#include +#endif + _image_iram_start = LOADADDR(.iram0.vectors); _image_iram_size = LOADADDR(_TEXT_SECTION_NAME) + SIZEOF(_TEXT_SECTION_NAME) - _image_iram_start; _image_iram_vaddr = ADDR(.iram0.vectors); diff --git a/soc/espressif/esp32c3/default.ld b/soc/espressif/esp32c3/default.ld index 17e883373553a..849f568f1aeb9 100644 --- a/soc/espressif/esp32c3/default.ld +++ b/soc/espressif/esp32c3/default.ld @@ -129,6 +129,10 @@ SECTIONS #include +#ifdef CONFIG_LLEXT + #include +#endif + /* --- START OF RTC --- */ .rtc.text : diff --git a/soc/espressif/esp32s2/default.ld b/soc/espressif/esp32s2/default.ld index 0799af2ea4adf..03c1d75a9278f 100644 --- a/soc/espressif/esp32s2/default.ld +++ b/soc/espressif/esp32s2/default.ld @@ -136,6 +136,10 @@ SECTIONS /* Virtual non-loadable sections */ #include +#ifdef CONFIG_LLEXT +#include +#endif + /* --- START OF RTC --- */ /* RTC fast memory holds RTC wake stub code, diff --git a/soc/espressif/esp32s3/default.ld b/soc/espressif/esp32s3/default.ld index 93c9c3044b98c..17277f5ebccab 100644 --- a/soc/espressif/esp32s3/default.ld +++ b/soc/espressif/esp32s3/default.ld @@ -135,6 +135,10 @@ SECTIONS /* Virtual non-loadable sections */ #include +#ifdef CONFIG_LLEXT +#include +#endif + /* --- START OF RTC --- */ /* RTC fast memory holds RTC wake stub code */ diff --git a/soc/espressif/esp32s3/default_appcpu.ld b/soc/espressif/esp32s3/default_appcpu.ld index d5e0e2fe3e9cd..efc684161b547 100644 --- a/soc/espressif/esp32s3/default_appcpu.ld +++ b/soc/espressif/esp32s3/default_appcpu.ld @@ -38,6 +38,10 @@ SECTIONS { #include + #ifdef CONFIG_LLEXT + #include + #endif + /* Send .iram0 code to iram */ .iram0.vectors : ALIGN(4) { diff --git a/soc/infineon/cat1b/cyw20829/linker.ld b/soc/infineon/cat1b/cyw20829/linker.ld index 11b36b5117054..efe1dffa603fa 100644 --- a/soc/infineon/cat1b/cyw20829/linker.ld +++ b/soc/infineon/cat1b/cyw20829/linker.ld @@ -104,6 +104,10 @@ SECTIONS #include +#ifdef CONFIG_LLEXT +#include +#endif + /* * .plt and .iplt are here according to 'arm-zephyr-elf-ld --verbose', * before text section. diff --git a/soc/intel/intel_adsp/ace/ace-link.ld b/soc/intel/intel_adsp/ace/ace-link.ld index 454893055e171..b259c842995cc 100644 --- a/soc/intel/intel_adsp/ace/ace-link.ld +++ b/soc/intel/intel_adsp/ace/ace-link.ld @@ -490,4 +490,8 @@ SECTIONS { #ifdef CONFIG_GEN_ISR_TABLES #include #endif + +#ifdef CONFIG_LLEXT +#include +#endif } diff --git a/soc/intel/intel_adsp/cavs/include/xtensa-cavs-linker.ld b/soc/intel/intel_adsp/cavs/include/xtensa-cavs-linker.ld index e9ecbe2ba1b67..03109061fc6ad 100644 --- a/soc/intel/intel_adsp/cavs/include/xtensa-cavs-linker.ld +++ b/soc/intel/intel_adsp/cavs/include/xtensa-cavs-linker.ld @@ -503,4 +503,8 @@ SECTIONS { #ifdef CONFIG_GEN_ISR_TABLES #include #endif + +#ifdef CONFIG_LLEXT +#include +#endif } diff --git a/soc/ite/ec/it8xxx2/linker.ld b/soc/ite/ec/it8xxx2/linker.ld index 3ad9bd21df3a0..8143d789d2005 100644 --- a/soc/ite/ec/it8xxx2/linker.ld +++ b/soc/ite/ec/it8xxx2/linker.ld @@ -91,6 +91,10 @@ SECTIONS #include +#ifdef CONFIG_LLEXT +#include +#endif + /* * The .plt and .iplt are here according to * 'riscv32-zephyr-elf-ld --verbose', before text section. diff --git a/soc/nxp/imx/imx8/adsp/linker.ld b/soc/nxp/imx/imx8/adsp/linker.ld index 52d3a46b2381a..caaaf8e60d1f3 100644 --- a/soc/nxp/imx/imx8/adsp/linker.ld +++ b/soc/nxp/imx/imx8/adsp/linker.ld @@ -173,6 +173,10 @@ SECTIONS { #include + +#ifdef CONFIG_LLEXT +#include +#endif .ResetVector.text : ALIGN(4) { _ResetVector_text_start = ABSOLUTE(.); diff --git a/soc/nxp/imx/imx8m/adsp/linker.ld b/soc/nxp/imx/imx8m/adsp/linker.ld index 97d969d476fcb..6ca8e72982e7b 100644 --- a/soc/nxp/imx/imx8m/adsp/linker.ld +++ b/soc/nxp/imx/imx8m/adsp/linker.ld @@ -179,6 +179,10 @@ SECTIONS #endif #include + +#ifdef CONFIG_LLEXT +#include +#endif .ResetVector.text : ALIGN(4) { _ResetVector_text_start = ABSOLUTE(.); diff --git a/soc/nxp/imx/imx8ulp/adsp/linker.ld b/soc/nxp/imx/imx8ulp/adsp/linker.ld index 4b5aec29742a7..96bd687917fbe 100644 --- a/soc/nxp/imx/imx8ulp/adsp/linker.ld +++ b/soc/nxp/imx/imx8ulp/adsp/linker.ld @@ -173,6 +173,10 @@ SECTIONS { #include + +#ifdef CONFIG_LLEXT +#include +#endif .ResetVector.text : ALIGN(4) { _ResetVector_text_start = ABSOLUTE(.); diff --git a/soc/nxp/imx/imx8x/adsp/linker.ld b/soc/nxp/imx/imx8x/adsp/linker.ld index 52d3a46b2381a..caaaf8e60d1f3 100644 --- a/soc/nxp/imx/imx8x/adsp/linker.ld +++ b/soc/nxp/imx/imx8x/adsp/linker.ld @@ -173,6 +173,10 @@ SECTIONS { #include + +#ifdef CONFIG_LLEXT +#include +#endif .ResetVector.text : ALIGN(4) { _ResetVector_text_start = ABSOLUTE(.); diff --git a/soc/nxp/imx/imx9/a55/linker.ld b/soc/nxp/imx/imx9/a55/linker.ld index 102d9f1b0445d..53982a309c860 100644 --- a/soc/nxp/imx/imx9/a55/linker.ld +++ b/soc/nxp/imx/imx9/a55/linker.ld @@ -71,6 +71,10 @@ SECTIONS #include +#ifdef CONFIG_LLEXT +#include +#endif + /* * .plt and .iplt are here according to 'arm-zephyr-elf-ld --verbose', * before text section. diff --git a/soc/nxp/imxrt/imxrt5xx/f1/linker.ld b/soc/nxp/imxrt/imxrt5xx/f1/linker.ld index adc8b87fb6213..de1e89846530b 100644 --- a/soc/nxp/imxrt/imxrt5xx/f1/linker.ld +++ b/soc/nxp/imxrt/imxrt5xx/f1/linker.ld @@ -134,6 +134,10 @@ SECTIONS { #include + +#ifdef CONFIG_LLEXT +#include +#endif .ResetVector.text : ALIGN(4) { _ResetVector_text_start = ABSOLUTE(.); diff --git a/soc/openisa/rv32m1/linker.ld b/soc/openisa/rv32m1/linker.ld index 784ba791722bf..b81a77868a908 100644 --- a/soc/openisa/rv32m1/linker.ld +++ b/soc/openisa/rv32m1/linker.ld @@ -87,6 +87,10 @@ SECTIONS #include +#ifdef CONFIG_LLEXT +#include +#endif + SECTION_PROLOGUE(.plt,,) { *(.plt) diff --git a/soc/st/stm32/stm32mp1x/linker.ld b/soc/st/stm32/stm32mp1x/linker.ld index 7f9a84501ef11..83f3511b7088e 100644 --- a/soc/st/stm32/stm32mp1x/linker.ld +++ b/soc/st/stm32/stm32mp1x/linker.ld @@ -13,6 +13,11 @@ SECTIONS { #include + +#ifdef CONFIG_LLEXT +#include +#endif + #ifdef CONFIG_OPENAMP_RSC_TABLE SECTION_PROLOGUE(.resource_table,, SUBALIGN(4)) diff --git a/subsys/llext/Kconfig b/subsys/llext/Kconfig index 8984cb3ca3988..4ad2aca1c0379 100644 --- a/subsys/llext/Kconfig +++ b/subsys/llext/Kconfig @@ -66,6 +66,21 @@ config LLEXT_STORAGE_WRITABLE Select if LLEXT storage is writable, i.e. if extensions are stored in RAM and can be modified in place +config LLEXT_EXPORT_BUILTINS_BY_SLID + bool "Export built-in symbols to llexts via SLIDs" + help + When enabled, symbols exported from the Zephyr kernel + or application (via EXPORT_SYMBOL) are linked to LLEXTs + via Symbol Link Identifiers (SLIDs) instead of name. + + Enabling this option provides a huge size reduction, + makes the linking process faster and provides more + confidentiality, as exported symbol names are dropped + from the binary. However, it can make LLEXT debugging + harder and prevents usage of 'llext_find_sym' to look + up symbols from the built-in table by name. It also + requires the LLEXTs to be post-processed after build. + module = LLEXT module-str = llext source "subsys/logging/Kconfig.template.log_config" diff --git a/subsys/llext/llext.c b/subsys/llext/llext.c index 856b322c49ae1..a647ac3bc27b0 100644 --- a/subsys/llext/llext.c +++ b/subsys/llext/llext.c @@ -24,6 +24,12 @@ LOG_MODULE_REGISTER(llext, CONFIG_LLEXT_LOG_LEVEL); #define LLEXT_PAGE_SIZE 32 #endif +#ifdef CONFIG_LLEXT_EXPORT_BUILTINS_BY_SLID +#define SYM_NAME_OR_SLID(name, slid) ((const char *)slid) +#else +#define SYM_NAME_OR_SLID(name, slid) name +#endif + K_HEAP_DEFINE(llext_heap, CONFIG_LLEXT_HEAP_SIZE * 1024); static const char ELF_MAGIC[] = {0x7f, 'E', 'L', 'F'}; @@ -118,11 +124,27 @@ const void *llext_find_sym(const struct llext_symtable *sym_table, const char *s { if (sym_table == NULL) { /* Built-in symbol table */ +#ifdef CONFIG_LLEXT_EXPORT_BUILTINS_BY_SLID + /* 'sym_name' is actually a SLID to search for */ + uintptr_t slid = (uintptr_t)sym_name; + + /* TODO: perform a binary search instead of linear. + * Note that - as of writing - the llext_const_symbol_area + * section is sorted in ascending SLID order. + * (see scripts/build/llext_prepare_exptab.py) + */ + STRUCT_SECTION_FOREACH(llext_const_symbol, sym) { + if (slid == sym->slid) { + return sym->addr; + } + } +#else STRUCT_SECTION_FOREACH(llext_const_symbol, sym) { if (strcmp(sym->name, sym_name) == 0) { return sym->addr; } } +#endif } else { /* find symbols in module */ for (size_t i = 0; i < sym_table->sym_cnt; i++) { @@ -728,7 +750,8 @@ static void llext_link_plt(struct llext_loader *ldr, struct llext *ext, switch (stb) { case STB_GLOBAL: - link_addr = llext_find_sym(NULL, name); + link_addr = llext_find_sym(NULL, + SYM_NAME_OR_SLID(name, sym_tbl.st_value)); if (!link_addr) link_addr = llext_find_sym(&ext->sym_tab, name); @@ -864,7 +887,8 @@ static int llext_link(struct llext_loader *ldr, struct llext *ext, bool do_local link_addr = 0; } else if (sym.st_shndx == SHN_UNDEF) { /* If symbol is undefined, then we need to look it up */ - link_addr = (uintptr_t)llext_find_sym(NULL, name); + link_addr = (uintptr_t)llext_find_sym(NULL, + SYM_NAME_OR_SLID(name, sym.st_value)); if (link_addr == 0) { LOG_ERR("Undefined symbol with no entry in " diff --git a/tests/subsys/llext/simple/src/test_llext_simple.c b/tests/subsys/llext/simple/src/test_llext_simple.c index 68b318f5e1c80..91a3c3e6f3d2a 100644 --- a/tests/subsys/llext/simple/src/test_llext_simple.c +++ b/tests/subsys/llext/simple/src/test_llext_simple.c @@ -24,6 +24,20 @@ LOG_MODULE_REGISTER(test_llext_simple); #define LLEXT_CONST const #endif +#ifdef CONFIG_LLEXT_EXPORT_BUILTINS_BY_SLID +#define LLEXT_FIND_BUILTIN_SYM(symbol_name) llext_find_sym(NULL, symbol_name ## _SLID) + +#ifdef CONFIG_64BIT +#define printk_SLID ((const char *)0x87B3105268827052ull) +#define z_impl_ext_syscall_fail_SLID ((const char *)0xD58BC0E7C64CD965ull) +#else +#define printk_SLID ((const char *)0x87B31052ull) +#define z_impl_ext_syscall_fail_SLID ((const char *)0xD58BC0E7ull) +#endif +#else +#define LLEXT_FIND_BUILTIN_SYM(symbol_name) llext_find_sym(NULL, # symbol_name) +#endif + struct llext_test { const char *name; bool try_userspace; @@ -271,7 +285,7 @@ ZTEST(llext, test_pre_located) */ ZTEST(llext, test_printk_exported) { - const void * const printk_fn = llext_find_sym(NULL, "printk"); + const void * const printk_fn = LLEXT_FIND_BUILTIN_SYM(printk); zassert_equal(printk_fn, printk, "printk should be an exported symbol"); } @@ -282,8 +296,9 @@ ZTEST(llext, test_printk_exported) */ ZTEST(llext, test_ext_syscall_fail) { - const void * const esf_fn = llext_find_sym(NULL, - "z_impl_ext_syscall_fail"); + const void * const esf_fn = LLEXT_FIND_BUILTIN_SYM(z_impl_ext_syscall_fail); + + zassert_not_null(esf_fn, "est_fn should not be NULL"); zassert_is_null(*(uintptr_t **)esf_fn, NULL, "ext_syscall_fail should be NULL"); diff --git a/tests/subsys/llext/simple/testcase.yaml b/tests/subsys/llext/simple/testcase.yaml index 6325bd51425c9..8a3aca97037d7 100644 --- a/tests/subsys/llext/simple/testcase.yaml +++ b/tests/subsys/llext/simple/testcase.yaml @@ -80,3 +80,71 @@ tests: - CONFIG_USERSPACE=y - CONFIG_MODULES=y - CONFIG_LLEXT_TEST_HELLO=m + llext.simple.readonly_slid_linking: + arch_exclude: xtensa # for now + filter: not CONFIG_MPU and not CONFIG_MMU and not CONFIG_SOC_SERIES_S32ZE + extra_configs: + - arch:arm:CONFIG_ARM_MPU=n + - CONFIG_LLEXT_STORAGE_WRITABLE=n + - CONFIG_LLEXT_EXPORT_BUILTINS_BY_SLID=y + llext.simple.readonly_mpu_slid_linking: + min_ram: 128 + arch_exclude: xtensa # for now + filter: CONFIG_ARCH_HAS_USERSPACE + extra_configs: + - CONFIG_USERSPACE=y + - CONFIG_LLEXT_STORAGE_WRITABLE=n + - CONFIG_LLEXT_EXPORT_BUILTINS_BY_SLID=y + llext.simple.writable_slid_linking: + filter: not CONFIG_MPU and not CONFIG_MMU and not CONFIG_SOC_SERIES_S32ZE + extra_configs: + - arch:arm:CONFIG_ARM_MPU=n + - CONFIG_LLEXT_STORAGE_WRITABLE=y + llext.simple.modules_enabled_writable_slid_linking: + filter: not CONFIG_MPU and not CONFIG_MMU + platform_key: + - simulation + - arch + platform_exclude: + - qemu_cortex_a9 # MMU + extra_configs: + - arch:arm:CONFIG_ARM_MPU=n + - CONFIG_MODULES=y + - CONFIG_LLEXT_STORAGE_WRITABLE=y + - CONFIG_LLEXT_TEST_HELLO=m + - CONFIG_LLEXT_EXPORT_BUILTINS_BY_SLID=y + llext.simple.modules_enabled_writable_relocatable_slid_linking: + arch_exclude: arm arm64 + filter: not CONFIG_MPU and not CONFIG_MMU + integration_platforms: + - qemu_xtensa + extra_configs: + - CONFIG_MODULES=y + - CONFIG_LLEXT_STORAGE_WRITABLE=y + - CONFIG_LLEXT_TYPE_ELF_RELOCATABLE=y + - CONFIG_LLEXT_TEST_HELLO=m + - CONFIG_LLEXT_EXPORT_BUILTINS_BY_SLID=y + llext.simple.modules_enabled_readonly_slid_linking: + filter: not CONFIG_MPU and not CONFIG_MMU + arch_exclude: xtensa # for now + platform_key: + - simulation + - arch + platform_exclude: + - qemu_cortex_a9 # MMU + extra_configs: + - arch:arm:CONFIG_ARM_MPU=n + - CONFIG_MODULES=y + - CONFIG_LLEXT_TEST_HELLO=m + - CONFIG_LLEXT_EXPORT_BUILTINS_BY_SLID=y + llext.simple.modules_enabled_readonly_mpu_slid_linking: + filter: CONFIG_ARCH_HAS_USERSPACE + arch_exclude: xtensa # for now + platform_key: + - simulation + - arch + extra_configs: + - CONFIG_USERSPACE=y + - CONFIG_MODULES=y + - CONFIG_LLEXT_TEST_HELLO=m + - CONFIG_LLEXT_EXPORT_BUILTINS_BY_SLID=y From 912a581a9572ea448e7e6d6b4c0b05b556fc2b67 Mon Sep 17 00:00:00 2001 From: Luca Burelli Date: Thu, 15 Feb 2024 15:12:10 +0100 Subject: [PATCH 1593/2849] drivers/led: add IS31FL3194 LED driver Add support for the IS31FL3194 3-channel LED driver. This driver can be configured to handle its outputs as either a single RGB LED or (up to) three independent LEDs. Signed-off-by: Luca Burelli --- drivers/led/CMakeLists.txt | 1 + drivers/led/Kconfig | 1 + drivers/led/Kconfig.is31fl3194 | 11 + drivers/led/is31fl3194.c | 359 ++++++++++++++++++++++++++ dts/bindings/led/issi,is31fl3194.yaml | 74 ++++++ 5 files changed, 446 insertions(+) create mode 100644 drivers/led/Kconfig.is31fl3194 create mode 100644 drivers/led/is31fl3194.c create mode 100644 dts/bindings/led/issi,is31fl3194.yaml diff --git a/drivers/led/CMakeLists.txt b/drivers/led/CMakeLists.txt index c3d90d0ba06ff..09ea5e202fdf5 100644 --- a/drivers/led/CMakeLists.txt +++ b/drivers/led/CMakeLists.txt @@ -18,6 +18,7 @@ zephyr_library_sources_ifdef(CONFIG_NCP5623 ncp5623.c) zephyr_library_sources_ifdef(CONFIG_PCA9633 pca9633.c) zephyr_library_sources_ifdef(CONFIG_TLC59108 tlc59108.c) zephyr_library_sources_ifdef(CONFIG_IS31FL3733 is31fl3733.c) +zephyr_library_sources_ifdef(CONFIG_IS31FL3194 is31fl3194.c) zephyr_library_sources_ifdef(CONFIG_LED_SHELL led_shell.c) diff --git a/drivers/led/Kconfig b/drivers/led/Kconfig index 7808a1013ae9c..26bf49cd5e2ae 100644 --- a/drivers/led/Kconfig +++ b/drivers/led/Kconfig @@ -40,5 +40,6 @@ source "drivers/led/Kconfig.pwm" source "drivers/led/Kconfig.tlc59108" source "drivers/led/Kconfig.xec" source "drivers/led/Kconfig.is31fl3733" +source "drivers/led/Kconfig.is31fl3194" endif # LED diff --git a/drivers/led/Kconfig.is31fl3194 b/drivers/led/Kconfig.is31fl3194 new file mode 100644 index 0000000000000..42166805a1d16 --- /dev/null +++ b/drivers/led/Kconfig.is31fl3194 @@ -0,0 +1,11 @@ +# Copyright (c) 2024 Arduino SA +# SPDX-License-Identifier: Apache-2.0 + +config IS31FL3194 + bool "IS31FL3194 LED driver" + default y + depends on DT_HAS_ISSI_IS31FL3194_ENABLED + select I2C + help + Enable LED driver for Lumissil Microsystems (a division of ISSI) + IS31FL3194. This chip supports one RGB LED or 3 independent LEDs. diff --git a/drivers/led/is31fl3194.c b/drivers/led/is31fl3194.c new file mode 100644 index 0000000000000..5b0c34ebf571c --- /dev/null +++ b/drivers/led/is31fl3194.c @@ -0,0 +1,359 @@ +/* + * Copyright (c) 2024 Arduino SA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT issi_is31fl3194 + +/** + * @file + * @brief IS31FL3194 LED driver + * + * The IS31FL3194 is a 3-channel LED driver that communicates over I2C. + */ + +#include +#include +#include +#include +#include + +#include + +LOG_MODULE_REGISTER(is31fl3194, CONFIG_LED_LOG_LEVEL); + +#define IS31FL3194_PROD_ID_REG 0x00 +#define IS31FL3194_CONF_REG 0x01 +#define IS31FL3194_CURRENT_REG 0x03 +#define IS31FL3194_OUT1_REG 0x10 +#define IS31FL3194_OUT2_REG 0x21 +#define IS31FL3194_OUT3_REG 0x32 +#define IS31FL3194_UPDATE_REG 0x40 + +#define IS31FL3194_PROD_ID_VAL 0xce +#define IS31FL3194_CONF_ENABLE 0x01 +#define IS31FL3194_UPDATE_VAL 0xc5 + +#define IS31FL3194_CHANNEL_COUNT 3 + +static const uint8_t led_channels[] = { + IS31FL3194_OUT1_REG, + IS31FL3194_OUT2_REG, + IS31FL3194_OUT3_REG +}; + +struct is31fl3194_config { + struct i2c_dt_spec bus; + uint8_t num_leds; + const struct led_info *led_infos; + const uint8_t *current_limits; +}; + +static const struct led_info *is31fl3194_led_to_info(const struct is31fl3194_config *config, + uint32_t led) +{ + if (led < config->num_leds) { + return &config->led_infos[led]; + } + + return NULL; +} + +static int is31fl3194_get_info(const struct device *dev, + uint32_t led, + const struct led_info **info_out) +{ + const struct is31fl3194_config *config = dev->config; + const struct led_info *info = is31fl3194_led_to_info(config, led); + + if (info == NULL) { + return -EINVAL; + } + + *info_out = info; + return 0; +} + +static int is31fl3194_set_color(const struct device *dev, uint32_t led, uint8_t num_colors, + const uint8_t *color) +{ + const struct is31fl3194_config *config = dev->config; + const struct led_info *info = is31fl3194_led_to_info(config, led); + int ret; + + if (info == NULL) { + return -ENODEV; + } + + if (info->num_colors != 3) { + return -ENOTSUP; + } + + if (num_colors != 3) { + return -EINVAL; + } + + for (int i = 0; i < 3; i++) { + uint8_t value; + + switch (info->color_mapping[i]) { + case LED_COLOR_ID_RED: + value = color[0]; + break; + case LED_COLOR_ID_GREEN: + value = color[1]; + break; + case LED_COLOR_ID_BLUE: + value = color[2]; + break; + default: + /* unreachable: mapping already tested in is31fl3194_check_config */ + continue; + } + + ret = i2c_reg_write_byte_dt(&config->bus, led_channels[i], value); + if (ret != 0) { + break; + } + } + + if (ret == 0) { + ret = i2c_reg_write_byte_dt(&config->bus, + IS31FL3194_UPDATE_REG, + IS31FL3194_UPDATE_VAL); + } + + if (ret != 0) { + LOG_ERR("%s: LED write failed: %d", dev->name, ret); + } + + return ret; +} + +static int is31fl3194_set_brightness(const struct device *dev, uint32_t led, uint8_t value) +{ + const struct is31fl3194_config *config = dev->config; + const struct led_info *info = is31fl3194_led_to_info(config, led); + int ret = 0; + + if (info == NULL) { + return -ENODEV; + } + + if (info->num_colors != 1) { + return -ENOTSUP; + } + + if (value > 100) { + return -EINVAL; + } + + /* Rescale 0..100 to 0..255 */ + value = value * 255 / 100; + + ret = i2c_reg_write_byte_dt(&config->bus, led_channels[led], value); + if (ret == 0) { + ret = i2c_reg_write_byte_dt(&config->bus, + IS31FL3194_UPDATE_REG, + IS31FL3194_UPDATE_VAL); + } + + if (ret != 0) { + LOG_ERR("%s: LED write failed", dev->name); + } + + return ret; +} + +static inline int is31fl3194_led_on(const struct device *dev, uint32_t led) +{ + return is31fl3194_set_brightness(dev, led, 100); +} + +static inline int is31fl3194_led_off(const struct device *dev, uint32_t led) +{ + return is31fl3194_set_brightness(dev, led, 0); +} + +/* + * Counts red, green, blue channels; returns true if color_id is valid + * and no more than one channel maps to the same color + */ +static bool is31fl3194_count_colors(const struct device *dev, + uint8_t color_id, uint8_t *rgb_counts) +{ + bool ret = false; + + switch (color_id) { + case LED_COLOR_ID_RED: + ret = (++rgb_counts[0] == 1); + break; + case LED_COLOR_ID_GREEN: + ret = (++rgb_counts[1] == 1); + break; + case LED_COLOR_ID_BLUE: + ret = (++rgb_counts[2] == 1); + break; + } + + if (!ret) { + LOG_ERR("%s: invalid color %d (duplicate or not RGB)", + dev->name, color_id); + } + + return ret; +} + +static int is31fl3194_check_config(const struct device *dev) +{ + const struct is31fl3194_config *config = dev->config; + const struct led_info *info; + uint8_t rgb_counts[3] = { 0 }; + uint8_t i; + + switch (config->num_leds) { + case 1: + /* check that it is a three-channel LED */ + info = &config->led_infos[0]; + + if (info->num_colors != 3) { + LOG_ERR("%s: invalid number of colors %d " + "(must be 3 for RGB LED)", + dev->name, info->num_colors); + return -EINVAL; + } + + for (i = 0; i < 3; i++) { + if (!is31fl3194_count_colors(dev, info->color_mapping[i], rgb_counts)) { + return -EINVAL; + } + + } + break; + case 3: + /* check that each LED is single-color */ + for (i = 0; i < 3; i++) { + info = &config->led_infos[i]; + + if (info->num_colors != 1) { + LOG_ERR("%s: invalid number of colors %d " + "(must be 1 when defining multiple LEDs)", + dev->name, info->num_colors); + return -EINVAL; + } + + if (!is31fl3194_count_colors(dev, info->color_mapping[0], rgb_counts)) { + return -EINVAL; + } + } + break; + default: + LOG_ERR("%s: invalid number of LEDs %d (must be 1 or 3)", + dev->name, config->num_leds); + return -EINVAL; + } + + return 0; +} + +static int is31fl3194_init(const struct device *dev) +{ + const struct is31fl3194_config *config = dev->config; + const struct led_info *info = NULL; + int i, ret; + uint8_t prod_id, band; + uint8_t current_reg = 0; + + ret = is31fl3194_check_config(dev); + if (ret != 0) { + return ret; + } + + if (!i2c_is_ready_dt(&config->bus)) { + LOG_ERR("%s: I2C device not ready", dev->name); + return -ENODEV; + } + + ret = i2c_reg_read_byte_dt(&config->bus, IS31FL3194_PROD_ID_REG, &prod_id); + if (ret != 0) { + LOG_ERR("%s: failed to read product ID", dev->name); + return ret; + } + + if (prod_id != IS31FL3194_PROD_ID_VAL) { + LOG_ERR("%s: invalid product ID 0x%02x (expected 0x%02x)", dev->name, prod_id, + IS31FL3194_PROD_ID_VAL); + return -ENODEV; + } + + /* calc current limit register value */ + info = &config->led_infos[0]; + if (info->num_colors == IS31FL3194_CHANNEL_COUNT) { + /* one RGB LED: set all channels to the same current limit */ + band = (config->current_limits[0] / 10) - 1; + for (i = 0; i < IS31FL3194_CHANNEL_COUNT; i++) { + current_reg |= band << (2 * i); + } + } else { + /* single-channel LEDs: independent limits */ + for (i = 0; i < config->num_leds; i++) { + band = (config->current_limits[i] / 10) - 1; + current_reg |= band << (2 * i); + } + } + + ret = i2c_reg_write_byte_dt(&config->bus, IS31FL3194_CURRENT_REG, current_reg); + if (ret != 0) { + LOG_ERR("%s: failed to set current limit", dev->name); + return ret; + } + + /* enable device */ + return i2c_reg_write_byte_dt(&config->bus, IS31FL3194_CONF_REG, IS31FL3194_CONF_ENABLE); +} + +static const struct led_driver_api is31fl3194_led_api = { + .set_brightness = is31fl3194_set_brightness, + .on = is31fl3194_led_on, + .off = is31fl3194_led_off, + .get_info = is31fl3194_get_info, + .set_color = is31fl3194_set_color, +}; + +#define COLOR_MAPPING(led_node_id) \ + static const uint8_t color_mapping_##led_node_id[] = \ + DT_PROP(led_node_id, color_mapping); + +#define LED_INFO(led_node_id) \ + { \ + .label = DT_PROP(led_node_id, label), \ + .num_colors = DT_PROP_LEN(led_node_id, color_mapping), \ + .color_mapping = color_mapping_##led_node_id, \ + }, + +#define LED_CURRENT(led_node_id) \ + DT_PROP(led_node_id, current_limit), + +#define IS31FL3194_DEFINE(id) \ + \ + DT_INST_FOREACH_CHILD(id, COLOR_MAPPING) \ + \ + static const struct led_info is31fl3194_leds_##id[] = \ + { DT_INST_FOREACH_CHILD(id, LED_INFO) }; \ + static const uint8_t is31fl3194_currents_##id[] = \ + { DT_INST_FOREACH_CHILD(id, LED_CURRENT) }; \ + BUILD_ASSERT(ARRAY_SIZE(is31fl3194_leds_##id) > 0, \ + "No LEDs defined for " #id); \ + \ + static const struct is31fl3194_config is31fl3194_config_##id = { \ + .bus = I2C_DT_SPEC_INST_GET(id), \ + .num_leds = ARRAY_SIZE(is31fl3194_leds_##id), \ + .led_infos = is31fl3194_leds_##id, \ + .current_limits = is31fl3194_currents_##id, \ + }; \ + DEVICE_DT_INST_DEFINE(id, &is31fl3194_init, NULL, NULL, \ + &is31fl3194_config_##id, POST_KERNEL, \ + CONFIG_LED_INIT_PRIORITY, &is31fl3194_led_api); + +DT_INST_FOREACH_STATUS_OKAY(IS31FL3194_DEFINE) diff --git a/dts/bindings/led/issi,is31fl3194.yaml b/dts/bindings/led/issi,is31fl3194.yaml new file mode 100644 index 0000000000000..4d07a36d7a4aa --- /dev/null +++ b/dts/bindings/led/issi,is31fl3194.yaml @@ -0,0 +1,74 @@ +# Copyright (c) 2024 Arduino SA +# SPDX-License-Identifier: Apache-2.0 + +description: | + IS31FL3194 3-channel LED driver with programmable pattern sequencing + + This driver supports single-channel and RGB LEDs. For single channel LEDs, + the led_set_brightness() API can be used to set the brightness of each LED. + For RGB LEDs, the led_set_color() API can be used to set the red, green and + blue components; the driver takes care of routing to the outputs described + by the color-mapping property. + + The LED_SHELL application can be used for testing. + + The following defines a single RGB LED in the is31fl3194 DT node: + + is31fl3194@53 { + compatible = "issi,is31fl3194"; + reg = <0x53>; + + led_0 { + label = "RGB LED"; + color-mapping = + , + , + ; + }; + }; + + The following example defines three single-channel LEDs in the is31fl3194 DT node: + + is31fl3194@53 { + compatible = "issi,is31fl3194"; + reg = <0x53>; + + led_0 { + label = "RED LED"; + color-mapping = ; + }; + + led_1 { + label = "GREEN LED"; + color-mapping = ; + }; + + led_2 { + label = "BLUE LED"; + color-mapping = ; + }; + }; + + +compatible: "issi,is31fl3194" + +include: ["i2c-device.yaml", "led-controller.yaml"] + +child-binding: + properties: + label: + required: true + + color-mapping: + required: true + + current-limit: + type: int + enum: + - 10 + - 20 + - 30 + - 40 + required: true + description: | + The current limit for the LED in mA. From 5fea5c4358f06e72d71aeec46938820be4a3bfc5 Mon Sep 17 00:00:00 2001 From: Luca Burelli Date: Tue, 20 Feb 2024 18:04:11 +0100 Subject: [PATCH 1594/2849] arduino_nicla_sense_me: add RGB LED support to the device tree This patch enables the user to control the RGB LED on the Arduino Nicla Sense ME board. The RGB LED is controlled by the IS31FL3194 LED driver and is connected to the I2C0 bus. Signed-off-by: Luca Burelli --- .../nicla_sense_me/arduino_nicla_sense_me.dts | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/boards/arduino/nicla_sense_me/arduino_nicla_sense_me.dts b/boards/arduino/nicla_sense_me/arduino_nicla_sense_me.dts index 2329853a1a3bb..87d1affecd604 100644 --- a/boards/arduino/nicla_sense_me/arduino_nicla_sense_me.dts +++ b/boards/arduino/nicla_sense_me/arduino_nicla_sense_me.dts @@ -8,6 +8,7 @@ #include #include "arduino_nicla_sense_me-pinctrl.dtsi" #include +#include / { model = "Arduino Nicla Sense ME"; @@ -73,6 +74,18 @@ pinctrl-0 = <&i2c0_default>; pinctrl-1 = <&i2c0_sleep>; pinctrl-names = "default", "sleep"; + + is31fl3194@53 { + compatible = "issi,is31fl3194"; + reg = <0x53>; + led_rgb { + label = "RGB LED"; + color-mapping = , + , + ; + current-limit = <10>; + }; + }; }; /* I2C1 in datasheet */ From 0d2b3e1f36b75eb188b8668bc63f0b218b7b2300 Mon Sep 17 00:00:00 2001 From: Luca Burelli Date: Fri, 16 Feb 2024 11:05:49 +0100 Subject: [PATCH 1595/2849] samples: add IS31FL3194 RGB LED driver sample This sample app cycles several colors on an RGB LED forever using the LED API. It can be built and executed on an Arduino Nicla Sense ME, or on any board where the devicetree has a similar compatible I2C device node. Signed-off-by: Luca Burelli --- samples/drivers/led_is31fl3194/CMakeLists.txt | 7 +++ samples/drivers/led_is31fl3194/README.rst | 28 +++++++++ samples/drivers/led_is31fl3194/prj.conf | 2 + samples/drivers/led_is31fl3194/sample.yaml | 10 ++++ samples/drivers/led_is31fl3194/src/main.c | 58 +++++++++++++++++++ 5 files changed, 105 insertions(+) create mode 100644 samples/drivers/led_is31fl3194/CMakeLists.txt create mode 100644 samples/drivers/led_is31fl3194/README.rst create mode 100644 samples/drivers/led_is31fl3194/prj.conf create mode 100644 samples/drivers/led_is31fl3194/sample.yaml create mode 100644 samples/drivers/led_is31fl3194/src/main.c diff --git a/samples/drivers/led_is31fl3194/CMakeLists.txt b/samples/drivers/led_is31fl3194/CMakeLists.txt new file mode 100644 index 0000000000000..ed52c77a3fd0e --- /dev/null +++ b/samples/drivers/led_is31fl3194/CMakeLists.txt @@ -0,0 +1,7 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(led_is31fl3194) + +target_sources(app PRIVATE src/main.c) diff --git a/samples/drivers/led_is31fl3194/README.rst b/samples/drivers/led_is31fl3194/README.rst new file mode 100644 index 0000000000000..0773587a4f80e --- /dev/null +++ b/samples/drivers/led_is31fl3194/README.rst @@ -0,0 +1,28 @@ +.. zephyr:code-sample:: is31fl3194 + :name: IS31FL3194 RGB LED + :relevant-api: led_interface + + Cycle colors on an RGB LED connected to the IS31FL3194 using the LED API. + +Overview +******** + +This sample cycles several colors on an RGB LED forever using the LED API. + +Building and Running +******************** + +This sample can be built and executed on an Arduino Nicla Sense ME, or on +any board where the devicetree has an I2C device node with compatible +:dtcompatible:`issi,is31fl3194` enabled, along with the relevant bus +controller node also being enabled. + +.. zephyr-app-commands:: + :zephyr-app: samples/drivers/led/issi_is31fl3194 + :board: arduino_nicla_sense_me + :goals: build flash + :compact: + +After flashing, the LED starts to switch colors and messages with the current +LED color are printed on the console. If a runtime error occurs, the sample +exits without printing to the console. diff --git a/samples/drivers/led_is31fl3194/prj.conf b/samples/drivers/led_is31fl3194/prj.conf new file mode 100644 index 0000000000000..555740ded902d --- /dev/null +++ b/samples/drivers/led_is31fl3194/prj.conf @@ -0,0 +1,2 @@ +CONFIG_LED=y +CONFIG_LOG=y diff --git a/samples/drivers/led_is31fl3194/sample.yaml b/samples/drivers/led_is31fl3194/sample.yaml new file mode 100644 index 0000000000000..0cb932b05d2ee --- /dev/null +++ b/samples/drivers/led_is31fl3194/sample.yaml @@ -0,0 +1,10 @@ +sample: + description: Demonstration of the IS31FL3194 LED driver + name: is31fl3194 sample +tests: + sample.drivers.led.is31fl3194: + filter: dt_compat_enabled("issi,is31fl3194") + tags: LED + depends_on: i2c + integration_platforms: + - arduino_nicla_sense_me diff --git a/samples/drivers/led_is31fl3194/src/main.c b/samples/drivers/led_is31fl3194/src/main.c new file mode 100644 index 0000000000000..335d152101b0f --- /dev/null +++ b/samples/drivers/led_is31fl3194/src/main.c @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2024 Arduino SA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +/* 1000 msec = 1 sec */ +#define SLEEP_TIME_MS 1000 + +/* Structure describing a color by its component values and name */ +struct color_data { + uint8_t r, g, b; + const char *name; +}; + +/* The sequence of colors the RGB LED will display */ +static const struct color_data color_sequence[] = { + { 0xFF, 0x00, 0x00, "Red" }, + { 0x00, 0xFF, 0x00, "Green" }, + { 0x00, 0x00, 0xFF, "Blue" }, + { 0xFF, 0xFF, 0xFF, "White" }, + { 0xFF, 0xFF, 0x00, "Yellow" }, + { 0xFF, 0x00, 0xFF, "Purple" }, + { 0x00, 0xFF, 0xFF, "Cyan" }, + { 0xF4, 0x79, 0x20, "Orange" }, +}; + +/* + * A build error on this line means your board is unsupported. + */ +const struct device *led = DEVICE_DT_GET_ANY(issi_is31fl3194); + +int main(void) +{ + int ret; + int i = 0; + + if (!device_is_ready(led)) { + return 0; + } + + while (1) { + ret = led_set_color(led, 0, 3, &(color_sequence[i].r)); + if (ret < 0) { + return 0; + } + + printk("LED color: %s\n", color_sequence[i].name); + k_msleep(SLEEP_TIME_MS); + i = (i + 1) % ARRAY_SIZE(color_sequence); + } + + return 0; +} From 1541fe9e2f787ac3a10d3d90297f185bbfa36a86 Mon Sep 17 00:00:00 2001 From: Kai Vehmanen Date: Thu, 30 May 2024 15:01:27 +0300 Subject: [PATCH 1596/2849] intel_adsp/ace: power: fix address space annotation for powerdown power_down() expects a cached pointer. Fix the sparse annotation to match the implementation (sys_cache_cached_ptr_get() returns a cached pointer so this is correct). Signed-off-by: Kai Vehmanen --- soc/intel/intel_adsp/ace/power.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/soc/intel/intel_adsp/ace/power.c b/soc/intel/intel_adsp/ace/power.c index afc270f9afa07..6eb504178e335 100644 --- a/soc/intel/intel_adsp/ace/power.c +++ b/soc/intel/intel_adsp/ace/power.c @@ -72,8 +72,8 @@ __imr void power_init(void) * (each bit corresponds to one ebb) * @param response_to_ipc flag if ipc response should be send during power down */ -extern void power_down(bool disable_lpsram, uint32_t *hpsram_pg_mask, - bool response_to_ipc); +extern void power_down(bool disable_lpsram, uint32_t __sparse_cache * hpsram_pg_mask, + bool response_to_ipc); #ifdef CONFIG_ADSP_IMR_CONTEXT_SAVE /** From e087d1bbb364466ebf2a2c03fc74f7c9579e404d Mon Sep 17 00:00:00 2001 From: Henrik Brix Andersen Date: Thu, 30 May 2024 19:48:23 +0000 Subject: [PATCH 1597/2849] tests: drivers: can: api: add test for frame without data Add test for sending/receing a CAN classic frame with no data. Signed-off-by: Henrik Brix Andersen --- tests/drivers/can/api/src/classic.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/tests/drivers/can/api/src/classic.c b/tests/drivers/can/api/src/classic.c index 9355651b7f19b..077f547cad102 100644 --- a/tests/drivers/can/api/src/classic.c +++ b/tests/drivers/can/api/src/classic.c @@ -818,6 +818,33 @@ ZTEST(can_classic, test_send_receive_std_id) &test_std_frame_1, &test_std_frame_2); } +/** + * @brief Test send/receive with standard (11-bit) CAN IDs without no data. + */ +ZTEST(can_classic, test_send_receive_std_id_no_data) +{ + const struct can_frame frame = { + .flags = 0, + .id = TEST_CAN_STD_ID_1, + .dlc = 0, + .data = { 0 } + }; + struct can_frame frame_buffer; + int filter_id; + int err; + + filter_id = add_rx_msgq(can_dev, &test_std_filter_1); + err = can_send(can_dev, &frame, TEST_SEND_TIMEOUT, NULL, NULL); + zassert_equal(err, 0, "failed to send frame without data (err %d)", err); + + err = k_msgq_get(&can_msgq, &frame_buffer, TEST_RECEIVE_TIMEOUT); + zassert_equal(err, 0, "receive timeout"); + + assert_frame_equal(&frame, &frame_buffer, 0); + + can_remove_rx_filter(can_dev, filter_id); +} + /** * @brief Test send/receive with extended (29-bit) CAN IDs. */ From 90c1aaad690bb3e206523972c9b11ddf64056b43 Mon Sep 17 00:00:00 2001 From: Tom Burdick Date: Wed, 29 May 2024 10:20:43 -0500 Subject: [PATCH 1598/2849] tests: i2c_ram: Add fixture for i2c_ram testing i2c_ram expects that a ram-like part is connected to an i2c bus and therefore requires a hardware fixture setup much like spi_loopback. Adds a fixture that must be designated when running twister tests on a board with -X i2c_ram. Signed-off-by: Tom Burdick --- tests/drivers/i2c/i2c_ram/testcase.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/drivers/i2c/i2c_ram/testcase.yaml b/tests/drivers/i2c/i2c_ram/testcase.yaml index d1257778cc3fd..75bfbf0eb9a8b 100644 --- a/tests/drivers/i2c/i2c_ram/testcase.yaml +++ b/tests/drivers/i2c/i2c_ram/testcase.yaml @@ -4,6 +4,9 @@ common: - drivers - i2c filter: dt_alias_exists("i2c-ram") + harness: ztest + harness_config: + fixture: i2c_ram tests: drivers.i2c.ram: depends_on: i2c From a9565f7a96b38a64631581a3ec54a3a9e8219c29 Mon Sep 17 00:00:00 2001 From: Maciej Perkowski Date: Fri, 24 May 2024 11:38:10 +0200 Subject: [PATCH 1599/2849] docs: Add pytest files to a scope triggering doc-build workflow Those files are used with autoclass to use their docstrings in docs. Signed-off-by: Maciej Perkowski --- .github/workflows/doc-build.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/doc-build.yml b/.github/workflows/doc-build.yml index e8d53405257e9..e55b4bea247bc 100644 --- a/.github/workflows/doc-build.yml +++ b/.github/workflows/doc-build.yml @@ -50,6 +50,8 @@ jobs: scripts/dts/ doc/requirements.txt .github/workflows/doc-build.yml + scripts/pylib/pytest-twister-harness/src/twister_harness/device/device_adapter.py + scripts/pylib/pytest-twister-harness/src/twister_harness/helpers/shell.py doc-build-html: name: "Documentation Build (HTML)" From 209a3bd40aba88674eedbf2b9f16fc52720118fb Mon Sep 17 00:00:00 2001 From: Hess Nathan Date: Tue, 7 May 2024 13:46:20 +0200 Subject: [PATCH 1600/2849] coding guidelines: comply with MISRA Rule 11.8 - modified parameter types to receive a const pointer when a non-const pointer is not needed Signed-off-by: Hess Nathan --- tests/kernel/device/src/mmio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/kernel/device/src/mmio.c b/tests/kernel/device/src/mmio.c index a97060654bfec..b8066eeea3ecf 100644 --- a/tests/kernel/device/src/mmio.c +++ b/tests/kernel/device/src/mmio.c @@ -60,7 +60,7 @@ DEVICE_DEFINE(foo0, "foo0", foo_single_init, NULL, */ ZTEST(device, test_mmio_single) { - struct z_device_mmio_rom *rom; + const struct z_device_mmio_rom *rom; const struct device *dev = device_get_binding("foo0"); mm_reg_t regs; From aaec285cd59832da245a4b2fe33d6890aef0dbf7 Mon Sep 17 00:00:00 2001 From: Hess Nathan Date: Thu, 2 May 2024 12:55:30 +0200 Subject: [PATCH 1601/2849] coding guidelines: comply with MISRA Rule 12.1. -added parentheses verifying lack of ambiguities Signed-off-by: Hess Nathan --- subsys/logging/log_minimal.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subsys/logging/log_minimal.c b/subsys/logging/log_minimal.c index 11a27f701bb47..1340cf59c2701 100644 --- a/subsys/logging/log_minimal.c +++ b/subsys/logging/log_minimal.c @@ -43,7 +43,7 @@ static void minimal_hexdump_line_print(const char *data, size_t length) if (i < length) { unsigned char c = data[i]; - printk("%c", isprint((int)c) != 0 ? c : '.'); + printk("%c", (isprint((int)c) != 0) ? c : '.'); } else { printk(" "); } From 3f90957e361f5153adc9a184a4c9277be23a03cd Mon Sep 17 00:00:00 2001 From: Luis Ubieda Date: Thu, 23 May 2024 19:15:33 -0400 Subject: [PATCH 1602/2849] snippets: cdc-acm-console: Redirect Shell target to USB To easily enable Shell over USB. Tested with: ``` west build -b nrf52840dk/nrf52840 \ -S cdc-acm-console` \ samples/subsys/shell/shell_module ``` Signed-off-by: Luis Ubieda --- snippets/cdc-acm-console/cdc-acm-console.overlay | 1 + 1 file changed, 1 insertion(+) diff --git a/snippets/cdc-acm-console/cdc-acm-console.overlay b/snippets/cdc-acm-console/cdc-acm-console.overlay index 91e61886e522f..52d8627803ce6 100644 --- a/snippets/cdc-acm-console/cdc-acm-console.overlay +++ b/snippets/cdc-acm-console/cdc-acm-console.overlay @@ -7,6 +7,7 @@ / { chosen { zephyr,console = &snippet_cdc_acm_console_uart; + zephyr,shell-uart = &snippet_cdc_acm_console_uart; }; }; From 73bf6f6371f8fdc3061b7077d3ca130b77d155f0 Mon Sep 17 00:00:00 2001 From: Yassine El Aissaoui Date: Tue, 24 Oct 2023 14:42:32 +0200 Subject: [PATCH 1603/2849] samples: bluetooth: Enable PM on rd_rw612_bga Enable PM by default for rd_rw612_bga on peripheral_ht and central_ht samples Those are the BLE samples running on the CI, so it will be better to also check the builds with PM and also have some BLE apps to try PM with. Signed-off-by: Yassine El Aissaoui --- samples/bluetooth/central_ht/boards/rd_rw612_bga.conf | 1 + samples/bluetooth/peripheral_ht/boards/rd_rw612_bga.conf | 1 + 2 files changed, 2 insertions(+) create mode 100644 samples/bluetooth/central_ht/boards/rd_rw612_bga.conf create mode 100644 samples/bluetooth/peripheral_ht/boards/rd_rw612_bga.conf diff --git a/samples/bluetooth/central_ht/boards/rd_rw612_bga.conf b/samples/bluetooth/central_ht/boards/rd_rw612_bga.conf new file mode 100644 index 0000000000000..2df782efc7115 --- /dev/null +++ b/samples/bluetooth/central_ht/boards/rd_rw612_bga.conf @@ -0,0 +1 @@ +CONFIG_PM=y diff --git a/samples/bluetooth/peripheral_ht/boards/rd_rw612_bga.conf b/samples/bluetooth/peripheral_ht/boards/rd_rw612_bga.conf new file mode 100644 index 0000000000000..2df782efc7115 --- /dev/null +++ b/samples/bluetooth/peripheral_ht/boards/rd_rw612_bga.conf @@ -0,0 +1 @@ +CONFIG_PM=y From 4fc6506a8af33e8025e9119fdddc96e007acb3ca Mon Sep 17 00:00:00 2001 From: Valerio Setti Date: Mon, 3 Jun 2024 17:46:52 +0200 Subject: [PATCH 1604/2849] random: enable AES support CTR_DRBG CSPRNG when it relies on Mbed TLS PR #72475 disabled default enabling of many Mbed TLS features including AES. This means that now it must be explicitly added when required. Signed-off-by: Valerio Setti --- subsys/random/Kconfig | 1 + tests/crypto/mbedtls/prj.conf | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/subsys/random/Kconfig b/subsys/random/Kconfig index 72106f09b5707..0124bb28b1021 100644 --- a/subsys/random/Kconfig +++ b/subsys/random/Kconfig @@ -107,6 +107,7 @@ config CTR_DRBG_CSPRNG_GENERATOR bool "Use CTR-DRBG CSPRNG" depends on MBEDTLS || TINYCRYPT depends on ENTROPY_HAS_DRIVER + select MBEDTLS_CIPHER_AES_ENABLED if MBEDTLS select TINYCRYPT_CTR_PRNG if TINYCRYPT select TINYCRYPT_AES if TINYCRYPT help diff --git a/tests/crypto/mbedtls/prj.conf b/tests/crypto/mbedtls/prj.conf index 7f9ee7aa45924..6da7c1489b7cf 100644 --- a/tests/crypto/mbedtls/prj.conf +++ b/tests/crypto/mbedtls/prj.conf @@ -9,6 +9,5 @@ CONFIG_MINIMAL_LIBC_NON_REENTRANT_FUNCTIONS=y CONFIG_MINIMAL_LIBC_RAND=y CONFIG_ENTROPY_GENERATOR=y CONFIG_TEST_RANDOM_GENERATOR=y -CONFIG_MBEDTLS_CIPHER_AES_ENABLED=y CONFIG_MBEDTLS_USE_PSA_CRYPTO=n CONFIG_PSA_CRYPTO_ENABLE_ALL=n From 059643062c2109ffa56f9a0da578a0f02f24f940 Mon Sep 17 00:00:00 2001 From: Marek Pieta Date: Mon, 3 Jun 2024 14:12:28 +0200 Subject: [PATCH 1605/2849] usb: device_next: Update remote wakeup log level The `Remote wakeup feature not enabled or not suspended` log is not related to an actual error (connected host might not enable USB remote wakeup feature). Use warning log level. Signed-off-by: Marek Pieta --- subsys/usb/device_next/usbd_device.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subsys/usb/device_next/usbd_device.c b/subsys/usb/device_next/usbd_device.c index 86570a1267585..b2ba1fe3cffc2 100644 --- a/subsys/usb/device_next/usbd_device.c +++ b/subsys/usb/device_next/usbd_device.c @@ -160,7 +160,7 @@ int usbd_wakeup_request(struct usbd_context *const uds_ctx) } if (!uds_ctx->status.rwup || !usbd_is_suspended(uds_ctx)) { - LOG_ERR("Remote wakeup feature not enabled or not suspended"); + LOG_WRN("Remote wakeup feature not enabled or not suspended"); ret = -EACCES; goto wakeup_request_error; } From f33306ab2f41710e5b260c3b4ea4a031585c066b Mon Sep 17 00:00:00 2001 From: Evgeniy Paltsev Date: Fri, 31 May 2024 00:56:19 +0100 Subject: [PATCH 1606/2849] MAINTAINERS: add hostlink channel sources to Synopsys Platforms Virtual UART over ARC hostlink channel driver is used on Synopsys platforms and maintained by Synopsys. Signed-off-by: Evgeniy Paltsev Signed-off-by: Eugeniy Paltsev --- MAINTAINERS.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/MAINTAINERS.yml b/MAINTAINERS.yml index c0122d065defa..b6346106bb426 100644 --- a/MAINTAINERS.yml +++ b/MAINTAINERS.yml @@ -3172,6 +3172,8 @@ Synopsys Platforms: - scripts/west_commands/tests/test_mdb.py - scripts/west_commands/runners/nsim.py - cmake/emu/nsim.cmake + - drivers/serial/uart_hostlink.c + - drivers/serial/Kconfig.hostlink labels: - "platform: Synopsys" From c93859c6596ad6e927d3a9823fb4f08c156c90fc Mon Sep 17 00:00:00 2001 From: alperen sener Date: Thu, 30 May 2024 12:52:56 +0200 Subject: [PATCH 1607/2849] bluetooth: mesh: fix lpn receive window timing error APIs for enabling and disabling the scanner may take larger time than expected and scheduling of the lpn state machine is affected by it. Since these type of latencies are factored into timeouts and scheduling times, we need to call scan enable/disable APIs after scheduling the next event time for LPN state machine to be more accurate. Signed-off-by: alperen sener --- subsys/bluetooth/mesh/lpn.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/subsys/bluetooth/mesh/lpn.c b/subsys/bluetooth/mesh/lpn.c index 0d14c9c55e569..a7e48e841d1a8 100644 --- a/subsys/bluetooth/mesh/lpn.c +++ b/subsys/bluetooth/mesh/lpn.c @@ -296,11 +296,11 @@ static void clear_friendship(bool force, bool disable) if (!disable) { lpn_set_state(BT_MESH_LPN_ENABLED); + k_work_reschedule(&lpn->timer, FRIEND_REQ_RETRY_TIMEOUT); + if (!IS_ENABLED(CONFIG_BT_MESH_LPN_ESTABLISHMENT)) { bt_mesh_scan_enable(); } - - k_work_reschedule(&lpn->timer, FRIEND_REQ_RETRY_TIMEOUT); } if (was_established) { @@ -570,7 +570,6 @@ static void friend_response_received(struct bt_mesh_lpn *lpn) lpn->fsn++; } - bt_mesh_scan_disable(); lpn_set_state(BT_MESH_LPN_ESTABLISHED); lpn->req_attempts = 0U; lpn->sent_req = 0U; @@ -581,6 +580,7 @@ static void friend_response_received(struct bt_mesh_lpn *lpn) int32_t timeout = poll_timeout(lpn); k_work_reschedule(&lpn->timer, K_MSEC(timeout)); + bt_mesh_scan_disable(); } void bt_mesh_lpn_msg_received(struct bt_mesh_net_rx *rx) @@ -857,9 +857,9 @@ static void update_timeout(struct bt_mesh_lpn *lpn) { if (lpn->established) { LOG_WRN("No response from Friend during ReceiveWindow"); - bt_mesh_scan_disable(); lpn_set_state(BT_MESH_LPN_ESTABLISHED); k_work_reschedule(&lpn->timer, K_MSEC(POLL_RETRY_TIMEOUT)); + bt_mesh_scan_disable(); } else { if (IS_ENABLED(CONFIG_BT_MESH_LPN_ESTABLISHMENT)) { bt_mesh_scan_disable(); @@ -903,19 +903,19 @@ static void lpn_timeout(struct k_work *work) send_friend_req(lpn); break; case BT_MESH_LPN_REQ_WAIT: - bt_mesh_scan_enable(); k_work_reschedule(&lpn->timer, K_MSEC(lpn->adv_duration + FRIEND_REQ_SCAN)); lpn_set_state(BT_MESH_LPN_WAIT_OFFER); + bt_mesh_scan_enable(); break; case BT_MESH_LPN_WAIT_OFFER: LOG_WRN("No acceptable Friend Offers received"); - if (IS_ENABLED(CONFIG_BT_MESH_LPN_ESTABLISHMENT)) { - bt_mesh_scan_disable(); - } - lpn_set_state(BT_MESH_LPN_ENABLED); lpn->sent_req = 0U; k_work_reschedule(&lpn->timer, FRIEND_REQ_RETRY_TIMEOUT); + + if (IS_ENABLED(CONFIG_BT_MESH_LPN_ESTABLISHMENT)) { + bt_mesh_scan_disable(); + } break; case BT_MESH_LPN_ESTABLISHED: if (lpn->req_attempts < REQ_ATTEMPTS(lpn)) { @@ -939,8 +939,8 @@ static void lpn_timeout(struct k_work *work) case BT_MESH_LPN_RECV_DELAY: k_work_reschedule(&lpn->timer, K_MSEC(SCAN_LATENCY + lpn->recv_win + RX_DELAY_CORRECTION(lpn))); - bt_mesh_scan_enable(); lpn_set_state(BT_MESH_LPN_WAIT_UPDATE); + bt_mesh_scan_enable(); break; case BT_MESH_LPN_WAIT_UPDATE: update_timeout(lpn); From a33341ac6676c527d9ba14d23b815157d492c7d5 Mon Sep 17 00:00:00 2001 From: Tom Chang Date: Thu, 30 May 2024 13:45:47 +0800 Subject: [PATCH 1608/2849] drivers: espi: npcx: add support 66MHz eSPI clock This CL adds support 66MHz eSPI clock for NPCX4. Signed-off-by: Tom Chang --- drivers/espi/espi_npcx.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/espi/espi_npcx.c b/drivers/espi/espi_npcx.c index 05d7b60e2eafd..de23de2b46a14 100644 --- a/drivers/espi/espi_npcx.c +++ b/drivers/espi/espi_npcx.c @@ -69,6 +69,7 @@ struct espi_npcx_data { #define NPCX_ESPI_MAXFREQ_25 1 #define NPCX_ESPI_MAXFREQ_33 2 #define NPCX_ESPI_MAXFREQ_50 3 +#define NPCX_ESPI_MAXFREQ_66 4 /* Minimum delay before acknowledging a virtual wire */ #define NPCX_ESPI_VWIRE_ACK_DELAY 10ul /* 10 us */ @@ -676,6 +677,11 @@ static int espi_npcx_configure(const struct device *dev, struct espi_cfg *cfg) case 50: max_freq = NPCX_ESPI_MAXFREQ_50; break; +#ifdef CONFIG_SOC_SERIES_NPCX4 + case 66: + max_freq = NPCX_ESPI_MAXFREQ_66; + break; +#endif default: return -EINVAL; } From af63e488f01b92a9ba124f90ec08bb7d2672aa73 Mon Sep 17 00:00:00 2001 From: Johann Fischer Date: Wed, 29 May 2024 14:57:52 +0200 Subject: [PATCH 1609/2849] usb: device_next: hid: fix Get Report buffer handling After the get_report() callback, we need to determine how many bytes the HID device wrote to the report buffer. Use the callback return value to do this, and modify the net_buf data length value if get_report was successful. Reported-by: Marek Pieta Signed-off-by: Johann Fischer --- include/zephyr/usb/class/usbd_hid.h | 6 ++++-- subsys/usb/device_next/class/usbd_hid.c | 15 ++++++++++++--- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/include/zephyr/usb/class/usbd_hid.h b/include/zephyr/usb/class/usbd_hid.h index 5dd6d0dad2354..9798b081093da 100644 --- a/include/zephyr/usb/class/usbd_hid.h +++ b/include/zephyr/usb/class/usbd_hid.h @@ -106,8 +106,10 @@ struct hid_device_ops { * feature, input, or output report, which is specified by the argument * type. If there is no report ID in the report descriptor, the id * argument is zero. The callback implementation must check the - * arguments, such as whether the report type is supported, and return - * a nonzero value to indicate an unsupported type or an error. + * arguments, such as whether the report type is supported and the + * report length, and return a negative value to indicate an + * unsupported type or an error, or return the length of the report + * written to the buffer. */ int (*get_report)(const struct device *dev, const uint8_t type, const uint8_t id, diff --git a/subsys/usb/device_next/class/usbd_hid.c b/subsys/usb/device_next/class/usbd_hid.c index 6fef55df27f39..1b39aa182cf94 100644 --- a/subsys/usb/device_next/class/usbd_hid.c +++ b/subsys/usb/device_next/class/usbd_hid.c @@ -231,25 +231,34 @@ static int handle_get_report(const struct device *dev, const uint8_t id = HID_GET_REPORT_ID(setup->wValue); struct hid_device_data *const ddata = dev->data; const struct hid_device_ops *ops = ddata->ops; + const size_t size = net_buf_tailroom(buf); + int ret = 0; switch (type) { case HID_REPORT_TYPE_INPUT: LOG_DBG("Get Report, Input Report ID %u", id); - errno = ops->get_report(dev, type, id, net_buf_tailroom(buf), buf->data); + ret = ops->get_report(dev, type, id, size, buf->data); break; case HID_REPORT_TYPE_OUTPUT: LOG_DBG("Get Report, Output Report ID %u", id); - errno = ops->get_report(dev, type, id, net_buf_tailroom(buf), buf->data); + ret = ops->get_report(dev, type, id, size, buf->data); break; case HID_REPORT_TYPE_FEATURE: LOG_DBG("Get Report, Feature Report ID %u", id); - errno = ops->get_report(dev, type, id, net_buf_tailroom(buf), buf->data); + ret = ops->get_report(dev, type, id, size, buf->data); break; default: errno = -ENOTSUP; break; } + if (ret > 0) { + __ASSERT(ret <= size, "Buffer overflow in the HID driver"); + net_buf_add(buf, MIN(size, ret)); + } else { + errno = ret ? ret : -ENOTSUP; + } + return 0; } From 7f0b5edd8c23ce1b285d00f7f376e5ad5a23c6ef Mon Sep 17 00:00:00 2001 From: Ederson de Souza Date: Tue, 28 May 2024 21:23:28 -0700 Subject: [PATCH 1610/2849] arch/x86: Make irq_offload SMP-safe on x86_64 The irq_offload mechanism was using the same entry of the IDT vector for all CPUs on SMP systems. This caused race conditions when two CPUs were doing irq_offload() calls. This patch addresses that by adding one indirection layer: the irq_offload() now sets a per CPU entry with the routine and parameter to be run. Then a software interrupt is generated, and a default handler will do the appropriate dispatching. Finally, test "kernel/smp_abort" is enabled for x86 as it should work now. Fixes #72172. Signed-off-by: Ederson de Souza --- arch/x86/core/intel64/irq_offload.c | 32 +++++++++++++++++++++++++--- tests/kernel/smp_abort/testcase.yaml | 1 - 2 files changed, 29 insertions(+), 4 deletions(-) diff --git a/arch/x86/core/intel64/irq_offload.c b/arch/x86/core/intel64/irq_offload.c index 0146321f7d9d9..c2771d735cfc2 100644 --- a/arch/x86/core/intel64/irq_offload.c +++ b/arch/x86/core/intel64/irq_offload.c @@ -9,6 +9,7 @@ */ #include +#include #include #include @@ -17,12 +18,37 @@ extern void (*x86_irq_funcs[NR_IRQ_VECTORS])(const void *arg); extern const void *x86_irq_args[NR_IRQ_VECTORS]; +static void (*irq_offload_funcs[CONFIG_MP_NUM_CPUS])(const void *arg); +static const void *irq_offload_args[CONFIG_MP_NUM_CPUS]; + +static void dispatcher(const void *arg) +{ + uint8_t cpu_id = _current_cpu->id; + + if (irq_offload_funcs[cpu_id] != NULL) { + irq_offload_funcs[cpu_id](irq_offload_args[cpu_id]); + } +} void arch_irq_offload(irq_offload_routine_t routine, const void *parameter) { - x86_irq_funcs[CONFIG_IRQ_OFFLOAD_VECTOR - IV_IRQS] = routine; - x86_irq_args[CONFIG_IRQ_OFFLOAD_VECTOR - IV_IRQS] = parameter; + int key = arch_irq_lock(); + uint8_t cpu_id = _current_cpu->id; + + irq_offload_funcs[cpu_id] = routine; + irq_offload_args[cpu_id] = parameter; + __asm__ volatile("int %0" : : "i" (CONFIG_IRQ_OFFLOAD_VECTOR) : "memory"); - x86_irq_funcs[CONFIG_IRQ_OFFLOAD_VECTOR - IV_IRQS] = NULL; + + arch_irq_unlock(key); +} + +int irq_offload_init(void) +{ + x86_irq_funcs[CONFIG_IRQ_OFFLOAD_VECTOR - IV_IRQS] = dispatcher; + + return 0; } + +SYS_INIT(irq_offload_init, PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT); diff --git a/tests/kernel/smp_abort/testcase.yaml b/tests/kernel/smp_abort/testcase.yaml index 3903e477e178c..3b5a006991a46 100644 --- a/tests/kernel/smp_abort/testcase.yaml +++ b/tests/kernel/smp_abort/testcase.yaml @@ -1,6 +1,5 @@ tests: kernel.smp_abort: - arch_exclude: x86 # Buggy irq_offload(), see #71172 tags: - kernel - smp From d877d299137ce8d325468ef563f13c823f626a7d Mon Sep 17 00:00:00 2001 From: Anas Nashif Date: Wed, 22 May 2024 14:55:49 -0400 Subject: [PATCH 1611/2849] twister: abort on execution and retun 0 on exceptions When something goes wrong with execution, due to twister issues and bugs, do not continue with execution and abort the process and report and return an error code. Fixes #72807 Signed-off-by: Anas Nashif --- scripts/pylib/twister/twisterlib/runner.py | 39 +++++++++++++--------- scripts/tests/twister/test_runner.py | 1 + 2 files changed, 25 insertions(+), 15 deletions(-) diff --git a/scripts/pylib/twister/twisterlib/runner.py b/scripts/pylib/twister/twisterlib/runner.py index 7251f3f733ceb..6725134cc24eb 100644 --- a/scripts/pylib/twister/twisterlib/runner.py +++ b/scripts/pylib/twister/twisterlib/runner.py @@ -1315,8 +1315,22 @@ def add_tasks_to_queue(self, pipeline, build_only=False, test_only=False, retry_ def pipeline_mgr(self, pipeline, done_queue, lock, results): - if sys.platform == 'linux': - with self.jobserver.get_job(): + try: + if sys.platform == 'linux': + with self.jobserver.get_job(): + while True: + try: + task = pipeline.get_nowait() + except queue.Empty: + break + else: + instance = task['test'] + pb = ProjectBuilder(instance, self.env, self.jobserver) + pb.duts = self.duts + pb.process(pipeline, done_queue, task, lock, results) + + return True + else: while True: try: task = pipeline.get_nowait() @@ -1327,20 +1341,10 @@ def pipeline_mgr(self, pipeline, done_queue, lock, results): pb = ProjectBuilder(instance, self.env, self.jobserver) pb.duts = self.duts pb.process(pipeline, done_queue, task, lock, results) - return True - else: - while True: - try: - task = pipeline.get_nowait() - except queue.Empty: - break - else: - instance = task['test'] - pb = ProjectBuilder(instance, self.env, self.jobserver) - pb.duts = self.duts - pb.process(pipeline, done_queue, task, lock, results) - return True + except Exception as e: + logger.error(f"General exception: {e}") + sys.exit(1) def execute(self, pipeline, done): lock = Lock() @@ -1360,6 +1364,11 @@ def execute(self, pipeline, done): try: for p in processes: p.join() + if p.exitcode != 0: + logger.error(f"Process {p.pid} failed, aborting execution") + for proc in processes: + proc.terminate() + sys.exit(1) except KeyboardInterrupt: logger.info("Execution interrupted") for p in processes: diff --git a/scripts/tests/twister/test_runner.py b/scripts/tests/twister/test_runner.py index 592d2c6304208..88ed43a87fef8 100644 --- a/scripts/tests/twister/test_runner.py +++ b/scripts/tests/twister/test_runner.py @@ -2691,6 +2691,7 @@ def mock_join(): process_mock = mock.Mock() process_mock().join = mock.Mock(side_effect=mock_join) + process_mock().exitcode = 0 pipeline_mock = mock.Mock() done_mock = mock.Mock() From d05cad1784be697640223b53e4d16b5848b320e3 Mon Sep 17 00:00:00 2001 From: Krystof Sadlik Date: Wed, 29 May 2024 16:14:14 +0200 Subject: [PATCH 1612/2849] tests: i2c: i2c_target_api: added single mode testcase Some drivers do not support dual mode testcase. It would be great to test both signle and dual mode, even when the drivers do support this feature. Signed-off-by: Krystof Sadlik --- .../i2c/i2c_target_api/boards/mimxrt1040_evk.overlay | 10 ++-------- .../boards/mimxrt1170_evk_mimxrt1176_cm7.conf | 1 + ...B.overlay => mimxrt1170_evk_mimxrt1176_cm7.overlay} | 0 .../boards/mimxrt1170_evkb_mimxrt1176_cm4.conf | 1 + ....overlay => mimxrt1170_evkb_mimxrt1176_cm4.overlay} | 0 .../boards/mimxrt1170_evkb_mimxrt1176_cm7.conf | 1 + ....overlay => mimxrt1170_evkb_mimxrt1176_cm7.overlay} | 0 tests/drivers/i2c/i2c_target_api/testcase.yaml | 7 +++++++ 8 files changed, 12 insertions(+), 8 deletions(-) create mode 100644 tests/drivers/i2c/i2c_target_api/boards/mimxrt1170_evk_mimxrt1176_cm7.conf rename tests/drivers/i2c/i2c_target_api/boards/{mimxrt1170_evk_mimxrt1176_cm4_B.overlay => mimxrt1170_evk_mimxrt1176_cm7.overlay} (100%) create mode 100644 tests/drivers/i2c/i2c_target_api/boards/mimxrt1170_evkb_mimxrt1176_cm4.conf rename tests/drivers/i2c/i2c_target_api/boards/{mimxrt1170_evk_mimxrt1176_cm7_B.overlay => mimxrt1170_evkb_mimxrt1176_cm4.overlay} (100%) create mode 100644 tests/drivers/i2c/i2c_target_api/boards/mimxrt1170_evkb_mimxrt1176_cm7.conf rename tests/drivers/i2c/i2c_target_api/boards/{mimxrt1170_evkb_cm4.overlay => mimxrt1170_evkb_mimxrt1176_cm7.overlay} (100%) diff --git a/tests/drivers/i2c/i2c_target_api/boards/mimxrt1040_evk.overlay b/tests/drivers/i2c/i2c_target_api/boards/mimxrt1040_evk.overlay index 5dbcf85abb655..ba70b01c1d424 100644 --- a/tests/drivers/i2c/i2c_target_api/boards/mimxrt1040_evk.overlay +++ b/tests/drivers/i2c/i2c_target_api/boards/mimxrt1040_evk.overlay @@ -15,23 +15,17 @@ &lpi2c1 { status = "okay"; eeprom0: eeprom@54 { - compatible = "atmel,at24"; + compatible = "zephyr,i2c-target-eeprom"; reg = <0x54>; size = <1024>; - pagesize = <16>; - address-width = <8>; - timeout = <5>; }; }; &lpi2c3 { status = "okay"; eeprom1: eeprom@56 { - compatible = "atmel,at24"; + compatible = "zephyr,i2c-target-eeprom"; reg = <0x56>; size = <1024>; - pagesize = <16>; - address-width = <8>; - timeout = <5>; }; }; diff --git a/tests/drivers/i2c/i2c_target_api/boards/mimxrt1170_evk_mimxrt1176_cm7.conf b/tests/drivers/i2c/i2c_target_api/boards/mimxrt1170_evk_mimxrt1176_cm7.conf new file mode 100644 index 0000000000000..70e009fae68ae --- /dev/null +++ b/tests/drivers/i2c/i2c_target_api/boards/mimxrt1170_evk_mimxrt1176_cm7.conf @@ -0,0 +1 @@ +CONFIG_I2C_VIRTUAL=n diff --git a/tests/drivers/i2c/i2c_target_api/boards/mimxrt1170_evk_mimxrt1176_cm4_B.overlay b/tests/drivers/i2c/i2c_target_api/boards/mimxrt1170_evk_mimxrt1176_cm7.overlay similarity index 100% rename from tests/drivers/i2c/i2c_target_api/boards/mimxrt1170_evk_mimxrt1176_cm4_B.overlay rename to tests/drivers/i2c/i2c_target_api/boards/mimxrt1170_evk_mimxrt1176_cm7.overlay diff --git a/tests/drivers/i2c/i2c_target_api/boards/mimxrt1170_evkb_mimxrt1176_cm4.conf b/tests/drivers/i2c/i2c_target_api/boards/mimxrt1170_evkb_mimxrt1176_cm4.conf new file mode 100644 index 0000000000000..70e009fae68ae --- /dev/null +++ b/tests/drivers/i2c/i2c_target_api/boards/mimxrt1170_evkb_mimxrt1176_cm4.conf @@ -0,0 +1 @@ +CONFIG_I2C_VIRTUAL=n diff --git a/tests/drivers/i2c/i2c_target_api/boards/mimxrt1170_evk_mimxrt1176_cm7_B.overlay b/tests/drivers/i2c/i2c_target_api/boards/mimxrt1170_evkb_mimxrt1176_cm4.overlay similarity index 100% rename from tests/drivers/i2c/i2c_target_api/boards/mimxrt1170_evk_mimxrt1176_cm7_B.overlay rename to tests/drivers/i2c/i2c_target_api/boards/mimxrt1170_evkb_mimxrt1176_cm4.overlay diff --git a/tests/drivers/i2c/i2c_target_api/boards/mimxrt1170_evkb_mimxrt1176_cm7.conf b/tests/drivers/i2c/i2c_target_api/boards/mimxrt1170_evkb_mimxrt1176_cm7.conf new file mode 100644 index 0000000000000..70e009fae68ae --- /dev/null +++ b/tests/drivers/i2c/i2c_target_api/boards/mimxrt1170_evkb_mimxrt1176_cm7.conf @@ -0,0 +1 @@ +CONFIG_I2C_VIRTUAL=n diff --git a/tests/drivers/i2c/i2c_target_api/boards/mimxrt1170_evkb_cm4.overlay b/tests/drivers/i2c/i2c_target_api/boards/mimxrt1170_evkb_mimxrt1176_cm7.overlay similarity index 100% rename from tests/drivers/i2c/i2c_target_api/boards/mimxrt1170_evkb_cm4.overlay rename to tests/drivers/i2c/i2c_target_api/boards/mimxrt1170_evkb_mimxrt1176_cm7.overlay diff --git a/tests/drivers/i2c/i2c_target_api/testcase.yaml b/tests/drivers/i2c/i2c_target_api/testcase.yaml index f3883c0459ce6..ca8f3a59bbfd2 100644 --- a/tests/drivers/i2c/i2c_target_api/testcase.yaml +++ b/tests/drivers/i2c/i2c_target_api/testcase.yaml @@ -32,3 +32,10 @@ tests: - nucleo_f091rc extra_configs: - CONFIG_APP_DUAL_ROLE_I2C=y + drivers.i2c.target_api.single_role: + platform_allow: + - frdm_mcxn947/mcxn947/cpu0 + - mimxrt1170_evk@B/mimxrt1176/cm7 + - mimxrt1170_evk/mimxrt1176/cm7 + - mimxrt1040_evk + - mimxrt1060_evk From fe60a49c6755832c6d435f4915f8d6cfe3c18bab Mon Sep 17 00:00:00 2001 From: Krystof Sadlik Date: Mon, 3 Jun 2024 16:34:25 +0200 Subject: [PATCH 1613/2849] tests: i2c: i2c_target_api: fixed sizes in ovelay Fixed sizes in ovelay files. Signed-off-by: Krystof Sadlik --- .../drivers/i2c/i2c_target_api/boards/mimxrt1040_evk.overlay | 4 ++-- .../drivers/i2c/i2c_target_api/boards/mimxrt1060_evk.overlay | 4 ++-- .../boards/mimxrt1170_evk_mimxrt1176_cm7.overlay | 4 ++-- .../boards/mimxrt1170_evkb_mimxrt1176_cm4.overlay | 4 ++-- .../boards/mimxrt1170_evkb_mimxrt1176_cm7.overlay | 4 ++-- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/tests/drivers/i2c/i2c_target_api/boards/mimxrt1040_evk.overlay b/tests/drivers/i2c/i2c_target_api/boards/mimxrt1040_evk.overlay index ba70b01c1d424..a1c329a6926e6 100644 --- a/tests/drivers/i2c/i2c_target_api/boards/mimxrt1040_evk.overlay +++ b/tests/drivers/i2c/i2c_target_api/boards/mimxrt1040_evk.overlay @@ -17,7 +17,7 @@ eeprom0: eeprom@54 { compatible = "zephyr,i2c-target-eeprom"; reg = <0x54>; - size = <1024>; + size = <256>; }; }; @@ -26,6 +26,6 @@ eeprom1: eeprom@56 { compatible = "zephyr,i2c-target-eeprom"; reg = <0x56>; - size = <1024>; + size = <256>; }; }; diff --git a/tests/drivers/i2c/i2c_target_api/boards/mimxrt1060_evk.overlay b/tests/drivers/i2c/i2c_target_api/boards/mimxrt1060_evk.overlay index 143c437549f0b..d47c67068ba92 100644 --- a/tests/drivers/i2c/i2c_target_api/boards/mimxrt1060_evk.overlay +++ b/tests/drivers/i2c/i2c_target_api/boards/mimxrt1060_evk.overlay @@ -25,7 +25,7 @@ eeprom0: eeprom@54 { compatible = "zephyr,i2c-target-eeprom"; reg = <0x54>; - size = <1024>; + size = <256>; }; }; @@ -36,6 +36,6 @@ eeprom1: eeprom@56 { compatible = "zephyr,i2c-target-eeprom"; reg = <0x56>; - size = <1024>; + size = <256>; }; }; diff --git a/tests/drivers/i2c/i2c_target_api/boards/mimxrt1170_evk_mimxrt1176_cm7.overlay b/tests/drivers/i2c/i2c_target_api/boards/mimxrt1170_evk_mimxrt1176_cm7.overlay index 4e17adc5dce5b..967f9a7de3858 100644 --- a/tests/drivers/i2c/i2c_target_api/boards/mimxrt1170_evk_mimxrt1176_cm7.overlay +++ b/tests/drivers/i2c/i2c_target_api/boards/mimxrt1170_evk_mimxrt1176_cm7.overlay @@ -11,7 +11,7 @@ eeprom0: eeprom@54 { compatible = "zephyr,i2c-target-eeprom"; reg = <0x54>; - size = <1024>; + size = <256>; }; }; @@ -20,6 +20,6 @@ eeprom1: eeprom@56 { compatible = "zephyr,i2c-target-eeprom"; reg = <0x56>; - size = <1024>; + size = <256>; }; }; diff --git a/tests/drivers/i2c/i2c_target_api/boards/mimxrt1170_evkb_mimxrt1176_cm4.overlay b/tests/drivers/i2c/i2c_target_api/boards/mimxrt1170_evkb_mimxrt1176_cm4.overlay index 4e17adc5dce5b..967f9a7de3858 100644 --- a/tests/drivers/i2c/i2c_target_api/boards/mimxrt1170_evkb_mimxrt1176_cm4.overlay +++ b/tests/drivers/i2c/i2c_target_api/boards/mimxrt1170_evkb_mimxrt1176_cm4.overlay @@ -11,7 +11,7 @@ eeprom0: eeprom@54 { compatible = "zephyr,i2c-target-eeprom"; reg = <0x54>; - size = <1024>; + size = <256>; }; }; @@ -20,6 +20,6 @@ eeprom1: eeprom@56 { compatible = "zephyr,i2c-target-eeprom"; reg = <0x56>; - size = <1024>; + size = <256>; }; }; diff --git a/tests/drivers/i2c/i2c_target_api/boards/mimxrt1170_evkb_mimxrt1176_cm7.overlay b/tests/drivers/i2c/i2c_target_api/boards/mimxrt1170_evkb_mimxrt1176_cm7.overlay index 4e17adc5dce5b..967f9a7de3858 100644 --- a/tests/drivers/i2c/i2c_target_api/boards/mimxrt1170_evkb_mimxrt1176_cm7.overlay +++ b/tests/drivers/i2c/i2c_target_api/boards/mimxrt1170_evkb_mimxrt1176_cm7.overlay @@ -11,7 +11,7 @@ eeprom0: eeprom@54 { compatible = "zephyr,i2c-target-eeprom"; reg = <0x54>; - size = <1024>; + size = <256>; }; }; @@ -20,6 +20,6 @@ eeprom1: eeprom@56 { compatible = "zephyr,i2c-target-eeprom"; reg = <0x56>; - size = <1024>; + size = <256>; }; }; From fb61c7b360a7471d4fe2e95ab9b2a507296f8935 Mon Sep 17 00:00:00 2001 From: Krystof Sadlik Date: Mon, 3 Jun 2024 17:56:07 +0200 Subject: [PATCH 1614/2849] tests: i2c: Fixed overlay for frdm board Fixed overlay for frdm board as well. Signed-off-by: Krystof Sadlik --- .../i2c_target_api/boards/frdm_mcxn947_mcxn947_cpu0.overlay | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/drivers/i2c/i2c_target_api/boards/frdm_mcxn947_mcxn947_cpu0.overlay b/tests/drivers/i2c/i2c_target_api/boards/frdm_mcxn947_mcxn947_cpu0.overlay index d0dc5661db8c3..71a99565aab4e 100644 --- a/tests/drivers/i2c/i2c_target_api/boards/frdm_mcxn947_mcxn947_cpu0.overlay +++ b/tests/drivers/i2c/i2c_target_api/boards/frdm_mcxn947_mcxn947_cpu0.overlay @@ -38,7 +38,7 @@ eeprom0: eeprom@54 { compatible = "zephyr,i2c-target-eeprom"; reg = <0x54>; - size = <1024>; + size = <256>; }; }; @@ -46,6 +46,6 @@ eeprom1: eeprom@56 { compatible = "zephyr,i2c-target-eeprom"; reg = <0x56>; - size = <1024>; + size = <256>; }; }; From b3c9f957c6e5fe5aea7b4b9796ff9d38b23839c4 Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Fri, 1 Sep 2023 18:48:37 +0000 Subject: [PATCH 1615/2849] drivers/flash: Add explicit_erase property The commit adds and no_explicit_erase capability to flash_parameters, that indicates whether device is program-erase type device; such devices, like Flash type devices, require erase prior to writing random data at any previously programmed location. This capability should only be set by drivers. The flash_params_get_erase_cap() function has been added, for parsing flash_parameters object to obtain erase capabilities of device. The function returns capabilities as combination of bits representing them. Currently it will return: 0 -- no erase capabilities FLASH_ERASE_C_EXPLICIT -- erase required before write of random data. Additional capabilities have been reserved but are not yet used. There are following Kconfig options added: FLASH_HAS_EXPLICIT_ERASE FLASH_HAS_NO_EXPLICIT_ERASE that should be selected by device driver to indicate whether devices served by driver needs erase prior to write. The above Kconfigs are used to figure out whether app is built for hardware that requires erase prior to write. They can be also used to detect that it is attempted to build some subsystem that will not work with provided hardware, for example file system that has not been prepared to work with devices that do not require erase. Signed-off-by: Dominik Ermel --- drivers/flash/Kconfig | 58 ++++++++++++++++++++++++++++++++-- include/zephyr/drivers/flash.h | 52 +++++++++++++++++++++++++++++- 2 files changed, 107 insertions(+), 3 deletions(-) diff --git a/drivers/flash/Kconfig b/drivers/flash/Kconfig index 441a79868786f..2762cd913f225 100644 --- a/drivers/flash/Kconfig +++ b/drivers/flash/Kconfig @@ -17,6 +17,56 @@ config FLASH_HAS_EX_OP This option is selected by drivers that support flash extended operations. +config FLASH_HAS_EXPLICIT_ERASE + bool + help + Device has does not do erase-on-write (erase-on-program, auto-erase + on write) and requires explicit erase procedure to be programmed + with random value, in place where it has already been programmed with + some other value, as program can only change bits from erased-value + to the opposite. + All pure Flash devices are evolution of EEPROM where erase has + been separated from write, EEPROM has erase-on-write, giving + it advantage of higher write speeds at a cost of larger erase block. + Note that explicit-erase capability does not warrants that + write without erase is not allowed, taking the above restrictions, + it only states that write of a random information will require + erase. + Erase is usually performed in pages, as we have chosen to name + the unit in Zephyr, that may have different naming in device + specifications, like pages, sectors or blocks, and may vary + in size, depending how they are named by vendor. + This option should be selected by drivers that serve devices with + such characteristic and is used and may be used by users to provide + paths in code that only serve such devices, and could be + optimized-out by compiler in case where there is no such device in + a system. + +config FLASH_HAS_NO_EXPLICIT_ERASE + bool + help + Device does not require explicit erase before programming + a new random value at any location that has been previously + programmed with some other value. + Note that the device may have erase-on-write (auto-erase), + as for example in EEPROM devices, but may also have no erase + at all. + A device driver may still provide erase callback, + especially if it is able to perform erase to accelerate + further writes or is able to fill the area requested for + erase, with single value, faster than consecutive writes + that would be used to emulate erase. + This option should be selected by drivers that serve + devices with such characteristic and is used and may be + used by users to provide paths in code that only serve + such devices, and could be optimized-out by compiler in + case where there is no such device in a system. + This option should be selected for any device that + can change storage bits, by write, from any value to opposite + value at any time. + When your driver sets this option you also need to set + no_explicit_erase capability in your drivers flash_parameters. + config FLASH_HAS_PAGE_LAYOUT bool help @@ -77,13 +127,17 @@ config FLASH_SHELL_BUFFER_SIZE endif # FLASH_SHELL + +if FLASH_HAS_PAGE_LAYOUT + config FLASH_PAGE_LAYOUT bool "API for retrieving the layout of pages" - depends on FLASH_HAS_PAGE_LAYOUT - default y + default FLASH_HAS_PAGE_LAYOUT help Enables API for retrieving the layout of flash memory pages. +endif + config FLASH_EX_OP_ENABLED bool "API for extended flash operations" depends on FLASH_HAS_EX_OP diff --git a/include/zephyr/drivers/flash.h b/include/zephyr/drivers/flash.h index beb8838d71e9e..ecc0f4d0e29bc 100644 --- a/include/zephyr/drivers/flash.h +++ b/include/zephyr/drivers/flash.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017 Nordic Semiconductor ASA + * Copyright (c) 2017-2024 Nordic Semiconductor ASA * Copyright (c) 2016 Intel Corporation * * SPDX-License-Identifier: Apache-2.0 @@ -58,9 +58,59 @@ struct flash_pages_layout { */ struct flash_parameters { const size_t write_block_size; + /* Device capabilities. Only drivers are supposed to set the + * capabilities directly, users need to call the FLASH_CAPS_ + * macros on pointer to flash_parameters to get capabilities. + */ + struct { + /* Device has no explicit erase, so it either erases on + * write or does not require it at all. + * This also includes devices that support erase but + * do not require it. + */ + bool no_explicit_erase: 1; + } caps; uint8_t erase_value; /* Byte value of erased flash */ }; +/** Set for ordinary Flash where erase is needed before write of random data */ +#define FLASH_ERASE_C_EXPLICIT 0x01 +/** Reserved for users as initializer for variables that will later store + * capabilities. + */ +#define FLASH_ERASE_CAPS_UNSET (int)-1 +/* The values below are now reserved but not used */ +#define FLASH_ERASE_C_SUPPORTED 0x02 +#define FLASH_ERASE_C_VAL_BIT 0x04 +#define FLASH_ERASE_UNIFORM_PAGE 0x08 + + +/* @brief Parser for flash_parameters for retrieving erase capabilities + * + * The functions parses flash_parameters type object and returns combination + * of erase capabilities of 0 if device does not have any. + * Not that in some cases availability of erase may be dependent on driver + * options, so even if by hardware design a device provides some erase + * capabilities, the function may return 0 if these been disabled or not + * implemented by driver. + * + * @param p pointer to flash_parameters type object + * + * @return 0 or combination of FLASH_ERASE_C_ capabilities. + */ +static inline +int flash_params_get_erase_cap(const struct flash_parameters *p) +{ +#if defined(CONFIG_FLASH_HAS_EXPLICIT_ERASE) +#if defined(CONFIG_FLASH_HAS_NO_EXPLICIT_ERASE) + return (p->caps.no_explicit_erase) ? 0 : FLASH_ERASE_C_EXPLICIT; +#else + return FLASH_ERASE_C_EXPLICIT; +#endif +#endif + return 0; +} + /** * @} */ From 010b8d19e935bfba11317ffde75c8cfc2fd338d0 Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Fri, 1 Sep 2023 18:53:55 +0000 Subject: [PATCH 1616/2849] tests/drivers/flash: Make tests check for explicit erase capability Test now check whether device has requirement for explicit erase before call or not, before performing various actions. Signed-off-by: Dominik Ermel --- tests/drivers/flash/common/src/main.c | 75 +++++++++++++++++++-------- 1 file changed, 53 insertions(+), 22 deletions(-) diff --git a/tests/drivers/flash/common/src/main.c b/tests/drivers/flash/common/src/main.c index d3c5d8b7cf609..8b6bb80ecab8b 100644 --- a/tests/drivers/flash/common/src/main.c +++ b/tests/drivers/flash/common/src/main.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020-2022 Nordic Semiconductor ASA + * Copyright (c) 2020-2024 Nordic Semiconductor ASA * * SPDX-License-Identifier: Apache-2.0 */ @@ -44,11 +44,16 @@ #define EXPECTED_SIZE 512 +#if !IS_ENABLED(CONFIG_FLASH_HAS_EXPLICIT_ERASE) && \ + !IS_ENABLED(CONFIG_FLASH_HAS_NO_EXPLICIT_ERASE) +#error There is no flash device enabled or it is missing Kconfig options +#endif + static const struct device *const flash_dev = TEST_AREA_DEVICE; static struct flash_pages_info page_info; static uint8_t __aligned(4) expected[EXPECTED_SIZE]; -static const struct flash_parameters *flash_params; static uint8_t erase_value; +static bool ebw_required; static void *flash_driver_setup(void) { @@ -57,12 +62,22 @@ static void *flash_driver_setup(void) TC_PRINT("Test will run on device %s\n", flash_dev->name); zassert_true(device_is_ready(flash_dev)); - flash_params = flash_get_parameters(flash_dev); - erase_value = flash_params->erase_value; + /* Check for erase is only needed when there is mix of devices */ + if (IS_ENABLED(CONFIG_FLASH_HAS_EXPLICIT_ERASE)) { + const struct flash_parameters *fparams = flash_get_parameters(flash_dev); + + erase_value = fparams->erase_value; + ebw_required = flash_params_get_erase_cap(fparams) & FLASH_ERASE_C_EXPLICIT; + /* For tests purposes use page (in nrf_qspi_nor page = 64 kB) */ + flash_get_page_info_by_offs(flash_dev, TEST_AREA_OFFSET, + &page_info); + } else { + TC_PRINT("No devices with erase requirement present\n"); + erase_value = 0x55; + page_info.start_offset = TEST_AREA_OFFSET; + page_info.size = TEST_AREA_MAX - TEST_AREA_OFFSET; + } - /* For tests purposes use page (in nrf_qspi_nor page = 64 kB) */ - flash_get_page_info_by_offs(flash_dev, TEST_AREA_OFFSET, - &page_info); /* Check if test region is not empty */ uint8_t buf[EXPECTED_SIZE]; @@ -85,23 +100,25 @@ static void *flash_driver_setup(void) "Test area exceeds flash size"); /* Check if flash is cleared */ - bool is_buf_clear = true; + if (IS_ENABLED(CONFIG_FLASH_HAS_EXPLICIT_ERASE) && ebw_required) { + bool is_buf_clear = true; - for (off_t i = 0; i < EXPECTED_SIZE; i++) { - if (buf[i] != erase_value) { - is_buf_clear = false; - break; + for (off_t i = 0; i < EXPECTED_SIZE; i++) { + if (buf[i] != erase_value) { + is_buf_clear = false; + break; + } } - } - if (!is_buf_clear) { - /* Erase a nb of pages aligned to the EXPECTED_SIZE */ - rc = flash_erase(flash_dev, page_info.start_offset, - (page_info.size * - ((EXPECTED_SIZE + page_info.size - 1) - / page_info.size))); + if (!is_buf_clear) { + /* Erase a nb of pages aligned to the EXPECTED_SIZE */ + rc = flash_erase(flash_dev, page_info.start_offset, + (page_info.size * + ((EXPECTED_SIZE + page_info.size - 1) + / page_info.size))); - zassert_equal(rc, 0, "Flash memory not properly erased"); + zassert_equal(rc, 0, "Flash memory not properly erased"); + } } return NULL; @@ -112,9 +129,23 @@ ZTEST(flash_driver, test_read_unaligned_address) int rc; uint8_t buf[EXPECTED_SIZE]; const uint8_t canary = erase_value; + uint32_t start; + + if (IS_ENABLED(CONFIG_FLASH_HAS_EXPLICIT_ERASE) && ebw_required) { + start = page_info.start_offset; + /* Erase a nb of pages aligned to the EXPECTED_SIZE */ + rc = flash_erase(flash_dev, page_info.start_offset, + (page_info.size * + ((EXPECTED_SIZE + page_info.size - 1) + / page_info.size))); + + zassert_equal(rc, 0, "Flash memory not properly erased"); + } else { + start = TEST_AREA_OFFSET; + } rc = flash_write(flash_dev, - page_info.start_offset, + start, expected, EXPECTED_SIZE); zassert_equal(rc, 0, "Cannot write to flash"); @@ -129,7 +160,7 @@ ZTEST(flash_driver, test_read_unaligned_address) buf[buf_o + len] = canary; memset(buf + buf_o, 0, len); rc = flash_read(flash_dev, - page_info.start_offset + ad_o, + start + ad_o, buf + buf_o, len); zassert_equal(rc, 0, "Cannot read flash"); zassert_equal(memcmp(buf + buf_o, From b8d073c572057354e3865f9aeafdad76eb6b3fb4 Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Thu, 7 Mar 2024 22:42:41 +0000 Subject: [PATCH 1617/2849] drivers/flash: Add flash_fill() and flash_flatten() The commit adds two new API calls: - flash_fill - that allows to fill selected part of device with specified value; - flash_flatten - that allows to erase or fill device with erase_value, depending on whether driver for the device provides erase callback. Signed-off-by: Dominik Ermel --- drivers/flash/CMakeLists.txt | 2 + drivers/flash/Kconfig | 13 +++++ drivers/flash/flash_handlers.c | 16 ++++++ drivers/flash/flash_util.c | 82 +++++++++++++++++++++++++++ include/zephyr/drivers/flash.h | 60 +++++++++++++++++++- tests/drivers/flash/common/src/main.c | 74 ++++++++++++++++++++++++ 6 files changed, 245 insertions(+), 2 deletions(-) create mode 100644 drivers/flash/flash_util.c diff --git a/drivers/flash/CMakeLists.txt b/drivers/flash/CMakeLists.txt index 54b9178c09183..744a6a5862c85 100644 --- a/drivers/flash/CMakeLists.txt +++ b/drivers/flash/CMakeLists.txt @@ -1,5 +1,7 @@ # SPDX-License-Identifier: Apache-2.0 +zephyr_library_sources(flash_util.c) + zephyr_syscall_header_ifdef( CONFIG_FLASH_SIMULATOR ${ZEPHYR_BASE}/include/zephyr/drivers/flash/flash_simulator.h diff --git a/drivers/flash/Kconfig b/drivers/flash/Kconfig index 2762cd913f225..4816db0b580f5 100644 --- a/drivers/flash/Kconfig +++ b/drivers/flash/Kconfig @@ -127,6 +127,19 @@ config FLASH_SHELL_BUFFER_SIZE endif # FLASH_SHELL +config FLASH_FILL_BUFFER_SIZE + int "Buffer size of flash_fill funciton" + default 32 + help + Size of a buffer used by flash_fill function to fill a device with + specific value; this buffer is allocated on stack. + The buffer is needed as most devices have write-block alignment + requirements that which imposes minimal size of data, which can + be written to a device, and alignment of write offset. + Even if device does not have such requirement, filling device by + single bytes is not efficient. + Value selected here should be multiply of the largest write-block-size + among all the memory devices used in system. if FLASH_HAS_PAGE_LAYOUT diff --git a/drivers/flash/flash_handlers.c b/drivers/flash/flash_handlers.c index 6e47b10dbd383..338c6c8402d61 100644 --- a/drivers/flash/flash_handlers.c +++ b/drivers/flash/flash_handlers.c @@ -50,6 +50,22 @@ static inline const struct flash_parameters *z_vrfy_flash_get_parameters(const s } #include +int z_vrfy_flash_fill(const struct device *dev, uint8_t val, off_t offset, + size_t size) +{ + K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_FLASH)); + return z_impl_flash_fill(dev, val, offset, size); +} +#include + +int z_vrfy_flash_flatten(const struct device *dev, off_t offset, size_t size) +{ + K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_FLASH)); + return z_impl_flash_flatten(dev, offset, size); +} + +#include + #ifdef CONFIG_FLASH_PAGE_LAYOUT static inline int z_vrfy_flash_get_page_info_by_offs(const struct device *dev, off_t offs, diff --git a/drivers/flash/flash_util.c b/drivers/flash/flash_util.c new file mode 100644 index 0000000000000..ee3b55798a56b --- /dev/null +++ b/drivers/flash/flash_util.c @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + + +#include + +#include +#include +#include + +LOG_MODULE_REGISTER(flash, CONFIG_FLASH_LOG_LEVEL); + +int z_impl_flash_fill(const struct device *dev, uint8_t val, off_t offset, + size_t size) +{ + uint8_t filler[CONFIG_FLASH_FILL_BUFFER_SIZE]; + const struct flash_driver_api *api = + (const struct flash_driver_api *)dev->api; + const struct flash_parameters *fparams = api->get_parameters(dev); + int rc = 0; + size_t stored = 0; + + if (sizeof(filler) < fparams->write_block_size) { + LOG_ERR("Size of CONFIG_FLASH_FILL_BUFFER_SIZE"); + return -EINVAL; + } + /* The flash_write will, probably, check write alignment but this + * is too late, as we write datain chunks; data alignment may be + * broken by the size of the last chunk, that is why the check + * happens here too. + * Note that we have no way to check whether offset and size are + * are correct, as such info is only available at the level of + * a driver, so only basic check on offset. + */ + if (offset < 0) { + LOG_ERR("Negative offset not allowed\n"); + return -EINVAL; + } + if ((size | (size_t)offset) & (fparams->write_block_size - 1)) { + LOG_ERR("Incorrect size or offset alignment, expected %zx\n", + fparams->write_block_size); + return -EINVAL; + } + + memset(filler, val, sizeof(filler)); + + while (stored < size) { + size_t chunk = MIN(sizeof(filler), size); + + rc = api->write(dev, offset + stored, filler, chunk); + if (rc < 0) { + LOG_DBG("Fill to dev %p failed at offset 0x%zx\n", + dev, (size_t)offset + stored); + break; + } + stored += chunk; + } + return rc; +} + +int z_impl_flash_flatten(const struct device *dev, off_t offset, size_t size) +{ + const struct flash_driver_api *api = + (const struct flash_driver_api *)dev->api; + const struct flash_parameters *params = api->get_parameters(dev); + +#if IS_ENABLED(CONFIG_FLASH_HAS_EXPLICIT_ERASE) + if ((flash_params_get_erase_cap(params) & FLASH_ERASE_C_EXPLICIT) && + api->erase != NULL) { + return api->erase(dev, offset, size); + } +#endif + +#if IS_ENABLED(CONFIG_FLASH_HAS_NO_EXPLICIT_ERASE) + return flash_fill(dev, params->erase_value, offset, size); +#else + return -ENOSYS; +#endif +} diff --git a/include/zephyr/drivers/flash.h b/include/zephyr/drivers/flash.h index ecc0f4d0e29bc..7ceea4a5b254e 100644 --- a/include/zephyr/drivers/flash.h +++ b/include/zephyr/drivers/flash.h @@ -141,6 +141,11 @@ typedef int (*flash_api_write)(const struct device *dev, off_t offset, * the driver, with the driver responsible for ensuring the "erase-protect" * after the operation completes (successfully or not) matches the erase-protect * state when the operation was started. + * + * The callback is optional for RAM non-volatile devices, which do not + * require erase by design, but may be provided if it allows device to + * work more effectively, or if device has a support for internal fill + * operation the erase in driver uses. */ typedef int (*flash_api_erase)(const struct device *dev, off_t offset, size_t size); @@ -278,12 +283,19 @@ static inline int z_impl_flash_write(const struct device *dev, off_t offset, * Any necessary erase protection management is performed by the driver * erase implementation itself. * + * The function should be used only for devices that are really + * explicit erase devices; in case when code relies on erasing + * device, i.e. setting it to erase-value, prior to some operations, + * but should work with explicit erase and RAM non-volatile devices, + * then flash_flatten should rather be used. + * * @param dev : flash device * @param offset : erase area starting offset * @param size : size of area to be erased * * @return 0 on success, negative errno code on fail. * + * @see flash_flatten() * @see flash_get_page_info_by_offs() * @see flash_get_page_info_by_idx() */ @@ -292,15 +304,59 @@ __syscall int flash_erase(const struct device *dev, off_t offset, size_t size); static inline int z_impl_flash_erase(const struct device *dev, off_t offset, size_t size) { + int rc = -ENOSYS; + const struct flash_driver_api *api = (const struct flash_driver_api *)dev->api; - int rc; - rc = api->erase(dev, offset, size); + if (api->erase != NULL) { + rc = api->erase(dev, offset, size); + } return rc; } +__syscall int flash_fill(const struct device *dev, uint8_t val, off_t offset, size_t size); + +/** + * @brief Erase part or all of a flash memory or level it + * + * If device is explicit erase type device or device driver provides erase + * callback, the callback of the device is called, in which it behaves + * the same way as flash_erase. + * If a device is does not require explicit erase, either because + * it has no erase at all or has auto-erase/erase-on-write, + * and does not provide erase callback then erase is emulated by + * leveling selected device memory area with erase_value assigned to + * device. + * + * Erase page offset and size are constrains of paged, explicit erase devices, + * but can be relaxed with devices without such requirement, which means that + * it is up to user code to make sure they are correct as the function + * will return on, if these constrains are not met, -EINVAL for + * paged device, but may succeed on non-explicit erase devices. + * For RAM non-volatile devices the erase pages are emulated, + * at this point, to allow smooth transition for code relying on + * device being paged to function properly; but this is completely + * software constrain. + * + * Generally: if your code previously required device to be erase + * prior to some actions to work, replace flash_erase calls with this + * function; but if your code can work with non-volatile RAM type devices, + * without emulating erase, you should rather have different path + * of execution for page-erase, i.e. Flash, devices and call + * flash_erase for them. + * + * @param dev : flash device + * @param offset : erase area starting offset + * @param size : size of area to be erased + * + * @return 0 on success, negative errno code on fail. + * + * @see flash_erase() + */ +__syscall int flash_flatten(const struct device *dev, off_t offset, size_t size); + struct flash_pages_info { off_t start_offset; /* offset from the base of flash address */ size_t size; diff --git a/tests/drivers/flash/common/src/main.c b/tests/drivers/flash/common/src/main.c index 8b6bb80ecab8b..4eeb492099372 100644 --- a/tests/drivers/flash/common/src/main.c +++ b/tests/drivers/flash/common/src/main.c @@ -180,4 +180,78 @@ ZTEST(flash_driver, test_read_unaligned_address) } } +ZTEST(flash_driver, test_flash_fill) +{ + uint8_t buf[EXPECTED_SIZE]; + int rc; + off_t i; + + if (IS_ENABLED(CONFIG_FLASH_HAS_EXPLICIT_ERASE) && ebw_required) { + /* Erase a nb of pages aligned to the EXPECTED_SIZE */ + rc = flash_erase(flash_dev, page_info.start_offset, + (page_info.size * + ((EXPECTED_SIZE + page_info.size - 1) + / page_info.size))); + + zassert_equal(rc, 0, "Flash memory not properly erased"); + } else { + rc = flash_fill(flash_dev, 0x55, page_info.start_offset, + (page_info.size * + ((EXPECTED_SIZE + page_info.size - 1) + / page_info.size))); + zassert_equal(rc, 0, "Leveling memory with fill failed\n"); + } + + /* Fill the device with 0xaa */ + rc = flash_fill(flash_dev, 0xaa, page_info.start_offset, + (page_info.size * + ((EXPECTED_SIZE + page_info.size - 1) + / page_info.size))); + zassert_equal(rc, 0, "Fill failed\n"); + + rc = flash_read(flash_dev, TEST_AREA_OFFSET, + buf, EXPECTED_SIZE); + zassert_equal(rc, 0, "Cannot read flash"); + + for (i = 0; i < EXPECTED_SIZE; i++) { + if (buf[i] != 0xaa) { + break; + } + } + zassert_equal(i, EXPECTED_SIZE, "Expected device to be filled wth 0xaa"); +} + +ZTEST(flash_driver, test_flash_flatten) +{ + uint8_t buf[EXPECTED_SIZE]; + int rc; + off_t i; + + rc = flash_flatten(flash_dev, page_info.start_offset, + (page_info.size * + ((EXPECTED_SIZE + page_info.size - 1) + / page_info.size))); + + zassert_equal(rc, 0, "Flash not leveled not properly erased"); + + /* Fill the device with 0xaa */ + rc = flash_fill(flash_dev, 0xaa, page_info.start_offset, + (page_info.size * + ((EXPECTED_SIZE + page_info.size - 1) + / page_info.size))); + zassert_equal(rc, 0, "Fill failed\n"); + + rc = flash_read(flash_dev, TEST_AREA_OFFSET, + buf, EXPECTED_SIZE); + zassert_equal(rc, 0, "Cannot read flash"); + + for (i = 0; i < EXPECTED_SIZE; i++) { + if (buf[i] != 0xaa) { + break; + } + } + zassert_equal(i, EXPECTED_SIZE, "Expected device to be filled wth 0xaa"); +} + + ZTEST_SUITE(flash_driver, NULL, flash_driver_setup, NULL, NULL, NULL); From a5f7ceff812e73a17b2720586abf367c0ee97f5c Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Thu, 7 Mar 2024 22:43:44 +0000 Subject: [PATCH 1618/2849] storage/flash_map: Add flash_area_flatten Add equivalent of flash_erase, from Flash API, to Flash Map API; idea is the same: function tries to erase area if driver provides erase function, otherwise writes erase_value across the defined area. Signed-off-by: Dominik Ermel --- include/zephyr/storage/flash_map.h | 23 +++++++++ subsys/storage/flash_map/flash_map.c | 9 ++++ tests/subsys/storage/flash_map/src/main.c | 61 +++++++++++++++++++++++ 3 files changed, 93 insertions(+) diff --git a/include/zephyr/storage/flash_map.h b/include/zephyr/storage/flash_map.h index b03628afc93ec..937e242830ae3 100644 --- a/include/zephyr/storage/flash_map.h +++ b/include/zephyr/storage/flash_map.h @@ -187,6 +187,29 @@ int flash_area_write(const struct flash_area *fa, off_t off, const void *src, */ int flash_area_erase(const struct flash_area *fa, off_t off, size_t len); +/** + * @brief Erase flash area or fill with erase-value + * + * On program-erase devices this function behaves exactly like flash_area_erase. + * On RAM non-volatile device it will call erase, if driver provides such + * callback, or will fill given range with erase-value defined by driver. + * This function should be only used by code that has not been written + * to directly support devices that do not require erase and rely on + * device being erased prior to some operations. + * Note that emulated erase, on devices that do not require, is done + * via write, which affects endurance of device. + * + * @see flash_area_erase() + * @see flash_flatten() + * + * @param[in] fa Flash area + * @param[in] off Offset relative from beginning of flash area. + * @param[in] len Number of bytes to be erase + * + * @return 0 on success, negative errno code on fail. + */ +int flash_area_flatten(const struct flash_area *fa, off_t off, size_t len); + /** * @brief Get write block size of the flash area * diff --git a/subsys/storage/flash_map/flash_map.c b/subsys/storage/flash_map/flash_map.c index 79be7cae6d661..471b33358c948 100644 --- a/subsys/storage/flash_map/flash_map.c +++ b/subsys/storage/flash_map/flash_map.c @@ -82,6 +82,15 @@ int flash_area_erase(const struct flash_area *fa, off_t off, size_t len) return flash_erase(fa->fa_dev, fa->fa_off + off, len); } +int flash_area_flatten(const struct flash_area *fa, off_t off, size_t len) +{ + if (!is_in_flash_area_bounds(fa, off, len)) { + return -EINVAL; + } + + return flash_flatten(fa->fa_dev, fa->fa_off + off, len); +} + uint32_t flash_area_align(const struct flash_area *fa) { return flash_get_write_block_size(fa->fa_dev); diff --git a/tests/subsys/storage/flash_map/src/main.c b/tests/subsys/storage/flash_map/src/main.c index e66f6ac7e0f13..18fea4b2421fd 100644 --- a/tests/subsys/storage/flash_map/src/main.c +++ b/tests/subsys/storage/flash_map/src/main.c @@ -202,4 +202,65 @@ ZTEST(flash_map, test_fixed_partition_node_macros) DEVICE_DT_GET(DT_MTD_FROM_FIXED_PARTITION(SLOT1_PARTITION_NODE))); } +ZTEST(flash_map, test_flash_area_erase_and_flatten) +{ + int i; + bool erased = true; + int rc; + const struct flash_area *fa; + const struct device *flash_dev; + + rc = flash_area_open(SLOT1_PARTITION_ID, &fa); + zassert_true(rc == 0, "flash_area_open() fail"); + + /* First erase the area so it's ready for use. */ + flash_dev = flash_area_get_device(fa); + + rc = flash_erase(flash_dev, fa->fa_off, fa->fa_size); + zassert_true(rc == 0, "flash area erase fail"); + + rc = flash_fill(flash_dev, 0xaa, fa->fa_off, fa->fa_size); + zassert_true(rc == 0, "flash device fill fail"); + + rc = flash_area_erase(fa, 0, fa->fa_size); + zassert_true(rc == 0, "flash area erase fail"); + + /* we work under assumption that flash_fill is working and tested */ + for (i = 0; erased && i < fa->fa_size; ++i) { + uint8_t buf[32]; + int chunk = MIN(sizeof(buf), fa->fa_size - i); + + rc = flash_read(flash_dev, i, buf, chunk); + zassert_equal(rc, 0, "Unexpected read fail"); + for (int ii = 0; ii < chunk; ++ii, ++i) { + if (buf[ii] != flash_area_erased_val(fa)) { + erased = false; + break; + } + } + } + zassert_true(erased, "Erase failed at index %d", i); + + rc = flash_fill(flash_dev, 0xaa, fa->fa_off, fa->fa_size); + zassert_true(rc == 0, "flash device fill fail"); + + rc = flash_area_flatten(fa, 0, fa->fa_size); + + erased = true; + for (i = 0; erased && i < fa->fa_size; ++i) { + uint8_t buf[32]; + int chunk = MIN(sizeof(buf), fa->fa_size - i); + + rc = flash_read(flash_dev, i, buf, chunk); + zassert_equal(rc, 0, "Unexpected read fail"); + for (int ii = 0; ii < chunk; ++ii, ++i) { + if (buf[ii] != flash_area_erased_val(fa)) { + erased = false; + break; + } + } + } + zassert_true(erased, "Flatten/Erase failed at index %d", i); +} + ZTEST_SUITE(flash_map, NULL, NULL, NULL, NULL, NULL); From ff81b5244833fc7d163f0d26ed35538c9bb577f7 Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Wed, 6 Mar 2024 21:53:44 +0000 Subject: [PATCH 1619/2849] drivers/flash_simulator: Add support for non-erase device The commit adds support for testing non-explicite-erase device on Flash Simulator. This is addition to already supported explicit erase before write, aka Flash, type of device behaviour. Signed-off-by: Dominik Ermel --- drivers/flash/Kconfig.simulator | 20 +++ drivers/flash/flash_simulator.c | 15 +- .../flash_simulator/flash_sim_impl/src/main.c | 160 ++++++++++++++++++ .../flash_sim_impl/testcase.yaml | 11 ++ 4 files changed, 205 insertions(+), 1 deletion(-) diff --git a/drivers/flash/Kconfig.simulator b/drivers/flash/Kconfig.simulator index e32a2a72bb0da..fd75479b31682 100644 --- a/drivers/flash/Kconfig.simulator +++ b/drivers/flash/Kconfig.simulator @@ -22,12 +22,32 @@ config FLASH_SIMULATOR_UNALIGNED_READ Disable this option only if you want to simulate a specific FLASH interface that requires aligned read access. +config FLASH_SIMULATOR_EXPLICIT_ERASE + bool "Program-erase device" + select FLASH_HAS_EXPLICIT_ERASE + default y + help + Explicit erase (non-erase-on-write) Flash, which is device that requires erase + to erase-value prior to write as it only allows to change bits from erase-value + to the opposite. + +config FLASH_SIMULATOR_RAMLIKE + bool + default y if !FLASH_SIMULATOR_EXPLICIT_ERASE + select FLASH_HAS_NO_EXPLICIT_ERASE + select FLASH_SIMULATOR_DOUBLE_WRITES + help + This is used for setting FLASH_HAS_NO_EXPLICIT_ERASE. + config FLASH_SIMULATOR_DOUBLE_WRITES bool "Allow program units to be programmed more than once" help If selected, writing to a non-erased program unit will succeed, otherwise, it will return an error. Keep in mind that write operations can only change value of a bit from erase-value to the opposite. + This option does not impact FLASH_SIMULATOR_RAMLIKE. + In case when FLASH_SIMULATOR_EXPLICIT_ERASE is selected multiple writes to the same bit + but only change from erase-value to opposite will be registered. config FLASH_SIMULATOR_SIMULATE_TIMING bool "Hardware timing simulation" diff --git a/drivers/flash/flash_simulator.c b/drivers/flash/flash_simulator.c index effd53c1f2b30..3a7d578a250a6 100644 --- a/drivers/flash/flash_simulator.c +++ b/drivers/flash/flash_simulator.c @@ -162,7 +162,12 @@ static const struct flash_driver_api flash_sim_api; static const struct flash_parameters flash_sim_parameters = { .write_block_size = FLASH_SIMULATOR_PROG_UNIT, - .erase_value = FLASH_SIMULATOR_ERASE_VALUE + .erase_value = FLASH_SIMULATOR_ERASE_VALUE, + .caps = { +#if !defined(CONFIG_FLASH_SIMULATOR_EXPLICIT_ERASE) + .no_explicit_erase = false, +#endif + }, }; static int flash_range_is_valid(const struct device *dev, off_t offset, @@ -226,8 +231,12 @@ static int flash_sim_write(const struct device *dev, const off_t offset, FLASH_SIM_STATS_INC(flash_sim_stats, flash_write_calls); +#if defined(CONFIG_FLASH_SIMULATOR_EXPLICIT_ERASE) /* check if any unit has been already programmed */ memset(buf, FLASH_SIMULATOR_ERASE_VALUE, sizeof(buf)); +#else + memcpy(buf, MOCK_FLASH(offset), sizeof(buf)); +#endif for (uint32_t i = 0; i < len; i += FLASH_SIMULATOR_PROG_UNIT) { if (memcmp(buf, MOCK_FLASH(offset + i), sizeof(buf))) { FLASH_SIM_STATS_INC(flash_sim_stats, double_writes); @@ -265,10 +274,14 @@ static int flash_sim_write(const struct device *dev, const off_t offset, #endif /* CONFIG_FLASH_SIMULATOR_STATS */ /* only pull bits to zero */ +#if IS_ENABLED(CONFIG_FLASH_SIMULATOR_EXPLICIT_ERASE) #if FLASH_SIMULATOR_ERASE_VALUE == 0xFF *(MOCK_FLASH(offset + i)) &= *((uint8_t *)data + i); #else *(MOCK_FLASH(offset + i)) |= *((uint8_t *)data + i); +#endif +#else + *(MOCK_FLASH(offset + i)) = *((uint8_t *)data + i); #endif } diff --git a/tests/drivers/flash_simulator/flash_sim_impl/src/main.c b/tests/drivers/flash_simulator/flash_sim_impl/src/main.c index 69871c2b8aab9..ac90a821410e4 100644 --- a/tests/drivers/flash_simulator/flash_sim_impl/src/main.c +++ b/tests/drivers/flash_simulator/flash_sim_impl/src/main.c @@ -8,6 +8,10 @@ #include #include +/* Warning: The test has been written for testing boards with single + * instance of Flash Simulator device only. + */ + /* configuration derived from DT */ #ifdef CONFIG_ARCH_POSIX #define SOC_NV_FLASH_NODE DT_CHILD(DT_INST(0, zephyr_sim_flash), flash_0) @@ -75,6 +79,44 @@ static void test_check_pattern32(off_t start, uint32_t (*pattern_gen)(void), } } +/* ret < 0 is errno; ret == 1 is bad value in flash */ +static int test_check_erase(const struct device *dev, off_t offset, size_t size) +{ + uint8_t buf[FLASH_SIMULATOR_PROG_UNIT]; + int rc; + int i = 0; + + BUILD_ASSERT(sizeof(buf) >= FLASH_SIMULATOR_PROG_UNIT); + + i = 0; + while (i < size) { + size_t chunk = MIN(size - i, sizeof(buf)); + /* The memset is done to set buf to something else than + * FLASH_SIMULATOR_ERASE_VALUE, as we are trying to chek + * whether that is what is now in the memory. + */ + memset(buf, ~FLASH_SIMULATOR_ERASE_VALUE, sizeof(buf)); + rc = flash_read(flash_dev, offset + i, + buf, chunk); + if (rc < 0) { + TC_PRINT("Unexpected flash_read fail @ %ld", + (long)(offset + i)); + return rc; + } + do { + if ((uint8_t)buf[i & (sizeof(buf) - 1)] != + (uint8_t)FLASH_SIMULATOR_ERASE_VALUE) { + TC_PRINT("Flash not erased at %ld\n", + (long)(offset + i)); + return 1; + } + ++i; + --chunk; + } while (chunk); + } + return 0; +} + /* Get access to the device and erase it ready for testing*/ static void test_init(void) { @@ -259,6 +301,8 @@ ZTEST(flash_sim_api, test_align) zassert_equal(-EINVAL, rc, "Unexpected error code (%d)", rc); } +#if !IS_ENABLED(CONFIG_FLASH_SIMULATOR_DOUBLE_WRITES) && \ + !IS_ENABLED(CONFIG_FLASH_SIMULATOR_RAMLIKE) ZTEST(flash_sim_api, test_double_write) { int rc; @@ -282,6 +326,122 @@ ZTEST(flash_sim_api, test_double_write) &data, sizeof(data)); zassert_equal(-EIO, rc, "Unexpected error code (%d)", rc); } +#endif + +#if IS_ENABLED(CONFIG_FLASH_SIMULATOR_RAMLIKE) +ZTEST(flash_sim_api, test_ramlike) +{ + /* Within code below there is assumption that the src size is + * equal or greater than the FLASH_SIMULATOR_PROG_UNIT + * (write-block-size) of device. + */ + const uint8_t src[] = "Hello world! This is test string"; + uint8_t buf[FLASH_SIMULATOR_PROG_UNIT]; + /* Round up to next write-block-size */ + int max = (sizeof(src) + FLASH_SIMULATOR_PROG_UNIT - 1) & + ~(FLASH_SIMULATOR_PROG_UNIT - 1); + int rc; + int i = 0; + int is = 0; /* The index within src */ + + BUILD_ASSERT(sizeof(src) >= FLASH_SIMULATOR_PROG_UNIT); + + /* Scrub memory with something constant */ + memset(buf, FLASH_SIMULATOR_ERASE_VALUE, sizeof(buf)); + while (i < max) { + rc = flash_write(flash_dev, FLASH_SIMULATOR_BASE_OFFSET + i, + buf, sizeof(buf)); + zassert_equal(0, rc, "flash_write should succeed"); + i += sizeof(buf); + } + + /* Check the scrubbing */ + zassert_equal(0, test_check_erase(flash_dev, FLASH_SIMULATOR_BASE_OFFSET, max), + "Area not erased"); + + /* Now write something new */ + i = 0; + while (i < max) { + do { + buf[i & (sizeof(buf) - 1)] = src[is]; + ++i; + ++is; + + /* Continue writing from the beginning of the src */ + if (is >= sizeof(src)) { + is = 0; + } + } while (i & (sizeof(buf) - 1)); + rc = flash_write(flash_dev, FLASH_SIMULATOR_BASE_OFFSET + i - sizeof(buf), + buf, sizeof(buf)); + zassert_equal(0, rc, "flash_write should succeed"); + } + + /* Check the write */ + i = 0; + is = 0; + while (i < max) { + rc = flash_read(flash_dev, FLASH_SIMULATOR_BASE_OFFSET + i, + buf, sizeof(buf)); + zassert_equal(0, rc, "flash_read should succeed"); + do { + zassert_equal((uint8_t)src[is], (uint8_t)buf[i & (sizeof(buf) - 1)], + "Expected src and buf to match at index %d\n", i); + ++i; + ++is; + /* Src has wrapped around */ + if (is >= sizeof(src)) { + is = 0; + } + } while (i & (sizeof(buf) - 1)); + zassert_equal(0, rc, "Unexpected value read"); + } + + /* Because we are checking random access writes, we are now going to + * write binary not of the same data we have just written. If this would be + * program-erase type memory, where you can only change from erase value + * to opposite, such write would render incorrect data in memory, + * but this is random access device so we should get exactly what we write. + */ + i = 0; + is = 0; + while (i < max) { + do { + buf[i & (sizeof(buf) - 1)] = ~src[is]; + ++i; + ++is; + + /* Continue writing from the beginning of the src */ + if (is >= sizeof(src)) { + is = 0; + } + } while (i & (sizeof(buf) - 1)); + rc = flash_write(flash_dev, FLASH_SIMULATOR_BASE_OFFSET + i - sizeof(buf), + buf, sizeof(buf)); + zassert_equal(0, rc, "flash_write should succeed"); + } + + /* Check the write */ + i = 0; + is = 0; + while (i < max) { + rc = flash_read(flash_dev, FLASH_SIMULATOR_BASE_OFFSET + i, + buf, sizeof(buf)); + zassert_equal(0, rc, "flash_read should succeed"); + do { + zassert_equal((uint8_t)~src[is], (uint8_t)buf[i & (sizeof(buf) - 1)], + "Expected src and buf to match at index %d\n", i); + ++i; + ++is; + /* Src has wrapped around */ + if (is >= sizeof(src)) { + is = 0; + } + } while (i & (sizeof(buf) - 1)); + zassert_equal(0, rc, "Unexpected value read"); + } +} +#endif ZTEST(flash_sim_api, test_get_erase_value) { diff --git a/tests/drivers/flash_simulator/flash_sim_impl/testcase.yaml b/tests/drivers/flash_simulator/flash_sim_impl/testcase.yaml index 11efcf49278c2..7f2fa5a471920 100644 --- a/tests/drivers/flash_simulator/flash_sim_impl/testcase.yaml +++ b/tests/drivers/flash_simulator/flash_sim_impl/testcase.yaml @@ -13,6 +13,17 @@ tests: - nucleo_f411re integration_platforms: - qemu_x86 + drivers.flash.flash_simulator.ramlike: + extra_args: CONFIG_FLASH_SIMULATOR_EXPLICIT_ERASE=n + platform_allow: + - qemu_x86 + - native_posix + - native_posix/native/64 + - native_sim + - native_sim/native/64 + - nucleo_f411re + integration_platforms: + - qemu_x86 drivers.flash.flash_simulator.qemu_erase_value_0x00: extra_args: DTC_OVERLAY_FILE=boards/qemu_x86_ev_0x00.overlay platform_allow: qemu_x86 From bbb7bbe46d9d537cedf3830bca864678560782c2 Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Thu, 7 Mar 2024 22:43:08 +0000 Subject: [PATCH 1620/2849] tests/flash_simulator: Test scenario for flash_flatten() The commit adds test scenarios for flash_fill() and flash_flatten() Flash API calls. Signed-off-by: Dominik Ermel --- .../flash_simulator/flash_sim_impl/src/main.c | 110 +++++++++++++++++- 1 file changed, 107 insertions(+), 3 deletions(-) diff --git a/tests/drivers/flash_simulator/flash_sim_impl/src/main.c b/tests/drivers/flash_simulator/flash_sim_impl/src/main.c index ac90a821410e4..87eff3986c4ba 100644 --- a/tests/drivers/flash_simulator/flash_sim_impl/src/main.c +++ b/tests/drivers/flash_simulator/flash_sim_impl/src/main.c @@ -301,8 +301,8 @@ ZTEST(flash_sim_api, test_align) zassert_equal(-EINVAL, rc, "Unexpected error code (%d)", rc); } -#if !IS_ENABLED(CONFIG_FLASH_SIMULATOR_DOUBLE_WRITES) && \ - !IS_ENABLED(CONFIG_FLASH_SIMULATOR_RAMLIKE) +#if defined(CONFIG_FLASH_SIMULATOR_DOUBLE_WRITES) && \ + defined(CONFIG_FLASH_SIMULATOR_EXPLICIT_ERASE) ZTEST(flash_sim_api, test_double_write) { int rc; @@ -328,7 +328,7 @@ ZTEST(flash_sim_api, test_double_write) } #endif -#if IS_ENABLED(CONFIG_FLASH_SIMULATOR_RAMLIKE) +#if !defined(CONFIG_FLASH_SIMULATOR_EXPLICIT_ERASE) ZTEST(flash_sim_api, test_ramlike) { /* Within code below there is assumption that the src size is @@ -452,6 +452,110 @@ ZTEST(flash_sim_api, test_get_erase_value) FLASH_SIMULATOR_ERASE_VALUE); } +ZTEST(flash_sim_api, test_flash_fill) +{ + off_t i; + int rc; + uint8_t buf[FLASH_SIMULATOR_PROG_UNIT]; +#if defined(CONFIG_FLASH_SIMULATOR_EXPLICIT_ERASE) + rc = flash_erase(flash_dev, FLASH_SIMULATOR_BASE_OFFSET, + FLASH_SIMULATOR_FLASH_SIZE); + zassert_equal(0, rc, "flash_erase should succeed"); +#else + rc = flash_fill(flash_dev, FLASH_SIMULATOR_ERASE_VALUE, + FLASH_SIMULATOR_BASE_OFFSET, + FLASH_SIMULATOR_FLASH_SIZE); + zassert_equal(0, rc, "flash_fill should succeed"); +#endif + size_t size = FLASH_SIMULATOR_FLASH_SIZE; + + zassert_equal(0, test_check_erase(flash_dev, FLASH_SIMULATOR_BASE_OFFSET, + FLASH_SIMULATOR_FLASH_SIZE), + "Area not erased"); + + rc = flash_fill(flash_dev, 0x55, + FLASH_SIMULATOR_BASE_OFFSET, + FLASH_SIMULATOR_FLASH_SIZE); + zassert_equal(0, rc, "flash_fill should succeed"); + + /* Check if fill did work on both type of devices */ + i = 0; + size = FLASH_SIMULATOR_FLASH_SIZE; + while (i < FLASH_SIMULATOR_FLASH_SIZE) { + size_t chunk = MIN(size, FLASH_SIMULATOR_PROG_UNIT); + + memset(buf, FLASH_SIMULATOR_ERASE_VALUE, sizeof(buf)); + rc = flash_read(flash_dev, FLASH_SIMULATOR_BASE_OFFSET + i, + buf, chunk); + zassert_equal(0, rc, "flash_read should succeed at offset %d", i); + do { + zassert_equal((uint8_t)buf[i & (sizeof(buf) - 1)], 0x55, + "Unexpected value at offset %d\n", i); + ++i; + --size; + --chunk; + } while (chunk); + } +} + +ZTEST(flash_sim_api, test_flash_flatten) +{ + int rc; +#if defined(CONFIG_FLASH_SIMULATOR_EXPLICIT_ERASE) + rc = flash_erase(flash_dev, FLASH_SIMULATOR_BASE_OFFSET, + FLASH_SIMULATOR_FLASH_SIZE); + zassert_equal(0, rc, "flash_erase should succeed"); +#else + rc = flash_fill(flash_dev, FLASH_SIMULATOR_ERASE_VALUE, + FLASH_SIMULATOR_BASE_OFFSET, + FLASH_SIMULATOR_FLASH_SIZE); + zassert_equal(0, rc, "flash_fill should succeed"); +#endif + /* Now fill the device with anything */ + rc = flash_fill(flash_dev, 0xaa, + FLASH_SIMULATOR_BASE_OFFSET, + FLASH_SIMULATOR_FLASH_SIZE); + zassert_equal(0, rc, "flash_fill should succeed"); + + /* And erase */ + rc = flash_flatten(flash_dev, FLASH_SIMULATOR_BASE_OFFSET, + FLASH_SIMULATOR_FLASH_SIZE); + zassert_equal(0, rc, "flash_flatten should succeed"); + +#if !defined(CONFIG_FLASH_SIMULATOR_EXPLICIT_ERASE) + /* In case of RAM like devices, the erase may not be + * provided, in such case flash_flatten calls flash_fill + * with erase_value. + */ + struct device other; + struct flash_driver_api api; + + memcpy(&other, flash_dev, sizeof(other)); + other.api = &api; + memcpy(&api, flash_dev->api, sizeof(api)); + api.erase = NULL; + + /* Now fill the device with anything */ + rc = flash_fill(flash_dev, 0xaa, + FLASH_SIMULATOR_BASE_OFFSET, + FLASH_SIMULATOR_FLASH_SIZE); + zassert_equal(0, rc, "flash_fill should succeed"); + + /* The erase is not implemented */ + rc = flash_erase(&other, FLASH_SIMULATOR_BASE_OFFSET, + FLASH_SIMULATOR_FLASH_SIZE); + zassert_equal(-ENOSYS, rc, "Expected not implemented"); + + rc = flash_flatten(&other, FLASH_SIMULATOR_BASE_OFFSET, + FLASH_SIMULATOR_FLASH_SIZE); + zassert_equal(0, rc, "flash_flatten should succeed"); + + test_check_erase(flash_dev, FLASH_SIMULATOR_BASE_OFFSET, + FLASH_SIMULATOR_FLASH_SIZE); + +#endif +} + #include ZTEST(flash_sim_api, test_get_mock) From 6d75bc519baaaf9bc85ce40fd67c219a0a9294bb Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Tue, 16 Jan 2024 16:59:38 +0000 Subject: [PATCH 1621/2849] drivers/flash/nrf: Mark driver as FLASH_HAS_EXPLICIT_ERASE Select CONFIG_FLASH_HAS_EXPLICIT_ERASE for the NRF driver. Signed-off-by: Dominik Ermel --- drivers/flash/Kconfig.nrf | 1 + drivers/flash/soc_flash_nrf.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/flash/Kconfig.nrf b/drivers/flash/Kconfig.nrf index 769ccc7a51d52..48c4e0d3fb94b 100644 --- a/drivers/flash/Kconfig.nrf +++ b/drivers/flash/Kconfig.nrf @@ -17,6 +17,7 @@ menuconfig SOC_FLASH_NRF depends on !FLASH_NRF_FORCE_ALT select FLASH_HAS_PAGE_LAYOUT select FLASH_HAS_DRIVER_ENABLED + select FLASH_HAS_EXPLICIT_ERASE select NRFX_NVMC select MPU_ALLOW_FLASH_WRITE if ARM_MPU help diff --git a/drivers/flash/soc_flash_nrf.c b/drivers/flash/soc_flash_nrf.c index cc840309264e6..de9cfd423450d 100644 --- a/drivers/flash/soc_flash_nrf.c +++ b/drivers/flash/soc_flash_nrf.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2023 Nordic Semiconductor ASA + * Copyright (c) 2017-2024 Nordic Semiconductor ASA * Copyright (c) 2016 Linaro Limited * Copyright (c) 2016 Intel Corporation * From 127bc5e35e28d412f9b9f214156e6d59d4fc0474 Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Mon, 26 Feb 2024 19:52:45 +0000 Subject: [PATCH 1622/2849] drivers/flash/nrf_rram: Set no explicit erase capability to true NRF RRAM does not require erase prior to re-programming already written area. Signed-off-by: Dominik Ermel --- drivers/flash/Kconfig.nrf_rram | 1 + drivers/flash/soc_flash_nrf_rram.c | 3 +++ 2 files changed, 4 insertions(+) diff --git a/drivers/flash/Kconfig.nrf_rram b/drivers/flash/Kconfig.nrf_rram index a729b57bc288d..84214f809eb43 100644 --- a/drivers/flash/Kconfig.nrf_rram +++ b/drivers/flash/Kconfig.nrf_rram @@ -11,6 +11,7 @@ menuconfig SOC_FLASH_NRF_RRAM select NRFX_RRAMC select FLASH_HAS_DRIVER_ENABLED select FLASH_HAS_PAGE_LAYOUT + select FLASH_HAS_NO_EXPLICIT_ERASE select FLASH_NRF_FORCE_ALT select MPU_ALLOW_FLASH_WRITE if ARM_MPU help diff --git a/drivers/flash/soc_flash_nrf_rram.c b/drivers/flash/soc_flash_nrf_rram.c index 9e5e652ca5ed5..35a6c98862c69 100644 --- a/drivers/flash/soc_flash_nrf_rram.c +++ b/drivers/flash/soc_flash_nrf_rram.c @@ -309,6 +309,9 @@ static const struct flash_parameters *nrf_rram_get_parameters(const struct devic static const struct flash_parameters parameters = { .write_block_size = WRITE_LINE_SIZE, .erase_value = ERASE_VALUE, + .caps = { + .no_explicit_erase = true, + }, }; return ¶meters; From 0e970c83627015090fb4c2eafb1cf99b1ec85aa2 Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Mon, 11 Mar 2024 16:19:47 +0000 Subject: [PATCH 1623/2849] drivers/flash/nrf_mram: Set no explicit erase capability to true NRF MRAM does not require erase prior to re-programming already written area. Signed-off-by: Dominik Ermel --- drivers/flash/Kconfig.nrf_mram | 1 + drivers/flash/soc_flash_nrf_mram.c | 3 +++ 2 files changed, 4 insertions(+) diff --git a/drivers/flash/Kconfig.nrf_mram b/drivers/flash/Kconfig.nrf_mram index 0ef65864a622f..be41cead07f18 100644 --- a/drivers/flash/Kconfig.nrf_mram +++ b/drivers/flash/Kconfig.nrf_mram @@ -10,6 +10,7 @@ config SOC_FLASH_NRF_MRAM depends on DT_HAS_NORDIC_MRAM_ENABLED select FLASH_HAS_DRIVER_ENABLED select FLASH_HAS_PAGE_LAYOUT + select FLASH_HAS_NO_EXPLICIT_ERASE imply MPU_ALLOW_FLASH_WRITE if ARM_MPU help Enables Nordic Semiconductor flash driver for MRAM in direct write mode. diff --git a/drivers/flash/soc_flash_nrf_mram.c b/drivers/flash/soc_flash_nrf_mram.c index 9b33ee05d6f6c..5d8215f7af30b 100644 --- a/drivers/flash/soc_flash_nrf_mram.c +++ b/drivers/flash/soc_flash_nrf_mram.c @@ -142,6 +142,9 @@ static const struct flash_parameters *nrf_mram_get_parameters(const struct devic static const struct flash_parameters parameters = { .write_block_size = WRITE_BLOCK_SIZE, .erase_value = ERASE_VALUE, + .caps = { + .no_explicit_erase = true, + }, }; return ¶meters; From ea627fda7e3e10f12b6c17ede61eae43c13c8728 Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Fri, 2 Feb 2024 13:46:29 +0000 Subject: [PATCH 1624/2849] drivers/flash: Add explict erase capability with proper values Add explicit_erase capability and set proper value to it, depending on type of a device. Select FLASH_HAS_EXPLICIT_ERASE by devices that have program-erase characteristics and FLASH_HAS_NO_EXPLICIT_ERASE, where needed. Signed-off-by: Dominik Ermel --- drivers/flash/Kconfig.andes | 1 + drivers/flash/Kconfig.at45 | 1 + drivers/flash/Kconfig.b91 | 1 + drivers/flash/Kconfig.cadence_nand | 1 + drivers/flash/Kconfig.cadence_qspi_nor | 1 + drivers/flash/Kconfig.cc13xx_cc26xx | 1 + drivers/flash/Kconfig.esp32 | 1 + drivers/flash/Kconfig.gd32 | 1 + drivers/flash/Kconfig.gecko | 1 + drivers/flash/Kconfig.ifx_cat1 | 1 + drivers/flash/Kconfig.it8xxx2 | 1 + drivers/flash/Kconfig.lpc | 1 + drivers/flash/Kconfig.mcux | 4 ++++ drivers/flash/Kconfig.nios2_qspi | 1 + drivers/flash/Kconfig.npcx_fiu | 1 + drivers/flash/Kconfig.numaker | 1 + drivers/flash/Kconfig.nxp_s32 | 1 + drivers/flash/Kconfig.rpi_pico | 1 + drivers/flash/Kconfig.rv32m1 | 1 + drivers/flash/Kconfig.sam | 1 + drivers/flash/Kconfig.sam0 | 1 + drivers/flash/Kconfig.smartbond | 1 + drivers/flash/Kconfig.stm32 | 1 + drivers/flash/Kconfig.stm32_ospi | 1 + drivers/flash/Kconfig.stm32_qspi | 1 + drivers/flash/Kconfig.xmc4xxx | 1 + 26 files changed, 29 insertions(+) diff --git a/drivers/flash/Kconfig.andes b/drivers/flash/Kconfig.andes index d639cf20467e6..0a1a563519533 100644 --- a/drivers/flash/Kconfig.andes +++ b/drivers/flash/Kconfig.andes @@ -12,6 +12,7 @@ menuconfig FLASH_ANDES_QSPI select FLASH_HAS_PAGE_LAYOUT select FLASH_JESD216 select FLASH_HAS_DRIVER_ENABLED + select FLASH_HAS_EXPLICIT_ERASE depends on !SPI_NOR help Enable driver for Andes QSPI diff --git a/drivers/flash/Kconfig.at45 b/drivers/flash/Kconfig.at45 index c1c892e33fd80..bf5c0add72c7d 100644 --- a/drivers/flash/Kconfig.at45 +++ b/drivers/flash/Kconfig.at45 @@ -7,6 +7,7 @@ menuconfig SPI_FLASH_AT45 depends on DT_HAS_ATMEL_AT45_ENABLED select FLASH_HAS_DRIVER_ENABLED select FLASH_HAS_PAGE_LAYOUT + select FLASH_HAS_EXPLICIT_ERASE select SPI help This driver can handle several instances of AT45 family chips that diff --git a/drivers/flash/Kconfig.b91 b/drivers/flash/Kconfig.b91 index 46a8b10e804bf..a3f35da8581f3 100644 --- a/drivers/flash/Kconfig.b91 +++ b/drivers/flash/Kconfig.b91 @@ -7,5 +7,6 @@ config SOC_FLASH_TELINK_B91 depends on DT_HAS_TELINK_B91_FLASH_CONTROLLER_ENABLED select FLASH_HAS_PAGE_LAYOUT select FLASH_HAS_DRIVER_ENABLED + select FLASH_HAS_EXPLICIT_ERASE help Enables Telink B91 flash driver. diff --git a/drivers/flash/Kconfig.cadence_nand b/drivers/flash/Kconfig.cadence_nand index 52b7a1422b109..436592aa2d8ef 100644 --- a/drivers/flash/Kconfig.cadence_nand +++ b/drivers/flash/Kconfig.cadence_nand @@ -10,6 +10,7 @@ config FLASH_CDNS_NAND depends on DT_HAS_CDNS_NAND_ENABLED select FLASH_HAS_PAGE_LAYOUT select FLASH_HAS_DRIVER_ENABLED + select FLASH_HAS_EXPLICIT_ERASE help Enable Cadence NAND support. diff --git a/drivers/flash/Kconfig.cadence_qspi_nor b/drivers/flash/Kconfig.cadence_qspi_nor index 0bc9a33402c65..4209b256cfdb9 100644 --- a/drivers/flash/Kconfig.cadence_qspi_nor +++ b/drivers/flash/Kconfig.cadence_qspi_nor @@ -7,6 +7,7 @@ config FLASH_CAD_QSPI_NOR depends on DT_HAS_CDNS_QSPI_NOR_ENABLED select FLASH_HAS_PAGE_LAYOUT select FLASH_HAS_DRIVER_ENABLED + select FLASH_HAS_EXPLICIT_ERASE help Enable Cadence QSPI-NOR support. diff --git a/drivers/flash/Kconfig.cc13xx_cc26xx b/drivers/flash/Kconfig.cc13xx_cc26xx index 3abc4fc2d7d34..e691dddb4727a 100644 --- a/drivers/flash/Kconfig.cc13xx_cc26xx +++ b/drivers/flash/Kconfig.cc13xx_cc26xx @@ -7,6 +7,7 @@ config SOC_FLASH_CC13XX_CC26XX depends on DT_HAS_TI_CC13XX_CC26XX_FLASH_CONTROLLER_ENABLED select FLASH_HAS_PAGE_LAYOUT select FLASH_HAS_DRIVER_ENABLED + select FLASH_HAS_EXPLICIT_ERASE select MPU_ALLOW_FLASH_WRITE if ARM_MPU help Enables TI SimpleLink CC13xx/CC26xx flash controller driver. diff --git a/drivers/flash/Kconfig.esp32 b/drivers/flash/Kconfig.esp32 index 3d5790d4a2f52..4da80bce0c0fd 100644 --- a/drivers/flash/Kconfig.esp32 +++ b/drivers/flash/Kconfig.esp32 @@ -7,6 +7,7 @@ config SOC_FLASH_ESP32 depends on DT_HAS_ESPRESSIF_ESP32_FLASH_CONTROLLER_ENABLED select FLASH_HAS_DRIVER_ENABLED select FLASH_HAS_PAGE_LAYOUT + select FLASH_HAS_EXPLICIT_ERASE help Enable ESP32 internal flash driver. diff --git a/drivers/flash/Kconfig.gd32 b/drivers/flash/Kconfig.gd32 index c3c86bf35795a..c4d8921a6aad0 100644 --- a/drivers/flash/Kconfig.gd32 +++ b/drivers/flash/Kconfig.gd32 @@ -7,6 +7,7 @@ config SOC_FLASH_GD32 depends on (GD32_NV_FLASH_V1 || GD32_NV_FLASH_V2 || GD32_NV_FLASH_V3) select FLASH_HAS_DRIVER_ENABLED select FLASH_HAS_PAGE_LAYOUT + select FLASH_HAS_EXPLICIT_ERASE select MPU_ALLOW_FLASH_WRITE if ARM_MPU help Enable the GigaDevice GD32 flash driver. diff --git a/drivers/flash/Kconfig.gecko b/drivers/flash/Kconfig.gecko index 903b08373b32e..fc5478eae2698 100644 --- a/drivers/flash/Kconfig.gecko +++ b/drivers/flash/Kconfig.gecko @@ -10,6 +10,7 @@ config SOC_FLASH_GECKO select FLASH_HAS_DRIVER_ENABLED select FLASH_HAS_PAGE_LAYOUT select SOC_GECKO_MSC + select FLASH_HAS_EXPLICIT_ERASE select MPU_ALLOW_FLASH_WRITE if ARM_MPU help Enable Silicon Labs Gecko series internal flash driver. diff --git a/drivers/flash/Kconfig.ifx_cat1 b/drivers/flash/Kconfig.ifx_cat1 index f8871d4d1e30d..4964258c4ec20 100644 --- a/drivers/flash/Kconfig.ifx_cat1 +++ b/drivers/flash/Kconfig.ifx_cat1 @@ -12,6 +12,7 @@ config FLASH_INFINEON_CAT1 select FLASH_HAS_PAGE_LAYOUT select FLASH_HAS_DRIVER_ENABLED select USE_INFINEON_FLASH + select FLASH_HAS_EXPLICIT_ERASE help Enable the Flash driver for Infineon CAT1 family. diff --git a/drivers/flash/Kconfig.it8xxx2 b/drivers/flash/Kconfig.it8xxx2 index 50b881335a4fe..ef0307f65a39e 100644 --- a/drivers/flash/Kconfig.it8xxx2 +++ b/drivers/flash/Kconfig.it8xxx2 @@ -10,6 +10,7 @@ config SOC_FLASH_ITE_IT8XXX2 select SOC_IT8XXX2_USE_ILM select FLASH_HAS_PAGE_LAYOUT select FLASH_HAS_DRIVER_ENABLED + select FLASH_HAS_EXPLICIT_ERASE select HAS_FLASH_LOAD_OFFSET help The flash driver includes support for read, write and diff --git a/drivers/flash/Kconfig.lpc b/drivers/flash/Kconfig.lpc index 379a4cdaadc70..4d1fd1940e0f1 100644 --- a/drivers/flash/Kconfig.lpc +++ b/drivers/flash/Kconfig.lpc @@ -8,6 +8,7 @@ config SOC_FLASH_LPC DT_HAS_NXP_IAP_FMC54_ENABLED select FLASH_HAS_PAGE_LAYOUT select FLASH_HAS_DRIVER_ENABLED + select FLASH_HAS_EXPLICIT_ERASE help Enables the LPC IAP flash shim driver. WARNING: This driver will disable the system interrupts for diff --git a/drivers/flash/Kconfig.mcux b/drivers/flash/Kconfig.mcux index 2cf9eac494d28..7b3df8361076b 100644 --- a/drivers/flash/Kconfig.mcux +++ b/drivers/flash/Kconfig.mcux @@ -11,6 +11,7 @@ config SOC_FLASH_MCUX DT_HAS_NXP_IAP_MSF1_ENABLED select FLASH_HAS_PAGE_LAYOUT select FLASH_HAS_DRIVER_ENABLED + select FLASH_HAS_EXPLICIT_ERASE select MPU_ALLOW_FLASH_WRITE if ARM_MPU help Enables the MCUX flash shim driver. @@ -41,6 +42,7 @@ config FLASH_MCUX_FLEXSPI_NOR depends on DT_HAS_NXP_IMX_FLEXSPI_NOR_ENABLED select FLASH_HAS_PAGE_LAYOUT select FLASH_HAS_DRIVER_ENABLED + select FLASH_HAS_EXPLICIT_ERASE select FLASH_JESD216 select MEMC select MEMC_MCUX_FLEXSPI @@ -51,6 +53,7 @@ config FLASH_MCUX_FLEXSPI_MX25UM51345G depends on DT_HAS_NXP_IMX_FLEXSPI_MX25UM51345G_ENABLED select FLASH_HAS_PAGE_LAYOUT select FLASH_HAS_DRIVER_ENABLED + select FLASH_HAS_EXPLICIT_ERASE select MEMC select MEMC_MCUX_FLEXSPI @@ -60,6 +63,7 @@ config FLASH_MCUX_FLEXSPI_HYPERFLASH depends on DT_HAS_NXP_IMX_FLEXSPI_HYPERFLASH_ENABLED select FLASH_HAS_PAGE_LAYOUT select FLASH_HAS_DRIVER_ENABLED + select FLASH_HAS_EXPLICIT_ERASE select MEMC select MEMC_MCUX_FLEXSPI diff --git a/drivers/flash/Kconfig.nios2_qspi b/drivers/flash/Kconfig.nios2_qspi index bcad6d9e50dd1..ab834b5b95635 100644 --- a/drivers/flash/Kconfig.nios2_qspi +++ b/drivers/flash/Kconfig.nios2_qspi @@ -6,5 +6,6 @@ config SOC_FLASH_NIOS2_QSPI depends on HAS_ALTERA_HAL depends on DT_HAS_ALTR_NIOS2_QSPI_NOR_ENABLED select FLASH_HAS_DRIVER_ENABLED + select FLASH_HAS_EXPLICIT_ERASE help Enables the Nios-II QSPI flash driver. diff --git a/drivers/flash/Kconfig.npcx_fiu b/drivers/flash/Kconfig.npcx_fiu index e4ac74c9d444e..9d464f48bb78c 100644 --- a/drivers/flash/Kconfig.npcx_fiu +++ b/drivers/flash/Kconfig.npcx_fiu @@ -18,6 +18,7 @@ config FLASH_NPCX_FIU_NOR depends on FLASH_NPCX_FIU_QSPI select FLASH_HAS_DRIVER_ENABLED select FLASH_HAS_PAGE_LAYOUT + select FLASH_HAS_EXPLICIT_ERASE select FLASH_JESD216 select FLASH_HAS_EX_OP help diff --git a/drivers/flash/Kconfig.numaker b/drivers/flash/Kconfig.numaker index 98d4790589d3f..4ab0f46271dc3 100644 --- a/drivers/flash/Kconfig.numaker +++ b/drivers/flash/Kconfig.numaker @@ -8,6 +8,7 @@ config SOC_FLASH_NUMAKER default y select FLASH_HAS_PAGE_LAYOUT select FLASH_HAS_DRIVER_ENABLED + select FLASH_HAS_EXPLICIT_ERASE select HAS_NUMAKER_FMC depends on DT_HAS_NUVOTON_NUMAKER_FMC_ENABLED help diff --git a/drivers/flash/Kconfig.nxp_s32 b/drivers/flash/Kconfig.nxp_s32 index 08a96f1cec9bf..47db1ab654eea 100644 --- a/drivers/flash/Kconfig.nxp_s32 +++ b/drivers/flash/Kconfig.nxp_s32 @@ -9,6 +9,7 @@ config FLASH_NXP_S32_QSPI_NOR select FLASH_HAS_PAGE_LAYOUT select FLASH_HAS_DRIVER_ENABLED select FLASH_JESD216 + select FLASH_HAS_EXPLICIT_ERASE help Enable the Flash driver for a NOR Serial Flash Memory device connected to an NXP S32 QSPI bus. diff --git a/drivers/flash/Kconfig.rpi_pico b/drivers/flash/Kconfig.rpi_pico index 4d7fee169417f..b41cd843c0899 100644 --- a/drivers/flash/Kconfig.rpi_pico +++ b/drivers/flash/Kconfig.rpi_pico @@ -8,6 +8,7 @@ config FLASH_RPI_PICO depends on DT_HAS_RASPBERRYPI_PICO_FLASH_CONTROLLER_ENABLED select FLASH_HAS_DRIVER_ENABLED select FLASH_HAS_PAGE_LAYOUT + select FLASH_HAS_EXPLICIT_ERASE select PICOSDK_USE_FLASH help Enable Raspberry Pi Pico flash driver. diff --git a/drivers/flash/Kconfig.rv32m1 b/drivers/flash/Kconfig.rv32m1 index 0dd7f29012918..46ada40d7c3f3 100644 --- a/drivers/flash/Kconfig.rv32m1 +++ b/drivers/flash/Kconfig.rv32m1 @@ -7,6 +7,7 @@ config SOC_FLASH_RV32M1 depends on DT_HAS_OPENISA_RV32M1_FTFE_ENABLED select FLASH_HAS_PAGE_LAYOUT select FLASH_HAS_DRIVER_ENABLED + select FLASH_HAS_EXPLICIT_ERASE help Enables the RV32M1 flash shim driver. WARNING: This driver will disable the system interrupts for diff --git a/drivers/flash/Kconfig.sam b/drivers/flash/Kconfig.sam index bb014d6527990..1e30636390d0f 100644 --- a/drivers/flash/Kconfig.sam +++ b/drivers/flash/Kconfig.sam @@ -9,6 +9,7 @@ config SOC_FLASH_SAM depends on DT_HAS_ATMEL_SAM_FLASH_CONTROLLER_ENABLED select FLASH_HAS_PAGE_LAYOUT select FLASH_HAS_DRIVER_ENABLED + select FLASH_HAS_EXPLICIT_ERASE select MPU_ALLOW_FLASH_WRITE if ARM_MPU help Enable the Atmel SAM series internal flash driver. diff --git a/drivers/flash/Kconfig.sam0 b/drivers/flash/Kconfig.sam0 index accaa30d3039d..f285aa868f847 100644 --- a/drivers/flash/Kconfig.sam0 +++ b/drivers/flash/Kconfig.sam0 @@ -9,6 +9,7 @@ menuconfig SOC_FLASH_SAM0 depends on DT_HAS_ATMEL_SAM0_NVMCTRL_ENABLED select FLASH_HAS_PAGE_LAYOUT select FLASH_HAS_DRIVER_ENABLED + select FLASH_HAS_EXPLICIT_ERASE select MPU_ALLOW_FLASH_WRITE if ARM_MPU help Enable the Atmel SAM0 series internal flash driver. diff --git a/drivers/flash/Kconfig.smartbond b/drivers/flash/Kconfig.smartbond index 3cc587ba7e197..5d5dbd6a98e36 100644 --- a/drivers/flash/Kconfig.smartbond +++ b/drivers/flash/Kconfig.smartbond @@ -7,6 +7,7 @@ config SOC_FLASH_SMARTBOND depends on DT_HAS_RENESAS_SMARTBOND_FLASH_CONTROLLER_ENABLED select FLASH_HAS_PAGE_LAYOUT select FLASH_HAS_DRIVER_ENABLED + select FLASH_HAS_EXPLICIT_ERASE select MPU_ALLOW_FLASH_WRITE if ARM_MPU help Enable flash driver for Renesas SmartBond(tm) MCU family. diff --git a/drivers/flash/Kconfig.stm32 b/drivers/flash/Kconfig.stm32 index 72481c5ae6ed9..9caf7a04de850 100644 --- a/drivers/flash/Kconfig.stm32 +++ b/drivers/flash/Kconfig.stm32 @@ -12,6 +12,7 @@ config SOC_FLASH_STM32 select FLASH_HAS_DRIVER_ENABLED default y select FLASH_HAS_PAGE_LAYOUT + select FLASH_HAS_EXPLICIT_ERASE select MPU_ALLOW_FLASH_WRITE if ARM_MPU select USE_STM32_HAL_FLASH if BT_STM32WBA select USE_STM32_HAL_FLASH_EX if BT_STM32WBA diff --git a/drivers/flash/Kconfig.stm32_ospi b/drivers/flash/Kconfig.stm32_ospi index 305fcfac76d13..2cc2ffcab5c00 100644 --- a/drivers/flash/Kconfig.stm32_ospi +++ b/drivers/flash/Kconfig.stm32_ospi @@ -17,6 +17,7 @@ config FLASH_STM32_OSPI select FLASH_HAS_DRIVER_ENABLED select FLASH_JESD216 select FLASH_HAS_PAGE_LAYOUT + select FLASH_HAS_EXPLICIT_ERASE select DMA if $(DT_STM32_OCTOSPI_1_HAS_DMA) || $(DT_STM32_OCTOSPI_2_HAS_DMA) select USE_STM32_HAL_DMA if $(DT_STM32_OCTOSPI_1_HAS_DMA) || \ $(DT_STM32_OCTOSPI_2_HAS_DMA) diff --git a/drivers/flash/Kconfig.stm32_qspi b/drivers/flash/Kconfig.stm32_qspi index c97be5ef354b4..4aeeaf3e2ee34 100644 --- a/drivers/flash/Kconfig.stm32_qspi +++ b/drivers/flash/Kconfig.stm32_qspi @@ -15,6 +15,7 @@ config FLASH_STM32_QSPI select FLASH_HAS_DRIVER_ENABLED select FLASH_JESD216 select FLASH_HAS_PAGE_LAYOUT + select FLASH_HAS_EXPLICIT_ERASE select DMA if $(DT_STM32_QUADSPI_HAS_DMA) select USE_STM32_HAL_DMA if $(DT_STM32_QUADSPI_HAS_DMA) help diff --git a/drivers/flash/Kconfig.xmc4xxx b/drivers/flash/Kconfig.xmc4xxx index 60e5f08a759ef..eff7b1e5679e9 100644 --- a/drivers/flash/Kconfig.xmc4xxx +++ b/drivers/flash/Kconfig.xmc4xxx @@ -7,5 +7,6 @@ config SOC_FLASH_XMC4XXX depends on DT_HAS_INFINEON_XMC4XXX_FLASH_CONTROLLER_ENABLED select FLASH_HAS_PAGE_LAYOUT select FLASH_HAS_DRIVER_ENABLED + select FLASH_HAS_EXPLICIT_ERASE help Enables XMC4XXX flash driver. From 3c24e1a530542b5c49e706fd4ac18753d26112a7 Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Fri, 2 Feb 2024 13:47:09 +0000 Subject: [PATCH 1625/2849] drivers/flash/Ambiq: Set erase capabilities, depending on SoC The commit selects HAS_NO_EXPLICIT_ERASE for Apollo4, with MRAM, and HAS_EXPLICIT_ERASE for Apollo3 which has Flash, for a driver that shares code between SoCs. In case of Apollo4 the no_explicit_erase capability is set to true, while it remains false for Apollo3. Signed-off-by: Dominik Ermel --- drivers/flash/Kconfig.ambiq | 2 ++ drivers/flash/flash_ambiq.c | 5 +++++ 2 files changed, 7 insertions(+) diff --git a/drivers/flash/Kconfig.ambiq b/drivers/flash/Kconfig.ambiq index 5ce028bba9664..da0df1fcdab73 100644 --- a/drivers/flash/Kconfig.ambiq +++ b/drivers/flash/Kconfig.ambiq @@ -8,6 +8,8 @@ config FLASH_AMBIQ select AMBIQ_HAL select FLASH_HAS_PAGE_LAYOUT select FLASH_HAS_DRIVER_ENABLED + select FLASH_HAS_NO_EXPLICIT_ERASE if SOC_SERIES_APOLLO4X + select FLASH_HAS_EXPLICIT_ERASE if SOC_SERIES_APOLLO3X help Enables Ambiq flash driver on MRAM (e.g. Apollo4x) or flash (e.g. Apollo3x). diff --git a/drivers/flash/flash_ambiq.c b/drivers/flash/flash_ambiq.c index 30ce852404510..b496790b95868 100644 --- a/drivers/flash/flash_ambiq.c +++ b/drivers/flash/flash_ambiq.c @@ -48,6 +48,11 @@ static struct k_sem flash_ambiq_sem; static const struct flash_parameters flash_ambiq_parameters = { .write_block_size = FLASH_WRITE_BLOCK_SIZE, .erase_value = FLASH_ERASE_BYTE, +#if defined(CONFIG_SOC_SERIES_APOLLO4X) + .caps = { + .no_explicit_erase = true, + }, +#endif }; static bool flash_ambiq_valid_range(off_t offset, size_t len) From 294187b576434dcff77a363d99bcb9893b853f2e Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Mon, 5 Feb 2024 20:15:30 +0000 Subject: [PATCH 1626/2849] flash/spi_nor: Mark driver with FLASH_HAS_EXPLICIT_ERASE Sets the Kconfig CONFIG_FLASH_HAS_EXPLICIT_ERASE. Signed-off-by: Dominik Ermel --- drivers/flash/Kconfig.nor | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/flash/Kconfig.nor b/drivers/flash/Kconfig.nor index 8263f7f6785da..eed33c8e1807f 100644 --- a/drivers/flash/Kconfig.nor +++ b/drivers/flash/Kconfig.nor @@ -1,4 +1,6 @@ # Copyright (c) 2018 Savoir-Faire Linux. +# Copyright (c) 2024 Nordic Semiconductor ASA +# # SPDX-License-Identifier: Apache-2.0 menuconfig SPI_NOR @@ -6,6 +8,7 @@ menuconfig SPI_NOR default y depends on DT_HAS_JEDEC_SPI_NOR_ENABLED select FLASH_HAS_DRIVER_ENABLED + select FLASH_HAS_EXPLICIT_ERASE select FLASH_HAS_PAGE_LAYOUT select FLASH_JESD216 select FLASH_HAS_EX_OP From 4fd503adacaa2f7d38b7336656544da6c148acd3 Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Mon, 5 Feb 2024 21:05:36 +0000 Subject: [PATCH 1627/2849] drivers/flashdisk: Remove erase for devices that do not require it No erase when not needed by device. Signed-off-by: Dominik Ermel --- drivers/disk/flashdisk.c | 64 ++++++++++++++++++++++++++++++++++------ 1 file changed, 55 insertions(+), 9 deletions(-) diff --git a/drivers/disk/flashdisk.c b/drivers/disk/flashdisk.c index 6336ad4dfd03e..4c9d65ee7a634 100644 --- a/drivers/disk/flashdisk.c +++ b/drivers/disk/flashdisk.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2016 Intel Corporation. - * Copyright (c) 2022-2023 Nordic Semiconductor ASA + * Copyright (c) 2022-2024 Nordic Semiconductor ASA * * SPDX-License-Identifier: Apache-2.0 */ @@ -19,6 +19,11 @@ #include LOG_MODULE_REGISTER(flashdisk, CONFIG_FLASHDISK_LOG_LEVEL); +#if defined(CONFIG_FLASH_HAS_EXPLICIT_ERASE) && \ + defined(CONFIG_FLASH_HAS_NO_EXPLICIT_ERASE) +#define DISK_ERASE_RUNTIME_CHECK +#endif + struct flashdisk_data { struct disk_info info; struct k_mutex lock; @@ -32,11 +37,43 @@ struct flashdisk_data { off_t cached_addr; bool cache_valid; bool cache_dirty; + bool erase_required; }; #define GET_SIZE_TO_BOUNDARY(start, block_size) \ (block_size - (start & (block_size - 1))) +/* + * The default block size is used for devices not requiring erase. + * It defaults to 512 as this is most widely used sector size + * on storage devices. + */ +#define DEFAULT_BLOCK_SIZE 512 + +static inline bool flashdisk_with_erase(const struct flashdisk_data *ctx) +{ + ARG_UNUSED(ctx); +#if CONFIG_FLASH_HAS_EXPLICIT_ERASE +#if CONFIG_FLASH_HAS_NO_EXPLICIT_ERASE + return ctx->erase_required; +#else + return true; +#endif +#endif + return false; +} + +static inline void flashdisk_probe_erase(struct flashdisk_data *ctx) +{ +#if defined(DISK_ERASE_RUNTIME_CHECK) + ctx->erase_required = + flash_params_get_erase_cap(flash_get_parameters(ctx->info.dev)) & + FLASH_ERASE_C_EXPLICIT; +#else + ARG_UNUSED(ctx); +#endif +} + static int disk_flash_access_status(struct disk_info *disk) { LOG_DBG("status : %s", disk->dev ? "okay" : "no media"); @@ -54,13 +91,20 @@ static int flashdisk_init_runtime(struct flashdisk_data *ctx, struct flash_pages_info page; off_t offset; - rc = flash_get_page_info_by_offs(ctx->info.dev, ctx->offset, &page); - if (rc < 0) { - LOG_ERR("Error %d while getting page info", rc); - return rc; + flashdisk_probe_erase(ctx); + + if (IS_ENABLED(CONFIG_FLASHDISK_VERIFY_PAGE_LAYOUT) && flashdisk_with_erase(ctx)) { + rc = flash_get_page_info_by_offs(ctx->info.dev, ctx->offset, &page); + if (rc < 0) { + LOG_ERR("Error %d while getting page info", rc); + return rc; + } + + ctx->page_size = page.size; + } else { + ctx->page_size = DEFAULT_BLOCK_SIZE; } - ctx->page_size = page.size; LOG_INF("Initialize device %s", ctx->info.name); LOG_INF("offset %lx, sector size %zu, page size %zu, volume size %zu", (long)ctx->offset, ctx->sector_size, ctx->page_size, ctx->size); @@ -71,7 +115,7 @@ static int flashdisk_init_runtime(struct flashdisk_data *ctx, return 0; } - if (IS_ENABLED(CONFIG_FLASHDISK_VERIFY_PAGE_LAYOUT)) { + if (IS_ENABLED(CONFIG_FLASHDISK_VERIFY_PAGE_LAYOUT) && flashdisk_with_erase(ctx)) { if (ctx->offset != page.start_offset) { LOG_ERR("Disk %s does not start at page boundary", ctx->info.name); @@ -213,8 +257,10 @@ static int flashdisk_cache_commit(struct flashdisk_data *ctx) return 0; } - if (flash_erase(ctx->info.dev, ctx->cached_addr, ctx->page_size) < 0) { - return -EIO; + if (flashdisk_with_erase(ctx)) { + if (flash_erase(ctx->info.dev, ctx->cached_addr, ctx->page_size) < 0) { + return -EIO; + } } /* write data to flash */ From d7a4b634f2b01dae9ff977b6b2e09043eaafb714 Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Mon, 8 Apr 2024 16:13:28 +0200 Subject: [PATCH 1628/2849] tests/flash_disk: Expand scenarios to cover no erase device The commit adds overlay for native_posix and modifies testcase.yaml to allow testing CONFIG_DISK_DRIVER_FLASH with device that do not have erase requirement. Signed-off-by: Dominik Ermel --- .../native_posix_no_explicit_erase.overlay | 32 +++++++++++++++++++ tests/drivers/disk/disk_access/testcase.yaml | 8 +++++ 2 files changed, 40 insertions(+) create mode 100644 tests/drivers/disk/disk_access/boards/native_posix_no_explicit_erase.overlay diff --git a/tests/drivers/disk/disk_access/boards/native_posix_no_explicit_erase.overlay b/tests/drivers/disk/disk_access/boards/native_posix_no_explicit_erase.overlay new file mode 100644 index 0000000000000..1d4edb73e972a --- /dev/null +++ b/tests/drivers/disk/disk_access/boards/native_posix_no_explicit_erase.overlay @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&flashcontroller0 { + reg = <0x00000000 DT_SIZE_K(1024)>; +}; + +&flash0 { + reg = <0x00000000 DT_SIZE_K(1024)>; + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + flashdisk_partition: partition@0 { + label = "flashdisk"; + reg = <0x00000000 0x00100000>; + }; + }; +}; + +/ { + test_disk: storage_disk { + compatible = "zephyr,flash-disk"; + partition = <&flashdisk_partition>; + disk-name = "NAND"; + cache-size = <512>; + }; +}; diff --git a/tests/drivers/disk/disk_access/testcase.yaml b/tests/drivers/disk/disk_access/testcase.yaml index 9fc566158bc28..94f25c00703d0 100644 --- a/tests/drivers/disk/disk_access/testcase.yaml +++ b/tests/drivers/disk/disk_access/testcase.yaml @@ -36,3 +36,11 @@ tests: - native_sim drivers.disk.stm32_sdhc: filter: dt_compat_enabled("st,stm32-sdmmc") + drivers.disk.simulator.no_explicit_erase: + extra_args: DTC_OVERLAY_FILE=boards/native_posix_no_explicit_erase.overlay + extra_configs: + - CONFIG_DISK_DRIVER_FLASH=y + - CONFIG_FLASH_SIMULATOR_EXPLICIT_ERASE=n + platform_allow: + - native_posix/native/64 + - native_posix From 0c10b20cc8d02869dcbb802d6e95a06b7b866b1f Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Thu, 8 Feb 2024 21:47:11 +0000 Subject: [PATCH 1629/2849] drivers: nrf_qspi_nor: Mark driver with FLASH_HAS_EXPLICIT_ERASE All QSPI connected NOR Flash devices require erase prior to write. Signed-off-by: Dominik Ermel --- drivers/flash/Kconfig.nordic_qspi_nor | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/flash/Kconfig.nordic_qspi_nor b/drivers/flash/Kconfig.nordic_qspi_nor index 4acce55856791..82e1e197e3753 100644 --- a/drivers/flash/Kconfig.nordic_qspi_nor +++ b/drivers/flash/Kconfig.nordic_qspi_nor @@ -7,6 +7,7 @@ menuconfig NORDIC_QSPI_NOR depends on DT_HAS_NORDIC_QSPI_NOR_ENABLED select FLASH_HAS_DRIVER_ENABLED select FLASH_HAS_PAGE_LAYOUT + select FLASH_HAS_EXPLICIT_ERASE select NRFX_QSPI select FLASH_JESD216 select PINCTRL From 5da7df4e7c8497ea3b0a0a56eacd8b3cf80a83aa Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Sat, 9 Mar 2024 22:59:35 +0000 Subject: [PATCH 1630/2849] Bluetooth: Mesh: Switch erase to flash_area_flatten The flash_area_erase has been replaced with flash_area_flatten, allowing code to work with devices that do not provide erase callback. Signed-off-by: Dominik Ermel --- subsys/bluetooth/mesh/blob_io_flash.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/subsys/bluetooth/mesh/blob_io_flash.c b/subsys/bluetooth/mesh/blob_io_flash.c index b82a7d20f7f7e..31abd117e3ce4 100644 --- a/subsys/bluetooth/mesh/blob_io_flash.c +++ b/subsys/bluetooth/mesh/blob_io_flash.c @@ -88,8 +88,8 @@ static int block_start(const struct bt_mesh_blob_io *io, erase_size = block->size; #endif - return flash_area_erase(flash->area, flash->offset + block->offset, - erase_size); + return flash_area_flatten(flash->area, flash->offset + block->offset, + erase_size); } static int rd_chunk(const struct bt_mesh_blob_io *io, From def4f060c1f7ac4d837101e8cbfad6a34808b910 Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Sat, 9 Mar 2024 23:09:09 +0000 Subject: [PATCH 1631/2849] storage/settings: Replace flash_area_erase with flash_area_flatten Replace flash_area_erase with flash_area_flatten to allow FCB Settings backend to work on devices that do not provide erase callback. Signed-off-by: Dominik Ermel --- subsys/settings/src/settings_fcb.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/subsys/settings/src/settings_fcb.c b/subsys/settings/src/settings_fcb.c index 3922c54fb0880..f58e4e3700b3e 100644 --- a/subsys/settings/src/settings_fcb.c +++ b/subsys/settings/src/settings_fcb.c @@ -74,7 +74,7 @@ int settings_fcb_src(struct settings_fcb *cf) */ if (fcb_free_sector_cnt(&cf->cf_fcb) < 1) { - rc = flash_area_erase(cf->cf_fcb.fap, + rc = flash_area_flatten(cf->cf_fcb.fap, cf->cf_fcb.f_active.fe_sector->fs_off, cf->cf_fcb.f_active.fe_sector->fs_size); @@ -424,7 +424,7 @@ int settings_backend_init(void) return rc; } - rc = flash_area_erase(fap, 0, fap->fa_size); + rc = flash_area_flatten(fap, 0, fap->fa_size); flash_area_close(fap); if (rc != 0) { From 743d66a7e5d10b2fea4d836f651f385a1962fee3 Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Sat, 9 Mar 2024 23:10:58 +0000 Subject: [PATCH 1632/2849] debug/coredump/flash_backend: Switch to flash_area_flatten Replace usage of flash_area_erase with flash_area_flatten to allow code to work with devices that do not provide erase callback. Signed-off-by: Dominik Ermel --- .../coredump_backend_flash_partition.c | 30 ++++++++++++------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/subsys/debug/coredump/coredump_backend_flash_partition.c b/subsys/debug/coredump/coredump_backend_flash_partition.c index 434cd4774a180..6f96ae726d220 100644 --- a/subsys/debug/coredump/coredump_backend_flash_partition.c +++ b/subsys/debug/coredump/coredump_backend_flash_partition.c @@ -39,12 +39,21 @@ LOG_MODULE_REGISTER(coredump, CONFIG_KERNEL_LOG_LEVEL); #else +/* Note that currently external memories are not supported */ #define FLASH_CONTROLLER \ DT_PARENT(DT_PARENT(DT_NODELABEL(FLASH_PARTITION))) #define FLASH_WRITE_SIZE DT_PROP(FLASH_CONTROLLER, write_block_size) #define FLASH_BUF_SIZE FLASH_WRITE_SIZE -#define FLASH_ERASE_SIZE DT_PROP(FLASH_CONTROLLER, erase_block_size) +#if DT_NODE_HAS_PROP(FLASH_CONTROLLER, erase_block_size) +#define DEVICE_ERASE_BLOCK_SIZE DT_PROP(FLASH_CONTROLLER, erase_block_size) +#else +/* Device has no erase block size */ +#define DEVICE_ERASE_BLOCK_SIZE 1 +#endif + +#define HEADER_SCRAMBLE_SIZE ROUND_UP(sizeof(struct flash_hdr_t), \ + DEVICE_ERASE_BLOCK_SIZE) #define HDR_VER 1 @@ -344,9 +353,9 @@ static int get_stored_dump(off_t off, uint8_t *dst, size_t len) } /** - * @brief Erase the stored coredump header from flash partition. + * @brief Erase or scramble the stored coredump header from flash partition. * - * This erases the stored coredump header from the flash partition, + * This erases or scrambles the stored coredump header from the flash partition, * invalidating the coredump data. * * @return 0 if successful; error otherwise @@ -357,10 +366,9 @@ static int erase_coredump_header(void) ret = partition_open(); if (ret == 0) { - /* Erase header block */ - ret = flash_area_erase(backend_ctx.flash_area, 0, - ROUND_UP(sizeof(struct flash_hdr_t), - FLASH_ERASE_SIZE)); + /* Erase or scramble header block */ + ret = flash_area_flatten(backend_ctx.flash_area, 0, + HEADER_SCRAMBLE_SIZE); } partition_close(); @@ -382,8 +390,8 @@ static int erase_flash_partition(void) ret = partition_open(); if (ret == 0) { /* Erase whole flash partition */ - ret = flash_area_erase(backend_ctx.flash_area, 0, - backend_ctx.flash_area->fa_size); + ret = flash_area_flatten(backend_ctx.flash_area, 0, + backend_ctx.flash_area->fa_size); } partition_close(); @@ -406,8 +414,8 @@ static void coredump_flash_backend_start(void) if (ret == 0) { /* Erase whole flash partition */ - ret = flash_area_erase(backend_ctx.flash_area, 0, - backend_ctx.flash_area->fa_size); + ret = flash_area_flatten(backend_ctx.flash_area, 0, + backend_ctx.flash_area->fa_size); } if (ret == 0) { From 9da26eda5eafa4d988660d00209fee616eb1629d Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Sat, 9 Mar 2024 23:06:57 +0000 Subject: [PATCH 1633/2849] fs/littlefs: Use flash_area_flatten in lfs_api_erase LittleFS is based on program-erase devices and require that characteristics to work; the commit replaces flash_area_erase with flash_area_flatten to allow LFS work on devices that do not provide erase callback. Signed-off-by: Dominik Ermel --- subsys/fs/Kconfig.littlefs | 2 +- subsys/fs/littlefs_fs.c | 18 +++++++++++++++++- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/subsys/fs/Kconfig.littlefs b/subsys/fs/Kconfig.littlefs index 50ebf7531f7a0..c3ebde18c3965 100644 --- a/subsys/fs/Kconfig.littlefs +++ b/subsys/fs/Kconfig.littlefs @@ -106,7 +106,7 @@ endif # FS_LITTLEFS_FC_HEAP_SIZE <= 0 config FS_LITTLEFS_FMP_DEV bool "Support for littlefs on flash devices" depends on FLASH_MAP - depends on FLASH_PAGE_LAYOUT + depends on FLASH_PAGE_LAYOUT || !FLASH_HAS_EXPLICIT_ERASE default y help Enable this option to provide support for littlefs on flash devices diff --git a/subsys/fs/littlefs_fs.c b/subsys/fs/littlefs_fs.c index b373ca92ba8ea..5989f856ac1f2 100644 --- a/subsys/fs/littlefs_fs.c +++ b/subsys/fs/littlefs_fs.c @@ -28,6 +28,9 @@ #include "fs_impl.h" +/* Used on devices that have no explicit erase */ +#define LITTLEFS_DEFAULT_BLOCK_SIZE 4096 + /* note: one of the next options have to be enabled, at least */ BUILD_ASSERT(IS_ENABLED(CONFIG_FS_LITTLEFS_BLK_DEV) || IS_ENABLED(CONFIG_FS_LITTLEFS_FMP_DEV)); @@ -195,7 +198,7 @@ static int lfs_api_erase(const struct lfs_config *c, lfs_block_t block) const struct flash_area *fa = c->context; size_t offset = block * c->block_size; - int rc = flash_area_erase(fa, offset, c->block_size); + int rc = flash_area_flatten(fa, offset, c->block_size); return errno_to_lfs(rc); } @@ -581,6 +584,7 @@ static int littlefs_statvfs(struct fs_mount_t *mountp, #ifdef CONFIG_FS_LITTLEFS_FMP_DEV +#if defined(CONFIG_FLASH_HAS_EXPLICIT_ERASE) /* Return maximum page size in a flash area. There's no flash_area * API to implement this, so we have to make one here. */ @@ -612,6 +616,7 @@ static bool get_page_cb(const struct flash_pages_info *info, void *ctxp) return true; } +#endif /* Iterate over all page groups in the flash area and return the * largest page size we see. This works as long as the partition is @@ -620,15 +625,26 @@ static bool get_page_cb(const struct flash_pages_info *info, void *ctxp) */ static lfs_size_t get_block_size(const struct flash_area *fa) { +#if defined(CONFIG_FLASH_HAS_EXPLICIT_ERASE) struct get_page_ctx ctx = { .area = fa, .max_size = 0, }; const struct device *dev = flash_area_get_device(fa); +#if defined(CONFIG_FLASH_HAS_NO_EXPLICIT_ERASE) + const struct flash_parameters *fparams = flash_get_parameters(dev); + + if (!(flash_params_get_erase_cap(fparams) & FLASH_ERASE_C_EXPLICIT)) { + return LITTLEFS_DEFAULT_BLOCK_SIZE; + } +#endif flash_page_foreach(dev, get_page_cb, &ctx); return ctx.max_size; +#else + return LITTLEFS_DEFAULT_BLOCK_SIZE; +#endif } static int littlefs_flash_init(struct fs_littlefs *fs, void *dev_id) From 64ccfb0479cade35e754c8dbe92b8cac169059df Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Fri, 1 Mar 2024 19:28:31 +0000 Subject: [PATCH 1634/2849] fs/fcb: Replace flash_area_erase with flash_area_flatten FCB depends on explicit erase characteristics of a device. Signed-off-by: Dominik Ermel --- subsys/fs/fcb/fcb.c | 3 +-- tests/subsys/fs/fcb/testcase.yaml | 6 ++++++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/subsys/fs/fcb/fcb.c b/subsys/fs/fcb/fcb.c index 778df0f54a6f1..44358a8dbeac3 100644 --- a/subsys/fs/fcb/fcb.c +++ b/subsys/fs/fcb/fcb.c @@ -82,8 +82,7 @@ fcb_erase_sector(const struct fcb *fcb, const struct flash_sector *sector) return -EIO; } - rc = flash_area_erase(fcb->fap, sector->fs_off, sector->fs_size); - + rc = flash_area_flatten(fcb->fap, sector->fs_off, sector->fs_size); if (rc != 0) { return -EIO; } diff --git a/tests/subsys/fs/fcb/testcase.yaml b/tests/subsys/fs/fcb/testcase.yaml index e01566b6721bb..19e47e33a1bdc 100644 --- a/tests/subsys/fs/fcb/testcase.yaml +++ b/tests/subsys/fs/fcb/testcase.yaml @@ -12,6 +12,12 @@ tests: tags: flash_circural_buffer integration_platforms: - nrf52840dk/nrf52840 + filesystem.fcb.no_erase: + platform_allow: + - nrf54l15pdk/nrf54l15/cpuapp + filesystem.fcb.native_sim.no_erase: + extra_args: CONFIG_FLASH_SIMULATOR_EXPLICIT_ERASE=n + platform_allow: native_sim filesystem.fcb.native_sim.fcb_0x00: extra_args: DTC_OVERLAY_FILE=boards/native_sim_ev_0x00.overlay platform_allow: native_sim From bf7d25117a65b5a7cab02c6191319c3d305e6874 Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Thu, 8 Feb 2024 22:31:37 +0000 Subject: [PATCH 1635/2849] fs/nvs: Switch to use flash_flatten instead of flash_erase The NVS currently requires explict erase capability of a device to work, so usage of flash_erase has been replaced with flash_flatten. There has been additional LOG_WRN added to warn user that NVS may not efficiently work with device that do not really have erase. Currently NVS relies on devices that require erase. Signed-off-by: Dominik Ermel --- subsys/fs/nvs/nvs.c | 2 +- tests/subsys/fs/nvs/src/main.c | 11 +++++++++++ tests/subsys/fs/nvs/testcase.yaml | 3 +++ 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/subsys/fs/nvs/nvs.c b/subsys/fs/nvs/nvs.c index ef35e677710e9..a07f9b3198bb1 100644 --- a/subsys/fs/nvs/nvs.c +++ b/subsys/fs/nvs/nvs.c @@ -308,7 +308,7 @@ static int nvs_flash_erase_sector(struct nvs_fs *fs, uint32_t addr) #ifdef CONFIG_NVS_LOOKUP_CACHE nvs_lookup_cache_invalidate(fs, addr >> ADDR_SECT_SHIFT); #endif - rc = flash_erase(fs->flash_device, offset, fs->sector_size); + rc = flash_flatten(fs->flash_device, offset, fs->sector_size); if (rc) { return rc; diff --git a/tests/subsys/fs/nvs/src/main.c b/tests/subsys/fs/nvs/src/main.c index 97e41f15b9666..34a0080866d95 100644 --- a/tests/subsys/fs/nvs/src/main.c +++ b/tests/subsys/fs/nvs/src/main.c @@ -207,7 +207,18 @@ ZTEST_F(nvs, test_nvs_corrupted_write) &flash_max_write_calls); stats_walk(fixture->sim_stats, flash_sim_write_calls_find, &flash_write_stat); +#if defined(CONFIG_FLASH_SIMULATOR_EXPLICIT_ERASE) *flash_max_write_calls = *flash_write_stat - 1; +#else + /* When there is no explicit erase, erase is done with write, which means + * that there are more writes needed. The nvs_write here will cause erase + * to be called, which in turn calls the flash_fill; flash_fill will + * overwrite data using buffer of size CONFIG_FLASH_FILL_BUFFER_SIZE, + * and then two additional real writes are allowed. + */ + *flash_max_write_calls = (fixture->fs.sector_size / + CONFIG_FLASH_FILL_BUFFER_SIZE) + 2; +#endif *flash_write_stat = 0; /* Flash simulator will lose part of the data at the end of this write. diff --git a/tests/subsys/fs/nvs/testcase.yaml b/tests/subsys/fs/nvs/testcase.yaml index f462a33ff0ed5..f02fc257fc1d3 100644 --- a/tests/subsys/fs/nvs/testcase.yaml +++ b/tests/subsys/fs/nvs/testcase.yaml @@ -6,6 +6,9 @@ tests: filesystem.nvs.0x00: extra_args: DTC_OVERLAY_FILE=boards/qemu_x86_ev_0x00.overlay platform_allow: qemu_x86 + filesystem.nvs.sim.no_erase: + extra_args: CONFIG_FLASH_SIMULATOR_EXPLICIT_ERASE=n + platform_allow: qemu_x86 filesystem.nvs.cache: extra_args: - CONFIG_NVS_LOOKUP_CACHE=y From 1ae352a760e1d7e2d1fca21c9ee185996459dce7 Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Sat, 9 Mar 2024 22:24:46 +0000 Subject: [PATCH 1636/2849] tests/fs: Replace flash_area_erase with flash_area_flatten Test of file systems use flash_area_erase to erase device to have a clear start for tests; switching to flash_area_flatten allows them to do the same with devices that do not explicit call to erase procedure before write. Signed-off-by: Dominik Ermel --- tests/subsys/fs/fat_fs_api/src/test_fat_mkfs.c | 2 +- tests/subsys/fs/fcb/src/main.c | 2 +- tests/subsys/fs/littlefs/src/testfs_lfs.c | 2 +- tests/subsys/fs/multi-fs/src/test_utils.c | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/subsys/fs/fat_fs_api/src/test_fat_mkfs.c b/tests/subsys/fs/fat_fs_api/src/test_fat_mkfs.c index a377fd1a5234a..5af5b53788cbb 100644 --- a/tests/subsys/fs/fat_fs_api/src/test_fat_mkfs.c +++ b/tests/subsys/fs/fat_fs_api/src/test_fat_mkfs.c @@ -45,7 +45,7 @@ static int wipe_partition(void) } TC_PRINT("Erasing %zu (0x%zx) bytes\n", pfa->fa_size, pfa->fa_size); - rc = flash_area_erase(pfa, 0, pfa->fa_size); + rc = flash_area_flatten(pfa, 0, pfa->fa_size); (void)flash_area_close(pfa); if (rc < 0) { diff --git a/tests/subsys/fs/fcb/src/main.c b/tests/subsys/fs/fcb/src/main.c index fb2afd6dc9f4a..2603f7fddf586 100644 --- a/tests/subsys/fs/fcb/src/main.c +++ b/tests/subsys/fs/fcb/src/main.c @@ -58,7 +58,7 @@ void test_fcb_wipe(void) zassert_true(rc == 0, "flash area open call failure"); for (i = 0; i < ARRAY_SIZE(test_fcb_sector); i++) { - rc = flash_area_erase(fap, test_fcb_sector[i].fs_off, + rc = flash_area_flatten(fap, test_fcb_sector[i].fs_off, test_fcb_sector[i].fs_size); zassert_true(rc == 0, "erase call failure"); } diff --git a/tests/subsys/fs/littlefs/src/testfs_lfs.c b/tests/subsys/fs/littlefs/src/testfs_lfs.c index c195b7cde0b67..01737749ec181 100644 --- a/tests/subsys/fs/littlefs/src/testfs_lfs.c +++ b/tests/subsys/fs/littlefs/src/testfs_lfs.c @@ -73,7 +73,7 @@ int testfs_lfs_wipe_partition(const struct fs_mount_t *mp) } TC_PRINT("Erasing %zu (0x%zx) bytes\n", pfa->fa_size, pfa->fa_size); - rc = flash_area_erase(pfa, 0, pfa->fa_size); + rc = flash_area_flatten(pfa, 0, pfa->fa_size); (void)flash_area_close(pfa); if (rc < 0) { diff --git a/tests/subsys/fs/multi-fs/src/test_utils.c b/tests/subsys/fs/multi-fs/src/test_utils.c index 1f50240df0690..579007ab8ff2a 100644 --- a/tests/subsys/fs/multi-fs/src/test_utils.c +++ b/tests/subsys/fs/multi-fs/src/test_utils.c @@ -31,6 +31,6 @@ void test_clear_flash(void) rc = flash_area_open(TEST_PARTITION_ID, &fap); zassert_equal(rc, 0, "Opening flash area for erase [%d]\n", rc); - rc = flash_area_erase(fap, 0, fap->fa_size); + rc = flash_area_flatten(fap, 0, fap->fa_size); zassert_equal(rc, 0, "Erasing flash area [%d]\n", rc); } From 7894474cf9a2644682428d4f360c5ea8e71ad4cb Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Sat, 9 Mar 2024 22:21:20 +0000 Subject: [PATCH 1637/2849] tests/settings: Move from flash_area_erase to flash_area_flatten The Settings test wipe out areas to have a start clean, so flash_arae_flatten will do that form them for program-erase and no-erase devices. Signed-off-by: Dominik Ermel --- tests/subsys/settings/fcb/src/settings_test_fcb.c | 2 +- tests/subsys/settings/fcb_init/src/settings_test_fcb_init.c | 2 +- tests/subsys/settings/file/src/settings_setup_littlefs.c | 2 +- tests/subsys/settings/functional/src/settings_basic_test.c | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/subsys/settings/fcb/src/settings_test_fcb.c b/tests/subsys/settings/fcb/src/settings_test_fcb.c index fdc2b7b8aac80..1b3097c6f8b31 100644 --- a/tests/subsys/settings/fcb/src/settings_test_fcb.c +++ b/tests/subsys/settings/fcb/src/settings_test_fcb.c @@ -193,7 +193,7 @@ void config_wipe_fcb(struct flash_sector *fs, int cnt) rc = flash_area_open(TEST_PARTITION_ID, &fap); for (i = 0; i < cnt; i++) { - rc = flash_area_erase(fap, fs[i].fs_off, fs[i].fs_size); + rc = flash_area_flatten(fap, fs[i].fs_off, fs[i].fs_size); zassert_true(rc == 0, "Can't get flash area"); } } diff --git a/tests/subsys/settings/fcb_init/src/settings_test_fcb_init.c b/tests/subsys/settings/fcb_init/src/settings_test_fcb_init.c index 964fc87c16658..8e3be17c4b354 100644 --- a/tests/subsys/settings/fcb_init/src/settings_test_fcb_init.c +++ b/tests/subsys/settings/fcb_init/src/settings_test_fcb_init.c @@ -110,7 +110,7 @@ void test_prepare_storage(void) err = flash_area_open(TEST_PARTITION_ID, &fa); zassert_true(err == 0, "Can't open storage flash area"); - err = flash_area_erase(fa, 0, fa->fa_size); + err = flash_area_flatten(fa, 0, fa->fa_size); zassert_true(err == 0, "Can't erase storage flash area"); err = flash_area_open(CODE_PARTITION_ID, &fa); diff --git a/tests/subsys/settings/file/src/settings_setup_littlefs.c b/tests/subsys/settings/file/src/settings_setup_littlefs.c index 2e2beb8bcee09..5e1705b876bfd 100644 --- a/tests/subsys/settings/file/src/settings_setup_littlefs.c +++ b/tests/subsys/settings/file/src/settings_setup_littlefs.c @@ -29,7 +29,7 @@ void *config_setup_fs(void) rc = flash_area_open(LITTLEFS_PARTITION_ID, &fap); zassume_true(rc == 0, "opening flash area for erase [%d]\n", rc); - rc = flash_area_erase(fap, 0, fap->fa_size); + rc = flash_area_flatten(fap, 0, fap->fa_size); zassume_true(rc == 0, "erasing flash area [%d]\n", rc); rc = fs_mount(&littlefs_mnt); diff --git a/tests/subsys/settings/functional/src/settings_basic_test.c b/tests/subsys/settings/functional/src/settings_basic_test.c index 81d4934fbfa1f..5798605a5a709 100644 --- a/tests/subsys/settings/functional/src/settings_basic_test.c +++ b/tests/subsys/settings/functional/src/settings_basic_test.c @@ -45,7 +45,7 @@ ZTEST(settings_functional, test_clear_settings) rc = flash_area_open(TEST_FLASH_AREA_ID, &fap); if (rc == 0) { - rc = flash_area_erase(fap, 0, fap->fa_size); + rc = flash_area_flatten(fap, 0, fap->fa_size); flash_area_close(fap); } zassert_true(rc == 0, "clear settings failed"); From 95dfd1210d0fe2e5aa1a8cfd5a681860cf04a2fb Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Fri, 1 Mar 2024 20:49:48 +0000 Subject: [PATCH 1638/2849] storage/stream_flash: Support for devices without explicit erase Support for devices not requiring erase with Stream Flash API. Signed-off-by: Dominik Ermel --- subsys/storage/stream/Kconfig | 2 ++ subsys/storage/stream/stream_flash.c | 12 ++++++++++++ 2 files changed, 14 insertions(+) diff --git a/subsys/storage/stream/Kconfig b/subsys/storage/stream/Kconfig index 63a9df458513f..59a985feb1248 100644 --- a/subsys/storage/stream/Kconfig +++ b/subsys/storage/stream/Kconfig @@ -11,8 +11,10 @@ menuconfig STREAM_FLASH Enable support of stream to flash API if STREAM_FLASH + config STREAM_FLASH_ERASE bool "Perform erase operations" + depends on FLASH_HAS_EXPLICIT_ERASE help If disabled an external actor must erase the flash area being written to. diff --git a/subsys/storage/stream/stream_flash.c b/subsys/storage/stream/stream_flash.c index e9b1a3dbc2722..b9bd63df411be 100644 --- a/subsys/storage/stream/stream_flash.c +++ b/subsys/storage/stream/stream_flash.c @@ -76,9 +76,18 @@ static int settings_direct_loader(const char *key, size_t len, int stream_flash_erase_page(struct stream_flash_ctx *ctx, off_t off) { +#if IS_ENABLED(CONFIG_FLASH_HAS_EXPLICIT_ERASE) int rc; struct flash_pages_info page; +#if IS_ENABLED(CONFIG_FLASH_HAS_NO_EXPLICIT_ERASE) + /* There are both types of devices */ + const struct flash_parameters *fparams = flash_get_parameters(ctx->fdev); + /* Stream flash does not rely on erase, it does it when device needs it */ + if (!(flash_params_get_erase_cap(fparams) & FLASH_ERASE_C_EXPLICIT)) { + return 0; + } +#endif rc = flash_get_page_info_by_offs(ctx->fdev, off, &page); if (rc != 0) { LOG_ERR("Error %d while getting page info", rc); @@ -100,6 +109,9 @@ int stream_flash_erase_page(struct stream_flash_ctx *ctx, off_t off) } return rc; +#else + return 0; +#endif } #endif /* CONFIG_STREAM_FLASH_ERASE */ From 27f5291b9461f2cc491530178608d68783b31be8 Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Fri, 1 Mar 2024 20:57:47 +0000 Subject: [PATCH 1639/2849] tests/storage/stream_flash: Support for devices without explicit erase Adds code that runs erase only when needed. Signed-off-by: Dominik Ermel --- .../storage/stream/stream_flash/src/main.c | 17 ++++++++++++++++- .../storage/stream/stream_flash/testcase.yaml | 13 +++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/tests/subsys/storage/stream/stream_flash/src/main.c b/tests/subsys/storage/stream/stream_flash/src/main.c index 089f68cd72e49..7b4627101c236 100644 --- a/tests/subsys/storage/stream/stream_flash/src/main.c +++ b/tests/subsys/storage/stream/stream_flash/src/main.c @@ -41,7 +41,9 @@ static uint8_t generic_buf[BUF_LEN]; static uint8_t read_buf[TESTBUF_SIZE]; const static uint8_t write_buf[TESTBUF_SIZE] = {[0 ... TESTBUF_SIZE - 1] = 0xaa}; static uint8_t written_pattern[TESTBUF_SIZE] = {[0 ... TESTBUF_SIZE - 1] = 0xaa}; +#if defined(CONFIG_FLASH_HAS_EXPLICIT_ERASE) static uint8_t erased_pattern[TESTBUF_SIZE] = {[0 ... TESTBUF_SIZE - 1] = 0xff}; +#endif #define VERIFY_BUF(start, size, buf) \ do { \ @@ -51,7 +53,11 @@ do { \ } while (0) #define VERIFY_WRITTEN(start, size) VERIFY_BUF(start, size, written_pattern) +#if defined(CONFIG_FLASH_HAS_EXPLICIT_ERASE) #define VERIFY_ERASED(start, size) VERIFY_BUF(start, size, erased_pattern) +#else +#define VERIFY_ERASED(start, size) +#endif int stream_flash_callback(uint8_t *buf, size_t len, size_t offset) { @@ -66,7 +72,15 @@ int stream_flash_callback(uint8_t *buf, size_t len, size_t offset) static void erase_flash(void) { +#if IS_ENABLED(CONFIG_FLASH_HAS_EXPLICIT_ERASE) int rc; +#if IS_ENABLED(CONFIG_FLASH_HAS_NO_EXPLICIT_ERASE) + const struct flash_parameters *fparam = flash_get_parameters(fdev); + + if (!(flash_params_get_erase_cap(fparam) & FLASH_ERASE_C_EXPLICIT)) { + return; + } +#endif for (int i = 0; i < MAX_NUM_PAGES; i++) { rc = flash_erase(fdev, @@ -74,6 +88,7 @@ static void erase_flash(void) layout->pages_size); zassert_equal(rc, 0, "should succeed"); } +#endif } @@ -588,7 +603,7 @@ ZTEST(lib_stream_flash, test_stream_flash_progress_resume) bytes_written = load_progress(progress_key); zassert_equal(bytes_written, bytes_written_old, "expected bytes_written to be loaded"); -#ifdef CONFIG_STREAM_FLASH_ERASE +#if defined(CONFIG_STREAM_FLASH_ERASE) zassert_equal(erase_offset_old, ctx.last_erased_page_start_offset, "expected last erased page offset to be loaded"); #endif diff --git a/tests/subsys/storage/stream/stream_flash/testcase.yaml b/tests/subsys/storage/stream/stream_flash/testcase.yaml index a2df663d8714f..5d4e35a6ead4c 100644 --- a/tests/subsys/storage/stream/stream_flash/testcase.yaml +++ b/tests/subsys/storage/stream/stream_flash/testcase.yaml @@ -9,6 +9,19 @@ common: tests: storage.stream_flash: tags: stream_flash + storage.stream_flash.simulator.no_explicit_erase: + extra_args: + - CONFIG_STREAM_FLASH_ERASE=n + - CONFIG_FLASH_SIMULATOR_EXPLICIT_ERASE=n + platform_allow: + - native_posix + - native_posix/native/64 + - native_sim + - native_sim/native/64 + tags: stream_flash + storage.stream_flash.no_explicit_erase: + platform_allow: + - nrf54l15pdk/nrf54l15/cpuapp storage.stream_flash.dword_wbs: extra_args: DTC_OVERLAY_FILE=unaligned_flush.overlay tags: stream_flash From bce06a64c41451fa7b417d048e403632e44cc680 Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Sat, 9 Mar 2024 22:34:46 +0000 Subject: [PATCH 1640/2849] mgmt/mcumgr: Replace use of flash_area_erase with flash_area_flatten The commit replaces flash_area_erase with flash_area_flatten. The function is used in to places: 1) in image management commands IMG_MGMT_ID_UPLOAD and IMG_MGMT_ID_ERASE: to erase an image in secondary slot or to scramble trailer part of image, which could be misunderstood by MCUboot as valid image operation request; 2) in command ZEPHYR_MGMT_GRP_BASIC_CMD_ERASE_STORAGE to erase/scramble data partition. Signed-off-by: Dominik Ermel --- subsys/mgmt/mcumgr/grp/img_mgmt/src/zephyr_img_mgmt.c | 6 +++--- subsys/mgmt/mcumgr/grp/zephyr_basic/src/basic_mgmt.c | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/subsys/mgmt/mcumgr/grp/img_mgmt/src/zephyr_img_mgmt.c b/subsys/mgmt/mcumgr/grp/img_mgmt/src/zephyr_img_mgmt.c index c899e31a3fb9b..b24babc6f8cbf 100644 --- a/subsys/mgmt/mcumgr/grp/img_mgmt/src/zephyr_img_mgmt.c +++ b/subsys/mgmt/mcumgr/grp/img_mgmt/src/zephyr_img_mgmt.c @@ -294,7 +294,7 @@ int img_mgmt_erase_slot(int slot) rc = img_mgmt_flash_check_empty_inner(fa); if (rc == 0) { - rc = flash_area_erase(fa, 0, fa->fa_size); + rc = flash_area_flatten(fa, 0, fa->fa_size); if (rc != 0) { LOG_ERR("Failed to erase flash area: %d", rc); @@ -473,7 +473,7 @@ int img_mgmt_erase_image_data(unsigned int off, unsigned int num_bytes) size_t erase_size = page.start_offset + page.size - fa->fa_off; - rc = flash_area_erase(fa, 0, erase_size); + rc = flash_area_flatten(fa, 0, erase_size); if (rc != 0) { LOG_ERR("image slot erase of 0x%zx bytes failed (err %d)", erase_size, @@ -498,7 +498,7 @@ int img_mgmt_erase_image_data(unsigned int off, unsigned int num_bytes) off = page.start_offset - fa->fa_off; erase_size = fa->fa_size - off; - rc = flash_area_erase(fa, off, erase_size); + rc = flash_area_flatten(fa, off, erase_size); if (rc != 0) { LOG_ERR("image slot trailer erase of 0x%zx bytes failed (err %d)", erase_size, rc); diff --git a/subsys/mgmt/mcumgr/grp/zephyr_basic/src/basic_mgmt.c b/subsys/mgmt/mcumgr/grp/zephyr_basic/src/basic_mgmt.c index 633b840a1a401..7c7c5d50161f5 100644 --- a/subsys/mgmt/mcumgr/grp/zephyr_basic/src/basic_mgmt.c +++ b/subsys/mgmt/mcumgr/grp/zephyr_basic/src/basic_mgmt.c @@ -31,7 +31,7 @@ static int storage_erase(void) LOG_ERR("Failed to get flash area device"); rc = ZEPHYRBASIC_MGMT_ERR_FLASH_CONFIG_QUERY_FAIL; } else { - rc = flash_area_erase(fa, 0, fa->fa_size); + rc = flash_area_flatten(fa, 0, fa->fa_size); if (rc < 0) { LOG_ERR("Failed to erase flash area"); From c4c7e15ba10fad75e13e95ce5d105e53e1d6ce12 Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Sat, 9 Mar 2024 22:49:32 +0000 Subject: [PATCH 1641/2849] dfu/mcuboot: Use flash_area_flatten instead of flash_area_erase The invocation of flash_area_erase, in boot_erase_img_bank, has been replaced by flash_area_flatten. Signed-off-by: Dominik Ermel --- subsys/dfu/boot/mcuboot.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subsys/dfu/boot/mcuboot.c b/subsys/dfu/boot/mcuboot.c index 4f03c7c9e24c9..20015349dbc6e 100644 --- a/subsys/dfu/boot/mcuboot.c +++ b/subsys/dfu/boot/mcuboot.c @@ -252,7 +252,7 @@ int boot_erase_img_bank(uint8_t area_id) return rc; } - rc = flash_area_erase(fa, 0, fa->fa_size); + rc = flash_area_flatten(fa, 0, fa->fa_size); flash_area_close(fa); From 7b36d34504018d08ff5e812175fa7f952cc059eb Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Sat, 9 Mar 2024 22:46:00 +0000 Subject: [PATCH 1642/2849] tests/dfu: Replace flash_area_erase with flash_area_flatten Use flash_area_flatten instead of flash_area_erase; this allows to run tests on devices that do not require explicit erase before write or do not provide the callback. Signed-off-by: Dominik Ermel --- tests/subsys/dfu/img_util/src/main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/subsys/dfu/img_util/src/main.c b/tests/subsys/dfu/img_util/src/main.c index 8e518388bf353..d72efa2cb0623 100644 --- a/tests/subsys/dfu/img_util/src/main.c +++ b/tests/subsys/dfu/img_util/src/main.c @@ -73,7 +73,7 @@ ZTEST(img_util, test_collecting) sizeof(erase_buf)); zassert_true(ret == 0, "Flash write failure (%d)", ret); #else - ret = flash_area_erase(ctx.flash_area, 0, ctx.flash_area->fa_size); + ret = flash_area_flatten(ctx.flash_area, 0, ctx.flash_area->fa_size); zassert_true(ret == 0, "Flash erase failure (%d)", ret); #endif @@ -137,7 +137,7 @@ ZTEST(img_util, test_check_flash) ret = flash_img_init_id(&ctx, SLOT1_PARTITION_ID); zassert_true(ret == 0, "Flash img init 1"); - ret = flash_area_erase(ctx.flash_area, 0, ctx.flash_area->fa_size); + ret = flash_area_flatten(ctx.flash_area, 0, ctx.flash_area->fa_size); zassert_true(ret == 0, "Flash erase failure (%d)\n", ret); ret = flash_img_buffered_write(&ctx, tst_vec, sizeof(tst_vec), true); zassert_true(ret == 0, "Flash img buffered write\n"); From 8dc1fcec03da35d078e3bbd7d06ff5794589bd18 Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Sat, 9 Mar 2024 22:44:28 +0000 Subject: [PATCH 1643/2849] tests: Bluetooth: Mesh: Use flash_area_flatten for erase The flash_area_erase is replaced with flash_area_flatten that is also able to erase/scramble devices that do not require explicit call to erase procedure before write. Signed-off-by: Dominik Ermel --- tests/bluetooth/mesh/blob_io_flash/src/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/bluetooth/mesh/blob_io_flash/src/main.c b/tests/bluetooth/mesh/blob_io_flash/src/main.c index 18111e1565f79..62fe590e6d914 100644 --- a/tests/bluetooth/mesh/blob_io_flash/src/main.c +++ b/tests/bluetooth/mesh/blob_io_flash/src/main.c @@ -68,7 +68,7 @@ ZTEST(blob_io_flash, test_chunk_read) err = flash_area_open(SLOT1_PARTITION_ID, &fa); zassert_equal(err, 0, "Preparing test data failed with err=%d", err); - err = flash_area_erase(fa, 0, ARRAY_SIZE(ctrl_data)); + err = flash_area_flatten(fa, 0, ARRAY_SIZE(ctrl_data)); zassert_equal(err, 0, "Preparing test data failed with err=%d", err); err = flash_area_write(fa, 0, test_data, ARRAY_SIZE(ctrl_data)); From c7037532b898a7143b966eee99979e57a8133c6d Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Mon, 5 Feb 2024 15:56:16 +0000 Subject: [PATCH 1644/2849] samples/soc_flash_nrf: Adjust for non-Flash SoC devices The sample has been modified to work with devices that have no explicit erase capability. For that purpose printf messages have been modified to use "Internal storage" rather than "Flash" when reporting status. Signed-off-by: Dominik Ermel --- samples/drivers/soc_flash_nrf/README.rst | 23 +++--- samples/drivers/soc_flash_nrf/src/main.c | 95 ++++++++++++++++-------- 2 files changed, 74 insertions(+), 44 deletions(-) diff --git a/samples/drivers/soc_flash_nrf/README.rst b/samples/drivers/soc_flash_nrf/README.rst index 2b69d8d6cb639..9f34ee631b6e9 100644 --- a/samples/drivers/soc_flash_nrf/README.rst +++ b/samples/drivers/soc_flash_nrf/README.rst @@ -1,5 +1,5 @@ .. zephyr:code-sample:: soc-flash-nrf - :name: nRF SoC flash + :name: nRF SoC Internal Storage :relevant-api: flash_interface flash_area_api Use the flash API to interact with the SoC flash. @@ -7,10 +7,11 @@ Overview ******** -This sample demonstrates using the :ref:`Flash API ` on an SoC internal flash. -The sample uses :ref:`Flash map API ` to obtain device for flash, using -DTS node label, and then directly uses :ref:`Flash API ` to perform -flash operations. +This sample demonstrates using the :ref:`Flash API ` on an SoC internal storage. +The sample uses :ref:`Flash map API ` to obtain a device that has +partition defined with label `storage_partition`, then uses :ref:`Flash API ` +to directly access and modify contents of a device, within area defined for said +partition. Within the sample, user may observe how read/write/erase operations are performed on a device, and how to first check whether device is @@ -19,11 +20,9 @@ ready for operation. Building and Running ******************** -The application will build for any SoC with internal flash memory -access enabled, as it is default for SoC devices, and fixed-partition -defined over that internal flash labeled `slot1_partition`, when -:kconfig:option:`CONFIG_TRUSTED_EXECUTION_NONSECURE` is not selected, -or `slot1_ns_partition`, when the Kconfig option is selected. +The application will build for any SoC with internal storage +access enabled, as it is default for SoC devices with defined +fixed-partition, over that internal storage, labeled `storage_partition`. .. zephyr-app-commands:: :zephyr-app: samples/drivers/soc_flash_nrf @@ -38,8 +37,8 @@ Sample Output *** Booting Zephyr OS build v2.7.99-17621-g54832687bcbb *** - Nordic nRF5 Flash Testing - ========================= + Nordic nRF5 Internal Storage Sample + =================================== Test 1: Flash erase page at 0x82000 Flash erase succeeded! diff --git a/samples/drivers/soc_flash_nrf/src/main.c b/samples/drivers/soc_flash_nrf/src/main.c index 29606a9ca5dfe..d55214afcc515 100644 --- a/samples/drivers/soc_flash_nrf/src/main.c +++ b/samples/drivers/soc_flash_nrf/src/main.c @@ -1,6 +1,7 @@ /* * Copyright (c) 2016 Linaro Limited * 2016 Intel Corporation. + * Copyright (c) 2024 Nordic Semiconductor ASA * * SPDX-License-Identifier: Apache-2.0 */ @@ -27,9 +28,45 @@ #define FLASH_TEST_OFFSET2 0x41234 #define FLASH_TEST_PAGE_IDX 37 +#if IS_ENABLED(CONFIG_FLASH_HAS_EXPLICIT_ERASE) && \ + IS_ENABLED(CONFIG_FLASH_HAS_NO_EXPLICIT_ERASE) +#define FLASH_PE_RUNTIME_CHECK(cond) (cond) +#elif IS_ENABLED(CONFIG_FLASH_HAS_EXPLICIT_ERASE) +#define FLASH_PE_RUNTIME_CHECK(cond) (true) +#else +/* Assumed IS_ENABLED(CONFIG_FLASH_HAS_NO_EXPLICIT_ERASE) */ +#define FLASH_PE_RUNTIME_CHECK(cond) (false) +#endif + +/** + * Depending on value of condition erase a device or not. The condition + * is supposed to be value of erase_requirement picked up from + * flash_parameters.flags for device. + */ +static void erase_when_needed(const struct device *dev, bool condition, + uint32_t off, uint32_t size) +{ + /* + * Alwayes invoke erase when there are only erase requiring devices, + * never invoke erase when there are no devices requiring erase, + * always check condition if there are both kind of devices. + */ + if (FLASH_PE_RUNTIME_CHECK(condition)) { + if (flash_erase(dev, off, size) != 0) { + printf(" Erase failed!\n"); + } else { + printf(" Erase succeeded!\n"); + } + } else { + (void)condition; + printf(" Erase not required by device\n"); + } +} + int main(void) { const struct device *flash_dev = TEST_PARTITION_DEVICE; + struct flash_parameters flash_params; uint32_t buf_array_1[4] = { TEST_DATA_WORD_0, TEST_DATA_WORD_1, TEST_DATA_WORD_2, TEST_DATA_WORD_3 }; uint32_t buf_array_2[4] = { TEST_DATA_WORD_3, TEST_DATA_WORD_1, @@ -41,35 +78,35 @@ int main(void) uint32_t buf_word = 0U; uint32_t i, offset; - printf("\nNordic nRF5 Flash Testing\n"); - printf("=========================\n"); + memcpy(&flash_params, flash_get_parameters(flash_dev), sizeof(flash_params)); + + printf("\nNordic nRF5 Internal Storage Sample\n"); + printf("=====================================\n"); if (!device_is_ready(flash_dev)) { - printf("Flash device not ready\n"); + printf("Internal storage device not ready\n"); return 0; } - printf("\nTest 1: Flash erase page at 0x%x\n", TEST_PARTITION_OFFSET); - if (flash_erase(flash_dev, TEST_PARTITION_OFFSET, FLASH_PAGE_SIZE) != 0) { - printf(" Flash erase failed!\n"); - } else { - printf(" Flash erase succeeded!\n"); - } + printf("\nTest 1: Internal storage erase page at 0x%x\n", TEST_PARTITION_OFFSET); + erase_when_needed(flash_dev, + flash_params_get_erase_cap(&flash_params) & FLASH_ERASE_C_EXPLICIT, + TEST_PARTITION_OFFSET, FLASH_PAGE_SIZE); - printf("\nTest 2: Flash write (word array 1)\n"); + printf("\nTest 2: Internal storage write (word array 1)\n"); for (i = 0U; i < ARRAY_SIZE(buf_array_1); i++) { offset = TEST_PARTITION_OFFSET + (i << 2); printf(" Attempted to write %x at 0x%x\n", buf_array_1[i], offset); if (flash_write(flash_dev, offset, &buf_array_1[i], sizeof(uint32_t)) != 0) { - printf(" Flash write failed!\n"); + printf(" Write failed!\n"); return 0; } printf(" Attempted to read 0x%x\n", offset); if (flash_read(flash_dev, offset, &buf_word, sizeof(uint32_t)) != 0) { - printf(" Flash read failed!\n"); + printf(" Read failed!\n"); return 0; } printf(" Data read: %x\n", buf_word); @@ -81,27 +118,24 @@ int main(void) } offset = TEST_PARTITION_OFFSET; - printf("\nTest 3: Flash erase (2 pages at 0x%x)\n", offset); - if (flash_erase(flash_dev, offset, FLASH_PAGE_SIZE * 2) != 0) { - printf(" Flash erase failed!\n"); - } else { - printf(" Flash erase succeeded!\n"); - } - - printf("\nTest 4: Flash write (word array 2)\n"); + printf("\nTest 3: Internal storage erase (2 pages at 0x%x)\n", offset); + erase_when_needed(flash_dev, + flash_params_get_erase_cap(&flash_params) & FLASH_ERASE_C_EXPLICIT, + offset, FLASH_PAGE_SIZE * 2); + printf("\nTest 4: Internal storage write (word array 2)\n"); for (i = 0U; i < ARRAY_SIZE(buf_array_2); i++) { offset = TEST_PARTITION_OFFSET + (i << 2); printf(" Attempted to write %x at 0x%x\n", buf_array_2[i], offset); if (flash_write(flash_dev, offset, &buf_array_2[i], sizeof(uint32_t)) != 0) { - printf(" Flash write failed!\n"); + printf(" Write failed!\n"); return 0; } printf(" Attempted to read 0x%x\n", offset); if (flash_read(flash_dev, offset, &buf_word, sizeof(uint32_t)) != 0) { - printf(" Flash read failed!\n"); + printf(" Read failed!\n"); return 0; } printf(" Data read: %x\n", buf_word); @@ -112,12 +146,10 @@ int main(void) } } - printf("\nTest 5: Flash erase page at 0x%x\n", TEST_PARTITION_OFFSET); - if (flash_erase(flash_dev, TEST_PARTITION_OFFSET, FLASH_PAGE_SIZE) != 0) { - printf(" Flash erase failed!\n"); - } else { - printf(" Flash erase succeeded!\n"); - } + printf("\nTest 5: Internal storage erase page at 0x%x\n", TEST_PARTITION_OFFSET); + erase_when_needed(flash_dev, + flash_params_get_erase_cap(&flash_params) & FLASH_ERASE_C_EXPLICIT, + TEST_PARTITION_OFFSET, FLASH_PAGE_SIZE); printf("\nTest 6: Non-word aligned write (word array 3)\n"); for (i = 0U; i < ARRAY_SIZE(buf_array_3); i++) { @@ -126,13 +158,13 @@ int main(void) offset); if (flash_write(flash_dev, offset, &buf_array_3[i], sizeof(uint32_t)) != 0) { - printf(" Flash write failed!\n"); + printf(" Write failed!\n"); return 0; } printf(" Attempted to read 0x%x\n", offset); if (flash_read(flash_dev, offset, &buf_word, sizeof(uint32_t)) != 0) { - printf(" Flash read failed!\n"); + printf(" Read failed!\n"); return 0; } printf(" Data read: %x\n", buf_word); @@ -185,8 +217,7 @@ int main(void) #endif printf("\nTest 8: Write block size API\n"); - printf(" write-block-size = %u\n", - flash_get_write_block_size(flash_dev)); + printf(" write-block-size = %u\n", flash_params.write_block_size); printf("\nFinished!\n"); return 0; From e31b8c8edfa9ce7cd506ddcefb13feb50f198380 Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Sat, 9 Mar 2024 22:54:18 +0000 Subject: [PATCH 1645/2849] samples/fs/littlefs: Use flash_area_flatten to wipe storage The commit replaces flash_area_erase with flash_area_flatten, as it allows to emulate erase and scramble data stored on devices that do not require explicit erase before write or do not provide erase callback. Signed-off-by: Dominik Ermel --- samples/subsys/fs/littlefs/src/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/subsys/fs/littlefs/src/main.c b/samples/subsys/fs/littlefs/src/main.c index 35fe1d2b3057b..7723023013eb7 100644 --- a/samples/subsys/fs/littlefs/src/main.c +++ b/samples/subsys/fs/littlefs/src/main.c @@ -252,7 +252,7 @@ static int littlefs_flash_erase(unsigned int id) /* Optional wipe flash contents */ if (IS_ENABLED(CONFIG_APP_WIPE_STORAGE)) { - rc = flash_area_erase(pfa, 0, pfa->fa_size); + rc = flash_area_flatten(pfa, 0, pfa->fa_size); LOG_ERR("Erasing flash area ... %d", rc); } From 856d7709bbc5db04590a9a2639ad51d952c34b40 Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Sat, 9 Mar 2024 22:54:18 +0000 Subject: [PATCH 1646/2849] samples/usb/imass: Use flash_area_flatten to wipe storage The commit replaces flash_area_erase with flash_area_flatten, as it allows to emulate erase and scramble data stored on devices that do not provide erase callback. Signed-off-by: Dominik Ermel --- samples/subsys/usb/mass/src/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/subsys/usb/mass/src/main.c b/samples/subsys/usb/mass/src/main.c index 51718a9dc8595..733f6f90ea86f 100644 --- a/samples/subsys/usb/mass/src/main.c +++ b/samples/subsys/usb/mass/src/main.c @@ -89,7 +89,7 @@ static int setup_flash(struct fs_mount_t *mnt) if (rc < 0 && IS_ENABLED(CONFIG_APP_WIPE_STORAGE)) { printk("Erasing flash area ... "); - rc = flash_area_erase(pfa, 0, pfa->fa_size); + rc = flash_area_flatten(pfa, 0, pfa->fa_size); printk("%d\n", rc); } From 56142dcc73f93a87248344beaba4b5c2e540762f Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Sat, 30 Mar 2024 15:11:59 +0100 Subject: [PATCH 1647/2849] drivers: flash: Mark numaker series RMC as no_explicit_erase The device is based on ReRAM and does not require erase. Signed-off-by: Dominik Ermel --- drivers/flash/Kconfig.numaker_rmc | 1 + drivers/flash/soc_flash_numaker_rmc.c | 3 +++ 2 files changed, 4 insertions(+) diff --git a/drivers/flash/Kconfig.numaker_rmc b/drivers/flash/Kconfig.numaker_rmc index ae149115255f7..72fd64c4d494d 100644 --- a/drivers/flash/Kconfig.numaker_rmc +++ b/drivers/flash/Kconfig.numaker_rmc @@ -8,6 +8,7 @@ config SOC_FLASH_NUMAKER_RMC default y select FLASH_HAS_PAGE_LAYOUT select FLASH_HAS_DRIVER_ENABLED + select FLASH_HAS_NO_EXPLICIT_ERASE select HAS_NUMAKER_RMC depends on DT_HAS_NUVOTON_NUMAKER_RMC_ENABLED help diff --git a/drivers/flash/soc_flash_numaker_rmc.c b/drivers/flash/soc_flash_numaker_rmc.c index 7e7d81f348b8c..4a6b4ff6b5f53 100644 --- a/drivers/flash/soc_flash_numaker_rmc.c +++ b/drivers/flash/soc_flash_numaker_rmc.c @@ -29,6 +29,9 @@ struct flash_numaker_data { static const struct flash_parameters flash_numaker_parameters = { .write_block_size = SOC_NV_FLASH_WRITE_BLOCK_SIZE, .erase_value = 0xff, + .caps = { + .no_explicit_erase = true, + }, }; /* Validate offset and length */ From 7e658607fc77c51379bd969dec5eb00174e3486e Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Sat, 30 Mar 2024 16:22:56 +0100 Subject: [PATCH 1648/2849] drivers: flash: shell: Add support for devices without erase Shell will now work with devices that do not implement erase callback. Signed-off-by: Dominik Ermel --- drivers/flash/flash_shell.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/flash/flash_shell.c b/drivers/flash/flash_shell.c index 015bbbe99158e..c3825d49ba39e 100644 --- a/drivers/flash/flash_shell.c +++ b/drivers/flash/flash_shell.c @@ -75,9 +75,10 @@ static int cmd_erase(const struct shell *sh, size_t argc, char *argv[]) { const struct device *flash_dev; uint32_t page_addr; - int result; + int result = -ENOTSUP; uint32_t size; +#if defined(CONFIG_FLASH_HAS_EXPLICIT_ERASE) result = parse_helper(sh, &argc, &argv, &flash_dev, &page_addr); if (result) { return result; @@ -106,6 +107,7 @@ static int cmd_erase(const struct shell *sh, size_t argc, char *argv[]) } else { shell_print(sh, "Erase success."); } +#endif return result; } From 12fa2944c9da209040401482e993e5f54a0dcb36 Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Mon, 8 Apr 2024 15:21:35 +0200 Subject: [PATCH 1649/2849] sample/fs: Add nrf54l15pdk/nrf54l15/cpuapp to fs_sample Adds custom overlay and config allowing the sample to run on the nrf54l15pdk. Signed-off-by: Dominik Ermel --- .../boards/nrf54l15pdk_nrf54l15_cpuapp.conf | 12 +++++ .../nrf54l15pdk_nrf54l15_cpuapp.overlay | 45 +++++++++++++++++++ samples/subsys/fs/fs_sample/sample.yaml | 3 ++ 3 files changed, 60 insertions(+) create mode 100644 samples/subsys/fs/fs_sample/boards/nrf54l15pdk_nrf54l15_cpuapp.conf create mode 100644 samples/subsys/fs/fs_sample/boards/nrf54l15pdk_nrf54l15_cpuapp.overlay diff --git a/samples/subsys/fs/fs_sample/boards/nrf54l15pdk_nrf54l15_cpuapp.conf b/samples/subsys/fs/fs_sample/boards/nrf54l15pdk_nrf54l15_cpuapp.conf new file mode 100644 index 0000000000000..949237fd4bafd --- /dev/null +++ b/samples/subsys/fs/fs_sample/boards/nrf54l15pdk_nrf54l15_cpuapp.conf @@ -0,0 +1,12 @@ +# +# Copyright (c) 2024 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: Apache-2.0 +# + +CONFIG_DISK_DRIVERS=y +CONFIG_DISK_DRIVER_FLASH=y +# There may be no files on internal SoC flash, so this Kconfig +# options has ben enabled to create some if listing does not +# find in the first place. +CONFIG_FS_SAMPLE_CREATE_SOME_ENTRIES=y diff --git a/samples/subsys/fs/fs_sample/boards/nrf54l15pdk_nrf54l15_cpuapp.overlay b/samples/subsys/fs/fs_sample/boards/nrf54l15pdk_nrf54l15_cpuapp.overlay new file mode 100644 index 0000000000000..391afea75a404 --- /dev/null +++ b/samples/subsys/fs/fs_sample/boards/nrf54l15pdk_nrf54l15_cpuapp.overlay @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* Because FAT FS needs at least 64kiB partition and default + * storage_partition is 36kiB for this board, we need to reorganize + * partitions to get at least 64KiB. + */ +/delete-node/ &slot0_partition; +/delete-node/ &slot1_partition; +/delete-node/ &slot0_ns_partition; +/delete-node/ &slot1_ns_partition; +/delete-node/ &storage_partition; + +&cpuapp_rram { + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + slot0_partition: parition@10000 { + reg = <0x00010000 DT_SIZE_K(300)>; + }; + slot1_partition: partition@5b000 { + reg = <0x0005b000 DT_SIZE_K(300)>; + }; + + storage_partition: partition@a6000 { + label = "storage"; + reg = <0x000a6000 DT_SIZE_K(128)>; + }; + }; +}; + +/ { + msc_disk0 { + status="okay"; + compatible = "zephyr,flash-disk"; + partition = <&storage_partition>; + disk-name = "SD"; + cache-size = <512>; + }; +}; diff --git a/samples/subsys/fs/fs_sample/sample.yaml b/samples/subsys/fs/fs_sample/sample.yaml index 55dc3d8677a08..8041ffb84c45e 100644 --- a/samples/subsys/fs/fs_sample/sample.yaml +++ b/samples/subsys/fs/fs_sample/sample.yaml @@ -43,6 +43,9 @@ tests: extra_args: - OVERLAY_CONFIG=boards/nrf52840dk_nrf52840_ram_disk.conf - DTC_OVERLAY_FILE=boards/nrf52840dk_nrf52840_ram_disk_region.overlay + sample.filesystem.fat_fs.nrf54l15pdk: + build_only: true + platform_allow: nrf54l15pdk/nrf54l15/cpuapp sample.filesystem.fat_fs.nrf52840dk_nrf52840.qspi: build_only: true platform_allow: nrf52840dk/nrf52840 From 12bfefd0872f39f3ca7e8d0528a4e2ff4bd8168f Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Mon, 8 Apr 2024 15:29:02 +0200 Subject: [PATCH 1650/2849] tests/flash/common: Add nrf54l15pdk to list of allowed platforms Allows running tests on nrf54l15pdk/nrf54l15/cpuapp. Signed-off-by: Dominik Ermel --- tests/drivers/flash/common/testcase.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/drivers/flash/common/testcase.yaml b/tests/drivers/flash/common/testcase.yaml index 5bfd4a209447e..028383fb5f8fa 100644 --- a/tests/drivers/flash/common/testcase.yaml +++ b/tests/drivers/flash/common/testcase.yaml @@ -35,6 +35,9 @@ tests: integration_platforms: - qemu_x86 - mimxrt1060_evk + drivers.flash.common.no_explicit_erase: + platform_allow: + - nrf54l15pdk/nrf54l15/cpuapp drivers.flash.common.tfm_ns: build_only: true filter: (CONFIG_FLASH_HAS_DRIVER_ENABLED and CONFIG_TRUSTED_EXECUTION_NONSECURE From 9ea5aee810f5c8c568b0b651893bf35f1b28ae77 Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Mon, 8 Apr 2024 15:30:39 +0200 Subject: [PATCH 1651/2849] tests/fs/littlefs: Allow tests to run on the nrf54l15pdk The commit adds nrf54l15pdk/nrf54l15/cpuapp to list of allowed platforms for default test configuration. Signed-off-by: Dominik Ermel --- .../nrf54l15pdk_nrf54l15_cpuapp.overlay | 22 +++++++++++++++++++ tests/subsys/fs/littlefs/testcase.yaml | 1 + 2 files changed, 23 insertions(+) create mode 100644 tests/subsys/fs/littlefs/boards/nrf54l15pdk_nrf54l15_cpuapp.overlay diff --git a/tests/subsys/fs/littlefs/boards/nrf54l15pdk_nrf54l15_cpuapp.overlay b/tests/subsys/fs/littlefs/boards/nrf54l15pdk_nrf54l15_cpuapp.overlay new file mode 100644 index 0000000000000..292e98c96a033 --- /dev/null +++ b/tests/subsys/fs/littlefs/boards/nrf54l15pdk_nrf54l15_cpuapp.overlay @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/delete-node/ &slot0_ns_partition; +/delete-node/ &slot1_partition; +/delete-node/ &slot1_ns_partition; + +&cpuapp_rram { + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + small_partition: partition@67000 { + label = "small"; + reg = <0x00067000 0x00010000>; + }; + }; +}; diff --git a/tests/subsys/fs/littlefs/testcase.yaml b/tests/subsys/fs/littlefs/testcase.yaml index b64ffa43d9629..e934ac5b9d8cb 100644 --- a/tests/subsys/fs/littlefs/testcase.yaml +++ b/tests/subsys/fs/littlefs/testcase.yaml @@ -15,6 +15,7 @@ common: tests: filesystem.littlefs.default: timeout: 60 + platform_allow: nrf54l15pdk/nrf54l15/cpuapp filesystem.littlefs.custom: timeout: 180 extra_configs: From e3866a969071be59fd70e896cfb9970cc9c397f0 Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Mon, 8 Apr 2024 15:32:31 +0200 Subject: [PATCH 1652/2849] samples/fs/littlefs: Allow building for nrf54l15pdk The commit adds nrf54l15pdk/nrf54l15/cpuapp target platfomr. Signed-off-by: Dominik Ermel --- samples/subsys/fs/littlefs/sample.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/samples/subsys/fs/littlefs/sample.yaml b/samples/subsys/fs/littlefs/sample.yaml index 4c53a55d59104..67231c5cfbdff 100644 --- a/samples/subsys/fs/littlefs/sample.yaml +++ b/samples/subsys/fs/littlefs/sample.yaml @@ -24,6 +24,7 @@ tests: - stm32f746g_disco - stm32h747i_disco/stm32h747xx/m7 - stm32h750b_dk + - nrf54l15pdk/nrf54l15/cpuapp integration_platforms: - nrf52840dk/nrf52840 sample.filesystem.littlefs.blk: From c56134ebff9be049885bd59a0b214c55e8b5335e Mon Sep 17 00:00:00 2001 From: Henrik Brix Andersen Date: Tue, 4 Jun 2024 06:56:12 +0000 Subject: [PATCH 1653/2849] drivers: flash: flash_util: params may be unused The params variable may be unused depending on the Kconfig options enabled. Fixes: #73697 Signed-off-by: Henrik Brix Andersen --- drivers/flash/flash_util.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/flash/flash_util.c b/drivers/flash/flash_util.c index ee3b55798a56b..cbaaa2049097c 100644 --- a/drivers/flash/flash_util.c +++ b/drivers/flash/flash_util.c @@ -65,7 +65,7 @@ int z_impl_flash_flatten(const struct device *dev, off_t offset, size_t size) { const struct flash_driver_api *api = (const struct flash_driver_api *)dev->api; - const struct flash_parameters *params = api->get_parameters(dev); + __maybe_unused const struct flash_parameters *params = api->get_parameters(dev); #if IS_ENABLED(CONFIG_FLASH_HAS_EXPLICIT_ERASE) if ((flash_params_get_erase_cap(params) & FLASH_ERASE_C_EXPLICIT) && From c9c9c9797ff1967468606c4b3e69d54ff36474ad Mon Sep 17 00:00:00 2001 From: Piotr Kosycarz Date: Tue, 14 May 2024 12:47:12 +0200 Subject: [PATCH 1654/2849] samples: basic: blinky_pwm: add testing base on console output Extend automated testing on HW by veryfing console output. Signed-off-by: Piotr Kosycarz --- samples/basic/blinky_pwm/sample.yaml | 11 ++++++++++- samples/basic/blinky_pwm/src/main.c | 1 + 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/samples/basic/blinky_pwm/sample.yaml b/samples/basic/blinky_pwm/sample.yaml index de2cb234933c2..d2087f73347f3 100644 --- a/samples/basic/blinky_pwm/sample.yaml +++ b/samples/basic/blinky_pwm/sample.yaml @@ -7,4 +7,13 @@ tests: - drivers - pwm depends_on: pwm - harness: led + harness: console + harness_config: + type: multi_line + ordered: true + regex: + - "PWM-based blinky" + - "Calibrating for channel [0-9]+" + - "Done calibrating; maximum/minimum periods [0-9]+/[0-9]+ nsec" + - "Using period [0-9]+" + - "Using period [0-9]+" diff --git a/samples/basic/blinky_pwm/src/main.c b/samples/basic/blinky_pwm/src/main.c index de1f6409c6d29..6539c05d5ccae 100644 --- a/samples/basic/blinky_pwm/src/main.c +++ b/samples/basic/blinky_pwm/src/main.c @@ -63,6 +63,7 @@ int main(void) printk("Error %d: failed to set pulse width\n", ret); return 0; } + printk("Using period %d\n", period); period = dir ? (period * 2U) : (period / 2U); if (period > max_period) { From 447bdea7ffa7bc63338c149760c4fa63d42ae50a Mon Sep 17 00:00:00 2001 From: Francois Ramu Date: Thu, 16 May 2024 15:53:40 +0200 Subject: [PATCH 1655/2849] drivers: entropy: stm32 entropy driver add semaphore protection Add a semaphore to protect the disable access to the RNG peripheral when the PM is going to suspend mode. The change does not affect other stm32 than CONFIG_SOC_SERIES_STM32WBX or CONFIG_STM32H7_DUAL_CORE Signed-off-by: Francois Ramu --- drivers/entropy/entropy_stm32.c | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/drivers/entropy/entropy_stm32.c b/drivers/entropy/entropy_stm32.c index a9cbda2abc730..2b079da3b8bf9 100644 --- a/drivers/entropy/entropy_stm32.c +++ b/drivers/entropy/entropy_stm32.c @@ -112,6 +112,10 @@ static int entropy_stm32_suspend(void) RNG_TypeDef *rng = dev_data->rng; int res; +#if defined(CONFIG_SOC_SERIES_STM32WBX) || defined(CONFIG_STM32H7_DUAL_CORE) + /* Prevent concurrent access with PM */ + z_stm32_hsem_lock(CFG_HW_RNG_SEMID, HSEM_LOCK_WAIT_FOREVER); +#endif /* CONFIG_SOC_SERIES_STM32WBX || CONFIG_STM32H7_DUAL_CORE */ LL_RNG_Disable(rng); #ifdef CONFIG_SOC_SERIES_STM32WBAX @@ -136,6 +140,10 @@ static int entropy_stm32_suspend(void) res = clock_control_off(dev_data->clock, (clock_control_subsys_t)&dev_cfg->pclken[0]); +#if defined(CONFIG_SOC_SERIES_STM32WBX) || defined(CONFIG_STM32H7_DUAL_CORE) + z_stm32_hsem_unlock(CFG_HW_RNG_SEMID); +#endif /* CONFIG_SOC_SERIES_STM32WBX || CONFIG_STM32H7_DUAL_CORE */ + return res; } @@ -710,7 +718,12 @@ static int entropy_stm32_rng_pm_action(const struct device *dev, switch (action) { case PM_DEVICE_ACTION_SUSPEND: - res = entropy_stm32_suspend(); +#if defined(CONFIG_SOC_SERIES_STM32WBX) || defined(CONFIG_STM32H7_DUAL_CORE) + /* Lock to Prevent concurrent access with PM */ + z_stm32_hsem_lock(CFG_HW_RNG_SEMID, HSEM_LOCK_WAIT_FOREVER); + /* Call release_rng instead of entropy_stm32_suspend to avoid double hsem_unlock */ +#endif /* CONFIG_SOC_SERIES_STM32WBX || CONFIG_STM32H7_DUAL_CORE */ + release_rng(); break; case PM_DEVICE_ACTION_RESUME: if (IS_ENABLED(CONFIG_PM_S2RAM)) { @@ -724,7 +737,15 @@ static int entropy_stm32_rng_pm_action(const struct device *dev, entropy_stm32_rng_init(dev); } else if (!entropy_stm32_rng_data.filling_pools) { /* Resume RNG only if it was suspended during filling pool */ - entropy_stm32_suspend(); +#if defined(CONFIG_SOC_SERIES_STM32WBX) || defined(CONFIG_STM32H7_DUAL_CORE) + /* Lock to Prevent concurrent access with PM */ + z_stm32_hsem_lock(CFG_HW_RNG_SEMID, HSEM_LOCK_WAIT_FOREVER); + /* + * Call release_rng instead of entropy_stm32_suspend + * to avoid double hsem_unlock + */ +#endif /* CONFIG_SOC_SERIES_STM32WBX || CONFIG_STM32H7_DUAL_CORE */ + release_rng(); } #endif /* health_test_config */ } else { From 709b2e44bfdd159577cb2e15d17bc10b5c8dc783 Mon Sep 17 00:00:00 2001 From: Luca Burelli Date: Fri, 31 May 2024 10:54:48 +0200 Subject: [PATCH 1656/2849] llext: automatically merge sections by type This patch changes the way sections are mapped to memories. Instead of looking at the section name, each section in the ELF file is mapped to the llext_mem enum by looking at the section type and flags. This allows for a more generic mapping that works for both the ARM and Xtensa cases, and also allows for sections to be merged if they are contiguous and non-overlapping in the ELF file. This patch also fixes a number of corner cases, such as in the logging test where a section with read-only data was being ignored (not copied and not relinked). Signed-off-by: Luca Burelli --- include/zephyr/llext/elf.h | 1 + include/zephyr/llext/loader.h | 3 - subsys/llext/llext.c | 178 +++++++++++++++++++++++++--------- 3 files changed, 132 insertions(+), 50 deletions(-) diff --git a/include/zephyr/llext/elf.h b/include/zephyr/llext/elf.h index 7e8628b37d5b9..b39af854312da 100644 --- a/include/zephyr/llext/elf.h +++ b/include/zephyr/llext/elf.h @@ -196,6 +196,7 @@ struct elf64_shdr { elf64_xword sh_entsize; }; +#define SHT_NULL 0x0 #define SHT_PROGBITS 0x1 #define SHT_SYMTAB 0x2 #define SHT_STRTAB 0x3 diff --git a/include/zephyr/llext/loader.h b/include/zephyr/llext/loader.h index b8477eb30039f..7eb49d611bed3 100644 --- a/include/zephyr/llext/loader.h +++ b/include/zephyr/llext/loader.h @@ -68,9 +68,6 @@ struct llext_loader { */ void *(*peek)(struct llext_loader *ldr, size_t pos); - /** Total calculated .data size for relocatable extensions */ - size_t prog_data_size; - /** @cond ignore */ elf_ehdr_t hdr; elf_shdr_t sects[LLEXT_MEM_COUNT]; diff --git a/subsys/llext/llext.c b/subsys/llext/llext.c index a647ac3bc27b0..ca5513b741f6b 100644 --- a/subsys/llext/llext.c +++ b/subsys/llext/llext.c @@ -186,11 +186,13 @@ static int llext_find_tables(struct llext_loader *ldr) return ret; } - LOG_DBG("section %d at %zx: name %d, type %d, flags %zx, addr %zx, size %zd", + LOG_DBG("section %d at %zx: name %d, type %d, flags %zx, " + "ofs %zx, addr %zx, size %zd", i, pos, shdr.sh_name, shdr.sh_type, (size_t)shdr.sh_flags, + (size_t)shdr.sh_offset, (size_t)shdr.sh_addr, (size_t)shdr.sh_size); @@ -240,14 +242,11 @@ static const char *llext_string(struct llext_loader *ldr, struct llext *ext, */ static int llext_map_sections(struct llext_loader *ldr, struct llext *ext) { - int i, ret; + int i, j, ret; size_t pos; - elf_shdr_t shdr, rodata = {.sh_addr = ~0}, - high_shdr = {.sh_offset = 0}, low_shdr = {.sh_offset = ~0}; + elf_shdr_t shdr; const char *name; - ldr->sects[LLEXT_MEM_RODATA].sh_size = 0; - for (i = 0, pos = ldr->hdr.e_shoff; i < ldr->hdr.e_shnum; i++, pos += ldr->hdr.e_shentsize) { @@ -261,62 +260,145 @@ static int llext_map_sections(struct llext_loader *ldr, struct llext *ext) return ret; } - /* Identify the lowest and the highest data sections */ - if (!(shdr.sh_flags & SHF_EXECINSTR) && - shdr.sh_type == SHT_PROGBITS) { - if (shdr.sh_offset > high_shdr.sh_offset) { - high_shdr = shdr; - } - if (shdr.sh_offset < low_shdr.sh_offset) { - low_shdr = shdr; - } + if ((shdr.sh_type != SHT_PROGBITS && shdr.sh_type != SHT_NOBITS) || + !(shdr.sh_flags & SHF_ALLOC) || + shdr.sh_size == 0) { + continue; } name = llext_string(ldr, ext, LLEXT_MEM_SHSTRTAB, shdr.sh_name); - LOG_DBG("section %d name %s", i, name); - + /* Identify the section type by its flags */ enum llext_mem mem_idx; - /* - * .rodata section is optional. If there isn't one, use the - * first read-only data section - */ - if (shdr.sh_addr && !(shdr.sh_flags & (SHF_WRITE | SHF_EXECINSTR)) && - shdr.sh_addr < rodata.sh_addr) { - rodata = shdr; - LOG_DBG("rodata: select %#zx name %s", (size_t)shdr.sh_addr, name); - } - - /* - * Keep in mind, that when using relocatable (partially linked) - * objects, ELF segments aren't created, so ldr->sect_map[] and - * ldr->sects[] don't contain all the sections - */ - if (strcmp(name, ".text") == 0) { - mem_idx = LLEXT_MEM_TEXT; - } else if (strcmp(name, ".data") == 0) { - mem_idx = LLEXT_MEM_DATA; - } else if (strcmp(name, ".rodata") == 0) { - mem_idx = LLEXT_MEM_RODATA; - } else if (strcmp(name, ".bss") == 0) { + switch (shdr.sh_type) { + case SHT_NOBITS: mem_idx = LLEXT_MEM_BSS; - } else if (strcmp(name, ".exported_sym") == 0) { - mem_idx = LLEXT_MEM_EXPORT; - } else { + break; + case SHT_PROGBITS: + if (shdr.sh_flags & SHF_EXECINSTR) { + mem_idx = LLEXT_MEM_TEXT; + } else if (shdr.sh_flags & SHF_WRITE) { + mem_idx = LLEXT_MEM_DATA; + } else { + mem_idx = LLEXT_MEM_RODATA; + } + break; + default: LOG_DBG("Not copied section %s", name); continue; } - ldr->sects[mem_idx] = shdr; + /* Special exception for .exported_sym */ + if (strcmp(name, ".exported_sym") == 0) { + mem_idx = LLEXT_MEM_EXPORT; + } + + LOG_DBG("section %d name %s maps to idx %d", i, name, mem_idx); + ldr->sect_map[i] = mem_idx; + elf_shdr_t *sect = ldr->sects + mem_idx; + + if (sect->sh_type == SHT_NULL) { + /* First section of this type, copy all info */ + *sect = shdr; + } else { + /* Make sure the sections are compatible before merging */ + if (shdr.sh_flags != sect->sh_flags) { + LOG_ERR("Unsupported section flags for %s (mem %d)", + name, mem_idx); + return -ENOEXEC; + } + + if (mem_idx == LLEXT_MEM_BSS) { + /* SHT_NOBITS sections cannot be merged properly: + * as they use no space in the file, the logic + * below does not work; they must be treated as + * independent entities. + */ + LOG_ERR("Multiple SHT_NOBITS sections are not supported"); + return -ENOEXEC; + } + + if (ldr->hdr.e_type == ET_DYN) { + /* In shared objects, sh_addr is the VMA. Before + * merging these sections, make sure the delta + * in VMAs matches that of file offsets. + */ + if (shdr.sh_addr - sect->sh_addr != + shdr.sh_offset - sect->sh_offset) { + LOG_ERR("Incompatible section addresses " + "for %s (mem %d)", name, mem_idx); + return -ENOEXEC; + } + } + + /* + * Extend the current section to include the new one + * (overlaps are detected later) + */ + size_t address = MIN(sect->sh_addr, shdr.sh_addr); + size_t bot_ofs = MIN(sect->sh_offset, shdr.sh_offset); + size_t top_ofs = MAX(sect->sh_offset + sect->sh_size, + shdr.sh_offset + shdr.sh_size); + + sect->sh_addr = address; + sect->sh_offset = bot_ofs; + sect->sh_size = top_ofs - bot_ofs; + } } - ldr->prog_data_size = high_shdr.sh_size + high_shdr.sh_offset - low_shdr.sh_offset; + /* + * Test that no computed range overlaps. This can happen if sections of + * different llext_mem type are interleaved in the ELF file or in VMAs. + */ + for (i = 0; i < LLEXT_MEM_COUNT; i++) { + for (j = i+1; j < LLEXT_MEM_COUNT; j++) { + elf_shdr_t *x = ldr->sects + i; + elf_shdr_t *y = ldr->sects + j; + + if (x->sh_type == SHT_NULL || x->sh_size == 0 || + y->sh_type == SHT_NULL || y->sh_size == 0) { + /* Skip empty sections */ + continue; + } + + if (ldr->hdr.e_type == ET_DYN) { + /* + * Test all merged VMA ranges for overlaps + */ + if ((x->sh_addr <= y->sh_addr && + x->sh_addr + x->sh_size > y->sh_addr) || + (y->sh_addr <= x->sh_addr && + y->sh_addr + y->sh_size > x->sh_addr)) { + LOG_ERR("VMA range %d (0x%zx +%zd) " + "overlaps with %d (0x%zx +%zd)", + i, (size_t)x->sh_addr, (size_t)x->sh_size, + j, (size_t)y->sh_addr, (size_t)y->sh_size); + return -ENOEXEC; + } + } + + /* + * Test file offsets. BSS sections store no + * data in the file and must not be included + * in checks to avoid false positives. + */ + if (i == LLEXT_MEM_BSS || j == LLEXT_MEM_BSS) { + continue; + } - /* No verbatim .rodata, use an automatically selected one */ - if (!ldr->sects[LLEXT_MEM_RODATA].sh_size) { - ldr->sects[LLEXT_MEM_RODATA] = rodata; + if ((x->sh_offset <= y->sh_offset && + x->sh_offset + x->sh_size > y->sh_offset) || + (y->sh_offset <= x->sh_offset && + y->sh_offset + y->sh_size > x->sh_offset)) { + LOG_ERR("ELF file range %d (0x%zx +%zd) " + "overlaps with %d (0x%zx +%zd)", + i, (size_t)x->sh_offset, (size_t)x->sh_size, + j, (size_t)y->sh_offset, (size_t)y->sh_size); + return -ENOEXEC; + } + } } return 0; @@ -352,6 +434,8 @@ static void llext_init_mem_part(struct llext *ext, enum llext_mem mem_idx, ext->mem_parts[mem_idx].size); } #endif + + LOG_DBG("mem idx %d: start 0x%zx, size %zd", mem_idx, (size_t)start, len); } static int llext_copy_section(struct llext_loader *ldr, struct llext *ext, From 06bb9f258a0a5921b9c16ad8291c9be9a80a6881 Mon Sep 17 00:00:00 2001 From: Jens Rehhoff Thomsen Date: Fri, 31 May 2024 11:09:27 +0200 Subject: [PATCH 1657/2849] Bluetooth: BAP: Shell: Add endpoint state info The bap list command now also shows the states of each endpoint. Fixes #70838 Signed-off-by: Jens Rehhoff Thomsen --- subsys/bluetooth/audio/shell/bap.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/subsys/bluetooth/audio/shell/bap.c b/subsys/bluetooth/audio/shell/bap.c index b560ba3c714df..e63b2d559d15d 100644 --- a/subsys/bluetooth/audio/shell/bap.c +++ b/subsys/bluetooth/audio/shell/bap.c @@ -1649,7 +1649,13 @@ static void conn_list_eps(struct bt_conn *conn, void *data) const struct bt_bap_ep *ep = snks[conn_index][i]; if (ep != NULL) { - shell_print(sh, " #%u: ep %p", i, ep); + struct bt_bap_ep_info ep_info; + int err; + + err = bt_bap_ep_get_info(ep, &ep_info); + if (err == 0) { + shell_print(sh, " #%u: ep %p (state: %d)", i, ep, ep_info.state); + } } } #endif /* CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT > 0 */ @@ -1661,7 +1667,13 @@ static void conn_list_eps(struct bt_conn *conn, void *data) const struct bt_bap_ep *ep = srcs[conn_index][i]; if (ep != NULL) { - shell_print(sh, " #%u: ep %p", i, ep); + struct bt_bap_ep_info ep_info; + int err; + + err = bt_bap_ep_get_info(ep, &ep_info); + if (err == 0) { + shell_print(sh, " #%u: ep %p (state: %d)", i, ep, ep_info.state); + } } } #endif /* CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SRC_COUNT > 0 */ From ebadb11645bd3e65df08b0ed5d3ce83250dea440 Mon Sep 17 00:00:00 2001 From: Emil Gydesen Date: Mon, 20 May 2024 19:40:04 +0200 Subject: [PATCH 1658/2849] Bluetooth: Audio: Spring cleaning Adds, removes and modifies includes in all LE audio files. Fixes any found spelling mistakes as well. Fixes a few places where incorrect types were used. Signed-off-by: Emil Gydesen --- include/zephyr/bluetooth/audio/aics.h | 3 + include/zephyr/bluetooth/audio/audio.h | 19 ++++-- include/zephyr/bluetooth/audio/bap.h | 12 +++- .../zephyr/bluetooth/audio/bap_lc3_preset.h | 1 + include/zephyr/bluetooth/audio/cap.h | 10 ++- include/zephyr/bluetooth/audio/csip.h | 9 +++ .../zephyr/bluetooth/audio/gmap_lc3_preset.h | 2 + include/zephyr/bluetooth/audio/has.h | 6 +- include/zephyr/bluetooth/audio/mcc.h | 3 +- include/zephyr/bluetooth/audio/mcs.h | 1 + include/zephyr/bluetooth/audio/media_proxy.h | 1 + include/zephyr/bluetooth/audio/micp.h | 2 + include/zephyr/bluetooth/audio/pacs.h | 4 ++ include/zephyr/bluetooth/audio/pbp.h | 6 +- include/zephyr/bluetooth/audio/tbs.h | 1 + include/zephyr/bluetooth/audio/tmap.h | 2 + include/zephyr/bluetooth/audio/vcp.h | 2 + subsys/bluetooth/audio/aics.c | 26 ++++++-- subsys/bluetooth/audio/aics_client.c | 27 +++++--- subsys/bluetooth/audio/aics_internal.h | 9 ++- subsys/bluetooth/audio/ascs.c | 37 +++++++---- subsys/bluetooth/audio/ascs_internal.h | 9 +++ subsys/bluetooth/audio/audio.c | 14 +++- subsys/bluetooth/audio/audio_internal.h | 7 +- subsys/bluetooth/audio/bap_base.c | 15 ++++- .../bluetooth/audio/bap_broadcast_assistant.c | 30 +++++++-- subsys/bluetooth/audio/bap_broadcast_sink.c | 32 +++++++--- subsys/bluetooth/audio/bap_broadcast_source.c | 23 +++++-- subsys/bluetooth/audio/bap_endpoint.h | 9 +++ subsys/bluetooth/audio/bap_internal.h | 9 ++- subsys/bluetooth/audio/bap_iso.c | 17 ++++- subsys/bluetooth/audio/bap_iso.h | 7 +- subsys/bluetooth/audio/bap_scan_delegator.c | 31 ++++++--- subsys/bluetooth/audio/bap_stream.c | 23 +++++-- subsys/bluetooth/audio/bap_stream.h | 8 +++ subsys/bluetooth/audio/bap_unicast_client.c | 47 ++++++++------ .../audio/bap_unicast_client_internal.h | 8 +++ subsys/bluetooth/audio/bap_unicast_server.c | 17 +++-- subsys/bluetooth/audio/bap_unicast_server.h | 3 + subsys/bluetooth/audio/cap_acceptor.c | 15 ++++- subsys/bluetooth/audio/cap_commander.c | 26 ++++++-- subsys/bluetooth/audio/cap_initiator.c | 4 +- subsys/bluetooth/audio/cap_internal.h | 12 ++-- subsys/bluetooth/audio/cap_stream.c | 5 +- subsys/bluetooth/audio/ccid.c | 5 ++ subsys/bluetooth/audio/ccid_internal.h | 4 +- subsys/bluetooth/audio/codec.c | 12 +++- subsys/bluetooth/audio/csip_crypto.c | 11 +++- subsys/bluetooth/audio/csip_crypto.h | 4 +- subsys/bluetooth/audio/csip_internal.h | 5 +- subsys/bluetooth/audio/csip_set_coordinator.c | 36 +++++++---- subsys/bluetooth/audio/csip_set_member.c | 40 ++++++++---- subsys/bluetooth/audio/gmap_client.c | 14 +++- subsys/bluetooth/audio/gmap_server.c | 18 ++++-- subsys/bluetooth/audio/has.c | 38 ++++++++--- subsys/bluetooth/audio/has_client.c | 21 ++++-- subsys/bluetooth/audio/has_internal.h | 6 ++ subsys/bluetooth/audio/mcc.c | 41 +++++++----- subsys/bluetooth/audio/mcc_internal.h | 9 ++- subsys/bluetooth/audio/mcs.c | 34 ++++++---- subsys/bluetooth/audio/mcs_internal.h | 5 +- subsys/bluetooth/audio/media_proxy.c | 13 ++-- subsys/bluetooth/audio/media_proxy_internal.h | 4 ++ subsys/bluetooth/audio/micp_internal.h | 6 +- subsys/bluetooth/audio/micp_mic_ctlr.c | 32 ++++++---- subsys/bluetooth/audio/micp_mic_dev.c | 27 +++++--- subsys/bluetooth/audio/mpl.c | 32 ++++++---- subsys/bluetooth/audio/mpl_internal.h | 7 ++ subsys/bluetooth/audio/pacs.c | 43 ++++++++----- subsys/bluetooth/audio/pacs_internal.h | 4 +- subsys/bluetooth/audio/pbp.c | 13 +++- subsys/bluetooth/audio/shell/audio.h | 18 +++++- subsys/bluetooth/audio/shell/bap.c | 44 +++++++++---- .../audio/shell/bap_broadcast_assistant.c | 28 +++++--- .../audio/shell/bap_scan_delegator.c | 30 ++++++--- subsys/bluetooth/audio/shell/bap_usb.c | 15 ++++- subsys/bluetooth/audio/shell/cap_acceptor.c | 18 +++++- subsys/bluetooth/audio/shell/cap_commander.c | 8 ++- subsys/bluetooth/audio/shell/cap_initiator.c | 21 +++++- .../audio/shell/csip_set_coordinator.c | 27 +++++--- .../bluetooth/audio/shell/csip_set_member.c | 24 +++++-- subsys/bluetooth/audio/shell/gmap.c | 15 ++++- subsys/bluetooth/audio/shell/has.c | 15 +++-- subsys/bluetooth/audio/shell/has_client.c | 11 +++- subsys/bluetooth/audio/shell/mcc.c | 21 ++++-- .../bluetooth/audio/shell/media_controller.c | 26 +++++--- subsys/bluetooth/audio/shell/micp_mic_ctlr.c | 15 +++-- subsys/bluetooth/audio/shell/micp_mic_dev.c | 17 +++-- subsys/bluetooth/audio/shell/mpl.c | 14 ++-- subsys/bluetooth/audio/shell/pbp.c | 12 +++- subsys/bluetooth/audio/shell/tbs.c | 15 ++++- subsys/bluetooth/audio/shell/tbs_client.c | 18 ++++-- subsys/bluetooth/audio/shell/tmap.c | 5 ++ subsys/bluetooth/audio/shell/vcp_vol_ctlr.c | 15 ++++- subsys/bluetooth/audio/shell/vcp_vol_rend.c | 19 ++++-- subsys/bluetooth/audio/tbs.c | 27 +++++--- subsys/bluetooth/audio/tbs_client.c | 35 ++++++---- subsys/bluetooth/audio/tbs_internal.h | 10 ++- subsys/bluetooth/audio/tmap.c | 28 ++++---- subsys/bluetooth/audio/vcp_internal.h | 8 +++ subsys/bluetooth/audio/vcp_vol_ctlr.c | 40 +++++++----- subsys/bluetooth/audio/vcp_vol_rend.c | 34 +++++++--- subsys/bluetooth/audio/vocs.c | 32 +++++++--- subsys/bluetooth/audio/vocs_client.c | 31 +++++---- subsys/bluetooth/audio/vocs_internal.h | 10 ++- .../audio/src/bap_bass_broadcaster_test.c | 11 ++++ .../audio/src/bap_broadcast_assistant_test.c | 20 +++++- .../audio/src/bap_broadcast_sink_test.c | 26 +++++++- .../audio/src/bap_broadcast_source_test.c | 22 ++++++- tests/bsim/bluetooth/audio/src/bap_common.c | 9 +++ tests/bsim/bluetooth/audio/src/bap_common.h | 5 +- .../audio/src/bap_scan_delegator_test.c | 22 ++++++- .../audio/src/bap_unicast_client_test.c | 29 +++++++-- .../audio/src/bap_unicast_server_test.c | 27 ++++++-- .../bluetooth/audio/src/cap_acceptor_test.c | 32 ++++++++-- .../bluetooth/audio/src/cap_commander_test.c | 23 +++++-- .../audio/src/cap_initiator_broadcast_test.c | 26 ++++++-- .../audio/src/cap_initiator_unicast_test.c | 33 ++++++++-- tests/bsim/bluetooth/audio/src/common.c | 23 ++++++- tests/bsim/bluetooth/audio/src/common.h | 22 ++++--- .../audio/src/csip_notify_client_test.c | 9 ++- .../audio/src/csip_notify_server_test.c | 14 +++- .../audio/src/csip_set_coordinator_test.c | 21 +++++- .../audio/src/csip_set_member_test.c | 14 +++- .../bsim/bluetooth/audio/src/gmap_ugg_test.c | 29 +++++++-- .../bsim/bluetooth/audio/src/gmap_ugt_test.c | 25 ++++++-- .../bluetooth/audio/src/has_client_test.c | 16 ++++- tests/bsim/bluetooth/audio/src/has_test.c | 12 +++- .../bluetooth/audio/src/ias_client_test.c | 10 ++- tests/bsim/bluetooth/audio/src/ias_test.c | 10 +-- tests/bsim/bluetooth/audio/src/main.c | 2 + tests/bsim/bluetooth/audio/src/mcc_test.c | 20 ++++-- tests/bsim/bluetooth/audio/src/mcs_test.c | 8 ++- .../audio/src/media_controller_test.c | 16 +++-- .../bluetooth/audio/src/micp_mic_ctlr_test.c | 11 +++- .../bluetooth/audio/src/micp_mic_dev_test.c | 14 +++- .../audio/src/pacs_notify_client_test.c | 11 ++++ .../audio/src/pacs_notify_server_test.c | 17 ++++- .../src/pbp_public_broadcast_sink_test.c | 23 +++++-- .../src/pbp_public_broadcast_source_test.c | 25 ++++++-- .../bluetooth/audio/src/tbs_client_test.c | 30 +++++---- tests/bsim/bluetooth/audio/src/tbs_test.c | 64 +++++++++++-------- .../bluetooth/audio/src/tmap_client_test.c | 17 +++-- .../bluetooth/audio/src/tmap_server_test.c | 17 ++--- .../bluetooth/audio/src/vcp_vol_ctlr_test.c | 14 ++-- .../bluetooth/audio/src/vcp_vol_rend_test.c | 13 +++- 146 files changed, 1924 insertions(+), 612 deletions(-) diff --git a/include/zephyr/bluetooth/audio/aics.h b/include/zephyr/bluetooth/audio/aics.h index 55f2eab2f931a..a554c1503959a 100644 --- a/include/zephyr/bluetooth/audio/aics.h +++ b/include/zephyr/bluetooth/audio/aics.h @@ -27,7 +27,10 @@ * autonomously read the change counter value when executing a write request. * */ +#include +#include +#include #include #ifdef __cplusplus diff --git a/include/zephyr/bluetooth/audio/audio.h b/include/zephyr/bluetooth/audio/audio.h index 0578f632bd2f4..5bc503f5a3d73 100644 --- a/include/zephyr/bluetooth/audio/audio.h +++ b/include/zephyr/bluetooth/audio/audio.h @@ -18,14 +18,21 @@ * @{ */ -#include +#include +#include +#include + +#include +#include +#include #include #include +#include #include #include -#include -#include - +#include +#include +#include #ifdef __cplusplus extern "C" { @@ -1011,7 +1018,7 @@ int bt_audio_codec_cfg_set_chan_allocation(struct bt_audio_codec_cfg *codec_cfg, * * The overall SDU size will be octets_per_frame * blocks_per_sdu. * - * The Bluetooth specificationa are not clear about this value - it does not state that + * The Bluetooth specifications are not clear about this value - it does not state that * the codec shall use this SDU size only. A codec like LC3 supports variable bit-rate * (per SDU) hence it might be allowed for an encoder to reduce the frame size below this * value. @@ -1040,7 +1047,7 @@ int bt_audio_codec_cfg_get_octets_per_frame(const struct bt_audio_codec_cfg *cod int bt_audio_codec_cfg_set_octets_per_frame(struct bt_audio_codec_cfg *codec_cfg, uint16_t octets_per_frame); -/** @brief Extract number of audio frame blockss in each SDU from BT codec config +/** @brief Extract number of audio frame blocks in each SDU from BT codec config * * The overall SDU size will be octets_per_frame * frame_blocks_per_sdu * number-of-channels. * diff --git a/include/zephyr/bluetooth/audio/bap.h b/include/zephyr/bluetooth/audio/bap.h index 32d9840c5be5b..00957b2b81be5 100644 --- a/include/zephyr/bluetooth/audio/bap.h +++ b/include/zephyr/bluetooth/audio/bap.h @@ -17,9 +17,17 @@ * @{ */ -#include -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #ifdef __cplusplus extern "C" { diff --git a/include/zephyr/bluetooth/audio/bap_lc3_preset.h b/include/zephyr/bluetooth/audio/bap_lc3_preset.h index d31c47fd4fb79..7ba6af250a216 100644 --- a/include/zephyr/bluetooth/audio/bap_lc3_preset.h +++ b/include/zephyr/bluetooth/audio/bap_lc3_preset.h @@ -10,6 +10,7 @@ #define ZEPHYR_INCLUDE_BLUETOOTH_AUDIO_BAP_LC3_PRESET_ #include +#include /** Struct to hold a BAP defined LC3 preset */ struct bt_bap_lc3_preset { diff --git a/include/zephyr/bluetooth/audio/cap.h b/include/zephyr/bluetooth/audio/cap.h index c5c4bbea6e8ae..afc1ca9018ef0 100644 --- a/include/zephyr/bluetooth/audio/cap.h +++ b/include/zephyr/bluetooth/audio/cap.h @@ -19,12 +19,18 @@ * @{ */ +#include +#include #include -#include -#include #include #include +#include +#include +#include +#include +#include +#include #ifdef __cplusplus extern "C" { diff --git a/include/zephyr/bluetooth/audio/csip.h b/include/zephyr/bluetooth/audio/csip.h index 6f3a028024236..7b8d8d2631fe4 100644 --- a/include/zephyr/bluetooth/audio/csip.h +++ b/include/zephyr/bluetooth/audio/csip.h @@ -19,7 +19,16 @@ * @{ */ +#include +#include +#include + +#include +#include #include +#include +#include +#include #ifdef __cplusplus extern "C" { diff --git a/include/zephyr/bluetooth/audio/gmap_lc3_preset.h b/include/zephyr/bluetooth/audio/gmap_lc3_preset.h index e5a22936c741e..5e50de243e7fd 100644 --- a/include/zephyr/bluetooth/audio/gmap_lc3_preset.h +++ b/include/zephyr/bluetooth/audio/gmap_lc3_preset.h @@ -9,7 +9,9 @@ #ifndef ZEPHYR_INCLUDE_BLUETOOTH_AUDIO_GMAP_LC3_PRESET_ #define ZEPHYR_INCLUDE_BLUETOOTH_AUDIO_GMAP_LC3_PRESET_ +#include #include +#include /* GMAP LC3 unicast presets defined by table 3.16 in the GMAP v1.0 specification */ diff --git a/include/zephyr/bluetooth/audio/has.h b/include/zephyr/bluetooth/audio/has.h index 0e5c165290215..7bd20aec89e3a 100644 --- a/include/zephyr/bluetooth/audio/has.h +++ b/include/zephyr/bluetooth/audio/has.h @@ -22,10 +22,12 @@ * to control hearing aid presets. */ -#include +#include +#include #include #include +#include #ifdef __cplusplus extern "C" { @@ -63,7 +65,7 @@ enum bt_has_properties { BT_HAS_PROP_AVAILABLE = BIT(1), }; -/** Hearing Aid device capablilities */ +/** Hearing Aid device capabilities */ enum bt_has_capabilities { BT_HAS_PRESET_SUPPORT = BIT(0), }; diff --git a/include/zephyr/bluetooth/audio/mcc.h b/include/zephyr/bluetooth/audio/mcc.h index 14dba82922530..fb71f011db96e 100644 --- a/include/zephyr/bluetooth/audio/mcc.h +++ b/include/zephyr/bluetooth/audio/mcc.h @@ -22,6 +22,7 @@ #define ZEPHYR_INCLUDE_BLUETOOTH_AUDIO_MCC_ #include +#include #include #include @@ -407,7 +408,7 @@ typedef void (*bt_mcc_read_content_control_id_cb)(struct bt_conn *conn, typedef void (*bt_mcc_otc_obj_selected_cb)(struct bt_conn *conn, int err); /** - * @brief Callback function for bt_mcc_otc_read_object_meatadata() + * @brief Callback function for bt_mcc_otc_read_object_metadata() * * Called when object metadata is read * diff --git a/include/zephyr/bluetooth/audio/mcs.h b/include/zephyr/bluetooth/audio/mcs.h index 7d9491944ef27..5212905497c27 100644 --- a/include/zephyr/bluetooth/audio/mcs.h +++ b/include/zephyr/bluetooth/audio/mcs.h @@ -23,6 +23,7 @@ */ #include +#include #ifdef __cplusplus extern "C" { diff --git a/include/zephyr/bluetooth/audio/media_proxy.h b/include/zephyr/bluetooth/audio/media_proxy.h index 0e236a1fd4a07..16bb978bfcc48 100644 --- a/include/zephyr/bluetooth/audio/media_proxy.h +++ b/include/zephyr/bluetooth/audio/media_proxy.h @@ -40,6 +40,7 @@ #include #include +#include /* TODO: Remove dependency on mcs.h */ #include "mcs.h" diff --git a/include/zephyr/bluetooth/audio/micp.h b/include/zephyr/bluetooth/audio/micp.h index 500eb2048395f..0fe9a7af681f5 100644 --- a/include/zephyr/bluetooth/audio/micp.h +++ b/include/zephyr/bluetooth/audio/micp.h @@ -22,6 +22,8 @@ #include #include +#include +#include #ifdef __cplusplus extern "C" { diff --git a/include/zephyr/bluetooth/audio/pacs.h b/include/zephyr/bluetooth/audio/pacs.h index 6db4d34b0a285..74f401d7bd54f 100644 --- a/include/zephyr/bluetooth/audio/pacs.h +++ b/include/zephyr/bluetooth/audio/pacs.h @@ -10,7 +10,11 @@ #ifndef ZEPHYR_INCLUDE_BLUETOOTH_AUDIO_PACS_H_ #define ZEPHYR_INCLUDE_BLUETOOTH_AUDIO_PACS_H_ +#include + #include +#include +#include #ifdef __cplusplus extern "C" { diff --git a/include/zephyr/bluetooth/audio/pbp.h b/include/zephyr/bluetooth/audio/pbp.h index 71d7d107b4e9c..d218720895d34 100644 --- a/include/zephyr/bluetooth/audio/pbp.h +++ b/include/zephyr/bluetooth/audio/pbp.h @@ -19,8 +19,12 @@ * @{ */ -#include #include +#include +#include +#include +#include +#include #ifdef __cplusplus extern "C" { diff --git a/include/zephyr/bluetooth/audio/tbs.h b/include/zephyr/bluetooth/audio/tbs.h index 523efc4264fc1..49039a7ff6145 100644 --- a/include/zephyr/bluetooth/audio/tbs.h +++ b/include/zephyr/bluetooth/audio/tbs.h @@ -14,6 +14,7 @@ #include #include +#include /* Call States */ #define BT_TBS_CALL_STATE_INCOMING 0x00 diff --git a/include/zephyr/bluetooth/audio/tmap.h b/include/zephyr/bluetooth/audio/tmap.h index 4bcdbb0a5bfc8..1c8e8ccb8921d 100644 --- a/include/zephyr/bluetooth/audio/tmap.h +++ b/include/zephyr/bluetooth/audio/tmap.h @@ -9,8 +9,10 @@ #ifndef ZEPHYR_INCLUDE_BLUETOOTH_AUDIO_TMAP_ #define ZEPHYR_INCLUDE_BLUETOOTH_AUDIO_TMAP_ +#include #include #include +#include /** Call Gateway (CG) supported */ #define BT_TMAP_CG_SUPPORTED \ diff --git a/include/zephyr/bluetooth/audio/vcp.h b/include/zephyr/bluetooth/audio/vcp.h index 1128bf18d1e4b..755ee12d065ab 100644 --- a/include/zephyr/bluetooth/audio/vcp.h +++ b/include/zephyr/bluetooth/audio/vcp.h @@ -23,6 +23,8 @@ #include #include +#include +#include #ifdef __cplusplus extern "C" { diff --git a/subsys/bluetooth/audio/aics.c b/subsys/bluetooth/audio/aics.c index 1e42cc73da52d..222969aba241b 100644 --- a/subsys/bluetooth/audio/aics.c +++ b/subsys/bluetooth/audio/aics.c @@ -5,17 +5,29 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include -#include -#include - -#include -#include - +#include +#include +#include +#include +#include +#include + +#include +#include #include #include #include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include "aics_internal.h" #include "audio_internal.h" diff --git a/subsys/bluetooth/audio/aics_client.c b/subsys/bluetooth/audio/aics_client.c index 943f6475a38d7..332f5a7fabff5 100644 --- a/subsys/bluetooth/audio/aics_client.c +++ b/subsys/bluetooth/audio/aics_client.c @@ -7,24 +7,31 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include -#include - -#include - -#include -#include +#include +#include +#include +#include +#include +#include +#include +#include #include #include #include #include -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include "aics_internal.h" -#include - LOG_MODULE_REGISTER(bt_aics_client, CONFIG_BT_AICS_CLIENT_LOG_LEVEL); static struct bt_aics aics_insts[CONFIG_BT_MAX_CONN * CONFIG_BT_AICS_CLIENT_MAX_INSTANCE_COUNT]; diff --git a/subsys/bluetooth/audio/aics_internal.h b/subsys/bluetooth/audio/aics_internal.h index 3c10287a0f311..4283abce2fb58 100644 --- a/subsys/bluetooth/audio/aics_internal.h +++ b/subsys/bluetooth/audio/aics_internal.h @@ -11,8 +11,15 @@ #ifndef ZEPHYR_INCLUDE_BLUETOOTH_AUDIO_AICS_INTERNAL_ #define ZEPHYR_INCLUDE_BLUETOOTH_AUDIO_AICS_INTERNAL_ -#include +#include +#include + +#include +#include #include +#include +#include +#include #if defined(CONFIG_BT_AICS) #define BT_AICS_MAX_DESC_SIZE CONFIG_BT_AICS_MAX_INPUT_DESCRIPTION_SIZE diff --git a/subsys/bluetooth/audio/ascs.c b/subsys/bluetooth/audio/ascs.c index 31e7bcca13350..2528cc00b13f0 100644 --- a/subsys/bluetooth/audio/ascs.c +++ b/subsys/bluetooth/audio/ascs.c @@ -7,20 +7,33 @@ * * SPDX-License-Identifier: Apache-2.0 */ - -#include -#include -#include - +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include #include #include #include +#include #include -#include -#include -#include - +#include +#include #include +#include +#include +#include +#include +#include +#include +#include LOG_MODULE_REGISTER(bt_ascs, CONFIG_BT_ASCS_LOG_LEVEL); @@ -29,9 +42,11 @@ LOG_MODULE_REGISTER(bt_ascs, CONFIG_BT_ASCS_LOG_LEVEL); #include "../host/att_internal.h" +#include "ascs_internal.h" #include "audio_internal.h" -#include "bap_iso.h" #include "bap_endpoint.h" +#include "bap_iso.h" +#include "bap_stream.h" #include "bap_unicast_server.h" #include "pacs_internal.h" #include "cap_internal.h" @@ -1680,7 +1695,7 @@ int bt_ascs_config_ase(struct bt_conn *conn, struct bt_bap_stream *stream, return -EALREADY; } - /* Get a free ASE or NULL if all ASE instances are aready in use */ + /* Get a free ASE or NULL if all ASE instances are already in use */ for (int i = 1; i <= ASE_COUNT; i++) { if (ase_find(conn, i) == NULL) { ase = ase_new(conn, i); diff --git a/subsys/bluetooth/audio/ascs_internal.h b/subsys/bluetooth/audio/ascs_internal.h index fc76964a01837..f96a1905ec525 100644 --- a/subsys/bluetooth/audio/ascs_internal.h +++ b/subsys/bluetooth/audio/ascs_internal.h @@ -7,6 +7,13 @@ * SPDX-License-Identifier: Apache-2.0 */ +#ifndef BT_ASCS_INTERNAL_H +#define BT_ASCS_INTERNAL_H + +#include +#include +#include + #define BT_ASCS_ASE_ID_NONE 0x00 /* The number of ASEs in the notification when the opcode is unsupported or the length of the @@ -349,3 +356,5 @@ int bt_ascs_disable_ase(struct bt_bap_ep *ep); int bt_ascs_release_ase(struct bt_bap_ep *ep); void bt_ascs_foreach_ep(struct bt_conn *conn, bt_bap_ep_func_t func, void *user_data); + +#endif /* BT_ASCS_INTERNAL_H */ diff --git a/subsys/bluetooth/audio/audio.c b/subsys/bluetooth/audio/audio.c index 619f52c7abc2e..f38ec14c00130 100644 --- a/subsys/bluetooth/audio/audio.c +++ b/subsys/bluetooth/audio/audio.c @@ -6,11 +6,21 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include +#include +#include +#include +#include + +#include +#include +#include #include +#include #include +#include #include -#include -#include +#include #include #include diff --git a/subsys/bluetooth/audio/audio_internal.h b/subsys/bluetooth/audio/audio_internal.h index f13e130089a11..b6fde6118f464 100644 --- a/subsys/bluetooth/audio/audio_internal.h +++ b/subsys/bluetooth/audio/audio_internal.h @@ -5,9 +5,14 @@ * * SPDX-License-Identifier: Apache-2.0 */ +#include +#include +#include -#include +#include #include +#include +#include #define BT_AUDIO_NOTIFY_RETRY_DELAY_US ((CONFIG_BT_AUDIO_NOTIFY_RETRY_DELAY) * 1250U) diff --git a/subsys/bluetooth/audio/bap_base.c b/subsys/bluetooth/audio/bap_base.c index 9d8c2de3933aa..a649f7446592f 100644 --- a/subsys/bluetooth/audio/bap_base.c +++ b/subsys/bluetooth/audio/bap_base.c @@ -6,11 +6,24 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include #include #include -#include #include +#include #include +#include +#include LOG_MODULE_REGISTER(bt_bap_base, CONFIG_BT_BAP_BASE_LOG_LEVEL); diff --git a/subsys/bluetooth/audio/bap_broadcast_assistant.c b/subsys/bluetooth/audio/bap_broadcast_assistant.c index 90402d2db96ec..54b5bdd60d68f 100644 --- a/subsys/bluetooth/audio/bap_broadcast_assistant.c +++ b/subsys/bluetooth/audio/bap_broadcast_assistant.c @@ -8,20 +8,36 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include -#include - -#include -#include - +#include +#include +#include +#include +#include + +#include +#include +#include +#include #include #include +#include #include #include +#include #include #include +#include +#include +#include +#include +#include +#include +#include #include #include +#include +#include +#include #include @@ -81,7 +97,7 @@ NET_BUF_SIMPLE_DEFINE_STATIC(att_buf, ATT_BUF_SIZE); static int16_t lookup_index_by_handle(uint16_t handle) { - for (int i = 0; i < ARRAY_SIZE(broadcast_assistant.recv_state_handles); i++) { + for (size_t i = 0U; i < ARRAY_SIZE(broadcast_assistant.recv_state_handles); i++) { if (broadcast_assistant.recv_state_handles[i] == handle) { return i; } diff --git a/subsys/bluetooth/audio/bap_broadcast_sink.c b/subsys/bluetooth/audio/bap_broadcast_sink.c index 97a1206b13a59..52a4f8da343dd 100644 --- a/subsys/bluetooth/audio/bap_broadcast_sink.c +++ b/subsys/bluetooth/audio/bap_broadcast_sink.c @@ -6,27 +6,43 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include -#include -#include -#include - +#include +#include +#include +#include +#include + +#include +#include #include #include +#include #include #include #include #include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include "../host/conn_internal.h" #include "../host/iso_internal.h" +#include "audio_internal.h" #include "bap_iso.h" #include "bap_endpoint.h" -#include "audio_internal.h" - -#include LOG_MODULE_REGISTER(bt_bap_broadcast_sink, CONFIG_BT_BAP_BROADCAST_SINK_LOG_LEVEL); diff --git a/subsys/bluetooth/audio/bap_broadcast_source.c b/subsys/bluetooth/audio/bap_broadcast_source.c index 0934fc0f8d06b..01e32ae99059d 100644 --- a/subsys/bluetooth/audio/bap_broadcast_source.c +++ b/subsys/bluetooth/audio/bap_broadcast_source.c @@ -6,21 +6,36 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include -#include -#include +#include +#include +#include +#include +#include +#include #include #include +#include #include #include #include - +#include +#include +#include +#include #include +#include +#include +#include +#include +#include +#include + LOG_MODULE_REGISTER(bt_bap_broadcast_source, CONFIG_BT_BAP_BROADCAST_SOURCE_LOG_LEVEL); #include "bap_iso.h" #include "bap_endpoint.h" +#include "bap_stream.h" struct bt_bap_broadcast_subgroup { /* The streams used to create the broadcast source */ diff --git a/subsys/bluetooth/audio/bap_endpoint.h b/subsys/bluetooth/audio/bap_endpoint.h index 12b1209fb09bd..4efea0dba6757 100644 --- a/subsys/bluetooth/audio/bap_endpoint.h +++ b/subsys/bluetooth/audio/bap_endpoint.h @@ -7,8 +7,17 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include +#include + +#include +#include #include +#include +#include #include +#include +#include #include #include "ascs_internal.h" diff --git a/subsys/bluetooth/audio/bap_internal.h b/subsys/bluetooth/audio/bap_internal.h index 27f62977a2287..905e862c9a223 100644 --- a/subsys/bluetooth/audio/bap_internal.h +++ b/subsys/bluetooth/audio/bap_internal.h @@ -9,10 +9,15 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include -#include +#include +#include + #include #include +#include +#include +#include +#include #define BT_BAP_BASS_SCAN_STATE_NOT_SCANNING 0x00 #define BT_BAP_BASS_SCAN_STATE_SCANNING 0x01 diff --git a/subsys/bluetooth/audio/bap_iso.c b/subsys/bluetooth/audio/bap_iso.c index 3fa2059ea94de..1104fbfb8daa2 100644 --- a/subsys/bluetooth/audio/bap_iso.c +++ b/subsys/bluetooth/audio/bap_iso.c @@ -7,12 +7,25 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + #include "bap_iso.h" #include "audio_internal.h" #include "bap_endpoint.h" -#include - LOG_MODULE_REGISTER(bt_bap_iso, CONFIG_BT_BAP_ISO_LOG_LEVEL); /* TODO: Optimize the ISO_POOL_SIZE */ diff --git a/subsys/bluetooth/audio/bap_iso.h b/subsys/bluetooth/audio/bap_iso.h index 4384182d697fa..f1ebd0eed9b25 100644 --- a/subsys/bluetooth/audio/bap_iso.h +++ b/subsys/bluetooth/audio/bap_iso.h @@ -7,9 +7,14 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include +#include +#include + +#include #include #include +#include +#include struct bt_bap_iso_dir { struct bt_bap_stream *stream; diff --git a/subsys/bluetooth/audio/bap_scan_delegator.c b/subsys/bluetooth/audio/bap_scan_delegator.c index 6a55d7da2c351..6ba46a49c1f50 100644 --- a/subsys/bluetooth/audio/bap_scan_delegator.c +++ b/subsys/bluetooth/audio/bap_scan_delegator.c @@ -7,20 +7,35 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include -#include -#include -#include - -#include - +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include #include #include +#include #include +#include #include #include - +#include +#include +#include #include +#include +#include +#include +#include +#include +#include LOG_MODULE_REGISTER(bt_bap_scan_delegator, CONFIG_BT_BAP_SCAN_DELEGATOR_LOG_LEVEL); diff --git a/subsys/bluetooth/audio/bap_stream.c b/subsys/bluetooth/audio/bap_stream.c index 0894af516a1b3..fa17e2d138e6f 100644 --- a/subsys/bluetooth/audio/bap_stream.c +++ b/subsys/bluetooth/audio/bap_stream.c @@ -7,28 +7,39 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include -#include -#include +#include +#include +#include +#include +#include +#include #include #include #include #include +#include #include #include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include "../host/iso_internal.h" -#include "bap_iso.h" #include "audio_internal.h" +#include "bap_iso.h" #include "bap_endpoint.h" #include "bap_unicast_client_internal.h" #include "bap_unicast_server.h" -#include - LOG_MODULE_REGISTER(bt_bap_stream, CONFIG_BT_BAP_STREAM_LOG_LEVEL); #if defined(CONFIG_BT_BAP_UNICAST_CLIENT) || defined(CONFIG_BT_BAP_BROADCAST_SOURCE) || \ diff --git a/subsys/bluetooth/audio/bap_stream.h b/subsys/bluetooth/audio/bap_stream.h index 3d02c2cf30c90..597bf80d94cd6 100644 --- a/subsys/bluetooth/audio/bap_stream.h +++ b/subsys/bluetooth/audio/bap_stream.h @@ -7,6 +7,14 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include +#include + +#include +#include +#include +#include + void bt_bap_stream_init(struct bt_bap_stream *stream); /* Disconnect ISO channel */ diff --git a/subsys/bluetooth/audio/bap_unicast_client.c b/subsys/bluetooth/audio/bap_unicast_client.c index 3de389618f4fe..236733c9c6bf2 100644 --- a/subsys/bluetooth/audio/bap_unicast_client.c +++ b/subsys/bluetooth/audio/bap_unicast_client.c @@ -9,28 +9,46 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include -#include -#include - +#include +#include +#include +#include +#include + +#include +#include #include #include +#include #include #include #include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include "../host/hci_core.h" #include "../host/conn_internal.h" #include "../host/iso_internal.h" -#include "bap_iso.h" +#include "ascs_internal.h" #include "audio_internal.h" +#include "bap_iso.h" #include "bap_endpoint.h" -#include "pacs_internal.h" #include "bap_unicast_client_internal.h" - -#include +#include "pacs_internal.h" BUILD_ASSERT(CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT > 0 || CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SRC_COUNT > 0, @@ -1752,7 +1770,6 @@ static int unicast_client_ep_config(struct bt_bap_ep *ep, struct net_buf_simple const struct bt_audio_codec_cfg *codec_cfg) { struct bt_ascs_config *req; - uint8_t cc_len; LOG_DBG("ep %p buf %p codec %p", ep, buf, codec_cfg); @@ -1784,7 +1801,6 @@ static int unicast_client_ep_config(struct bt_bap_ep *ep, struct net_buf_simple req->codec.cid = codec_cfg->cid; req->codec.vid = codec_cfg->vid; - cc_len = buf->len; req->cc_len = codec_cfg->data_len; net_buf_simple_add_mem(buf, codec_cfg->data, codec_cfg->data_len); @@ -2795,7 +2811,6 @@ int bt_bap_unicast_client_qos(struct bt_conn *conn, struct bt_bap_unicast_group struct net_buf_simple *buf; struct bt_bap_ep *ep; bool conn_stream_found; - bool cig_connected; int err; if (conn == NULL) { @@ -2809,11 +2824,6 @@ int bt_bap_unicast_client_qos(struct bt_conn *conn, struct bt_bap_unicast_group */ conn_stream_found = false; - /* User to determine if any stream in the group is in - * the connected state - */ - cig_connected = false; - /* Validate streams before starting the QoS execution */ SYS_SLIST_FOR_EACH_CONTAINER(&group->streams, stream, _node) { if (stream->conn != conn) { @@ -3292,7 +3302,7 @@ static uint8_t unicast_client_ase_read_func(struct bt_conn *conn, uint8_t err, unicast_client_ep_set_status(ep, buf); cb_err = unicast_client_ep_subscribe(conn, ep); if (cb_err != 0) { - LOG_DBG("Failed to subcribe to ep %p: %d", ep, cb_err); + LOG_DBG("Failed to subscribe to ep %p: %d", ep, cb_err); goto fail; } @@ -3764,7 +3774,6 @@ static uint8_t unicast_client_pacs_context_read_func(struct bt_conn *conn, uint8 struct net_buf_simple buf; struct bt_pacs_context *context; int cb_err; - int index; memset(read, 0, sizeof(*read)); @@ -3777,8 +3786,6 @@ static uint8_t unicast_client_pacs_context_read_func(struct bt_conn *conn, uint8 net_buf_simple_init_with_data(&buf, (void *)data, length); context = net_buf_simple_pull_mem(&buf, sizeof(*context)); - index = bt_conn_index(conn); - discover_loc: /* Read ASE instances */ cb_err = unicast_client_pacs_location_discover(conn); diff --git a/subsys/bluetooth/audio/bap_unicast_client_internal.h b/subsys/bluetooth/audio/bap_unicast_client_internal.h index 56542365ac62d..8e279ad652d01 100644 --- a/subsys/bluetooth/audio/bap_unicast_client_internal.h +++ b/subsys/bluetooth/audio/bap_unicast_client_internal.h @@ -6,6 +6,14 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include + +#include +#include +#include +#include +#include + int bt_bap_unicast_client_config(struct bt_bap_stream *stream, const struct bt_audio_codec_cfg *codec_cfg); diff --git a/subsys/bluetooth/audio/bap_unicast_server.c b/subsys/bluetooth/audio/bap_unicast_server.c index 911ca7f7d7a47..0c631186c03a4 100644 --- a/subsys/bluetooth/audio/bap_unicast_server.c +++ b/subsys/bluetooth/audio/bap_unicast_server.c @@ -5,17 +5,24 @@ * * SPDX-License-Identifier: Apache-2.0 */ +#include +#include +#include +#include +#include -#include - +#include #include #include +#include +#include +#include +#include +#include "ascs_internal.h" #include "bap_iso.h" -#include "pacs_internal.h" #include "bap_endpoint.h" - -#include +#include "pacs_internal.h" LOG_MODULE_REGISTER(bt_bap_unicast_server, CONFIG_BT_BAP_UNICAST_SERVER_LOG_LEVEL); diff --git a/subsys/bluetooth/audio/bap_unicast_server.h b/subsys/bluetooth/audio/bap_unicast_server.h index 7aef4f4bc2b5e..34f204e267c3d 100644 --- a/subsys/bluetooth/audio/bap_unicast_server.h +++ b/subsys/bluetooth/audio/bap_unicast_server.h @@ -6,6 +6,9 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include +#include + #include #include diff --git a/subsys/bluetooth/audio/cap_acceptor.c b/subsys/bluetooth/audio/cap_acceptor.c index d84fad1e8fb5f..f8365eccade35 100644 --- a/subsys/bluetooth/audio/cap_acceptor.c +++ b/subsys/bluetooth/audio/cap_acceptor.c @@ -4,13 +4,22 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include +#include +#include +#include +#include + +#include #include #include #include -#include "cap_internal.h" - +#include +#include #include +#include +#include + +#include "cap_internal.h" LOG_MODULE_REGISTER(bt_cap_acceptor, CONFIG_BT_CAP_ACCEPTOR_LOG_LEVEL); diff --git a/subsys/bluetooth/audio/cap_commander.c b/subsys/bluetooth/audio/cap_commander.c index fcd28d92fd60d..8f7d98bac4bf2 100644 --- a/subsys/bluetooth/audio/cap_commander.c +++ b/subsys/bluetooth/audio/cap_commander.c @@ -4,20 +4,34 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include -#include +#include +#include +#include +#include +#include + +#include +#include #include +#include #include +#include #include #include #include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "bap_endpoint.h" #include "bap_internal.h" #include "cap_internal.h" -#include "ccid_internal.h" #include "csip_internal.h" -#include "bap_endpoint.h" - -#include LOG_MODULE_REGISTER(bt_cap_commander, CONFIG_BT_CAP_COMMANDER_LOG_LEVEL); diff --git a/subsys/bluetooth/audio/cap_initiator.c b/subsys/bluetooth/audio/cap_initiator.c index 61257e8a013e5..f5a6adfde71b2 100644 --- a/subsys/bluetooth/audio/cap_initiator.c +++ b/subsys/bluetooth/audio/cap_initiator.c @@ -4,6 +4,7 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include #include #include #include @@ -16,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -25,10 +27,10 @@ #include #include +#include "bap_endpoint.h" #include "cap_internal.h" #include "ccid_internal.h" #include "csip_internal.h" -#include "bap_endpoint.h" LOG_MODULE_REGISTER(bt_cap_initiator, CONFIG_BT_CAP_INITIATOR_LOG_LEVEL); diff --git a/subsys/bluetooth/audio/cap_internal.h b/subsys/bluetooth/audio/cap_internal.h index e460fce98dcdd..839d4a31757a3 100644 --- a/subsys/bluetooth/audio/cap_internal.h +++ b/subsys/bluetooth/audio/cap_internal.h @@ -8,17 +8,19 @@ #include #include +#include +#include #include -#include -#include -#include -#include -#include #include #include #include +#include +#include +#include +#include #include +#include bool bt_cap_acceptor_ccid_exist(const struct bt_conn *conn, uint8_t ccid); diff --git a/subsys/bluetooth/audio/cap_stream.c b/subsys/bluetooth/audio/cap_stream.c index 46009b36a4771..ebebeb2eb5fa2 100644 --- a/subsys/bluetooth/audio/cap_stream.c +++ b/subsys/bluetooth/audio/cap_stream.c @@ -5,10 +5,10 @@ */ #include -#include -#include #include +#include +#include #include #include #include @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include diff --git a/subsys/bluetooth/audio/ccid.c b/subsys/bluetooth/audio/ccid.c index c3a9d6a2b42ea..60991a54a8b75 100644 --- a/subsys/bluetooth/audio/ccid.c +++ b/subsys/bluetooth/audio/ccid.c @@ -6,9 +6,14 @@ * * SPDX-License-Identifier: Apache-2.0 */ +#include +#include +#include + #include #include #include +#include #include "ccid_internal.h" diff --git a/subsys/bluetooth/audio/ccid_internal.h b/subsys/bluetooth/audio/ccid_internal.h index bf48877529d87..b67331f00a3f7 100644 --- a/subsys/bluetooth/audio/ccid_internal.h +++ b/subsys/bluetooth/audio/ccid_internal.h @@ -10,7 +10,9 @@ #ifndef ZEPHYR_INCLUDE_BLUETOOTH_CCID_H_ #define ZEPHYR_INCLUDE_BLUETOOTH_CCID_H_ -#include +#include + +#include /** * @brief Gets a free CCID value. diff --git a/subsys/bluetooth/audio/codec.c b/subsys/bluetooth/audio/codec.c index 86936d58a8ef9..208448646fc09 100644 --- a/subsys/bluetooth/audio/codec.c +++ b/subsys/bluetooth/audio/codec.c @@ -10,13 +10,21 @@ * Generic Audio. */ +#include +#include +#include +#include #include +#include +#include #include +#include +#include +#include #include #include - -#include +#include LOG_MODULE_REGISTER(bt_audio_codec, CONFIG_BT_AUDIO_CODEC_LOG_LEVEL); diff --git a/subsys/bluetooth/audio/csip_crypto.c b/subsys/bluetooth/audio/csip_crypto.c index 0efe1fec5a26b..08346bed0bdcc 100644 --- a/subsys/bluetooth/audio/csip_crypto.c +++ b/subsys/bluetooth/audio/csip_crypto.c @@ -9,16 +9,23 @@ * in the CSIS spec is also provided as BE, and logging values as BE will make * it easier to compare. */ -#include "csip_crypto.h" +#include +#include +#include + +#include +#include #include +#include #include #include +#include #include "crypto/bt_crypto.h" #include "common/bt_str.h" -#include +#include "csip_crypto.h" LOG_MODULE_REGISTER(bt_csip_crypto, CONFIG_BT_CSIP_SET_MEMBER_CRYPTO_LOG_LEVEL); diff --git a/subsys/bluetooth/audio/csip_crypto.h b/subsys/bluetooth/audio/csip_crypto.h index 1a41bf32d547e..b522eb94a98a3 100644 --- a/subsys/bluetooth/audio/csip_crypto.h +++ b/subsys/bluetooth/audio/csip_crypto.h @@ -5,10 +5,10 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include -#include +#include #include +#include #define BT_CSIP_CRYPTO_KEY_SIZE 16 #define BT_CSIP_CRYPTO_SALT_SIZE 16 diff --git a/subsys/bluetooth/audio/csip_internal.h b/subsys/bluetooth/audio/csip_internal.h index 6335e664c40a5..0ac61f335c0bf 100644 --- a/subsys/bluetooth/audio/csip_internal.h +++ b/subsys/bluetooth/audio/csip_internal.h @@ -7,8 +7,11 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include +#include +#include +#include +#include #define BT_CSIP_SIRK_TYPE_ENCRYPTED 0x00 #define BT_CSIP_SIRK_TYPE_PLAIN 0x01 diff --git a/subsys/bluetooth/audio/csip_set_coordinator.c b/subsys/bluetooth/audio/csip_set_coordinator.c index b9d6f251a8bc7..fea61e131b67c 100644 --- a/subsys/bluetooth/audio/csip_set_coordinator.c +++ b/subsys/bluetooth/audio/csip_set_coordinator.c @@ -18,27 +18,41 @@ * 10) Unlock all members */ +#include +#include +#include +#include #include -#include -#include - -#include -#include -#include +#include +#include +#include +#include #include #include +#include #include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include -#include -#include "csip_crypto.h" -#include "csip_internal.h" + #include "../host/conn_internal.h" #include "../host/keys.h" -#include "common/bt_str.h" -#include +#include "csip_crypto.h" +#include "csip_internal.h" +#include "common/bt_str.h" LOG_MODULE_REGISTER(bt_csip_set_coordinator, CONFIG_BT_CSIP_SET_COORDINATOR_LOG_LEVEL); diff --git a/subsys/bluetooth/audio/csip_set_member.c b/subsys/bluetooth/audio/csip_set_member.c index d038020f9c8a9..f3e91beb8a555 100644 --- a/subsys/bluetooth/audio/csip_set_member.c +++ b/subsys/bluetooth/audio/csip_set_member.c @@ -6,37 +6,51 @@ * * SPDX-License-Identifier: Apache-2.0 */ - -#include -#include - -#include -#include +#include +#include +#include +#include +#include #include +#include +#include +#include +#include +#include #include #include +#include #include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include #include -#include "audio_internal.h" -#include "csip_internal.h" -#include "csip_crypto.h" #include "../host/conn_internal.h" #include "../host/hci_core.h" #include "../host/keys.h" +#include "common/bt_str.h" +#include "audio_internal.h" +#include "csip_internal.h" +#include "csip_crypto.h" + #define CSIP_SET_LOCK_TIMER_VALUE K_SECONDS(60) #define CSIS_CHAR_ATTR_COUNT 3 /* declaration + value + cccd */ #define CSIS_RANK_CHAR_ATTR_COUNT 2 /* declaration + value */ -#include "common/bt_str.h" - -#include - LOG_MODULE_REGISTER(bt_csip_set_member, CONFIG_BT_CSIP_SET_MEMBER_LOG_LEVEL); enum csip_flag { diff --git a/subsys/bluetooth/audio/gmap_client.c b/subsys/bluetooth/audio/gmap_client.c index dff67356b760b..8f4fb74ffa066 100644 --- a/subsys/bluetooth/audio/gmap_client.c +++ b/subsys/bluetooth/audio/gmap_client.c @@ -4,9 +4,21 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include +#include +#include +#include +#include +#include + +#include +#include #include +#include +#include +#include #include +#include +#include #include #include "audio_internal.h" diff --git a/subsys/bluetooth/audio/gmap_server.c b/subsys/bluetooth/audio/gmap_server.c index 5bc16ee686f15..d80003bf210a7 100644 --- a/subsys/bluetooth/audio/gmap_server.c +++ b/subsys/bluetooth/audio/gmap_server.c @@ -3,12 +3,22 @@ * * SPDX-License-Identifier: Apache-2.0 */ - -#include +#include +#include +#include +#include +#include +#include + +#include #include -#include - +#include +#include +#include #include +#include +#include +#include #include "audio_internal.h" diff --git a/subsys/bluetooth/audio/has.c b/subsys/bluetooth/audio/has.c index b018e034bb7b6..f90c54159cd31 100644 --- a/subsys/bluetooth/audio/has.c +++ b/subsys/bluetooth/audio/has.c @@ -4,24 +4,42 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include - -#include -#include +#include +#include +#include +#include +#include +#include + +#include #include #include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include #include +#include +#include +#include +#include #include "../bluetooth/host/hci_core.h" #include "../bluetooth/host/settings.h" -#include "audio_internal.h" -#include "has_internal.h" +#include "audio_internal.h" #include "common/bt_str.h" - -#include +#include "has_internal.h" LOG_MODULE_REGISTER(bt_has, CONFIG_BT_HAS_LOG_LEVEL); @@ -184,7 +202,7 @@ static struct client_context { uint8_t last_preset_index_known; } contexts[CONFIG_BT_MAX_PAIRED]; -/* Connected client clientance */ +/* Connected client instance */ static struct has_client { struct bt_conn *conn; #if defined(CONFIG_BT_HAS_PRESET_SUPPORT) @@ -919,7 +937,7 @@ static int settings_set_cb(const char *name, size_t len_rd, settings_read_cb rea return 0; } -BT_SETTINGS_DEFINE(has, "has", settings_set_cb, NULL); +static BT_SETTINGS_DEFINE(has, "has", settings_set_cb, NULL); static void store_client_context(struct client_context *context) { diff --git a/subsys/bluetooth/audio/has_client.c b/subsys/bluetooth/audio/has_client.c index 9ac33139a965c..0426cf9dbe3a9 100644 --- a/subsys/bluetooth/audio/has_client.c +++ b/subsys/bluetooth/audio/has_client.c @@ -3,20 +3,29 @@ * * SPDX-License-Identifier: Apache-2.0 */ - -#include - +#include +#include +#include +#include +#include + +#include +#include +#include #include +#include #include -#include +#include +#include +#include #include #include #include +#include +#include #include "has_internal.h" -#include - LOG_MODULE_REGISTER(bt_has_client, CONFIG_BT_HAS_CLIENT_LOG_LEVEL); #define HAS_INST(_has) CONTAINER_OF(_has, struct bt_has_client, has) diff --git a/subsys/bluetooth/audio/has_internal.h b/subsys/bluetooth/audio/has_internal.h index 5c5dc6b941093..97b4d2017aefa 100644 --- a/subsys/bluetooth/audio/has_internal.h +++ b/subsys/bluetooth/audio/has_internal.h @@ -8,8 +8,14 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include +#include + #include #include +#include +#include +#include /* Control Point opcodes */ #define BT_HAS_OP_READ_PRESET_REQ 0x01 diff --git a/subsys/bluetooth/audio/mcc.c b/subsys/bluetooth/audio/mcc.c index e192c0352dba8..38929ab19cdd2 100644 --- a/subsys/bluetooth/audio/mcc.c +++ b/subsys/bluetooth/audio/mcc.c @@ -7,22 +7,38 @@ * * SPDX-License-Identifier: Apache-2.0 */ +#include +#include +#include +#include +#include -#include -#include -#include -#include -#include -#include - +#include +#include +#include +#include +#include #include #include #include -#include -#include "mcc_internal.h" - #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + #include "../services/ots/ots_client_internal.h" +#include "common/bt_str.h" +#include "mcc_internal.h" #include "mcs_internal.h" /* TODO: Temporarily copied here from media_proxy_internal.h - clean up */ @@ -38,13 +54,8 @@ } \ } while (0) - -#include - LOG_MODULE_REGISTER(bt_mcc, CONFIG_BT_MCC_LOG_LEVEL); -#include "common/bt_str.h" - static struct mcs_instance_t mcs_instance; static struct bt_uuid_16 uuid = BT_UUID_INIT_16(0); diff --git a/subsys/bluetooth/audio/mcc_internal.h b/subsys/bluetooth/audio/mcc_internal.h index 2838e53ba350d..603977a70f3f9 100644 --- a/subsys/bluetooth/audio/mcc_internal.h +++ b/subsys/bluetooth/audio/mcc_internal.h @@ -11,10 +11,15 @@ #ifndef ZEPHYR_INCLUDE_BLUETOOTH_AUDIO_MCP_INTERNAL_ #define ZEPHYR_INCLUDE_BLUETOOTH_AUDIO_MCP_INTERNAL_ -#include +#include +#include + +#include +#include +#include #include #include -#include "../services/ots/ots_client_internal.h" +#include struct mcs_instance_t *lookup_inst_by_conn(struct bt_conn *conn); diff --git a/subsys/bluetooth/audio/mcs.c b/subsys/bluetooth/audio/mcs.c index 271ea690ad735..d0eb2f7658bb3 100644 --- a/subsys/bluetooth/audio/mcs.c +++ b/subsys/bluetooth/audio/mcs.c @@ -8,29 +8,37 @@ * SPDX-License-Identifier: Apache-2.0 */ - -#include +#include +#include #include -#include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include #include #include #include +#include #include -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include "audio_internal.h" #include "media_proxy_internal.h" #include "mcs_internal.h" -#include - LOG_MODULE_REGISTER(bt_mcs, CONFIG_BT_MCS_LOG_LEVEL); static void notify(const struct bt_uuid *uuid, const void *data, uint16_t len); @@ -986,7 +994,7 @@ static void notify_string(struct bt_conn *conn, const struct bt_uuid *uuid, cons __ASSERT(att_mtu > att_header_size, "Could not get valid ATT MTU"); maxlen = att_mtu - att_header_size; /* Subtract opcode and handle */ - /* Send notifcation potentially truncated to the MTU */ + /* Send notification potentially truncated to the MTU */ err = bt_gatt_notify_uuid(conn, uuid, mcs.attrs, (void *)str, MIN(strlen(str), maxlen)); if (err != 0) { diff --git a/subsys/bluetooth/audio/mcs_internal.h b/subsys/bluetooth/audio/mcs_internal.h index 3bbce49fa1492..e2a16049541ff 100644 --- a/subsys/bluetooth/audio/mcs_internal.h +++ b/subsys/bluetooth/audio/mcs_internal.h @@ -8,9 +8,8 @@ #ifndef ZEPHYR_SUBSYS_BLUETOOTH_HOST_AUDIO_MCS_INTERNAL_H_ #define ZEPHYR_SUBSYS_BLUETOOTH_HOST_AUDIO_MCS_INTERNAL_H_ -#include -#include -#include +#include +#include #ifdef __cplusplus extern "C" { diff --git a/subsys/bluetooth/audio/media_proxy.c b/subsys/bluetooth/audio/media_proxy.c index e816b1f20a00b..54e567de10195 100644 --- a/subsys/bluetooth/audio/media_proxy.c +++ b/subsys/bluetooth/audio/media_proxy.c @@ -6,17 +6,22 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include +#include +#include +#include +#include -#include +#include #include #include +#include +#include +#include +#include #include "media_proxy_internal.h" #include "mcs_internal.h" -#include - LOG_MODULE_REGISTER(media_proxy, CONFIG_MCTL_LOG_LEVEL); /* Media player */ diff --git a/subsys/bluetooth/audio/media_proxy_internal.h b/subsys/bluetooth/audio/media_proxy_internal.h index 37f5e5997674b..6a24f80d11b81 100644 --- a/subsys/bluetooth/audio/media_proxy_internal.h +++ b/subsys/bluetooth/audio/media_proxy_internal.h @@ -9,7 +9,11 @@ /** @brief Internal APIs for Bluetooth Media Control */ +#include + +#include #include +#include #define MPL_NO_TRACK_ID 0 diff --git a/subsys/bluetooth/audio/micp_internal.h b/subsys/bluetooth/audio/micp_internal.h index ce486bf6fe6c0..d23d655133bc4 100644 --- a/subsys/bluetooth/audio/micp_internal.h +++ b/subsys/bluetooth/audio/micp_internal.h @@ -12,7 +12,11 @@ #ifndef ZEPHYR_INCLUDE_BLUETOOTH_AUDIO_MICP_INTERNAL_ #define ZEPHYR_INCLUDE_BLUETOOTH_AUDIO_MICP_INTERNAL_ -#include +#include +#include + +#include +#include #include struct bt_micp_mic_ctlr { diff --git a/subsys/bluetooth/audio/micp_mic_ctlr.c b/subsys/bluetooth/audio/micp_mic_ctlr.c index 45190b7c9b4ca..9b3605f7efe8b 100644 --- a/subsys/bluetooth/audio/micp_mic_ctlr.c +++ b/subsys/bluetooth/audio/micp_mic_ctlr.c @@ -7,26 +7,36 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include -#include - -#include - -#include -#include - +#include +#include +#include +#include +#include + +#include +#include +#include +#include #include #include #include -#include +#include +#include +#include +#include #include +#include +#include +#include +#include +#include +#include +#include "common/bt_str.h" #include "micp_internal.h" LOG_MODULE_REGISTER(bt_micp_mic_ctlr, CONFIG_BT_MICP_MIC_CTLR_LOG_LEVEL); -#include "common/bt_str.h" - /* Callback functions */ static sys_slist_t micp_mic_ctlr_cbs = SYS_SLIST_STATIC_INIT(&micp_mic_ctlr_cbs); diff --git a/subsys/bluetooth/audio/micp_mic_dev.c b/subsys/bluetooth/audio/micp_mic_dev.c index e282845936aa9..1bc1e10b43e7a 100644 --- a/subsys/bluetooth/audio/micp_mic_dev.c +++ b/subsys/bluetooth/audio/micp_mic_dev.c @@ -6,23 +6,32 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include -#include -#include - -#include -#include - +#include +#include +#include +#include +#include + +#include +#include #include #include #include #include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include "audio_internal.h" -#include - LOG_MODULE_REGISTER(bt_micp, CONFIG_BT_MICP_MIC_DEV_LOG_LEVEL); struct bt_micp_server { diff --git a/subsys/bluetooth/audio/mpl.c b/subsys/bluetooth/audio/mpl.c index 111482b3e04c9..a80429ee80e31 100644 --- a/subsys/bluetooth/audio/mpl.c +++ b/subsys/bluetooth/audio/mpl.c @@ -6,25 +6,35 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include - +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include #include +#include +#include +#include #include #include +#include -#include -#include - +#include "ccid_internal.h" #include "media_proxy_internal.h" +#include "mcs_internal.h" #include "mpl_internal.h" -#include - LOG_MODULE_REGISTER(bt_mpl, CONFIG_BT_MPL_LOG_LEVEL); -#include "ccid_internal.h" -#include "mcs_internal.h" - #define TRACK_STATUS_INVALID 0x00 #define TRACK_STATUS_VALID 0x01 @@ -395,7 +405,7 @@ static uint32_t setup_parent_group_object(struct mpl_group *group) /* The implementation has a fixed structure, with one parent group, */ /* and one level of groups containing tracks only. */ /* The track groups have a pointer to the parent, but there is no */ - /* poinbter in the other direction, so it is not possible to go from */ + /* pointer in the other direction, so it is not possible to go from */ /* the parent group to a group of tracks. */ uint8_t type = MEDIA_PROXY_GROUP_OBJECT_GROUP_TYPE; diff --git a/subsys/bluetooth/audio/mpl_internal.h b/subsys/bluetooth/audio/mpl_internal.h index c8a553da2166d..e24441371927e 100644 --- a/subsys/bluetooth/audio/mpl_internal.h +++ b/subsys/bluetooth/audio/mpl_internal.h @@ -10,6 +10,13 @@ #ifndef ZEPHYR_SUBSYS_BLUETOOTH_AUDIO_MPL_INTERNAL_ #define ZEPHYR_SUBSYS_BLUETOOTH_AUDIO_MPL_INTERNAL_ +#include +#include + +#include +#include +#include + #ifdef __cplusplus extern "C" { #endif diff --git a/subsys/bluetooth/audio/pacs.c b/subsys/bluetooth/audio/pacs.c index 64f750523ff71..bbad4ee89dae9 100644 --- a/subsys/bluetooth/audio/pacs.c +++ b/subsys/bluetooth/audio/pacs.c @@ -9,31 +9,44 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include -#include -#include - -#include -#include - +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include #include #include #include -#include -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include +#include +#include + #include "../host/conn_internal.h" #include "../host/hci_core.h" - -#include - -LOG_MODULE_REGISTER(bt_pacs, CONFIG_BT_PACS_LOG_LEVEL); - #include "common/bt_str.h" #include "audio_internal.h" -#include "pacs_internal.h" #include "bap_unicast_server.h" +#include "pacs_internal.h" + +LOG_MODULE_REGISTER(bt_pacs, CONFIG_BT_PACS_LOG_LEVEL); #define PAC_NOTIFY_TIMEOUT K_MSEC(10) #define READ_BUF_SEM_TIMEOUT K_MSEC(50) diff --git a/subsys/bluetooth/audio/pacs_internal.h b/subsys/bluetooth/audio/pacs_internal.h index 2c449f7f4adc5..8fe715e57ba87 100644 --- a/subsys/bluetooth/audio/pacs_internal.h +++ b/subsys/bluetooth/audio/pacs_internal.h @@ -7,7 +7,9 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include +#include + +#include #define BT_AUDIO_LOCATION_MASK BIT_MASK(28) diff --git a/subsys/bluetooth/audio/pbp.c b/subsys/bluetooth/audio/pbp.c index 3b624045de27d..ab3ab4822e9a4 100644 --- a/subsys/bluetooth/audio/pbp.c +++ b/subsys/bluetooth/audio/pbp.c @@ -3,14 +3,21 @@ * * SPDX-License-Identifier: Apache-2.0 */ +#include +#include +#include -#include -#include -#include +#include #include #include +#include +#include +#include #include +#include +#include #include +#include LOG_MODULE_REGISTER(bt_pbp, CONFIG_BT_PBP_LOG_LEVEL); diff --git a/subsys/bluetooth/audio/shell/audio.h b/subsys/bluetooth/audio/shell/audio.h index 63fb699ad99ac..02d7618cb6093 100644 --- a/subsys/bluetooth/audio/shell/audio.h +++ b/subsys/bluetooth/audio/shell/audio.h @@ -10,15 +10,27 @@ * SPDX-License-Identifier: Apache-2.0 */ -#ifndef __AUDIO_H -#define __AUDIO_H +#ifndef AUDIO_SHELL_AUDIO_H +#define AUDIO_SHELL_AUDIO_H +#include +#include +#include #include +#include +#include +#include #include +#include +#include #include +#include #include #include +#include +#include +#include #include "shell/bt.h" @@ -1159,4 +1171,4 @@ static inline void copy_broadcast_source_preset(struct broadcast_source *source, } #endif /* CONFIG_BT_AUDIO */ -#endif /* __AUDIO_H */ +#endif /* AUDIO_SHELL_AUDIO_H */ diff --git a/subsys/bluetooth/audio/shell/bap.c b/subsys/bluetooth/audio/shell/bap.c index e63b2d559d15d..a400555dd76b1 100644 --- a/subsys/bluetooth/audio/shell/bap.c +++ b/subsys/bluetooth/audio/shell/bap.c @@ -10,22 +10,42 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include -#include -#include -#include -#include -#include -#include -#include - -#include +#include +#include +#include +#include +#include +#include + +#include #include #include #include #include #include +#include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include "shell/bt.h" #include "audio.h" @@ -192,6 +212,8 @@ void bap_foreach_stream(void (*func)(struct shell_stream *sh_stream, void *data) } #if defined(CONFIG_LIBLC3) +#include + static int get_lc3_chan_alloc_from_index(const struct shell_stream *sh_stream, uint8_t index, enum bt_audio_location *chan_alloc) { @@ -4060,7 +4082,7 @@ static ssize_t connectable_ad_data_add(struct bt_data *data_array, sys_put_le16(snk_context, &ad_bap_announcement[3]); src_context = bt_pacs_get_available_contexts(BT_AUDIO_DIR_SOURCE); - sys_put_le16(snk_context, &ad_bap_announcement[5]); + sys_put_le16(src_context, &ad_bap_announcement[5]); /* Metadata length */ ad_bap_announcement[7] = 0x00; diff --git a/subsys/bluetooth/audio/shell/bap_broadcast_assistant.c b/subsys/bluetooth/audio/shell/bap_broadcast_assistant.c index ee3d70509180c..85be52069ab58 100644 --- a/subsys/bluetooth/audio/shell/bap_broadcast_assistant.c +++ b/subsys/bluetooth/audio/shell/bap_broadcast_assistant.c @@ -7,18 +7,30 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include +#include +#include +#include +#include +#include -#include -#include -#include -#include -#include -#include -#include +#include #include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include +#include +#include +#include #include "shell/bt.h" #include "../../host/hci_core.h" diff --git a/subsys/bluetooth/audio/shell/bap_scan_delegator.c b/subsys/bluetooth/audio/shell/bap_scan_delegator.c index 9c0789eabb184..e31a85c064ddc 100644 --- a/subsys/bluetooth/audio/shell/bap_scan_delegator.c +++ b/subsys/bluetooth/audio/shell/bap_scan_delegator.c @@ -7,22 +7,36 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include - +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include #include -#include #include -#include -#include -#include -#include +#include +#include +#include +#include +#include + #include 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 literal 0 HcmV?d00001 diff --git a/boards/adi/max32655evkit/doc/index.rst b/boards/adi/max32655evkit/doc/index.rst new file mode 100644 index 0000000000000..30ee39c9ce003 --- /dev/null +++ b/boards/adi/max32655evkit/doc/index.rst @@ -0,0 +1,177 @@ +.. _max32655_evkit: + +MAX32655EVKIT +############# + +Overview +******** +The MAX32655 evaluation kit (EV kit) provides a platform for evaluation capabilities +of the MAX32655 microcontroller, which is an advanced system-on-chip (SoC). +It features an Arm® Cortex®-M4F CPU for efficient computation of complex functions and +algorithms, integrated power management (SIMO), and the newest generation +Bluetooth® 5.0 Low Energy (Bluetooth LE), long-range radio for wearable and hearable device applications. + +The Zephyr port is running on the MAX32655 MCU. + +.. image:: img/max32655evkit_img1.jpg + :align: center + :alt: MAX32655 EVKIT Front + +.. image:: img/max32655evkit_img2.jpg + :align: center + :alt: MAX32655 Back + +Hardware +******** + +- MAX32655 MCU: + + - Ultra-Low-Power Wireless Microcontroller + - Internal 100MHz Oscillator + - Flexible Low-Power Modes with 7.3728MHz System Clock Option + - 512KB Flash and 128KB SRAM (Optional ECC on One 32KB SRAM Bank) + - 16KB Instruction Cache + - Bluetooth 5.2 LE Radio + - Dedicated, Ultra-Low-Power, 32-Bit RISC-V Coprocessor to Offload Timing-Critical Bluetooth Processing + - Fully Open-Source Bluetooth 5.2 Stack Available + - Supports AoA, AoD, LE Audio, and Mesh + - High-Throughput (2Mbps) Mode + - Long-Range (125kbps and 500kbps) Modes + - Rx Sensitivity: -97.5dBm; Tx Power: +4.5dBm + - Single-Ended Antenna Connection (50Ω) + - Power Management Maximizes Battery Life + - 2.0V to 3.6V Supply Voltage Range + - Integrated SIMO Power Regulator + - Dynamic Voltage Scaling (DVS) + - 23.8μA/MHz Active Current at 3.0V + - 4.4μA at 3.0V Retention Current for 32KB + - Selectable SRAM Retention + RTC in Low-Power Modes + - Multiple Peripherals for System Control + - Up to Two High-Speed SPI Master/Slave + - Up to Three High-Speed I2C Master/Slave (3.4Mbps) + - Up to Four UART, One I2S Master/Slave + - Up to 8-Input, 10-Bit Sigma-Delta ADC 7.8ksps + - Up to Four Micro-Power Comparators + - Timers: Up to Two Four 32-Bit, Two LP, TwoWatchdog Timers + - 1-Wire® Master + - Up to Four Pulse Train (PWM) Engines + - RTC with Wake-Up Timer + - Up to 52 GPIOs + - Security and Integrity​ + - Available Secure Boot + - TRNG Seed Generator + - AES 128/192/256 Hardware Acceleration Engine + +- External devices connected to the MAX32655 EVKIT: + + - Color TFT Display + - Audio Stereo Codec Interface + - Digital Microphone + - A 128Mb QSPI flash + +Supported Features +================== + +Below are the interfaces supported by Zephyr on MAX32655EVKIT. + ++-----------+------------+-------------------------------------+ +| Interface | Controller | Driver/Component | ++===========+============+=====================================+ +| NVIC | on-chip | nested vector interrupt controller | ++-----------+------------+-------------------------------------+ +| SYSTICK | on-chip | systick | ++-----------+------------+-------------------------------------+ +| CLOCK | on-chip | clock and reset control | ++-----------+------------+-------------------------------------+ +| GPIO | on-chip | gpio | ++-----------+------------+-------------------------------------+ +| UART | on-chip | serial | ++-----------+------------+-------------------------------------+ + +Connections and IOs +=================== + ++-----------+---------------+-----------------------------------------------------------------------+ +| Name | Signal | Usage | ++===========+===============+=======================================================================+ +| JP1 | VREGI | Connect/Disconnect VREGIO power | ++-----------+---------------+-----------------------------------------------------------------------+ +| JP2 | P0_24 | Enable/Disable LED1 | ++-----------+---------------+-----------------------------------------------------------------------+ +| JP3 | P0_25 | Enable/Disable LED2 | ++-----------+---------------+-----------------------------------------------------------------------+ +| JP4 | P2_6/ P2_7 | Connect/Disconnect the USB to serial UART to GPIO P2_6 (LPUART_RX) | ++-----------+---------------+-----------------------------------------------------------------------+ +| JP5 | P2_7/ P0_1 | Connect/Disconnect the USB to serial UART to GPIO P2_7 (LPUART_TX) | ++-----------+---------------+-----------------------------------------------------------------------+ +| JP6 | P0_2 | Connect/Disconnect the USB to serial UART to GPIO P0_2 (UART0_CTS) | ++-----------+---------------+-----------------------------------------------------------------------+ +| JP7 | P0_3 | Connect/Disconnect he USB to serial UART to GPIO P0_3 (UART0_RTS) | ++-----------+---------------+-----------------------------------------------------------------------+ +| JP8 | VREGI | Select VDDIO_EN power source (3V3 or coin cell) | ++-----------+---------------+-----------------------------------------------------------------------+ +| JP9 | VDDIOH_EN | Select VDDIOH_EN power source 3V3/VREGI | ++-----------+---------------+-----------------------------------------------------------------------+ +| JP10 | VDDIOH | Connect/Disconnect VDDIOH power | ++-----------+---------------+-----------------------------------------------------------------------+ +| JP11 | VDDIO_EN | Select VDDIO_EN power source 1V8/VREGO_A | ++-----------+---------------+-----------------------------------------------------------------------+ +| JP12 | VDDIO | Connect/Disconnect VDDIO power | ++-----------+---------------+-----------------------------------------------------------------------+ +| JP13 | VDDA_EN | Select VDDA_EN power source 1V8/VREGO_A | ++-----------+---------------+-----------------------------------------------------------------------+ +| JP14 | VDDA | Connect/Disconnect VDDA power | ++-----------+---------------+-----------------------------------------------------------------------+ +| JP15 | VCOREA_EN | Select VCOREA_EN power source 1V1/VREGO_C | ++-----------+---------------+-----------------------------------------------------------------------+ +| JP16 | VCOREA | Connect/Disconnect VCOREA power | ++-----------+---------------+-----------------------------------------------------------------------+ +| JP17 | VCOREB_EN | Select VCOREB_EN power source 1V1/VREGO_B | ++-----------+---------------+-----------------------------------------------------------------------+ +| JP18 | VCOREB | Connect/Disconnect VCOREB power | ++-----------+---------------+-----------------------------------------------------------------------+ +| JP19 | BLE_LDO | Connect/Disconnect BLE_LDO power | ++-----------+---------------+-----------------------------------------------------------------------+ +| JP20 | VREF | Select VREF power source VDDIO/VDDIOH | ++-----------+---------------+-----------------------------------------------------------------------+ +| JP21 | I2C0_PU | Select I2C0_PU power source VDDIO/VDDIOH | ++-----------+---------------+-----------------------------------------------------------------------+ +| JP22 | I2C1_PU | Select I2C1_PU power source VDDIO/VDDIOH | ++-----------+---------------+-----------------------------------------------------------------------+ +| JP23 | BOARD RESET | Connect/Disconnect RV JTAG NRESET from the BOARD RESET circuitry | ++-----------+---------------+-----------------------------------------------------------------------+ + +Programming and Debugging +************************* + +Flashing +======== + +The MAX32655 MCU can be flashed by connecting an external debug probe to the +SWD port. SWD debug can be accessed through the Cortex 10-pin connector, JH3. +Logic levels are fixed to VDDIO (1.8V). + +Once the debug probe is connected to your host computer, then you can simply run the +``west flash`` command to write a firmware image into flash. + +.. note:: + + This board uses OpenOCD as the default debug interface. You can also use + a Segger J-Link with Segger's native tooling by overriding the runner, + appending ``--runner jlink`` to your ``west`` command(s). The J-Link should + be connected to the standard 2*5 pin debug connector (JW3) using an + appropriate adapter board and cable. + +Debugging +========= + +Please refer to the `Flashing`_ section and run the ``west debug`` command +instead of ``west flash``. + +References +********** + +- `MAX32655EVKIT web page`_ + +.. _MAX32655EVKIT web page: + https://www.analog.com/en/design-center/evaluation-hardware-and-software/evaluation-boards-kits/max32655evkit.html#eb-overview diff --git a/boards/adi/max32655evkit/max32655evkit_max32655_m4.dts b/boards/adi/max32655evkit/max32655evkit_max32655_m4.dts new file mode 100644 index 0000000000000..b1323a9bd3cd8 --- /dev/null +++ b/boards/adi/max32655evkit/max32655evkit_max32655_m4.dts @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2023-2024 Analog Devices, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; + + #include + #include + #include + +/ { + model = "Analog Devices MAX32655EVKIT"; + compatible = "adi,max32655evkit"; + + chosen { + zephyr,console = &uart0; + zephyr,shell-uart = &uart0; + zephyr,sram = &sram2; + zephyr,flash = &flash0; + }; + + leds { + compatible = "gpio-leds"; + led1: led_1 { + gpios = <&gpio0 24 GPIO_ACTIVE_LOW>; + label = "Red LED"; + }; + led2: led_2 { + gpios = <&gpio0 25 GPIO_ACTIVE_LOW>; + label = "Blue LED"; + }; + }; + + buttons { + compatible = "gpio-keys"; + pb1: pb1 { + gpios = <&gpio0 18 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>; + label = "SW2"; + }; + pb2: pb2 { + gpios = <&gpio0 19 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>; + label = "SW3"; + }; + pb_wakeup: pb_wakeup { + gpios = <&gpio3 1 (GPIO_PULL_UP | GPIO_ACTIVE_LOW + | MAX32_GPIO_VSEL_VDDIOH)>; + label = "Wakeup"; + }; + }; + + /* These aliases are provided for compatibility with samples */ + aliases { + led0 = &led1; + led1 = &led2; + sw0 = &pb1; + sw1 = &pb2; + }; +}; + +&uart0 { + pinctrl-0 = <&uart0a_tx_p0_1 &uart0a_rx_p0_0>; + pinctrl-names = "default"; + current-speed = <115200>; + data-bits = <8>; + parity = "none"; + status = "okay"; +}; + +&clk_ipo { + status = "okay"; +}; + +&gpio0 { + status = "okay"; +}; + +&gpio1 { + status = "okay"; +}; + +&gpio2 { + status = "okay"; +}; + +&gpio3 { + status = "okay"; +}; diff --git a/boards/adi/max32655evkit/max32655evkit_max32655_m4.yaml b/boards/adi/max32655evkit/max32655evkit_max32655_m4.yaml new file mode 100644 index 0000000000000..257a0d060a940 --- /dev/null +++ b/boards/adi/max32655evkit/max32655evkit_max32655_m4.yaml @@ -0,0 +1,13 @@ +identifier: max32655evkit/max32655/m4 +name: max32655evkit m4 +type: mcu +arch: arm +toolchain: + - zephyr + - gnuarmemb + - xtools +supported: + - gpio + - serial +ram: 128 +flash: 512 diff --git a/boards/adi/max32655evkit/max32655evkit_max32655_m4_defconfig b/boards/adi/max32655evkit/max32655evkit_max32655_m4_defconfig new file mode 100644 index 0000000000000..4fa0a46410634 --- /dev/null +++ b/boards/adi/max32655evkit/max32655evkit_max32655_m4_defconfig @@ -0,0 +1,13 @@ +# Copyright (c) 2023-2024 Analog Devices, Inc. +# SPDX-License-Identifier: Apache-2.0 + +# Enable GPIO +CONFIG_GPIO=y + +# Console +CONFIG_CONSOLE=y +CONFIG_UART_CONSOLE=y + +# Enable UART +CONFIG_SERIAL=y +CONFIG_UART_INTERRUPT_DRIVEN=y From ff89fc98eacee2b9b2f0c77880137d4d27582e7d Mon Sep 17 00:00:00 2001 From: Sadik Ozer Date: Fri, 13 Oct 2023 16:13:46 +0300 Subject: [PATCH 1681/2849] tests: drivers: gpio: Enable gpio driver tests for max32655evkit board Enable gpio driver test for max32655evkit board Signed-off-by: Sadik Ozer --- .../boards/max32655evkit_max32655_m4.overlay | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 tests/drivers/gpio/gpio_basic_api/boards/max32655evkit_max32655_m4.overlay diff --git a/tests/drivers/gpio/gpio_basic_api/boards/max32655evkit_max32655_m4.overlay b/tests/drivers/gpio/gpio_basic_api/boards/max32655evkit_max32655_m4.overlay new file mode 100644 index 0000000000000..aef5fe92da573 --- /dev/null +++ b/tests/drivers/gpio/gpio_basic_api/boards/max32655evkit_max32655_m4.overlay @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2023-2024 Analog Devices, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + resources { + compatible = "test-gpio-basic-api"; + out-gpios = <&gpio2 0 0>; + in-gpios = <&gpio2 1 0>; + }; +}; From 7204e24aa1328399aee13c87a29cbf5946ec934c Mon Sep 17 00:00:00 2001 From: Sadik Ozer Date: Mon, 6 Nov 2023 14:26:11 +0300 Subject: [PATCH 1682/2849] boards: Add MAX32655FTHR board Added MAX32655FTHR boards. For more information about this board please check https://www.analog.com/MAX32655FTHR Co-authored-by: Maureen Helm Signed-off-by: Sadik Ozer --- boards/adi/max32655fthr/Kconfig.max32655fthr | 7 + boards/adi/max32655fthr/board.cmake | 7 + boards/adi/max32655fthr/board.yml | 8 + .../doc/img/max32655fthr_img1.jpg | Bin 0 -> 95828 bytes .../doc/img/max32655fthr_img2.jpg | Bin 0 -> 95965 bytes .../doc/img/max32655fthr_img3.jpg | Bin 0 -> 95147 bytes boards/adi/max32655fthr/doc/index.rst | 193 ++++++++++++++++++ .../max32655fthr/max32655fthr_max32655_m4.dts | 123 +++++++++++ .../max32655fthr_max32655_m4.yaml | 13 ++ .../max32655fthr_max32655_m4_defconfig | 13 ++ 10 files changed, 364 insertions(+) create mode 100644 boards/adi/max32655fthr/Kconfig.max32655fthr create mode 100644 boards/adi/max32655fthr/board.cmake create mode 100644 boards/adi/max32655fthr/board.yml create mode 100644 boards/adi/max32655fthr/doc/img/max32655fthr_img1.jpg create mode 100644 boards/adi/max32655fthr/doc/img/max32655fthr_img2.jpg create mode 100644 boards/adi/max32655fthr/doc/img/max32655fthr_img3.jpg create mode 100644 boards/adi/max32655fthr/doc/index.rst create mode 100644 boards/adi/max32655fthr/max32655fthr_max32655_m4.dts create mode 100644 boards/adi/max32655fthr/max32655fthr_max32655_m4.yaml create mode 100644 boards/adi/max32655fthr/max32655fthr_max32655_m4_defconfig diff --git a/boards/adi/max32655fthr/Kconfig.max32655fthr b/boards/adi/max32655fthr/Kconfig.max32655fthr new file mode 100644 index 0000000000000..589209a2fb3e2 --- /dev/null +++ b/boards/adi/max32655fthr/Kconfig.max32655fthr @@ -0,0 +1,7 @@ +# MAX32655FTHR boards configuration + +# Copyright (c) 2023-2024 Analog Devices, Inc. +# SPDX-License-Identifier: Apache-2.0 + +config BOARD_MAX32655FTHR + select SOC_MAX32655_M4 if BOARD_MAX32655FTHR_MAX32655_M4 diff --git a/boards/adi/max32655fthr/board.cmake b/boards/adi/max32655fthr/board.cmake new file mode 100644 index 0000000000000..d2353452cbe3c --- /dev/null +++ b/boards/adi/max32655fthr/board.cmake @@ -0,0 +1,7 @@ +# Copyright (c) 2023-2024 Analog Devices, Inc. +# SPDX-License-Identifier: Apache-2.0 + +board_runner_args(openocd --cmd-pre-init "source [find interface/cmsis-dap.cfg]") +board_runner_args(openocd --cmd-pre-init "source [find target/max32655.cfg]") + +include(${ZEPHYR_BASE}/boards/common/openocd.board.cmake) diff --git a/boards/adi/max32655fthr/board.yml b/boards/adi/max32655fthr/board.yml new file mode 100644 index 0000000000000..087b51d8d958c --- /dev/null +++ b/boards/adi/max32655fthr/board.yml @@ -0,0 +1,8 @@ +# Copyright (c) 2023-2024 Analog Devices, Inc. +# SPDX-License-Identifier: Apache-2.0 + +board: + name: max32655fthr + vendor: adi + socs: + - name: max32655 diff --git a/boards/adi/max32655fthr/doc/img/max32655fthr_img1.jpg b/boards/adi/max32655fthr/doc/img/max32655fthr_img1.jpg new file mode 100644 index 0000000000000000000000000000000000000000..075a68e15fb6db9996d318153802e2955f231695 GIT binary patch literal 95828 zcmce7bzEG}lJ5{SI0R<~2ohv~;0}S{9vIw{!F?DU5&|Ry2n@lUV1w)69w5QpJ-AzN zNPx$0_uakwd7r!Y?(QG&%;(cneY&Qqy3cfVoo{vD&)hEqh*cDn6#!^x007#<2XKD} zpqF)Va&@zU!>ueC-uN)syIR?BxmiK~@6G#pfGhwX=P}-69DF=nJVF9|LQ*<1QW6qU z7Fr+$9VaU{H<%U7!7HpF&MWXzfCDTEk$S15qM@nrTwKpYSIt;KT|@ORA!r1Igrvlz z%w%NDs(fHR)&KEz{|!KbgD!<3hK|MvctnDRPJ(v-9RPgj#UpgIzdH1{3lj?s9pe!; z&O@saF#ru6{h>;L^%&l+Eyidqvw8$wK`E+z&!=htiN5`=FwFBcS znFIu1Lfo=Y?Uc+ydT-$Ft1Pl|P|Kj~jurXfoMWrpXCJD5jX%hyebD)r=D(?Z_(sP- zdxVLF{m>{v0(kW3K{Y!1qra?qPzykNgieA%`t%8}7AB(%8J{-!YbO4eu)wTnNaZo} zoAzGG zYYmo78vE-$<5_FTS!3|ly>0XGmVx60TzeN%)ldqseHSbBWE@+A_W*|TRQX*Q38 zX=C>t<;(RBe_!Nzp~t6D_tw1jp4^~|U$+55(Anlb8@yA-_!x7Soy3zHWm~hJk@nWs z#Fr>D4{O~~zT`y!9RiQxY=ehCc8<$umrVm}t!=2nhHd6^Cz1J5OHg_cUudZ1e}5GI zCnNU1;qB;SkO-X9UzW9eKOGY>2XH(_Fw?nws%q9Lc zF0ip3frwixb1rA@TJ1y_ukfKRxb(SD#c0ri=+T6KGNxvDnL`y!{R>WDrq6LDw>I;* z=u7RmuU#q!D@P3`9H!JP6~dWkm~Uq7%isPTwhFn|94= z^>St0{0ZJc1yn`G{bGgvXNC?iyI|g^fT2_oRtMZ zk#AF%k7iX0cWpNu5mVbkRLUn@{4@4NZ`>#25&U*T371*UvnusgfoJ=n->yZ4AQ{t6sr=!lW_HJ`>VfUH~YYrdd=PZF4)TFe$UBLUo+Qx0PLZopk$_ zf$1wyDj$A)k-i$BDu!vDO-@NxxR*}fw1m4Wq(WOLXyS_MQbMroFltJNz#{?mQ{{T4 z%&$RcOSh_L(NoCv}pethGi6^;E8o!=7q?r0Yiz<)S@|Cf*o}Zb^}K{-C!q3 zpb{RY6ia*BE^Uxmntt;6t?X-8bhEOrGrDD?>ZbT^xI6RgtW4OS_VM_ayAn8Hn=jUj z%?~1Ls4(1m?)3HjecSE<_HX8^qIpLq-A+UzL>d>xJC)#Phzy~Y6m68{&o-gHF>nS$kU}+l!0V5Gk&SP5vXJy5uEUO%>t!1S# zaw63McR}+mY~d7wI#blMRfkMA_R6b^{{DT8-42xeZ2n`yiumMQuX|_ba&GPcZl9{; zO_^8)o(S<_yNjtjk2P$48s{;htYzPZ`>bz=3I1M`V^bJWqdpsrKdnq)2rIJdneaX% zhXX81IS)-opF;z%tL3y3JN`Qk_kZI){>O4TIZGHMw!kqvv>Tb}(UBUQ41gwd*A)L^ z(e{#@28*)&Qv9>C@!D)w#ezdZtw)_&v(9QAYZ@#^J&XAqzjCl)>QcJ3moX*PU*fcn z^)K=e_TeJb>Q6EZZdY=0@KTOc4Oy~764-#NRDx@n?@Prb3iJCaa-FyYEay+;wG7#* zRjE=^gnMWgDS519O`Ra)rr8-mNeRv{k_dqJYvZ#LyOWZ_N-j>Ij($6&QCn}38&-MT z@HX_c+wEP*oJ29^hda-+CFstZan1Ge5vfg11oRDO;b*uY z;wfxma;fNz#|yskV%R$|@(O-0GYWSPGHoJ_IaQchTAg3dPTMD z4EpEmd6S)9&7#rj*iVT)HFO3>^j;ZfAr@#>hptF|s67lq$l+?mrnQ(A#gdPeLap&+ z2PK3?O1XSt?IYN+CI!#3GPcMNjTK}MeVoG-K6FYl&cZdgUgC%(Q0I(IUUm0DZ`HFt zmY{HlBGF-E6-&zYg}R`EQYQ~`dE*^*35{5dlAZ14{6ZNkW;NH&UwRtrp?OMGzhGaoI08JE=+aJ^0|HoJTwf=?}C?Bvr<(^vu;Vg6XOHdxtVGe}9AGyHnZYfY!H2+FQiZRq1Q8Aisfi!y( zOJ5mCurCyAG|lEBSx!FK^}iYI{Y&RlfqKu_1!2R_?$SbwGcc5W;9G zJY3ZQbvxK`oukIpX7Q58rbwHeh}ZXaKy*fCpmbKit!hJMmkd0qbIN2Po*5b+OU?M( zukQBoZL-GF!9Cz*fVEDnIyj9+lvGn1&2Rn9E!n#QV@Cx(dCyCin5KHLoy zIx9RMRowmX?+ogpmSG2nKhIb%ti=CanD#=1d3My~SFSc!K?)N>2 zS*Df>XyVX1$dB-H`q)-7Lcv6KB9I`&8aVODNtV?K1m`HoE&v2F^k9c?hv*Fw`)RBe zB@Q5zBVi6E%j3Cgp1MUDLNa*J$VMZq6r9PLzSS_^jpy0trjZrBVD0{)N7HC8AC;hw zTNIAa9dxDW`fM7bwjp|Tzi!1R4emjqvOHJUh7Bnc?6_9sAD|LNc{4oLvJxv2cDr9P74dZANjnI9B9c0f z$l;*Kf0hUj8deq1@u)eZ0f8Ue?&2jZa(QqiPYRrL&7_=|j4i~ry*szasnzY+!VNz( zV_dKup{eg0XmFi`wM#y&2RFr*tkcBzP6BP%#%3N1}H9{ zvYrG!l+QB~5@K-LK@QZrt7IU-W0`Y3%Nu%^v$tg9WCwSjqlDvimSYfk(;)s`dFF_B z`MVJrkUhNcvWyJCl8eDy(Eb)a*Z7W6J##Aa-fTpk8Mv%s@mXfflZcvb>Xj{R!OeHp z7+iLQN4=7`h4%RfnowYu-IQ=zal}g3#~WC&#zv_pyR4g-3KvU#RBq+BB@OGAm9@sT zCJxh-GXhIW_ho0Ti-uy8Lyc_WDXhzOWv(n1mN=Ska`I2#hknK)#GUu9w@_PUf}%!# zWG8&Q*i9$PF>&rfo#bwCTWZ2-3zwZS%2XXE`4bz9p3>vn8L4=C3wQaE%qz2fjEGyW zK@fH)1vP?&royB5U7lT|CxH?&YWk}WCLcTVZ=D?Ks(x&{Uf_Yq(Oe5#WW)ov$lrW^ zTIUv=#QCS~xz*MBPupUmwR78+}DS}4HUzwHd;BO*$SOOMK;XIv3fcW#ParRvf2 zTF$QhokBO!TLj4T?w+RXIWM(Ewc3f0Ygfu)j*Fm-sd0ib9wK!9F0*^U2R8Pjni@iG z|1!^av8dAVojT(_lP6vM)EA)_VZmF49893sjjbC$72S}f7~=!eYoSBOtwfssrGc}K z!}O=*Z)%+&Hh%K9PuD(-rt=Z`n(ox;R0YX9<}CaseA!n%bEIH{%0R9h`gzET`^_pI zyY51+@lvih6;xD%#~7bh{Nt#?49_e6z#alm94etT%vcCgW85sT0DL*aT&9k-~240OdFSH(~1G;Z2i})|ATJ*L#h8U0)JWZ|7!&PGWu^L@E->JMf{frFjeqw z{ra6aPk&@AWN*hIyJik6 zPXAI_8U;mCiT<{o_?JBK<5%qE{*l!QJNCeD=wSg^)h-;}gdGdHQ3jb`@ZZ5J-r{Z3 zf~qQwZIdBjwBq=NUeNL`?hv{7t;SA2ueW?W#=Cco2E|;tC&$Y48g!I`wY4f@Axhm8 z3271T&)ZB&&n`J^+O@x3h&cDGY?@=u;lZlS?6+&|NnXJAuzh!IJprx z1t;)&3X)|(tbZ{4>4kb*GZ_oa#ZhOdhiijKQ{nu1^*Rnb4O(9ORHqE}Ln8V_lMpB# zQ)D#X2&9=AL#FG`LQ{Sc30hcM`-mz8x0xHA`iE<2I>lrzCk30p$KxB3aXdP$DdLbk z-kRKc4dd@tj0i+|;>W4W@xGqVGpC|%>4u=0Yteb;@x=B;4`5AWwopx^W6;wla|fq% z<%N0|F%`yz$&UHr$)~yR{BGXjc@9@7dwytZbd(vhxCdC07E^|$OFAN8EZ^75qVh*d zn@A591|*L-HxQy6mYrTPC3**ldcE)THC#P3EZ1t zXAeFMj4NJ1O?Hjg$s?^rH-8)>##Oev6M{au(Olbom5LW;4}9K#|XID zqPm0(HQvSxwkAnX!=KgUMvGW)dg-(GDfF*WziJFY_}QM-i(DvdTL$pPue*JqTFkhR zS^DaG(~?~=HOi;x?0sk^7HW=OGq7!+vs8Ob&0fqDZlAQPilP2VBd5R;<_eT3mP=LCBqz|-sh(8x0H@4aaJjJI zAr1+-L{BqWpK$PA7U>y&oaXir&mk2M@RFlL2RXbYcNdH!nX2RbcrbmXK0~L2Z4KdI zL|n|(bwRUAoFwv(JqV%h;=4ncL~-0R&SY>M8tia!;O1HLoTXyRd zqk7X`!kvhCNq{k!HBw57`U;&hpUs)VRl&dm3?E`zR5C92urIP{e$fyoI=W6Qm7z04qW=f#R@p79p!BoJE9oul zWQ7a>@Q~FLM_P5AF(}H;F1Lo}0-}@fID(OJ>Qf>*A`u!Dul#DFSC`to8b0;~mgm-? znW`F&Ud~j?mtA;7tg~R5ZK+ETBXYjyCs5NVvY37ksI+w+g-|CgxoETh6lR#qrtKBI zHN7YkuZplj6G_G;J^=BvGK^20!k#nRSJ%Z(c9y>|qnN{c2-nBTLZ0>Y?r4BY0MmyU zJL0Di5yz{UPRN35Br)}zh#a^DHq{5818(hq zYP7o|OX`5sG?&VR0U~D~m5Tx=PDMWu%a}!t+fYw(nD;6ay1k3c?|w=rVuv?s&OJ*M zN1}|!R!+@ny{RUAqdVgC_H)dJI16E#M_L)zjd*dwG=-VAS{gG}j0V6QW1eP8|A5Q? z*U{@(rF%e}-5u`Fny+lIVNDj6B=IIH_pRa{%HhIQ54EgFjPEcJsx8x;t_)J!7!^64?!0vk@t{^ z2PjyRKMDV7^e&eRpg~{rEy7HNT0J$V*3NOf-<;VsNwz=qXEzl%L)FQceYbE?dtX{q zp_*=Ge-F>`j8fS$RbEltG8#M4hGsq^yGB{n4>5JoW7cQT1?*T!^NUlUBU!W$5&2Db z!Go<#{hR?Nsvmmi`1~vFXRhk0S+nkDH$^z_6mq9_j=G|!bW&65C52n`yM#1SPQf8d zY2~NyLqnWgK-zB29P)gn@P zRn8K-RYIxr-735FZ0d}0?GZ8Aly~dck)?k$G$%L;eGy{5jWAkSY!=$69N&W$Cw0jV zR=GLDH5k?5G}j;Nq9oS=lG~mXM`V%1@JL6TC>30tzu~V)>)YLF72hDO%gQ?618@iW8Y?D)c zhgN;V`CTHtYc_=312%-(!c}8qMTtTbdd;Bk?0r6qnp(hp5qD>z1+l0*%F@zIhYj+x zPM+b#I`lCqz}qIpdCl;-QVJWO#RveD}tzed_#?4O?$wVQF+)de>y z^)4K@7TeFy3;IjKH+>MOm}cZqwm!3 zydTF)I+vyOOqh@B+MIn(J+o+zW=-PuyVD{Ndiv7$T}ba-KFf#ZFm-0d`5AMaZ(`H4 zp2jEfa&LLtY4ry$ROXlq1U=BzB}F#qG&Nt{Om0~ef%IYZLr3RHBHF&lqJEJp4h8e? z&y_;!HzqWT;0`Ak@Z8k5dha3MN;3qh&DDu>mWWq^yYXX6>Y`OM?~;OY&hsxPqEj zquwsI&mNUNnKa}_S;fM$On27Gik5Q{pffy;k4oZuJgdA*f@!=5Mx?u&s@fHzj7d-N z7o^~Qxt8vPSXkV%pAd4{H@u=7Ns;v!mM?PIZfFcmxC92W5;A<*J%;&nI$hBNI~(Eg zFas}N@3*$N5uV9@+Qpxe6DB2(#PIxb7T2Fs;@Df3YOJhw-mG4s|i$aF@eFMgO}z$Whjja;jm zX%^ghvku7cA{<&WUQfk%-af))CI{+V=k5NN^^A`q$x%Bj8F`OaMlPol>!K$>k(P=0 zXJ99Cs+`Etu>4e3(Tta;zxCfRfEm5o>`htuN{Cb5$;R=3#A(Pg{$+5( z5a8i<`@<8}<4Vb&6W!&owP*C>2Z{0!k1QqHpA_@;{j)SZI__WpwH%7_?V|rw zkyicZNo^ke!1x1iR&<|lI2LCVd=2V-k@;9f^d_8m=_C&cw@=e}raeC`n?XKmWoEsj z-a2$6td`r&97MKH*oJz&#Zbv6EwS0h1(KN>|K9rS)$DU@JqS1v^W}m z97Z24%kplYmD`2N=Z>uN4o{8G9V-`s!c4TR%X{+O4@`KU<}hn%3aq`Bk(OVJmi4@t z2uV$<-Am#AQ8xu5VwM>*KKMHAN{b9Gk~iM!d8; zGx#L5D0z}!kX~gEVbeFH2gcyWZh_18zdIj`Dl#TNH012sgxER73qE%+BoV7~rsfz` zlu@r5b&EH$EMem9?AE+UtJO0(Bs*BY#u^puyfyI!zC-1fuBN7<>CC%`xLb6IXREf= z9#ZQH(#$)rT=2H^E|;nc#133r!{AG9DqpK`XKe+AQ0dVXU#1556vX1*o=LMtR`5|s z@VKRg^?UeGHoa}lF8X*B^3~+^me^-sv^|~ti=^=%9yDU?48=`C*@_E>B-|qhnq3=2 z5;3*PP`-w5BEg?5$)7scY3fb)s;ilF)!P%g?(J%!s`>PVWs@Vni=36d9{6~y6=eGW zofVg!8QHHyjw;BeT(Y3BmF1Q+^c4(FKMB4(T&n${CEzp;MCSD9_=ek9!mvYZ)C(fD z7nuzMz6M@vXA&{4#IXM~V|eR$XlI?X$d+RWi5!2i3&tvP^3P{GFtySRN!4!MNz5_-I8IrW^Fjit~?l$l}5f zF0Ra!S0W;kZCA!kPxV(Dqf9f-g)Wa3L7ZBrM)!bNzpVJKq^`{^Pt%C9=j*HYfE$q( zkF&k_+o?W9U0vf{>L*In6XV@`uhuqb7CTdQZXPueK_+CJuAb@UY6rxAzT93tpVr0h zZJAIZP-LFk%DUDY-k_OZKBs$M3;C02T*PXro}Wh9q{K|n&v&jaH^m3Ci=O<=3FyeHx=AuJj->r#55`Fz zAM`%_Kh{r5?$Oze2Hmkis=W9L!P$@;y+oUQx4*Bi6u&>_#VlX6W}zG`xUfXO(ydMB zMr4A|qrz8E_=T1(`Hqf@Ps|tAMTknA7jh4^UU_m*AF6M>{utQ)VGB~(gr0lOol?w# zY0B&#^L<5=cx+}ZdbE!2)fit*f7R4=c7C|hCY&8n5G5K5(Iot>_lkV?u*Ycs!h-6W z0~$RO(Zq}oM4x_NWlrW?Y5bMg16EWTc@p%8T6tCYSkJpur?QqJq~}g%Zf1uC-XrCv zY=o>d-i-W}1e|I$GYH-A`Wfu}W5 z-QnQY5V%(-w5m|2lcA<2mig#(w@B#-eou8RIm74J9nf>bd3G?>O7f>R?U)JIiapPT z_Q+d~LmMao(~Z)G;29ZM?-Gvqba2(w7KATJk^gCw9yLfV5?dd*GJjW%!L(VjpFUI+ zURmnEfOvVRCLVVf@Fuo(A|*1sqzKfH%;Iz2W@*rVIjbbhit^2*kMc{jh)WkwI zc4S>+;IGZ3?%t#mzXd4B7PnbfdwfKyqZepj6Phjh^8v=Xm4VM6>XK13IbrhWxqw-u zH>fE&m#I$QV{4K-3(d)z%q__`Z;A{!CFTkj+Py^t9`g~(g|7MK+BqT|g45Ghz6J5e zybp2eI|6f6#O&JTCn&A^SGsVa!-F;P%Xt=^D?9ptlwZi85p)MFfhpFr&ihR4`CAuJ?u7c z(Mk)kxoL}y1vh;;K`*1Zri%OmOQ+m-p-j9%CTg!2r<3BJvLKdr>vYA?OX?-RDIIr{ zj2WggUw7;UCE)t7#;_gVeEQS_|1s0`7Qn#hc_(Z77s(J#!Cm_s?t@@>FI%-|*?(lZrDiNtiuj)5Z7X zFI==4s~xW#R|iTj_Z%;7mD-u=Ro=xQw}Dl{w+_4;DdtpN1i9*MmYWXgPaKv#WQ~iX ze-`5uo11y4NDj;H)c zd?c-)T6$`|Z;}BP!0p{^43=^QL;IJ2Aj$ zkLjCgl@ymx^l0BnH?#>X&js?(q5+<)@`qH{-~Fh)ZiJ3s$zGP1?5hhh3n^I#%jTwX z`*oc*r}x*0n~K@icQP+DyzP@V(PbN@xjb*>{K+PxCg|m zq$qQ2uYQ&(wCnHpZ7$Yj@xaN+}XS=^0?z4 zLL@n}=Bv&p8jM`Mup!u{j>;}qe=mtKCQs3*3^+gHGGBvG?~0u}?$@>z5ZSQvX2*%l z-B?DUCvBDPLR@y}0(dN9Dk!L1Wdf$@+YPDL5smJe_R-N(X8YYls%ugw;l*UP!~NwE zts?hn`o2kxK)k>asm`|x>?UMA#KmeZa_#H%gxvIHu5$X`56iKM{RIUdQ>KPdYS_<@ zB`l!D$o;|t}(3b8@2R-`MTu{Oa-&TH#z0*JalVHEV=6y(J_2^aul8-(%J$S4{!OgI=by@y;3f5 zlE-^mOYi7jJ?xvC)_Eljl2wLKVMmjuy`WQry3HQT>$qJrg6*KlF{YyMoEOr^hBYR8 z43WP&IivX{&{pfr44IuHQKPb|(P`h63D073wgdk>vm~Nv6r(U2bgarVsE$iGb#>H) z+apD=PZKfp#b(jqdC6tF+-7-pJjxLf0x|Exx3WS9v!z~14oRMjJ?2>W+AftZs{CZq z!zBxegfb%Zb>zzwl>{lT`PU6*>(E(+6Qdp7w%V+(MGkR|5<-06rWB+}iE^-?_9Rw- zK>oVE;jJ5*SfQ!v+%YEIlF6K`1qExC)~HCm6u$;>&V~^CFWXrNs*OLKQWPVTQnIzk#>L*6e*g{n7d^vK<6Sgb9=&349RjL!>v0=P zsaxq}#-i>#!y z;J?#^i*=C>H~zS~9WKNa)MhPrz- z{yxO?Z|)4Z{(je3cTW(~s#$U-n709Ikh96J{m#7pE?IPK8{*b$3acK}_T*cdcdw*W z6nI+MGj+=dZ$aahGT`d|h$^1458$LYqL}m@G&xIfF!lT~&!)~vvH-TrjiFAZB7)B- z9GG}*D5yIk5#6YjGuK)}2T{@92&+Yl^UP;$33y(g?OQzaPuiV-IhmJCc6&F?v(w92MrAyyN3F1Eo_x<@{$yy~qzY4uwZqvwofd2pAaIk4| z!pLI7RFiWM=uR*QvMi@%y``wS2Lye(d^B3qk?kipQC$t0=;ilvv&s}6jv)pm;_ehC zjcdwtK|+~BM1;}%R5pY!q*4$nz7Gp;)hh&#tk-+xUhz7MQvHOIf-v@6&2cniys~v)rFRdV71RU76`5UXH4J zd+1t5%PNAG5wcIVCYCm4hW)yM!lksrih=?)<;3dhs!Z+S>_5xY)_k~o*EU$(bhLGq zy~BOM?q~79CUtpLD_}$=p{TQ8K9s?#0TXRvFlUl!X_wkqg#)D7|Ec;?=10Sr@S59B z{nBbygZ5}c6g+?R;<9pm$GKdT0TYuvJP+XT;kk#Z!$#bG;@b%#_?L!*g$vqt}E)-wwkha38&C{7p{2nz6{NIdCw+@@FbW32;4Ddrb}+ zi&@(K%Cu{m5Ajy4Uz74De*$qVYfzirWsl%%U7E6=5DyCu>sqZ;b*fik1A{FdHL7g( zYttw&K@BdVM1Fp~9-+8{>8oU>&By%<+HosBZIqF+;l{m+frxq`muaX6R-gi`kBEjL5Zy| zg&UQT-b=NL%GH&RsQU8Ocf}jM%7%U(zR1j{*SajZxCg*?^7GH=edlLd4bATX`p@qH zCQ1pj&x2qh$byZ)p=Ou9?^EE3lSacrR=>sX3BRIQ_1xntQ zpiC<`J79s5^=$Awrf$(iOgp!t3m4_J#o_%s&x^ki4z=aXEiT%BNbu$kroUOA>s)j@ z-uhE|?-p6Ob4E#CYHXDMO|I(x)O5dly--3P1@F+2Dqmfh;Guz)scGY-DkQw!&5Q*- z=HJpRKOfR8`lFjHGgrD}X%p%U7?zU#y43X})u@DqUp!~L{k1udvfsF3<^0iqQoI5U z?G@QwYCN0w9E>(pWE3(;)e>k#*gfM@f6jK|72~Fok)Ja2)HWl-rvLg!`8N(B_E~;7 z^^nLBWVljFX_+iC`cU9c)jI6ZM02yQFK5EovLY`+RKq3C1wn)Nx%6xVTVc$!#D@E3 z8vJ_mT$k*Zj%11Dk5aC82VxbJTpiIDJ5aPEB7ff~+0=FLXU`a6VA>Y#Ek{CkLvxJ6 zO!r~f>$kLQ7a{SLEyE5-=f|Sp@7YQ&g7GDt4K$xNa<5gwGmAIRzo>97OkxoR+XiXnNiB0xOt_8&NLc-Jr4EA1%jA10tHcU3b|%BmPcDU~BL@hVblhsiFGwNs2=VLz6K7KWq;@Ey zrSuLI+sL>y?)2LZK_7=ArHezzNsSzc&OIUeHc#Mo#gR|q*LqZ9v`d54OiBkUBBQ5Y zR9u`u!)P=046~fdllF&#mYcf=!HcAB)~DSVQ9Rm+x^~ScR!@iBog9YlBssvGD&pqW z%44O*h$4bQ6KS!A}}OfvrQvQ?C-OY{J4 zba%EEm8>-P=@c*VQuavW19|GS+w(${gJl!(q|@_!Zx>QB4+8fI=0<7|ZIr4?!h&!U z0Bua4v%30Z{qP|;?=P2+@5?v+%r>s+rFOH_KFne^I6la~a9Q8P?UioOQM!*VD`cHs zx`gJnR1yf=jEPmPoYY=GIebl6AAXu+uF#5?DE#8eMcK5c!g6JB_>S_f+|7FH9)R~S z-y1wBY);c8dNXf@-+jlXa}GFeJNJuyU^l->w0ZU}we8Ir)?qa^^RuQnU`4PZ)v725D%CN?8g7ZC{E?a!bQwnRbC3z4Jd^6~DgBCf6Vdw}(x!+JqV zp06RZD4Z!iu;HfNVBhN5mEsS94`YDEOLF9TS71 zD~)9^V~py-Q1>|9(G$0wRgt6HqIP-z*(Ol!2B>vKUuU=AGgG)y5B@1B@&V;iPx!l} zKMsFMdg8{5GQ&-OHx5BfRxySs!kcW^tT5}llrGud=FI(;|8AJBc3C~H`*_RlHI45v zG9cFUL559T)QaZ%wACL6{lBbnYmSULmS5nWXVI#T`MFV2nDJ(_A#Rm)YNHh3aud&L zTUOp`S_EFF@lkXJ$-D($3(f}6>i+h=BfC=3?vQ>o%8V#+7O+2wP2crbq@&Iu_}RkK?WZ|NT~cjQyUVSs z7YxMC#PpFHG;(N&lQZO@!0l_7{wq^$G<=6kzksWvSo5jT&j@zijVt{3bd*-AI$B|y zF_esK@@G)oi7q!<3;nFyqmJEBgYCH;D$vuXsaMwtQ}N0*4Fe&=Xp4f9I-?EEM$`C* zE*FY`rk%3$=XJA7yMg^WlS#-PjCyPl=mi7k@4D;6gfIJRm~B6FxTe7^{sS38Q(~+d zn@WSkp$6ZS7W{5y(Zi<|S=4JMT{FaXRKJ=$#nP*&<#K`gs9{B}iLQOXoN!)jAzaB2 z(N)=tf16=6BRana)95v3F0p>iGUv4efO>j!>Zi=4>$lFrP^IY}AI#s1R z10`gn4b!#o=z(r3->${KJtUfuO|ICu33EmniZ)d9ALcT~eDnoB4jd|MUW%Lr<=6UV z`-a=iLcn=38Cl24z!BgwmIACPzvq1%DNhsH0kb=L3(#mZQAEH;gIoa-Rx5VHDwwca zzxT}5u_PZqxiL(1x?r7%FQr-8A>oUv+05>nuq`!jqKQ8w`I^cn3@k~vPCX34--3Tw zN_a%6gv}Ny+dA?75EbQaC(6VC~Twt7$o% zTPle+oauWC!elQP@HJm-UH`& zq~xgv?;5*_#60T4>cYcA4FC?lqcz82mHAZ(|K+|4EZo2cd}+h{0be3J z37lszt*S|9CHUPj7T~}#eh(0Pu}IH~2S%f0zTt!ggY#xq`>ybq9Lpy|D!XB+k5I?9{%!5i8e&xMVMZle6x_xm9GEO zR&ZMD3u~9c0`E3eRhRq_{cfsA5P)hJ4aTy(Mw5~Ek93SG}28xrn({A(e2hYd0iUih;QSKpcg zr0f&oDZ_kd@gg|XYG`pJJMQoY(LEq~>>e<9N!}9R%f2^v;}h`aXkJkN{N2|6#K+bZ zmJWonRZd3qAWL&vCt(-b@PW1|o=K*g#wq!f;_$}oSDfY^gKL_fLq7C1o?6BRGfgEP zpap%wF?9Y7{G*f;#RKEQaxFfFzJjG*8sUV94UcD~3F+?imnRN8s4V4k4ZnCMHmeZt zFk5(agJD5wd`pz&*t8gj*_9Ae!Of%M2_3O5ah`4=oFRp>c(FN^KCF&il`v7SAN?)S zX?8Y-dqzLwaSGeKdd&?v(g&yNMV+}no?}P54=*mdHHB$U&sY1UzC0wyDwk$#>!7N8Iq8Z zN51VSaV7e7tfP!Gd1E7DRjhBQG5D@pc!00ApYvAm9j@(+-5;jApl0PtzAmhyv`6m( z^p+8r_o$frxyuFjPDSC|?~J#P z&p(DZ9$eKNB^2S%jCVmIZqN*bzy)@a@mc5hfMaBrvdP%t!``=Mok{c6sO>*bq&6Uq z!szK919n5=lTy1giwbXIw6A@H>fo@E%m(3)QL!97PX2#D` zqL>tQvT<>y?J`_H!D-d%R|D{=$(iCsWSqrVbUI_l2EA2PuewtXS#^cRwt-(v&%(-% z>FVadR_f$$Y_{7^LH2J`k%(+=6|J=D>xnD8;E?**^=&VvycQXB!F~c&+No`mhTk@I z_kh+54T#7>(g|iPhOpxq{ZUJpS#ovtb8p)Xlm^xtSM3?2UF>D^O#?nBY^JAHJ}$nL z$XGOQc&GR(;3WRQ)s*v0-+LD1E>XoKYCE;Ld@IKwX3B&k;s;*`ujw0w*@L(I%i*Cu zK>e}V$|*Kx$LLo(euQ~V@jmT0eb;Zj)?)7(bk3jS9QgvFV5|6JyD8scq+nA?Ia{Gs zMpZr$cBu_*Z+E%@qEBZRA?2s>EIwtHT5=S(UJ|^+*DAE&v^>9_pf4XNZUUo{(!l+} ztF6gOJ5d_X7asT$nN?6&kNYf5wV-yOI5*L>uw3u@u^1xVr%+HEmv7k0_m;9)+On zoXM`DQ<4Pf_Murad!8a+RVojZv1YBlJp_aFuDVEqdQF@iUtdrCR{x9|@sb+|q;VMO zBTr%Yc9IAqJ|x?KdtxCC;arHWamNJSk6fnw@o@G!-tI-K%Tnvu5}MgqbDqx&;}1|r z&zvzvuno@t3kRvcEec<~5JRQMQvDv=KQx*DI~w%k1eF)1npv2Y_u8(1_e3^*1VBh< zx=mQ%Gy&tIS_|S~zjK5(8$nUVhOg|Ym5EdJN)489H=UfuiY8Tc(d`P&nI&?wvk;!K z5os?X+5+ergSmG^#oNIn_d|j^?2n$!R$e zp?+K0>HEH5PHd)_1Ca8emZnS^Vkc46Z6MZmU@GjCnX%N@svu=L(vOEO=P%eq+v|CT z(IQzClED5nBt=M()gQ1b(V!x(PL6IiXXL3^@_J?mWIP?-cg;{WXwVa(%_sRr^x-rV z(Jw8%;zcWY>2PJXqNE#r%|3|2^2}lrfv1U^hJP9{=~-W_Oxw9Br7vxO>k1E_FHgvHbk2C)bVfsy({^a5`8oBb zbi_QhDpB<@Cj4y@Zk68k%CZ=YRC71U>yBEVfWlfkBHKpS8>XlX!?Kg{)@LC*9um&4 zxmnQ~RT1zeBw8z?+c_&vRaK=Y0}IU#Tr$>SPoNOkPhmSbo-f)FF0QH$B-hNy$V;E7 z45KHDp!uw+)Gn&v#3dA-sH&+;^i;!M*3tq?shf21&RJxY7{oW@R3#5|(^lA2ToMkU zu&$iXx8#h85f&nrgKlpX+KI~mf<#4YwD`q|yQlnr44)9*xtDj!WqYKqf-15@Qg#)i?_Wzw5U$&lsLP5x-)aqy4T=ZH2(~ z>1TvNbK%m?S))G`JdNPh9UMI00q;8{Nae6Q|X%Q z6Sb!ljL%MjU`6wXz|wZ_0X1Ij-tLs(I1f$unv{)%TTzcpRYV&8`{4 z0sEg?OoB;NQ+p1+!yZv{RrBQF)qD?$2R!)I*oFKPg$lIxA*C+Db&N_85ovh4-fnGD z^1+|67`xR%zj+1%nvjIpz(j&;gS0!QBS;;BJGv+hD;hkUQD?{qOgzbIw}lu5~}%b?+Bwp04id zuIi`hr>p8$u5WsrsOpcqz+&>s|BRXK5_sua=ksOXL>0Vy(A>NOv`LSPBS=HG7RU;?jtS2^Ut zSXb!Na%gP4K%(AxSLp(IlLkEK>o+B%rN7i|TKhB*2~y9N(nM0soxuZJuO8SQdj_!K z-TjujH!LjXDKWKj(chlrUYxj{2q-@741bejSwtNMmBW&eEyR+tQ6{l52@|GKm;lzn z5?DfduLMA$&-=OFiF*v9di}Tg7#|k)AG7lR(UeSynPM@|#sM*+zzcQF$eSGhQP(Ed zQ$1~G440Pu<&$OHLhH5JX2rb876u)FErhu$>pb4DVKNNfX!_0jTtm)V;#L}$fj1d2 zi9|cel(8%~JTo5_Nt>!UmH6o(Ajuz;6+?*?q`?_F+^fV%*XiEcMeVD^GW7=~?}e9b zm5v+i7D>6rVse+SO(>qwA+{qa$ySm$BuOqy?On|io*fxi?h*s6 zBqU0MZcg04k7+Ugsu8K9aA_#~2Sp~QGL zpA-jGpYP$<7I``K@EN$0MA!f+BdTPTu#%{HDJvi)uy#Aa(RAMM#rMT$hYUj=%6@a4 z85eJ(O55N3LD_fvgEDPCu99dL`ZB4tQUkeBq$GU0x88&*+tb{AGi0W8zGQy*7Bjp+ z>Q>v6^%H?|x&#`p<4`cFD84u_R?a=NN1vVzYqMPW)Vl2v_lWiQsUl}+sOnVsbkyuj z=waJ}%>?ob?vv$Jkt9twCL}(8Ke!$Kav>Tcx|)`z%pON%Ukk_XR>?}3U_#XNDqRJY zEEJ7V&95wwkUKd2C!BI;YaemW#GoLC^r=g2T|Q`K?nL zyNFIMw#z`_Tn;w<<*Wo|S21BMbaYOIppvzO&%$cCH9@L-Y%r*zE&NP^3C@Ku#!<6SG z<=QcaIPo`K-$9d?HR_k+S=f2ob1**`MowLr@;keIVibKXrLHm2-8-^ck7V z#}NwRtKIcO*~es1jNd56u*Y-Sz6R)il5NFLkkW-^yvDmd| z+ITXCT{~bC0%Q0r8j};Kpx2)?gLoDMp?F!Ufe`p+yWHz3*ED1+PT}&p_RH{;dy|S> zL6-Mo{x`auEjjvxW|8Ma?7J|0xD4%9h>cJ!Ope$(3?cNy0`g^+`C^ro#d2Y0M^JqC zifxc*X+`CtUKR&im=}i4yRr!}cZy(l+aetox3S(OO4rbe9eBv-aB{{RzP7Exjx*Xyndv^ z=*(o}rc-=C?lYd2hT7w>=IV?~XW;A-iOv%j_IxN?(p>*V#BE~u-Q5a^hD{}p+uhcL zcAR&nEX|b;=BD?Zg)L?*N$+MGeyq~4)r-A3^TY2C3QLM@Ck!V47MhVO`_uLpkc-u){TY!Yw%8fZV}uRYRR1PfJ4GAESkV$OME_H{ml=n z0hLtl{e_Ury2i5mf*8tz#>B)o!g{^B_%0u(SH8q@jnW}5aT_rg2iEPWuh#5YOTb>8 zH^Zl^=F$D9+In8^*r}?lcV^pjzz4!6&%I(KW=mba&a70nF^^Oj$~Mn9Ia|+8lwYP* ze`#Y}xP(+z>cKIDgwHC%&%v`m_tNbc6|ZMz@wuLQM~}g2Sf^*c1<3wK>n)nhg?4%d`ToX4Lo=CUNaia2L;x#BNt zbk)_DN^mBj&1NVA&gGu0BjtAN%rP+~+zEzELt!^VC zH%~H%>02HPS|F_QBQE&A5B1k>`DKOPo;5B`J-MMgxfFe+Mg*JxeF3U}2J9e^W?rSX zfj!-+x%kraZiA_sqW}gd1ikqW4oc|C9YG{IVP4km_=kubJzAM0SV)GoOj9u9^ohF+ExTlta zrQh{tKi|dSB%sl8%g&C3YAU0ep6~^3oN$qVEm>(w15{KWY{Z3VukfFdvCR_O;@4e~ zGA9#=8vCrmM4y?uFXLu0Fa~%$iIdZ$okKgmTWI`mmHQ? z4g*DmB-*H(Kd=RVsN6-bQ*l$&Ge?ReI`Svmm`iR!maR?o6V)Rjk7v7}^#*F85_TYC z(wO{BunNPwH|9!Th-uv}``!F1g+O%{qSP$61L$IzBWGS-r@;(EmyH)E>D3KYU(vBu z7D7DSg~kqb>R0wS)Yx+3;jgjP=za;>iS}b)G$)KrYYnLZg>qA}1sWld+apm5;?L~0 zOXl}?>H%;mHEDDPa@X3EVO2(9}#=B&Lm*DcbVEz9G)r9r5OzF5ZR;?!F1g3JH4 z{tLCSd-l@;juBA5)rMHVG~lDzc1XESKt|+T|9N?F3EBtf>5xbgf+SJRB!s$qkp~57@Ufm)h^V7)kZ#D*FnUm{bxn!VVsDb4iQTjZc34 znqk=)QY_L>Ac_KL&8V5CR(oOC91_VhZqPrzi7 zKvbsff)t{u4$&Qd=IB|Xrx?WG{3;cC_8Cf@_fem!>pz%ZacjW*PkUvd3>!4FDb^A5=^>#4wFa9y5C8 zFj+7P8f-?op68n4!T~&KTmsrlM>bf$$GIa|NvT;|gNmX1^y)iPM{M3|Z+G!HWS{?# zMXr;?65Bv8!JoTBWR0xe%-FoGBV(@jz%Q?nj0Sqd$SS!sgsA(5jACU|Dp?p|Ck zB!I5f{pPjsK_kAq4a=>l9lNz=E;$gP!$-gnynI zzdI_paH{SnyYEor!0bV3Sj^9JuB0O#o2kv@HjP)ZjjfR;zyp!zUEjKLkiDa|?^JPd1-m2Gy_@D6L&a zHHu0%`9Y}^0A-7?Y^SuEvl5f~v|S-Vo1=H7jk7Z_*>e~UJz07~1(|-?OfeB?&(>K1 zt<>$%wF1@X*!+C$BF?Tu@A{DtM?tQ&r<5e3rm9i9be%wRu+}ZuWgm*8U0@+7376Vu zX;<{ahFz*~ZUNuN&wryUYUy|dXv>fb%9q7DS{~2ymTJ5hK+i4mO`3oC-K-qY>GO%{ecMNI^M?Emn6iu~T&<5yPPJ@`h6(DRtLE-vpYdyB4HqgdI$N+R zs0uxIDqsHK>g5W^SR$wq>9^dvek*O68#$IAmc)y0?*2ZudTEc@Xlpn3soLa|G+)J5 zG=bz-FtGue-@62M)tVE1(yFs<=`n%FP6IkcV~Eb-&6fv}>bv#>1lMIU%`sF?X%hJ) zp1+EtKrSJha#Oj50uWa374R!~lXJqp9ZyaLTz&AY z%8#k6$Ks5l2f6Mj>d*#12y7^}+a>i8N<4+HP*0lorY{SF!E=$K$k8Q{4C2;MKCw^qJF$ zX9%qJ(u?6UO24xYLV~px$eV``-;X@zAR*~hd%vn)Lx4A_fNHt_$tDP!yDKm|sjo3N z1WGEn=AhA=M`9;@ji48!Q&?o#Eh-C!4jRlf#ALwo1RiCDFT4z}wY`9j5g9@~(j>Gd z57cCd#pW7S$FBOUR^V}R`IVY@4uCBoUsKO}q@q4;8MSrm{Te4eX6!F0!7fP$ufz9i zBx5@^oV!_a&%jG#I|+09d1HQkP*A=K-)BJ{o#&8?psrz1cxa;-6e0eeNCJ0pK%a%N zfagUz$2nnEyE{lTevk>VR_7Guqb@vZoi2RbaLR(M+myU*`=MI#y1v!Zarv@TQw6BK z&Muu7_hnUR_la)Dh=$%aVM!i6{Rhxan}{`Lc%fs+lE$I?5p$-YDSuO9`9YaZLP5}K@1?|uv&Zb1aQCs>GcWyS)*fI}*#%Sy z=m-H2a*cvP@0X>S%;-5?L#_4^x~gD@Fw5^Svrbkex(-k0=R(P#!b7&0X1|c!n;8lK*^4 zP7C?kVD5UGd6PiSlrvajz|JMRJWhD3{d(S!a#@BIPT!6u$@izmpL?AZ!JI8w_dF+_ zzg@no$0@UJwt-SNwN5O3n{X-LFHW36{u_=REJEa$;tk$nppu4%h9@kmQHNIohS;T- zb_v@Xg9BVlaxa+GVk5;6%~C@s%ljHiRk}%o0vt+vgM)7a5X7Awn5;}VG)2MtuPGgp z3}TG__4CQ@i{O1isa;GVoe$_~$RJiE?C)QYgy{bvn1=9s!cktm&~^3;m}8fNfq?F= z6y=Dn4!tce<$_R9%6tg{H2&)X}2p!kvu#twR@q3S(1sSD@AQ2O5Q=)Dv9_pe4UbF@H^n8&_31 zuVAC)X5{0$fb}Ld3besMls-tIT zu6Bq65WuN<$8-`CdJ9Z4#f6r^~+83`T^k%h3da8PVz8}XGcz08NOUFVL+ki8OpRwF_fo?&p zqo`zMmEN@1xxR@$~lo$ahAGV-&RX)`I8#%--0m#OHrd2n34TS*XUrnUAx`z>`m? zTlS0T+0J2yHJiil&lh_qZZ-(!4w&&(>*@kU$nNz;*TdHb=V9^HkpjQ4BlwAxEfp_ zwk|%{|C+wbG9pqn9i4A?5&uvwr?tpiUV~j^#O`8uQtQk3M)Pr*J8{n176sc=29uTg zz@r1(>S_G^a^0?NE&&mx(+=YGneRM>N9Tyyi5=71ZEJ?c$?AP2!kGK_E#%eP9HA71 z=l9{XpX{b*#S5EsSrPOlKfFH=I}5c4V)rRN&0Oq-dmyJrDC)5wNv?VK{%fg)nR2PU z*KD*nz2!UYkR@BHNQ5|zuAiFQ=#f?p*GH|Xrec<~0K=Z#r&=QfLB?3}3r(o+=h6X1 z3(s=*M}zt>a3=nBaO3_cRzBmwUoh)+QZKTB5cX#3ClOGMc_QMnIW*aW8|Ee zs`df!fVLsimnA55QWQcF9qQr=-{h}ld1yzkqTUzvKjVaa#v*YeCoOX@ShuFlkk93h z>3)k=(M8VvC1&Qwv^w0HBAK9ug<+G{hY({cWSNVDJ^iQhlNGTNefFl{skjZdfg#QQ zo4E&YYN!!C<+!s>kpb~WuUz&=HHw2C`UNP9(1%L#^T`3)P15GH<`AF31YQ0|DkN;Q z=9p!<_d5G_4t?wR;31iu)*Y$8DUmpz=Co}g5?y0UPyZ(`-L}onOeV2B`Zd+9?4(`_ z`$1LZ5rH~ccEJ^mgBEDSP}7RB!#jYY|L1a}>$#GaOs|?T(&7uTv^tGw>q2fEW*wnT z`t!u@%uOOX`|Q^e25(2yYhFPZ3pxBOtvddo$PZmgAsfJV;F_HaCZ5T|CaNLwT?Hqy z6W^rCVd@Ls_=tB@gXeD#H-Gv1#jBC^%E{~NJ(i?88#vQ^wHv2s#!Ph}tAE?^oxZs$ zDY;y>wojh!RZ+>M>BQ93xEvmd3NCz{q(!iT1b4OUgfr$R{crR=!+VsO@`tPnB=+9#it?fsT*NkMO)u_?n(^JVtA za7#vj3ib4ti6S{Q8OI+vTlrBcVvub?v|v7MSSroX2XEvV#I*QX z4dom13r+#WA`2?ILkMHlkwbSRy8mk}+t#z8no2cZ6T6l*xh{uJvttW5|Hey&bc$H- zXTO7C*a{WwOUFXGmdCQP{UlcT_V8!%Ln?d|Kuu)KwG3^pQ4&t7xOMT~&1PPHI3#PD zw~|uBcvWtBhcIRQ^Ztakp z>^a?c*T$b80mqgzhvdPnB`nO*Q}w#Pe(5FoPpFKIQ+XZQDr`~e)n81dK+M6Ij;{^B8Ps{ zy?UeHg(l5m6NWX=bPn|cs}Qiij)^-Am!6sAT&nq<_QqQ4vff#Ws!-BhCv*TbgzZJFDF?Hz%{u=ixW zwf!E#SL#G(ZrJtUOh+Bm>{55ZQ!pRp)n}KmIx%$@w314{_O~hq)a+XK@G|qW_@2Pb z;suLu(slj-cB`Kf3(KtC%)dz+OWd+2^~p?xW~7INmm%g?#}90+uD}1+On6EvVaun$NLgZgEHbbDr^u13l^M?fI1QyBjYG_ znh}!CeZvpCi&Pt={#CMR_a-e;YFA8?rlAJy^aS_5yjR(x>se8Nx7-+>(vh3w4zWk8 zv}j7~pm1-WTAghMlc6-{zVOz+gFyQ`2>+@Tn*94$mM{Z!gLcO56$N3@fqet5#m1|? zn~=;y?g9y9F!bxmhY-HGzP|*4wZD_4*qY7ly~&EItem4h!r$K!{iVSLJcRIbSJ%!6 zj^5a6#;CV0pMx!?(#G+Hu+C1amEPK1*{-yV zc#qs#4G?%y+~#@kV&&OyE8>$%pmD=`7t5#OQPjoa?I%N|4%g}PR-piYkP=0txl4I$ zTufU=V3cNLIB1%?oY(`?BP+jexEk?Np!`MIn5ky`b5Lv6D0k$~vggI^`-A@522OYE z@sUNFztc(WiwOz`+Z4);RqhDcNMG8IS7!1A?`q)`a2BT_)-UodHCdJ1ACQ?H=uUvD z{)vylGXl~YU}7vg5h6lCyN!C)eN#_fBBI;(6XVTsJ-s!#XAb2l@sT~ogo;+A?trRZ z2B@6k{4jI-`_=bBW-89QsQMf+U04Q<%l`1hX+3McdSL;i`njK1subD5K zH?O!Tg4QOlbu+zHQ*<-p&6$@_Sqgn_e7=0zEY_NMbNJz4`rOv`MB&~*EnZNX%$;n> z_El2~Y-vJ8%qc-;*}_c|^8^pFeGz9v-^zD{?yrVcK5x&@ZyR2yfJYAh{iPebw2T6C z!0klc?X;#RB|9NStF4@d)@2P{sJz5xYSUs9%8o0Y5!)OZ@3C{GetWqRQXmL>5IK?7 zETU)ID$MyjP5$PMt`+(GhME2gh+Lw5l9^R*wI)0?1f>4vI8m91Q4r>fBnPCw@G3Qp zrv*MH7L9`Gs_067f{dRUgw!cT2^Rz?_jPx)uDP(YIjIkOC(u|sfp6q+Opo*0155Mb zcZ0wTmm4YDHLfb&MMarRCNHMEU^zImk;Ku-%qC#g_fwJZtG;}{V7Z<&>1;J{@$3U|wBxG* z4*4Y$>2g_}x~2#Tou{|Qo*f7VjdJ$T5~ZYuX(tdE+4khR3?Ufp1v2wE3u}?Prr^Zt z4bLd7xX+GVQqfTT`I4?*Tw8V@h*A!2c*8RuUg@?mfqWN`UnMoZ%)T=5Heyk^?Wbm0 z1lqQ(xqd!v*_VqW1^Y?}#{X(D8ea8Z59|e^kUY}0J*gD@*M>xx$oyu&th+Y2@@v-) zGfT|J!7ymzCz4r_6}n0@A_9GDW>i;%qh}W>GScA^tppZz>gry&8fG6T29?k8X8MCd zq~#TP6Z_9|E*^!qk%u|I_4N^g8>)knJ<}^Wesn(v=)wj6ArbvgBUCyl)5@}6-V*8MK)Q#KYdAz5#+llM3eg9g`xA#*6)cHJV3iZ#mK9RE?`27Os%4u0kH%z+pk}Syr@D zGZq)Iza~~P%~qE1TsYEMTNZ_uSnv89h4`z;2qN4-i9A|Ac$!J7BYj6U%R*tnmw1}s z>WF%UwLIiC1!uCffZXhq#uu{G0qn!{#i>!nZj!cQZWUWW>5s;dM_Y48a@5V@1MryHEID7Qbg$wn{Mayx(nH8Iw6sp(i0>|mA><~0VJT9_hPv-|Xawhm=UY?yT+srQ!l;;sNO93>063~TYPXXIMTJJ7m56D%JG;`rb*v|0 z=qynAc2%|4=_5IL&?mpMux11bN-L02G<<2{2<9_TAF6(-hAO6ImQqLNx{^|y_dAWd;lS<1 z23&-QxKB5BK58Ee=b-ue<#5}KQvRbAduxlf82?JoWX$Q=#nls#KooSYZg=Ijj$somzoxiKrwEH* zHh6lf=&AF$JN2X3`Ft&FXNl)h0?Me7U>BOylKWYJ$$&aa&v1dushH`+Y~Q2{`6$U| z67RD}=tG888+v_6Ej)AW;%lIdr%y!-jxRX!+r;d>eOWj*?aB*FIa5H&4t(t)@3#)c z)d0S%BUXGDgT2d1oRfu3T;0}#jJLAB0(SsCUmQEN_;**71w|QgNXmESGn$f0at|8z z#qE#LE$KkhdXGLSJvzGsuz7(m?}g-(xjj~emFB5V?vfWNh?)-t1O0;NvCIG2P zIB41C&gP={o*jr2S#I$;c3bCA<}dfK&nbxv%b`xKKm;>O*eR`u!K&ifJ}un4?$^Ob z{m>$WeV!;Tpxs$ktOR%RW3#R;yUK|1lzpY(12ZiWoyOEjMC?Iad~l~IrST}-Dnoq) z`!|WlhR^qSsKT={Z*m=4ipCMq4h=wCcKL!G-crDB{G6M;#K@7PKdke-cWyt0&1h|CdJtE%V3=!JSzwD6u#iIUW#X@jF6|xpBsQP zTKh#sP*5GCiTW8`f;t^t;_cher?5&PPDQ-pW;6tGrdVk>!;W0DlGHxy;HrHwAFxvM zNruARuMj0ci&$s<_m$28qRZlAsVoI__Q-^8k(0C(c_WN@zKnH?TKwCM1_xAvk++7T zrARcFi-z>lc(i_2lhx8daAH z-xih?7Z)YScHz-JlU-`qZog4?RR_<%;5*YyM#r*6@#_)OkYm_o92gj75!}$>-Est+ z@q`VB4W+!+|Yw5k+XtzXS(3>i0fysjEazs zSNksG4k6BGZhWLxC!-tj+{O7xJmwVJzKmOAyTyM{G+7L$lDaFoC=b)32`0BDcS|HS z*(>TR@`KBTY{C&ape$L&aa?@Yg{AvA8x!l|!V7XlL9CR7>j)b~`HB9HAzsCAH$S?w zU|#|8)C9&l)lq%AS8ioEne6V-70FtD!V(@~FAItfk@z85{yc_riUA!9tS1g5mbV9`RoCs1aJ);2SKX7kuY1aF*Cnt?EF zQRziJt1DoSzbQXMWrVTam=PVbjXf#bRZr7CW(U+Ws1|gOqH9wdEmsR|ieHa|nVJMh zJ_zf@ybLe7R36vDV6+Z1S@J$%&@8di4}arc2ai=kIvmGBPYIf+$z)mH#+TEaDhqCw z$+8+u4bLtVC2QW$HCP>|6DheDrvy%iIk<{TsJiSJ9u9W06%O6V=@)H?rt>bX&D4Rm zyML{;)o>0T!(vc$4oC%ZDF*+&ii+(RDI z3x*#3e9apr0kQ{72xP`IzB9{DrACB;<}o}|D}{TWpBG*Dr?3(kKST~SN1XKj zm`;1T!hyfDX5pIQL{eIh9-0{l$v9Bb631I>kRUwo!cORwPyR_>c`M@dLj@?6WBX8Z z{(=q(0=Iu$ld!iwy%apHE=A8SF#LgdS2#XU!9nOvA6{l@{u5fe1=*S9;zHqCC1IkF z+MO4IkM+(=<%L&)AznFZ_|RtMw3wL6_So6!3R345m%>57NFC(#RZ0@#=Ok(kxoATl z!NF%c+>ajtx_PE$Ws%1bJp-A!s-?er1@oWekJOBRSXg%|ju{Ovmfe!w#Yip;K~TF( z>ZX@9!_}R{Y9P+V*l%r=otGI7ui5Psh!Ma8A0Djqwwmq-wTw?s>~Uj*$He&Yr$JWp zEarJZRZHLV!Wmksw)n2!1$CqDDLY^Sc?zu4byq1D zx*)!Y7R`!n*mXLsx8XTFpC332ivOG+g6JQ87z)I&fJ`jr&LfP~FkQnZUx~$Hx}?)| zp)zV1;X!TD@EC2>d;)}jC&fbD>GY9e*5a*;iCB2SZkJc|^Q%HxrTivzL+JT+bMv-N z^DJnoEXquC`e~u2@f7!DB-WEvB~^c`%oN!P+XA7?k0IH?mA${deFuSqZU$DS=k%l@DJ{gFie&yvfQrIHDcfZp+ezrnOVMThN z#s-#QPaveUcS~TYHwkjtjl0;7ne{~ug=<0V26 zMaL7p1^sm21#JX%eARI8p2!VuOQFQ1otNVf+-vkk6SAVIK#pHowOyLjtW6=*OTZZW z`F9PK5QtU7I>gBpkT38_eTc0!Z>e2P;Xrh$YC(VK;v%EEjR1^Wy(c(cxlZD#M*I727Q%*GQXzImMtBb?SL`&GW}QSRkG8AIAiHau%>ZwL590DnbQs= zy2(?(7k3X#&*sp-E%NDMoUOow!?55l{g1h!sQrC$bMJWj*w3OfcduoKuY<%rv==!U zikBrfe0j~;-y>nzmD6&g+zJ}7<~0!2m9;!0cFE9|_Lx{{1>xm@(!rYM^d?;gRq=@I zPWv-<1?B8s}A@ z@ZUHC=z@Y>ZR{9$wW^5GYj8;Q`zJ^hGW$tH#+dpCvRc`dl z_^X^^4b2aO94@qI4THPIjWWuE?jk53y2QMvDX;aCRYHkS| z;H5b5#k5fxzyYY8KOOk5h15DIXMUw?h56ML2$0>RbP*6cr6oIin)_}3LM}`BFk-Br zZBmA;rcWTh!G&@wbFDVc46-$)BVF~0agr#^&vwP^$RlxQc?YOImuRwnY4b*jSC5B3 zLsEBAfq!sik^;+nU3x# zq`tDt81|dwyPeALsev zNMz}>sXqBbJKL?p{oUgIJY8)OQC5YEv0?zM#+Or~Nbe!Yd|!W0+9WDp%ZtD-#gZ4mDFcO+frrqQ*%T3FITotJY$$Rq>4n89XVjEqfcjBbqwnuKpFUEDyi z7m!OuvN8sY84uq#jXhy$!dhOh=jMZw)v~Ng#(yhp&Ci!xCuLJ~ThUSUEVJm&-C3nt z?=kScpyFg&Q55%mNk4M@jqI00?v+~`t8G_eA@<}$LWLBwZD`H9X0?fi;DRxJy*le= zAvafJX}9krgnOmTP3V@aWw`6-D-Y5T9PH@kwKf1xYdpucu)t9I$esZ+VzYdKq#zWO z_~G$B3JsqS^T&j?sb15!8pLPcqVNN0ggGi1GqELtecitnC#%+=-}kNX5}bBOPBa{ zQzDxLmK8jsy)_D1q0cfXUb<8b4B09)MC+sH28*#derCpDVkX0YDunJ*=9fj!S?*R8 z=G*;n>7#vKepycaTI)ldMRqYV98>uwW4AeWwi#8ZQ`oed)p4urh@z@W3Ex3ciGny9 z{d#27oeAM_P&5a|Qa4e1pV2zeqsY7+36uS7$pMiwtw*P-ecx6`D2lcc>{Y@R@BLqX=wXnV%?-q{|L-jW6-YP?Ce(5=yT!@>pXdrn76+`oG=~+P5w2pA8(%MQ1BP(cg z50h9&W=zC92=X$|Vb05{sff|^_^a4fjUday_8B;1Vwtftexxjg0YS|pm=GY5hqd@- z`1{?<6PWGCUqei{VnI}p_9?ZkGaM}cLIN>EyEdMZt5Kc9qs3mJ-~3?Roft)X?j`4N zgFj=XIr){Ey2-70sOW(qf(g^)DsUGcI=NJU^(|oIE)=avyACSyEz7kt=hyOPV^^i- z_q>R;BK}g9UQlVp?_bJ)P#DKAK<&tgyTQIQfAo;{sgHaW3#27qr_^Vs!Zt?B0L^4A zB_n*ZcPU}(W}UebX=ZoD6dfivhGA*el8B1m$OJwCKADrT5Tq?j-Rn_}`q%7TIAubn zMRC!mBC}DD9Mh2NRD+qEmY#haKXzdDI*87mTy@KreiY4dW)w{GX~6PtqrSVa-x(e2 z6_-y7uG|hbS=w#3A*0JaW?DySHOq2=WAMAg9fPt|TqS9Zfo0KcHert7JB&nznCqW8Jk1GQ8HHTzP4k&e7?pmG@{Yeh z9XU4O`hK{&V_=63)h*VQ9lS|p^3Kq9khc>wKQL&xmFm`nFV1_5aM9GJiru^|yE;w6TSfz=L z?&`-0$KCJbHVIa3{x%X@*o^91zZblXO6|Tw7Y$jn25M$6D0^M-TDEO7dW!X&*nO{1{e5xE-xYbT_4_0Q_;NV zFGg)0f8G3*`A$6*PAF1cs@+minPrm5Y~N~ONbaaNJ@yM*H_@Z7&XH_r{+YvHbyc#z ze$1#pg8C@TeUnrJN1Z}_@kW z6c~++-634UwS8TG#~ZD&B!~Ic5Q+TD6X-j-u%fqdJ^*Ne>3lu2u%y(tvSQWes}hh$ zl<4(Es=S4%qCcAQ{#y@!CFJNvSPff_5hN5bCZc;%ur#wP+MGAZUzdVm$W{xChzv*+ zno(%*8j{Yg=ZTDmR21WnVNKGMCSp%_e@`#*i&a2GcsN|LSK*ZH ziU9}XU#cPQIQU;y%9bw8-xY|QmVRhZC+pwE9EAEmQ~f_)%bc9K4f2@!4o2vZ6d$UU z|9){=+Qxt4&;zw+FYo}gAwJzdI_8y7nX^pUmS$d|wL0pWyQ(|`NVYo&FLwt8&sEw) z{4a@kyBY}MLmil2nh&Cr`9JPH6#pn+be7@&fIs=6^At0^kk9m_uMyx$;xCP~Yb>%X ztJrpQ&1x~)X^5c}=bU;11fxoFaIV58h{xW6AXTbHrAPn|nOSLgfPMWakr zuA#GYHIEu*Rmw{{YXx$Vpqhv`IEs7Jp1%)brs8YLUS;KRphM~!sUiDxDJ(@OVe{B* z*n{&*n9uMgM{UQ}whFL_?jlS`pQB?3v){G>`-kY1Jz{FAtq$PZi~U1)B);!s2KADr zWX8w{6YCS)OBI*waQdpRNY}TuZS6}FRrv#ZkJ~fi`J4P zdJ!x-XT2J=dib=rTYXHyK6$d&WIK0eCPU~ah+om)ac@rr6wBHg-0H7wdWCgeV9aSa zL*g6ci|GBX@u_i6X;yW7=#cD0wPQuH)ERjfJ{@WNME{Ur^R7>@(!N#J@FZt%uBXmE$27ws-Ad9w8YMjKk=IK7vFB_YyZGu1CqS&+?G^aGAlOjAN?7JeL76F zkJ~si$IDNmVnKDvH5MBUOCEZQK@RGES6&`h_tuJ`C* zk1kPAM=xy82#LxY7{V^0LXB6UjeWV541}U7_i1ryI{kg2m4wl2?pp+D1WQ9`BV|~& zO-AS_q(tQ%%VJOc-)S)CooOUwEY)TAuQeSW6$@Iazu!v*ld$q-C~6Um|M9%ppszY=b$mgCnpNZZguR|AU*;|D1P`nQ#!&6Xyw~%st5H}hE`QaG5 zr+HBN+*}F5?kVY2cet`Tp{~1`*U-mG|INt4&XuDYq@+fmb<1LzCj7Q;rQ`XS7C>{t z3Rls+G6T(h2<#kx*Yo4G?h4=bYOS;_`<+UDgX}3uIF#}irG%?-cH@MG#utiC6Ah$; za&B#gafh5Y^sDCMNi3LL@5UTUf5QVIi6b{4R+}S5tc&(5K=P@$+4QTAASFJSA|fX< z&7*V4_9Dmq?eq>m;eLFiDtmQSL50SF>YGj>QGt{3pdF`3I!QAkWX66_-vq`xF{W?Kss)@u@5_%Da(`&wTgk zaqY56V4Tb_1xerL>uQek6J7o<=$y4}7{2+%DOS2PYyi2B-~lA~F=?;+>++eX*n1m3 zwq2<+<(+F)Gz~WhujqmfkYBp0sHKpmL+8++sb*q=hc#ED&ZC!~%Uq-JJ7oq-=9%8) zppfS=NT8|P&Fz5X>*GsuImc8@Dm~q&ti3a+9(97yryZ{>mVa^_FkuvSc zQ#X7oS*m8hwMnnwkNavJh_>>m0Ycw6Q~OH&XYi!W{;4D3-s8ONb+3FIw*@Prw$E@e z(KrWMiFiB}`q7jWE063r89~1lweTH$R|71;LSWj63>`#LHf))dk$=o&k6(o_`JjAZ zJ{1R$2&$kKJq{hVzDZp)^vm`4`ja5hOelVI9=-NxK|XI5^xXS z%&$O{UaE}YU=(19s0gbdAqE!LY5?cxI&2&5aVPhYq9GMWEGx5ZS_a$ONn`=2TpqQ~ zO6;S$+LoE*OL5|BxWBZ^eFs~IU6pyoDlO4td$%c4bE^Vp5*h&R>LWhCV}@w#c3dTp zqXr~Ty8u)W1crH%=;nx`-_hB#qib8=-Z({0mV`Jrv+j4KYDG@!K4=xAg-`3KJLgZT z(Mp?IhdDbue|e9xRxv?D?BuDY4I|V|Gw@)YvT3S2Rhrjf*7Fp0aeA^kcL1W!KIY&8 zX#f)%Cwk{e&nCJ+f{#7b)h<*85;?7d9X)ioa#wai7k^MLM3>T2e>_M&U|%y34^W3o z{-r@0K~}a7m(lnCpzOIfa`h^p>D|6xh1HsXG7#)He^5N88RwgDkN}C}Cr(?9KwXYF z`@E9)(cqhY3vUnmJ!S6L{0wMi7oY28M229!{MP!`cfVE{%`3lrulpr8L`s1~LO|=( z$pHBYS#?G_3BVEagYnVsbcOYT_J?>pF{9fV$4^hc@gbX8!8^^i$8Ss$F|+t*YPBh47w``;1M{7AI$8 zU4nm2daLGUO4cRL8Q4%@#i1hTb@xG0x8MMo=Tt<3_yG4Xk{;pX?D8^-WkFb%0)sy3 z1S;$N!fVeUM5ZZ>V+4bpdS!>D!luT2Eqy#}GaB-0;)z_+BOQ(l@w#Ahdb7g9ExP=~ zmPomFy)zREb1US{iWECbjg;6CeoX=3-H5ga7qv+r?hwKlef9|}`Uh_{fqQQ$l znNbFQEDkEJE_b(M;SLfe7YD3MnLiejOXbBH9pMc0bH~7YaJ47{(z?&8(y1bL!ZK1w zFiP{mbd09SX=w_fa>vjvOHt%cv*FUeua-jX=}DQv@E~)t>F>5qaQxSnG_a z3_d4+>u~5=)@+?RJ!Ny#xdDW@s0D__YliE{1VXnaQX&6W(RD zoSfqR8hPf4ZVsSYTmr=|Coe24O;moIklj~D_g-FAG%|8brCY&4?ma|cQum8G_q!Wc>P_Fo&3OtsT(0-M0$3k z7b15j{IsgMhT)ow)$L_jk=gUT+&2F^OSIY`*4O zJ<70O1D>_0TE=;?c2N?NkCZv`u138{MxVmwUFRHNS{sfrV~D&ZSE2HHtLz0-TlQ1D z)B8<_tqBt6hBo+^#C@CkOB}um$$66f1B{bDCI*xM-_~oS)H~xT*drFh_=gz9zckMOj6F$4RAFZt zFHLua6cB5qmVtp|M+0)XqnIU35SFxI1hiBLlC^jI)3pet%PjN+m=z@)>?=jM29Z8Q zr}(54_dkQ?YC5l0SGvA`555-}U{A(1+$!*JGEzq(xrxW%+6EK!93oDN;B~t``3Q6} ztd(W^3I@e;W?r7VGPNHymQ1?ML+dw>KW|m)i<)&Q>Jb@ciX+PK%N=O9ZK-gGDACPc zRrtTMJdCT<@o>w?Um+CKitY%oF+272o_%20wn{P2&QFGcW6l7L5ov4Ax+MIHtvTtu z!OlV4eoAEx!|3+$RS;lP#+Sq8g8Zew>vulo4&S&!gh#2~(Maw~rqg(CW9$sJ^!5lu z;rtZsT~yzHUAkI$sa|AQy|D0W68?tRWG1e#?f|3Z@ZTlwO4V{k9fab5Vb?jb|Iaw)r6nP>x) zw4Kgk_%NP3g=+-Hd$&uU4AdZHam@5R|7Afk6boZI_CDm341f z?b?qm?L1|C8b=;qME5z2qOOD{BJ-laT3vxic<+l$IYW8}bWYlmUN;EY&#xJp3HPw9 z#(tE>maec4JX*0s;G0F2^XkoYR!)rN4X|ptQdY~qv6rw|NMV2KQQHOos^(e`Z`*&w zxQTy%($N7M5AA*w89!av$oEL~ zPj#?T7pPfRkWwfdE=Qc?lw7c{YaOnKAU}+kZWNW>Bn~m-+jtel{#u{m9a@DSu}{`z zV~HId8DcYycum7BU!`#C(hLjT2^K7L5%^8Hlbq6kIrLtt?V9~+HK!khO{S%W7{?^y zjMgrph|xx=Pw|fP-e8bP)e-h;0MpBI_9<;>o3ScJM?wK^*(ZEIMFpwFqt*RNh`P_7 zU$E7yiDl=^%tLvYADflP@zlJ79;D@md~%yw27Lv2iMk*dq%0{>fD@7QSvV2?Nn%SG z`2FGLD%qiSe{Bp`h8BQvek8jB*K?t{3$#<)ii=(QdO(7a#Ssi@dtp-EUmjK3M1f!U z@J)Y4$W2>@a0Bv8P_ad$f7T?qXD?&D%DQ%`{OD5@d#)48csbn2`G7P;jkj<0l5kvn z&DSNukuKThT@(<=RPK!kr_}Pb7rCrwAu&V&V9RSl2~G$haa0Fa&W zT-v)zn>T6YF*idB8%$jU!vw*&^}8=A8QL1uc03CNO%`klJs7#)yy|p3HQ(b=R&OMv zKUCj-L!vyVb9Hpw=6q7rpR#$j9%{s37xir z)m2pBw-*f^zLy=yAS@m7^j3=`4Lh5EpC-n7_>kSaJ7m)%jg6bL1%$4k?mcOBRK;kr zxtlPi1qjcD#t)xOvM)EI<16f02#$`pZwxtVpdTp~_nPL% z1+?895M>xDEVAuc3AUUbPZ+yizT05#2uGYfkeTzx6y}QwnY>@ukA16+)*kvAqN14m zw!gN2Em89JM>Oj1GgrQ{{P^917YlQlfKg?qJJx=XbV&fKemdHQmRG|i za1yk-2RUFpS#!#d=}fk)UBOt@`6el!2)5Bok=D7p-!&9}gs_Jc887`3nbKY;OqG|Z zqSp4<4_{#3!Iz&L;%77sN~`^S5!f@F<1D?0 zUy(*!2haYpXyk)3q2c;nP0(D*g^ncUv#qcIeSIOPX@#Q)aewbcN+0@A@$2|}y4T-L zzYu%GY^iIbx9}^ez-OM}DRpI?5cWBj+L6S067=3OE4%94O?U6Yf^A#@O<9||s%$=N z0afEl-K#4dXKj|ucheQruQ&-hDJ$Zu)cKODWcP00z1h0ggPEzHWswNNV zt|AyYlJ%kW_(>CuxaSVc*upLjKqMD zJ7KSr)#hA!tns1UQ+k2Huwg=qvbL()U+TP~1hb&V0=fFLyILaxQnqjBQAGxmGgNeQ zue_LJn`b>d9;)of&a=n^aSz&Bm2y6@WT^$L>cr?2mJ_51nyHY^Q>OA^W1Y%v*w@5D zLY|ZlS10w&ecICU7TOD25eGYdl7^qF5S(ewwRYO#jb)M&_rK zm8lO<@za&384B5J0{qLD18@=$MbNM5m(5f)?%0Jw3 z;KGM#XX6Jg9j;W4%GIB>uSnn6CldmAfe5}v52CFoeoPBI+kXoU=YqOf)Y;^l8++Q< zeHNWP;PJ9#KGrd8P~_TDQc?gpF_&u-z>^d2EXwD6yo z8p5w$B(h6u+YhRfnq!^Zrl4JJvAWbuG-seIV)#^)X#$|QaUHX;L=)XGy(`}e5a ze)N2L+T=;UC7GanaRNF1)AlZiw*OoEV?W!TT3qovd9N?~=9X#1eHebTG`_ao2c=Es zvrI6U&eCEY)%Hu#5|1cx0bbdvfcm&5S5AU?iW3^TzwIovs-4^NmA)|3*yLd^DptMx zG}DaQp4*~^)X6mTu&$3b5=Om|yGkaYb(XK${-IyDnK=9q`v&))YM6Oh5U%zfx=iRh z3Gdh>gyJx566xxW&pwG`Vf}CW$=@dY4{P~HDEo4x*r051sl_22!_=TARuMOl|Rs=AiX$#+Hm?$FS*KOhp@(Qc!}8lXmX zP*h+%c3n;c?1-+!zEGt&_dZpoee?Az+kbaH(sX%V-TbqK77c638yNlo@Nw&Je2ISn zI!u9V_pYdX2otw?%i(ujXjkogOe{40t>$&t*G)^u>gwqUdI1JC9UDl3DTm3hA(Fe= z2#mocQvWwAK)K#^>?wh<>0>WtPBoJt8fM)R83*gx55LbOeZ0%?k`HAGKjXZ3Qc%ga z(lVcUQNS2{BK7yakwNNhxivOQRNld(K5Is5(DCxKLHhHna?<%|DK2C>y2M0{10ROX zH&e-aK^<_J$}5ZEqLP56=|hxnOu;o@4(&8vja)gRME-?@Di~?z()XoKSVPtaU1q6y zYdrZ`f5HmlO%?E7sor&{^Y=GQNWJUSQvy>CPY%#=T8pt6A7@wmVhh-W5P#~a<{eqJ z`dY^>Vigwdoh#`b-rqR1iQf3>Y@@vi1=M3P)c zop2$?^gq;$&l%Gjvo~HO56t#cJkP(9yQVRs^+ZdZ<6dkWvy`-VW(#gBYKisg`{y-t z?H9YNKYu>PdiBHVIUFyp=FK`^C^e-$OZbeu+*G84=QZw+9#6SiGz{f^iBeEz%0!2= zKsIWA>&;#2v<6JAR$mvQN0?~DQvGjJ!6rk0-I4IeooDcc1x@bBo=x$I3rg668Uiom zC#{z`d`f>EN-y&0k_&Bro9cgiB&P?RpI8XkUWzV00PVT4t&^jB4wNd(%)K&paKJSj zRamZADqQe1M>I+3e0)=P)JS?bksoFG@$Bu8Kx;O7sxc-iDstvN8N+~K`Oa`*LTm!k zHBv7Uc(OIhS$a|EQo>y`z!<^U+4DeiP__`5*6d7=!92=|NmEE#p>JRBoM&@d(!wY| zS+>mSQ`$wNOs$b!b>6Oo+_;!m_iahWzS$oC2bcMGW?L+pDD8YiKQlVZX<<~JMrWd~ z8iqhc0V@r?>sUu+1Gs5AuAe6MOmsu*+z&;%5IZ(Aj~NrPYRHTX6^CNTH#=sg7l);fZq~gNge`n-6UbMBP=DnyWw=#NfGcv)KRvY|WN1F$tF;JZIR*qe_nSf#) zrmU*Vbm-`af7VI#Fx?P1VactWxlBx}W|5i;=7!em>NIkoYMpmz#1)v^q zVq=!Xu$hRk)iXbUOfD4L)C}*L8a^D}k_iUZt%xZoNoX*ROZKSL@}NEoh%c*-FenKh z7L)_0rZwM~z3iUChItD|ui{H-DH>kXPi%pR)pQ;9ZNyOb{oVGcAUgn}hcf^P*3LJwRfFtEk>>2sia$(4LaAQ{*wa*Hl})L`_I z7f9OQN0;_w2*ze&#vEO8ckh^IU%E<;2lGHShbm0hAjz>aQtus8J4u>crW;tU!22Hyy9^JDb zU`cUiXx1QTvAxjDR-Fktds6LCm^UnrH9FnUz+3soeO+AtH!+fx?X%553x6XFdu~bR z)~a@?aqXo~LnEqlSr`@q?PTNSTPyRryK_;-T3OX&Gvi&U$W4SxvLM9C z-=cV_tiViIAgLF0DXD=bvf${LNvumyuYI2`CK=n zdb@i97fW7!+TyTRzyh4+Zh7FT5iPyQ^)6C>*RDcsWNBIay&Q95dBZ-I^w+aOX>XYN z?{eiX5G}NfOj+-0OlDh+=QdP8IVdXEr!dh4s5WyOtU922nCECLT2?N=ti&WP5Lf^uT!MqS2yG*jkj1gp8^-tMo0>9wq3~9B_J%7fwont21=qApRNe zYw26gLFb24ol^-7RG=I$hyW;OR$3U&e^KccChe zMYsvu@Htg*ZoKC$*X`ZN6k2QDY(GyZlf8UzuGcdO-DF2cs{@%mtxq1Uwxr_xNy@Zv z3E6ViR7Gkt7S7VHLJ$V_q(qEoe=UxNP|S||J*X;Bwc#MLIKS*%M(F)@+A0rri$-IS zoUP*{x0YUljmoW{^=KMm)i1M4mZ!~nb9*_To~QM|e=lCVB4@bt=pg;|VCcv{A@~QJ z=Lt=eN}wHZ+Ig(as1fq9WlC*Y+Q_Qy7?b8mrQll`8UE2#q~;<0*xK+_q;jElE0z_^ z{oVG2_xi`|JuwC2!knm9;P+UZ+*WQ(!T8XUGH!Qz^%>RH1b62>p#Wwq3gsjce2bH7 z5AgyE^=LxCJg0T_%n680JyPPx?HGc!WmmVzu$RRqMTXDMpGr0HQ^4Db#f1b$$rzRC zUoO1^Z~N`>YFrS;KCheUQ{Obt36QOI^$2}BEx~Hi_9S644dq!^@b?=V$MHh4(#^?l zS#DCPEfESvP>Nnmli~kPF;*^<#fB>fbF0XfElR|Dd1~)+L~pA;^%Xy#s&+2st5d*R zY?`+p)xp9qMX^j-#FbsUOQ!up*}*ty8UZ)7S|Yr+47MP&Iq*Pmq{$WQeQc8Y&9uG|1^n5^Fu*@$-v7M(@%H~4 zVNRX@!W@Xx<7#9|hE+r(+Oc1uAKqPvKhCG6f$UrWv_)_+wPdglGI8(rs!AdjaR1T|Z* zR7EfP``2RkL+%M5d$Gu}>tt*TVS9l!q9}?GgLT$|LD#bDaDFvs`eHQk9=U<~hVjwq zU^^n@!FT7PItp7-5>J!fn;e`yh&Z7*pF@eGFQTf#_AR1_P%^L=E@ccvjtU~aws^rV z6MErW!wIdZvr*;=D1%`cpEooZ0ky9-NL{vqpVU|p!hpCD!qg0cJk40DqZfSxE9ZU_ zF=+^fLyVOiEX@e~bw=`<{MYNPuDSF5gYt(MheO-*bJCxlwE^BI{2sxIq%zTh2igeH z4;&a>)3BDE=C*bV*&{=O{Ii+z8>SisIL5n32v^sd{eIe~lK4j>nvdgOTX-Sb^F(PfASr8YZ?sZhs{@fG{t8 zuMzh((**ow<`zdX1^(1Zfa9cajN}(kfFG~~q%TWGNqhOV)BkK$=-YO^qJo-&{C;T9$DzY$ z>7jmD?7$#gz3Yv@LbQgWl1&18Z1x5Lzr@2ewSlLKNS}6lFp|snRGjV|d+pQF=gLWN z)K^$W$e15Yi^aQep=a7i>!>GrH@vr&gQTn)IGXeBVTL4WY!ihPa7hcWjPP9?21@oJ z?po4hFa`m@JKkXAK)aI#&Q&ryje+|4$(%y@)vP^7{ivV2`9>$2!im}n=b0WCngvy6 zq0zF=Y~J`H6#1DpKC%guiq88YPYu5QFLSK<1gqqmV3noPDIZN{?=j_!#StmdA@iz_ zW;UeFDg*D9&Xyf{7 zEvkK;qXFU2TK}Kdv}DD#L&6d-AdCC^^QM?%fa>MT9-%60?1rGLDeG)_Uk&0o6`h#q zf@D`OV1ulk|yM?HQLrTMJ7f*-6<^z&-i)gCh+zwzy?C-mmYNZ`G86 zt21N5f^uv|OA~n#%H9{*W#rHnDPynD&PCk8&EfurHTWF3tLe9PQq_i2=oo(}+eCUz zNArDzKb0?aS6w$S{&Z=x02EDiBNOh>^d7PGf@!?O8PDUg551hR5vT9lQ=r-?e`%0@ zxCpB`WHjHQu^$jjX_obQam=bnV`^FT_yK+|wqjG?2hM@efoMt{LY?7DiMHMN9PY23 z&3es*hN&MNuH(D!dNmIS0=Bi9dbO`%Khw^yOQw4cOkUJYPicJp#C8l)h_&DA=A6O2 zGK0?Y##`J))_q;5xUidOmmCy~>;Af<;1t_~p0YqqrK&bIqLeMAP28RdeE|(jZ>SVC zs3<7RvI+Ub!#MIh+mBFNz9BacYjFB-st;Fvp^3JrD2eSr`baHlaT|YEU2(vvq?q&V zMDsv7UDD#w9^qNxXC=|vfD%T71NbCY>lRhj^XZnh=Nmo!8pd_cUPOff<8jHCnH&bEJYLQeU z8fb*%-H*96_P!0u@e-EMQ^}iUj+UtRzGZRu-)@TBxF-k(moMkkv~oRTr5M^LuPp(M z(h0n@I+=-;X<79(=I2x}obfXZD+99IZUopmh|BI|vPW?~hf-${bGAP;uP7yrN9=aV z&@{i;GRWeG%lk`OJhRC@JIjfjg4m^uGZ^^+xo$=?f!xX&O#gcLenub@I-nHg2N1j* zb9pG!csy^tr0Tt}+LE&w)g*PiG_z+U>)cl&m|uf%ANM6>9Hn2E-?rM%JYkmjKi;xU zY=*A5AE)jxWvq6@U(t5nmM(qQ(o`boN%cu~ln~WmaZ{jsdCws0b#E)l7mQ-u$mO>8 z&4eL5gk-ps_nBT{enN74jkxAIpLBGE6&N;JZMGXZg@t9iOQd_wCNBB4eQjl7J^NVb z$DU`6fHl^Zm*_97x&@;xI3>t;?7DeX6=P$MKHfx)5novXul*GEi*wP1iStaL^407P zrcGPBzI2ThQ$Ez6YjPqq-vhNE-kr6$0bH|LqRR?5zMWLAR!V51KRpATUuG2JYk&@9 z=N4*pX4hZ4zgDk^Rmdn6nnNcJ5fhUqOA6ElKm>iOepKg_&zLjGMqXmZcSu-}rgGwc z*&`cXia+Bk($!F+s!6wD7Pz|f3I~;)_x2`}DLM?J8oX!8*kE?~O)jJjP4i4!QH+gv zhs{Sc+UA`*K9ad2a@o#SYPY%pPK*t!t|r#fBFS=CetOPjTsomXp(=jutF5*2lHFA& zQIxiEoRAp9m+Zqru=H;IcpvT-v_KLf`jZq72tDe0tW+)H?mLRAhE|<%(T=R1rpx`- z)z(4`i%RN=HPzhD5+dLY?dL^7kH1~{%a!z%k`!KTmK6KPu>(1Ici=`O5RFE&YUjid z#32UfLAz4oJNR{oUt9+UFpY0UE?=W}E@hAROOFB1MHyZV^RM#?yds*um8_q_t=}=s zM!{L`{U|Iqw8x3DUey{CI&_=9yPwo|UWU-1{}%PX#i!YDe3H_-ANZZ)t9En)(1R`n z^u>KuBzyDUXW{>0LjFG~cJy~V&x1|#_1__mA7-hUOoQ1KUxor|cGR9`SOi&IYNOXR zN~YFH_%Ra{^>)%&eK+XQ>yyrJzC%ap*620@(!Kax_=nDfuj<`S9Ue=4-kv#|o&f`F zsBCY0pQsHE_gRn<=U*Id3n6|`>VEU%I69Wxg`iqZZ3R4E@O#|!c{_a=3+J74%0=X+ zlooQYa=xVSl{$Rh1IBTE0Uc#D^`Y%Ak%hY8hhB+4oS+B*Rt?B@9ev&oarGV|lgoW& zPH*T=1gzxxqIHx3 zu(P`9$gz|bR#dP4MmVda{kPxK);furECyrLiso2aMw`%LS^9s}{G;_B1-vn*v>hw+ zRm6f6XV|M?u6BK-;nz=Hwc7N&rUSEgm8%>9y+XlRKo7U*HtNd`OnCGk{f*d8%uHDB z`dzC>hIzfa)qB!A5M1Hd~_!2JZK|*Z?+n#u@JX({+l^Ju3Xc;V^-jZe9n$ywr6JgQ&3nm}!5)N&}aI-4$B^H!VVt?LFLUW@y}=A2eO=3=O_BtK|C ziL@M)!Qfbxyb?QJ_)e%l#>e?Dq=s_t-rH9!c6MYY&YB2s7xw%5#{u(e%9=yKPGOPp z#l=NFVY{zTV+3jXZ?R$M>fI-zyudN|FBc|EUi5rR`l8%|qFl$XuS5a$ZZp)gI+S_g zX?!>sHhiKAQrbQQB|Y;R(&ed3i$nR)Rz5l^e@!A1Jyg=^=Ga|^>=gG{6>0&QteBve z0LL%Ppf3$_GOYQZ&%mxMlXlI_4Yb8sQ0?N*H|BnWM>>^_EjoyORKWNzkC=-Rf9KmClB6A@e%oeMIhheth}MEK^$|>bd@L3UOVHV0%QrI1jWVrt!A@XIWA=#s zl%kpUnKekWbN(Y(B*iW~e6jyDHTtu7qeano_SY%v8_R~2&?IHvXi!9t->&x8x4iS( zJ#TrAG_90{cp{fZ$Oh!&z0Ry>;1490AnM{ED4pZ3Un4M@zH(?~{-IV_t(Ip8)9xI_ z;_rFgKSi?#SuT;k#=gI!-*@jJIr`Zl^HMO1AoGxy*cXQ!PvPWf^}|Q$<}^jJYd2nv zi2?s5J6jq7>MwdeA0~V}FF)$&Mt=RlV`8hDvNLC)-Cnd4n>=fKcJtA;nNI) z-WGh&MK}UaT4h^lXl_NhcC&SF@~SRiRM>&Oxgk7mnXn=&XjH^Kv-DNIuT^)&H5uf{ zomE7TrK)%V6dWT@e(mlVkabrzmzW_gk*9C{bE`6Kke+R7fMdZKrH_g^lbUIG-zsCM zotu~?MhX16Pwr-FRppaQBWeTB(H1zps8wT9v^LG{#&0$p+7b8Ijw4ofjS^{`zL4VT z!(W&&9eli0=72PER8<&P6F#S6IcWJr4W+fdjX`i2F$x&{=0~kLIJ#z#0JGj8Mlu>O z>z@IQu70FlG%NohEcOr|JHEPcMWd|wHDXBHyXr5})Z9nwm}rO+e%i7+-2Tt(!h#rO zP$I`qz+*YlZqla1eYmhrP!Z@aB#tEGja}`bpXO(FlHQGO-uP~RzCjR2E$5uP7Rc1z z_QpJwzR$}zQqeUjE%NiPUQpbLN|^Y$STAf*=$ArSuU6@Vh8T3~>ysXyE116nxc@y3 z;N`7O&B$mvtd?8})@1wt(Sgxfu&K@R385Cu`JBL4=I}XU6#O%lt$04*TyU(!=)>kg z#SE*Y)2=Bqup`Hqgvg%$RwxgB3+k+j+LQ!Fr4(vQd)M5H5|NG_e0?|DtRy669?yzG;`c72W{91Yb{h63Y4&??XOKO;?8zcdAlhJM*%&Pm6C{(xE*$_3}B(&n8Wq$+O8H z(@$B{isADskC4Ev(tq8$Cot!iYv+qw_F0ZQBOny}QMr9Ev-Sp1B~^)W5;X3e=exGwmoP)1fZ*Q_OT(D5HqbP2E-Ew#Q{U}O zX~XuOs`ZGOyAnE3R>INaFFC@qp3b(T{E+8NkvHN-CM@MWSXj85UsPV0J_5mkM~w4C z#pj+!p=+Cv4J+SpwZg`=hQ8W-l;gd-(_peTQ6c&I!EO3xAidN3pyKnms;CT5Dr?x( zz6YlZY|YV;zbJ!6X^6e_7*EmAL^wroig1CtW^z~&co%F~ece_@016b9^^fl=3wBtU zmg*)*R8+w4e?Q&OHnabdl%OQCSbRdJSB3!wP>-+yObg87sOC4}vXaSK@a}5ytOORP zu;Z~-4Ku$7Q!y2wIW5E{a#RnZe5g5>Q1Hr0upl9|b{l{mJX?f9aypJHC%V);a)YwD z25_NHtex+#slVxis3v?kDZ~zjYAE8&ADaYz8#^hgiCj+%kq!}Au>MpWArI`EUrOzY zYaL`xai_OLbNiSZ_@i>GtJDV7m7W2eM%%MeUImjpTW`7|D`VD8G^fggW!*#!oF4Wywh}#noPlXj$FzpQ-~H+|s)R%w0-7#Bjz$dj_f9c{^MofqsMk+^?6#Bg-(@)SD+@cgmA>rkX zh_pLZmvzO+q;5H@@;4bTtS&0NmZ1s7Rq;d)T4hna$U*pXS(RAQJhQWNO6DrPEs*%OvMjOi7QLd8Ccx6vWZyZld2{r{d&(K zmDiP%S;0LrfS<9@V2%pfB93as5ybaHad25Vo%vK-rW z>xB9vo)G?~_UjCdUAM}DG$-Kuuz7*r!+ZI=;;>;m6afL1EVK6%@XX`oTHT_ONDO5; zZR#kgSL16DZ|dY{cRcam=)4a-{4SB#GYn_8m+d$8$^DRA>a0CG{P@TqSJ!0UI$oWw z%aymdVv%2l_f|$h^MjFbcThcp7pIs(NdnY8mcypN;{+JkY3W&B5XZIl0@I`2!FZ3M z9JL2yTy?~@;75o~+cXpwndsyIMZIhEMjVQuEH|d1R@-lL*ci2W*iHH8(*8Dv&veVm z8d_-+&vqZ6p#1cHeo(KVWK|mEEraR7$*m!I7gygdUl)U#puAr(o0uDU1fQxZqn;OE zt+I|BNvRi=`X~Y~vZ-cna3OWTjUat#P;~d(s65Vj zM_B32=H7f~(arnvT*L2h-X*Yu=7Hmdo03S64J4(dQgzZkB^A1^{6)n&YAF|4@-=e4 zNb#JfWx^amiLT}rp_bMd!jtAur*=wMlIeROeDYZ`t3&Kj| zq}%f6En;JH#UR72WYzB4hHI8o^y>4M>{Vmqjgl)2W@KI1s#BH2h@3&8o*XG`r*Ceu|s=%VnJf_bHn0y+- zeM+(>gaxt0<_wg{6u7R%nWY@@r-ZrpQ|FsAJHLfgX`|!Wk;^9|!%@8imhpb}6^y8x z?FQ!OiK}(Hb{Z8B>Qs6?!x3M~Y8WE@wxEU&Xg?Z^+3(%gSwB5Gy`^uu4;6B(h_7!U zH*snhvnI?cV%OQzCk)*hvKGRLLW={8ZL6E}lIJ~sz`@&j9}MT=JH%6#-!)=2PG};d z_NW=)s2ZW5ml3V(BW0^s0CRFnZaWa~rjld1pJ|vzNq_7mnE#VN+$x6rx`Sz zNNA-!*=crC=3=-aE1ehVMbn4Ww`<9%@YhI?7{$*+9hOg5n>^@5n~CN!_y$b^`^YZ) zRR-1NxOoUaCS;w}TU%c>|o{@73fE2y3;02|^ht6s3s<@6{6<;o# z6fQNEq-JzVlLOy`NPgj$Vy0+Um;Z7cou}|hhDdgMpA%o)HO^koL#p0YOrv}y5Fq)V zf>MzCNFE5PCr;CA?^p{Jkg={l6DE^mTKm%K91q@uR?L7q((`~n6*PX=uj#Xgoz1)> z=;W~eabyPwn^SYd+gkBYJ}~Tr@-Vse*n76~TL}iJoOzfPzaL^!qI_JXXm<_XTpoCl zmTRvTjD4N6SoEX!Q)D$q6BbfLTw&^uz%w!l$-d>9s_VY&sZIc%%*kx3&v&)E!yA>_ zRG05+?uR!T!xo_2w3^%6L8D+#-G=fu1udcTkIFuuYFZ2Vc?inKt(S4s5W;B!aKR^G z6}mssa*QuCq>VR1d(y4z^yCDKqeCcEVGEgc?Y$}-uym?4i2ICXnH7@`j03laBk&<2 zMO$k3J;i!yacu(8bXk!Y$LAz1F@I4)S;lN+^r$Tv6l;u8)wHiyYdt0XP54G&YDecn z?U^@JNu0BLg!Y5#T6qwqaH}8y@0Zuzqss1OH`4%M)>Gv;qBP~<%wxjM;6c5)2H1Z< z#|AkHO`|EO{Uja%#R*N*|0$Ip>1d$Gsme!|M>PD9>iM!*xjy3z){P%p|IGAQuJ{*{ zW|4sUgT?$7_GM7)6u7&1D&B5F<@JS0ZiE*ITE2(R5yLt5upwGA`3~XjDSm2~XgLrK zs?`A)pB*4BTh_~voG7TQMTAckJ^J_}suoN!Y4T0yVj%I4bi{vT z>iM@+!R;Z;gcR4dk8Z{N_*KBN$%+x#bQf{@{-^Sy^z^xXZSDMNE?9h&ji?OL_{1K4 z#Fu@vo=OP69#v=oh9mVarynBIc93X$Yff1IuQ-{z(?1!_)w{~UDL#K3YY>3cXuS(m z6ReBq(Wlyl`{i|`ySof4cwVA^A$u5O|7zX>er%jkRBX?mp7wQmjl?I(v;kM!h=D{@&8d?(9YJR#`b6dmVrCs+ zX`HPJY*DxJ3UAq8_bYoO6KLpJmY_%l@hq|yRYjmMXw}M=abbC_Ho0NAlAJPJ~ytLeg|FEDy5Y zYX%$)>qR&|iyi})T6C}LjyD+9sYwoLzj~Rqs6MQyQ^&1yPgzx)Fhh#o6e^%vuB@J_ z!#bIqU6P`~8b#>DYOpLAvznO-E(*+d-Xn!Rz!vcWKoxkkgHZduA~W#IYdOmPA8|D4 z5xiRDj9>Xr&EpTLzr%VwbYu2_=5)N9K>~)263R(=IsW-c@)iNYeMhb+`74s|@g}Me zsPei^C0HLc?$S>oItI&p8YCZA=%ARv&b;6|4a|-ZC4o$-(x#{_^X*GwhoB82#Y>K~ zv;0!Y!%t9F8i(>0Yptul28=S+IThen?A`*;)n(S?u3zO97ldf38!Dpnp_vxk;bz)oSk*e{f@p%qw5t-Vqdgk(;CU7ZUaCLgR3XPEP*oA`tDtWY*n< z;aXqctoTwK;MkeV?w%n1 z)o^ND9wR=S$|89rv^iF45xFM1>_zlTkG{LffP-~_F^sJj$nXj0Ron38;*C)rX5=)T zC0XvT>_ogQ1=eprx7WBs$92)u2r;=Lzd8rKVr09QX#2T2j(r$WLF? zIgj_a<@nq8C7N_F)q|AmvZM#GMws?4RI)VTzD}K>12{16jJ|uPq|Db{P*nj+Sw)v$ z$CfTux7rG$OYfgaF~eQ9KL9V|!xpg!dbeW`Fzk@6V}~dy<*9e~YzgJP)72Z0srjej zo7Kl`A^RTCJzyjDD&(<0uc^qqEHzbyPjS?4I^Pa-7lt#bK?D2J==`&$l~>3d;T!Ph ztIfxJA^Y3k%K!t_26ij zHLI*?Eyouh=l;hmm#1x0MyTN69!ZKmZvn{hHnoo;+3IR_4WAOX^7D)=aC zkAO)@J)ogH+YM0VCXo^rQZ!d=p+(}pe1JUPe*j z8pORDEt2Kk$T46fL8G!S9eU92deDMElWQsY1M}wg7ZN!Cs_eR0JP08N9)CUEW*H5?i2S#wbjqKPG;J+9Z zmLu6phL1naGAxmGZC9kIPt?(+jcXOSI^$)i&JV9#$y`qJ9L+tA z3k3VUd|ws@s~Y|gZ#7~+hx$@|wbU1ZG$iAx8nwjb^uA#8A{^Pje=+WVaSQpsyM;n0 zL*#<>N8Y)2y0sBH8A9ZaKS5imb1rTyp0(Wj=2*4~=jP1uURO9(8}3|edk`t`xx#N; zbWUT^<&vHr=a~_3eKHf|_QqVXQ}zmm-?SD?N@&?ASXk6gz7gl{uD3RVqo`>S(fC)1 zN~o#H$WlYN+R0CI!FSUG=`xm7+pI06cVLG~{3rl*H&;;glH&BGJxKKGTi!8?SH2m~ zMbf0Elo53oFZ?J@PY}!9RE&(@I&^*(2`QlKTcrdQwpEWP>1Vsix`CSO?zLJ+dojY@ z&+#cB{ClMx$7<;go>%Jk4ei(y3W#9v&vZ6##H5t>zEL(>IG56mqCVc-CEV0`*U?yp z%>WeiKh=eEj!?wzdwmV)=?mWgu!ht`liW>fio2Azb}n{5^-SJ{&W0x-LiD{93hR^~ z`~N~xFtzgsn$R+ zv`N{r0?~CBefuFvGSd)&IIH4`!S8FFml$z5(QMmesMR{saSK!^Ob>#)BFv^insYM3 zcX8#)Q~7Ko{uv94nt;)qw3#7ks(h)@Ur0^ym2>4^-&kMrJc?~Ika@~6nbg^`XQXP& zES+iQ$(OdkO_ZfFm_j%Y`8HfF$bi$g>sFU1zfNo|D)D^}4z;kr-*!5qBsZtqzm-pu zTgUDrBb|AnYv4z1MULxcKS`G{4tq^Q>HKEUbtd2pIYDWH?$Y(I(?4CA-7rWPF!0)F zRK=bJoWliv_suodu+YsW!<^16U`7oqOmp-1q?23S?+DU(YR&Ag6cQO~DrZ;-{+J7t z7{2c%_DKU0klnq|-Zk;lKW?tyvazHlSqwOshl5)xP7xE+gyL}ZantAGE<;JPj%`d! zPVcUGYLk>q_0*Mikn<>n){U7_Uvnsr}%Nlr^jiqUCmyHP~ud(itq4BNK5 zNyrTC18#Gds)Vy{^mjcfM$bqv0srHcJ{P-DS@(2*$}9!hw?YB+LpCW9>QH65|vu4dH0)J+QoiJY=@ZU66)e&dUq}<>S=;OVvb)shGpkv zPDFd{3P<7zg>YMqa+saEATHVGJe(RS1C@6yU74gFKi9J>Vr4i@>nFto#Wx6^ZR#eZ z^wRBpo1xUcYT}bx>9X?@VOHy6p=!;bMo&%jKV}Hf8J+e&Z!>go2(_IE!j!`rX8Y{U zO$&F1L_Fb)`ET2Hc1$j1=XtO(oxeG}_xI=Q*MBLuqJ8^`MC%irtvjL840B^oSM`i2 zx&NI7*6_29D74n4oWQ`Is&gdqr=2XTaLYYegOH0_M*^x6D6g=-$}J@)A`X*x5F68@ zDbbce-&t+|MmrJxG^@?_CU~G6R6st@1vFz@w-c z$fXU(_?)q=v+s73gM`O68UmHQ-3q4(NIb{Aaj(lD_sk;Oz_BYcAYor=Iv7X!!3fFb z#qAi+kUUR2^8??qjBnAiMwjcrW<0_kUifc5?Ojwh^<~`~K=SXx{e3sf-#L-#55wIX zqp*qYH&BOm!Rn#Qjh6;AUa4Dkh ztZqt7bIW3?ty{w7>25+m*&_&8Xy|{)L?*iFVZ;Oevlg(&!Oo1FCDJOeY3zI?w8V-tamkPT z@shYGoqdCP|BJD=3~RG%x`wGxS}4>Ag<@^7;_lX>#T!C!X&Wp! z1ozS+MS??dcY?bXC=Nk_6Pys--L5yiulITWeeZYw%6Y)B_w3^cbIzVwvsQ>;A3LRa z0(EaVJd^u-PGfTE*KVoxYYAoGJI~nW>hjLYTJsdSj{)Aqo0>k+Do2_$WdJ4U9(=~5 z*fz{RX85dr8C;9w!QaGTUfG>=!169W(V8oh|6%Z%)SOv?%qf9E#Ve!-TW>xVf98NX zmULHh_tVjl6%`SoDGSD??umPh6NIFNXZr+S9#GupOq(wR<3^M!c-tkBF*B%QE{VL(zYI* zV&nV|4A@@1((|1|zoh34ws7x*>K?Gpp?!sldZzVS@2JsM5s^$Q6$LTI@%S`Zpq?G- zhU=>A{=8!YS;_P-rJhKRsRIWqx+t#2LwxZS!B#4#Zc0;F8Ho@RixZV{!Tf56x?j&i zCFF|t&SiWQ*iLA#0hVADzDg0O$vEiU{4fd)Pp>bckXa_Cq?$?5e~{xr$>2oU$@c!_ zFie}0$qDIJrE|N_?%Kw5Kw6Rc58i4(sF2*82lDPQ>F~53l6!Ck2Xv^``#p5zdXuhR z^jw>{nSHRfD!^FEZ7H;QV4PJ>*G}%%-+M=jlXC8_xUD~d^|Vr;_|Fq%V<7j^Y+8P@ zTkQ2a_NX{6CrAFiI(~XBQD8{dnNPLPl9rL`j7VYr{iu&qYjpZ0V=Il>rJ1FvbH5l$ zal#V58_8&F&r43DLG7C!FQ92mTJ$Fm?uENzTN(g+HNJ8#%m_qF^W=$IWz6mmhh3j{ z3VVhPRugSDsd*m;)PCDKMW2+YDb``I(LYCWnXBf3R#n?gV1WjOK_r%znTR?kmfXB& zQIMl#?CU~E^}>$Pxw@WsYTN8l>qV7M18I<97)=dTb{_yaGi%ZxWv!wjm;YfL$XFqm z($P~@L^Gnx!cs^9`uOTBz#R6dOU@w^KXGgE`%JZcb)uzJdEdLE#2xAheGH(jtH>pA z_@_ytU_UX;h3`S?c2VFLo0bRSMOvwC=${Kx9oWc17QRW%!)4h#l!0=^a-V^UbS9!k zV-iyrWGQsUQMdL|Z%15~SO0S^bnK9eJGip@nXY)s`c z$Kq&;H4ZkQ6M1`(zhrrpPGu86r?(e{$bE%lzUOz0e!oM(DDizfHZ1xHgk|M3M;^(5 zEsRSaVcH9`!_lGai6P{sIUq3eM1m+ygo(lEcQ|q_y7bdljI)dIGiT>lTZ`7G2puxL zJipqRYIR-8fAC%;H%kJ~qeN-DYOlI(H!I+GWVUx|lsunP^k5jAGYRCSezhO-b#^`C z9p6Y_Qv91%zl|yTuS>h+4|g9v-G8sOH~BN4g+fJf!XYO)E9G_1J=aCk{erp&fu|+z$({Jk&{e#rVn&r`erf_X#_9FYJ33t!%az=U=nuR@?{4s- zn}b(v8h|QF^~3%RKik=r>YXWN9oL=S{DU{`(p4q^-)JStI^{SYw~0gcxpZ=}zDa1l zKw{q!T1+!VDZ!|8H-GkUy1b_*GM}?Lsxb)5utp)LPxso6xvR9)^5nOv4~kDaoh}_y zI~QL4%==j;)sv9S2cbs<$5fv&p|SmAwrYej@m7Lrc?#PG2gS}Ej+YwVoeR(5sy_@f zT%u|77gp=6ZhFsH+^AV!_0l=VKS-JG@(GUB2m#2>zXXR^lLDS4+_8@`5E7A!#m)kk zgC(mXVZ)T@6>O41khmg~Jv$R47Yi-?<$l{<^u$@HjB282ah;x5b zlR4ezjNC|F6H#`9xcvEU&Cx0qKHazs{s(VxKB?ATOF+I2ds{N^#>Ql|n|1W=CaHx1 zjxPDvNFyxW?(Q#POfjcOIB|a}#lVYkm{$G10Gpqx9p=SM+ShGr6hg_~htkY(kwQLg zckY16M$0fx-9yk*35yI?bQf{2={ut98IPVQ)hqgQ{shOEXt5H`p+z_gn;=Zc2 zqNT%Gr#9!YhBYabd=3@D#kN#b@3y2(yx3LisosvGg$}xoJz${^^{k2(>YBo;8nCba zI!P}Ib-E-?9b9;xt}fgh3xVeNFu}Ks6f{Xf;g0|>_rG416x{sTpB2sf&+;*;Lpv%e z)?FgHJxf$2jt#Hn4qCkxG=^PE8bvoD4WkXgj7pzql*rGZ1oh&qJU{FPpeLG&f087M zn^ca}jsSOtYO*>>eW2c0)IvV=_rh6W&`wKt4-@UbIPr|(uA_MF z?30M*N#)m3W{n$ZO^6x~z~*HKKfSe;bWS%>9vC!R-~Vt`s$j78g%X}Q`oV5`aYU!B z4_^VSz%85W>qoTR;cePX(Ti>^>mt5*@=yo({bT>Hesl5+4AgQE(rrlEryH+{mSQhO z){J*eEnSdDQrc$3)5q!(FGtGD{g68d^qtE|W$qc`G6hx)zigfzw9Dtpf6zHNGB@S8 zL;hX6;qUDw7myx$OUWV${De6@g+z3}a5^B8os~Dv^BEs;u9LA!(b#LIC!>Nzd>~oI zd~?e!N@6kh5beQhwa0~X&G38#{0$u)rzjf3&EAlkm=_b!^14gTaD&{{Ry6oej7A*s z#;u;2yb#tgR*o|4&!N3=cWhWjW5Xk`5yuD3SI{jB2Kzb!1vM%;E%^>T_la)~zM-c) zNj{Muvm=SVr+p>0d41xPF%PR(ah7{RhH`&V!R1<$G@LXNo*Vtf1slGj)BC$?n>n?o zZF$C4>R%f&LHV{?)KD++$?j1}k%<|1NkGPLAvu?ecpu}>2PQ24*NQR(_a?DA)TMN& z?IlmCjuenck#C?;W*ImO%4^Wnh*+YE6k)Wv^gEhqF_Qv zUuIrwKup|{DU_1yMsG?IA@{(2qVUx(Y7l+wp-P`1w$Gos3EWXM%)n--C~z2;`6mbxcQjZoXQ2z`~N3l^tA|ja+&iVfKFgcMm8@ zO8TpBbOeL#d^(5oq?#6A%(A?OiZIkebv;n0eGHd0S3j#Qbgqa>)q$?$6v2WVxf_q% zdlvj3tY^U*bNLFC=7$gSy3+jf9coB7_%n&SUy(1rcrPpM!(~s*7z8@bxLH1b)(6QrPFg z(00Q#f>ABz9$3f*ZBxNUux)f&Nd>r5r~*_Y+8s)NYIUwjT~%w!)jY{mMIwxg|6#&& zV_AFhWYbN3TI4y&R5PVD4odbCg9Y_XOYu@ip=a#jOY+vToj(HSh>V7bAm?D7UpzYN z^~pAtQzLzizO2TdDoUbiGVK#|R|3tNfhMjT)qEF890uj{53jw|OotrWW|SH~aMX!C zVWrs5SF)VHBv+73tW|qq8d{-B2nN7Ag$*oHC*P`z=hyc~^k>*p*-Z`Ir{+mhi59F}!pRl3 zr}xumaHplkJ>=I2iDwK7lcVK7%Cdy&Zhwl)TyL^rLL{jbgRI!l)M%&Y-JAv{%UsN|h?_t%%yi+BxJ zPB`_{oA2>f$G|IK!#{X#i2OY7PbeVj z*CWz(Dy#L*b3(9&7mrUHBz<+;ajw}cu@9kd{Q7^Bv(MJVsGPCXwuM)4u=|;LgUU1= zSI~8TLR*m{zn1O-y}OrY=Gx5^Cv}{dMYAb;P*}9%PJ39%DCAPP#6km4?uB~Vre8zat32rahc;U z+2?|C^2g+!$K3+0b^j_N`M)kib3NVH!C@Zm zsLX`c98c1a)jZgELuyRE1s=KW!p8}bRI`fQdWGffsS0uQU^m4cW( zCve^q!E8TrVwYB$VsuQ-wxK4x$TPWIZ~p9SRc`x=&AUuT*NrKb-UPausxitM(+(tZ zb9kKYB4ek=lXtw`YVfl7so=lvNvf(~?KKS($PU+no)i$Kp(+;k4a=0RTDTKAwb{Ir z<4?#9V`&FzPT5QeyI1Nxv+g^dy=Hy2mQK3-8tQl`<03+W8Et$DpUOWM$LIQlkoA13 zXLKPTxi{6~1qL~8hb-nAfAF<{+AY5vc5bB(3l|eMWdXo;L-PlD->hB|_29!!d zYI}Pp*fvEu7U;dCOVF3$DTiMrKsUOV54!gXOK-GW_cZ!k45>wh2c90j-+S!`9)h&K zDm|>>yqZWfyLPPG*@x!1jmds-_6kw_KKnrUN?e_?$*-fa=QJu$M6>>$5=pZNcdHiu zWccHqKGDpPL$OdN#=W=A!i~(S>%;DC5Y=8M+=tGlcQ@U-)~e?kM#l275OD`})D!gu z1~&cg%a$_M9`@)^)^nR)voL~UGRN&-8|f#0IE|*MNNCQF+Wqjjidl^{`THpOo-PL> zxxZwp01)lk8+fBWZtd+;xk$@1_BO$i+Y0mQ}+KhY21X8or{NLBU1{7NK zU<*7U(d(a=bDof}9Ap`H`?|OBZKsXm9P5iRy6?Qv5T5WhSj5LKcG@(42cIS~g#!i` zc@QO7#1R%vhdTyoSi0^#w6$rP7S=(YnN?`}Ys#x1D74bjU)9ooHIY)*!0@8&A;0;+ zCF;?UH#p#<2P7vz37_jn*!0+)!`Q>Vo>?{&|7=&~S!`}_F4h{q3J@L^m<|~G!&&g5 zi4T~$-oYGK8mq&+0G6iG=6{{M0)I&sEb0Vcivk{1st=kVqls+}x$ri&KHX)ePaf0g z+sG5=5Y{Y`ZHcOg3@BjBPYXyMi?r0EgmpMzTR^f(qB{3z=uma_7bHg<1@x<@?kGlnvO&)I zf}vllqg4%IyuCSPe0vB4R2&#ua-~c*qSHI7IWD5}O73SSKKuwllAY=F*lB#6k*RNo z?e|=2&f1W0)IWGCFQ#)2ETBUPvMs7ge&~WvYLN=|1$9~?!5ITjBi3$-eW_pD5fn%Z z`fdmrOc?d!=#yc)tU-3_DEqll1qSsdiDG4H>S0q^|Kk$LdUo+ z67QmWM*iD=9?Y|&DjdTz$V(|?9$5~tzrPZ$yB8ZJuR5=2+K??p&%HuHzNO2o*QIsF zsM*2U#_Lh?^MucFA9Ez~i4VFAP`qI)o43@XDuw9ZES1nnIMs(^tDaAaWQ?eNT=E?` zuJZvD#?2y^t;WG$nOUgZ*o{&>3$;y--lk@Hoc}ax5FeGLh(yAqyFFpPEprxej}T*f zx$N9zIHX}eGvb*>i#aO`<-Np%r=~pmdk#yMyQew~Sve&h+TBmzi{fbL7t{mnMru;W zA71@zjb+Bo>C5#5@d~!I$KyZ-o2}!7{#4H;U_cOSPV5{9%hkVAjbsf8a{PrTk%5ER9oU#T~Hfxzcwh#{(@1 zp9;fAIFSrYq)~*5?p7o!vvC@(E85Z6$q@N{VL;x(BCq6|rqQT|7F z8&kY265Jeo6WzTG+1}O0&N454-`9PJi#vh#YVZF|LqJFD> zyPj83sF$o!vmQEVC!FuLe#or!LK&oq;*nQ)%yGwmc2exQ!RCwwv)*In2u!_sFVS48 zdqd&H{cU6Y*;dO3{4Y{AlP^N_N!fLN#6P?Y81j~`yLrZ97aQ`5^uuyt3dB31h$9?IU`SjX-b$^Xr`KIDroGSKoVIg~t=MEKn;0 z51oj=Ac38X zkgrVT9!ky7GEDvlk6z=3$0$lfKq!jU#Rj9xi{p{h1U7N7>XVkKR{^1p^4{sNqW;*K zmo{})!SY#|)FLs;{;}WMOl(yD>yju=v!0c;zY!IKFKF?|3lk>V!94T+FkY1D^xZt% zp8==+6fbzrE9tf==z@=}9*wHc9%9(!i62v7gb*^`IHu0^96qa%SG4zgbjxBOHNS#k z-I-dP{w5KTG1@QSkw6lb=b*lAsgc@}Uu%-QfSAt;R#@kdS8sD0J2d?(&5ATE7zFMO>gS{GCYSG2QnJj=sh3#^ zh(=_IsDeVT;(Pr8X^!4LBXb}lEd?7dS!H{NP`j?=xX4v?(ml*)xOC?r$#G$ZaaXtc zM1%ZqLt$}<8--?~_*lff5lU~25pV|%x?tH{&UjpMAqW{rp^@oh(Zj4_nfrUcPPMEN z)^)q~zQ-}J#Q=;oEQtf)+ne<))Iufvx?Xx)wy_XbRy&? zEa^+jEcrh;jp-wzpScB%V>~S-+7vJBX;LY)l6H|Jx*J*fd5*h2EEBiS)t6dXO8LeP zC%``oR@lEKz*7DcCI*a$T#-7dcV2Y2<+i!_AD4HCT_gd`d*~yFODU;fV57@&A9Rb? z2lchF5ANFM{>35uFiMsXBME)^E--GA1$gRpw3Z%otQ2$EKO%q=9DA zt44b9xg*M=_Sz+ZNW6_BmUqYM+nxbFT?|7g$xi#0k_VzBuE%Wi430Jtg7zLgH#tVm zqQ=&_Bh<3iqAUz)KF&fM$zKedig47k57)+XHwE8@lScO3App6*7aeb)biy}4#J*@j z40oXg1QhA%Za)dW^QtP7ubd=wTW|cuLLEksUXa>L>5-%cG+fhwzWQVD!hQ$<><0(O zi1M0fsj4xUR*yKqNw4#NHYQHPKY~0%!>6x+Ry@j6nD|c+oHz$qC2qw)k2lB)J~vn0 z2-i$>f*FzVjETV0`J z>v))`Gvkp(A0GY+PKf1QfSse7O?Fv|(6&$bN$jA#_-HWLghD&*>xx#>Ziuk;W44y1 zw%@lef(`+{g_!F&0=B$^K}28K!v^P2===|Dy3u`fD9;4k*pA)b`)`?V-`m$jM63@< zHbb3T6-wVEZ%m`Q$qAJz$pSusMq7ljKa1NS`;IpjJf)YSN@EsASB0-_kQy5%R3VHj zf_~GM_0raXF}UGzDAKXVWK5ijRONPwxLteo=by-wF2=I(VvZtqW9LgjA;N?-R{IRZ zu3jr^z=`hV^q=r-6ONtsHz*?DWa=vn8u|Y?AkyjO6l=ctj~KC@=t2*eMH5 z9T_85V7z@KLNwq93q>pz!4-kOP!-ud-5{Y>X}zPszF+5pKaxx@SsL7Ebu`T2aWzoM z2PUS7#~XD0ZCWgw8Svcq7WeZ+=Lx(p21!cJfHA%uOKxDFC#)iW&RJbrR^a>0!lb;zWPivRDe4){lV~cZe-F*V>zjX{TJ;9fjRXhV<0R#Yx8+ptuGMKsBt|Lxy2HL@K;XPG zTvtjbF#TSf5b6L2v-0W)XV#6&T|z)q`YH165Q6ipT`-TsA*h=o;6qU>#Z@r11GZnN8X(5W!U5c}PUb0y}FcfzkBdB>JIAk-l9>J1+T-O!$vHx4am6h2a?K&j>^RXK zV=GTKnD#K&@OyNl91<;A44(IG<}`M{ydAUK0dh3TP1+Ls3O!-ACuF-5)@D;bq9P09 z9@687gtEUm3|nb%#^ku&cxEHo&0cBr zp*TgvGPD3GO#f~-3M`y9NN=p}Qej57rEA>!fP$t^hgyZQO5(kDPMhkP`eX-wOa2(B zheYRCv(O?RQUM-SyjC@SEl4@n^hIqn7(=F+N`aKz)y<5oC@(c7(!Yc6(T+`rWM$yK zH0)vZ#~l6xNioKwX0HaiR2aE_$>=f<_0n9pF`Wt{9~YZCjJ%^`D#kaV3^>u7x;<^Y znz&upeBZ1>v5`9j&9)w)I_LRMZI9dhzpm{O_1AGK^#?5bmKw3Ym;?*t##Cy5h9n;O z$|>A3$erHZxMVT1+4FbWVQzXyN0`QdsRKb5&%uI{9kx0+>c>|N;Y;l*s zF09@F2jz&wF){L_hLu)FiTgHq2glFS`V$A>JpL-#B1sq?wZ#UkQQ(N?51*f;Z~<(x z#wwQ|M(P(*AWiO3JP#!Lxtki$^{`C*uUYfrHtZ(m0!3io= z^W00Vq#88h$_E;DHOVtW?A3PAnY*kN zTdUS$cIueVdIOOX#9q2!9e#DnnPjw7eH15AaP;Wod{3*8o7Sjv$DyTU%h!tzOmM)J zSZvnggsfx%kDM$1L%7u&zM(_SOi=_S}E(ii;d0@j<~LNaCZkE>Wcv&JU~}!sp(Tl zY>m6r4pln2xC~XvZY*UL|4^+iQ$grGI>&%j$M`$fT0j?3p7wAC>8h)I(G-<%w!ozi z<&&VrmhlC`aKWN1xZ8Ed00urdC-w!n#j2gq2^+;=o|8;n6$p27NH$9n4q3cZSGcv_ zG1$+qukmYm`nXm>`-$FuImz&(vLrq%VbSX)27g)N5i4bDmb)4(Ntrq#pk zGYhOqy%@d%F1F>sDxs{j907AC9Gerhrxw_iM>i&66{ZI@!M7BXYUMA@>4uFSr)nY9 zZi=8&SLJBoeA;h2MEZhR3kI1O40 zTx=P>W);uFT}76>3eGi@MdkH)tGbZuT9tbjzm_ej_kLiC|rE_#FOPQ&Q%B6Ga zh+iu;Aw_+lR9Z{${dHz@|HNO{k`MBJA*JtY&5}L4lh`mc;#uD_TE}gt{M~Y;XMRfr zEzgXuv zMro-}4D4eyo09KzkkFlT7*v@#dn=7C&{`PXPvfg|eKZug1TEwpeQ=Zrp)?lxFh=qZ zUV#n^CQ7hOK1yxvTP#ua5&1f^i3c9cq?bbfe50suaSJ*9u0`>7=vLcS6?@a^KtiZG ziK8GSy|A-OWctXB!IvW;Dw}v4*@<$AjFHi1_bVT^t0-U7Hs}^|Wq_W#*SOmlWMpI; z-|LiZ4iFR$N3X?NX3SVLz~N+{>&I1>?Jo-D zFqJ#2$_kTN&Z8s{OVF7lL(Yj+WHPDn~CosR=flr+ypY7$R(avLhNr`AA! zL?bXZe^bUGE{$JP6JfJ~kp?X)-rkibQYfIY33a*l$3f>t8|BNpZ*d9ZWGhnvu*g}Y zN}~r#OOy%w`D!jZ{JpSNrs~O&#ZE@u*jV$(xWWs5YW6Q(7e_1ug3EhE%cH z8Cri?l`5y<&q_|QKTcYS#`HeerR0pD*Ic(OC%DBH7eqYGEJawHAM5~`-3qMS*5T>j zu8PJ5+6@YN8C@|$GSN6q5Q~*?b4v^?i5h7Z=ki<9Z;De(l3Z=;?T<9Z-OJ}wD0&aI zMzTd1ZbHp{&mU4Xo4;>lu69$%VUSVkdygGydar}C{RD8i#OuU^@FfkhdO$Bl~(RS385i$ElyKgF|*poe2 zkieUGCM4*{-;HQ(0+C+VVSpExb0l{bAY3ZEY}XPc^v+7fMMPI#FMNL(td!$dp*U@p z{j9l?sy^H~nO1_ZIul`HUv3@AU)8?86REW0zIDlBYvoN!De4IOu0KTwT|Qte_R^JV zc>B$KLqA)?Fey)eaV;~KG{z29=EBXzWqeHB?@C$6`4JJnuX!3Z2?A>L6`I$pwXMTG zP%Nu%=X-adUH-w#!d@m1xwpJ6vWaUnX^^FCmMF?=k$qBLOZ#$Yi+5SIOW)H#GAHeM z%iECSOV6jb(I1X3*a1g;0($zT)bby?Z$9?(8(XoP6zo8k(Q>?3TEow*s=y`BS~sd8 zk1DYTI;?N#JE1VxpRjx9r5xqs4F)z<^+N4Kq==4WHe{evsZa>Fzwb95|2A<1iq*Xu=Gf$DX{v{qo7E`Rf{+1#y5F zGT$bF(bYM%_%U;tpqnPpFc_#UuUN;joY{h>Bcmhuzx=WPUxPybYk(t|ZK^YV>YKYG zh^f4#NNYNwjAg1OW^0r?vw|sY;`7^XWI_vXQEfKCjGnAQQQe8jN-or}&qmw+Go%-}; z-45wsrWY^TC?7M#3|CN4U@1Ya(B{3KK^vUSMoscUL2%aESCR;dNAC-Ce%46#g4x56`uyE>6}kkr~4O9ENrXF1-P?857>L!*I$>3KxOW9}YvYdxVl|^E(4U&Ac9CrgFPT!`32@S56CtqRK@tMJ3a` zkj()lqx2{SISK8Uas6VT!7(Xw;p~k-P|!)Yr0=V36E(l=-C#HD@?5oBPW^HJ3t(kH zs8<5`%m=1B<8T^}ce7}#KN9E=>%{eb{q1VVdpZhnR}etMFS|P)x;hux7(7R(M@K~6 z^sJQzOa#~QewqJ4_U!}hwD)=%kwDyS*&i>qI~D@E*HgJ(#4}odV{$` z?e2J;-aPYa*hz(?A$Qza!Q5)Q2kX=V6F>|&qdzbOjYNamaP zsQtv9vR;A8kqVJsjt)^jM`C)fEhxm24<&m7wAjXM<(cMQDUtfO6c$#%6a{G^c;LNIg!b?D6n@GRq8-oBf~`{ZN?9!0^% zw;fuw-XnCh>OH`bd!oY9NmZkc8h>O`xq2i}F=sGn^UMJz7~l%vp5FR_svgx;qNH*; zG&^Uejn(?SS@>|Jt)Lgz?9$3#F&_Wa&3Y_{#lzCzv0MLHqI}-OZwVRK*6lz0+gW>&1E`j4n3!Q@%+= zk=jm7VIni8R{~?@tgQue*$3^kIe^{tp<{Q1uGg?R($>zRL`r$hPc}6P^E)tKUZ=3n zWryipj*(35RjH>;b6(FAr5T~&gZ=#d1Y(l0IF_6x$#0*en?YsXTDAY+{kX;dKyqRf z4@t<|9msq;T=So%1vxIJv9T39#t>L*9XtQ}9**Ulmjui7(yiKaGOQj)q`tKX`qQ`@9hNhJJu52uf)WwPGoX+RM&PCpg2Vqrjac# z{&x|)A=HR@e*j29xTE5M~ZCKB+F#7ULg+a#bMx~O38 zp`&9Y2zp84;03@9RVwCtM(3vqYh9i-wEnOU?04BkSyX?qWoq@eZ_K zx?2(Z@^?K@Xv5k>^rsM>BDyp-a!xX4@abh#2SPlM= zvtv*2MokTtu*qDP9eyuR%KZgh285-Xfb#jiv>{EGet`j-sT@@Jvkj~}!=oCs<)t*h zD8zuCpzd$bmFw36D0n}9A11Vtj5w^-x3x58XUZlaWN)f5+WK18_Ds`RK;-h2>r2KU zo*6P{_Udj}ZjDHs8zX>6EM*t(alQL?R!8}Og{p`&+2{Q-ODCIYQ>x@zt5c~LRMz>f zrsqL(@amRMxXrbVy^G_3OVRB5#cYE5G_4x5=@Z@c%xrjMNk@P3O8j%7Vp)$01>=>G z=|e~FKU5%>4}I-P-&3lS3J8uGeD?mb&VKj9O@!OTwImA7=R?6Z&EqkeVg=4V&eM2TY59UCtwZs9Su}kn*C^&J*ROkI=X4w zi@LXBPjvK@^gJz{`N~>%MYxPx*we;Qr{>LDudM%l*p#tbXg0x3Rq3|oP~M0=oFhY~ zq)3{E%zvvX?=YLgnQkh4&OGV&A%$!#I?h^rF8B`S8tpn0aa>W0CPHZCb2#z=Y9DSE zF8Vge#r>qAOkH#;*_|rB<;yx9JSzn$U&eNM18KP1P!9R<#8_lxa;|E`P_~-Xx2Nsc zl`?@HV>A4np-=%Dy$7HBhwpj-7w_+Ii4%NiUSW1A_xOB0 zD#Y6ik5**YZ%JO-wFuz!2^HV@j4JCllIU_wSH&RCXf%%Y&Lnwpwl)r7v6A=gaA0w2 zif7q9{)v@<&nw`SX}(u})9j`dmZc3gnoxWsKGnA)YZ5uQBmir2eaAr-)9e9;i0)2s8}Mk z)GVB(Y?mJq75vvNRixEWFy*QCxWrp!YYvg0R8nWdm7_9h247vFWE~#US?$9M73GRk zB@@930~${S5~Z7JqaJe{+Z#y`RSfD8x9q8a)R%j*?8n{@twj!(Z7DnlB4Ub_9$pq6 z2@W<66x}pVUBAW6`QTb@b5NUO2Q`^9iPuVx*x46Ck1yJb8&lkzCB$_oO%hFo%o=gx zu;!aK&gdGy>I1H0{FW@o!@pIQH75;VtDyp~_zHL9WrthU)W@!K<|?(cQog>R_zqb*jk zXD;;4uE3TQWC_D0?Z~jYkqY zUWpY9IC=V)8@hZ3(ZKW%L#+HKQd^0YYFTF{L;$_g>TVrcgTQfn4%d6h#bWZQRn zwN;RCCk55@w#&%^-J%5MWhzWGPt@(D!IsfvDiA5h4VnifP&^C@kis?Ms2NNkIrl^@ z{`ckn`hcb5zNr$J=stTAKj$vh&g(OA3)w2NvugjUsuG)9yET;~Mb{>}Xk$T@L+NQq z?f8p(i%Id%;?H;?I@EVun@6S9@Oh_6Ba|4OC)$OtJ#1S*&af1VU^yz|BUi{vrS&-BX$SP`>&Egu- z`q&e`hIQBmjEhYs9`3G6d}9qz%-6OvYSzznW~imOX?a{^oXRRz@rXYEFJTij94l0` z_b+LThHJJ}($pfx~5h~FOY-06mszS7z zw>NAj!oDMY@!;d)5h8`HQAi~ zH*EdKUVD3f5OOH(-Pfu9P^duUBjNYOKHid%|psaI{7CqfZLT z$NfKyb9V!Jc0_cQQp)?~fX`&~|Mz9_0* zi_D2-c2b!Kc<?SwA4qh~KtQuXkL_2VK7T!#4E>Q4puPm!}Yo7O} znbAIP&K=&Y+Ssv-))H#LC^n=Xcx2Ul0;3cj+nPIB{RmriwBInGpjryr0*(=T!4a9j3sX z56$oq{ya{l0^QiSBV{e#l3P+pL02np^z`TU=-I}w0y$lOr%q`rKdvE`)~R)xxZr?r zlnYk=JuDL;V5r=CQX*HsGyWlO-7DNzf_SFiYRZRm`Lm%UJ-yFpTT;* zGG(+)A}ABp*F_z+w-kG)BBE2t2t>JqQb(@DHGC*?=90@XtG?ANx!t5~-el)Rwn~;K zcm>LTMo6$`UWtnLy|h3GY+3@8%RZ@h(kbyZM^tCKe73)%+whWl^jkd3qXI+6n)iZm zKN5L#GnFBQp(QtzmRZ(V6ktf*keNoKzUSZ^ZMPq6d)eH#pw5)$E()7MvK&!pttbglsui zZoS})un~2+?p-^oM+SsF0*p&br1S9}(N#r(KS1sVyLv@$;|Nis28{EB!yD>J+&8Z? zZd|;V)CssD@EAG;M5d#VPHFO?u)t;v4>%X`1$ z8oxHT1}2%^_I!K5n&tT|S!w7%YbSDQ7PK8Pril{Bbo)l%>MbJ30+@OEal>&BW~jEK zIT%0Nr^rHv(jwri>}f#gusr|E50dCY@-d|vho*_$SCRXelYI8$tgv4mnwwT0tNQq^ zh#kF+P_hl!t8nICHDI47m8Z{Kb;l@K!{69N)D^C!L}4NkAYSY$Vn@P{pK}%SHt+1! z%yLe<*eurZ)7;E(`>Rp8+m>rZ~9(1vd8?*E0#_Y_Z$mR|6eHzs@hT zn&)2cw=bvHkA31E2rI7>!ZzC2xwjYK%3u1Uo+$^>R#}CGR@|>rjiN;o^10l?b!V<* z_+2W{4%`i7$Wz|*M#`pOj<_9=8hv=b@$=;73PE-TR}&J$KLEsPC}fvf=a7zff*6yQ|LwH)|T$o6WDrWmgK>` z`LdPN)&2VJ9r;Sry0{H4p>MVeySAkF*WSo$h9cmC9|Q z_Y(vEI#=P7#FT$Onw)8{mvVdm;04(>JC10xt|b9pNC+Kol0ZVL-OAt(`^E;FKBK1e z0>9Jh6y5E&>vF4~yQx8p3%C{R@{OU_iD0@VY>aZ>AfYwj@Fe3Kf*o*R>+hNsqH1~P=Nn$*<$2d5b#rK?%Aes%o zi4>Un=>bDDHMzacCmDxvz5~B@Ya|~jDOh!FO)(yO-|UrE<=6D6|$8?fWUN z)9iA-Hc^>opa87i1U%H|5+OhBC=~)bx86w@5KsrzMC|5-cQs37qUUM>o?vn+PLIr5 z>^V&7?+eXJt`~L`19fFZOdrW$pw!HLXYR zZ+{9`3stEh(Q#cec;e7%Kg_33nBUT5=Uf&a%lPDWp){l~YiRPJ$i%*S9E8Rvtq;r{ z`~w4-ng&8Gv7Jm=!!q>7Y}tnL4EP$l#+t|m#W{@GJ{=4bxQd(WCS{3d({|na$1NF7 zABmJ8yt~_^R8djIBZwZBFF$oASzaW;e*#Eyb)Ewy6l`Kl_rA6K@2%!!QH0!=RaGMVmUExabCOk7m7nX z?Il!mKk3y>`qBkdo6s7YsMKH_+u^%5Q=;~6S)8>sVxZhogG_=%u*cA^t6wLT1<6m- z22}R^z-`L)opawpIj~hd4+6{-7ix{S2Dy2OAHn=4zl^RM)?eUJq)-feA*8`&mfD?} z@je6oecdF`^b`nL;{{`;C~3IsK4mMv51j67pEC3B?fEYq7MGmL5}mls#NWX`vzl8Q zMX~kk_B=@t{KGuD1tWVA+wBN6+9TPr5L%%BzL-+pddYARJybRIQfv3=59@z@ zMy5cyO(q1YOzkm}jj*=%B^vVCEVg2hV*G9V_P?TgHa2oy(0V39F>CC#&T1RT|9kqx z`B2#dO%Tn*AO6U*^hk9NZ~(Bm`z3Q_^viD-ir?d3KBcHL7L5Nas;z4#+9!HDC=Bfj z{jV1T2n+Xzg2TSFeZ}WB^K#02LA)4SUs_SdS+=$Anb05LVTK=Ij18V;P`-ygZT>^b z-XYQJrQrP05tF?H1L3RT5FEHNEuW#$C$wdV7hKe;)Xo!F&IOnffkg>gmsJ!)Lzgj^ z)lWei`{S8qMZ<~0QQy(VW~rONEZz^J%LHy*E`7)~vf|uV?N#7RkJ3mV6NJoP81&_2 ze__;y%$6L6`kL@8z0SKJyyU)MTwJ>`|FDe4KVm~VZ_<9TDkEr2zt>*1Cd`N|gpND+ zK3J&mKcHGsbCrQjp>yKV9+&(GI&PUTFKa%J7*`ccA(|DkZ-~f8oIr>DwgT2zAD)mhmSH>dK=W*``~0e z7HMewrineRZx4eeflSgm&to@rtd&&~(Eqfcp zw;Jqolf!&3Y%AcxX!-{KB1M1o+@)#huf}hO{$aBLgS1W(3|5t? zl}~&l8@(*O4R!a=y{7#WRNa%l3$P>H9dQjqrgBG7yDbANe_GqeaxbD9P4I=@%d@?x z!B|SS{%vysqx)?dQU)>WDtT?YPkL7Cw^7tGtV^vb_!4Q0+w{m^>5^;a7zd4>vw{&V z&*D{WWGtP7`hb!a#uwjir`cDc4rZ<-*DI=}hG75aQ||fq+yW`Qo8Z+YC0Okls`ObBTlbeC z7KlYdS_1ZBLt-3=(UlA#EpBoYQNrD#d=>!!_KL*!=;2pIZF>(A@@*<8=i&S{eA<8M zPlqOtTJ?K=9v%ql>QzH;e+3#AVQ=c4Pr@4u5g+=dBCvFJ+^)hu*XMbuK9^uKnH(8x zhgL%OI@yHJOQqfSD=f`Nv!lqB8NiOD zJ4;~Rls&>Y)7L@953p~5kJ?C|)c!sCNUG1{^YBm4ov#-Mi(lPV^){Bq<#`-{BYdOr z9ii1`J2|PTD;y1?>!ds=Rn4IoXBnLmmAMkUYDKrtU3@EeGrpc#K`V5yVkjELN$j<|dQv^GQRaxh7E&hjTyewx;~oVcbmGR_cK|+B zTU`is({19s=yhQJbY!(wWDYF+*wHS2quxZPZCa8YkRn!2P!-?9P@Z^(A&)ijQd+ii zrSxdnJg>-Mw)r$wqZ_C3aR@%78uSsGq*fZ0w8z*q$i9dLLzB!bmD|`j4L~YIw)=OJ z@%`g!LJFI!vl9Vh^@m_Mb&Ddq=T0<@xU0dsOpx+A0f8;#z$e%TLlA9_VXB9y*~o>3C!!Oc z+>RX;l7@{IBs#TCo`_0gy%O7SM{I9JCk1)cWwF zW8`QFW$|NJg2pmRu_|5FL?g2_HFvvtd`96;bgI{ko zKPeLqQq&hHpo|(4?XxURxYK?-sjF&U(PqvvRYYT6>`Rq$tN~8JF9M za0P?zz4yOl-qBo~`{xlLBz{h!>xAevWcObV28d^g63v_Ib15n!EKFNZqQv+8bF1b1 zxbpd{HZdZ|gZd+AF|Eggkkvy94NX#S>3_6?uzQJd~?D zNzXi#X08R=53v7q8+@wBjd<51D7vsVWrf|RsjhE0NY6!0qE+*3AF$A@ljMQ7%0U$! zM?aIh%=j0E1|CqrE;fA6A+@`njyn10pyc!9mRLgi+5TgP0b7Ql(|o7m9_H1gH^_$R z4kA9Jn1;NUg6>mXJcDw-phixU*diq8nUmR`fysT^WIz+N zV*A9Im?cujyLiK)Iw!d)N_5Voql1l8_s85YL2ZD@EyRCgZstJuLc_?MH{!*WiD$&& zuAUHK$-JVAQtmzgB&)0$*M&TPEc_&8-%Y-EX>s)rmFYHq66jJ6z#l~!(E52b<~r$y zb7t4*QQ;`F)40YwyR;;OQ` z^W78>3Xj+TTr^+^lAKMmo z6Ur;3UJ_Rm|4pd$MxnJlbYUjk{Ux!yD#%zHY*2u8E z>f~{M*rC?f=dbvG1eStFOcrw*o>sE(9tgR0`%CAiog%$VtHB;mNI%d@`QfRzqUe<1 zwFm924dpUnT{~F+anWS=_Y|Th+(9Y{@XllK8mzWnA=5!~<=Fp=*guD1H-*HDT$72{ z`U#Fzv@yXC-dy^wM%PCvNa*4cb`+a_dza^UiJA+U2w5OqaK*1KNPs9;hm}Re4l=#6 z{@{$y*{AjIYs85}@wu?97#I$i#}*0IVtrV+d14yM*|1@3!7|3adl_uow0nyOx^sa| zhH&oNjj*0aIltOe z%7p5f%V3kP`d#k>pRdQX#0-GwSr$gLY0(x*M%B$YYVn1gJAX)6g{})qO^+8(6qm! ze=8x_L?V7>&8Gn{Y3Jy=;zoF@q*ze?`26-%lzt^YnWY zZ6MbC7e;p4Y=e3e%Dw;TgSANr%BHjG4mR8TxM|X+v(T_Q{a&0n{YUds$cXx0dX1bD zn6ua(OX$%UQYK6auj3A8+-z>TQ@y5%@*Z3vT`HAk_OV%+6UU}mz2x$`_{kL}hb*?W z8}^{2Z*y>JEr|rh$4}|~coQL(Zz2Pkmxx2$zM!A88O?}&LYFsR5_AV+5Y-q$*Odmevqo(! z{uJ#1IDkA-ablZs}w8`)zNVHWzbIUu2@#Sp{q_NM2x;0~x!L(uR9z&Qlf( z9~3lgCZ}&Me}fR=^5uq>j17zLIK@t~+Ypj?UMf&V^O$pvjW-s2iLa;nynnU!xGZ)a zq#)it(u)d`EiOqM5Rvsh|JXRK%u*1|6GJ(-Z(T;YfDA8(@y9r5iZZskRUN(aWUMmy zK5yaVS}-moCojLfz<=G}u%X2UE?ceHtI>hOR|#H#DNcWBlD;BLqTGx;8&}$~6Bs#? zD9RMai-=O}Ji1yi**JRT7z)cxmy{EnpCf@Zr#2wRHB?%yLM7+i>Q;y@ zqs%3X%Um(jhQ*}BBLN({lzl`d1=%vid63#|r^QfxE5SOpp!1m2eJvWyxtSJRY^S{I z0ps1=kYnvNIOIp~)K8ktnoA8k9TGp3(}%D|v~hr+i8e=HU*Cslt(CcsSEWVJ(4XL% z`i9M5%?!WH2=@K`BJ8e%tszw7c9=_H+o6x!u1X8*C=rd2NH!g!%!XU>^}0&QDX%n^ zR;miwv~K?uY6V|&&vc@>e2Sd~Rs{ZF8q4c_AW8mmAOL6T8v$bOI5QJJcam9a^sTk8 zgUQipG7m6s%Hzc4iL5F;1+zV;-Tsk0+So&pg$tm8V{*UFOPFdcuOn|haDq0;6cf1= zTV3=c@zS;DvPw0YWv*1%v~#uN!AKZuSS>I95@#hS6%+DotWg_C)1XP5_|bR4-X2q- zoXCv@>O;z9g$l3D8?`5;DHY6Kog+~b>?7vLeK&TI)YShXGuPfQS(XdR9Bc;=N__v+ zV!autrk**E4z~3k_}VjDYxdE2DCWMU86PqHqdt{$HZrbcvbC0A#NcBZsFyP5M>R+| znRgyeP)$daVb}&Uw)L!ys7H(|rXON2ked>CYToe(CqKIWU6E!m(IchGVu>&3yY8mr zc`G|;oSOl243g*3Lxm?Q!74nAc?@-i`T;4(^uCP6fJxJ1I0QVbZ>ZB-2$_k(wfw^5 zj{;wdRyYA^PfZlP1#k@7o}@0mEaiRPMFaDg8S9~!!De=!GB%heSz_$XfI_X_czW?^ zT-z?4jFv{bb-u1N*(gk1#@sd=C;JjZ&v^ZQG+sQ36CFz^VNHlYeS7nYaHqF8$O57we>Vx&kdRGCe1qSq?%3=(uL zB=fE86uTg&%b+BBNLtN{L=IVy?-*mzUH3~P`aMA}7r63>alLyE95=QEn`uvYkY{Yx zyVqYFYCZW2L$T-A{Wf|CJJyjoyJ{)EWO6@pp_s^e$${WEHD=|oZHuv_N?8Xbt?JP9 z-#qU_o-(;D!K9id60W|Qp|vUa)6VB~kH~AKQ8B7*wVqdp!{97+JCeKsrV zi#EqSb@{CGUcPUh-h-yx=iOnIj&#zGNVDnw%VZhZUfg1j&BRRezNv_5mhht>HXD$m z@aeQV{XsYbv^L;`v_7Om@is>(e99Drc_8Pc&J7VBZW93@w``TUL6+E>(4suoPzsQ-Fb$fN0qOYaTI z8KH+=G1|U%IZ5<>w@`cADsylNCF%_;qoHCKygzLv1$y~A z_q6p8MIYz7$mi^`X{5Q1-Nxtl98_ufvvxNVTc&tWik|0t?uUu_k^>Dt;FY4>#Y$-1 z$bTopj*0d7B|iJ-cI?Erq`D{x?~aAxOY^@lASF{Jzc}VEs5a3MMs&%n(dRof#zFoq z>8TA*(yiG*^nTDwUQ$xQ?;LjPl+K#w*(Fqsd;2%j(!-5i!GV?XePSl|Df0=`t$DZ_ zBV7{ZqvCZ|#rrV9H&0h=E!{G)uwS2qRZnfsEu)!vc>Za@-~RMM2`69nyaY+K$26Ol zjXE}yMRBEHJ_YE^s*QDStk@5$%$g%EkhLG-9JE5Pf*-nis~}3}hp=DnkF|`;v-$~X zIqJr#d`5OXC8Isb?U3Ppw!#@DjX>^%S=(*qxJ15TwL#nlZxQGP{EznuegbD4zcp8` zfV&2=kcJ;J_}*`}JiQp!2-w}I2ijv^3%e7=mQ8q!eZJn?TSoE{nj6O*X`5bgx+KeJFf9$pvOZnxWavokv~SYfjw3-B4HQ1V)eS!xXpiUlkMmf0-w zqPvgg(=vWQSaBq*E%+}CMl%-vMxZmR+?^h!l-QDCh+?*3hi4WpE6Krtb*MooFEXf^q{dXk!V*F!5@u)z8M- z%1Yb1n5-UHa0dGejVszX*At)FG*z>QkFbEh*5Izl*S^7 zC;a#&iTsKCHj~>{|B%uOI51-&KPXpN7?h`s)x+(9BP(OlnLN;}G0u!C1YL+MAQV{? z1#@^E{K)z}$<8t%8#kIV0X}xlEB=!{!sXg_C$BC%zq2}+vric7>%XBgLSjw@4!g5e?ilDo^l zX!CedeBOzae&Zaw<1{&TMRgJ-t;U z-p~O#Q-?V@ASSk0igCfe9ukOJF$j?qq)02&$PhCD@RNYP$+?@CifNy-tU$Jx6AClt znhja~8*F&=N#DG9w~F0ztP~=X$c8U@bee)%Pg@Yt5bSawr3m#MpuSSHAJ*y7zU!2d z*auHLRpjk?DkeHw#8M8_Z0|0PLsZM+;reP zo7tmRMJ0TcsTU{y6pwl)@?lPwj1zhn6*IdtO{7wD#@3}&$Zr^YX9SziouDvTImrX`DVh?SUpy&S* z>b_f0tFN!g%>RC|>ogUF8MsZ0&M<@WpRIj5#)=^>S5DNOxm{VOr0iaSFPu5+ObGw# z7$miFCXS>2a#|d18Va&3U%joa&*=X(`Ch#ZrtM6{#eyw#qUQsWG*oNeuoo4W7RPxp zbLn}k3o#H^@e2c#cVKODO_(69+~Bji+Jl*DydMrcP)hce9Q%SiG^L=8{=JFQv3lWL zHib12D_$|qT(l*mK;A_r>{p6zhpsxeCW=OG9k-Epi*ma0W!4T|T#osqqnM4}B8&~Buh-E&4cvjcfVP-a<~o9e$atagp|zb5h3 zHf@-oWYcC9-kKbYfszbmCU5fsfMAok;)zvwDIR9Y)boUD%VdBGve}sPb!XQ zdCPvrd5>sZ)Px#YxOf)fwgxL_CZVIr>5k7A2?p{J7?Wt8WAvT-P_pIYgMyPW|3-RCX( zn&d?8J(g>qq?(7xqluLl_VJR=PFyPxWVGCug}h-34##9&4p&8hO#sYYkyLK;tB9E2 zHo!Va-sii~cKSv$?aXhZ{M=%%-+F!c3?C>)rrpf!UsZrt`Xk0dXHNJl%54*r8hGGo z-4ZXUug)3PD%%g#8^7S@c`@iRB~DQuP*Rc{E1l+-#eYp05qb?JEUQ`x$;-KKMV*#> zpw-6&3ea-lJV7qLE{XP{!#!0Av08So@bUC+k=U~eaY~Y*l)DY;FAXe@+BDVY!5T~y zXRU&{n4SCYdC`aJ-m>08UfXfZ%$Mu&eR<-^L)+mNv$I4>sM_Utur=kxNw%vtaTY(N z)5pYF_me3h>@LN$Nw|+%Qw$OzBL30Up!N4~Oj^ETj?#Q_mMSsx^)ml(-~(5dgeA+@ z)4u6&CrKnWY_O)*KR}&CXS%bG=}WAKhR?H+CJ6_)Z$JGUTFj8|mHK6<;LDJgq*Ve% z-@&^dWH*100tl~R$y<0;jn9BncM^piCo)x5LL+H2;{5qE#B#3D#MkLqoYNQT!@Icu zf!4k*c2f-466_9|F1W8?^0QHzI;W5zx_{w1l?W} z)wpN*ZFnyt#(5g|titpX(P(^+rKkOAc#v)9#TO{b`AEXP21_3ZpLkTo!_zBf?|`6_ zwBDZk{ykDAn-E@Iq%T2;X1r-zujwM^16ALq(61q1DI$C>v^PSH-hXF)gz^3R<9}vY zysEKSBAgtyJ1O*7gJT!xXRw;LfqQp9=AJSe8r1FDG+18K*Z8(KJ;a3vkv^jre^A_) z=7XV?ysMh)!J|mL!y9SRGrhNgyVndgSM7CU!{IVue9aiHkgdztxw)8|=6%?O9lIgh zmux38c1JhMH$ekiMW3&y(eIAKUGC}eLYOYHC=5eJk1GB?Ty8yhOy(SK8QrR2HQ|rM!hCA{dw0FRylmoL4Q?mF!qzUaeFz^B650wfPbJ47oPG=;%dE-xzf_1ohy@%CleDsv{zaz7fu+-k@M)L5 z=9jJDRH!B+kz7_1b`-^+SEh*)O`B+<*q}$4YTEj+&Nf_b@KeP%JyJni2Tw}Ap0mu| zUW8S=v0ZvHSGYp`YGx+;GUhogVK;QT!F5tUwK$Dyj>3e$K@C{^5!R@-%I8eAXyoHg zBpRfeVw{TWrPqTw(u29J&tlDK95iaJ>zT8^XYK@$lND-Zlm67bQTdoSUP~C<$^|*_ zTe~i+@jD)aUW+u!5jc5#_r|d87GSrHhDV z3V*YxXSqW`Q}QG|FJ*>A4fdbxZQwP+!h`9P=DljiZ2}yp1mRg10_#+9&<-EkulB z!YvHMRkwZtO3L+*{N!LR$e&XP1*xRZ+vCZ73Jj06Die#TvGhl9c!Y*~wlwvZlTz>O z9_VQPOnX_~iQAv%^S5)Gp zcJ8M(HpwJ#PO)9XD=fC7kd_O+SaUoU+Vk#+zlSs0`J_0`D(m=EpP`0@TW4iL*rrjIE#OUo99AsF)>7l%c@+XY$PLz{`8lrEt9teq1~$Su zNU>3pYS0kjm}LB@2I5$r8;YmP9g4d<%`uR!0-u%E+Mbv1-EFfvuA}q94+M+lIb_!k zsEjU)?J*fnj^t#JXi}yB_85D-V*Bl=tWFDzUO{lyIk&d`c zsIk{1C^|#$_ElrkF?%;Yd6js1mpNY`o}X&dR6c0&@RYpoyz#M`;GcH?l;Lo|kw4j6 zE^5@maz242wszBV^@OPYFX-kopgLF9$~S2T=p+N)u#Q5hreSF5oYd=xi5uzzjnVBu zfx?F@cZ7@jy>hFW+TYh;TDKQYN~+3=#=54sWA=6j=UW;r!4Xca>y=+WRFRM}+4-2W zu$|_9l5EyrbTa_hIULz%JEr>DKu2w!k!y>+BgPJ39yGGBF;Uih3x6~!lr#% zteeCf(PUbs1rVj1OqZ4kjpX{)z=V5Mm{WLuk_t|fN4VsNn;aj6pQVyB|Cf=L@G&u| zYq8R;+=>Fvmqe?}RqqJnqjMXxAFaDI7(cUiU{^35ZFWqQo-(-Aj_cTwBD`dnWxtb# zjtslQxu2=@sL&BMUifik6f3Tt)0Il~%_aISn(GknR4*1f%gXwkuJ~?gNe^`Z%z-#ZsP~u-5 zv)S`s1u5pVqO9e&<$mwZu75|&WY?*DA`TpX9_vnr*%!`9rtJ&{GK#RVC82TTU(#KS zjrsm<;nsh#l8&t5?;w5c>lb(P&Am;j1J%+@+E;%v{D+Tqo@vRdYRol3qm2&J!dp)7 z3VW+v3gVJW%8IG73*AIzGVju{0nLjn4f-u75^>s#=YEg3(U|X6UsI4C=O1`qR4nYx zwRI!=cG|;!)BVSKoXG`*{ieVT%CFL~rTgJ-tgGNzK(Tp4$?RR?U|+C~4aa2PfvK3B ztlT_X5>W5xovxF^22Do0=#J$Mr0Jfk#2(MT(MKOZ2kbr!B$67JgqE?JX3wfZzU~yq z0V#h&(%Mngz>Vw@%b7b%p9w_Md;K3fTD^{W@k4?=QWoBT{V{{x0JC1CO%T)2<7MwC zky@%7S251dUT=ub?_W9P5R}#Q$ zBThaG-J6cZfs|haepr-y_@3#@=J9i&`;Fc^k1v^AU3y2Y86EIR!H^H2byzVM3cC5p zLw&&3HZtbb{%;?Gm~wZ$`B+-{A4wZf>>5-WGDL%R0z4!pqRy%~+Q zB5zZTFRH;&wGM&%sXyn;*SSg>&jFs`SGv3=(*zh$e;kqWnu$|=4aQIrrPJ$jyxpjS zA#NK<3xR=vK%(6G?-bO$A75S?Pb^iP!~9l@b82z<<5KN%X!3@{2yC?QLu-3HpkKx{ zpL^g28{He7u71J+ENis!Oyz()0t%j_zcq0?(wM(yE%Nl{BtwKLzJb7sh_0It$HNVC zp-Hu9QfnsM_tBJL&>H)z0;m%SD1g~w;w_W*@A!NGA8`6YE? zPLbbe_nAmZr{?*1B82rP>h2w(Oww(K}H#PT{n z0;;a;I=?vh&Ji)Mdcw&0P4C}MPXCY0ZU3|0rbPy2{up$vnWy=r%0f3^GNOyTXsKr z6^L{F*2&PnL_qmjublEWE&iEcomItGr$IF@fW9l3DJk;J!9y>`{Xq5Bc(RVRX{F*P zKIK{FO#{4M(_dg)NW)fJ8&G{g(`0+rt#1zYqN(NC^KGtHkse2cPCo}S)ujA=x9smX zNvrx3Ya+_8*?4E1UfcAe=p{--04cSz58hB#COd^fqsEU?Pzaoh2)n-=LbHV(KZ z3lj>ni^{=de>Qq&=6Yg|*YuxmBUzVJN$uGvikLy{wwvXFph62*+(>-2k=9I0lAjK9 z3i<_L9{{KQTK=mtUg9x8y7NkQg)ZfR4!X8nYKZc{74h|y4eO5vgzB<&gA)@c<0Ykn zxF&Y7W2QD!su+4kcK&ZK`dD*R z1UeKgoz6y=*fC%6TY!>m)Avn043^&s~?6N}KkAjk|U3p)02W)LaafceE zt4PX`Z8}_6-x0ZtXv?1eUPS)?tT_L(yYk=bg2y9p{I1K<1a)2K7f*#A_SKAMsl7}o z4)Q}4RobQ&ukqrUXtDAO-LOq44S8tW#^1VbNFHwkVBX(do;B7kEXdqDQZ7@Tc!f5J z6KcxtCx7yAs7|N7rLA?!{}7tf)?%@M*Q!`Eg(RyMjz@8=>W-=7M+18vOGYbA$BKy> z?48Z=2CQB)g#&HDEvpSKz4?E!NmB0n!~$w6!_pH7ToW_KH&! zIG7fvLp`$3Ak!|qjT6H{>I_*vfuEk&zB-2ul-EX3*%x-HFj-P9y>sJ*=}H>n={T$Z z0w<{7evhJt7Bgom%F@8npLr2sob!0^#w6mrof1%5{|m$5IBDGz#{c^|v87v82yT>} znUr(LFYs=oAD0Yee-!HwvpF+}GdeNa>a$vbN~iI{ZZkKz*_obHnnDaSiQ*TC4@j0z z($*G*P4Zp72DTJ-L4s!jlA`VX*jyV`9mJgl=6CvvtN~xcKf7CJFtCqoH8jy!b$&hk zB+8rVW=F$=Kp&ovZqf`e-2c|#z?^@g{?wE{OlxBSsmbjpC3PWg`1vDWG9^EQ4~97T z+oGDddx461V)qjV9*p#PE~)HG9&v{gk)6d=I)3#5{^qI?z#@$+SI>$chbE`oTtGaC ztAui2w|54Lm?EbGX$2%DEjVf@TCnJjMfgPH z*I3An&&y?^nyUBt=jD#a->=!;yf|76QuLqlG89Q_5Qg0{fMYI()*F zHSoXYWlRO?j&xBojV7s#9Sy-ad7}z4OA@Ni4|t;Q^@i>`CIX|TQa9D3WL5YApHYhh zWp&k=dCu_ZTu8fcj4!uj{{jaHIbY*!jtU*iDZ%{D0_b>C0GgfL~gN;Gb zbxZjX!0=MsdEO>V7if4FTxe+P;8*Ci^ym_*c}m>yW#6VNTU3+-JyRnv--(Q>G-k%i zc}!x>msq?@+(|m_3Y=t=QE(5bOD!2?>RGWo$YaZa`kk!?;ak|pS`VQ_Pxh=|aDUgDt>k=`;H)+`z0n;f@uABh6=jnHP&a8UC%UJh63zyDDBA8LUBy_y+s z?g}uoMnBx5n24)RDE2jr9ji}{-cv#bX`ofV{AaNXjI142>c<7%`jGY3wuGONlrxBW zOuNz;3}j$(8TY-T@?vk;tQxV~*-`ECB9zjOo%4IUPwdm; zHl_n8rMu{G&H@I?6||=b=)!%!?oYld@?l-u!;zqdXP2Fg_ZjnOvXIKn3NwF89FZOJ z3Ia@~4B5H%E)#O6aj+x~a|`!B$xh;5Y}n+bH(trvrR6XFp)Zq|NXzTyt+&Tpw3pF$ zMi^0O?!KXPz|<@5np;s8Dp9sqFh=oYq2mXU2y(Zdb=jSoKWwr#7D0k=|CQ($L!i*n z(pf$}Yg3S46nMzcKGl%*ey(L8b&}8uEOsUU7o(nL{}jYk;!ho2ypv(h+*VmHRu9$McDA-iQlkBg|6O-j1p-ny*@B|YU> zef}*J*9Z{u^ek-)AU?&HBhD7r9>jX{@+eEWHT>}DSKPnf`jck}QC@c=&kYv1vq{`1 zbd~$I~3C7*N=g=h@7 z*wzQj=-wk+PoQh%rBMpXw9JD6G&JLR2TVIgUizwi9>uJ@Y-~KzsDN$MZAjn1O@KGj zZhU+qI*F=I+FAXWOrj`uw+J)TRf)RZ`K-)XuhdSdf?ee`fhTO<+BY{a=h!`7Wsulb zRP==RwZK+xsTXznMGr}M2mM#)cabU4>$`)kxg5r-a(wYsU_n+-5Q4I!@RhobS>~!% zkB;KE-xm)!(p%2R4XsAEOKwKx=DUnULzPqoid6Z^;3(N7Sc0K_8Y{rgGLBC9HYvd_ zm4m}?h@$_qs%LsS@2E|->!V~9KjwRi5YJq+$pxdoT`iisPzxI+x++HY&iG1*D8N*RRT{i-V+1g4g%d%ZtHXc?iDi0hff}@G(u$ z!ZW$ZT|@H(&8)I}ty0s-OyeD6)%^W0jp?e5;_dLeROce}jy!kW2yNPDu5|?HTbf;? z@;~S8{Qrtc{6E^ohMA{^q?AVkf4w;rpa_bKRcDd&2tB6$#PZd3q7JyTvqL9lmmf^u z0Fx9Uu)KivNF-zz`2D6iU%Z^ETjH8GCSmBqUznwi#qcTv*ndTmHCU^ZKF~CXsgsHp zf=W=@T73n62PO*{1M(9WTdM)tnPmg9b3bE>1MXr#Dk4&ICM@13HF^tM=JuKVte-r? z6sWhA0YV=`fr8I+iFg{^<+T*m%nsbRN4?yg`VR{0=1SN=IC^@*%0$$~(ZbQ;%<82t zMFsWb1$njsA4@`W58u5C&SmNQZ3G!NV9)P(p4*aEN5=}S8x?+%SCHywWhdrv{2P{P zw_U)U<0S=j(@^Rt5H%_SQ}TModdV>nTFz}sglVV@0=8EhM;Z|PN+WxyLQx7X-U0Cv z(G`Vy&vdxK#s`ox#o{XLmFJYt*fUpGY1FWeZ01M)(9<^0iO*KP65WRl>Yv>D=;E3r z<|cIPkHV z99-TU^|})I5;Ml>O3>fG%0Cse$eW@}97uL}gXRtUqv~gJ^Ya7Cet<{ENV9f;-fhgZ0R^~uH{1+MQ}-mP(+(CT0zkyxLYws(Id=b@X_ zS^LlUPKv2-_S*)2K(*s8@W=+(6#<&%h8AM2RC?fJSN<~lX1@z8{N!{1Ss#zxY-Le( zr*8FDU!J2wZAvDV+w!`Gj7gH|X@h_9V3GJx!4w+?sZSF+SIR?Jf5`yWANc_12t9jB zlH_j5iTf&sr>;X~YAR$l<$vWee*F)O+@t5u{)>^q|HobV-)sSg9IX(3_}EhMPw)|) zhC0R923HO$*;#DXl2?z7lC0 za12O&ugo*PXFr=m&%^wFIl_<7WhLzQNqRB9)O%Ci5@z4nvO;kW5+?D+3H4N1)Q?)j zK}kV{y9Z)lNQ+{zW9?!wQb;|0082-M&4p!Cs(;z`Ychh$)Ddz%5+Md}guce4^1rIk zul0{G7?*qHKrblw$f3G}Q=#E>So=MIkafUSDb`cA-C)mA{8Kz*Us< z1d^doQh#EsLdyy_ShurW>i8vB1(}r@me{#X7Scq%^s|zp(;t@^YJz@SD6EWDy0-Z$ zua)ua`*(s5wCk9g#?%q(@{hb{9l9EKHMRCWybwT!w_PuJ4ZFrx%TI~^7&{1sLmQBy ze4BMiL2PvtjnMOHA@7OzXw$LC*qr$$)Tw`fASWw`0zuxpGPQnI@nS9)Et$SIwqRH( zrVDLwn+iEnJU{2vQ?C=FW*t@8s29s~qqA<}N~L07@vgP;F*c=!3;_8lx-N{wOrrIx z7h*R3bPOIbmGnj#S=iCe=TTDJOnfk%n%T;8Qj~&>BFeDCp={FDn0t!m3q~#iGF2yC z8asw{vM83`3G_^7T>omY`i??d6ZD6Jl_0Y~1;k(9jTyM0SJR#e7w7otQ5dSU^1NR1 zWs6}Wk*nMLo6Sg6#?;hDI7l5e>;NauFrr+XZ0QM(_)Ka)OK>)wl3P>+a_jq6^@kR# zl!J;3Po5fNJwEtaKryYmj=Va{@2 z`MU~ina}i++hZFo{_Km>cl{eZ=#s)?{>d=;^rQLc^LK#%@6oz{FD`(df}@Ea&Zn;( zfXi2`CEEVzG<0 zdTUO}_;*6dC6Qn%ft`*M^}PWA(+(dWRl83n1m~XSx_L!vu*2_d$D&UQo8BPdU|X*Xr!uCTgg1QV^QaVQS%1YOsfR(wH_RBu~+Y7va#+@@0f zvZS!zWxP|wQCJ`(RA-V@ed=f6;`1}Rq@!lX)q_oTjeIK(2r#~CSz1+KhBMxp z#zXTL7{j|LEV9C9< z94@72NtVicW`&Qaw`ug^!ja!U9d5Ws%A%0)LKo) z39Z-VlO-4?*mVXzp42eze#&G;6`0_|N7!wVu@8;!*rfoPv-Z414}o9MHk|rHoOBCP z)z#oTE+0hGX}H*lQ>*__%PW^8WFMd?-@fgPL|&V`{olS<{pcLZ5(GZe;-e6Edv9osB_1jgp)uV(S12yM zOU&DLic;vmROMRt-fZY>8XhZS3CpnTm$X)zLB^j8h>I<1%phOK?;Tc>xSG~Rq7`=s zK7-$>L9u=(cH02yPS@MWU?A{SMk3@q5X!{MlN|P0TkvkRC*eT1PIQ^JRv{#kmfBaaRrK|M2yy3%!?J`pUdC+oIhPTWBiL~i6;h+n|6+6?l&xA#68Qe!|7JqeKG%rX-D zPSYgoI-JG@mk8QE1n1R$>Yd7X-viwRd?-NZO19#kLW98q3{qmW4%19d50yiTm(G`E zE($vZ$;^+~#KeYwD(RY)Fn(1y`d`gmM_AK+mjw|~=_&{Uf&x-Pk={WBgb)y^p^Jtd zdW#f6K{|vQdXZj3HB_Z*F!U}}1VSJ{K#Fvn_`cs_W-+t)o|$>xUH-dl&b{}X`#a}O z8%t9N<)BT7iR{I3HHyTLugv`2*KZFC-0gc_SU>-;glrx%7H_AH350^__W4er66IAs z%GBT5)LY$Fy&0urkoi-cY*8ltao0aPqyUiv1$KOw-${Q6JG|jL;T8B< zP74#^lrit&C4eYIGsSWCTMQ?PfPJ1i?He3OrullNvt_*QE+w93BxeTc3dz`bCPcoyWy1wynX(; z%&HPjUHQch83WV_E9-cp??ggbasI5F!SA!d0HSk<_FfN7Jn}nHBLbh~ISYRX*Et&_ z#^Y6FzxlsL%6|gQ|NN7(=TBp^ocwF?9nsUuE<8>2>KEbRTLXU4h{FDzE4#qEh#x4i zQN#Wgk0U?`Q@ni%;;gZOaxYCugn3E zse5gV(|8_t;D*u%8;quU+(>a;4lOrf14J))EY)7mvP&{U@nc3U1_uYsVN1y6e(*JS zcOjqMr<%KUmC5FrKi;A}lBa(S4K5s+kY%%oYRzvL81Gd@IhKrx<{_!wG8AYgMm|B4 z?A--YpzpjV=rxJrAWruFX1L8a^yBKGy{a`!2ZC6~&gO1f><9^gggzAik}8~K4}P6_ z2cDASU-(L`HGLd%{~AqDjeh#L)#|lJ?9=?B>m`2=AkFwA^^?9l-_=pW-rgnB!OPj_ z%C-uk^8TS8O&!CSEe_$aRNUe|r)y-Q^lwHCD3>ty|hKR7(_qEvTC zX)nw!Htmq{n5Q07f- zV^Sa{;;L~e?@y>w>AB}&*%}dQZWrx4{MSFggOr|f5l7!NH&4{-LHE;J*oLZ6R zAeqh)>-KIHWzc1KCnSd$klWOIUamNyufs|xlW-}?P3E4hN0#I{tOl)Xj|52#sleO- zttqIUWtJ_JsFIR&2bmFkUBEx^+7H#D1&avH^>kgZ{79^Te_xni9WwVpy8;n1D#}j5 zb#{_oSVf0q*e6%7ZN`6)ag z*Z&7k^#3v^n0C!7EsGM zSHZ}vf?!ARR{?E*)Upus+{dlm2EUT4eH2BbQ+i{37#aRcV;VsdxtejS+c<5wr1V>k zFWdYl?GKA~h^F@fm;K>RLC*Zh7#QC%vJ0hV)Ma^W-RJ$AMAZ$X|7Cee*%Jpe*R6 zJIh&=gr?J3ZKokIyw7-qvMEPq?dprld?7S|Eg+w?Bk9@Dg1(vl(E;rtWSgH6EhwLg zxvMEUrK&!mz#~*QwF8xI zrTr$s6c)_*$2d{hP==Vbz5+}+gLN(`h7i<;JTS=tNw34BaP>9AleGi(_Hs?ZqOF3A zE&ggGMa6?}+l7`4Aq^EJZ`ln_lNu^=-{cycrs%U2tcf5U9B$-*~ z?OwSefTrISh~(H%G5crY`LSclM|UXe(Ze+zU1N5IOH_jbNZD^~{WE0*L3;O{$_vR@a0&SrVK1&>own zy0hJqYsH=YBCLYugA`5KRAb|pW_wjmm@XPZt2Ls0uBJ_f#~x7zT)NvL{iA7+g~_E{ z{R5;QXr9Z%9%JMi9N$cf8^d*Sou*QJZTusBC=xH1PQWQo?(>3P`~y^vzhQPeGSGS9 zU(&~C`bZx|PMHgL;f>snRWou5Hd-R%Jzp4ac;Veh7OVK>(Z56Qjix&m8Whm>n1)NOYyCzr%&GjcGh}ZK6)J0kLZvL4`rLUppsWQ`E8MPrv z{tLhuI6R+GOS+)M?nwIpU{SSWf6pr*r{-xT)@XTk*ET<@od2ml?q2-O!eja9?>_>d zYIwxwcA#hTELmg8gyD4q?yoLexv(W19sqy+-nna?=!Y2n6?l`YJiDv7B{&ec+jFr( zw<_iHn?&}fO<5v!zJ$aeX_dXb8%uKXL}^UDR40#R`cLw&2dl7x{*MM1g2H(AX50I$ z!|GI23{knCvF9p>fUpuY_c88xXyIeE-r3$6Zrk$NA8|?^$F2v#Kk_d~imxtCuT9<6 z3#S`FvrPGKOF7-u=$*thJGi*rj%E`_fq9oBTe3)%YK`q0498ThQv}4_Im%)9%CeuV z1vW*Y?GwQ*8`$}f7Q}!nqM|rz+eA)``&De`ydYE8XPo@!3pbRZc`TK9Wuq)(4}^Ta z8x*-tgGtr#LP-!n0JW;F}CEmhklmxa7wjF`=U|es;97^8J=g z=ZZH!3fhnG!L?s*N%B>2N5ER#%X5#lN4Dtt~f9iii_6V=upW2h7J&4UV-(~L<7 ziA)JVqT5AYnokZPN2x1#sP6=~t;aAe z>2GDvm7^cN!F%#I4vSxw!V@zF#F67)n8jL8%?)!Y7y;?@b!LEqa71FFRp+QNIMb7# z&5&jNhu2_i=QmRC(Yb!9K#K#h7HaF(paA(i8^jjlbl#h`9DNx?zQ}iR!WTkeUq_FB z_5@gRc0eVcn1C4-bK4^`1h&t6G9x?tZV!xB=ZylVy0|=|6l$h0V$Z5)+)$1FSx->8;!4?>>GN?VkN^4=(H7wG zJSQmYd;@bJJft)jcz`8QRV5F9x#qC3u?jC1;Z*fy-V5z?&kIQP!}v*qGH=1V)gO_A z&T=mFOD{H#LL25=9fgj#=%!z>^BKF6F^kkTw9J4?Gm3LGroSenN|EdyM;tKROV!N?pim= z(b!`9US&uPe-zo`qVFiZxiTjoHB|gqGfPoMW}(2zZ`ynZ2y}g8-g9e0pfs9%F^+?W z+)^;%$qes4-73VL66fWa;aFO1yUbGGI!yG2PIPs1x4bHh{EoL_Cfi_{dhC$kz)b@L zoQsR8uyD;;E-AfOC{=yY<0i9Yn26OCpq5}j+}8{jM^!@IChf|M-u8a~h{zc0WJGoY z$d|HqVR9xMSK89VrE{c>?xZ|Aip;!YDvb@OlTFW0l-h;Ecoy*P(tASn0Z31`bqTRG zL|DlV(5Re6FTsl;#n~7~1~Y4{IuUY$+~`n-ws^F?-ct>4Dt zNg>~}7Uvx+y45fr!>7jANxNjFvclbZ0nsb7Kcl`sG&ts8O$2|%$W#TrF6yx{yUOzF9_33@V#Ahwpglq9tNkdjuI7{zoB#}GeuFsCbhL>6~)y#CSvfa0Xq{{E)$Z>rs>W=iH z$c3i`@h;`8t|PpyyeP5ZL0T_;+9`tBZ__N=y5Z9gbbFkR=YjVFEfm^IGMp7JRHYoP zhPQO}D-IJ0Ym+wLmazu}4#(ki?Ra*mbPs;&==;I*zKu>j8A%!@p#=UCa7eKpLXFXO zpilDngBVi}Xy=lDlZde6FPEKJS}OcFO;+0@PQ-t;UT|5U`)`s;a58b!Va!eXj`93W z;(hk`P*v^)kOlEy4*Hso1kV2lU zBUs8#cGH@LAUfCv`85zo(0VKE%59Ac5`dqAx@F^o8c&Igz|hQ_UklwZ>A}Ok73>UF zPK0R0%FoyZ?+M8-Q*~LN5_=BMNt?a(!420nU#(O|#-mBChZzr54{S_5hF(e=E%!HZ z6g0N^=*kb|c;B-cdUEv;nQWBi$R@{b^lc?XHnT)7Tyvw*U=&Dx6PugheXGhB66PJ! zLHl_5eR+hTQQy68>(~=dtm=!>lDW@q^W@H2@lhQEG6LM;EhINIm7T12wN@uYKGeX* zq+Lum#Y8D10;;I&;mWykG>jY8@gSg~nmF>E=Hjp3C!6q)cYP9?JPpP?iN*E>{?=m@ z!pyEG9nGIV{3el@5O8Loo=DBQvJ5wa*V^2KXM_$N4(0VHomyZgZZED3poy4lc2jA0U1Q460{1<-A`EYn zaccos&~C>OIseocD{wTgZMZ?+h=LBiX&t?ZGMjqSKFa73>#o!@g_%CPQ!#0bby}b{ z+z|X!z7RluQKMWpRZR-3Wb}w}&Nz}0nn;)&zjhCj_NC?_1>0$gU2j@K4}@T$Zd1(# zNo${^%&C+5Y{=#60G)AL^b=`TgBUNi7RDqw=c~2qz@RE>CLMEE=x4QkJV6#lARYQp zI$8JOx_seFKpCH1U0He(wa}b*SMahkE!U`$JzH)|TdlJiHQOXQunSa+Y8>8JQrFyD z*Kg&#$y1$P9a(34+rfd^*!2oHWU}WgD;Vh^gLHkcwNeqg)R4Y^1640F$VoR_^=r2I`;mDe$0`boP`u%e5pPJKYtlV#;T*9 z9nkfggiGH7Ul_95cL)jI#8yv;cw8}A=!e`1Uf$$JcUr7p-@l<|Mtq@tOXH#~d8v>* z@ke(?lW(u7b{(=X{IQ38xpr^KXl_W-)yB3&+Z(L?471wxQ<|kL;10x}QpU23Z?dqxN`B)o%XBe|h#ISLf4utDEj7hWW_Tp5(lwIHYcI8vyv|Je6a{j$ zbIEvemuC-i5^{%Wc#=Ts8+JvR1rnJTW8XpIX89BQ47h?f)I(bBM?~vc{bRJzzq&VB z@3q)@N@>-HzFm;sPcIMYDJVM~KGP1p0X;nuOfeHy!nmb-GpY$GZd z`gTfa>Cc3+m&t@Zp?ui!Fe?N7E{E$NSZsClS{J_Q?p8sm(6!caic-gB&4?FcaKj(X zLnd7(&LK7f`9x1jj=mu09dMuENDCCjX*_x^ib88FlGP&)jpyzTuWn!FQ1H5c|59k< z@@+q|i!I_)MYY*eG+%66K~jNAW(6j1O%CnF!M&AP1WN~!vp8)p1VjNzFrm4) z+@xcST_LYyTu#si$9<@j=H3eUJn15C_&13c@q}ui_r;^O@VeSIIqI9%4$yZh9F><0 zWsP*Lng0p(?!WyHFKp=OZ@k(_7|_t#gS3ZBZK2uqMBRx_`7_k{g&gleCVz=h{msO rd$G#?4f2`OyN3p%`Qt6CMPqKe-=J31H=HBD5&VD$e8G8=hAH96T1>a}R*%r5EsUFAw0~9=O*Ci14qFUMjUQ0dVlI zUctXbeFKkx^cwCJ5**+a{A(jY}esS^Nt2tHGoN79! zHYh(OaB%x?o>7S#n>gp@AyJE&p3_PMbm0Z^)K0&&O!$KEFSP%L^o5@ntD{gm*AmnCDLe>g);vi{qmElL-kvK-gUbh~ zxfhCpZs71r!ZpI8+@8PNV}ueYc`VmQeERnFjiKybUI2J$153f-s>q^K?(C|v;=JhAKssDR>~yHBj%tt zO$jFgS#oF%u;X&xtTwP`QWvv%Hg+$AnX?K%`=5wdqp=DFjnJu$DLG{j^$7cdo{rL6 zO_+i$QE1W>;{!zrs6}W_6{QxdNJp)wnm^oI;#<$|Hg|hz(bl@$n02qmup_P{pP>*o z1uG_p!8M)+iB6=HQfm`yKR6v-e2ZbZs0;+IL=St9N{hKZvomI=RkslIMbku~)UwSf zFqeXng5nhg+5b+#?T%jcXPhx zRZhMi8nqQECE&uj*taT|hfve|rQH37*$caKRZi9%yIrqC+lj@UO=$cT#t28_jmh{x zu8Ctq$}#V;Wt~-`hNtXcp5NnOldzo`>}w~nGx;%D^WC`d_n?i|gE$@NX+FuI;KRP( zOiNPnZ-{mCtk0(c3x{D;Pqzq=fKqTYd8mR6s|me6U86UjFbZj$! z%M&V`ggafecw*NGK~Q^}jge1OHWkmdyn=1-AKuqmo_6l>`+;$bttA`LAJZj-^Fw&K zl&(G+wgeYY-gapZt>e8LE@KZXY$~;PqoRG7VMe;iFN+esYf2T<j!R9X+6doNpM;P1xtOrs zm6c-?CE-C~3}b6|N^5Gj5FgpPrn=lfwQ#4Ak>S*b+?DXTc(;W48RpYLFZHSLNP--m zRz?#>1UGIx`BQi~3oh9WD=a7yc&awFHqi`bzHb!s{9=?U0`821#6@ z@1p{u21I=cJj~Y-EZiT<(w9|rRmJ1AlZQ>fltX>NepP@r1u8`SiEdKgG7xi__9|mK zZ%^s4loDH8HQU}3jeq-=Kb>!_iSD&Ta((icYPz^;>)Az8+}qKepcnz>UH`UV0x5{6 zCG2bYR}b}X=`@L1ml$*#rt*W>gngHApW8CUWDPSqN$tFI4+fE90SfV;aa&Lx#rd7@`9#qrzT3}ck!v8*M>T$(pfALtn{`x zHwBK$#-+jBlH1UjJ2?0&ysNg2L6RJ;vtvjg=S0uNuT2vrUfT-TggzD<7U{dt(AfWT zG3CD(V*a10{gfd328xM=LzbW%N{vJDR^pAnI>k!{`hxCLg7|CkkK+GZ2NG|nu|B<3 z4kvZ0`u4Wwt%SH%-yc{R*$|Q!n5fJzY|DTB9->71rE#b*GCCEHqbub!LigBb|DW-J z`@nuIM36rEroMgtB;#MPsq;W{7EZr6XdQg5_^+6q-&AiN*`%GxzW%;aR!<5qu7rC= zoj3&wGLs63**QUtDW5Sj><>-f+46_fh zQcgG(G`7^epB>)SaK|wtB#(eJ^jm73!6+Q4b9Svx`BR!#ha1%-!AxpK4?B9r#nExB zw~D!%<|L{Nht#QgYAe!B+gc1(-6adxO|a-0{NvBS{!sAFp`1RNjzegiZXJp2&^gW| z>uMyb;PDJB!JmR20a+a@HD52{k`8CLm;QU=dGj8J3yJK2muZLqhSNr|H=*~{W31B4aGjh!mhsX2}_U0M^+wmm%OQ>uU;f|6%+7~SF8;wDwmc0#n8F3 zx{6jt(c_tDPJ>sz>CIHE%uTP{^j((h#w&nOZ|gHxTyt?X@{uw0%*eOfFL*31%ZRUD$TXdZ3IJD)upuGa%pmjdxVfp`Pj+0)?Dz%pW@B7HLmQU zKNV53F{=Ia5O2-&zS=9&na#R?7USGC@GwKdr`_j#@|H6GuAQCC_5A-!uSoxw_;C3* zC$-Z1;$K>rqEk80UTJP;Qm<`^!AWObbnsGF-E?Wv*QI9z^TlwRb{p?&D#lIM*w9$; zf+H=EMhcjQ>tY2iX06cii0~$K7GC#xlcq@#WhBv#*wlT>?<7oegG0knj@ zeI!IWL~gQSTx=11DcnE<9?;U>C;c+Ev>@fP3IC0}pbW+QL~)rUiev8;l{V=V zdN$r$I)b)h1Q8E3hpg6cUnF)LH!YfEqtQEj7`a@R_85Ff93`*xqK_KQFFIM>CiZhu z07K)ttqcmKrZp$Wp2$Z9+S<2^6Sr6UL6@tfBB{fgB}d$^3o`4D;TF-tCQg|Ts=viq>ic;}^uA4%CM;FZcyfkSS}??j#7K=) z#c`+&)^x?jWK}|$MXsY3B6NF2Ktvr7ddrY-5_J=xkAiALt0n`3xq{fXoX>s?q{?XG;zzRxC+|M+#Eu@}{oLnzL+dDl~imhhE}Uz3IELxi`?2 zQ8XV)bbirztfuHFhWc8O6#HhLaf zi6o@ACEgOf<)5j(Eyp3TYFcdvnh3P!LyX2Vc>TSH=ng2L6&Wp``Ua*5m|B+;ryKDI zOEo9ctYcA#O-JDDAr?dzx|v=|oV=WxwWei4m(kT9zCp4XS`I=p_JK?C!Ed?=uYEbj z8MaCaUBt({!gzqC(9T2Mj-b+Lp2b787nO(fp0LzA55;<2XAhnc&$%&_yes@vgvb*Q zz2m53eY%PG=12PPYmx{0$p?4d99@)lC0j=uxur>XNL;%c&hCmlt+4Ve`MBsmM(aG| zSN@fezg8uXTqqI6ilj#aZ>1=HAWX^(y;0-ro}Ds}EmobGzIxzpn(5P_L(39=fG@h0 z`c}H(NGKGV+>P3Et%5}qBY9?ka6rb)KXVBVQS(gwxo{?d$ga=xynZh5x<~ zim<5i)G6HHb^4{&**LJt~09s{$TACmVxX=#}0OEWIOe@l`cuwXLUCxz;!VkbA0_Ln1uW2GvH=2E5&=l z#l`)ej`fWrVbYq6_7tVXC2vWU=Dz$HcX^#N1ube9l2DhN#~(&C+VLMZSR#u%whxED zX>gmPm>N{MJif`BjYUC^hc>w)j)41!y>$PHSO3i5`Uw5B?vT{_}q>TKif}2dyWn)&`PnrbNmin==WDa444pYp6hJvtA}~%<~E}H@vyrm zaK6^y4!f;hd$4hRN_uJI_OAYz9EUP4DRhRJ<)d$iFg12m7S-IEhB&h^ez^_5y~M}C z0cesybE;&mh37LM@r#uKz5eUp3HW-c)&;F$Ros@BCE8!Hp8*F7Z(?+!nGXkx5AwAW z;`eP0$Vt!?Y?Rk%?3iH9%mLpgQ8ndtk>06`aGnd+e3Gbe4LH~SeWg7H%ufkI#V;*3 zE^JM=OncONHQX&xk}U<*aITpilpksx7=YrEtsTG+-b=V98J|zh4a-o16wQ6PtBZ2x zy3UC;D{49rv&zeh1KLVV-F9~DdKC+7T(f10&mhr4%e5RQt*ib^VW+-bWtK#Frn57% zSh|?epQt@}nCF+;9ob$eHy{<+j)|Yp>!+>gI=KZ?vPOICO*`veS0E9(?e1fhY<8E`m;L^BL@fyLWbaQ zY~M4$uW-RdzF<-)cWis%6G}>;r%aG?dutG7$x5&lxifk0N&|2YZ;CLrP7_rM!^2<4 z0N=Kv?+>N6E=Y#c;n$;Az5_vymsCR1qQhyhv@>$%c!!%xYCHH?bk;JMLzw*a@7WWW znLul~=E!ta39s-sO$S73ebr0BZ-Swn0Po~P2s&EWM#?Zt(>M`XQ6t~0o=O-}IAI1Y zX87m%UaB5mQe|b&pL?Xebh$mL5k0Gu^J{%r2`EcF$1TnIDMvR}1$ntqHCpQ5=0a@j zsqf|x*#c)QOWnm#%iIG82#wwD77B4w`(+$t?;_aZg5P-{!YsLfpQq%xqhZ?K5$5$SE}6}|@JlmKT;Bwv3) zWT#o_3~4yo9cdx%f7@jmR{*^t3P8!EO4m1w$VsT=y3&VPlS1Z7< z)#M9S6Eq-*F2=2ti^21Rx```heN7D&2!gKH={uO~QTMAT2t<-!~-btsB4j1===G$gsf~Qo_)bxlB z>RzjzG6Z~4Vt8l!8?^Nd;JGjaX*`~Gwx2zSB1OkRX1eeQWc8F1<`j3B8$-HgON=5nPUp=Hc_$vQ%6JH)GSKwIT-3D#LMURim)(xbQJE*c=Mv^|79CGb=1`MI3tjgagCK}ZvdZ2MhuNZVG>K?&hMlODi&w#st zFXL#8r;UBk`TjMY5zH^l_6ov53j4kkEfS;qg%ib(EZdbat8XilC0~xH-1O?7{#J4P zkChLf5{W}84x-sNSz97V%7^D{DjAQwV*}J<2PQ9(jpXjlZr2h7Gek$XZND0T1f)8^ zix`wEgx<@t)%la=MK;H$rj`zZhg;&MlzDxd?CD&qqYtGk{rArC?=Sj^J5+=5H^Qp> zCgwP`;RaxUn&2kBoPc`Svo?P9bC7l^>+MFO-zX!kA$iS%!!D zj9_i558cUyWe9)j7O)3gd`id0sT&X0;XKfmt17`u=7PpG=QQcT75yp4omWdj3{Qhl z>bvpH{N(CRu~yFmQv{&;e`eg{mkM!uWg~)oAC=&uL9no3!svk!by91v=Fqn6;bdp* zC1hn?EMDogD!)KNS;IDo#6N$7u%|1?w6>8R8PEO6_v=bad9he}aHvUW@RAfPSNYhs zde&u+i&1?n7f|cEYU9LzoBl;Y)0l>aDnedP_qC&QjH8uRbCY0%hw(g{ej=_PiLxc%&jz%AEZfd8!-{#d>T6)fK3aoMpkZ z(wF9SV1`mhPg-71IVXh>Cyl9zpQ3IsK z4uLn0i?Im1L;dM52v|;$E5+CnqaiN`cNmOsC8FGqv3ywXdI_pn

;Ur&TjRj>B|5NMt+>sp{fGZq7an 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%0AU{S|_sF}^eJP&$1c~0aWR420N+sl?1dR-MG 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 Y?{UWd8)NaWSZ4o!$N%IAiSB*=JLHnmY5)KL literal 0 HcmV?d00001 diff --git a/boards/st/nucleo_h533re/doc/index.rst b/boards/st/nucleo_h533re/doc/index.rst new file mode 100644 index 0000000000000..b2ddb225e137f --- /dev/null +++ b/boards/st/nucleo_h533re/doc/index.rst @@ -0,0 +1,306 @@ +.. _nucleo_h533re_board: + +ST Nucleo H533RE +################ + +Overview +******** + +The Nucleo H533RE board is designed as an affordable development platform for +STMicroelectronics ARM |reg| Cortex |reg|-M33 core-based STM32H533RET6 +microcontroller with TrustZone |reg|. +Here are some highlights of the Nucleo H533RE board: + +- STM32H533RE microcontroller featuring 512 kbytes of Flash memory and 272 Kbytes of + SRAM in LQFP64 package + +- Board connectors: + + - USB Type-C |trade| Sink device FS + - ST Zio expansion connector including Arduino Uno V3 connectivity (CN5, CN6, CN8, CN9) + - ST morpho extension connector (CN7, CN10) + +- Flexible board power supply: + + - 5V_USB_STLK from ST-Link USB connector + - VIN (7 - 12V, 0.8) supplied via pin header CN6 pin 8 or CN7 pin 24 + - ESV on the ST morpho connector CN7 Pin 6 (5V, O.5A) + - VBUS_STLK from a USB charger via the ST-LINK USB connector + - VBUSC from the USB user connector (5V, 0.5A) + - 3V3_EXT supplied via a pin header CN6 pin 4 or CN7 pin 16 (3.3V, 1.3A) + +- On-board ST-LINK/V3EC debugger/programmer + + - mass storage + - Virtual COM port + - debug port + +- One user LED shared with ARDUINO |reg| Uno V3 +- Two push-buttons: USER and RESET +- 32.768 kHz crystal oscillator + +More information about the board can be found at the `NUCLEO_H533RE website`_. + +.. image:: img/nucleo_h533re.jpg + :align: center + :alt: NUCLEO H533RE + +Hardware +******** + +The STM32H533xx devices are high-performance microcontrollers from the STM32H5 +Series based on the high-performance Arm |reg| Cortex |reg|-M33 32-bit RISC core. +They operate at a frequency of up to 250 MHz. + +- Core: ARM |reg| 32-bit Cortex |reg| -M33 CPU with TrustZone |reg| and FPU. +- Performance benchmark: + + - 375 DMPIS/MHz (Dhrystone 2.1) + +- Security + + - Arm |reg| TrustZone |reg| with Armv8-M mainline security extension + - Up to eight configurable SAU regions + - TrustZone |reg| aware and securable peripherals + - Flexible life cycle scheme with secure debug authentication + - SESIP3 and PSA Level 3 certified assurance target + - Preconfigured immutable root of trust (ST-iROT) + - SFI (secure firmware installation) + - Root of trust thanks to unique boot entry and secure hide protection area (HDP) + - Secure data storage with hardware unique key (HUK) + - Secure firmware upgrade support with TF-M + - Two AES coprocessors including one with DPA resistance + - Public key accelerator, DPA resistant + - On-the-fly decryption of Octo-SPI external memories + - HASH hardware accelerator + - True random number generator, NIST SP800-90B compliant + - 96-bit unique ID + - Active tampers + +- Clock management: + + - 24 MHz crystal oscillator (HSE) + - 32 kHz crystal oscillator for RTC (LSE) + - Internal 64 MHz (HSI) trimmable by software + - Internal low-power 32 kHz RC (LSI)( |plusminus| 5%) + - Internal 4 MHz oscillator (CSI), trimmable by software + - Internal 48 MHz (HSI48) with recovery system + - 3 PLLs for system clock, USB, audio, ADC + +- Power management + + - Embedded regulator (LDO) with three configurable range output to supply the digital circuitry + - Embedded SMPS step-down converter + +- RTC with HW calendar, alarms and calibration +- Up to 112 fast I/Os, most 5 V-tolerant, up to 10 I/Os with independent supply down to 1.08 V +- Up to 16 timers and 2 watchdogs + + - 8x 16-bit + - 2x 32-bit timers with up to 4 IC/OC/PWM or pulse counter and quadrature (incremental) encoder input + - 2x 16-bit low-power 16-bit timers (available in Stop mode) + - 2x watchdogs + - 2x SysTick timer + +- Memories + + - Up to 512 Kbytes Flash, 2 banks read-while-write + - 1 Kbyte OTP (one-time programmable) + - 272 Kbytes of SRAM (80-Kbyte SRAM2 with ECC) + - 2 Kbytes of backup SRAM available in the lowest power modes + - Flexible external memory controller with up to 16-bit data bus: SRAM, PSRAM, FRAM, NOR/NAND memories + - 1x OCTOSPI memory interface with on-the-fly decryption and support for serial PSRAM/NAND/NOR, Hyper RAM/Flash frame formats + - 1x SD/SDIO/MMC interfaces + +- Rich analog peripherals (independent supply) + + - 2x 12-bit ADC with up to 5 MSPS in 12-bit + - 1x 12-bit DAC with 2 channels + - 1x Digital temperature sensor + - Voltage reference buffer + +- 34x communication interfaces + + - 1x USB Type-C / USB power-delivery controller + - 1x USB 2.0 full-speed host and device (crystal-less) + - 3x I2C FM+ interfaces (SMBus/PMBus) + - 2x I3C interface + - 6x U(S)ARTS (ISO7816 interface, LIN, IrDA, modem control) + - 1x LP UART + - 4x SPIs including 3 muxed with full-duplex I2S + - 4x additional SPI from 4x USART when configured in Synchronous mode + - 2x FDCAN + - 1x SDMMC interface + - 2x 16 channel DMA controllers + - 1x 8- to 14- bit camera interface + - 1x HDMI-CEC + - 1x 16-bit parallel slave synchronous-interface + +- Development support: serial wire debug (SWD), JTAG, Embedded Trace Macrocell |trade| + +More information about STM32H533RE can be found here: + +- `STM32H533re on www.st.com`_ +- `STM32H533 reference manual`_ + +Supported Features +================== + +The Zephyr nucleo_h533re board configuration supports the following hardware features: + ++-----------+------------+-------------------------------------+ +| Interface | Controller | Driver/Component | ++===========+============+=====================================+ +| CLOCK | on-chip | reset and clock control | ++-----------+------------+-------------------------------------+ +| GPIO | on-chip | gpio | ++-----------+------------+-------------------------------------+ +| NVIC | on-chip | nested vector interrupt controller | ++-----------+------------+-------------------------------------+ +| PINMUX | on-chip | pinmux | ++-----------+------------+-------------------------------------+ +| PWM | on-chip | PWM | ++-----------+------------+-------------------------------------+ +| RNG | on-chip | True Random number generator | ++-----------+------------+-------------------------------------+ +| RTC | on-chip | Real Time Clock | ++-----------+------------+-------------------------------------+ +| UART | on-chip | serial port-polling; | +| | | serial port-interrupt | ++-----------+------------+-------------------------------------+ +| WATCHDOG | on-chip | independent watchdog | ++-----------+------------+-------------------------------------+ + +Other hardware features are not yet supported on this Zephyr port. + +The default configuration can be found in the defconfig and dts files: + +- Secure target: + + - :zephyr_file:`boards/st/nucleo_h533re/nucleo_h533re_defconfig` + - :zephyr_file:`boards/st/nucleo_h533re/nucleo_h533re.dts` + +Zephyr board options +==================== + +The STM32H533 is a SoC with Cortex-M33 architecture. Zephyr provides support +for building for Secure firmware. + +The BOARD options are summarized below: + ++----------------------+-----------------------------------------------+ +| BOARD | Description | ++======================+===============================================+ +| nucleo_h533re | For building Secure firmware | ++----------------------+-----------------------------------------------+ + +Connections and IOs +=================== + +Nucleo H533RE Board has 8 GPIO controllers. These controllers are responsible for pin muxing, +input/output, pull-up, etc. + +For more details please refer to `STM32H5 Nucleo-64 board User Manual`_. + +Default Zephyr Peripheral Mapping: +---------------------------------- + +- ADC1 channel 14 input: PB1 +- USART1 TX/RX : PB14/PB15 (Arduino USART1) +- SPI1 SCK/MISO/MOSI/NSS: PA5/PA6/PA7/PC9 +- UART2 TX/RX : PA2/PA3 (VCP) +- USER_PB : PC13 + +System Clock +------------ + +Nucleo H533RE System Clock could be driven by internal or external oscillator, +as well as main PLL clock. By default System clock is driven by PLL clock at +240MHz, driven by an 24MHz high-speed external clock. + +Serial Port +----------- + +Nucleo H533RE board has up to 6 U(S)ARTs. The Zephyr console output is assigned +to USART2. Default settings are 115200 8N1. + +Programming and Debugging +************************* + +Applications for the ``nucleo_h533re`` board can be built and +flashed in the usual way (see :ref:`build_an_application` and +:ref:`application_run` for more details). + +Flashing +======== + +Nucleo H533RE board includes an ST-LINK/V3EC embedded debug tool interface. +This probe allows to flash the board using various tools. + +Board is configured to be flashed using west STM32CubeProgrammer runner. +Installation of `STM32CubeProgrammer`_ is then required to flash the board. + +Alternatively, pyocd or jlink via an external probe can also be used to flash +and debug the board if west is told to use it as runner, which can be done by +passing either or ``-r pyocd``, or ``-r jlink``. + +For pyocd additional target information needs to be installed. +This can be done by executing the following commands. + +.. code-block:: console + + $ pyocd pack --update + $ pyocd pack --install stm32h5 + + +Flashing an application to Nucleo H533RE +------------------------------------------ + +Connect the Nucleo H533RE to your host computer using the USB port. +Then build and flash an application. Here is an example for the +:ref:`hello_world` application. + +Run a serial host program to connect with your Nucleo board: + +.. code-block:: console + + $ minicom -D /dev/ttyACM0 + +Then build and flash the application. + +.. zephyr-app-commands:: + :zephyr-app: samples/hello_world + :board: nucleo_h533re + :goals: build flash + +You should see the following message on the console: + +.. code-block:: console + + Hello World! nucleo_h533re + +Debugging +========= + +You can debug an application in the usual way. Here is an example for the +:zephyr:code-sample:`blinky` application. + +.. zephyr-app-commands:: + :zephyr-app: samples/basic/blinky + :board: nucleo_h533re + :goals: debug + +.. _NUCLEO_H533RE website: + https://www.st.com/en/evaluation-tools/nucleo-h533re + +.. _STM32H5 Nucleo-64 board User Manual: + https://www.st.com/resource/en/user_manual/um3121-stm32h5-nucleo64-board-mb1814-stmicroelectronics.pdf + +.. _STM32H533RE on www.st.com: + https://www.st.com/en/microcontrollers-microprocessors/stm32h533re + +.. _STM32H533 reference manual: + https://www.st.com/resource/en/reference_manual/rm0481-stm32h533-stm32h563-stm32h573-and-stm32h562-armbased-32bit-mcus-stmicroelectronics.pdf + +.. _STM32CubeProgrammer: + https://www.st.com/en/development-tools/stm32cubeprog.html diff --git a/boards/st/nucleo_h533re/nucleo_h533re.dts b/boards/st/nucleo_h533re/nucleo_h533re.dts new file mode 100644 index 0000000000000..7071a5e21a8fb --- /dev/null +++ b/boards/st/nucleo_h533re/nucleo_h533re.dts @@ -0,0 +1,137 @@ +/* + * Copyright (c) 2024 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; +#include +#include +#include "arduino_r3_connector.dtsi" +#include "st_morpho_connector.dtsi" +#include + +/ { + model = "STMicroelectronics STM32H533RE-NUCLEO board"; + compatible = "st,stm32h533re-nucleo"; + + chosen { + zephyr,console = &usart2; + zephyr,shell-uart = &usart2; + zephyr,sram = &sram1; + zephyr,flash = &flash0; + }; + + leds: leds { + compatible = "gpio-leds"; + green_led_2: led_42 { + gpios = <&gpioa 5 GPIO_ACTIVE_LOW>; + label = "User LD2"; + }; + }; + + + pwmleds { + compatible = "pwm-leds"; + + green_pwm_led: green_pwm_led { + pwms = <&pwm3 1 PWM_MSEC(20) PWM_POLARITY_NORMAL>; + }; + }; + + gpio_keys { + compatible = "gpio-keys"; + user_button: button { + label = "User"; + gpios = <&gpioc 13 GPIO_ACTIVE_HIGH>; + zephyr,code = ; + }; + }; + + aliases { + led0 = &green_led_2; + pwm-led0 = &green_pwm_led; + sw0 = &user_button; + watchdog0 = &iwdg; + volt-sensor0 = &vref; + }; +}; + +&clk_csi { + status = "okay"; +}; + +&clk_hsi { + status = "okay"; +}; + +&clk_hse { + clock-frequency = ; + status = "okay"; +}; + +&pll { + div-m = <2>; + mul-n = <40>; + div-p = <2>; + div-q = <2>; + div-r = <2>; + clocks = <&clk_hse>; + status = "okay"; +}; + +&rcc { + clocks = <&pll>; + clock-frequency = ; + ahb-prescaler = <1>; + apb1-prescaler = <1>; + apb2-prescaler = <1>; + apb3-prescaler = <1>; +}; + +&usart1 { + pinctrl-0 = <&usart1_tx_pb14 &usart1_rx_pb15>; + 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"; +}; + +&iwdg { + status = "okay"; +}; + +&timers3 { + st,prescaler = <1000>; + status = "okay"; + + pwm3: pwm { + pinctrl-0 = <&tim3_ch3_pb0>; + pinctrl-names = "default"; + status = "okay"; + }; +}; + +&vref { + status = "okay"; +}; + +&rng { + status = "okay"; +}; + +&clk_lse { + status = "okay"; +}; + +&rtc { + clocks = <&rcc STM32_CLOCK_BUS_APB3 0x00200000>, + <&rcc STM32_SRC_LSE RTC_SEL(1)>; + status = "okay"; +}; diff --git a/boards/st/nucleo_h533re/nucleo_h533re.yaml b/boards/st/nucleo_h533re/nucleo_h533re.yaml new file mode 100644 index 0000000000000..8262b95a84379 --- /dev/null +++ b/boards/st/nucleo_h533re/nucleo_h533re.yaml @@ -0,0 +1,17 @@ +# Copyright (c) 2024 +# SPDX-License-Identifier: Apache-2.0 + +identifier: nucleo_h533re +name: ST Nucleo H533RE +type: mcu +arch: arm +toolchain: + - zephyr +ram: 272 +flash: 512 +supported: + - gpio + - watchdog + - pwm + - rtc +vendor: st diff --git a/boards/st/nucleo_h533re/nucleo_h533re_defconfig b/boards/st/nucleo_h533re/nucleo_h533re_defconfig new file mode 100644 index 0000000000000..5b88c80b24fec --- /dev/null +++ b/boards/st/nucleo_h533re/nucleo_h533re_defconfig @@ -0,0 +1,16 @@ +# SPDX-License-Identifier: Apache-2.0 + +# enable uart driver +CONFIG_SERIAL=y + +# console +CONFIG_CONSOLE=y +CONFIG_UART_CONSOLE=y + +# Enable clock +CONFIG_CLOCK_CONTROL=y + +# enable GPIO +CONFIG_GPIO=y +# enable pin controller +CONFIG_PINCTRL=y diff --git a/boards/st/nucleo_h533re/st_morpho_connector.dtsi b/boards/st/nucleo_h533re/st_morpho_connector.dtsi new file mode 100644 index 0000000000000..ce3d7c8401738 --- /dev/null +++ b/boards/st/nucleo_h533re/st_morpho_connector.dtsi @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2024 STMicroelectronics + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +/ { + st_morpho_header: st-morpho-header { + compatible = "st-morpho-header"; + #gpio-cells = <2>; + gpio-map-mask = ; + gpio-map-pass-thru = <0x0 GPIO_DT_FLAGS_MASK>; + gpio-map = , + , + , + , + , /* SB40=ON, SB41=ON */ + , /* SB40=ON, SB41=ON */ + , + , + , + , + , + , + , + , + , + , + , + , + , + , + + , + , + , + , + , + , + , /* SB13=ON, SB17=ON */ + , + , /* SB13=ON, SB17=ON */ + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + ; + }; +}; From 1e556a85dfffae1551fef0fb942df02f9659799a Mon Sep 17 00:00:00 2001 From: IBEN EL HADJ MESSAOUD Marwa Date: Fri, 31 May 2024 23:34:57 +0200 Subject: [PATCH 1847/2849] soc: st: stm32: add stm32h533xx support Add STM32H533XX familly support Signed-off-by: IBEN EL HADJ MESSAOUD Marwa --- soc/st/stm32/soc.yml | 1 + soc/st/stm32/stm32h5x/Kconfig.defconfig.stm32h533xx | 11 +++++++++++ soc/st/stm32/stm32h5x/Kconfig.soc | 5 +++++ 3 files changed, 17 insertions(+) create mode 100644 soc/st/stm32/stm32h5x/Kconfig.defconfig.stm32h533xx diff --git a/soc/st/stm32/soc.yml b/soc/st/stm32/soc.yml index 2572f6b0f0c7c..ac27dee7f6233 100644 --- a/soc/st/stm32/soc.yml +++ b/soc/st/stm32/soc.yml @@ -98,6 +98,7 @@ family: - name: stm32h5x socs: - name: stm32h503xx + - name: stm32h533xx - name: stm32h562xx - name: stm32h563xx - name: stm32h573xx diff --git a/soc/st/stm32/stm32h5x/Kconfig.defconfig.stm32h533xx b/soc/st/stm32/stm32h5x/Kconfig.defconfig.stm32h533xx new file mode 100644 index 0000000000000..62af9621c28b4 --- /dev/null +++ b/soc/st/stm32/stm32h5x/Kconfig.defconfig.stm32h533xx @@ -0,0 +1,11 @@ +# STMicroelectronics STM32H503XX MCU + +# Copyright (c) 2024 STMicroelectronics +# SPDX-License-Identifier: Apache-2.0 + +if SOC_STM32H533XX + +config NUM_IRQS + default 133 + +endif # SOC_STM32H533XX diff --git a/soc/st/stm32/stm32h5x/Kconfig.soc b/soc/st/stm32/stm32h5x/Kconfig.soc index f218ad100648e..abc8b16f34c7a 100644 --- a/soc/st/stm32/stm32h5x/Kconfig.soc +++ b/soc/st/stm32/stm32h5x/Kconfig.soc @@ -14,6 +14,10 @@ config SOC_STM32H503XX bool select SOC_SERIES_STM32H5X +config SOC_STM32H533XX + bool + select SOC_SERIES_STM32H5X + config SOC_STM32H562XX bool select SOC_SERIES_STM32H5X @@ -28,6 +32,7 @@ config SOC_STM32H573XX config SOC default "stm32h503xx" if SOC_STM32H503XX + default "stm32h533xx" if SOC_STM32H533XX default "stm32h562xx" if SOC_STM32H562XX default "stm32h563xx" if SOC_STM32H563XX default "stm32h573xx" if SOC_STM32H573XX From c9491a818f9a2657cbf5854cda0e44827b70733b Mon Sep 17 00:00:00 2001 From: Alberto Escolar Piedras Date: Mon, 3 Jun 2024 15:59:56 +0200 Subject: [PATCH 1848/2849] Bluetooth: Controller: Correct power levels for bsim targets The simulated targets support the same power levels as the real targets. Let's correct the kconfig dependencies accordingly. Signed-off-by: Alberto Escolar Piedras --- subsys/bluetooth/controller/Kconfig | 40 ++++++++++++++--------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/subsys/bluetooth/controller/Kconfig b/subsys/bluetooth/controller/Kconfig index dc7143bc7f52d..3d1a36445444d 100644 --- a/subsys/bluetooth/controller/Kconfig +++ b/subsys/bluetooth/controller/Kconfig @@ -280,83 +280,83 @@ config BT_CTLR_TX_PWR_PLUS_9 config BT_CTLR_TX_PWR_PLUS_8 bool "+8 dBm" - depends on HAS_HW_NRF_RADIO_TX_PWR_HIGH || SOC_SERIES_NRF54HX || SOC_SERIES_NRF54LX + depends on HAS_HW_NRF_RADIO_TX_PWR_HIGH || SOC_SERIES_NRF54HX || SOC_COMPATIBLE_NRF54LX config BT_CTLR_TX_PWR_PLUS_7 bool "+7 dBm" - depends on HAS_HW_NRF_RADIO_TX_PWR_HIGH || SOC_SERIES_NRF54HX || SOC_SERIES_NRF54LX + depends on HAS_HW_NRF_RADIO_TX_PWR_HIGH || SOC_SERIES_NRF54HX || SOC_COMPATIBLE_NRF54LX config BT_CTLR_TX_PWR_PLUS_6 bool "+6 dBm" - depends on HAS_HW_NRF_RADIO_TX_PWR_HIGH || SOC_SERIES_NRF54HX || SOC_SERIES_NRF54LX + depends on HAS_HW_NRF_RADIO_TX_PWR_HIGH || SOC_SERIES_NRF54HX || SOC_COMPATIBLE_NRF54LX config BT_CTLR_TX_PWR_PLUS_5 bool "+5 dBm" - depends on HAS_HW_NRF_RADIO_TX_PWR_HIGH || SOC_SERIES_NRF54HX || SOC_SERIES_NRF54LX + depends on HAS_HW_NRF_RADIO_TX_PWR_HIGH || SOC_SERIES_NRF54HX || SOC_COMPATIBLE_NRF54LX config BT_CTLR_TX_PWR_PLUS_4 bool "+4 dBm" - depends on SOC_SERIES_NRF51X || SOC_COMPATIBLE_NRF52X || SOC_SERIES_NRF54HX || SOC_SERIES_NRF54LX + depends on SOC_SERIES_NRF51X || SOC_COMPATIBLE_NRF52X || SOC_SERIES_NRF54HX || SOC_COMPATIBLE_NRF54LX config BT_CTLR_TX_PWR_PLUS_3 bool "+3 dBm" - depends on SOC_COMPATIBLE_NRF52X || SOC_SERIES_NRF53X || SOC_SERIES_NRF54HX || SOC_SERIES_NRF54LX + depends on SOC_COMPATIBLE_NRF52X || SOC_COMPATIBLE_NRF53X || SOC_SERIES_NRF54HX || SOC_COMPATIBLE_NRF54LX config BT_CTLR_TX_PWR_PLUS_2 bool "+2 dBm" - depends on HAS_HW_NRF_RADIO_TX_PWR_HIGH || SOC_SERIES_NRF53X || SOC_SERIES_NRF54HX || SOC_SERIES_NRF54LX + depends on HAS_HW_NRF_RADIO_TX_PWR_HIGH || SOC_COMPATIBLE_NRF53X || SOC_SERIES_NRF54HX || SOC_COMPATIBLE_NRF54LX config BT_CTLR_TX_PWR_PLUS_1 bool "+1 dBm" - depends on SOC_SERIES_NRF53X || SOC_SERIES_NRF54HX || SOC_SERIES_NRF54LX + depends on SOC_COMPATIBLE_NRF53X || SOC_SERIES_NRF54HX || SOC_COMPATIBLE_NRF54LX config BT_CTLR_TX_PWR_0 bool "0 dBm" config BT_CTLR_TX_PWR_MINUS_1 bool "-1 dBm" - depends on SOC_SERIES_NRF53X || SOC_SERIES_NRF54HX || SOC_SERIES_NRF54LX + depends on SOC_COMPATIBLE_NRF53X || SOC_SERIES_NRF54HX || SOC_COMPATIBLE_NRF54LX config BT_CTLR_TX_PWR_MINUS_2 bool "-2 dBm" - depends on SOC_SERIES_NRF53X || SOC_SERIES_NRF54HX || SOC_SERIES_NRF54LX + depends on SOC_COMPATIBLE_NRF53X || SOC_SERIES_NRF54HX || SOC_COMPATIBLE_NRF54LX config BT_CTLR_TX_PWR_MINUS_3 bool "-3 dBm" - depends on SOC_SERIES_NRF53X || SOC_SERIES_NRF54LX + depends on SOC_COMPATIBLE_NRF53X || SOC_COMPATIBLE_NRF54LX config BT_CTLR_TX_PWR_MINUS_4 bool "-4 dBm" config BT_CTLR_TX_PWR_MINUS_5 bool "-5 dBm" - depends on SOC_SERIES_NRF53X || SOC_SERIES_NRF54LX + depends on SOC_COMPATIBLE_NRF53X || SOC_COMPATIBLE_NRF54LX config BT_CTLR_TX_PWR_MINUS_6 bool "-6 dBm" - depends on SOC_SERIES_NRF53X || SOC_SERIES_NRF54LX + depends on SOC_COMPATIBLE_NRF53X || SOC_COMPATIBLE_NRF54LX config BT_CTLR_TX_PWR_MINUS_7 bool "-7 dBm" - depends on SOC_SERIES_NRF53X || SOC_SERIES_NRF54LX + depends on SOC_COMPATIBLE_NRF53X || SOC_COMPATIBLE_NRF54LX config BT_CTLR_TX_PWR_MINUS_8 bool "-8 dBm" config BT_CTLR_TX_PWR_MINUS_9 bool "-9 dBm" - depends on SOC_SERIES_NRF54LX + depends on SOC_COMPATIBLE_NRF54LX config BT_CTLR_TX_PWR_MINUS_10 bool "-10 dBm" - depends on SOC_SERIES_NRF54LX + depends on SOC_COMPATIBLE_NRF54LX config BT_CTLR_TX_PWR_MINUS_12 bool "-12 dBm" config BT_CTLR_TX_PWR_MINUS_14 bool "-14 dBm" - depends on SOC_SERIES_NRF54LX + depends on SOC_COMPATIBLE_NRF54LX config BT_CTLR_TX_PWR_MINUS_16 bool "-16 dBm" @@ -366,7 +366,7 @@ config BT_CTLR_TX_PWR_MINUS_20 config BT_CTLR_TX_PWR_MINUS_26 bool "-26 dBm" - depends on SOC_SERIES_NRF54LX + depends on SOC_COMPATIBLE_NRF54LX config BT_CTLR_TX_PWR_MINUS_30 bool "-30 dBm" @@ -374,11 +374,11 @@ config BT_CTLR_TX_PWR_MINUS_30 config BT_CTLR_TX_PWR_MINUS_40 bool "-40 dBm" - depends on SOC_COMPATIBLE_NRF52X || SOC_SERIES_NRF53X || SOC_SERIES_NRF54HX || SOC_SERIES_NRF54LX + depends on SOC_COMPATIBLE_NRF52X || SOC_COMPATIBLE_NRF53X || SOC_SERIES_NRF54HX || SOC_COMPATIBLE_NRF54LX config BT_CTLR_TX_PWR_MINUS_46 bool "-46 dBm" - depends on SOC_SERIES_NRF54LX + depends on SOC_COMPATIBLE_NRF54LX config BT_CTLR_TX_PWR_MINUS_70 bool "-70 dBm" From ee4a20de1507b3817ba8b6a8d28565a420f1ec3b Mon Sep 17 00:00:00 2001 From: Ilhan Ates Date: Mon, 3 Jun 2024 16:04:58 +0200 Subject: [PATCH 1849/2849] modules: hal_nordic: nrfx: Use soc compatible definition CONFIG_SOC_SERIES_NRF53X is replaced with SOC_COMPATIBLE_NRF53X to have support for nrf5340bsim Signed-off-by: Ilhan Ates --- modules/hal_nordic/nrfx/nrfx_config.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/hal_nordic/nrfx/nrfx_config.h b/modules/hal_nordic/nrfx/nrfx_config.h index a0f2f481bc37e..d1f9314954ae5 100644 --- a/modules/hal_nordic/nrfx/nrfx_config.h +++ b/modules/hal_nordic/nrfx/nrfx_config.h @@ -32,7 +32,7 @@ #endif #ifdef CONFIG_CLOCK_CONTROL_NRF_K32SRC_RC -#if defined(CONFIG_SOC_SERIES_NRF91X) || defined(CONFIG_SOC_SERIES_NRF53X) +#if defined(CONFIG_SOC_SERIES_NRF91X) || defined(CONFIG_SOC_COMPATIBLE_NRF53X) #define NRFX_CLOCK_CONFIG_LF_SRC 1 #else #define NRFX_CLOCK_CONFIG_LF_SRC 0 @@ -40,7 +40,7 @@ #endif // CONFIG_CLOCK_CONTROL_NRF_K32SRC_RC #ifdef CONFIG_CLOCK_CONTROL_NRF_K32SRC_XTAL -#if defined(CONFIG_SOC_SERIES_NRF91X) || defined(CONFIG_SOC_SERIES_NRF53X) +#if defined(CONFIG_SOC_SERIES_NRF91X) || defined(CONFIG_SOC_COMPATIBLE_NRF53X) #define NRFX_CLOCK_CONFIG_LF_SRC 2 #else #define NRFX_CLOCK_CONFIG_LF_SRC 1 @@ -48,7 +48,7 @@ #endif // CONFIG_CLOCK_CONTROL_NRF_K32SRC_XTAL #ifdef CONFIG_CLOCK_CONTROL_NRF_K32SRC_SYNTH -#ifdef CONFIG_SOC_SERIES_NRF53X +#ifdef CONFIG_SOC_COMPATIBLE_NRF53X #define NRFX_CLOCK_CONFIG_LF_SRC 3 #else #define NRFX_CLOCK_CONFIG_LF_SRC 2 From 38c7503532a39e628038970625ae70cdf6df1187 Mon Sep 17 00:00:00 2001 From: Ryan Erickson Date: Mon, 3 Jun 2024 09:38:14 -0500 Subject: [PATCH 1850/2849] boards: rebrand lairdconnect to ezurio Rename boards/lairdconnect to boards/ezurio. Signed-off-by: Ryan Erickson --- .../bl5340_dvk/CMakeLists.txt | 0 boards/{lairdconnect => ezurio}/bl5340_dvk/Kconfig | 0 .../bl5340_dvk/Kconfig.bl5340_dvk | 0 .../bl5340_dvk/Kconfig.defconfig | 0 .../bl5340_dvk/bl5340_dvk_nrf5340_cpuapp.dts | 0 .../bl5340_dvk/bl5340_dvk_nrf5340_cpuapp.yaml | 0 .../bl5340_dvk_nrf5340_cpuapp_common-pinctrl.dtsi | 0 .../bl5340_dvk_nrf5340_cpuapp_common.dtsi | 0 .../bl5340_dvk/bl5340_dvk_nrf5340_cpuapp_defconfig | 0 .../bl5340_dvk/bl5340_dvk_nrf5340_cpuapp_ns.dts | 0 .../bl5340_dvk/bl5340_dvk_nrf5340_cpuapp_ns.yaml | 0 .../bl5340_dvk_nrf5340_cpuapp_ns_defconfig | 0 .../bl5340_dvk_nrf5340_cpuapp_partition_conf.dtsi | 0 .../bl5340_dvk_nrf5340_cpunet-pinctrl.dtsi | 0 .../bl5340_dvk/bl5340_dvk_nrf5340_cpunet.dts | 0 .../bl5340_dvk/bl5340_dvk_nrf5340_cpunet.yaml | 0 .../bl5340_dvk_nrf5340_cpunet_common.dtsi | 0 .../bl5340_dvk/bl5340_dvk_nrf5340_cpunet_defconfig | 0 .../bl5340_dvk/bl5340_dvk_nrf5340_cpunet_reset.c | 0 ...l5340_dvk_nrf5340_shared_sram_planning_conf.dtsi | 0 .../{lairdconnect => ezurio}/bl5340_dvk/board.cmake | 0 .../{lairdconnect => ezurio}/bl5340_dvk/board.yml | 0 .../bl5340_dvk/doc/img/bl5340_dvk_top.jpg | Bin .../bl5340_dvk/doc/index.rst | 0 .../bl5340_dvk/pre_dt_board.cmake | 0 boards/{lairdconnect => ezurio}/bl652_dvk/Kconfig | 0 .../bl652_dvk/Kconfig.bl652_dvk | 0 .../bl652_dvk/Kconfig.defconfig | 0 .../bl652_dvk/bl652_dvk-pinctrl.dtsi | 0 .../bl652_dvk/bl652_dvk.dts | 0 .../bl652_dvk/bl652_dvk.yaml | 0 .../bl652_dvk/bl652_dvk_defconfig | 0 .../{lairdconnect => ezurio}/bl652_dvk/board.cmake | 0 boards/{lairdconnect => ezurio}/bl652_dvk/board.yml | 0 .../bl652_dvk/doc/bl652_dvk.rst | 0 .../bl652_dvk/doc/img/BL652-SA_DVK_BoxContents.jpg | Bin .../bl652_dvk/doc/img/bl652_dvk.jpg | Bin .../bl652_dvk/pre_dt_board.cmake | 0 boards/{lairdconnect => ezurio}/bl653_dvk/Kconfig | 0 .../bl653_dvk/Kconfig.bl653_dvk | 0 .../bl653_dvk/Kconfig.defconfig | 0 .../bl653_dvk/bl653_dvk-pinctrl.dtsi | 0 .../bl653_dvk/bl653_dvk.dts | 0 .../bl653_dvk/bl653_dvk.yaml | 0 .../bl653_dvk/bl653_dvk_defconfig | 0 .../{lairdconnect => ezurio}/bl653_dvk/board.cmake | 0 boards/{lairdconnect => ezurio}/bl653_dvk/board.yml | 0 .../bl653_dvk/doc/bl653_dvk.rst | 0 .../bl653_dvk/doc/img/bl653_dvk.jpg | Bin .../bl653_dvk/pre_dt_board.cmake | 0 boards/{lairdconnect => ezurio}/bl654_dvk/Kconfig | 0 .../bl654_dvk/Kconfig.bl654_dvk | 0 .../bl654_dvk/Kconfig.defconfig | 0 .../bl654_dvk/bl654_dvk-pinctrl.dtsi | 0 .../bl654_dvk/bl654_dvk.dts | 0 .../bl654_dvk/bl654_dvk.yaml | 0 .../bl654_dvk/bl654_dvk_defconfig | 0 .../bl654_dvk/bl654_dvk_nrf52840_pa.dts | 0 .../bl654_dvk/bl654_dvk_nrf52840_pa.yaml | 0 .../bl654_dvk/bl654_dvk_nrf52840_pa_defconfig | 0 .../{lairdconnect => ezurio}/bl654_dvk/board.cmake | 0 boards/{lairdconnect => ezurio}/bl654_dvk/board.yml | 0 .../bl654_dvk/doc/bl654_dvk.rst | 0 .../bl654_dvk/doc/img/455-00001_BoxContents.jpg | Bin .../bl654_dvk/doc/img/bl654_dvk.jpg | Bin .../bl654_dvk/pre_dt_board.cmake | 0 .../bl654_sensor_board/Kconfig | 0 .../bl654_sensor_board/Kconfig.bl654_sensor_board | 0 .../bl654_sensor_board/Kconfig.defconfig | 0 .../bl654_sensor_board-pinctrl.dtsi | 0 .../bl654_sensor_board/bl654_sensor_board.dts | 0 .../bl654_sensor_board/bl654_sensor_board.yaml | 0 .../bl654_sensor_board/bl654_sensor_board_defconfig | 0 .../bl654_sensor_board/board.cmake | 0 .../bl654_sensor_board/board.yml | 0 .../bl654_sensor_board/doc/bl654_sensor_board.rst | 0 .../doc/img/bl654_sensor_board.jpg | Bin .../img/bl654_sensor_board_usb_swd_programmer.jpg | Bin .../bl654_sensor_board/pre_dt_board.cmake | 0 boards/{lairdconnect => ezurio}/bl654_usb/Kconfig | 0 .../bl654_usb/Kconfig.bl654_usb | 0 .../bl654_usb/Kconfig.defconfig | 0 .../bl654_usb/bl654_usb-pinctrl.dtsi | 0 .../bl654_usb/bl654_usb.dts | 0 .../bl654_usb/bl654_usb.yaml | 0 .../bl654_usb/bl654_usb_defconfig | 0 boards/{lairdconnect => ezurio}/bl654_usb/board.yml | 0 .../bl654_usb/doc/bl654_usb.rst | 0 .../bl654_usb/doc/img/bl654_usb.jpg | Bin .../bl654_usb/doc/img/bl654_usb_pcb.jpg | Bin .../bl654_usb/doc/img/bl654_usb_reset.jpg | Bin .../bl654_usb/pre_dt_board.cmake | 0 boards/{lairdconnect => ezurio}/bt510/Kconfig | 0 boards/{lairdconnect => ezurio}/bt510/Kconfig.bt510 | 0 .../bt510/Kconfig.defconfig | 0 boards/{lairdconnect => ezurio}/bt510/board.cmake | 0 boards/{lairdconnect => ezurio}/bt510/board.yml | 0 .../bt510/bt510-pinctrl.dtsi | 0 boards/{lairdconnect => ezurio}/bt510/bt510.dts | 0 boards/{lairdconnect => ezurio}/bt510/bt510.yaml | 0 .../{lairdconnect => ezurio}/bt510/bt510_defconfig | 0 boards/{lairdconnect => ezurio}/bt510/doc/bt510.rst | 0 .../bt510/doc/img/bt510.jpg | Bin .../bt510/doc/img/bt510_back.jpg | Bin .../bt510/doc/img/bt510_prog.jpg | Bin .../bt510/pre_dt_board.cmake | 0 boards/{lairdconnect => ezurio}/bt610/Kconfig | 0 boards/{lairdconnect => ezurio}/bt610/Kconfig.bt610 | 0 .../bt610/Kconfig.defconfig | 0 boards/{lairdconnect => ezurio}/bt610/board.cmake | 0 boards/{lairdconnect => ezurio}/bt610/board.yml | 0 .../bt610/bt610-pinctrl.dtsi | 0 boards/{lairdconnect => ezurio}/bt610/bt610.dts | 0 boards/{lairdconnect => ezurio}/bt610/bt610.yaml | 0 .../{lairdconnect => ezurio}/bt610/bt610_defconfig | 0 boards/{lairdconnect => ezurio}/bt610/doc/bt610.rst | 0 .../bt610/doc/img/bt610_back.jpg | Bin .../bt610/doc/img/bt610_board.jpg | Bin .../bt610/doc/img/bt610_front.jpg | Bin .../bt610/pre_dt_board.cmake | 0 boards/{lairdconnect => ezurio}/index.rst | 0 boards/{lairdconnect => ezurio}/mg100/Kconfig | 0 .../mg100/Kconfig.defconfig | 0 boards/{lairdconnect => ezurio}/mg100/Kconfig.mg100 | 0 boards/{lairdconnect => ezurio}/mg100/board.cmake | 0 boards/{lairdconnect => ezurio}/mg100/board.yml | 0 .../mg100/doc/img/mg100.jpg | Bin boards/{lairdconnect => ezurio}/mg100/doc/index.rst | 0 .../mg100/mg100-pinctrl.dtsi | 0 boards/{lairdconnect => ezurio}/mg100/mg100.dts | 0 boards/{lairdconnect => ezurio}/mg100/mg100.yaml | 0 .../{lairdconnect => ezurio}/mg100/mg100_defconfig | 0 .../mg100/pre_dt_board.cmake | 0 .../pinnacle_100_dvk/Kconfig | 0 .../pinnacle_100_dvk/Kconfig.defconfig | 0 .../pinnacle_100_dvk/Kconfig.pinnacle_100_dvk | 0 .../pinnacle_100_dvk/board.cmake | 0 .../pinnacle_100_dvk/board.yml | 0 .../pinnacle_100_dvk/doc/img/pinnacle_100_dvk.jpg | Bin .../pinnacle_100_dvk/doc/index.rst | 0 .../pinnacle_100_dvk/pinnacle_100_dvk-pinctrl.dtsi | 0 .../pinnacle_100_dvk/pinnacle_100_dvk.dts | 0 .../pinnacle_100_dvk/pinnacle_100_dvk.yaml | 0 .../pinnacle_100_dvk/pinnacle_100_dvk_defconfig | 0 .../pinnacle_100_dvk/pre_dt_board.cmake | 0 .../rm1xx_dvk/Kconfig.defconfig | 0 .../rm1xx_dvk/Kconfig.rm1xx_dvk | 0 .../{lairdconnect => ezurio}/rm1xx_dvk/board.cmake | 0 boards/{lairdconnect => ezurio}/rm1xx_dvk/board.yml | 0 .../rm1xx_dvk/doc/img/RM186-DVK.jpg | Bin .../rm1xx_dvk/doc/img/RM186-SM.jpg | Bin .../rm1xx_dvk/doc/index.rst | 0 .../rm1xx_dvk/pre_dt_board.cmake | 0 .../rm1xx_dvk/rm1xx_dvk-pinctrl.dtsi | 0 .../rm1xx_dvk/rm1xx_dvk.dts | 0 .../rm1xx_dvk/rm1xx_dvk.yaml | 0 .../rm1xx_dvk/rm1xx_dvk_defconfig | 0 157 files changed, 0 insertions(+), 0 deletions(-) rename boards/{lairdconnect => ezurio}/bl5340_dvk/CMakeLists.txt (100%) rename boards/{lairdconnect => ezurio}/bl5340_dvk/Kconfig (100%) rename boards/{lairdconnect => ezurio}/bl5340_dvk/Kconfig.bl5340_dvk (100%) rename boards/{lairdconnect => ezurio}/bl5340_dvk/Kconfig.defconfig (100%) rename boards/{lairdconnect => ezurio}/bl5340_dvk/bl5340_dvk_nrf5340_cpuapp.dts (100%) rename boards/{lairdconnect => ezurio}/bl5340_dvk/bl5340_dvk_nrf5340_cpuapp.yaml (100%) rename boards/{lairdconnect => ezurio}/bl5340_dvk/bl5340_dvk_nrf5340_cpuapp_common-pinctrl.dtsi (100%) rename boards/{lairdconnect => ezurio}/bl5340_dvk/bl5340_dvk_nrf5340_cpuapp_common.dtsi (100%) rename boards/{lairdconnect => ezurio}/bl5340_dvk/bl5340_dvk_nrf5340_cpuapp_defconfig (100%) rename boards/{lairdconnect => ezurio}/bl5340_dvk/bl5340_dvk_nrf5340_cpuapp_ns.dts (100%) rename boards/{lairdconnect => ezurio}/bl5340_dvk/bl5340_dvk_nrf5340_cpuapp_ns.yaml (100%) rename boards/{lairdconnect => ezurio}/bl5340_dvk/bl5340_dvk_nrf5340_cpuapp_ns_defconfig (100%) rename boards/{lairdconnect => ezurio}/bl5340_dvk/bl5340_dvk_nrf5340_cpuapp_partition_conf.dtsi (100%) rename boards/{lairdconnect => ezurio}/bl5340_dvk/bl5340_dvk_nrf5340_cpunet-pinctrl.dtsi (100%) rename boards/{lairdconnect => ezurio}/bl5340_dvk/bl5340_dvk_nrf5340_cpunet.dts (100%) rename boards/{lairdconnect => ezurio}/bl5340_dvk/bl5340_dvk_nrf5340_cpunet.yaml (100%) rename boards/{lairdconnect => ezurio}/bl5340_dvk/bl5340_dvk_nrf5340_cpunet_common.dtsi (100%) rename boards/{lairdconnect => ezurio}/bl5340_dvk/bl5340_dvk_nrf5340_cpunet_defconfig (100%) rename boards/{lairdconnect => ezurio}/bl5340_dvk/bl5340_dvk_nrf5340_cpunet_reset.c (100%) rename boards/{lairdconnect => ezurio}/bl5340_dvk/bl5340_dvk_nrf5340_shared_sram_planning_conf.dtsi (100%) rename boards/{lairdconnect => ezurio}/bl5340_dvk/board.cmake (100%) rename boards/{lairdconnect => ezurio}/bl5340_dvk/board.yml (100%) rename boards/{lairdconnect => ezurio}/bl5340_dvk/doc/img/bl5340_dvk_top.jpg (100%) rename boards/{lairdconnect => ezurio}/bl5340_dvk/doc/index.rst (100%) rename boards/{lairdconnect => ezurio}/bl5340_dvk/pre_dt_board.cmake (100%) rename boards/{lairdconnect => ezurio}/bl652_dvk/Kconfig (100%) rename boards/{lairdconnect => ezurio}/bl652_dvk/Kconfig.bl652_dvk (100%) rename boards/{lairdconnect => ezurio}/bl652_dvk/Kconfig.defconfig (100%) rename boards/{lairdconnect => ezurio}/bl652_dvk/bl652_dvk-pinctrl.dtsi (100%) rename boards/{lairdconnect => ezurio}/bl652_dvk/bl652_dvk.dts (100%) rename boards/{lairdconnect => ezurio}/bl652_dvk/bl652_dvk.yaml (100%) rename boards/{lairdconnect => ezurio}/bl652_dvk/bl652_dvk_defconfig (100%) rename boards/{lairdconnect => ezurio}/bl652_dvk/board.cmake (100%) rename boards/{lairdconnect => ezurio}/bl652_dvk/board.yml (100%) rename boards/{lairdconnect => ezurio}/bl652_dvk/doc/bl652_dvk.rst (100%) rename boards/{lairdconnect => ezurio}/bl652_dvk/doc/img/BL652-SA_DVK_BoxContents.jpg (100%) rename boards/{lairdconnect => ezurio}/bl652_dvk/doc/img/bl652_dvk.jpg (100%) rename boards/{lairdconnect => ezurio}/bl652_dvk/pre_dt_board.cmake (100%) rename boards/{lairdconnect => ezurio}/bl653_dvk/Kconfig (100%) rename boards/{lairdconnect => ezurio}/bl653_dvk/Kconfig.bl653_dvk (100%) rename boards/{lairdconnect => ezurio}/bl653_dvk/Kconfig.defconfig (100%) rename boards/{lairdconnect => ezurio}/bl653_dvk/bl653_dvk-pinctrl.dtsi (100%) rename boards/{lairdconnect => ezurio}/bl653_dvk/bl653_dvk.dts (100%) rename boards/{lairdconnect => ezurio}/bl653_dvk/bl653_dvk.yaml (100%) rename boards/{lairdconnect => ezurio}/bl653_dvk/bl653_dvk_defconfig (100%) rename boards/{lairdconnect => ezurio}/bl653_dvk/board.cmake (100%) rename boards/{lairdconnect => ezurio}/bl653_dvk/board.yml (100%) rename boards/{lairdconnect => ezurio}/bl653_dvk/doc/bl653_dvk.rst (100%) rename boards/{lairdconnect => ezurio}/bl653_dvk/doc/img/bl653_dvk.jpg (100%) rename boards/{lairdconnect => ezurio}/bl653_dvk/pre_dt_board.cmake (100%) rename boards/{lairdconnect => ezurio}/bl654_dvk/Kconfig (100%) rename boards/{lairdconnect => ezurio}/bl654_dvk/Kconfig.bl654_dvk (100%) rename boards/{lairdconnect => ezurio}/bl654_dvk/Kconfig.defconfig (100%) rename boards/{lairdconnect => ezurio}/bl654_dvk/bl654_dvk-pinctrl.dtsi (100%) rename boards/{lairdconnect => ezurio}/bl654_dvk/bl654_dvk.dts (100%) rename boards/{lairdconnect => ezurio}/bl654_dvk/bl654_dvk.yaml (100%) rename boards/{lairdconnect => ezurio}/bl654_dvk/bl654_dvk_defconfig (100%) rename boards/{lairdconnect => ezurio}/bl654_dvk/bl654_dvk_nrf52840_pa.dts (100%) rename boards/{lairdconnect => ezurio}/bl654_dvk/bl654_dvk_nrf52840_pa.yaml (100%) rename boards/{lairdconnect => ezurio}/bl654_dvk/bl654_dvk_nrf52840_pa_defconfig (100%) rename boards/{lairdconnect => ezurio}/bl654_dvk/board.cmake (100%) rename boards/{lairdconnect => ezurio}/bl654_dvk/board.yml (100%) rename boards/{lairdconnect => ezurio}/bl654_dvk/doc/bl654_dvk.rst (100%) rename boards/{lairdconnect => ezurio}/bl654_dvk/doc/img/455-00001_BoxContents.jpg (100%) rename boards/{lairdconnect => ezurio}/bl654_dvk/doc/img/bl654_dvk.jpg (100%) rename boards/{lairdconnect => ezurio}/bl654_dvk/pre_dt_board.cmake (100%) rename boards/{lairdconnect => ezurio}/bl654_sensor_board/Kconfig (100%) rename boards/{lairdconnect => ezurio}/bl654_sensor_board/Kconfig.bl654_sensor_board (100%) rename boards/{lairdconnect => ezurio}/bl654_sensor_board/Kconfig.defconfig (100%) rename boards/{lairdconnect => ezurio}/bl654_sensor_board/bl654_sensor_board-pinctrl.dtsi (100%) rename boards/{lairdconnect => ezurio}/bl654_sensor_board/bl654_sensor_board.dts (100%) rename boards/{lairdconnect => ezurio}/bl654_sensor_board/bl654_sensor_board.yaml (100%) rename boards/{lairdconnect => ezurio}/bl654_sensor_board/bl654_sensor_board_defconfig (100%) rename boards/{lairdconnect => ezurio}/bl654_sensor_board/board.cmake (100%) rename boards/{lairdconnect => ezurio}/bl654_sensor_board/board.yml (100%) rename boards/{lairdconnect => ezurio}/bl654_sensor_board/doc/bl654_sensor_board.rst (100%) rename boards/{lairdconnect => ezurio}/bl654_sensor_board/doc/img/bl654_sensor_board.jpg (100%) rename boards/{lairdconnect => ezurio}/bl654_sensor_board/doc/img/bl654_sensor_board_usb_swd_programmer.jpg (100%) rename boards/{lairdconnect => ezurio}/bl654_sensor_board/pre_dt_board.cmake (100%) rename boards/{lairdconnect => ezurio}/bl654_usb/Kconfig (100%) rename boards/{lairdconnect => ezurio}/bl654_usb/Kconfig.bl654_usb (100%) rename boards/{lairdconnect => ezurio}/bl654_usb/Kconfig.defconfig (100%) rename boards/{lairdconnect => ezurio}/bl654_usb/bl654_usb-pinctrl.dtsi (100%) rename boards/{lairdconnect => ezurio}/bl654_usb/bl654_usb.dts (100%) rename boards/{lairdconnect => ezurio}/bl654_usb/bl654_usb.yaml (100%) rename boards/{lairdconnect => ezurio}/bl654_usb/bl654_usb_defconfig (100%) rename boards/{lairdconnect => ezurio}/bl654_usb/board.yml (100%) rename boards/{lairdconnect => ezurio}/bl654_usb/doc/bl654_usb.rst (100%) rename boards/{lairdconnect => ezurio}/bl654_usb/doc/img/bl654_usb.jpg (100%) rename boards/{lairdconnect => ezurio}/bl654_usb/doc/img/bl654_usb_pcb.jpg (100%) rename boards/{lairdconnect => ezurio}/bl654_usb/doc/img/bl654_usb_reset.jpg (100%) rename boards/{lairdconnect => ezurio}/bl654_usb/pre_dt_board.cmake (100%) rename boards/{lairdconnect => ezurio}/bt510/Kconfig (100%) rename boards/{lairdconnect => ezurio}/bt510/Kconfig.bt510 (100%) rename boards/{lairdconnect => ezurio}/bt510/Kconfig.defconfig (100%) rename boards/{lairdconnect => ezurio}/bt510/board.cmake (100%) rename boards/{lairdconnect => ezurio}/bt510/board.yml (100%) rename boards/{lairdconnect => ezurio}/bt510/bt510-pinctrl.dtsi (100%) rename boards/{lairdconnect => ezurio}/bt510/bt510.dts (100%) rename boards/{lairdconnect => ezurio}/bt510/bt510.yaml (100%) rename boards/{lairdconnect => ezurio}/bt510/bt510_defconfig (100%) rename boards/{lairdconnect => ezurio}/bt510/doc/bt510.rst (100%) rename boards/{lairdconnect => ezurio}/bt510/doc/img/bt510.jpg (100%) rename boards/{lairdconnect => ezurio}/bt510/doc/img/bt510_back.jpg (100%) rename boards/{lairdconnect => ezurio}/bt510/doc/img/bt510_prog.jpg (100%) rename boards/{lairdconnect => ezurio}/bt510/pre_dt_board.cmake (100%) rename boards/{lairdconnect => ezurio}/bt610/Kconfig (100%) rename boards/{lairdconnect => ezurio}/bt610/Kconfig.bt610 (100%) rename boards/{lairdconnect => ezurio}/bt610/Kconfig.defconfig (100%) rename boards/{lairdconnect => ezurio}/bt610/board.cmake (100%) rename boards/{lairdconnect => ezurio}/bt610/board.yml (100%) rename boards/{lairdconnect => ezurio}/bt610/bt610-pinctrl.dtsi (100%) rename boards/{lairdconnect => ezurio}/bt610/bt610.dts (100%) rename boards/{lairdconnect => ezurio}/bt610/bt610.yaml (100%) rename boards/{lairdconnect => ezurio}/bt610/bt610_defconfig (100%) rename boards/{lairdconnect => ezurio}/bt610/doc/bt610.rst (100%) rename boards/{lairdconnect => ezurio}/bt610/doc/img/bt610_back.jpg (100%) rename boards/{lairdconnect => ezurio}/bt610/doc/img/bt610_board.jpg (100%) rename boards/{lairdconnect => ezurio}/bt610/doc/img/bt610_front.jpg (100%) rename boards/{lairdconnect => ezurio}/bt610/pre_dt_board.cmake (100%) rename boards/{lairdconnect => ezurio}/index.rst (100%) rename boards/{lairdconnect => ezurio}/mg100/Kconfig (100%) rename boards/{lairdconnect => ezurio}/mg100/Kconfig.defconfig (100%) rename boards/{lairdconnect => ezurio}/mg100/Kconfig.mg100 (100%) rename boards/{lairdconnect => ezurio}/mg100/board.cmake (100%) rename boards/{lairdconnect => ezurio}/mg100/board.yml (100%) rename boards/{lairdconnect => ezurio}/mg100/doc/img/mg100.jpg (100%) rename boards/{lairdconnect => ezurio}/mg100/doc/index.rst (100%) rename boards/{lairdconnect => ezurio}/mg100/mg100-pinctrl.dtsi (100%) rename boards/{lairdconnect => ezurio}/mg100/mg100.dts (100%) rename boards/{lairdconnect => ezurio}/mg100/mg100.yaml (100%) rename boards/{lairdconnect => ezurio}/mg100/mg100_defconfig (100%) rename boards/{lairdconnect => ezurio}/mg100/pre_dt_board.cmake (100%) rename boards/{lairdconnect => ezurio}/pinnacle_100_dvk/Kconfig (100%) rename boards/{lairdconnect => ezurio}/pinnacle_100_dvk/Kconfig.defconfig (100%) rename boards/{lairdconnect => ezurio}/pinnacle_100_dvk/Kconfig.pinnacle_100_dvk (100%) rename boards/{lairdconnect => ezurio}/pinnacle_100_dvk/board.cmake (100%) rename boards/{lairdconnect => ezurio}/pinnacle_100_dvk/board.yml (100%) rename boards/{lairdconnect => ezurio}/pinnacle_100_dvk/doc/img/pinnacle_100_dvk.jpg (100%) rename boards/{lairdconnect => ezurio}/pinnacle_100_dvk/doc/index.rst (100%) rename boards/{lairdconnect => ezurio}/pinnacle_100_dvk/pinnacle_100_dvk-pinctrl.dtsi (100%) rename boards/{lairdconnect => ezurio}/pinnacle_100_dvk/pinnacle_100_dvk.dts (100%) rename boards/{lairdconnect => ezurio}/pinnacle_100_dvk/pinnacle_100_dvk.yaml (100%) rename boards/{lairdconnect => ezurio}/pinnacle_100_dvk/pinnacle_100_dvk_defconfig (100%) rename boards/{lairdconnect => ezurio}/pinnacle_100_dvk/pre_dt_board.cmake (100%) rename boards/{lairdconnect => ezurio}/rm1xx_dvk/Kconfig.defconfig (100%) rename boards/{lairdconnect => ezurio}/rm1xx_dvk/Kconfig.rm1xx_dvk (100%) rename boards/{lairdconnect => ezurio}/rm1xx_dvk/board.cmake (100%) rename boards/{lairdconnect => ezurio}/rm1xx_dvk/board.yml (100%) rename boards/{lairdconnect => ezurio}/rm1xx_dvk/doc/img/RM186-DVK.jpg (100%) rename boards/{lairdconnect => ezurio}/rm1xx_dvk/doc/img/RM186-SM.jpg (100%) rename boards/{lairdconnect => ezurio}/rm1xx_dvk/doc/index.rst (100%) rename boards/{lairdconnect => ezurio}/rm1xx_dvk/pre_dt_board.cmake (100%) rename boards/{lairdconnect => ezurio}/rm1xx_dvk/rm1xx_dvk-pinctrl.dtsi (100%) rename boards/{lairdconnect => ezurio}/rm1xx_dvk/rm1xx_dvk.dts (100%) rename boards/{lairdconnect => ezurio}/rm1xx_dvk/rm1xx_dvk.yaml (100%) rename boards/{lairdconnect => ezurio}/rm1xx_dvk/rm1xx_dvk_defconfig (100%) diff --git a/boards/lairdconnect/bl5340_dvk/CMakeLists.txt b/boards/ezurio/bl5340_dvk/CMakeLists.txt similarity index 100% rename from boards/lairdconnect/bl5340_dvk/CMakeLists.txt rename to boards/ezurio/bl5340_dvk/CMakeLists.txt diff --git a/boards/lairdconnect/bl5340_dvk/Kconfig b/boards/ezurio/bl5340_dvk/Kconfig similarity index 100% rename from boards/lairdconnect/bl5340_dvk/Kconfig rename to boards/ezurio/bl5340_dvk/Kconfig diff --git a/boards/lairdconnect/bl5340_dvk/Kconfig.bl5340_dvk b/boards/ezurio/bl5340_dvk/Kconfig.bl5340_dvk similarity index 100% rename from boards/lairdconnect/bl5340_dvk/Kconfig.bl5340_dvk rename to boards/ezurio/bl5340_dvk/Kconfig.bl5340_dvk diff --git a/boards/lairdconnect/bl5340_dvk/Kconfig.defconfig b/boards/ezurio/bl5340_dvk/Kconfig.defconfig similarity index 100% rename from boards/lairdconnect/bl5340_dvk/Kconfig.defconfig rename to boards/ezurio/bl5340_dvk/Kconfig.defconfig diff --git a/boards/lairdconnect/bl5340_dvk/bl5340_dvk_nrf5340_cpuapp.dts b/boards/ezurio/bl5340_dvk/bl5340_dvk_nrf5340_cpuapp.dts similarity index 100% rename from boards/lairdconnect/bl5340_dvk/bl5340_dvk_nrf5340_cpuapp.dts rename to boards/ezurio/bl5340_dvk/bl5340_dvk_nrf5340_cpuapp.dts diff --git a/boards/lairdconnect/bl5340_dvk/bl5340_dvk_nrf5340_cpuapp.yaml b/boards/ezurio/bl5340_dvk/bl5340_dvk_nrf5340_cpuapp.yaml similarity index 100% rename from boards/lairdconnect/bl5340_dvk/bl5340_dvk_nrf5340_cpuapp.yaml rename to boards/ezurio/bl5340_dvk/bl5340_dvk_nrf5340_cpuapp.yaml diff --git a/boards/lairdconnect/bl5340_dvk/bl5340_dvk_nrf5340_cpuapp_common-pinctrl.dtsi b/boards/ezurio/bl5340_dvk/bl5340_dvk_nrf5340_cpuapp_common-pinctrl.dtsi similarity index 100% rename from boards/lairdconnect/bl5340_dvk/bl5340_dvk_nrf5340_cpuapp_common-pinctrl.dtsi rename to boards/ezurio/bl5340_dvk/bl5340_dvk_nrf5340_cpuapp_common-pinctrl.dtsi diff --git a/boards/lairdconnect/bl5340_dvk/bl5340_dvk_nrf5340_cpuapp_common.dtsi b/boards/ezurio/bl5340_dvk/bl5340_dvk_nrf5340_cpuapp_common.dtsi similarity index 100% rename from boards/lairdconnect/bl5340_dvk/bl5340_dvk_nrf5340_cpuapp_common.dtsi rename to boards/ezurio/bl5340_dvk/bl5340_dvk_nrf5340_cpuapp_common.dtsi diff --git a/boards/lairdconnect/bl5340_dvk/bl5340_dvk_nrf5340_cpuapp_defconfig b/boards/ezurio/bl5340_dvk/bl5340_dvk_nrf5340_cpuapp_defconfig similarity index 100% rename from boards/lairdconnect/bl5340_dvk/bl5340_dvk_nrf5340_cpuapp_defconfig rename to boards/ezurio/bl5340_dvk/bl5340_dvk_nrf5340_cpuapp_defconfig diff --git a/boards/lairdconnect/bl5340_dvk/bl5340_dvk_nrf5340_cpuapp_ns.dts b/boards/ezurio/bl5340_dvk/bl5340_dvk_nrf5340_cpuapp_ns.dts similarity index 100% rename from boards/lairdconnect/bl5340_dvk/bl5340_dvk_nrf5340_cpuapp_ns.dts rename to boards/ezurio/bl5340_dvk/bl5340_dvk_nrf5340_cpuapp_ns.dts diff --git a/boards/lairdconnect/bl5340_dvk/bl5340_dvk_nrf5340_cpuapp_ns.yaml b/boards/ezurio/bl5340_dvk/bl5340_dvk_nrf5340_cpuapp_ns.yaml similarity index 100% rename from boards/lairdconnect/bl5340_dvk/bl5340_dvk_nrf5340_cpuapp_ns.yaml rename to boards/ezurio/bl5340_dvk/bl5340_dvk_nrf5340_cpuapp_ns.yaml diff --git a/boards/lairdconnect/bl5340_dvk/bl5340_dvk_nrf5340_cpuapp_ns_defconfig b/boards/ezurio/bl5340_dvk/bl5340_dvk_nrf5340_cpuapp_ns_defconfig similarity index 100% rename from boards/lairdconnect/bl5340_dvk/bl5340_dvk_nrf5340_cpuapp_ns_defconfig rename to boards/ezurio/bl5340_dvk/bl5340_dvk_nrf5340_cpuapp_ns_defconfig diff --git a/boards/lairdconnect/bl5340_dvk/bl5340_dvk_nrf5340_cpuapp_partition_conf.dtsi b/boards/ezurio/bl5340_dvk/bl5340_dvk_nrf5340_cpuapp_partition_conf.dtsi similarity index 100% rename from boards/lairdconnect/bl5340_dvk/bl5340_dvk_nrf5340_cpuapp_partition_conf.dtsi rename to boards/ezurio/bl5340_dvk/bl5340_dvk_nrf5340_cpuapp_partition_conf.dtsi diff --git a/boards/lairdconnect/bl5340_dvk/bl5340_dvk_nrf5340_cpunet-pinctrl.dtsi b/boards/ezurio/bl5340_dvk/bl5340_dvk_nrf5340_cpunet-pinctrl.dtsi similarity index 100% rename from boards/lairdconnect/bl5340_dvk/bl5340_dvk_nrf5340_cpunet-pinctrl.dtsi rename to boards/ezurio/bl5340_dvk/bl5340_dvk_nrf5340_cpunet-pinctrl.dtsi diff --git a/boards/lairdconnect/bl5340_dvk/bl5340_dvk_nrf5340_cpunet.dts b/boards/ezurio/bl5340_dvk/bl5340_dvk_nrf5340_cpunet.dts similarity index 100% rename from boards/lairdconnect/bl5340_dvk/bl5340_dvk_nrf5340_cpunet.dts rename to boards/ezurio/bl5340_dvk/bl5340_dvk_nrf5340_cpunet.dts diff --git a/boards/lairdconnect/bl5340_dvk/bl5340_dvk_nrf5340_cpunet.yaml b/boards/ezurio/bl5340_dvk/bl5340_dvk_nrf5340_cpunet.yaml similarity index 100% rename from boards/lairdconnect/bl5340_dvk/bl5340_dvk_nrf5340_cpunet.yaml rename to boards/ezurio/bl5340_dvk/bl5340_dvk_nrf5340_cpunet.yaml diff --git a/boards/lairdconnect/bl5340_dvk/bl5340_dvk_nrf5340_cpunet_common.dtsi b/boards/ezurio/bl5340_dvk/bl5340_dvk_nrf5340_cpunet_common.dtsi similarity index 100% rename from boards/lairdconnect/bl5340_dvk/bl5340_dvk_nrf5340_cpunet_common.dtsi rename to boards/ezurio/bl5340_dvk/bl5340_dvk_nrf5340_cpunet_common.dtsi diff --git a/boards/lairdconnect/bl5340_dvk/bl5340_dvk_nrf5340_cpunet_defconfig b/boards/ezurio/bl5340_dvk/bl5340_dvk_nrf5340_cpunet_defconfig similarity index 100% rename from boards/lairdconnect/bl5340_dvk/bl5340_dvk_nrf5340_cpunet_defconfig rename to boards/ezurio/bl5340_dvk/bl5340_dvk_nrf5340_cpunet_defconfig diff --git a/boards/lairdconnect/bl5340_dvk/bl5340_dvk_nrf5340_cpunet_reset.c b/boards/ezurio/bl5340_dvk/bl5340_dvk_nrf5340_cpunet_reset.c similarity index 100% rename from boards/lairdconnect/bl5340_dvk/bl5340_dvk_nrf5340_cpunet_reset.c rename to boards/ezurio/bl5340_dvk/bl5340_dvk_nrf5340_cpunet_reset.c diff --git a/boards/lairdconnect/bl5340_dvk/bl5340_dvk_nrf5340_shared_sram_planning_conf.dtsi b/boards/ezurio/bl5340_dvk/bl5340_dvk_nrf5340_shared_sram_planning_conf.dtsi similarity index 100% rename from boards/lairdconnect/bl5340_dvk/bl5340_dvk_nrf5340_shared_sram_planning_conf.dtsi rename to boards/ezurio/bl5340_dvk/bl5340_dvk_nrf5340_shared_sram_planning_conf.dtsi diff --git a/boards/lairdconnect/bl5340_dvk/board.cmake b/boards/ezurio/bl5340_dvk/board.cmake similarity index 100% rename from boards/lairdconnect/bl5340_dvk/board.cmake rename to boards/ezurio/bl5340_dvk/board.cmake diff --git a/boards/lairdconnect/bl5340_dvk/board.yml b/boards/ezurio/bl5340_dvk/board.yml similarity index 100% rename from boards/lairdconnect/bl5340_dvk/board.yml rename to boards/ezurio/bl5340_dvk/board.yml diff --git a/boards/lairdconnect/bl5340_dvk/doc/img/bl5340_dvk_top.jpg b/boards/ezurio/bl5340_dvk/doc/img/bl5340_dvk_top.jpg similarity index 100% rename from boards/lairdconnect/bl5340_dvk/doc/img/bl5340_dvk_top.jpg rename to boards/ezurio/bl5340_dvk/doc/img/bl5340_dvk_top.jpg diff --git a/boards/lairdconnect/bl5340_dvk/doc/index.rst b/boards/ezurio/bl5340_dvk/doc/index.rst similarity index 100% rename from boards/lairdconnect/bl5340_dvk/doc/index.rst rename to boards/ezurio/bl5340_dvk/doc/index.rst diff --git a/boards/lairdconnect/bl5340_dvk/pre_dt_board.cmake b/boards/ezurio/bl5340_dvk/pre_dt_board.cmake similarity index 100% rename from boards/lairdconnect/bl5340_dvk/pre_dt_board.cmake rename to boards/ezurio/bl5340_dvk/pre_dt_board.cmake diff --git a/boards/lairdconnect/bl652_dvk/Kconfig b/boards/ezurio/bl652_dvk/Kconfig similarity index 100% rename from boards/lairdconnect/bl652_dvk/Kconfig rename to boards/ezurio/bl652_dvk/Kconfig diff --git a/boards/lairdconnect/bl652_dvk/Kconfig.bl652_dvk b/boards/ezurio/bl652_dvk/Kconfig.bl652_dvk similarity index 100% rename from boards/lairdconnect/bl652_dvk/Kconfig.bl652_dvk rename to boards/ezurio/bl652_dvk/Kconfig.bl652_dvk diff --git a/boards/lairdconnect/bl652_dvk/Kconfig.defconfig b/boards/ezurio/bl652_dvk/Kconfig.defconfig similarity index 100% rename from boards/lairdconnect/bl652_dvk/Kconfig.defconfig rename to boards/ezurio/bl652_dvk/Kconfig.defconfig diff --git a/boards/lairdconnect/bl652_dvk/bl652_dvk-pinctrl.dtsi b/boards/ezurio/bl652_dvk/bl652_dvk-pinctrl.dtsi similarity index 100% rename from boards/lairdconnect/bl652_dvk/bl652_dvk-pinctrl.dtsi rename to boards/ezurio/bl652_dvk/bl652_dvk-pinctrl.dtsi diff --git a/boards/lairdconnect/bl652_dvk/bl652_dvk.dts b/boards/ezurio/bl652_dvk/bl652_dvk.dts similarity index 100% rename from boards/lairdconnect/bl652_dvk/bl652_dvk.dts rename to boards/ezurio/bl652_dvk/bl652_dvk.dts diff --git a/boards/lairdconnect/bl652_dvk/bl652_dvk.yaml b/boards/ezurio/bl652_dvk/bl652_dvk.yaml similarity index 100% rename from boards/lairdconnect/bl652_dvk/bl652_dvk.yaml rename to boards/ezurio/bl652_dvk/bl652_dvk.yaml diff --git a/boards/lairdconnect/bl652_dvk/bl652_dvk_defconfig b/boards/ezurio/bl652_dvk/bl652_dvk_defconfig similarity index 100% rename from boards/lairdconnect/bl652_dvk/bl652_dvk_defconfig rename to boards/ezurio/bl652_dvk/bl652_dvk_defconfig diff --git a/boards/lairdconnect/bl652_dvk/board.cmake b/boards/ezurio/bl652_dvk/board.cmake similarity index 100% rename from boards/lairdconnect/bl652_dvk/board.cmake rename to boards/ezurio/bl652_dvk/board.cmake diff --git a/boards/lairdconnect/bl652_dvk/board.yml b/boards/ezurio/bl652_dvk/board.yml similarity index 100% rename from boards/lairdconnect/bl652_dvk/board.yml rename to boards/ezurio/bl652_dvk/board.yml diff --git a/boards/lairdconnect/bl652_dvk/doc/bl652_dvk.rst b/boards/ezurio/bl652_dvk/doc/bl652_dvk.rst similarity index 100% rename from boards/lairdconnect/bl652_dvk/doc/bl652_dvk.rst rename to boards/ezurio/bl652_dvk/doc/bl652_dvk.rst diff --git a/boards/lairdconnect/bl652_dvk/doc/img/BL652-SA_DVK_BoxContents.jpg b/boards/ezurio/bl652_dvk/doc/img/BL652-SA_DVK_BoxContents.jpg similarity index 100% rename from boards/lairdconnect/bl652_dvk/doc/img/BL652-SA_DVK_BoxContents.jpg rename to boards/ezurio/bl652_dvk/doc/img/BL652-SA_DVK_BoxContents.jpg diff --git a/boards/lairdconnect/bl652_dvk/doc/img/bl652_dvk.jpg b/boards/ezurio/bl652_dvk/doc/img/bl652_dvk.jpg similarity index 100% rename from boards/lairdconnect/bl652_dvk/doc/img/bl652_dvk.jpg rename to boards/ezurio/bl652_dvk/doc/img/bl652_dvk.jpg diff --git a/boards/lairdconnect/bl652_dvk/pre_dt_board.cmake b/boards/ezurio/bl652_dvk/pre_dt_board.cmake similarity index 100% rename from boards/lairdconnect/bl652_dvk/pre_dt_board.cmake rename to boards/ezurio/bl652_dvk/pre_dt_board.cmake diff --git a/boards/lairdconnect/bl653_dvk/Kconfig b/boards/ezurio/bl653_dvk/Kconfig similarity index 100% rename from boards/lairdconnect/bl653_dvk/Kconfig rename to boards/ezurio/bl653_dvk/Kconfig diff --git a/boards/lairdconnect/bl653_dvk/Kconfig.bl653_dvk b/boards/ezurio/bl653_dvk/Kconfig.bl653_dvk similarity index 100% rename from boards/lairdconnect/bl653_dvk/Kconfig.bl653_dvk rename to boards/ezurio/bl653_dvk/Kconfig.bl653_dvk diff --git a/boards/lairdconnect/bl653_dvk/Kconfig.defconfig b/boards/ezurio/bl653_dvk/Kconfig.defconfig similarity index 100% rename from boards/lairdconnect/bl653_dvk/Kconfig.defconfig rename to boards/ezurio/bl653_dvk/Kconfig.defconfig diff --git a/boards/lairdconnect/bl653_dvk/bl653_dvk-pinctrl.dtsi b/boards/ezurio/bl653_dvk/bl653_dvk-pinctrl.dtsi similarity index 100% rename from boards/lairdconnect/bl653_dvk/bl653_dvk-pinctrl.dtsi rename to boards/ezurio/bl653_dvk/bl653_dvk-pinctrl.dtsi diff --git a/boards/lairdconnect/bl653_dvk/bl653_dvk.dts b/boards/ezurio/bl653_dvk/bl653_dvk.dts similarity index 100% rename from boards/lairdconnect/bl653_dvk/bl653_dvk.dts rename to boards/ezurio/bl653_dvk/bl653_dvk.dts diff --git a/boards/lairdconnect/bl653_dvk/bl653_dvk.yaml b/boards/ezurio/bl653_dvk/bl653_dvk.yaml similarity index 100% rename from boards/lairdconnect/bl653_dvk/bl653_dvk.yaml rename to boards/ezurio/bl653_dvk/bl653_dvk.yaml diff --git a/boards/lairdconnect/bl653_dvk/bl653_dvk_defconfig b/boards/ezurio/bl653_dvk/bl653_dvk_defconfig similarity index 100% rename from boards/lairdconnect/bl653_dvk/bl653_dvk_defconfig rename to boards/ezurio/bl653_dvk/bl653_dvk_defconfig diff --git a/boards/lairdconnect/bl653_dvk/board.cmake b/boards/ezurio/bl653_dvk/board.cmake similarity index 100% rename from boards/lairdconnect/bl653_dvk/board.cmake rename to boards/ezurio/bl653_dvk/board.cmake diff --git a/boards/lairdconnect/bl653_dvk/board.yml b/boards/ezurio/bl653_dvk/board.yml similarity index 100% rename from boards/lairdconnect/bl653_dvk/board.yml rename to boards/ezurio/bl653_dvk/board.yml diff --git a/boards/lairdconnect/bl653_dvk/doc/bl653_dvk.rst b/boards/ezurio/bl653_dvk/doc/bl653_dvk.rst similarity index 100% rename from boards/lairdconnect/bl653_dvk/doc/bl653_dvk.rst rename to boards/ezurio/bl653_dvk/doc/bl653_dvk.rst diff --git a/boards/lairdconnect/bl653_dvk/doc/img/bl653_dvk.jpg b/boards/ezurio/bl653_dvk/doc/img/bl653_dvk.jpg similarity index 100% rename from boards/lairdconnect/bl653_dvk/doc/img/bl653_dvk.jpg rename to boards/ezurio/bl653_dvk/doc/img/bl653_dvk.jpg diff --git a/boards/lairdconnect/bl653_dvk/pre_dt_board.cmake b/boards/ezurio/bl653_dvk/pre_dt_board.cmake similarity index 100% rename from boards/lairdconnect/bl653_dvk/pre_dt_board.cmake rename to boards/ezurio/bl653_dvk/pre_dt_board.cmake diff --git a/boards/lairdconnect/bl654_dvk/Kconfig b/boards/ezurio/bl654_dvk/Kconfig similarity index 100% rename from boards/lairdconnect/bl654_dvk/Kconfig rename to boards/ezurio/bl654_dvk/Kconfig diff --git a/boards/lairdconnect/bl654_dvk/Kconfig.bl654_dvk b/boards/ezurio/bl654_dvk/Kconfig.bl654_dvk similarity index 100% rename from boards/lairdconnect/bl654_dvk/Kconfig.bl654_dvk rename to boards/ezurio/bl654_dvk/Kconfig.bl654_dvk diff --git a/boards/lairdconnect/bl654_dvk/Kconfig.defconfig b/boards/ezurio/bl654_dvk/Kconfig.defconfig similarity index 100% rename from boards/lairdconnect/bl654_dvk/Kconfig.defconfig rename to boards/ezurio/bl654_dvk/Kconfig.defconfig diff --git a/boards/lairdconnect/bl654_dvk/bl654_dvk-pinctrl.dtsi b/boards/ezurio/bl654_dvk/bl654_dvk-pinctrl.dtsi similarity index 100% rename from boards/lairdconnect/bl654_dvk/bl654_dvk-pinctrl.dtsi rename to boards/ezurio/bl654_dvk/bl654_dvk-pinctrl.dtsi diff --git a/boards/lairdconnect/bl654_dvk/bl654_dvk.dts b/boards/ezurio/bl654_dvk/bl654_dvk.dts similarity index 100% rename from boards/lairdconnect/bl654_dvk/bl654_dvk.dts rename to boards/ezurio/bl654_dvk/bl654_dvk.dts diff --git a/boards/lairdconnect/bl654_dvk/bl654_dvk.yaml b/boards/ezurio/bl654_dvk/bl654_dvk.yaml similarity index 100% rename from boards/lairdconnect/bl654_dvk/bl654_dvk.yaml rename to boards/ezurio/bl654_dvk/bl654_dvk.yaml diff --git a/boards/lairdconnect/bl654_dvk/bl654_dvk_defconfig b/boards/ezurio/bl654_dvk/bl654_dvk_defconfig similarity index 100% rename from boards/lairdconnect/bl654_dvk/bl654_dvk_defconfig rename to boards/ezurio/bl654_dvk/bl654_dvk_defconfig diff --git a/boards/lairdconnect/bl654_dvk/bl654_dvk_nrf52840_pa.dts b/boards/ezurio/bl654_dvk/bl654_dvk_nrf52840_pa.dts similarity index 100% rename from boards/lairdconnect/bl654_dvk/bl654_dvk_nrf52840_pa.dts rename to boards/ezurio/bl654_dvk/bl654_dvk_nrf52840_pa.dts diff --git a/boards/lairdconnect/bl654_dvk/bl654_dvk_nrf52840_pa.yaml b/boards/ezurio/bl654_dvk/bl654_dvk_nrf52840_pa.yaml similarity index 100% rename from boards/lairdconnect/bl654_dvk/bl654_dvk_nrf52840_pa.yaml rename to boards/ezurio/bl654_dvk/bl654_dvk_nrf52840_pa.yaml diff --git a/boards/lairdconnect/bl654_dvk/bl654_dvk_nrf52840_pa_defconfig b/boards/ezurio/bl654_dvk/bl654_dvk_nrf52840_pa_defconfig similarity index 100% rename from boards/lairdconnect/bl654_dvk/bl654_dvk_nrf52840_pa_defconfig rename to boards/ezurio/bl654_dvk/bl654_dvk_nrf52840_pa_defconfig diff --git a/boards/lairdconnect/bl654_dvk/board.cmake b/boards/ezurio/bl654_dvk/board.cmake similarity index 100% rename from boards/lairdconnect/bl654_dvk/board.cmake rename to boards/ezurio/bl654_dvk/board.cmake diff --git a/boards/lairdconnect/bl654_dvk/board.yml b/boards/ezurio/bl654_dvk/board.yml similarity index 100% rename from boards/lairdconnect/bl654_dvk/board.yml rename to boards/ezurio/bl654_dvk/board.yml diff --git a/boards/lairdconnect/bl654_dvk/doc/bl654_dvk.rst b/boards/ezurio/bl654_dvk/doc/bl654_dvk.rst similarity index 100% rename from boards/lairdconnect/bl654_dvk/doc/bl654_dvk.rst rename to boards/ezurio/bl654_dvk/doc/bl654_dvk.rst diff --git a/boards/lairdconnect/bl654_dvk/doc/img/455-00001_BoxContents.jpg b/boards/ezurio/bl654_dvk/doc/img/455-00001_BoxContents.jpg similarity index 100% rename from boards/lairdconnect/bl654_dvk/doc/img/455-00001_BoxContents.jpg rename to boards/ezurio/bl654_dvk/doc/img/455-00001_BoxContents.jpg diff --git a/boards/lairdconnect/bl654_dvk/doc/img/bl654_dvk.jpg b/boards/ezurio/bl654_dvk/doc/img/bl654_dvk.jpg similarity index 100% rename from boards/lairdconnect/bl654_dvk/doc/img/bl654_dvk.jpg rename to boards/ezurio/bl654_dvk/doc/img/bl654_dvk.jpg diff --git a/boards/lairdconnect/bl654_dvk/pre_dt_board.cmake b/boards/ezurio/bl654_dvk/pre_dt_board.cmake similarity index 100% rename from boards/lairdconnect/bl654_dvk/pre_dt_board.cmake rename to boards/ezurio/bl654_dvk/pre_dt_board.cmake diff --git a/boards/lairdconnect/bl654_sensor_board/Kconfig b/boards/ezurio/bl654_sensor_board/Kconfig similarity index 100% rename from boards/lairdconnect/bl654_sensor_board/Kconfig rename to boards/ezurio/bl654_sensor_board/Kconfig diff --git a/boards/lairdconnect/bl654_sensor_board/Kconfig.bl654_sensor_board b/boards/ezurio/bl654_sensor_board/Kconfig.bl654_sensor_board similarity index 100% rename from boards/lairdconnect/bl654_sensor_board/Kconfig.bl654_sensor_board rename to boards/ezurio/bl654_sensor_board/Kconfig.bl654_sensor_board diff --git a/boards/lairdconnect/bl654_sensor_board/Kconfig.defconfig b/boards/ezurio/bl654_sensor_board/Kconfig.defconfig similarity index 100% rename from boards/lairdconnect/bl654_sensor_board/Kconfig.defconfig rename to boards/ezurio/bl654_sensor_board/Kconfig.defconfig diff --git a/boards/lairdconnect/bl654_sensor_board/bl654_sensor_board-pinctrl.dtsi b/boards/ezurio/bl654_sensor_board/bl654_sensor_board-pinctrl.dtsi similarity index 100% rename from boards/lairdconnect/bl654_sensor_board/bl654_sensor_board-pinctrl.dtsi rename to boards/ezurio/bl654_sensor_board/bl654_sensor_board-pinctrl.dtsi diff --git a/boards/lairdconnect/bl654_sensor_board/bl654_sensor_board.dts b/boards/ezurio/bl654_sensor_board/bl654_sensor_board.dts similarity index 100% rename from boards/lairdconnect/bl654_sensor_board/bl654_sensor_board.dts rename to boards/ezurio/bl654_sensor_board/bl654_sensor_board.dts diff --git a/boards/lairdconnect/bl654_sensor_board/bl654_sensor_board.yaml b/boards/ezurio/bl654_sensor_board/bl654_sensor_board.yaml similarity index 100% rename from boards/lairdconnect/bl654_sensor_board/bl654_sensor_board.yaml rename to boards/ezurio/bl654_sensor_board/bl654_sensor_board.yaml diff --git a/boards/lairdconnect/bl654_sensor_board/bl654_sensor_board_defconfig b/boards/ezurio/bl654_sensor_board/bl654_sensor_board_defconfig similarity index 100% rename from boards/lairdconnect/bl654_sensor_board/bl654_sensor_board_defconfig rename to boards/ezurio/bl654_sensor_board/bl654_sensor_board_defconfig diff --git a/boards/lairdconnect/bl654_sensor_board/board.cmake b/boards/ezurio/bl654_sensor_board/board.cmake similarity index 100% rename from boards/lairdconnect/bl654_sensor_board/board.cmake rename to boards/ezurio/bl654_sensor_board/board.cmake diff --git a/boards/lairdconnect/bl654_sensor_board/board.yml b/boards/ezurio/bl654_sensor_board/board.yml similarity index 100% rename from boards/lairdconnect/bl654_sensor_board/board.yml rename to boards/ezurio/bl654_sensor_board/board.yml diff --git a/boards/lairdconnect/bl654_sensor_board/doc/bl654_sensor_board.rst b/boards/ezurio/bl654_sensor_board/doc/bl654_sensor_board.rst similarity index 100% rename from boards/lairdconnect/bl654_sensor_board/doc/bl654_sensor_board.rst rename to boards/ezurio/bl654_sensor_board/doc/bl654_sensor_board.rst diff --git a/boards/lairdconnect/bl654_sensor_board/doc/img/bl654_sensor_board.jpg b/boards/ezurio/bl654_sensor_board/doc/img/bl654_sensor_board.jpg similarity index 100% rename from boards/lairdconnect/bl654_sensor_board/doc/img/bl654_sensor_board.jpg rename to boards/ezurio/bl654_sensor_board/doc/img/bl654_sensor_board.jpg diff --git a/boards/lairdconnect/bl654_sensor_board/doc/img/bl654_sensor_board_usb_swd_programmer.jpg b/boards/ezurio/bl654_sensor_board/doc/img/bl654_sensor_board_usb_swd_programmer.jpg similarity index 100% rename from boards/lairdconnect/bl654_sensor_board/doc/img/bl654_sensor_board_usb_swd_programmer.jpg rename to boards/ezurio/bl654_sensor_board/doc/img/bl654_sensor_board_usb_swd_programmer.jpg diff --git a/boards/lairdconnect/bl654_sensor_board/pre_dt_board.cmake b/boards/ezurio/bl654_sensor_board/pre_dt_board.cmake similarity index 100% rename from boards/lairdconnect/bl654_sensor_board/pre_dt_board.cmake rename to boards/ezurio/bl654_sensor_board/pre_dt_board.cmake diff --git a/boards/lairdconnect/bl654_usb/Kconfig b/boards/ezurio/bl654_usb/Kconfig similarity index 100% rename from boards/lairdconnect/bl654_usb/Kconfig rename to boards/ezurio/bl654_usb/Kconfig diff --git a/boards/lairdconnect/bl654_usb/Kconfig.bl654_usb b/boards/ezurio/bl654_usb/Kconfig.bl654_usb similarity index 100% rename from boards/lairdconnect/bl654_usb/Kconfig.bl654_usb rename to boards/ezurio/bl654_usb/Kconfig.bl654_usb diff --git a/boards/lairdconnect/bl654_usb/Kconfig.defconfig b/boards/ezurio/bl654_usb/Kconfig.defconfig similarity index 100% rename from boards/lairdconnect/bl654_usb/Kconfig.defconfig rename to boards/ezurio/bl654_usb/Kconfig.defconfig diff --git a/boards/lairdconnect/bl654_usb/bl654_usb-pinctrl.dtsi b/boards/ezurio/bl654_usb/bl654_usb-pinctrl.dtsi similarity index 100% rename from boards/lairdconnect/bl654_usb/bl654_usb-pinctrl.dtsi rename to boards/ezurio/bl654_usb/bl654_usb-pinctrl.dtsi diff --git a/boards/lairdconnect/bl654_usb/bl654_usb.dts b/boards/ezurio/bl654_usb/bl654_usb.dts similarity index 100% rename from boards/lairdconnect/bl654_usb/bl654_usb.dts rename to boards/ezurio/bl654_usb/bl654_usb.dts diff --git a/boards/lairdconnect/bl654_usb/bl654_usb.yaml b/boards/ezurio/bl654_usb/bl654_usb.yaml similarity index 100% rename from boards/lairdconnect/bl654_usb/bl654_usb.yaml rename to boards/ezurio/bl654_usb/bl654_usb.yaml diff --git a/boards/lairdconnect/bl654_usb/bl654_usb_defconfig b/boards/ezurio/bl654_usb/bl654_usb_defconfig similarity index 100% rename from boards/lairdconnect/bl654_usb/bl654_usb_defconfig rename to boards/ezurio/bl654_usb/bl654_usb_defconfig diff --git a/boards/lairdconnect/bl654_usb/board.yml b/boards/ezurio/bl654_usb/board.yml similarity index 100% rename from boards/lairdconnect/bl654_usb/board.yml rename to boards/ezurio/bl654_usb/board.yml diff --git a/boards/lairdconnect/bl654_usb/doc/bl654_usb.rst b/boards/ezurio/bl654_usb/doc/bl654_usb.rst similarity index 100% rename from boards/lairdconnect/bl654_usb/doc/bl654_usb.rst rename to boards/ezurio/bl654_usb/doc/bl654_usb.rst diff --git a/boards/lairdconnect/bl654_usb/doc/img/bl654_usb.jpg b/boards/ezurio/bl654_usb/doc/img/bl654_usb.jpg similarity index 100% rename from boards/lairdconnect/bl654_usb/doc/img/bl654_usb.jpg rename to boards/ezurio/bl654_usb/doc/img/bl654_usb.jpg diff --git a/boards/lairdconnect/bl654_usb/doc/img/bl654_usb_pcb.jpg b/boards/ezurio/bl654_usb/doc/img/bl654_usb_pcb.jpg similarity index 100% rename from boards/lairdconnect/bl654_usb/doc/img/bl654_usb_pcb.jpg rename to boards/ezurio/bl654_usb/doc/img/bl654_usb_pcb.jpg diff --git a/boards/lairdconnect/bl654_usb/doc/img/bl654_usb_reset.jpg b/boards/ezurio/bl654_usb/doc/img/bl654_usb_reset.jpg similarity index 100% rename from boards/lairdconnect/bl654_usb/doc/img/bl654_usb_reset.jpg rename to boards/ezurio/bl654_usb/doc/img/bl654_usb_reset.jpg diff --git a/boards/lairdconnect/bl654_usb/pre_dt_board.cmake b/boards/ezurio/bl654_usb/pre_dt_board.cmake similarity index 100% rename from boards/lairdconnect/bl654_usb/pre_dt_board.cmake rename to boards/ezurio/bl654_usb/pre_dt_board.cmake diff --git a/boards/lairdconnect/bt510/Kconfig b/boards/ezurio/bt510/Kconfig similarity index 100% rename from boards/lairdconnect/bt510/Kconfig rename to boards/ezurio/bt510/Kconfig diff --git a/boards/lairdconnect/bt510/Kconfig.bt510 b/boards/ezurio/bt510/Kconfig.bt510 similarity index 100% rename from boards/lairdconnect/bt510/Kconfig.bt510 rename to boards/ezurio/bt510/Kconfig.bt510 diff --git a/boards/lairdconnect/bt510/Kconfig.defconfig b/boards/ezurio/bt510/Kconfig.defconfig similarity index 100% rename from boards/lairdconnect/bt510/Kconfig.defconfig rename to boards/ezurio/bt510/Kconfig.defconfig diff --git a/boards/lairdconnect/bt510/board.cmake b/boards/ezurio/bt510/board.cmake similarity index 100% rename from boards/lairdconnect/bt510/board.cmake rename to boards/ezurio/bt510/board.cmake diff --git a/boards/lairdconnect/bt510/board.yml b/boards/ezurio/bt510/board.yml similarity index 100% rename from boards/lairdconnect/bt510/board.yml rename to boards/ezurio/bt510/board.yml diff --git a/boards/lairdconnect/bt510/bt510-pinctrl.dtsi b/boards/ezurio/bt510/bt510-pinctrl.dtsi similarity index 100% rename from boards/lairdconnect/bt510/bt510-pinctrl.dtsi rename to boards/ezurio/bt510/bt510-pinctrl.dtsi diff --git a/boards/lairdconnect/bt510/bt510.dts b/boards/ezurio/bt510/bt510.dts similarity index 100% rename from boards/lairdconnect/bt510/bt510.dts rename to boards/ezurio/bt510/bt510.dts diff --git a/boards/lairdconnect/bt510/bt510.yaml b/boards/ezurio/bt510/bt510.yaml similarity index 100% rename from boards/lairdconnect/bt510/bt510.yaml rename to boards/ezurio/bt510/bt510.yaml diff --git a/boards/lairdconnect/bt510/bt510_defconfig b/boards/ezurio/bt510/bt510_defconfig similarity index 100% rename from boards/lairdconnect/bt510/bt510_defconfig rename to boards/ezurio/bt510/bt510_defconfig diff --git a/boards/lairdconnect/bt510/doc/bt510.rst b/boards/ezurio/bt510/doc/bt510.rst similarity index 100% rename from boards/lairdconnect/bt510/doc/bt510.rst rename to boards/ezurio/bt510/doc/bt510.rst diff --git a/boards/lairdconnect/bt510/doc/img/bt510.jpg b/boards/ezurio/bt510/doc/img/bt510.jpg similarity index 100% rename from boards/lairdconnect/bt510/doc/img/bt510.jpg rename to boards/ezurio/bt510/doc/img/bt510.jpg diff --git a/boards/lairdconnect/bt510/doc/img/bt510_back.jpg b/boards/ezurio/bt510/doc/img/bt510_back.jpg similarity index 100% rename from boards/lairdconnect/bt510/doc/img/bt510_back.jpg rename to boards/ezurio/bt510/doc/img/bt510_back.jpg diff --git a/boards/lairdconnect/bt510/doc/img/bt510_prog.jpg b/boards/ezurio/bt510/doc/img/bt510_prog.jpg similarity index 100% rename from boards/lairdconnect/bt510/doc/img/bt510_prog.jpg rename to boards/ezurio/bt510/doc/img/bt510_prog.jpg diff --git a/boards/lairdconnect/bt510/pre_dt_board.cmake b/boards/ezurio/bt510/pre_dt_board.cmake similarity index 100% rename from boards/lairdconnect/bt510/pre_dt_board.cmake rename to boards/ezurio/bt510/pre_dt_board.cmake diff --git a/boards/lairdconnect/bt610/Kconfig b/boards/ezurio/bt610/Kconfig similarity index 100% rename from boards/lairdconnect/bt610/Kconfig rename to boards/ezurio/bt610/Kconfig diff --git a/boards/lairdconnect/bt610/Kconfig.bt610 b/boards/ezurio/bt610/Kconfig.bt610 similarity index 100% rename from boards/lairdconnect/bt610/Kconfig.bt610 rename to boards/ezurio/bt610/Kconfig.bt610 diff --git a/boards/lairdconnect/bt610/Kconfig.defconfig b/boards/ezurio/bt610/Kconfig.defconfig similarity index 100% rename from boards/lairdconnect/bt610/Kconfig.defconfig rename to boards/ezurio/bt610/Kconfig.defconfig diff --git a/boards/lairdconnect/bt610/board.cmake b/boards/ezurio/bt610/board.cmake similarity index 100% rename from boards/lairdconnect/bt610/board.cmake rename to boards/ezurio/bt610/board.cmake diff --git a/boards/lairdconnect/bt610/board.yml b/boards/ezurio/bt610/board.yml similarity index 100% rename from boards/lairdconnect/bt610/board.yml rename to boards/ezurio/bt610/board.yml diff --git a/boards/lairdconnect/bt610/bt610-pinctrl.dtsi b/boards/ezurio/bt610/bt610-pinctrl.dtsi similarity index 100% rename from boards/lairdconnect/bt610/bt610-pinctrl.dtsi rename to boards/ezurio/bt610/bt610-pinctrl.dtsi diff --git a/boards/lairdconnect/bt610/bt610.dts b/boards/ezurio/bt610/bt610.dts similarity index 100% rename from boards/lairdconnect/bt610/bt610.dts rename to boards/ezurio/bt610/bt610.dts diff --git a/boards/lairdconnect/bt610/bt610.yaml b/boards/ezurio/bt610/bt610.yaml similarity index 100% rename from boards/lairdconnect/bt610/bt610.yaml rename to boards/ezurio/bt610/bt610.yaml diff --git a/boards/lairdconnect/bt610/bt610_defconfig b/boards/ezurio/bt610/bt610_defconfig similarity index 100% rename from boards/lairdconnect/bt610/bt610_defconfig rename to boards/ezurio/bt610/bt610_defconfig diff --git a/boards/lairdconnect/bt610/doc/bt610.rst b/boards/ezurio/bt610/doc/bt610.rst similarity index 100% rename from boards/lairdconnect/bt610/doc/bt610.rst rename to boards/ezurio/bt610/doc/bt610.rst diff --git a/boards/lairdconnect/bt610/doc/img/bt610_back.jpg b/boards/ezurio/bt610/doc/img/bt610_back.jpg similarity index 100% rename from boards/lairdconnect/bt610/doc/img/bt610_back.jpg rename to boards/ezurio/bt610/doc/img/bt610_back.jpg diff --git a/boards/lairdconnect/bt610/doc/img/bt610_board.jpg b/boards/ezurio/bt610/doc/img/bt610_board.jpg similarity index 100% rename from boards/lairdconnect/bt610/doc/img/bt610_board.jpg rename to boards/ezurio/bt610/doc/img/bt610_board.jpg diff --git a/boards/lairdconnect/bt610/doc/img/bt610_front.jpg b/boards/ezurio/bt610/doc/img/bt610_front.jpg similarity index 100% rename from boards/lairdconnect/bt610/doc/img/bt610_front.jpg rename to boards/ezurio/bt610/doc/img/bt610_front.jpg diff --git a/boards/lairdconnect/bt610/pre_dt_board.cmake b/boards/ezurio/bt610/pre_dt_board.cmake similarity index 100% rename from boards/lairdconnect/bt610/pre_dt_board.cmake rename to boards/ezurio/bt610/pre_dt_board.cmake diff --git a/boards/lairdconnect/index.rst b/boards/ezurio/index.rst similarity index 100% rename from boards/lairdconnect/index.rst rename to boards/ezurio/index.rst diff --git a/boards/lairdconnect/mg100/Kconfig b/boards/ezurio/mg100/Kconfig similarity index 100% rename from boards/lairdconnect/mg100/Kconfig rename to boards/ezurio/mg100/Kconfig diff --git a/boards/lairdconnect/mg100/Kconfig.defconfig b/boards/ezurio/mg100/Kconfig.defconfig similarity index 100% rename from boards/lairdconnect/mg100/Kconfig.defconfig rename to boards/ezurio/mg100/Kconfig.defconfig diff --git a/boards/lairdconnect/mg100/Kconfig.mg100 b/boards/ezurio/mg100/Kconfig.mg100 similarity index 100% rename from boards/lairdconnect/mg100/Kconfig.mg100 rename to boards/ezurio/mg100/Kconfig.mg100 diff --git a/boards/lairdconnect/mg100/board.cmake b/boards/ezurio/mg100/board.cmake similarity index 100% rename from boards/lairdconnect/mg100/board.cmake rename to boards/ezurio/mg100/board.cmake diff --git a/boards/lairdconnect/mg100/board.yml b/boards/ezurio/mg100/board.yml similarity index 100% rename from boards/lairdconnect/mg100/board.yml rename to boards/ezurio/mg100/board.yml diff --git a/boards/lairdconnect/mg100/doc/img/mg100.jpg b/boards/ezurio/mg100/doc/img/mg100.jpg similarity index 100% rename from boards/lairdconnect/mg100/doc/img/mg100.jpg rename to boards/ezurio/mg100/doc/img/mg100.jpg diff --git a/boards/lairdconnect/mg100/doc/index.rst b/boards/ezurio/mg100/doc/index.rst similarity index 100% rename from boards/lairdconnect/mg100/doc/index.rst rename to boards/ezurio/mg100/doc/index.rst diff --git a/boards/lairdconnect/mg100/mg100-pinctrl.dtsi b/boards/ezurio/mg100/mg100-pinctrl.dtsi similarity index 100% rename from boards/lairdconnect/mg100/mg100-pinctrl.dtsi rename to boards/ezurio/mg100/mg100-pinctrl.dtsi diff --git a/boards/lairdconnect/mg100/mg100.dts b/boards/ezurio/mg100/mg100.dts similarity index 100% rename from boards/lairdconnect/mg100/mg100.dts rename to boards/ezurio/mg100/mg100.dts diff --git a/boards/lairdconnect/mg100/mg100.yaml b/boards/ezurio/mg100/mg100.yaml similarity index 100% rename from boards/lairdconnect/mg100/mg100.yaml rename to boards/ezurio/mg100/mg100.yaml diff --git a/boards/lairdconnect/mg100/mg100_defconfig b/boards/ezurio/mg100/mg100_defconfig similarity index 100% rename from boards/lairdconnect/mg100/mg100_defconfig rename to boards/ezurio/mg100/mg100_defconfig diff --git a/boards/lairdconnect/mg100/pre_dt_board.cmake b/boards/ezurio/mg100/pre_dt_board.cmake similarity index 100% rename from boards/lairdconnect/mg100/pre_dt_board.cmake rename to boards/ezurio/mg100/pre_dt_board.cmake diff --git a/boards/lairdconnect/pinnacle_100_dvk/Kconfig b/boards/ezurio/pinnacle_100_dvk/Kconfig similarity index 100% rename from boards/lairdconnect/pinnacle_100_dvk/Kconfig rename to boards/ezurio/pinnacle_100_dvk/Kconfig diff --git a/boards/lairdconnect/pinnacle_100_dvk/Kconfig.defconfig b/boards/ezurio/pinnacle_100_dvk/Kconfig.defconfig similarity index 100% rename from boards/lairdconnect/pinnacle_100_dvk/Kconfig.defconfig rename to boards/ezurio/pinnacle_100_dvk/Kconfig.defconfig diff --git a/boards/lairdconnect/pinnacle_100_dvk/Kconfig.pinnacle_100_dvk b/boards/ezurio/pinnacle_100_dvk/Kconfig.pinnacle_100_dvk similarity index 100% rename from boards/lairdconnect/pinnacle_100_dvk/Kconfig.pinnacle_100_dvk rename to boards/ezurio/pinnacle_100_dvk/Kconfig.pinnacle_100_dvk diff --git a/boards/lairdconnect/pinnacle_100_dvk/board.cmake b/boards/ezurio/pinnacle_100_dvk/board.cmake similarity index 100% rename from boards/lairdconnect/pinnacle_100_dvk/board.cmake rename to boards/ezurio/pinnacle_100_dvk/board.cmake diff --git a/boards/lairdconnect/pinnacle_100_dvk/board.yml b/boards/ezurio/pinnacle_100_dvk/board.yml similarity index 100% rename from boards/lairdconnect/pinnacle_100_dvk/board.yml rename to boards/ezurio/pinnacle_100_dvk/board.yml diff --git a/boards/lairdconnect/pinnacle_100_dvk/doc/img/pinnacle_100_dvk.jpg b/boards/ezurio/pinnacle_100_dvk/doc/img/pinnacle_100_dvk.jpg similarity index 100% rename from boards/lairdconnect/pinnacle_100_dvk/doc/img/pinnacle_100_dvk.jpg rename to boards/ezurio/pinnacle_100_dvk/doc/img/pinnacle_100_dvk.jpg diff --git a/boards/lairdconnect/pinnacle_100_dvk/doc/index.rst b/boards/ezurio/pinnacle_100_dvk/doc/index.rst similarity index 100% rename from boards/lairdconnect/pinnacle_100_dvk/doc/index.rst rename to boards/ezurio/pinnacle_100_dvk/doc/index.rst diff --git a/boards/lairdconnect/pinnacle_100_dvk/pinnacle_100_dvk-pinctrl.dtsi b/boards/ezurio/pinnacle_100_dvk/pinnacle_100_dvk-pinctrl.dtsi similarity index 100% rename from boards/lairdconnect/pinnacle_100_dvk/pinnacle_100_dvk-pinctrl.dtsi rename to boards/ezurio/pinnacle_100_dvk/pinnacle_100_dvk-pinctrl.dtsi diff --git a/boards/lairdconnect/pinnacle_100_dvk/pinnacle_100_dvk.dts b/boards/ezurio/pinnacle_100_dvk/pinnacle_100_dvk.dts similarity index 100% rename from boards/lairdconnect/pinnacle_100_dvk/pinnacle_100_dvk.dts rename to boards/ezurio/pinnacle_100_dvk/pinnacle_100_dvk.dts diff --git a/boards/lairdconnect/pinnacle_100_dvk/pinnacle_100_dvk.yaml b/boards/ezurio/pinnacle_100_dvk/pinnacle_100_dvk.yaml similarity index 100% rename from boards/lairdconnect/pinnacle_100_dvk/pinnacle_100_dvk.yaml rename to boards/ezurio/pinnacle_100_dvk/pinnacle_100_dvk.yaml diff --git a/boards/lairdconnect/pinnacle_100_dvk/pinnacle_100_dvk_defconfig b/boards/ezurio/pinnacle_100_dvk/pinnacle_100_dvk_defconfig similarity index 100% rename from boards/lairdconnect/pinnacle_100_dvk/pinnacle_100_dvk_defconfig rename to boards/ezurio/pinnacle_100_dvk/pinnacle_100_dvk_defconfig diff --git a/boards/lairdconnect/pinnacle_100_dvk/pre_dt_board.cmake b/boards/ezurio/pinnacle_100_dvk/pre_dt_board.cmake similarity index 100% rename from boards/lairdconnect/pinnacle_100_dvk/pre_dt_board.cmake rename to boards/ezurio/pinnacle_100_dvk/pre_dt_board.cmake diff --git a/boards/lairdconnect/rm1xx_dvk/Kconfig.defconfig b/boards/ezurio/rm1xx_dvk/Kconfig.defconfig similarity index 100% rename from boards/lairdconnect/rm1xx_dvk/Kconfig.defconfig rename to boards/ezurio/rm1xx_dvk/Kconfig.defconfig diff --git a/boards/lairdconnect/rm1xx_dvk/Kconfig.rm1xx_dvk b/boards/ezurio/rm1xx_dvk/Kconfig.rm1xx_dvk similarity index 100% rename from boards/lairdconnect/rm1xx_dvk/Kconfig.rm1xx_dvk rename to boards/ezurio/rm1xx_dvk/Kconfig.rm1xx_dvk diff --git a/boards/lairdconnect/rm1xx_dvk/board.cmake b/boards/ezurio/rm1xx_dvk/board.cmake similarity index 100% rename from boards/lairdconnect/rm1xx_dvk/board.cmake rename to boards/ezurio/rm1xx_dvk/board.cmake diff --git a/boards/lairdconnect/rm1xx_dvk/board.yml b/boards/ezurio/rm1xx_dvk/board.yml similarity index 100% rename from boards/lairdconnect/rm1xx_dvk/board.yml rename to boards/ezurio/rm1xx_dvk/board.yml diff --git a/boards/lairdconnect/rm1xx_dvk/doc/img/RM186-DVK.jpg b/boards/ezurio/rm1xx_dvk/doc/img/RM186-DVK.jpg similarity index 100% rename from boards/lairdconnect/rm1xx_dvk/doc/img/RM186-DVK.jpg rename to boards/ezurio/rm1xx_dvk/doc/img/RM186-DVK.jpg diff --git a/boards/lairdconnect/rm1xx_dvk/doc/img/RM186-SM.jpg b/boards/ezurio/rm1xx_dvk/doc/img/RM186-SM.jpg similarity index 100% rename from boards/lairdconnect/rm1xx_dvk/doc/img/RM186-SM.jpg rename to boards/ezurio/rm1xx_dvk/doc/img/RM186-SM.jpg diff --git a/boards/lairdconnect/rm1xx_dvk/doc/index.rst b/boards/ezurio/rm1xx_dvk/doc/index.rst similarity index 100% rename from boards/lairdconnect/rm1xx_dvk/doc/index.rst rename to boards/ezurio/rm1xx_dvk/doc/index.rst diff --git a/boards/lairdconnect/rm1xx_dvk/pre_dt_board.cmake b/boards/ezurio/rm1xx_dvk/pre_dt_board.cmake similarity index 100% rename from boards/lairdconnect/rm1xx_dvk/pre_dt_board.cmake rename to boards/ezurio/rm1xx_dvk/pre_dt_board.cmake diff --git a/boards/lairdconnect/rm1xx_dvk/rm1xx_dvk-pinctrl.dtsi b/boards/ezurio/rm1xx_dvk/rm1xx_dvk-pinctrl.dtsi similarity index 100% rename from boards/lairdconnect/rm1xx_dvk/rm1xx_dvk-pinctrl.dtsi rename to boards/ezurio/rm1xx_dvk/rm1xx_dvk-pinctrl.dtsi diff --git a/boards/lairdconnect/rm1xx_dvk/rm1xx_dvk.dts b/boards/ezurio/rm1xx_dvk/rm1xx_dvk.dts similarity index 100% rename from boards/lairdconnect/rm1xx_dvk/rm1xx_dvk.dts rename to boards/ezurio/rm1xx_dvk/rm1xx_dvk.dts diff --git a/boards/lairdconnect/rm1xx_dvk/rm1xx_dvk.yaml b/boards/ezurio/rm1xx_dvk/rm1xx_dvk.yaml similarity index 100% rename from boards/lairdconnect/rm1xx_dvk/rm1xx_dvk.yaml rename to boards/ezurio/rm1xx_dvk/rm1xx_dvk.yaml diff --git a/boards/lairdconnect/rm1xx_dvk/rm1xx_dvk_defconfig b/boards/ezurio/rm1xx_dvk/rm1xx_dvk_defconfig similarity index 100% rename from boards/lairdconnect/rm1xx_dvk/rm1xx_dvk_defconfig rename to boards/ezurio/rm1xx_dvk/rm1xx_dvk_defconfig From 647efdc6c27539a851d4a793fbb284d1f81e2b38 Mon Sep 17 00:00:00 2001 From: Ryan Erickson Date: Mon, 3 Jun 2024 11:15:04 -0500 Subject: [PATCH 1851/2849] dts: bindings: change lairdconnect vendor prefix to ezurio lairdconnect is now ezurio. Signed-off-by: Ryan Erickson --- dts/bindings/vendor-prefixes.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dts/bindings/vendor-prefixes.txt b/dts/bindings/vendor-prefixes.txt index 4cc0cae7e82f7..2af0085632bc0 100644 --- a/dts/bindings/vendor-prefixes.txt +++ b/dts/bindings/vendor-prefixes.txt @@ -224,6 +224,7 @@ evervision Evervision Electronics Co. Ltd. exar Exar Corporation excito Excito ezchip EZchip Semiconductor +ezurio Ezurio facebook Facebook (deprecated, use meta) fairphone Fairphone B.V. fanke FANKE Technology Co., Ltd. @@ -353,7 +354,6 @@ kvg Kverneland Group kyo Kyocera Corporation lacie LaCie laird Laird PLC -lairdconnect Laird Connectivity lamobo Ketai Huajie Technology Co., Ltd. lantiq Lantiq Semiconductor lattice Lattice Semiconductor From 2eef28a624c2695b7898785a382002d9541e804d Mon Sep 17 00:00:00 2001 From: Ryan Erickson Date: Mon, 3 Jun 2024 10:36:03 -0500 Subject: [PATCH 1852/2849] drivers: change Laird references to Ezurio Laird is now Ezurio. Update web links. Signed-off-by: Ryan Erickson --- drivers/bluetooth/hci/Kconfig.infineon | 4 ++-- drivers/wifi/infineon/Kconfig.airoc | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/bluetooth/hci/Kconfig.infineon b/drivers/bluetooth/hci/Kconfig.infineon index 6204ed4f8a2fd..bad10399c1b85 100644 --- a/drivers/bluetooth/hci/Kconfig.infineon +++ b/drivers/bluetooth/hci/Kconfig.infineon @@ -92,11 +92,11 @@ choice CYW4373_MODULE config CYW4373_STERLING_LWB5PLUS bool "STERLING-LWB5plus" help - Laird Sterling LWB5+ 802.11ac / Bluetooth 5.0 M.2 Carrier Board + Ezurio Sterling LWB5+ 802.11ac / Bluetooth 5.0 M.2 Carrier Board (E-Type Key w/ SDIO/UART) Detailed information about Type Sterling LWB5+ module you can find on - https://www.lairdconnect.com/wireless-modules/wifi-modules-bluetooth/sterling-lwb5-plus-wifi-5-bluetooth-5-module + https://www.ezurio.com/wireless-modules/wifi-modules-bluetooth/sterling-lwb5-plus-wifi-5-bluetooth-5-module endchoice diff --git a/drivers/wifi/infineon/Kconfig.airoc b/drivers/wifi/infineon/Kconfig.airoc index a3eac53862d54..319253378d318 100644 --- a/drivers/wifi/infineon/Kconfig.airoc +++ b/drivers/wifi/infineon/Kconfig.airoc @@ -116,11 +116,11 @@ choice CYW4373_MODULE config CYW4373_STERLING_LWB5PLUS bool "STERLING-LWB5plus" help - Laird Sterling LWB5+ 802.11ac / Bluetooth 5.0 M.2 Carrier Board + Ezurio Sterling LWB5+ 802.11ac / Bluetooth 5.0 M.2 Carrier Board (E-Type Key w/ SDIO/UART) Detailed information about Type Sterling LWB5+ module you can find on - https://www.lairdconnect.com/wireless-modules/wifi-modules-bluetooth/sterling-lwb5-plus-wifi-5-bluetooth-5-module + https://www.ezurio.com/wireless-modules/wifi-modules-bluetooth/sterling-lwb5-plus-wifi-5-bluetooth-5-module endchoice choice CYW43439_MODULE From 35a45aa9ec2f73ee5de829c155363f5ea805dfef Mon Sep 17 00:00:00 2001 From: Ryan Erickson Date: Tue, 4 Jun 2024 09:10:44 -0500 Subject: [PATCH 1853/2849] boards: ezurio: change Laird Connectivity references to Ezurio Update Laird Connectivity references to Ezurio. Update web links. Signed-off-by: Ryan Erickson --- .../bl5340_dvk/bl5340_dvk_nrf5340_cpuapp.dts | 5 +++-- .../bl5340_dvk/bl5340_dvk_nrf5340_cpuapp.yaml | 2 +- .../bl5340_dvk_nrf5340_cpuapp_ns.dts | 5 +++-- .../bl5340_dvk_nrf5340_cpuapp_ns.yaml | 2 +- .../bl5340_dvk/bl5340_dvk_nrf5340_cpunet.dts | 5 +++-- .../bl5340_dvk/bl5340_dvk_nrf5340_cpunet.yaml | 2 +- boards/ezurio/bl5340_dvk/board.yml | 2 +- boards/ezurio/bl5340_dvk/doc/index.rst | 10 ++++----- boards/ezurio/bl652_dvk/bl652_dvk.dts | 5 +++-- boards/ezurio/bl652_dvk/bl652_dvk.yaml | 2 +- boards/ezurio/bl652_dvk/board.yml | 2 +- boards/ezurio/bl652_dvk/doc/bl652_dvk.rst | 10 ++++----- boards/ezurio/bl653_dvk/bl653_dvk.dts | 5 +++-- boards/ezurio/bl653_dvk/bl653_dvk.yaml | 2 +- boards/ezurio/bl653_dvk/board.yml | 2 +- boards/ezurio/bl653_dvk/doc/bl653_dvk.rst | 10 ++++----- boards/ezurio/bl654_dvk/bl654_dvk.dts | 5 +++-- boards/ezurio/bl654_dvk/bl654_dvk.yaml | 2 +- .../bl654_dvk/bl654_dvk_nrf52840_pa.yaml | 2 +- boards/ezurio/bl654_dvk/board.yml | 2 +- boards/ezurio/bl654_dvk/doc/bl654_dvk.rst | 10 ++++----- .../bl654_sensor_board/bl654_sensor_board.dts | 5 +++-- .../bl654_sensor_board.yaml | 2 +- boards/ezurio/bl654_sensor_board/board.yml | 2 +- .../doc/bl654_sensor_board.rst | 22 +++++++++---------- boards/ezurio/bl654_usb/bl654_usb.dts | 5 +++-- boards/ezurio/bl654_usb/bl654_usb.yaml | 2 +- boards/ezurio/bl654_usb/board.yml | 2 +- boards/ezurio/bl654_usb/doc/bl654_usb.rst | 20 ++++++++--------- boards/ezurio/bt510/board.yml | 2 +- boards/ezurio/bt510/bt510.dts | 5 +++-- boards/ezurio/bt510/bt510.yaml | 2 +- boards/ezurio/bt510/doc/bt510.rst | 12 +++++----- boards/ezurio/bt610/board.yml | 2 +- boards/ezurio/bt610/bt610.dts | 5 +++-- boards/ezurio/bt610/bt610.yaml | 2 +- boards/ezurio/bt610/doc/bt610.rst | 10 ++++----- boards/ezurio/index.rst | 4 ++-- boards/ezurio/mg100/board.yml | 2 +- boards/ezurio/mg100/doc/index.rst | 6 ++--- boards/ezurio/mg100/mg100.dts | 3 ++- boards/ezurio/mg100/mg100.yaml | 2 +- boards/ezurio/pinnacle_100_dvk/board.yml | 2 +- boards/ezurio/pinnacle_100_dvk/doc/index.rst | 6 ++--- .../pinnacle_100_dvk/pinnacle_100_dvk.dts | 3 ++- .../pinnacle_100_dvk/pinnacle_100_dvk.yaml | 2 +- boards/ezurio/rm1xx_dvk/board.yml | 2 +- boards/ezurio/rm1xx_dvk/doc/index.rst | 12 +++++----- boards/ezurio/rm1xx_dvk/rm1xx_dvk.dts | 5 +++-- boards/ezurio/rm1xx_dvk/rm1xx_dvk.yaml | 2 +- 50 files changed, 128 insertions(+), 115 deletions(-) diff --git a/boards/ezurio/bl5340_dvk/bl5340_dvk_nrf5340_cpuapp.dts b/boards/ezurio/bl5340_dvk/bl5340_dvk_nrf5340_cpuapp.dts index 7640e86e4aad1..a1ef13d63e543 100644 --- a/boards/ezurio/bl5340_dvk/bl5340_dvk_nrf5340_cpuapp.dts +++ b/boards/ezurio/bl5340_dvk/bl5340_dvk_nrf5340_cpuapp.dts @@ -1,5 +1,6 @@ /* * Copyright (c) 2021 Laird Connectivity + * Copyright (c) 2024 Ezurio * * SPDX-License-Identifier: Apache-2.0 */ @@ -9,8 +10,8 @@ #include "bl5340_dvk_nrf5340_cpuapp_common.dtsi" / { - model = "Laird Connectivity BL5340 (nRF5340) Application"; - compatible = "lairdconnect,bl5340-dvk-cpuapp"; + model = "Ezurio BL5340 (nRF5340) Application"; + compatible = "ezurio,bl5340-dvk-cpuapp"; chosen { zephyr,sram = &sram0_image; diff --git a/boards/ezurio/bl5340_dvk/bl5340_dvk_nrf5340_cpuapp.yaml b/boards/ezurio/bl5340_dvk/bl5340_dvk_nrf5340_cpuapp.yaml index a4e91d78ab3f4..cf432d7ab6e24 100644 --- a/boards/ezurio/bl5340_dvk/bl5340_dvk_nrf5340_cpuapp.yaml +++ b/boards/ezurio/bl5340_dvk/bl5340_dvk_nrf5340_cpuapp.yaml @@ -18,4 +18,4 @@ supported: - uart - usb_device - watchdog -vendor: lairdconnect +vendor: ezurio diff --git a/boards/ezurio/bl5340_dvk/bl5340_dvk_nrf5340_cpuapp_ns.dts b/boards/ezurio/bl5340_dvk/bl5340_dvk_nrf5340_cpuapp_ns.dts index d159b8c4afe1b..35410c51b70cb 100644 --- a/boards/ezurio/bl5340_dvk/bl5340_dvk_nrf5340_cpuapp_ns.dts +++ b/boards/ezurio/bl5340_dvk/bl5340_dvk_nrf5340_cpuapp_ns.dts @@ -1,5 +1,6 @@ /* * Copyright (c) 2021 Laird Connectivity + * Copyright (c) 2024 Ezurio * * SPDX-License-Identifier: Apache-2.0 */ @@ -9,8 +10,8 @@ #include "bl5340_dvk_nrf5340_cpuapp_common.dtsi" / { - model = "Laird Connectivity BL5340 (nRF5340) Application"; - compatible = "lairdconnect,bl5340-dvk-cpuapp"; + model = "Ezurio BL5340 (nRF5340) Application"; + compatible = "ezurio,bl5340-dvk-cpuapp"; chosen { zephyr,sram = &sram0_ns; diff --git a/boards/ezurio/bl5340_dvk/bl5340_dvk_nrf5340_cpuapp_ns.yaml b/boards/ezurio/bl5340_dvk/bl5340_dvk_nrf5340_cpuapp_ns.yaml index f9ad633de314b..89d29c79e055e 100644 --- a/boards/ezurio/bl5340_dvk/bl5340_dvk_nrf5340_cpuapp_ns.yaml +++ b/boards/ezurio/bl5340_dvk/bl5340_dvk_nrf5340_cpuapp_ns.yaml @@ -17,4 +17,4 @@ supported: - uart - usb_device - watchdog -vendor: lairdconnect +vendor: ezurio diff --git a/boards/ezurio/bl5340_dvk/bl5340_dvk_nrf5340_cpunet.dts b/boards/ezurio/bl5340_dvk/bl5340_dvk_nrf5340_cpunet.dts index 4df761d04879a..ef70281f16670 100644 --- a/boards/ezurio/bl5340_dvk/bl5340_dvk_nrf5340_cpunet.dts +++ b/boards/ezurio/bl5340_dvk/bl5340_dvk_nrf5340_cpunet.dts @@ -1,5 +1,6 @@ /* * Copyright (c) 2021-2023 Laird Connectivity + * Copyright (c) 2024 Ezurio * * SPDX-License-Identifier: Apache-2.0 */ @@ -10,8 +11,8 @@ #include "bl5340_dvk_nrf5340_cpunet_common.dtsi" / { - model = "Laird Connectivity BL5340 (nRF5340) Network"; - compatible = "lairdconnect,bl5340-dvk-cpunet"; + model = "Ezurio BL5340 (nRF5340) Network"; + compatible = "ezurio,bl5340-dvk-cpunet"; chosen { zephyr,console = &uart0; diff --git a/boards/ezurio/bl5340_dvk/bl5340_dvk_nrf5340_cpunet.yaml b/boards/ezurio/bl5340_dvk/bl5340_dvk_nrf5340_cpunet.yaml index d972729671459..ab6f60bdd3ab5 100644 --- a/boards/ezurio/bl5340_dvk/bl5340_dvk_nrf5340_cpunet.yaml +++ b/boards/ezurio/bl5340_dvk/bl5340_dvk_nrf5340_cpunet.yaml @@ -15,4 +15,4 @@ supported: - spi - uart - watchdog -vendor: lairdconnect +vendor: ezurio diff --git a/boards/ezurio/bl5340_dvk/board.yml b/boards/ezurio/bl5340_dvk/board.yml index 71343692f4cb1..69be46ffe62ec 100644 --- a/boards/ezurio/bl5340_dvk/board.yml +++ b/boards/ezurio/bl5340_dvk/board.yml @@ -1,6 +1,6 @@ board: name: bl5340_dvk - vendor: lairdconnect + vendor: ezurio socs: - name: 'nrf5340' variants: diff --git a/boards/ezurio/bl5340_dvk/doc/index.rst b/boards/ezurio/bl5340_dvk/doc/index.rst index 4148b639a6d3a..700838f0764ab 100644 --- a/boards/ezurio/bl5340_dvk/doc/index.rst +++ b/boards/ezurio/bl5340_dvk/doc/index.rst @@ -1,11 +1,11 @@ .. _bl5340_dvk: -Laird Connectivity BL5340 DVK -############################# +Ezurio BL5340 DVK +################# Overview ******** -The BL5340 Development Kit provides support for the Laird Connectivity +The BL5340 Development Kit provides support for the Ezurio BL5340 module which is powered by a dual-core Nordic Semiconductor nRF5340 ARM Cortex-M33F CPU. The nRF5340 inside the BL5340 module is a dual-core SoC based on the Arm® Cortex®-M33 architecture, with: @@ -47,7 +47,7 @@ This development kit has the following features: :align: center :alt: BL5340 DVK - BL5340 DVK (Credit: Laird Connectivity) + BL5340 DVK (Credit: Ezurio) More information about the module can be found on the `BL5340 homepage`_. @@ -420,7 +420,7 @@ References .. _IDAU: https://developer.arm.com/docs/100690/latest/attribution-units-sau-and-idau -.. _BL5340 homepage: https://www.lairdconnect.com/wireless-modules/bluetooth-modules/bluetooth-5-modules/bl5340-series-multi-core-bluetooth-52-802154-nfc-modules +.. _BL5340 homepage: https://www.ezurio.com/wireless-modules/bluetooth-modules/bluetooth-5-modules/bl5340-series-multi-core-bluetooth-52-802154-nfc-modules .. _Nordic Semiconductor Infocenter: https://infocenter.nordicsemi.com .. _TI TCA9538 datasheet: https://www.ti.com/lit/gpn/TCA9538 .. _Macronix MX25R6435FZNIL0 datasheet: https://www.macronix.com/Lists/Datasheet/Attachments/8868/MX25R6435F,%20Wide%20Range,%2064Mb,%20v1.6.pdf diff --git a/boards/ezurio/bl652_dvk/bl652_dvk.dts b/boards/ezurio/bl652_dvk/bl652_dvk.dts index f2cffbd819b96..8a537a8979664 100644 --- a/boards/ezurio/bl652_dvk/bl652_dvk.dts +++ b/boards/ezurio/bl652_dvk/bl652_dvk.dts @@ -1,6 +1,7 @@ /* * Copyright (c) 2019 Laird Connectivity * Copyright (c) 2023 Nordic Semiconductor ASA + * Copyright (c) 2024 Ezurio * * SPDX-License-Identifier: Apache-2.0 */ @@ -11,8 +12,8 @@ #include / { - model = "Laird BL652 DVK"; - compatible = "lairdconnect,bl652_dvk"; + model = "Ezurio BL652 DVK"; + compatible = "ezurio,bl652_dvk"; chosen { zephyr,console = &uart0; diff --git a/boards/ezurio/bl652_dvk/bl652_dvk.yaml b/boards/ezurio/bl652_dvk/bl652_dvk.yaml index a2fd4370d7f4b..a549fcfdd6698 100644 --- a/boards/ezurio/bl652_dvk/bl652_dvk.yaml +++ b/boards/ezurio/bl652_dvk/bl652_dvk.yaml @@ -15,4 +15,4 @@ supported: - pwm - spi - watchdog -vendor: lairdconnect +vendor: ezurio diff --git a/boards/ezurio/bl652_dvk/board.yml b/boards/ezurio/bl652_dvk/board.yml index 2c2e672ec80ac..b573627457f80 100644 --- a/boards/ezurio/bl652_dvk/board.yml +++ b/boards/ezurio/bl652_dvk/board.yml @@ -1,5 +1,5 @@ board: name: bl652_dvk - vendor: lairdconnect + vendor: ezurio socs: - name: nrf52832 diff --git a/boards/ezurio/bl652_dvk/doc/bl652_dvk.rst b/boards/ezurio/bl652_dvk/doc/bl652_dvk.rst index 9acbb30d46ebc..b6fffcc4aa78b 100644 --- a/boards/ezurio/bl652_dvk/doc/bl652_dvk.rst +++ b/boards/ezurio/bl652_dvk/doc/bl652_dvk.rst @@ -1,13 +1,13 @@ .. _bl652_dvk: -Laird Connectivity BL652 DVK -############################ +Ezurio BL652 DVK +################ Overview ******** The BL652 Development Kit hardware provides -support for the Laird Connectivity BL652 module powered by a Nordic Semiconductor nRF52832 ARM Cortex-M4F CPU. +support for the Ezurio BL652 module powered by a Nordic Semiconductor nRF52832 ARM Cortex-M4F CPU. This development kit has the following features: @@ -260,11 +260,11 @@ the board are working properly with Zephyr: You can build and flash the examples to make sure Zephyr is running correctly on your board. The button and LED definitions can be found in -:zephyr_file:`boards/lairdconnect/bl652_dvk/bl652_dvk.dts`. +:zephyr_file:`boards/ezurio/bl652_dvk/bl652_dvk.dts`. References ********** .. target-notes:: -.. _BL652 Module Website: https://connectivity.lairdtech.com/wireless-modules/bluetooth-modules/bluetooth-5-modules/bl652-series-bluetooth-v5-nfc +.. _BL652 Module Website: https://ezurio.com/wireless-modules/bluetooth-modules/bluetooth-5-modules/bl652-series-bluetooth-v5-nfc diff --git a/boards/ezurio/bl653_dvk/bl653_dvk.dts b/boards/ezurio/bl653_dvk/bl653_dvk.dts index 4c536eb451255..35de9a2a80278 100644 --- a/boards/ezurio/bl653_dvk/bl653_dvk.dts +++ b/boards/ezurio/bl653_dvk/bl653_dvk.dts @@ -1,6 +1,7 @@ /* * Copyright (c) 2020 Laird Connectivity * Copyright (c) 2023 Nordic Semiconductor ASA + * Copyright (c) 2024 Ezurio * * SPDX-License-Identifier: Apache-2.0 */ @@ -11,8 +12,8 @@ #include / { - model = "Laird BL653 Dev Kit"; - compatible = "lairdconnect,bl653_dvk"; + model = "Ezurio BL653 Dev Kit"; + compatible = "ezurio,bl653_dvk"; chosen { zephyr,console = &uart0; diff --git a/boards/ezurio/bl653_dvk/bl653_dvk.yaml b/boards/ezurio/bl653_dvk/bl653_dvk.yaml index 6a2792ea5219d..ee1b610f312b9 100644 --- a/boards/ezurio/bl653_dvk/bl653_dvk.yaml +++ b/boards/ezurio/bl653_dvk/bl653_dvk.yaml @@ -16,4 +16,4 @@ supported: - counter - spi - i2c -vendor: lairdconnect +vendor: ezurio diff --git a/boards/ezurio/bl653_dvk/board.yml b/boards/ezurio/bl653_dvk/board.yml index c898247f1f383..dc42555309a23 100644 --- a/boards/ezurio/bl653_dvk/board.yml +++ b/boards/ezurio/bl653_dvk/board.yml @@ -1,5 +1,5 @@ board: name: bl653_dvk - vendor: lairdconnect + vendor: ezurio socs: - name: nrf52833 diff --git a/boards/ezurio/bl653_dvk/doc/bl653_dvk.rst b/boards/ezurio/bl653_dvk/doc/bl653_dvk.rst index 71270f6f4e850..ec8fdb0e02d8c 100644 --- a/boards/ezurio/bl653_dvk/doc/bl653_dvk.rst +++ b/boards/ezurio/bl653_dvk/doc/bl653_dvk.rst @@ -1,13 +1,13 @@ .. _bl653_dvk: -Laird Connectivity BL653 DVK -############################ +Ezurio BL653 DVK +################ Overview ******** The BL653 Development Kit (453-00039-K1, 453-00041-K1) hardware provides -support for the Laird Connectivity BL653 module powered by a Nordic Semiconductor nRF52833 ARM Cortex-M4F CPU. +support for the Ezurio BL653 module powered by a Nordic Semiconductor nRF52833 ARM Cortex-M4F CPU. This development kit has the following features: @@ -167,7 +167,7 @@ the board are working properly with Zephyr: You can build and flash the examples to make sure Zephyr is running correctly on your board. The button and LED definitions can be found in -:zephyr_file:`boards/lairdconnect/bl653_dvk/bl653_dvk.dts`. +:zephyr_file:`boards/ezurio/bl653_dvk/bl653_dvk.dts`. Using UART1 *********** @@ -225,5 +225,5 @@ References .. target-notes:: -.. _BL653 website: https://www.lairdconnect.com/wireless-modules/bluetooth-modules/bluetooth-5-modules/bl653-series-bluetooth-51-802154-nfc-module +.. _BL653 website: https://www.ezurio.com/wireless-modules/bluetooth-modules/bluetooth-5-modules/bl653-series-bluetooth-51-802154-nfc-module .. _nRF52833 Product Specification: https://infocenter.nordicsemi.com/pdf/nRF52833_OPS_v0.7.pdf diff --git a/boards/ezurio/bl654_dvk/bl654_dvk.dts b/boards/ezurio/bl654_dvk/bl654_dvk.dts index 7ede69427de75..6e9848f03cd32 100644 --- a/boards/ezurio/bl654_dvk/bl654_dvk.dts +++ b/boards/ezurio/bl654_dvk/bl654_dvk.dts @@ -1,6 +1,7 @@ /* * Copyright (c) 2019 Laird Connectivity * Copyright (c) 2023 Nordic Semiconductor ASA + * Copyright (c) 2024 Ezurio * * SPDX-License-Identifier: Apache-2.0 */ @@ -11,8 +12,8 @@ #include / { - model = "Laird BL654 Dev Kit"; - compatible = "lairdconnect,bl654_dvk"; + model = "Ezurio BL654 Dev Kit"; + compatible = "ezurio,bl654_dvk"; chosen { zephyr,console = &uart0; diff --git a/boards/ezurio/bl654_dvk/bl654_dvk.yaml b/boards/ezurio/bl654_dvk/bl654_dvk.yaml index 27eec7dcaebac..c4d016d63b699 100644 --- a/boards/ezurio/bl654_dvk/bl654_dvk.yaml +++ b/boards/ezurio/bl654_dvk/bl654_dvk.yaml @@ -12,4 +12,4 @@ supported: - ble - pwm - watchdog -vendor: lairdconnect +vendor: ezurio diff --git a/boards/ezurio/bl654_dvk/bl654_dvk_nrf52840_pa.yaml b/boards/ezurio/bl654_dvk/bl654_dvk_nrf52840_pa.yaml index d02d93862843d..6ecf919159136 100644 --- a/boards/ezurio/bl654_dvk/bl654_dvk_nrf52840_pa.yaml +++ b/boards/ezurio/bl654_dvk/bl654_dvk_nrf52840_pa.yaml @@ -12,4 +12,4 @@ supported: - ble - pwm - watchdog -vendor: lairdconnect +vendor: ezurio diff --git a/boards/ezurio/bl654_dvk/board.yml b/boards/ezurio/bl654_dvk/board.yml index 788824c7af192..fdc9035ff68b0 100644 --- a/boards/ezurio/bl654_dvk/board.yml +++ b/boards/ezurio/bl654_dvk/board.yml @@ -1,6 +1,6 @@ board: name: bl654_dvk - vendor: lairdconnect + vendor: ezurio socs: - name: nrf52840 variants: diff --git a/boards/ezurio/bl654_dvk/doc/bl654_dvk.rst b/boards/ezurio/bl654_dvk/doc/bl654_dvk.rst index 7ccb6294f4bc8..fba2bafba9cbb 100644 --- a/boards/ezurio/bl654_dvk/doc/bl654_dvk.rst +++ b/boards/ezurio/bl654_dvk/doc/bl654_dvk.rst @@ -1,13 +1,13 @@ .. _bl654_dvk: -Laird Connectivity BL654 DVK -############################ +Ezurio BL654 DVK +################ Overview ******** The BL654 Development Kit hardware provides -support for the Laird Connectivity BL654 module powered by a Nordic Semiconductor nRF52840 ARM Cortex-M4F CPU. +support for the Ezurio BL654 module powered by a Nordic Semiconductor nRF52840 ARM Cortex-M4F CPU. It is also pin compatible with the BL654PA which adds a power amplifier. The "pa" variant provides this compatibility. Use board ``bl654_dvk/nrf52840/pa`` to build for that target. @@ -178,7 +178,7 @@ the board are working properly with Zephyr: You can build and flash the examples to make sure Zephyr is running correctly on your board. The button and LED definitions can be found in -:zephyr_file:`boards/lairdconnect/bl654_dvk/bl654_dvk.dts`. +:zephyr_file:`boards/ezurio/bl654_dvk/bl654_dvk.dts`. References @@ -186,5 +186,5 @@ References .. target-notes:: -.. _BL654 website: https://connectivity.lairdtech.com/wireless-modules/bluetooth-modules/bluetooth-5-modules/bl654-series +.. _BL654 website: https://ezurio.com/wireless-modules/bluetooth-modules/bluetooth-5-modules/bl654-series .. _J-Link Software and documentation pack: https://www.segger.com/jlink-software.html diff --git a/boards/ezurio/bl654_sensor_board/bl654_sensor_board.dts b/boards/ezurio/bl654_sensor_board/bl654_sensor_board.dts index c43354f2705f7..8b5993d864dc8 100644 --- a/boards/ezurio/bl654_sensor_board/bl654_sensor_board.dts +++ b/boards/ezurio/bl654_sensor_board/bl654_sensor_board.dts @@ -1,5 +1,6 @@ /* * Copyright (c) 2021 Laird Connectivity + * Copyright (c) 2024 Ezurio * * SPDX-License-Identifier: Apache-2.0 */ @@ -10,8 +11,8 @@ #include / { - model = "Laird BL654 Sensor Board"; - compatible = "lairdconnect,bl654-sensor-board"; + model = "Ezurio BL654 Sensor Board"; + compatible = "ezurio,bl654-sensor-board"; chosen { zephyr,console = &uart0; diff --git a/boards/ezurio/bl654_sensor_board/bl654_sensor_board.yaml b/boards/ezurio/bl654_sensor_board/bl654_sensor_board.yaml index 856805fbd1691..bcaafe5669ac5 100644 --- a/boards/ezurio/bl654_sensor_board/bl654_sensor_board.yaml +++ b/boards/ezurio/bl654_sensor_board/bl654_sensor_board.yaml @@ -17,4 +17,4 @@ supported: - pwm - watchdog - netif:openthread -vendor: lairdconnect +vendor: ezurio diff --git a/boards/ezurio/bl654_sensor_board/board.yml b/boards/ezurio/bl654_sensor_board/board.yml index ebe40b44601f3..566c992411db1 100644 --- a/boards/ezurio/bl654_sensor_board/board.yml +++ b/boards/ezurio/bl654_sensor_board/board.yml @@ -1,5 +1,5 @@ board: name: bl654_sensor_board - vendor: lairdconnect + vendor: ezurio socs: - name: nrf52840 diff --git a/boards/ezurio/bl654_sensor_board/doc/bl654_sensor_board.rst b/boards/ezurio/bl654_sensor_board/doc/bl654_sensor_board.rst index c990c934952ea..50eb94cf5b266 100644 --- a/boards/ezurio/bl654_sensor_board/doc/bl654_sensor_board.rst +++ b/boards/ezurio/bl654_sensor_board/doc/bl654_sensor_board.rst @@ -1,12 +1,12 @@ .. _bl654_sensor_board: -Laird Connectivity BL654 Sensor Board -##################################### +Ezurio BL654 Sensor Board +######################### Overview ******** -The BL654 Sensor Board hardware provides support for the Laird Connectivity +The BL654 Sensor Board hardware provides support for the Ezurio BL654 module which is powered by a Nordic Semiconductor nRF52840 ARM Cortex-M4F CPU. @@ -132,7 +132,7 @@ Applications for the ``bl654_sensor_board`` board configuration can be built, flashed, and debugged in the usual way. See :ref:`build_an_application` and :ref:`application_run` for more details on building and running. An external debugger/programmer is required which can be connected to using a Tag-Connect -TC2030-CTX cable, a Laird Connectivity USB-SWD Programmer board or Segger JLink +TC2030-CTX cable, a Ezurio USB-SWD Programmer board or Segger JLink programmer can be used to program and debug the BL654 sensor board. Flashing @@ -142,14 +142,14 @@ If using an external JLink, follow the instructions in the :ref:`nordic_segger` page to install and configure all the necessary software. Further information can be found in :ref:`nordic_segger_flashing`. Then build and flash applications as usual (see :ref:`build_an_application` and :ref:`application_run` for more -details). If using a Laird Connectivity USB-SWD Programmer Board, see the +details). If using a Ezurio USB-SWD Programmer Board, see the `pyOCD website`_ to find details about the software and how to install it. Here is an example for the :ref:`hello_world` application. First, run your favorite terminal program to listen for output - note that an external UART is required to be connected to the BL654 sensor board's UART, if -using the Laird Connectivity USB-SWD Programmer Board, the BL654 sensor board +using the Ezurio USB-SWD Programmer Board, the BL654 sensor board can be plugged in to the UART header. An FTDI cable can also be used - the voltage of the I/O lines and power line must be between 1.8v and 3.3v, do not connect an FTDI cable with a 5v power line to the BL654 sensor board. @@ -181,7 +181,7 @@ can be found. For example, under Linux, :code:`/dev/ttyACM0`. The BL654 sensor board needs an external programmer to program it, any SWD programmer which has a 9-pin ARM debug port can be used with a Tag-Connect -TC2030-CTX cable. If using the Laird Connectivity USB-SWD Programmer Board, +TC2030-CTX cable. If using the Ezurio USB-SWD Programmer Board, connect the cable to P1 and ensure the board is set to supply power to the target at 3.3v. @@ -214,7 +214,7 @@ Debugging ========= Refer to the :ref:`nordic_segger` page to learn about debugging Nordic based -boards if using an external JLink debugger. If using a Laird Connectivity +boards if using an external JLink debugger. If using a Ezurio USB-SWD Programmer Board, pyOCD can be used for debugging. Testing Bluetooth on the BL654 Sensor Board @@ -238,7 +238,7 @@ the board are working properly with Zephyr: You can build and flash the examples to make sure Zephyr is running correctly on your board. The button and LED definitions can be found in -:zephyr_file:`boards/lairdconnect/bl654_sensor_board/bl654_sensor_board.dts`. +:zephyr_file:`boards/ezurio/bl654_sensor_board/bl654_sensor_board.dts`. References @@ -247,6 +247,6 @@ References .. target-notes:: .. _Bosch BME280 sensor website: https://www.bosch-sensortec.com/products/environmental-sensors/humidity-sensors-bme280/ -.. _BL654 website: https://connectivity.lairdtech.com/wireless-modules/bluetooth-modules/bluetooth-5-modules/bl654-series +.. _BL654 website: https://ezurio.com/wireless-modules/bluetooth-modules/bluetooth-5-modules/bl654-series .. _pyOCD website: https://github.com/pyocd/pyOCD -.. _USB-SWD Programmer website: https://www.lairdconnect.com/usb-swd-programmer +.. _USB-SWD Programmer website: https://www.ezurio.com/usb-swd-programmer diff --git a/boards/ezurio/bl654_usb/bl654_usb.dts b/boards/ezurio/bl654_usb/bl654_usb.dts index fa814f4b80e42..8cde4ae008f98 100644 --- a/boards/ezurio/bl654_usb/bl654_usb.dts +++ b/boards/ezurio/bl654_usb/bl654_usb.dts @@ -1,5 +1,6 @@ /* * Copyright (c) 2021 Laird Connectivity + * Copyright (c) 2024 Ezurio * * SPDX-License-Identifier: Apache-2.0 */ @@ -9,8 +10,8 @@ #include "bl654_usb-pinctrl.dtsi" / { - model = "Laird Connectivity BL654 USB adapter"; - compatible = "lairdconnect,bl654_usb"; + model = "Ezurio BL654 USB adapter"; + compatible = "ezurio,bl654_usb"; chosen { zephyr,sram = &sram0; diff --git a/boards/ezurio/bl654_usb/bl654_usb.yaml b/boards/ezurio/bl654_usb/bl654_usb.yaml index d927657dc7da7..4bf396760cc64 100644 --- a/boards/ezurio/bl654_usb/bl654_usb.yaml +++ b/boards/ezurio/bl654_usb/bl654_usb.yaml @@ -12,4 +12,4 @@ supported: - pwm - watchdog - counter -vendor: lairdconnect +vendor: ezurio diff --git a/boards/ezurio/bl654_usb/board.yml b/boards/ezurio/bl654_usb/board.yml index dc616554605c4..13642fbe7124d 100644 --- a/boards/ezurio/bl654_usb/board.yml +++ b/boards/ezurio/bl654_usb/board.yml @@ -1,5 +1,5 @@ board: name: bl654_usb - vendor: lairdconnect + vendor: ezurio socs: - name: nrf52840 diff --git a/boards/ezurio/bl654_usb/doc/bl654_usb.rst b/boards/ezurio/bl654_usb/doc/bl654_usb.rst index 3bb3139b61564..34a64c14aec47 100644 --- a/boards/ezurio/bl654_usb/doc/bl654_usb.rst +++ b/boards/ezurio/bl654_usb/doc/bl654_usb.rst @@ -1,13 +1,13 @@ .. _bl654_usb: -Laird Connectivity BL654 USB (451-00004) -######################################## +Ezurio BL654 USB (451-00004) +############################ Overview ******** -The BL654 USB adapter hardware (Laird Connectivity part 451-00004) provides -support for the Laird Connectivity BL654 module powered by a Nordic +The BL654 USB adapter hardware (Ezurio part 451-00004) provides +support for the Ezurio BL654 module powered by a Nordic Semiconductor nRF52840 ARM Cortex-M4F CPU. This USB adapter has the following features: @@ -105,14 +105,14 @@ Applications for the ``bl654_usb`` board configuration can be built in the usual way (see :ref:`build_an_application` for more details). The ``bl654_usb`` board cannot be used for debugging. The compatible BL654 DVK board can be used for development. Documentation can be found at the :ref:`bl654_dvk` -site and :zephyr_file:`boards/lairdconnect/bl654_dvk/doc/bl654_dvk.rst` +site and :zephyr_file:`boards/ezurio/bl654_dvk/doc/bl654_dvk.rst` Flashing ======== The board supports programming using the built-in bootloader. -The board is factory-programmed with a Laird Connectivity variation of Nordic's +The board is factory-programmed with a Ezurio variation of Nordic's open bootloader from Nordic's nRF5x SDK. With this option, you'll use Nordic's `nrfutil`_ program to create firmware packages supported by this bootloader and flash them to the device. Make sure ``nrfutil`` is installed @@ -175,7 +175,7 @@ the board is working properly with Zephyr: You can build and flash the example to make sure Zephyr is running correctly on your board. The LED definitions can be found in -:zephyr_file:`boards/lairdconnect/bl654_usb/bl654_usb.dts`. +:zephyr_file:`boards/ezurio/bl654_usb/bl654_usb.dts`. References @@ -183,8 +183,8 @@ References .. target-notes:: -.. _BL654 USB Dongle Quick Start Guide: https://www.lairdconnect.com/documentation/user-guide-bl654-usb-nordic-sdk-zephyr -.. _BL654 website: https://connectivity.lairdtech.com/wireless-modules/bluetooth-modules/bluetooth-5-modules/bl654-series +.. _BL654 USB Dongle Quick Start Guide: https://www.ezurio.com/documentation/user-guide-bl654-usb-nordic-sdk-zephyr +.. _BL654 website: https://ezurio.com/wireless-modules/bluetooth-modules/bluetooth-5-modules/bl654-series .. _J-Link Software and documentation pack: https://www.segger.com/jlink-software.html -.. _Creating a secure bootloader image: https://www.lairdconnect.com/documentation/application-note-creating-secure-bootloader-image-bl654-usb +.. _Creating a secure bootloader image: https://www.ezurio.com/documentation/application-note-creating-secure-bootloader-image-bl654-usb .. _nrfutil: https://github.com/NordicSemiconductor/pc-nrfutil diff --git a/boards/ezurio/bt510/board.yml b/boards/ezurio/bt510/board.yml index 1a9760895ecf1..e4692ed452673 100644 --- a/boards/ezurio/bt510/board.yml +++ b/boards/ezurio/bt510/board.yml @@ -1,5 +1,5 @@ board: name: bt510 - vendor: lairdconnect + vendor: ezurio socs: - name: nrf52840 diff --git a/boards/ezurio/bt510/bt510.dts b/boards/ezurio/bt510/bt510.dts index 984b098e5d53d..adc8337862c08 100644 --- a/boards/ezurio/bt510/bt510.dts +++ b/boards/ezurio/bt510/bt510.dts @@ -1,5 +1,6 @@ /* * Copyright (c) 2020 Laird Connectivity + * Copyright (c) 2024 Ezurio * * SPDX-License-Identifier: Apache-2.0 */ @@ -10,8 +11,8 @@ #include / { - model = "Laird Sentrius BT510 Sensor"; - compatible = "lairdconnect,bt510"; + model = "Ezurio Sentrius BT510 Sensor"; + compatible = "ezurio,bt510"; chosen { zephyr,console = &uart0; diff --git a/boards/ezurio/bt510/bt510.yaml b/boards/ezurio/bt510/bt510.yaml index c9b6823d18815..198b538eecd44 100644 --- a/boards/ezurio/bt510/bt510.yaml +++ b/boards/ezurio/bt510/bt510.yaml @@ -13,4 +13,4 @@ supported: - watchdog - i2c - sm351lt -vendor: lairdconnect +vendor: ezurio diff --git a/boards/ezurio/bt510/doc/bt510.rst b/boards/ezurio/bt510/doc/bt510.rst index 13459f69ea722..2d0dbcbf5069b 100644 --- a/boards/ezurio/bt510/doc/bt510.rst +++ b/boards/ezurio/bt510/doc/bt510.rst @@ -1,7 +1,7 @@ .. _bt510: -Laird Connectivity Sentrius BT510 Sensor -######################################## +Ezurio Sentrius BT510 Sensor +############################ Overview ******** @@ -162,7 +162,7 @@ A non-standard layout is used to include access to the sensor debug UART. Connectivity to the programmer/debugger must be modified to match the pinout shown above. -Laird Connectivity provide the USB-SWD programming board (750-03239) that supports +Ezurio provide the USB-SWD programming board (750-03239) that supports this connector layout, refer to the `USB SWD Programmer product page`_ . @@ -244,7 +244,7 @@ the board are working properly with Zephyr: You can build and flash the examples to make sure Zephyr is running correctly on your board. The button, LED and sensor device definitions can be found in -:zephyr_file:`boards/lairdconnect/bt510/bt510.dts`. +:zephyr_file:`boards/ezurio/bt510/bt510.dts`. References @@ -252,9 +252,9 @@ References .. target-notes:: -.. _Sentrius BT510 website: https://www.lairdconnect.com/iot-devices/iot-sensors/bt510-bluetooth-5-long-range-ip67-multi-sensor +.. _Sentrius BT510 website: https://www.ezurio.com/iot-devices/iot-sensors/bt510-bluetooth-5-long-range-ip67-multi-sensor .. _TagConnect TC2050 product page: https://www.tag-connect.com/product/tc2050-idc-050 -.. _USB SWD Programmer product page: https://www.lairdconnect.com/wireless-modules/programming-kits/usb-swd-programming-kit +.. _USB SWD Programmer product page: https://www.ezurio.com/wireless-modules/programming-kits/usb-swd-programming-kit .. _MAX3232 datasheet: https://www.ti.com/lit/ds/symlink/max3232.pdf .. _Silabs 7055 datasheet: https://www.silabs.com/documents/public/data-sheets/Si7050-1-3-4-5-A20.pdf .. _ST Microelectronics LIS2DH datasheet: https://www.st.com/resource/en/datasheet/lis2dh.pdf diff --git a/boards/ezurio/bt610/board.yml b/boards/ezurio/bt610/board.yml index c5a846a0d8d4a..0e4f29742c5d4 100644 --- a/boards/ezurio/bt610/board.yml +++ b/boards/ezurio/bt610/board.yml @@ -1,5 +1,5 @@ board: name: bt610 - vendor: lairdconnect + vendor: ezurio socs: - name: nrf52840 diff --git a/boards/ezurio/bt610/bt610.dts b/boards/ezurio/bt610/bt610.dts index c6b9bad9910ac..8eb52c0139f11 100644 --- a/boards/ezurio/bt610/bt610.dts +++ b/boards/ezurio/bt610/bt610.dts @@ -1,5 +1,6 @@ /* * Copyright (c) 2021 Laird Connectivity + * Copyright (c) 2024 Ezurio * * SPDX-License-Identifier: Apache-2.0 */ @@ -10,8 +11,8 @@ #include / { - model = "Laird BT610 Sensor"; - compatible = "lairdconnect,bt610"; + model = "Ezurio BT610 Sensor"; + compatible = "ezurio,bt610"; chosen { zephyr,console = &uart0; diff --git a/boards/ezurio/bt610/bt610.yaml b/boards/ezurio/bt610/bt610.yaml index 80cbe9975da15..5b96d98c5275e 100644 --- a/boards/ezurio/bt610/bt610.yaml +++ b/boards/ezurio/bt610/bt610.yaml @@ -19,4 +19,4 @@ supported: - counter - sm351lt - qspi -vendor: lairdconnect +vendor: ezurio diff --git a/boards/ezurio/bt610/doc/bt610.rst b/boards/ezurio/bt610/doc/bt610.rst index baf9827e3d62d..20527ceb1e08a 100644 --- a/boards/ezurio/bt610/doc/bt610.rst +++ b/boards/ezurio/bt610/doc/bt610.rst @@ -1,7 +1,7 @@ .. _bt610: -Laird Connectivity Sentrius BT610 Sensor -######################################## +Ezurio Sentrius BT610 Sensor +############################ Overview ******** @@ -598,7 +598,7 @@ on the board are working properly with Zephyr: You can build and flash the examples to make sure Zephyr is running correctly on your board. The button, LED and sensor device definitions can be found in -:zephyr_file:`boards/lairdconnect/bt610/bt610.dts`. +:zephyr_file:`boards/ezurio/bt610/bt610.dts`. References @@ -606,10 +606,10 @@ References .. target-notes:: -.. _Sentrius BT610 website: https://www.lairdconnect.com/iot-devices/iot-sensors/sentrius-bt610-io-sensor +.. _Sentrius BT610 website: https://www.ezurio.com/iot-devices/iot-sensors/sentrius-bt610-io-sensor .. _Honeywell SM351LT datasheet: https://sensing.honeywell.com/honeywell-sensing-nanopower-series-datasheet-50095501-c-en.pdf .. _MAX3232 datasheet: https://www.ti.com/lit/ds/symlink/max3232.pdf .. _TI TMUX1204 datasheet: https://www.ti.com/lit/gpn/TMUX1204 .. _TI TCA9538 datasheet: https://www.ti.com/lit/gpn/TCA9538 .. _Macronix MX25R6435FZNIL0 datasheet: https://www.macronix.com/Lists/Datasheet/Attachments/7913/MX25R6435F,%20Wide%20Range,%2064Mb,%20v1.5.pdf -.. _BT610 Zephyr Application Thermistor Calibration: https://www.lairdconnect.com/technology/bt610-thermistor-coefficient-calculator +.. _BT610 Zephyr Application Thermistor Calibration: https://www.ezurio.com/technology/bt610-thermistor-coefficient-calculator diff --git a/boards/ezurio/index.rst b/boards/ezurio/index.rst index 5c3a6d6621a2a..5352513a1f378 100644 --- a/boards/ezurio/index.rst +++ b/boards/ezurio/index.rst @@ -1,6 +1,6 @@ -.. _boards-lairdconnect: +.. _boards-ezurio: -Laird Connectivity +Ezurio ################## .. toctree:: diff --git a/boards/ezurio/mg100/board.yml b/boards/ezurio/mg100/board.yml index 25a3ace314f71..4c62320fc5eb7 100644 --- a/boards/ezurio/mg100/board.yml +++ b/boards/ezurio/mg100/board.yml @@ -1,5 +1,5 @@ board: name: mg100 - vendor: lairdconnect + vendor: ezurio socs: - name: nrf52840 diff --git a/boards/ezurio/mg100/doc/index.rst b/boards/ezurio/mg100/doc/index.rst index 611f0db54658a..b8d929c0491a2 100644 --- a/boards/ezurio/mg100/doc/index.rst +++ b/boards/ezurio/mg100/doc/index.rst @@ -1,7 +1,7 @@ .. _mg100: -Laird Connectivity Sentrius™ MG100 Gateway -########################################## +Ezurio Sentrius™ MG100 Gateway +############################## Overview ******** @@ -162,7 +162,7 @@ Applications for the ``mg100`` board configuration can be built and flashed in the usual way. (see :ref:`build_an_application` and :ref:`application_run` for more details) -The `Laird Connectivity USB-SWD Programming Kit`_ contains all the necessary +The `Ezurio USB-SWD Programming Kit`_ contains all the necessary hardware to enable programming and debugging an MG100. Flashing diff --git a/boards/ezurio/mg100/mg100.dts b/boards/ezurio/mg100/mg100.dts index 7c6fbb92d246a..3f69d46febf9c 100644 --- a/boards/ezurio/mg100/mg100.dts +++ b/boards/ezurio/mg100/mg100.dts @@ -1,5 +1,6 @@ /* * Copyright (c) 2022 Laird Connectivity + * Copyright (c) 2024 Ezurio * * SPDX-License-Identifier: Apache-2.0 */ @@ -11,7 +12,7 @@ / { model = "MG100"; - compatible = "lairdconnect,mg100"; + compatible = "ezurio,mg100"; chosen { zephyr,console = &uart0; diff --git a/boards/ezurio/mg100/mg100.yaml b/boards/ezurio/mg100/mg100.yaml index 917eb7f0d8600..54de18e63ee29 100644 --- a/boards/ezurio/mg100/mg100.yaml +++ b/boards/ezurio/mg100/mg100.yaml @@ -18,4 +18,4 @@ supported: - spi - watchdog - netif:modem -vendor: lairdconnect +vendor: ezurio diff --git a/boards/ezurio/pinnacle_100_dvk/board.yml b/boards/ezurio/pinnacle_100_dvk/board.yml index 1741e687ace1b..8ed639a9a0a21 100644 --- a/boards/ezurio/pinnacle_100_dvk/board.yml +++ b/boards/ezurio/pinnacle_100_dvk/board.yml @@ -1,5 +1,5 @@ board: name: pinnacle_100_dvk - vendor: lairdconnect + vendor: ezurio socs: - name: nrf52840 diff --git a/boards/ezurio/pinnacle_100_dvk/doc/index.rst b/boards/ezurio/pinnacle_100_dvk/doc/index.rst index 6feaa13833d46..bedcb8567602c 100644 --- a/boards/ezurio/pinnacle_100_dvk/doc/index.rst +++ b/boards/ezurio/pinnacle_100_dvk/doc/index.rst @@ -1,7 +1,7 @@ .. _pinnacle_100_dvk: -Laird Connectivity Pinnacle 100 DVK -################################### +Ezurio Pinnacle 100 DVK +####################### Overview ******** @@ -14,7 +14,7 @@ internal antennas. Develop your application directly on the M4F controller using Zephyr RTOS to cut BOM costs and power consumption. Take advantage of the Zephyr community, -Laird Connectivity’s sample code (cellular, Bluetooth) and hardware interfaces, +Ezurio’s sample code (cellular, Bluetooth) and hardware interfaces, or use our hosted mode AT commands set firmware. Extremely power conscious, the Pinnacle 100 is ideal for battery-powered diff --git a/boards/ezurio/pinnacle_100_dvk/pinnacle_100_dvk.dts b/boards/ezurio/pinnacle_100_dvk/pinnacle_100_dvk.dts index 1e3006dd0d325..acb5c4e42374a 100644 --- a/boards/ezurio/pinnacle_100_dvk/pinnacle_100_dvk.dts +++ b/boards/ezurio/pinnacle_100_dvk/pinnacle_100_dvk.dts @@ -1,5 +1,6 @@ /* * Copyright (c) 2019 Laird Connectivity + * Copyright (c) 2024 Ezurio * * SPDX-License-Identifier: Apache-2.0 */ @@ -11,7 +12,7 @@ / { model = "Pinnacle 100 Dev Kit"; - compatible = "lairdconnect,pinnacle-100-dvk"; + compatible = "ezurio,pinnacle-100-dvk"; chosen { zephyr,console = &uart0; diff --git a/boards/ezurio/pinnacle_100_dvk/pinnacle_100_dvk.yaml b/boards/ezurio/pinnacle_100_dvk/pinnacle_100_dvk.yaml index c4bd8252d1947..3d44a009e2d06 100644 --- a/boards/ezurio/pinnacle_100_dvk/pinnacle_100_dvk.yaml +++ b/boards/ezurio/pinnacle_100_dvk/pinnacle_100_dvk.yaml @@ -19,4 +19,4 @@ supported: - usb_device - watchdog - netif:modem -vendor: lairdconnect +vendor: ezurio diff --git a/boards/ezurio/rm1xx_dvk/board.yml b/boards/ezurio/rm1xx_dvk/board.yml index 1e7ddd8f80678..4a8792eecc57d 100644 --- a/boards/ezurio/rm1xx_dvk/board.yml +++ b/boards/ezurio/rm1xx_dvk/board.yml @@ -1,5 +1,5 @@ board: name: rm1xx_dvk - vendor: lairdconnect + vendor: ezurio socs: - name: nrf51822 diff --git a/boards/ezurio/rm1xx_dvk/doc/index.rst b/boards/ezurio/rm1xx_dvk/doc/index.rst index bd006dc058a52..f530c9b791fd5 100644 --- a/boards/ezurio/rm1xx_dvk/doc/index.rst +++ b/boards/ezurio/rm1xx_dvk/doc/index.rst @@ -1,12 +1,12 @@ .. _rm1xx_dvk: -Laird Connectivity RM1xx DVK -############################ +Ezurio RM1xx DVK +################ Overview ******** -Laird Connectivity's RM1xx is a module which integrates both LoRa and +Ezurio's RM1xx is a module which integrates both LoRa and BLE communications, powered by a Nordic Semiconductor nRF51822 ARM Cortex-M0 CPU and on-board Semtech SX1272 LoRa RF chip. This board supports the RM1xx on the RM1xx development board - RM191 for the @@ -32,13 +32,13 @@ This development kit has the following features: :align: center :alt: RM1xx development kit (DVK) - RM1xx development kit (DVK) (Credit: Laird Connectivity) + RM1xx development kit (DVK) (Credit: Ezurio) .. figure:: img/RM186-SM.jpg :align: center :alt: RM1xx module - RM1xx module (Credit: Laird Connectivity) + RM1xx module (Credit: Ezurio) More information about the module can be found on the `RM1xx homepage`_. @@ -172,7 +172,7 @@ References .. target-notes:: -.. _RM1xx homepage: https://www.lairdconnect.com/wireless-modules/lorawan-solutions/sentrius-rm1xx-lora-ble-module +.. _RM1xx homepage: https://www.ezurio.com/wireless-modules/lorawan-solutions/sentrius-rm1xx-lora-ble-module .. _Nordic Semiconductor Infocenter: https://infocenter.nordicsemi.com .. _Adesto AT25DF041B datasheet: https://www.dialog-semiconductor.com/sites/default/files/ds-at25df041b_040.pdf .. _Semtech SX1272 datasheet: https://semtech.my.salesforce.com/sfc/p/#E0000000JelG/a/440000001NCE/v_VBhk1IolDgxwwnOpcS_vTFxPfSEPQbuneK3mWsXlU diff --git a/boards/ezurio/rm1xx_dvk/rm1xx_dvk.dts b/boards/ezurio/rm1xx_dvk/rm1xx_dvk.dts index 8d364bfa27aa0..1db61912dfb0c 100644 --- a/boards/ezurio/rm1xx_dvk/rm1xx_dvk.dts +++ b/boards/ezurio/rm1xx_dvk/rm1xx_dvk.dts @@ -1,5 +1,6 @@ /* * Copyright (c) 2021 Laird Connectivity + * Copyright (c) 2024 Ezurio * * SPDX-License-Identifier: Apache-2.0 */ @@ -10,8 +11,8 @@ #include / { - model = "Laird Connectivity RM1XX_DVK"; - compatible = "lairdconnect,rm1xx_dvk"; + model = "Ezurio RM1XX_DVK"; + compatible = "ezurio,rm1xx_dvk"; chosen { zephyr,console = &uart0; diff --git a/boards/ezurio/rm1xx_dvk/rm1xx_dvk.yaml b/boards/ezurio/rm1xx_dvk/rm1xx_dvk.yaml index c673fd4d55ec2..2dd24375a5b7d 100644 --- a/boards/ezurio/rm1xx_dvk/rm1xx_dvk.yaml +++ b/boards/ezurio/rm1xx_dvk/rm1xx_dvk.yaml @@ -14,4 +14,4 @@ supported: testing: ignore_tags: - net -vendor: lairdconnect +vendor: ezurio From 163afed89e8d58813b434a4b9d1e5a515538d9fc Mon Sep 17 00:00:00 2001 From: Ryan Erickson Date: Mon, 3 Jun 2024 10:49:09 -0500 Subject: [PATCH 1854/2849] boards: ezurio: mg100: update software links Highlight Canvas Software Suite platform. Update web links. Signed-off-by: Ryan Erickson --- boards/ezurio/mg100/doc/index.rst | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/boards/ezurio/mg100/doc/index.rst b/boards/ezurio/mg100/doc/index.rst index b8d929c0491a2..b665997a762ca 100644 --- a/boards/ezurio/mg100/doc/index.rst +++ b/boards/ezurio/mg100/doc/index.rst @@ -17,7 +17,7 @@ and network certifications and End Device carrier approvals. Develop your application directly on the integrated Cortex M4F microcontroller using Zephyr RTOS, enabling your application development with a secure, open source RTOS with more than just kernel services. Remotely debug your fleet of devices with the `Memfault Platform`_. Take advantage of the -Zephyr community and Laird Connectivity’s multi featured Out of Box (OOB) sample source code +Zephyr community and Ezurio’s `Canvas Software Suite`_ to accelerate your development. covering all aspects of the product's capabilities and hardware interfaces. The MG100 also delivers complete antenna flexibility with internal or external antenna options available, and the optional battery backup provides uninterrupted reporting of remote Bluetooth sensor data. @@ -204,10 +204,9 @@ Segger IC. Software ******** -MG100 Out-of-Box Demo Software +Canvas Software Suite ============================== -The MG100 ships with an out of the box software demo. -Check out the `BLE Gateway OOB Demo`_ source code and documentation. +The MG100 is a supported hardware platform for `Canvas Software Suite`_. Testing Bluetooth on the MG100 ============================== @@ -231,19 +230,19 @@ the board are working properly with Zephyr: You can build and flash the examples to make sure Zephyr is running correctly on your board. The button and LED definitions can be found in -:zephyr_file:`boards/lairdconnect/mg100/mg100.dts`. +:zephyr_file:`boards/ezurio/mg100/mg100.dts`. References ********** .. target-notes:: -.. _MG100 website: https://www.lairdconnect.com/iot-devices/iot-gateways/sentrius-mg100-gateway-lte-mnb-iot-and-bluetooth-5 +.. _MG100 website: https://www.ezurio.com/iot-devices/iot-gateways/sentrius-mg100-gateway-lte-mnb-iot-and-bluetooth-5 .. _nRF52840 Product Specification: https://infocenter.nordicsemi.com/pdf/nRF52840_PS_v1.1.pdf .. _Sierra Wireless HL7800: https://source.sierrawireless.com/devices/hl-series/hl7800/#sthash.641qTTwA.dpbs .. _J-Link Software and documentation pack: https://www.segger.com/jlink-software.html -.. _BLE Gateway OOB Demo: https://github.com/LairdCP/Pinnacle-100-Firmware-Manifest .. _Macronix MX25R6435F datasheet: https://www.macronix.com/Lists/Datasheet/Attachments/7913/MX25R6435F,%20Wide%20Range,%2064Mb,%20v1.5.pdf -.. _Laird Connectivity USB-SWD Programming Kit: https://www.lairdconnect.com/wireless-modules/programming-kits/usb-swd-programming-kit +.. _Ezurio USB-SWD Programming Kit: https://www.ezurio.com/wireless-modules/programming-kits/usb-swd-programming-kit .. _Memfault Platform: https://docs.memfault.com/docs/mcu/pinnacle-100-guide .. _nRF52840: https://www.nordicsemi.com/products/nrf52840 +.. _Canvas Software Suite: https://www.ezurio.com/canvas/software-suite From d4c15c76ecc8faf1a06bb74a843787010e9e2446 Mon Sep 17 00:00:00 2001 From: Ryan Erickson Date: Mon, 3 Jun 2024 10:52:50 -0500 Subject: [PATCH 1855/2849] boards: ezurio: pinnacle_100_dvk: update software links Highlight Canvas Software Suite platform. Update web links. Signed-off-by: Ryan Erickson --- boards/ezurio/pinnacle_100_dvk/doc/index.rst | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/boards/ezurio/pinnacle_100_dvk/doc/index.rst b/boards/ezurio/pinnacle_100_dvk/doc/index.rst index bedcb8567602c..9650d0c8e25ea 100644 --- a/boards/ezurio/pinnacle_100_dvk/doc/index.rst +++ b/boards/ezurio/pinnacle_100_dvk/doc/index.rst @@ -174,10 +174,9 @@ Segger IC. Software ******** -Pinnacle 100 Out-of-Box Demo Software -===================================== -The Pinnacle 100 development kit ships with an out of the box software demo. -Check out the `Pinnacle 100 OOB Demo`_ source code and documentation. +Canvas Software Suite +============================== +The Pinnacle 100 is a supported hardware platform for `Canvas Software Suite`_. Sample Applications =================== @@ -205,16 +204,16 @@ the board are working properly with Zephyr: You can build and flash the examples to make sure Zephyr is running correctly on your board. The button and LED definitions can be found in -:zephyr_file:`boards/lairdconnect/pinnacle_100_dvk/pinnacle_100_dvk.dts`. +:zephyr_file:`boards/ezurio/pinnacle_100_dvk/pinnacle_100_dvk.dts`. References ********** .. target-notes:: -.. _Pinnacle 100 website: https://www.lairdconnect.com/wireless-modules/cellular-solutions/pinnacle-100-cellular-modem +.. _Pinnacle 100 website: https://www.ezurio.com/wireless-modules/cellular-solutions/pinnacle-100-cellular-modem .. _nRF52840 Product Specification: https://infocenter.nordicsemi.com/pdf/nRF52840_PS_v1.1.pdf .. _Sierra Wireless HL7800: https://source.sierrawireless.com/devices/hl-series/hl7800/#sthash.641qTTwA.dpbs .. _J-Link Software and documentation pack: https://www.segger.com/jlink-software.html -.. _Pinnacle 100 OOB Demo: https://github.com/LairdCP/Pinnacle_100_oob_demo .. _Pinnacle 100 Sample Applications: https://github.com/LairdCP/Pinnacle_100_Sample_Applications +.. _Canvas Software Suite: https://www.ezurio.com/canvas/software-suite From b980e444f09cd87d039f09098c42658fe1656ae2 Mon Sep 17 00:00:00 2001 From: Ryan Erickson Date: Mon, 3 Jun 2024 11:02:17 -0500 Subject: [PATCH 1856/2849] codeowners: fix ezurio boards owner Update codeowner for all Ezurio boards. Signed-off-by: Ryan Erickson --- CODEOWNERS | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/CODEOWNERS b/CODEOWNERS index ab9b5bd47559b..a55c868247dd4 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -55,8 +55,6 @@ /boards/arm/acn52832/ @sven-hm /boards/arm/arduino_mkrzero/ @soburi /boards/arm/bbc_microbit_v2/ @LingaoM -/boards/arm/bl5340_dvk/ @lairdjm -/boards/arm/bl65*/ @lairdjm /boards/arm/blackpill_f401ce/ @coderkalyan /boards/arm/blackpill_f411ce/ @coderkalyan /boards/arm/bt*10/ @greg-leach @@ -77,7 +75,6 @@ /boards/arm/ip_k66f/ @parthitce @lmajewski /boards/arm/legend/ @mbittan @simonguinot /boards/arm/lpcxpresso*/ @mmahadevan108 @dleach02 -/boards/arm/mg100/ @rerickson1 /boards/arm/mimx8mm_evk/ @Mani-Sadhasivam /boards/arm/mimx8mm_phyboard_polis @pefech /boards/arm/mimxrt*/ @mmahadevan108 @dleach02 @@ -88,7 +85,6 @@ /boards/arm/nucleo*/ @erwango @ABOSTM @FRASTM /boards/arm/nucleo_f401re/ @idlethread /boards/arm/nuvoton_pfm_m487/ @ssekar15 -/boards/arm/pinnacle_100_dvk/ @rerickson1 /boards/arm/qemu_cortex_a9/ @ibirnbaum /boards/arm/qemu_cortex_r*/ @stephanosio /boards/arm/qemu_cortex_m*/ @ioannisg @stephanosio @@ -114,6 +110,7 @@ /boards/arm/ubx_bmd345eval_nrf52840/ @Navin-Sankar @brec-u-blox /boards/arm/nrf5340_audio_dk_nrf5340 @koffes @alexsven @erikrobstad @rick1082 @gWacey /boards/arm/stm32_min_dev/ @sidcha +/boards/ezurio/* @rerickson1 /boards/riscv/rv32m1_vega/ @dleach02 /boards/riscv/adp_xc7k_ae350/ @cwshu @kevinwang821020 @jimmyzhe /boards/riscv/longan_nano/ @soburi From b1cfc103447e6af894c69725b346f87362606642 Mon Sep 17 00:00:00 2001 From: Ryan Erickson Date: Mon, 3 Jun 2024 10:17:38 -0500 Subject: [PATCH 1857/2849] maintainers: update Laird Connectivity to Ezurio Laird Connectivity is now Ezurio. Signed-off-by: Ryan Erickson --- MAINTAINERS.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/MAINTAINERS.yml b/MAINTAINERS.yml index 44d2c990a0d3e..4ed3c15422f47 100644 --- a/MAINTAINERS.yml +++ b/MAINTAINERS.yml @@ -2325,16 +2325,16 @@ Memory Management: tests: - mem_mgmt -Laird Connectivity platforms: +Ezurio platforms: status: maintained maintainers: - rerickson1 collaborators: - greg-leach files: - - boards/lairdconnect/ + - boards/ezurio/ labels: - - "platform: Laird Connectivity" + - "platform: Ezurio" Linker Scripts: status: maintained From 0ea95390a5cd9da8a428627060065585b66ca411 Mon Sep 17 00:00:00 2001 From: Ryan Erickson Date: Mon, 3 Jun 2024 11:10:33 -0500 Subject: [PATCH 1858/2849] migration: 3.7: lairdconnect boards are now ezurio Laird Connectivity has rebranded to Ezurio. Signed-off-by: Ryan Erickson --- doc/releases/migration-guide-3.7.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/doc/releases/migration-guide-3.7.rst b/doc/releases/migration-guide-3.7.rst index ce86715258151..ffe45d629c5db 100644 --- a/doc/releases/migration-guide-3.7.rst +++ b/doc/releases/migration-guide-3.7.rst @@ -81,6 +81,8 @@ Boards * LiteX: Renamed the ``compatible`` of the LiteX VexRiscV interrupt controller node from ``vexriscv-intc0`` to :dtcompatible:`litex,vexriscv-intc0`. (:github:`73211`) +* `lairdconnect` boards are now `ezurio` boards. Laird Connectivity has rebranded to `Ezurio `_. + Modules ******* From 584a99f6ab281dc30217220d578202a0bf83ec03 Mon Sep 17 00:00:00 2001 From: Anas Nashif Date: Mon, 3 Jun 2024 09:14:17 -0400 Subject: [PATCH 1859/2849] tracing: add missing calls for k_wakeup/k_thread_user_mode_enter Add missing hooks for k_wakeup/k_thread_user_mode_enter to CTF backend. Signed-off-by: Anas Nashif --- subsys/tracing/ctf/ctf_top.c | 19 +++++++++++++++++++ subsys/tracing/ctf/ctf_top.h | 17 ++++++++++++++++- subsys/tracing/ctf/tracing_ctf.h | 5 ++--- subsys/tracing/ctf/tsdl/metadata | 18 ++++++++++++++++++ 4 files changed, 55 insertions(+), 4 deletions(-) diff --git a/subsys/tracing/ctf/ctf_top.c b/subsys/tracing/ctf/ctf_top.c index 64708c075f427..09dcfc8109bb4 100644 --- a/subsys/tracing/ctf/ctf_top.c +++ b/subsys/tracing/ctf/ctf_top.c @@ -33,6 +33,25 @@ void sys_trace_k_thread_switched_out(void) ctf_top_thread_switched_out((uint32_t)(uintptr_t)thread, name); } +void sys_trace_k_thread_user_mode_enter(void) +{ + struct k_thread *thread; + ctf_bounded_string_t name = { "unknown" }; + + thread = k_sched_current_thread_query(); + _get_thread_name(thread, &name); + ctf_top_thread_user_mode_enter((uint32_t)(uintptr_t)thread, name); +} + +void sys_trace_k_thread_wakeup(struct k_thread *thread) +{ + ctf_bounded_string_t name = { "unknown" }; + + _get_thread_name(thread, &name); + ctf_top_thread_wakeup((uint32_t)(uintptr_t)thread, name); +} + + void sys_trace_k_thread_switched_in(void) { struct k_thread *thread; diff --git a/subsys/tracing/ctf/ctf_top.h b/subsys/tracing/ctf/ctf_top.h index 845711ceeed16..0b5104a8451a9 100644 --- a/subsys/tracing/ctf/ctf_top.h +++ b/subsys/tracing/ctf/ctf_top.h @@ -102,7 +102,9 @@ typedef enum { CTF_EVENT_TIMER_STOP = 0x30, CTF_EVENT_TIMER_STATUS_SYNC_ENTER = 0x31, CTF_EVENT_TIMER_STATUS_SYNC_BLOCKING = 0x32, - CTF_EVENT_TIMER_STATUS_SYNC_EXIT = 0x33 + CTF_EVENT_TIMER_STATUS_SYNC_EXIT = 0x33, + CTF_EVENT_THREAD_USER_MODE_ENTER = 0x34, + CTF_EVENT_THREAD_WAKEUP = 0x35, } ctf_event_t; @@ -188,6 +190,19 @@ static inline void ctf_top_thread_name_set(uint32_t thread_id, name); } + +static inline void ctf_top_thread_user_mode_enter(uint32_t thread_id, ctf_bounded_string_t name) +{ + CTF_EVENT(CTF_LITERAL(uint8_t, CTF_EVENT_THREAD_USER_MODE_ENTER), + thread_id, name); +} + +static inline void ctf_top_thread_wakeup(uint32_t thread_id, ctf_bounded_string_t name) +{ + CTF_EVENT(CTF_LITERAL(uint8_t, CTF_EVENT_THREAD_WAKEUP), + thread_id, name); +} + static inline void ctf_top_isr_enter(void) { CTF_EVENT(CTF_LITERAL(uint8_t, CTF_EVENT_ISR_ENTER)); diff --git a/subsys/tracing/ctf/tracing_ctf.h b/subsys/tracing/ctf/tracing_ctf.h index 2c95195f94d53..b49ed97c8cfa8 100644 --- a/subsys/tracing/ctf/tracing_ctf.h +++ b/subsys/tracing/ctf/tracing_ctf.h @@ -25,7 +25,7 @@ extern "C" { sys_trace_k_thread_create(new_thread, stack_size, prio) #define sys_port_trace_k_thread_user_mode_enter() \ - sys_trace_k_thread_user_mode_enter(entry, p1, p2, p3) + sys_trace_k_thread_user_mode_enter() #define sys_port_trace_k_thread_heap_assign(thread, heap) #define sys_port_trace_k_thread_join_enter(thread, timeout) @@ -372,8 +372,7 @@ void sys_trace_k_thread_foreach_unlocked_exit(k_thread_user_cb_t user_cb, void *user_data); void sys_trace_k_thread_create(struct k_thread *new_thread, size_t stack_size, int prio); -void sys_trace_k_thread_user_mode_enter(k_thread_entry_t entry, void *p1, - void *p2, void *p3); +void sys_trace_k_thread_user_mode_enter(void); void sys_trace_k_thread_heap_assign(struct k_thread *thread, struct k_heap *heap); void sys_trace_k_thread_join_blocking(struct k_thread *thread, diff --git a/subsys/tracing/ctf/tsdl/metadata b/subsys/tracing/ctf/tsdl/metadata index 1b44f6a5e4f1d..02eddb641ace4 100644 --- a/subsys/tracing/ctf/tsdl/metadata +++ b/subsys/tracing/ctf/tsdl/metadata @@ -310,3 +310,21 @@ event { uint32_t result; }; }; + +event { + name = user_mode_enter; + id = 0x34; + fields := struct { + uint32_t thread_id; + ctf_bounded_string_t name[20]; + }; +}; + +event { + name = thread_wakeup; + id = 0x35; + fields := struct { + uint32_t thread_id; + ctf_bounded_string_t name[20]; + }; +}; From 4dc2a98d0c018ee58d4b88235a6a9fc64e637bfe Mon Sep 17 00:00:00 2001 From: Dmitrii Golovanov Date: Mon, 3 Jun 2024 19:06:43 +0200 Subject: [PATCH 1860/2849] twister: Ensure serial-pty process termination Make sure Twster DeviceHandler serial-pty process is terminated with all its remaining children to avoid Twister hanging on it infinitely. The reolved issue occurs sometimes, for example when serial-pty script is used for serial port tunneling over network. Signed-off-by: Dmitrii Golovanov --- scripts/pylib/twister/twisterlib/handlers.py | 18 ++++++++++++------ scripts/tests/twister/test_handlers.py | 7 +++++-- 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/scripts/pylib/twister/twisterlib/handlers.py b/scripts/pylib/twister/twisterlib/handlers.py index 4a9ed97ea2dbd..1ecaa27b038e8 100755 --- a/scripts/pylib/twister/twisterlib/handlers.py +++ b/scripts/pylib/twister/twisterlib/handlers.py @@ -569,6 +569,16 @@ def _update_instance_info(self, harness_state, handler_time, flash_error): if self.instance.status in ["error", "failed"]: self.instance.add_missing_case_status("blocked", self.instance.reason) + def _terminate_pty(self, ser_pty, ser_pty_process): + logger.debug(f"Terminating serial-pty:'{ser_pty}'") + terminate_process(ser_pty_process) + try: + (stdout, stderr) = ser_pty_process.communicate(timeout=self.get_test_timeout()) + logger.debug(f"Terminated serial-pty:'{ser_pty}', stdout:'{stdout}', stderr:'{stderr}'") + except subprocess.TimeoutExpired: + logger.debug(f"Terminated serial-pty:'{ser_pty}'") + # + def _create_serial_connection(self, serial_device, hardware_baud, flash_timeout, serial_pty, ser_pty_process): try: @@ -588,9 +598,7 @@ def _create_serial_connection(self, serial_device, hardware_baud, self.instance.add_missing_case_status("blocked", "Serial Device Error") if serial_pty and ser_pty_process: - ser_pty_process.terminate() - outs, errs = ser_pty_process.communicate() - logger.debug("Process {} terminated outs: {} errs {}".format(serial_pty, outs, errs)) + self._terminate_pty(serial_pty, ser_pty_process) if serial_pty: self.make_device_available(serial_pty) @@ -754,9 +762,7 @@ def handle(self, harness): ser.close() if serial_pty: - ser_pty_process.terminate() - outs, errs = ser_pty_process.communicate() - logger.debug("Process {} terminated outs: {} errs {}".format(serial_pty, outs, errs)) + self._terminate_pty(serial_pty, ser_pty_process) handler_time = time.time() - start_time diff --git a/scripts/tests/twister/test_handlers.py b/scripts/tests/twister/test_handlers.py index 2aa6aa92fcb11..a309e35db4f04 100644 --- a/scripts/tests/twister/test_handlers.py +++ b/scripts/tests/twister/test_handlers.py @@ -1169,6 +1169,7 @@ def mock_serial(*args, **kwargs): available_mock = mock.Mock() handler.make_device_available = available_mock handler.options = mock.Mock(timeout_multiplier=1) + twisterlib.handlers.terminate_process = mock.Mock() hardware_baud = 14400 flash_timeout = 60 @@ -1191,7 +1192,7 @@ def mock_serial(*args, **kwargs): missing_mock.assert_called_once_with('blocked', 'Serial Device Error') if terminate_ser_pty_process: - ser_pty_process.terminate.assert_called_once() + twisterlib.handlers.terminate_process.assert_called_once() ser_pty_process.communicate.assert_called_once() if make_available: @@ -1252,7 +1253,8 @@ def mock_popen(command, *args, **kwargs): (True, False, False, False, 0, True, False, None, None, ['Timed out while monitoring serial output on IPName']), (True, False, False, False, 0, False, True, - None, None, ['Process Serial PTY terminated outs: errs ']), + None, None, ["Terminating serial-pty:'Serial PTY'", + "Terminated serial-pty:'Serial PTY', stdout:'', stderr:''"]), ] @pytest.mark.parametrize( @@ -1351,6 +1353,7 @@ def mock_popen(command, *args, **kwargs): handler._update_instance_info = mock.Mock() handler._final_handle_actions = mock.Mock() handler.make_device_available = mock.Mock() + twisterlib.handlers.terminate_process = mock.Mock() handler.instance.platform.name = 'IPName' harness = mock.Mock() From 753f8ff0c76e0635ae5524689757cd89fc321b29 Mon Sep 17 00:00:00 2001 From: Tom Burdick Date: Tue, 4 Jun 2024 12:25:07 -0500 Subject: [PATCH 1861/2849] docs: Move sensor.rst to sensor/index.rst Looking to expand the sensor docs and break out significant sections. First though to move this to a directory to allow for multiple sensor related rst docs. Signed-off-by: Tom Burdick --- MAINTAINERS.yml | 2 +- doc/_scripts/redirects.py | 1 + doc/hardware/peripherals/index.rst | 2 +- doc/hardware/peripherals/{sensor.rst => sensor/index.rst} | 4 ++-- 4 files changed, 5 insertions(+), 4 deletions(-) rename doc/hardware/peripherals/{sensor.rst => sensor/index.rst} (98%) diff --git a/MAINTAINERS.yml b/MAINTAINERS.yml index 4ed3c15422f47..f4af2300684a4 100644 --- a/MAINTAINERS.yml +++ b/MAINTAINERS.yml @@ -1843,7 +1843,7 @@ Release Notes: - dts/bindings/sensor/ - include/zephyr/drivers/sensor/ - include/zephyr/dt-bindings/sensor/ - - doc/hardware/peripherals/sensor.rst + - doc/hardware/peripherals/sensor/ - tests/drivers/build_all/sensor/ labels: - "area: Sensors" diff --git a/doc/_scripts/redirects.py b/doc/_scripts/redirects.py index aa4bd4fdebfa0..8b2d5e65626d2 100644 --- a/doc/_scripts/redirects.py +++ b/doc/_scripts/redirects.py @@ -143,6 +143,7 @@ ('guides/west/workspaces', 'develop/west/workspaces'), ('guides/west/zephyr-cmds', 'develop/west/zephyr-cmds'), ('guides/zephyr_cmake_package', 'build/zephyr_cmake_package'), + ('hardware/peripherals/sensor', 'hardware/peripherals/sensor/index'), ('reference/api/api_lifecycle', 'develop/api/api_lifecycle'), ('reference/api/index', 'develop/api/index'), ('reference/api/overview', 'develop/api/overview'), diff --git a/doc/hardware/peripherals/index.rst b/doc/hardware/peripherals/index.rst index cd75fee037105..9889ca9ac2cb4 100644 --- a/doc/hardware/peripherals/index.rst +++ b/doc/hardware/peripherals/index.rst @@ -51,7 +51,7 @@ Peripherals reset.rst retained_mem.rst sdhc.rst - sensor.rst + sensor/index.rst spi.rst smbus.rst uart.rst diff --git a/doc/hardware/peripherals/sensor.rst b/doc/hardware/peripherals/sensor/index.rst similarity index 98% rename from doc/hardware/peripherals/sensor.rst rename to doc/hardware/peripherals/sensor/index.rst index 5c7817b627bbb..ec3cf2028faa9 100644 --- a/doc/hardware/peripherals/sensor.rst +++ b/doc/hardware/peripherals/sensor/index.rst @@ -57,7 +57,7 @@ measures ambient temperature and atmospheric pressure. Note that :c:func:`sensor_sample_fetch` is only called once, as it reads and compensates data for both channels. -.. literalinclude:: ../../../samples/sensor/bme280/src/main.c +.. literalinclude:: ../../../../samples/sensor/bme280/src/main.c :language: c :lines: 12- :linenos: @@ -217,7 +217,7 @@ interest of saving power. Since the application has direct access to the kernel config symbols, no trigger is registered when triggering was disabled by the driver's configuration. -.. literalinclude:: ../../../samples/sensor/mcp9808/src/main.c +.. literalinclude:: ../../../../samples/sensor/mcp9808/src/main.c :language: c :lines: 12- :linenos: From 10457879d351a3b2de629377b0008d9af2280e3e Mon Sep 17 00:00:00 2001 From: Aaron Ye Date: Wed, 5 Jun 2024 11:02:01 +0800 Subject: [PATCH 1862/2849] doc: release-notes-3.7: Update release notes for Ambiq changes Added the SoC, board and drivers changes for Ambiq platform. Signed-off-by: Aaron Ye --- doc/releases/release-notes-3.7.rst | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/doc/releases/release-notes-3.7.rst b/doc/releases/release-notes-3.7.rst index dda728bad3750..5bec18d4e20d4 100644 --- a/doc/releases/release-notes-3.7.rst +++ b/doc/releases/release-notes-3.7.rst @@ -187,17 +187,25 @@ Bluetooth or speakers. The audio data is compressed in a proper format for efficient use of the limited bandwidth. +* HCI Driver + + * Added support for Ambiq Apollo3 Blue series. + Boards & SoC Support ******************** * Added support for these SoC series: + * Added support for Ambiq Apollo3 Blue and Apollo3 Blue Plus SoC series. + * Made these changes in other SoC series: * ITE: Rename the Kconfig symbol for all ITE SoC variants. * Added support for these ARM boards: + * Added support for Ambiq Apollo3 boards: ``apollo3_evb``, ``apollo3p_evb``. + * Added support for these Xtensa boards: * Made these changes for ARM boards: @@ -279,6 +287,8 @@ Drivers and Sensors * Counter + * Added support for Ambiq Apollo3 series. + * Crypto * Display @@ -301,12 +311,18 @@ Drivers and Sensors * Flash + * Added support for Ambiq Apollo3 series. + * GNSS * GPIO + * Added support for Ambiq Apollo3 series. + * I2C + * Added support for Ambiq Apollo3 series. + * I2S * I3C @@ -369,6 +385,9 @@ Drivers and Sensors * SPI + * Added support for Ambiq Apollo3 series general IOM based SPI. + * Added support for Ambiq Apollo3 BLEIF based SPI, which is specific for internal HCI. + * USB * W1 @@ -377,6 +396,7 @@ Drivers and Sensors * 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`. + * Added support for Ambiq Apollo3 series. * Wi-Fi From 17acb4defe203aa504205b2c70b13154fffb7346 Mon Sep 17 00:00:00 2001 From: Pieter De Gendt Date: Wed, 5 Jun 2024 08:53:24 +0200 Subject: [PATCH 1863/2849] MAINTAINERS: add pdgendt as ethernet collaborator Propose to help out for ethernet driver subsystem. Signed-off-by: Pieter De Gendt --- MAINTAINERS.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/MAINTAINERS.yml b/MAINTAINERS.yml index f4af2300684a4..4f2c3a7f9fd9c 100644 --- a/MAINTAINERS.yml +++ b/MAINTAINERS.yml @@ -1250,6 +1250,7 @@ Release Notes: collaborators: - decsny - lmajewski + - pdgendt files: - drivers/ethernet/ - include/zephyr/dt-bindings/ethernet/ From 21d4d49925fd01494f4317ad2a9b59bf7e578dbd Mon Sep 17 00:00:00 2001 From: Seppo Takalo Date: Wed, 5 Jun 2024 15:51:49 +0300 Subject: [PATCH 1864/2849] test: lwm2m: Increase FDS for native_sim After last refactoring of POSIX Kconfig options default is again dropped below what we need. Signed-off-by: Seppo Takalo --- tests/net/lib/lwm2m/interop/boards/native_sim.conf | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/net/lib/lwm2m/interop/boards/native_sim.conf b/tests/net/lib/lwm2m/interop/boards/native_sim.conf index 99b234c8e6627..1d22c6b673f22 100644 --- a/tests/net/lib/lwm2m/interop/boards/native_sim.conf +++ b/tests/net/lib/lwm2m/interop/boards/native_sim.conf @@ -7,3 +7,4 @@ CONFIG_NATIVE_SIM_SLOWDOWN_TO_REAL_TIME=y CONFIG_NATIVE_UART_0_ON_STDINOUT=y CONFIG_ASAN=y CONFIG_NATIVE_EXTRA_CMDLINE_ARGS="--seed-random" +CONFIG_ZVFS_OPEN_MAX=16 From ec9f71e23794291f0d0a6546f3018e4ab0d23cd8 Mon Sep 17 00:00:00 2001 From: frei tycho Date: Wed, 5 Jun 2024 12:55:40 +0000 Subject: [PATCH 1865/2849] kernel: avoid Boolean-to-integer type casts Avoid casting expression to an inappropriate essential type. Signed-off-by: frei tycho --- include/zephyr/kernel.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/zephyr/kernel.h b/include/zephyr/kernel.h index a6cf1ca352db3..d61ae39ce86a1 100644 --- a/include/zephyr/kernel.h +++ b/include/zephyr/kernel.h @@ -2089,7 +2089,7 @@ __syscall int k_queue_is_empty(struct k_queue *queue); static inline int z_impl_k_queue_is_empty(struct k_queue *queue) { - return (int)sys_sflist_is_empty(&queue->data_q); + return sys_sflist_is_empty(&queue->data_q) ? 1 : 0; } /** From c250c330c6bf69cb3cfbd78b2c0290d2651742e0 Mon Sep 17 00:00:00 2001 From: Fabio Baltieri Date: Wed, 5 Jun 2024 19:26:18 +0100 Subject: [PATCH 1866/2849] posix: re-introduce PTHREAD_RWLOCK_INITIALIZER Rename the POSIX_RWLOCK_INITIALIZER back to PTHREAD_RWLOCK_INITIALIZER. This was changed in 70e2b02c8e1, but PTHREAD_RWLOCK_INITIALIZER is the standard name used by external libraries. Change it back to restore compatibility. Signed-off-by: Fabio Baltieri --- include/zephyr/posix/pthread.h | 2 +- lib/posix/options/rwlock.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/include/zephyr/posix/pthread.h b/include/zephyr/posix/pthread.h index 33288d7d75502..f2723d68d76a6 100644 --- a/include/zephyr/posix/pthread.h +++ b/include/zephyr/posix/pthread.h @@ -153,7 +153,7 @@ int pthread_condattr_setclock(pthread_condattr_t *att, clockid_t clock_id); * * Initialize a rwlock with the default rwlock attributes. */ -#define POSIX_RWLOCK_INITIALIZER (-1) +#define PTHREAD_RWLOCK_INITIALIZER (-1) /* * Mutex attributes - type diff --git a/lib/posix/options/rwlock.c b/lib/posix/options/rwlock.c index ef14867b028de..f282fc26549fe 100644 --- a/lib/posix/options/rwlock.c +++ b/lib/posix/options/rwlock.c @@ -86,7 +86,7 @@ struct posix_rwlock *to_posix_rwlock(pthread_rwlock_t *rwlock) size_t bit; struct posix_rwlock *rwl; - if (*rwlock != POSIX_RWLOCK_INITIALIZER) { + if (*rwlock != PTHREAD_RWLOCK_INITIALIZER) { return get_posix_rwlock(*rwlock); } @@ -116,7 +116,7 @@ int pthread_rwlock_init(pthread_rwlock_t *rwlock, struct posix_rwlock *rwl; ARG_UNUSED(attr); - *rwlock = POSIX_RWLOCK_INITIALIZER; + *rwlock = PTHREAD_RWLOCK_INITIALIZER; rwl = to_posix_rwlock(rwlock); if (rwl == NULL) { From 6906c2f878649f05c2ad5314049f296dfc81966e Mon Sep 17 00:00:00 2001 From: Daniel DeGrasse Date: Fri, 31 May 2024 09:34:36 -0500 Subject: [PATCH 1867/2849] dts: bindings: gpio: add bindings for NXP display interfaces Add bindings for nxp display interfaces. These bindings describe the 6 and 40 pin FPC connectors used for displays on several NXP EVKs using gpio nexus nodes. Signed-off-by: Daniel DeGrasse --- dts/bindings/gpio/nxp,i2c-tsc-fpc.yaml | 20 +++++++++++ .../gpio/nxp,parallel-lcd-connector.yaml | 33 +++++++++++++++++++ 2 files changed, 53 insertions(+) create mode 100644 dts/bindings/gpio/nxp,i2c-tsc-fpc.yaml create mode 100644 dts/bindings/gpio/nxp,parallel-lcd-connector.yaml diff --git a/dts/bindings/gpio/nxp,i2c-tsc-fpc.yaml b/dts/bindings/gpio/nxp,i2c-tsc-fpc.yaml new file mode 100644 index 0000000000000..077f6701961a0 --- /dev/null +++ b/dts/bindings/gpio/nxp,i2c-tsc-fpc.yaml @@ -0,0 +1,20 @@ +# Copyright 2024 NXP +# SPDX-License-Identifier: Apache-2.0 + + +compatible: "nxp,i2c-tsc-fpc" + +description: | + GPIO pins exposed on NXP LCD touch controller interface. These pins are + exposed on a 6 pin flexible printed cable connector. The pins have the + following assignments: + + Pin Number Usage + 1 VDD + 2 LCD touch reset + 3 LCD touch interrupt + 4 LCD touch controller I2C SCL + 5 LCD touch controller I2C SDA + 6 GND + +include: [gpio-nexus.yaml, base.yaml] diff --git a/dts/bindings/gpio/nxp,parallel-lcd-connector.yaml b/dts/bindings/gpio/nxp,parallel-lcd-connector.yaml new file mode 100644 index 0000000000000..c1d8e8657e2ff --- /dev/null +++ b/dts/bindings/gpio/nxp,parallel-lcd-connector.yaml @@ -0,0 +1,33 @@ +# Copyright 2024 NXP +# SPDX-License-Identifier: Apache-2.0 + + +compatible: "nxp,parallel-lcd-connector" + +description: | + GPIO pins exposed on NXP LCD interface. These pins are + exposed on a 40 pin flexible printed cable connector. The pins have the + following assignments: + + FPC Pin Function + 1 LED backlight cathode + 2 LED backlight anode + 3 GND + 4 VDD (3v3) + 5-7 GND + 8-12 LCD D11-D15 + 13-14 GND + 15-20 LCD D5-D10 + 21-23 GND + 24-28 LCD D0-D4 + 29 GND + 30 LCD CLK + 31 LCD DISP + 32 LCD HSYNC + 33 LCD VSYNC + 34 LCD DE + 35 NC + 36 GND + 37-40 NC + +include: [gpio-nexus.yaml, base.yaml] From 98c82cea8fcca007b1bbbdce6710def6be70d5de Mon Sep 17 00:00:00 2001 From: Daniel DeGrasse Date: Tue, 30 Apr 2024 19:53:52 +0000 Subject: [PATCH 1868/2849] boards: nxp: mimxrt1060_evk: define parallel and i2c FPC interfaces Define parallel and i2c FPC display interfaces for the RT1060 EVK. These interfaces are used by multiple displays for the EVK. Signed-off-by: Daniel DeGrasse --- boards/nxp/mimxrt1060_evk/mimxrt1060_evk.dts | 31 +++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/boards/nxp/mimxrt1060_evk/mimxrt1060_evk.dts b/boards/nxp/mimxrt1060_evk/mimxrt1060_evk.dts index 08eb8541432c4..ac33358ff4f24 100644 --- a/boards/nxp/mimxrt1060_evk/mimxrt1060_evk.dts +++ b/boards/nxp/mimxrt1060_evk/mimxrt1060_evk.dts @@ -39,6 +39,33 @@ reg = <0x80000000 DT_SIZE_M(32)>; }; + /* + * This node describes the GPIO pins of the parallel FPC interface, + * This interface is standard to several NXP EVKs, and is used with + * several parallel LCD displays (available as zephyr shields) + */ + nxp_parallel_lcd_connector: parallel-connector { + compatible = "nxp,parallel-lcd-connector"; + #gpio-cells = <2>; + gpio-map-mask = <0xffffffff 0xffffffc0>; + gpio-map-pass-thru = <0 0x3f>; + gpio-map = <0 0 &gpio2 31 0>; /* Pin 1, BL+ */ + }; + + /* + * This node describes the GPIO pins of the I2C display FPC interface, + * This interface is standard to several NXP EVKs, and is used with + * several parallel LCD displays (available as zephyr shields) + */ + nxp_i2c_touch_fpc: i2c-touch-connector { + compatible = "nxp,i2c-tsc-fpc"; + #gpio-cells = <2>; + gpio-map-mask = <0xffffffff 0xffffffc0>; + gpio-map-pass-thru = <0 0x3f>; + gpio-map = <1 0 &gpio1 2 0>, /* Pin 2, LCD touch RST */ + <2 0 &gpio1 11 0>; /* Pin 3, LCD touch INT */ + }; + leds { compatible = "gpio-leds"; green_led: led-1 { @@ -114,7 +141,7 @@ arduino_serial: &lpuart3 { pinctrl-names = "default", "flowcontrol", "sleep"; }; -&lcdif { +zephyr_lcdif: &lcdif { status = "okay"; width = <480>; height = <272>; @@ -144,6 +171,8 @@ arduino_serial: &lpuart3 { }; }; +nxp_touch_i2c: &lpi2c1 {}; + arduino_i2c: &lpi2c1 { status = "okay"; pinctrl-0 = <&pinmux_lpi2c1>; From a98faf2567438e22512e4404d439b1b750f4e0f1 Mon Sep 17 00:00:00 2001 From: Daniel DeGrasse Date: Tue, 30 Apr 2024 19:55:09 +0000 Subject: [PATCH 1869/2849] boards: shields: rk043fn02h_ct: add shield for rk043fn02h_ct Add a shield for the RK043FN02H-CT panel, a Rocktech display panel with an FT5336 touch controller. This panel uses a 40+6 FPC interface for parallel displays, which is supported by many NXP iMX RT EVKs. Signed-off-by: Daniel DeGrasse --- .../shields/rk043fn02h_ct/Kconfig.defconfig | 47 ++++++++ boards/shields/rk043fn02h_ct/Kconfig.shield | 5 + boards/shields/rk043fn02h_ct/doc/index.rst | 105 ++++++++++++++++++ .../rk043fn02h_ct/rk043fn02h_ct.overlay | 50 +++++++++ 4 files changed, 207 insertions(+) create mode 100644 boards/shields/rk043fn02h_ct/Kconfig.defconfig create mode 100644 boards/shields/rk043fn02h_ct/Kconfig.shield create mode 100644 boards/shields/rk043fn02h_ct/doc/index.rst create mode 100644 boards/shields/rk043fn02h_ct/rk043fn02h_ct.overlay diff --git a/boards/shields/rk043fn02h_ct/Kconfig.defconfig b/boards/shields/rk043fn02h_ct/Kconfig.defconfig new file mode 100644 index 0000000000000..f2b199d916968 --- /dev/null +++ b/boards/shields/rk043fn02h_ct/Kconfig.defconfig @@ -0,0 +1,47 @@ +# Copyright 2024 NXP +# SPDX-License-Identifier: Apache-2.0 + +if SHIELD_RK043FN02H_CT + +if LVGL + +config INPUT + default y + +config INPUT_FT5336_INTERRUPT + default y + +# LVGL should allocate buffers equal to size of display +config LV_Z_VDB_SIZE + 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_Z_BITS_PER_PIXEL + default 16 + +config LV_DPI_DEF + default 128 + +# Use offloaded render thread +config LV_Z_FLUSH_THREAD + default y + +choice LV_COLOR_DEPTH + default LV_COLOR_DEPTH_16 +endchoice + +# Force display buffers to be aligned to cache line size (32 bytes) +config LV_Z_VDB_ALIGN + default 32 + +endif # LVGL + +endif # SHIELD_RK043FN02H_CT diff --git a/boards/shields/rk043fn02h_ct/Kconfig.shield b/boards/shields/rk043fn02h_ct/Kconfig.shield new file mode 100644 index 0000000000000..4cf0c812ae89e --- /dev/null +++ b/boards/shields/rk043fn02h_ct/Kconfig.shield @@ -0,0 +1,5 @@ +# Copyright 2024 NXP +# SPDX-License-Identifier: Apache-2.0 + +config SHIELD_RK043FN02H_CT + def_bool $(shields_list_contains,rk043fn02h_ct) diff --git a/boards/shields/rk043fn02h_ct/doc/index.rst b/boards/shields/rk043fn02h_ct/doc/index.rst new file mode 100644 index 0000000000000..8fe083d61c5e5 --- /dev/null +++ b/boards/shields/rk043fn02h_ct/doc/index.rst @@ -0,0 +1,105 @@ +.. _rk043fn02h_ct: + +RK043FN02H-CT Parallel Display +############################## + +Overview +******** + +RK043FN02H-CT is a 4.3 inch TFT 480*272 pixels with LED backlight and +capacitive touch panel from Rocktech. This LCD panel can work with several i.MX +RT EVKs and LPC MCUs for evaluation of applications with display. + +More information about the shield can be found at the `RK043FN02H-CT product +page`_. + +This display uses a 40 pin parallel FPC interface plus 6 pin I2C interface, +available on many NXP EVKs. Note that this parallel FPC interface is not +compatible with the MIPI FPC interface present on other NXP EVKs. + +Pins Assignment of the Rocktech RK043FN02H-CT Parallel Display +============================================================== + ++-----------------------+------------------------+ +| Parallel FPC Pin | Function | ++=======================+========================+ +| 1 | LED backlight cathode | ++-----------------------+------------------------+ +| 2 | LED backlight anode | ++-----------------------+------------------------+ +| 3 | GND | ++-----------------------+------------------------+ +| 4 | VDD (3v3) | ++-----------------------+------------------------+ +| 5-7 | GND | ++-----------------------+------------------------+ +| 8-12 | LCD D11-D15 | ++-----------------------+------------------------+ +| 13-14 | GND | ++-----------------------+------------------------+ +| 15-20 | LCD D5-D10 | ++-----------------------+------------------------+ +| 21-23 | GND | ++-----------------------+------------------------+ +| 24-28 | LCD D0-D4 | ++-----------------------+------------------------+ +| 29 | GND | ++-----------------------+------------------------+ +| 30 | LCD CLK | ++-----------------------+------------------------+ +| 31 | LCD DISP | ++-----------------------+------------------------+ +| 32 | LCD HSYNC | ++-----------------------+------------------------+ +| 33 | LCD VSYNC | ++-----------------------+------------------------+ +| 34 | LCD DE | ++-----------------------+------------------------+ +| 35 | NC | ++-----------------------+------------------------+ +| 36 | GND | ++-----------------------+------------------------+ +| 37-40 | NC | ++-----------------------+------------------------+ + ++-----------------------+------------------------+ +| I2C Connector Pin | Function | ++=======================+========================+ +| 1 | VDD (3v3) | ++-----------------------+------------------------+ +| 2 | LCD Touch Reset | ++-----------------------+------------------------+ +| 3 | LCD Touch Interrupt | ++-----------------------+------------------------+ +| 4 | LCD I2C SCL | ++-----------------------+------------------------+ +| 5 | LCD I2C SDA | ++-----------------------+------------------------+ +| 6 | GND | ++-----------------------+------------------------+ + +Requirements +************ + +This shield can only be used with a board which provides a configuration +for the 40+6 pin parallel/I2C FPC interface + +Programming +*********** + +Set ``-DSHIELD=rk043fn02h_ct`` when you invoke ``west build``. For +example: + +.. zephyr-app-commands:: + :zephyr-app: samples/drivers/display + :board: mimxrt1060_evk + :shield: rk043fn02h_ct + :goals: build + +References +********** + +.. target-notes:: + +.. _RK043FN02H-CT product page: + https://www.nxp.com/design/design-center/development-boards-and-designs/i-mx-evaluation-and-development-boards/4-3-lcd-panel:RK043FN02H-CT diff --git a/boards/shields/rk043fn02h_ct/rk043fn02h_ct.overlay b/boards/shields/rk043fn02h_ct/rk043fn02h_ct.overlay new file mode 100644 index 0000000000000..ab0b10d70af2a --- /dev/null +++ b/boards/shields/rk043fn02h_ct/rk043fn02h_ct.overlay @@ -0,0 +1,50 @@ +/* + * Copyright 2024, NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +/{ + chosen { + zephyr,display = &zephyr_lcdif; + }; + + lvgl_pointer { + compatible = "zephyr,lvgl-pointer-input"; + input = <&ft5336_rk043fn02h_ct>; + }; +}; + +&nxp_touch_i2c { + status = "okay"; + ft5336_rk043fn02h_ct: ft5336@38 { + compatible = "focaltech,ft5336"; + reg = <0x38>; + int-gpios = <&nxp_i2c_touch_fpc 2 GPIO_ACTIVE_LOW>; + }; +}; + +&zephyr_lcdif { + status = "okay"; + width = <480>; + height = <272>; + display-timings { + compatible = "zephyr,panel-timing"; + hsync-len = <41>; + hfront-porch = <4>; + hback-porch = <8>; + vsync-len = <10>; + vfront-porch = <4>; + vback-porch = <2>; + de-active= <1>; + pixelclk-active = <1>; + hsync-active = <0>; + vsync-active = <0>; + clock-frequency = <9210240>; + }; + pixel-format = ; + data-bus-width = "16-bit"; + backlight-gpios = <&nxp_parallel_lcd_connector 0 GPIO_ACTIVE_HIGH>; +}; From 7d441d5c81788ea196a4913700fb99d0fdaf045a Mon Sep 17 00:00:00 2001 From: Daniel DeGrasse Date: Tue, 30 Apr 2024 19:56:37 +0000 Subject: [PATCH 1870/2849] boards: shields: rk043fn66hs_ctg: add shield for rk043fn66hs_ctg Add a shield for the RK043FN66HS-CTG panel, a Rocktech display panel with an GT911 touch controller. This panel uses a 40+6 FPC interface for parallel displays, which is supported by many NXP iMX RT EVKs. Signed-off-by: Daniel DeGrasse --- .../shields/rk043fn66hs_ctg/Kconfig.defconfig | 47 ++++++++ boards/shields/rk043fn66hs_ctg/Kconfig.shield | 5 + boards/shields/rk043fn66hs_ctg/doc/index.rst | 105 ++++++++++++++++++ .../rk043fn66hs_ctg/rk043fn66hs_ctg.overlay | 51 +++++++++ 4 files changed, 208 insertions(+) create mode 100644 boards/shields/rk043fn66hs_ctg/Kconfig.defconfig create mode 100644 boards/shields/rk043fn66hs_ctg/Kconfig.shield create mode 100644 boards/shields/rk043fn66hs_ctg/doc/index.rst create mode 100644 boards/shields/rk043fn66hs_ctg/rk043fn66hs_ctg.overlay diff --git a/boards/shields/rk043fn66hs_ctg/Kconfig.defconfig b/boards/shields/rk043fn66hs_ctg/Kconfig.defconfig new file mode 100644 index 0000000000000..58e4b93b08860 --- /dev/null +++ b/boards/shields/rk043fn66hs_ctg/Kconfig.defconfig @@ -0,0 +1,47 @@ +# Copyright 2024 NXP +# SPDX-License-Identifier: Apache-2.0 + +if SHIELD_RK043FN66HS_CTG + +if LVGL + +config INPUT + default y + +config INPUT_GT911_INTERRUPT + default y + +# LVGL should allocate buffers equal to size of display +config LV_Z_VDB_SIZE + 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_Z_BITS_PER_PIXEL + default 16 + +config LV_DPI_DEF + default 128 + +# Use offloaded render thread +config LV_Z_FLUSH_THREAD + default y + +choice LV_COLOR_DEPTH + default LV_COLOR_DEPTH_16 +endchoice + +# Force display buffers to be aligned to cache line size (32 bytes) +config LV_Z_VDB_ALIGN + default 32 + +endif # LVGL + +endif # SHIELD_RK043FN66HS_CTG diff --git a/boards/shields/rk043fn66hs_ctg/Kconfig.shield b/boards/shields/rk043fn66hs_ctg/Kconfig.shield new file mode 100644 index 0000000000000..02a15503e4c7d --- /dev/null +++ b/boards/shields/rk043fn66hs_ctg/Kconfig.shield @@ -0,0 +1,5 @@ +# Copyright 2024 NXP +# SPDX-License-Identifier: Apache-2.0 + +config SHIELD_RK043FN66HS_CTG + def_bool $(shields_list_contains,rk043fn66hs_ctg) diff --git a/boards/shields/rk043fn66hs_ctg/doc/index.rst b/boards/shields/rk043fn66hs_ctg/doc/index.rst new file mode 100644 index 0000000000000..29d031e8305e3 --- /dev/null +++ b/boards/shields/rk043fn66hs_ctg/doc/index.rst @@ -0,0 +1,105 @@ +.. _rk043fn66hs_ctg: + +RK043FN66HS-CTG Parallel Display +################################ + +Overview +******** + +RK043FN66HS-CTG is a 4.3 inch TFT 480*272 pixels with LED backlight and +capacitive touch panel from Rocktech. This LCD panel can work with several i.MX +RT EVKs and LPC MCUs for evaluation of applications with display. + +More information about the shield can be found at the `RK043FN66HS-CTG product +page`_. + +This display uses a 40 pin parallel FPC interface plus 6 pin I2C interface, +available on many NXP EVKs. Note that this parallel FPC interface is not +compatible with the MIPI FPC interface present on other NXP EVKs. + +Pins Assignment of the Rocktech RK043FN66HS-CTG Parallel Display +================================================================ + ++-----------------------+------------------------+ +| Parallel FPC Pin | Function | ++=======================+========================+ +| 1 | LED backlight cathode | ++-----------------------+------------------------+ +| 2 | LED backlight anode | ++-----------------------+------------------------+ +| 3 | GND | ++-----------------------+------------------------+ +| 4 | VDD (3v3) | ++-----------------------+------------------------+ +| 5-7 | GND | ++-----------------------+------------------------+ +| 8-12 | LCD D11-D15 | ++-----------------------+------------------------+ +| 13-14 | GND | ++-----------------------+------------------------+ +| 15-20 | LCD D5-D10 | ++-----------------------+------------------------+ +| 21-23 | GND | ++-----------------------+------------------------+ +| 24-28 | LCD D0-D4 | ++-----------------------+------------------------+ +| 29 | GND | ++-----------------------+------------------------+ +| 30 | LCD CLK | ++-----------------------+------------------------+ +| 31 | LCD DISP | ++-----------------------+------------------------+ +| 32 | LCD HSYNC | ++-----------------------+------------------------+ +| 33 | LCD VSYNC | ++-----------------------+------------------------+ +| 34 | LCD DE | ++-----------------------+------------------------+ +| 35 | NC | ++-----------------------+------------------------+ +| 36 | GND | ++-----------------------+------------------------+ +| 37-40 | NC | ++-----------------------+------------------------+ + ++-----------------------+------------------------+ +| I2C Connector Pin | Function | ++=======================+========================+ +| 1 | VDD (3v3) | ++-----------------------+------------------------+ +| 2 | LCD Touch Reset | ++-----------------------+------------------------+ +| 3 | LCD Touch Interrupt | ++-----------------------+------------------------+ +| 4 | LCD I2C SCL | ++-----------------------+------------------------+ +| 5 | LCD I2C SDA | ++-----------------------+------------------------+ +| 6 | GND | ++-----------------------+------------------------+ + +Requirements +************ + +This shield can only be used with a board which provides a configuration +for the 40+6 pin parallel/I2C FPC interface + +Programming +*********** + +Set ``-DSHIELD=rk043fn66hs_ctg`` when you invoke ``west build``. For +example: + +.. zephyr-app-commands:: + :zephyr-app: samples/drivers/display + :board: mimxrt1060_evk + :shield: rk043fn66hs_ctg + :goals: build + +References +********** + +.. target-notes:: + +.. _RK043FN66HS-CTG product page: + https://www.nxp.com/design/design-center/development-boards-and-designs/i-mx-evaluation-and-development-boards/4-3-lcd-panel:RK043FN66HS-CTG diff --git a/boards/shields/rk043fn66hs_ctg/rk043fn66hs_ctg.overlay b/boards/shields/rk043fn66hs_ctg/rk043fn66hs_ctg.overlay new file mode 100644 index 0000000000000..b992ec932b819 --- /dev/null +++ b/boards/shields/rk043fn66hs_ctg/rk043fn66hs_ctg.overlay @@ -0,0 +1,51 @@ +/* + * Copyright 2024, NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +/{ + chosen { + zephyr,display = &zephyr_lcdif; + }; + + lvgl_pointer { + compatible = "zephyr,lvgl-pointer-input"; + input = <>911_rk043fn66hs_ctg>; + }; +}; + +&nxp_touch_i2c { + status = "okay"; + gt911_rk043fn66hs_ctg: gt911@5d { + compatible = "goodix,gt911"; + reg = <0x5d>; + irq-gpios = <&nxp_i2c_touch_fpc 2 GPIO_ACTIVE_HIGH>; + reset-gpios = <&nxp_i2c_touch_fpc 1 GPIO_ACTIVE_LOW>; + }; +}; + +&zephyr_lcdif { + status = "okay"; + width = <480>; + height = <272>; + display-timings { + compatible = "zephyr,panel-timing"; + hsync-len = <4>; + hfront-porch = <8>; + hback-porch = <43>; + vsync-len = <4>; + vfront-porch = <8>; + vback-porch = <12>; + de-active= <1>; + pixelclk-active = <1>; + hsync-active = <0>; + vsync-active = <0>; + clock-frequency = <9210240>; + }; + pixel-format = ; + data-bus-width = "16-bit"; + backlight-gpios = <&nxp_parallel_lcd_connector 0 GPIO_ACTIVE_HIGH>; +}; From 6c95c826048bbe34f88f980773f5c77c51ac0306 Mon Sep 17 00:00:00 2001 From: Daniel DeGrasse Date: Tue, 30 Apr 2024 19:57:39 +0000 Subject: [PATCH 1871/2849] boards: nxp: mimxrt1060_evk: remove display definition Remove display definition for the RT1060 EVK. This display panel is now supported as the RK043FN02H-CT shield. Add this information to the documentation for the board, along with other tested shields. Signed-off-by: Daniel DeGrasse --- boards/nxp/mimxrt1060_evk/Kconfig.defconfig | 45 ------------------- boards/nxp/mimxrt1060_evk/doc/index.rst | 4 +- boards/nxp/mimxrt1060_evk/mimxrt1060_evk.dts | 47 -------------------- 3 files changed, 3 insertions(+), 93 deletions(-) diff --git a/boards/nxp/mimxrt1060_evk/Kconfig.defconfig b/boards/nxp/mimxrt1060_evk/Kconfig.defconfig index 37dc90279ddee..899e8b3ffe0f2 100644 --- a/boards/nxp/mimxrt1060_evk/Kconfig.defconfig +++ b/boards/nxp/mimxrt1060_evk/Kconfig.defconfig @@ -11,16 +11,6 @@ config DEVICE_CONFIGURATION_DATA config NXP_IMX_EXTERNAL_SDRAM default y -config INPUT - default y if LVGL - -if INPUT - -config INPUT_FT5336_INTERRUPT - default y - -endif # INPUT - if NETWORKING config NET_L2_ETHERNET @@ -35,39 +25,4 @@ endif # ETH_MCUX endif # NETWORKING -if LVGL - -# LVGL should allocate buffers equal to size of display -config LV_Z_VDB_SIZE - 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 - -endif # LVGL - endif # BOARD_MIMXRT1060_EVK || BOARD_MIMXRT1060_EVKB diff --git a/boards/nxp/mimxrt1060_evk/doc/index.rst b/boards/nxp/mimxrt1060_evk/doc/index.rst index e33336ea98648..0c9fdd6096eb9 100644 --- a/boards/nxp/mimxrt1060_evk/doc/index.rst +++ b/boards/nxp/mimxrt1060_evk/doc/index.rst @@ -115,7 +115,9 @@ already supported, which can also be re-used on this mimxrt1060_evk board: +-----------+------------+-------------------------------------+ | SYSTICK | on-chip | systick | +-----------+------------+-------------------------------------+ -| DISPLAY | on-chip | display | +| DISPLAY | on-chip | eLCDIF. Tested with | +| | | :ref:`rk043fn02h_ct`, and | +| | | :ref:`rk043fn66hs_ctg` shields | +-----------+------------+-------------------------------------+ | FLASH | on-chip | QSPI flash | +-----------+------------+-------------------------------------+ diff --git a/boards/nxp/mimxrt1060_evk/mimxrt1060_evk.dts b/boards/nxp/mimxrt1060_evk/mimxrt1060_evk.dts index ac33358ff4f24..330451875e5c9 100644 --- a/boards/nxp/mimxrt1060_evk/mimxrt1060_evk.dts +++ b/boards/nxp/mimxrt1060_evk/mimxrt1060_evk.dts @@ -8,7 +8,6 @@ #include #include "mimxrt1060_evk-pinctrl.dtsi" -#include #include / { @@ -30,7 +29,6 @@ zephyr,console = &lpuart1; zephyr,shell-uart = &lpuart1; zephyr,canbus = &flexcan3; - zephyr,display = &lcdif; }; sdram0: memory@80000000 { @@ -90,11 +88,6 @@ }; }; - lvgl_pointer { - compatible = "zephyr,lvgl-pointer-input"; - input = <&ft5336>; - }; - arduino_header: connector { compatible = "arduino-header-r3"; #gpio-cells = <2>; @@ -123,15 +116,6 @@ <20 0 &gpio1 17 0>, /* D14 */ <21 0 &gpio1 16 0>; /* D15 */ }; - - panel { - compatible = "rocktech,rk043fn02h-ct"; - port { - lcd_panel_in: endpoint { - remote-endpoint = <&lcd_panel_out>; - }; - }; - }; }; arduino_serial: &lpuart3 { @@ -142,33 +126,8 @@ arduino_serial: &lpuart3 { }; zephyr_lcdif: &lcdif { - status = "okay"; - width = <480>; - height = <272>; - display-timings { - compatible = "zephyr,panel-timing"; - hsync-len = <41>; - hfront-porch = <4>; - hback-porch = <8>; - vsync-len = <10>; - vfront-porch = <4>; - vback-porch = <2>; - de-active= <1>; - pixelclk-active = <1>; - hsync-active = <0>; - vsync-active = <0>; - clock-frequency = <9210240>; - }; - pixel-format = ; - data-bus-width = "16-bit"; pinctrl-0 = <&pinmux_lcdif>; pinctrl-names = "default"; - backlight-gpios = <&gpio2 31 GPIO_ACTIVE_HIGH>; - port { - lcd_panel_out: endpoint { - remote-endpoint = <&lcd_panel_in>; - }; - }; }; nxp_touch_i2c: &lpi2c1 {}; @@ -177,12 +136,6 @@ arduino_i2c: &lpi2c1 { status = "okay"; pinctrl-0 = <&pinmux_lpi2c1>; pinctrl-names = "default"; - - ft5336: ft5336@38 { - compatible = "focaltech,ft5336"; - reg = <0x38>; - int-gpios = <&gpio1 11 GPIO_ACTIVE_LOW>; - }; }; &lpuart1 { From 7b207e309f0aa3e232119c7cd0594398fd4eac9a Mon Sep 17 00:00:00 2001 From: Daniel DeGrasse Date: Tue, 30 Apr 2024 20:22:22 +0000 Subject: [PATCH 1872/2849] samples: add testcases for rk043fn02h_ct and rk043fn66hs_ctg shields Add testcases for rk043fn02h_ct and rk043fn66hs_ctg shields to display and LVGL samples, so these testcases will be built by CI. Signed-off-by: Daniel DeGrasse --- samples/drivers/display/sample.yaml | 14 ++++++++++++++ samples/subsys/display/lvgl/sample.yaml | 14 ++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/samples/drivers/display/sample.yaml b/samples/drivers/display/sample.yaml index 50038edf93936..04fb4317ad848 100644 --- a/samples/drivers/display/sample.yaml +++ b/samples/drivers/display/sample.yaml @@ -175,3 +175,17 @@ tests: harness: console harness_config: fixture: fixture_display + sample.display.rk043fn66hs_ctg: + platform_allow: mimxrt1060_evk + tags: display + harness: console + extra_args: SHIELD=rk043fn66hs_ctg + harness_config: + fixture: fixture_display + sample.display.rk043fn02h_ct: + platform_allow: mimxrt1060_evk + tags: display + harness: console + extra_args: SHIELD=rk043fn02h_ct + harness_config: + fixture: fixture_display diff --git a/samples/subsys/display/lvgl/sample.yaml b/samples/subsys/display/lvgl/sample.yaml index d8bfb5de9b54b..d205051a12992 100644 --- a/samples/subsys/display/lvgl/sample.yaml +++ b/samples/subsys/display/lvgl/sample.yaml @@ -70,3 +70,17 @@ tests: - shield - lvgl - gui + samples.subsys.display.lvgl.rk043fn66hs_ctg: + platform_allow: mimxrt1060_evk + tags: display + harness: console + extra_args: SHIELD=rk043fn66hs_ctg + harness_config: + fixture: fixture_display + samples.subsys.display.lvgl.rk043fn02h_ct: + platform_allow: mimxrt1060_evk + tags: display + harness: console + extra_args: SHIELD=rk043fn02h_ct + harness_config: + fixture: fixture_display From 633065ec3b78bc15722b02804ad9d72450ebec71 Mon Sep 17 00:00:00 2001 From: Henrik Brix Andersen Date: Wed, 5 Jun 2024 15:43:58 +0000 Subject: [PATCH 1873/2849] drivers: can: mcux: flexcan: calculate and set proper TDCO Calculate and set a proper Transceiver Delay Compensation Offset (TDCO) based on FlexCAN FD timing. Signed-off-by: Henrik Brix Andersen --- drivers/can/can_mcux_flexcan.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/can/can_mcux_flexcan.c b/drivers/can/can_mcux_flexcan.c index 562d02650aa27..cc11dadf96247 100644 --- a/drivers/can/can_mcux_flexcan.c +++ b/drivers/can/can_mcux_flexcan.c @@ -305,6 +305,12 @@ static int mcux_flexcan_start(const struct device *dev) timing.fphaseSeg2 = data->timing_data.phase_seg2 - 1U; timing.fpropSeg = data->timing_data.prop_seg; FLEXCAN_SetFDTimingConfig(config->base, &timing); + + FLEXCAN_EnterFreezeMode(config->base); + config->base->FDCTRL &= ~(CAN_FDCTRL_TDCOFF_MASK); + config->base->FDCTRL |= FIELD_PREP(CAN_FDCTRL_TDCOFF_MASK, + CAN_CALC_TDCO((&data->timing_data), 1U, 31U)); + FLEXCAN_ExitFreezeMode(config->base); } #endif /* CONFIG_CAN_MCUX_FLEXCAN_FD */ From 16fc8f5295cc666923dabfff9d268d8e16dd8259 Mon Sep 17 00:00:00 2001 From: Balaji Srinivasan Date: Tue, 4 Jun 2024 09:07:46 +0200 Subject: [PATCH 1874/2849] task_wdt: Feed hardware watchdog only when its started Previously the schedule_next_timeout() function was feeding the hardware watchdog irrespective of whether or not it was started. This is now fixed. Signed-off-by: Balaji Srinivasan --- subsys/task_wdt/task_wdt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subsys/task_wdt/task_wdt.c b/subsys/task_wdt/task_wdt.c index 1a4e21cf3ebc5..361acc0e156e8 100644 --- a/subsys/task_wdt/task_wdt.c +++ b/subsys/task_wdt/task_wdt.c @@ -79,7 +79,7 @@ static void schedule_next_timeout(int64_t current_ticks) k_timer_start(&timer, K_TIMEOUT_ABS_TICKS(next_timeout), K_FOREVER); #ifdef CONFIG_TASK_WDT_HW_FALLBACK - if (hw_wdt_dev) { + if (hw_wdt_started) { wdt_feed(hw_wdt_dev, hw_wdt_channel); } #endif From 1635ad5a4d915734ccb0f0b1231cb3775f2d466d Mon Sep 17 00:00:00 2001 From: Jeppe Odgaard Date: Tue, 4 Jun 2024 08:42:42 +0200 Subject: [PATCH 1875/2849] dts: boards: stm32h562: add timers 15, 16 and 17 Add the remaining timer nodes for stm32h562. Tested with a Logic Analyzer and `samples/drivers/led_pwm` with added `nucleo_h563zi.overlay`: ``` &timers15 { status = "okay"; st,prescaler = <1000>; pwm15: pwm { status = "okay"; pinctrl-0 = <&tim15_ch2_pa3 /* CN10.34 */>; pinctrl-names = "default"; }; }; &timers16 { status = "okay"; st,prescaler = <1000>; pwm16: pwm { status = "okay"; pinctrl-0 = <&tim16_ch1n_pb6 /* CN10.14 */>; pinctrl-names = "default"; }; }; &timers17 { st,prescaler = <1000>; status = "okay"; pwm17: pwm { status = "okay"; pinctrl-0 = <&tim17_ch1n_pb7 /* CN10.16 */>; pinctrl-names = "default"; }; }; &pwmleds { status = "okay"; pwm_led_1: green_led_1 { pwms = <&pwm15 2 PWM_MSEC(20) PWM_POLARITY_NORMAL>; label = "green led"; }; pwm_led_2: red_led_1 { pwms = <&pwm16 1 PWM_MSEC(20) (PWM_POLARITY_NORMAL | STM32_PWM_COMPLEMENTARY)>; label = "red led"; }; pwm_led_3: blue_led_1 { pwms = <&pwm17 1 PWM_MSEC(20) (PWM_POLARITY_NORMAL | STM32_PWM_COMPLEMENTARY)>; label = "blue led"; }; }; ``` Signed-off-by: Jeppe Odgaard --- dts/arm/st/h5/stm32h562.dtsi | 63 ++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/dts/arm/st/h5/stm32h562.dtsi b/dts/arm/st/h5/stm32h562.dtsi index b8e7a23554bdd..bf3e11bbb195f 100644 --- a/dts/arm/st/h5/stm32h562.dtsi +++ b/dts/arm/st/h5/stm32h562.dtsi @@ -368,6 +368,69 @@ }; }; + timers15: timers@40014000 { + compatible = "st,stm32-timers"; + reg = <0x40014000 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_APB2 0x00010000>; + resets = <&rctl STM32_RESET(APB2, 16U)>; + interrupts = <71 0>; + interrupt-names = "global"; + status = "disabled"; + + pwm { + compatible = "st,stm32-pwm"; + status = "disabled"; + #pwm-cells = <3>; + }; + + counter { + compatible = "st,stm32-counter"; + status = "disabled"; + }; + }; + + timers16: timers@40014400 { + compatible = "st,stm32-timers"; + reg = <0x40014400 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_APB2 0x00020000>; + resets = <&rctl STM32_RESET(APB2, 17U)>; + interrupts = <72 0>; + interrupt-names = "global"; + status = "disabled"; + + pwm { + compatible = "st,stm32-pwm"; + status = "disabled"; + #pwm-cells = <3>; + }; + + counter { + compatible = "st,stm32-counter"; + status = "disabled"; + }; + }; + + timers17: timers@40014800 { + compatible = "st,stm32-timers"; + reg = <0x40014800 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_APB2 0x00040000>; + resets = <&rctl STM32_RESET(APB2, 18U)>; + interrupts = <73 0>; + interrupt-names = "global"; + status = "disabled"; + + pwm { + compatible = "st,stm32-pwm"; + status = "disabled"; + #pwm-cells = <3>; + }; + + counter { + compatible = "st,stm32-counter"; + status = "disabled"; + }; + }; + aes: aes@420c0000 { compatible = "st,stm32-aes"; reg = <0x420c0000 0x400>; From 6844016d9d4227fb24acca5dad67d0cd8656fa75 Mon Sep 17 00:00:00 2001 From: Pekka Niskanen Date: Tue, 4 Jun 2024 09:20:24 +0300 Subject: [PATCH 1876/2849] doc: update Infocenter links to TechDocs links As the Infocenter will soon be taken offline, updating links to point to TechDocs. Signed-off-by: Pekka Niskanen --- boards/nordic/nrf21540dk/doc/index.rst | 10 +++++----- boards/nordic/nrf51dk/doc/index.rst | 6 +++--- boards/nordic/nrf51dongle/doc/index.rst | 6 +++--- boards/nordic/nrf52833dk/doc/index.rst | 8 ++++---- boards/nordic/nrf52840dk/doc/index.rst | 8 ++++---- boards/nordic/nrf52840dongle/doc/index.rst | 10 +++++----- boards/nordic/nrf52dk/doc/index.rst | 6 +++--- boards/nordic/nrf5340_audio_dk/doc/index.rst | 8 ++++---- boards/nordic/nrf5340dk/doc/index.rst | 6 +++--- boards/nordic/nrf9131ek/doc/index.rst | 6 +++--- boards/nordic/nrf9151dk/doc/index.rst | 2 +- boards/nordic/nrf9160dk/doc/index.rst | 11 ++++++----- boards/nordic/nrf9161dk/doc/index.rst | 6 +++--- boards/nordic/thingy52/doc/index.rst | 4 ++-- boards/nordic/thingy53/doc/index.rst | 4 ++-- 15 files changed, 51 insertions(+), 50 deletions(-) diff --git a/boards/nordic/nrf21540dk/doc/index.rst b/boards/nordic/nrf21540dk/doc/index.rst index fdc726056360d..8ea583edb1a09 100644 --- a/boards/nordic/nrf21540dk/doc/index.rst +++ b/boards/nordic/nrf21540dk/doc/index.rst @@ -32,7 +32,7 @@ The CPU provides support for the following devices: nRF21540 DK (Credit: Nordic Semiconductor) More information about the board can be found at the `nRF21540 website`_. -The `Nordic Semiconductor Infocenter`_ contains the processor's and front end +`nRF21540 Product Specification`_ contains the processor's and front end module's information and the datasheet. Hardware @@ -83,7 +83,7 @@ hardware features: +-----------+------------+----------------------+ Other hardware features have not been enabled yet for this board. -See `nRF52840 Product Specification`_ and `Nordic Semiconductor Infocenter`_ +See `nRF52840 Product Specification`_ and `nRF21540 DK Hardware guide`_ for a complete list of nRF21540 Development Kit board hardware features. Connections and IOs @@ -229,8 +229,8 @@ References .. target-notes:: -.. _Nordic Semiconductor Infocenter: https://infocenter.nordicsemi.com +.. _nRF21540 DK Hardware guide: https://docs.nordicsemi.com/bundle/ug_nrf21540_dk/page/UG/nrf21540_DK/intro.html .. _J-Link Software and documentation pack: https://www.segger.com/jlink-software.html .. _nRF21540 website: https://www.nordicsemi.com/Products/Low-power-short-range-wireless/nRF21540 -.. _nRF52840 Product Specification: http://infocenter.nordicsemi.com/pdf/nRF52840_PS_v1.0.pdf -.. _nRF21540 Product Specification: http://infocenter.nordicsemi.com/pdf/nRF21540_PS_v1.0.pdf +.. _nRF52840 Product Specification: https://docs.nordicsemi.com/bundle/ps_nrf52840/page/keyfeatures_html5.html +.. _nRF21540 Product Specification: https://docs.nordicsemi.com/bundle/ps_nrf21540/page/keyfeatures_html5.html diff --git a/boards/nordic/nrf51dk/doc/index.rst b/boards/nordic/nrf51dk/doc/index.rst index b97e70e961319..c905dc0f4764b 100644 --- a/boards/nordic/nrf51dk/doc/index.rst +++ b/boards/nordic/nrf51dk/doc/index.rst @@ -29,7 +29,7 @@ Semiconductor nRF51822 ARM Cortex-M0 CPU and the following devices: nRF51 DK (Credit: Nordic Semiconductor) More information about the board can be found at the -`nRF51 DK website`_. The `Nordic Semiconductor Infocenter`_ +`nRF51 DK website`_. The `nRF51 Development Kit User Guide`_ contains the processor's information and the datasheet. @@ -75,7 +75,7 @@ hardware features: +-----------+------------+----------------------+ Other hardware features have not been enabled yet for this board. -See `nRF51 DK website`_ and `Nordic Semiconductor Infocenter`_ +See `nRF51 DK website`_ and `nRF51 Development Kit User Guide`_ for a complete list of nRF51 Development Kit board hardware features. Connections and IOs @@ -156,4 +156,4 @@ References .. target-notes:: .. _nRF51 DK website: https://www.nordicsemi.com/Software-and-Tools/Development-Kits/nRF51-DK -.. _Nordic Semiconductor Infocenter: https://infocenter.nordicsemi.com +.. _nRF51 Development Kit User Guide: https://docs.nordicsemi.com/bundle/nRF51-Series-DK/resource/nRF51_Development_Kit_User_Guide_v1.2.pdf diff --git a/boards/nordic/nrf51dongle/doc/index.rst b/boards/nordic/nrf51dongle/doc/index.rst index 720ff3a59861d..d8183371654a8 100644 --- a/boards/nordic/nrf51dongle/doc/index.rst +++ b/boards/nordic/nrf51dongle/doc/index.rst @@ -29,7 +29,7 @@ Semiconductor nRF51822 ARM Cortex-M0 CPU and the following devices: nRF51 Dongle (Credit: Nordic Semiconductor) More information about the board can be found at the -`nRF51 Dongle website`_. The `Nordic Semiconductor Infocenter`_ +`nRF51 Dongle website`_. The `Nordic Semiconductor TechDocs`_ contains the processor's information and the datasheet. @@ -75,7 +75,7 @@ hardware features: +-----------+------------+----------------------+ Other hardware features have not been enabled yet for this board. -See `nRF51 Dongle website`_ and `Nordic Semiconductor Infocenter`_ +See `nRF51 Dongle website`_ and `Nordic Semiconductor TechDocs`_ for a complete list of nRF51 Dongle hardware features. Connections and IOs @@ -141,4 +141,4 @@ References .. target-notes:: .. _nRF51 Dongle website: http://www.nordicsemi.com/eng/Products/nRF51-Dongle -.. _Nordic Semiconductor Infocenter: http://infocenter.nordicsemi.com/ +.. _Nordic Semiconductor TechDocs: https://docs.nordicsemi.com/ diff --git a/boards/nordic/nrf52833dk/doc/index.rst b/boards/nordic/nrf52833dk/doc/index.rst index d182053d50647..027f471586fed 100644 --- a/boards/nordic/nrf52833dk/doc/index.rst +++ b/boards/nordic/nrf52833dk/doc/index.rst @@ -27,7 +27,7 @@ the following devices: * :abbr:`WDT (Watchdog Timer)` More information about the board can be found at the -`nRF52833 DK website`_. The `Nordic Semiconductor Infocenter`_ +`nRF52833 DK website`_. `nRF52833 Product Specification`_ contains the processor's information and the datasheet. @@ -80,7 +80,7 @@ hardware features: +-----------+------------+----------------------+ Other hardware features have not been enabled yet for this board. -See `nRF52833 DK website`_ and `Nordic Semiconductor Infocenter`_ +See `nRF52833 DK website`_ and `nRF52833 DK Hardware guide`_ for a complete list of nRF52833 Development Kit board hardware features. Connections and IOs @@ -212,9 +212,9 @@ References .. target-notes:: .. _nRF52833 DK website: https://www.nordicsemi.com/Software-and-Tools/Development-Kits/nRF52833-DK -.. _Nordic Semiconductor Infocenter: https://infocenter.nordicsemi.com +.. _nRF52833 Product Specification: https://docs.nordicsemi.com/bundle/ps_nrf52833/page/keyfeatures_html5.html .. _J-Link Software and documentation pack: https://www.segger.com/jlink-software.html -.. _nRF52833 Product Specification: https://infocenter.nordicsemi.com/pdf/nRF52833_OPS_v0.7.pdf +.. _nRF52833 DK Hardware guide: https://docs.nordicsemi.com/bundle/ug_nrf52833_dk/page/UG/dk/intro.html .. _nrf52833dk_nrf52820: diff --git a/boards/nordic/nrf52840dk/doc/index.rst b/boards/nordic/nrf52840dk/doc/index.rst index 953c86fd19022..faa7f07d5c931 100644 --- a/boards/nordic/nrf52840dk/doc/index.rst +++ b/boards/nordic/nrf52840dk/doc/index.rst @@ -32,7 +32,7 @@ Nordic Semiconductor nRF52840 ARM Cortex-M4F CPU and the following devices: nRF52840 DK (Credit: Nordic Semiconductor) More information about the board can be found at the `nRF52840 DK website`_. -The `Nordic Semiconductor Infocenter`_ contains the processor's information +`nRF52840 Product Specification`_ contains the processor's information and the datasheet. @@ -84,7 +84,7 @@ hardware features: +-----------+------------+----------------------+ Other hardware features have not been enabled yet for this board. -See `nRF52840 DK website`_ and `Nordic Semiconductor Infocenter`_ +See `nRF52840 DK website`_ and `nRF52840 DK Hardware guide`_ for a complete list of nRF52840 Development Kit board hardware features. Connections and IOs @@ -244,7 +244,7 @@ References .. target-notes:: .. _nRF52840 DK website: https://www.nordicsemi.com/Software-and-Tools/Development-Kits/nRF52840-DK -.. _Nordic Semiconductor Infocenter: https://infocenter.nordicsemi.com +.. _nRF52840 Product Specification: https://docs.nordicsemi.com/bundle/ps_nrf52840/page/keyfeatures_html5.html +.. _nRF52840 DK Hardware guide: https://docs.nordicsemi.com/bundle/ug_nrf52840_dk/page/UG/dk/intro.html .. _J-Link Software and documentation pack: https://www.segger.com/jlink-software.html -.. _nRF52840 Product Specification: http://infocenter.nordicsemi.com/pdf/nRF52840_PS_v1.0.pdf .. _nRF52811 website: https://www.nordicsemi.com/Products/Low-power-short-range-wireless/nRF52811 diff --git a/boards/nordic/nrf52840dongle/doc/index.rst b/boards/nordic/nrf52840dongle/doc/index.rst index 235b0ea4b35b4..9aa6f74811f3e 100644 --- a/boards/nordic/nrf52840dongle/doc/index.rst +++ b/boards/nordic/nrf52840dongle/doc/index.rst @@ -31,7 +31,7 @@ Semiconductor nRF52840 ARM Cortex-M4F CPU and the following devices: nRF52840 Dongle More information about the board can be found at the -`nRF52840 Dongle website`_. The `Nordic Semiconductor Infocenter`_ +`nRF52840 Dongle website`_. The `nRF52840 Dongle guide`_ contains the processor's information and the datasheet. @@ -82,7 +82,7 @@ hardware features: +-----------+------------+----------------------+ Other hardware features have not been enabled yet for this board. -See `nRF52840 Dongle website`_ and `Nordic Semiconductor Infocenter`_ +See `nRF52840 Dongle website`_ and `nRF52840 Dongle Hardware description`_ for a complete list of nRF52840 Dongle board hardware features. Connections and IOs @@ -334,12 +334,12 @@ References .. _nRF52840 Dongle website: https://www.nordicsemi.com/Software-and-Tools/Development-Kits/nRF52840-Dongle -.. _Nordic Semiconductor Infocenter: - https://infocenter.nordicsemi.com +.. _nRF52840 Dongle guide: https://docs.nordicsemi.com/bundle/ug_nrf52840_dk/page/UG/dk/intro.html +.. _nRF52840 Dongle Hardware description: https://docs.nordicsemi.com/bundle/ug_nrf52840_dongle/page/UG/nrf52840_Dongle/hw_description.html .. _J-Link Software and documentation pack: https://www.segger.com/jlink-software.html .. _Nordic Semiconductor USB DFU: - https://infocenter.nordicsemi.com/index.jsp?topic=%2Fcom.nordic.infocenter.sdk5.v15.2.0%2Fsdk_app_serial_dfu_bootloader.html + https://docs.nordicsemi.com/bundle/sdk_nrf5_v17.1.0/page/sdk_app_serial_dfu_bootloader.html .. _nrfutil: https://github.com/NordicSemiconductor/pc-nrfutil .. _MCUboot: diff --git a/boards/nordic/nrf52dk/doc/index.rst b/boards/nordic/nrf52dk/doc/index.rst index 07f241eac1efe..4ebcac44e6c25 100644 --- a/boards/nordic/nrf52dk/doc/index.rst +++ b/boards/nordic/nrf52dk/doc/index.rst @@ -32,7 +32,7 @@ the following devices: nRF52 DK (Credit: Nordic Semiconductor) More information about the board can be found at the -`nRF52 DK website`_. The `Nordic Semiconductor Infocenter`_ +`nRF52 DK website`_. `nRF52832 Product Specification`_ contains the processor's information and the datasheet. @@ -82,7 +82,7 @@ hardware features: +-----------+------------+----------------------+ Other hardware features have not been enabled yet for this board. -See `nRF52 DK website`_ and `Nordic Semiconductor Infocenter`_ +See `nRF52 DK website`_ and `nRF52832 Product Specification`_ for a complete list of nRF52 Development Kit board hardware features. Connections and IOs @@ -403,7 +403,7 @@ References .. target-notes:: .. _nRF52 DK website: https://www.nordicsemi.com/Software-and-Tools/Development-Kits/nRF52-DK -.. _Nordic Semiconductor Infocenter: https://infocenter.nordicsemi.com +.. _nRF52832 Product Specification: https://docs.nordicsemi.com/bundle/ps_nrf52832/page/nrf52832_ps.html .. _nrf52dk_nrf52805: diff --git a/boards/nordic/nrf5340_audio_dk/doc/index.rst b/boards/nordic/nrf5340_audio_dk/doc/index.rst index 558f995be6625..f7b23c0d6de63 100644 --- a/boards/nordic/nrf5340_audio_dk/doc/index.rst +++ b/boards/nordic/nrf5340_audio_dk/doc/index.rst @@ -35,7 +35,7 @@ The nRF5340 Audio DK comes with the following hardware features: :align: center :alt: nRF5340 DK -More information about the board can be found at the `nRF5340 Audio DK website`_. The `Nordic Semiconductor Infocenter`_ +More information about the board can be found at the `nRF5340 Audio DK website`_. The `nRF5340 Audio DK hardware guide`_ contains the processor's information and the datasheet. nRF5340 SoC @@ -53,13 +53,13 @@ The ``nrf5340_audio_dk/nrf5340/cpuapp`` build target provides support for the ap core on the nRF5340 SoC. The ``nrf5340_audio_dk/nrf5340/cpunet`` build target provides support for the network core on the nRF5340 SoC. -The `Nordic Semiconductor Infocenter`_ contains the processor's information and +The `nRF5340 Audio DK hardware guide`_ contains the processor's information and the datasheet. Supported Features ================== -See :ref:`nrf5340dk_nrf5340` and `Nordic Semiconductor Infocenter`_ +See :ref:`nrf5340dk_nrf5340` and `nRF5340 Audio DK hardware guide`_ for a complete list of nRF5340 Audio DK board hardware features. @@ -106,4 +106,4 @@ References .. _nRF5340 Audio DK website: https://www.nordicsemi.com/Products/Development-hardware/nrf5340-audio-dk -.. _Nordic Semiconductor Infocenter: https://infocenter.nordicsemi.com +.. _nRF5340 Audio DK hardware guide: https://docs.nordicsemi.com/bundle/ug_nrf5340_audio/page/UG/nrf5340_audio/intro.html diff --git a/boards/nordic/nrf5340dk/doc/index.rst b/boards/nordic/nrf5340dk/doc/index.rst index f8ce8a2a84b8a..e933f43bdb4b5 100644 --- a/boards/nordic/nrf5340dk/doc/index.rst +++ b/boards/nordic/nrf5340dk/doc/index.rst @@ -48,7 +48,7 @@ nRF5340 SoC provides support for the following devices: More information about the board can be found at the `nRF5340 DK website`_. -The `Nordic Semiconductor Infocenter`_ +The `nRF5340 DK Product Specification`_ contains the processor's information and the datasheet. @@ -132,7 +132,7 @@ hardware features: +-----------+------------+----------------------+ Other hardware features have not been enabled yet for this board. -See `Nordic Semiconductor Infocenter`_ +See `nRF5340 DK Product Specification`_ for a complete list of nRF5340 DK board hardware features. Connections and IOs @@ -326,5 +326,5 @@ References https://developer.arm.com/docs/100690/latest/attribution-units-sau-and-idau .. _nRF5340 DK website: https://www.nordicsemi.com/Software-and-tools/Development-Kits/nRF5340-DK -.. _Nordic Semiconductor Infocenter: https://infocenter.nordicsemi.com +.. _nRF5340 DK Product Specification: https://docs.nordicsemi.com/bundle/ps_nrf5340/page/keyfeatures_html5.html .. _Trusted Firmware M: https://www.trustedfirmware.org/projects/tf-m/ diff --git a/boards/nordic/nrf9131ek/doc/index.rst b/boards/nordic/nrf9131ek/doc/index.rst index 4e328e0bb0ec8..accd403a28683 100644 --- a/boards/nordic/nrf9131ek/doc/index.rst +++ b/boards/nordic/nrf9131ek/doc/index.rst @@ -32,8 +32,8 @@ Cortex-M33F CPU with ARMv8-M Security Extension and the following devices: nRF9131 EK (Credit: Nordic Semiconductor) -The `Nordic Semiconductor Infocenter`_ -contains the processor's information and the datasheet. +The `Nordic Semiconductor TechDocs`_ will soon +contain the processor's information and the datasheet. Hardware @@ -225,5 +225,5 @@ References .. _IDAU: https://developer.arm.com/docs/100690/latest/attribution-units-sau-and-idau -.. _Nordic Semiconductor Infocenter: https://infocenter.nordicsemi.com +.. _Nordic Semiconductor TechDocs: https://docs.nordicsemi.com/ .. _Trusted Firmware M: https://www.trustedfirmware.org/projects/tf-m/ diff --git a/boards/nordic/nrf9151dk/doc/index.rst b/boards/nordic/nrf9151dk/doc/index.rst index 40979cc90898c..4017347c4f84b 100644 --- a/boards/nordic/nrf9151dk/doc/index.rst +++ b/boards/nordic/nrf9151dk/doc/index.rst @@ -196,5 +196,5 @@ References .. _IDAU: https://developer.arm.com/docs/100690/latest/attribution-units-sau-and-idau .. _nRF9151 website: https://www.nordicsemi.com/Products/nRF9151 -.. _Nordic Semiconductor Infocenter: https://infocenter.nordicsemi.com +.. _Nordic Semiconductor TechDocs: https://docs.nordicsemi.com/ .. _Trusted Firmware M: https://www.trustedfirmware.org/projects/tf-m/ diff --git a/boards/nordic/nrf9160dk/doc/index.rst b/boards/nordic/nrf9160dk/doc/index.rst index 0527bbe00b5ad..70fd2c2fc46ec 100644 --- a/boards/nordic/nrf9160dk/doc/index.rst +++ b/boards/nordic/nrf9160dk/doc/index.rst @@ -33,7 +33,7 @@ Cortex-M33F CPU with ARMv8-M Security Extension and the following devices: nRF9160 DK (Credit: Nordic Semiconductor) More information about the board can be found at the -`nRF9160 DK website`_. The `Nordic Semiconductor Infocenter`_ +`nRF9160 DK website`_. `nRF9160 Product Specification`_ contains the processor's information and the datasheet. @@ -108,7 +108,7 @@ Remember to also enable routing for this additional hardware in the firmware for :ref:`nrf9160dk_nrf52840` (see :ref:`nrf9160dk_board_controller_firmware`). Other hardware features have not been enabled yet for this board. -See `nRF9160 DK website`_ and `Nordic Semiconductor Infocenter`_ +See `nRF9160 DK website`_ and `nRF9160 Product Specification`_ for a complete list of nRF9160 DK board hardware features. Connections and IOs @@ -282,7 +282,7 @@ SiP. More information about the board can be found at the `Nordic Low power cellular IoT`_ website. -The `Nordic Semiconductor Infocenter`_ +`nRF52840 Product Specification`_ contains the processor's information and the datasheet. @@ -526,6 +526,7 @@ References .. _nRF9160 DK website: https://www.nordicsemi.com/Software-and-Tools/Development-Kits/nRF9160-DK .. _Trusted Firmware M: https://www.trustedfirmware.org/projects/tf-m/ .. _Nordic Low power cellular IoT: https://www.nordicsemi.com/Products/Low-power-cellular-IoT -.. _Nordic Semiconductor Infocenter: https://infocenter.nordicsemi.com +.. _nRF9160 Product Specification: https://docs.nordicsemi.com/bundle/ps_nrf9160/page/nRF9160_html5_keyfeatures.html +.. _nRF52840 Product Specification: https://docs.nordicsemi.com/bundle/ps_nrf52840/page/keyfeatures_html5.html .. _J-Link Software and documentation pack: https://www.segger.com/jlink-software.html -.. _nRF9160 DK board control section in the nRF9160 DK User Guide: https://infocenter.nordicsemi.com/topic/ug_nrf91_dk/UG/nrf91_DK/board_controller.html +.. _nRF9160 DK board control section in the nRF9160 DK User Guide: https://docs.nordicsemi.com/bundle/ug_nrf9160_dk/page/UG/nrf91_DK/hw_description/nrf9160_board_controller.html diff --git a/boards/nordic/nrf9161dk/doc/index.rst b/boards/nordic/nrf9161dk/doc/index.rst index 8b3a7fb023682..251c8467a214c 100644 --- a/boards/nordic/nrf9161dk/doc/index.rst +++ b/boards/nordic/nrf9161dk/doc/index.rst @@ -27,7 +27,7 @@ Cortex-M33F CPU with ARMv8-M Security Extension and the following devices: * :abbr:`IDAU (Implementation Defined Attribution Unit)` More information about the board can be found at the -`nRF9161 DK website`_. The `Nordic Semiconductor Infocenter`_ +`nRF9161 DK website`_. `nRF9161 Product Specification`_ contains the processor's information and the datasheet. @@ -84,7 +84,7 @@ hardware features: .. _nrf9161dk_additional_hardware: Other hardware features have not been enabled yet for this board. -See `nRF9161 DK website`_ and `Nordic Semiconductor Infocenter`_ +See `nRF9161 DK website`_ and `nRF9161 Product Specification`_ for a complete list of nRF9161 DK board hardware features. Connections and IOs @@ -199,5 +199,5 @@ References .. _IDAU: https://developer.arm.com/docs/100690/latest/attribution-units-sau-and-idau .. _nRF9161 DK website: https://www.nordicsemi.com/Software-and-Tools/Development-Kits/nRF9161-DK -.. _Nordic Semiconductor Infocenter: https://infocenter.nordicsemi.com +.. _nRF9161 Product Specification: https://docs.nordicsemi.com/bundle/ps_nrf9161/page/nRF9161_html5_keyfeatures.html .. _Trusted Firmware M: https://www.trustedfirmware.org/projects/tf-m/ diff --git a/boards/nordic/thingy52/doc/index.rst b/boards/nordic/thingy52/doc/index.rst index e56f00df34370..e83968f746984 100644 --- a/boards/nordic/thingy52/doc/index.rst +++ b/boards/nordic/thingy52/doc/index.rst @@ -41,7 +41,7 @@ processor, a set of environmental sensors, a pushbutton, and two RGB LEDs. nRF52 Thingy:52 (Credit: Nordic Semiconductor) More information about the board can be found at the `nRF52 DK website`_. The -`Nordic Semiconductor Infocenter`_ contains the processor's information and the +`Nordic Thingy:52 guide`_ contains the processor's information and the datasheet. @@ -390,4 +390,4 @@ References .. target-notes:: .. _nRF52 DK website: https://www.nordicsemi.com/Software-and-Tools/Development-Kits/Nordic-Thingy-52 -.. _Nordic Semiconductor Infocenter: http://infocenter.nordicsemi.com/ +.. _Nordic Thingy:52 guide: https://docs.nordicsemi.com/bundle/ug_thingy52/page/UG/thingy52/intro/frontpage.html diff --git a/boards/nordic/thingy53/doc/index.rst b/boards/nordic/thingy53/doc/index.rst index e2f8b000f17ab..f82626e16842c 100644 --- a/boards/nordic/thingy53/doc/index.rst +++ b/boards/nordic/thingy53/doc/index.rst @@ -22,7 +22,7 @@ The ``thingy53/nrf5340/cpuapp`` build target provides support for the applicatio core on the nRF5340 SoC. The ``thingy53/nrf5340/cpunet`` build target provides support for the network core on the nRF5340 SoC. -The `Nordic Semiconductor Infocenter`_ contains the processor's information and +The `Nordic Thingy:53 Hardware guide`_ contains the processor's information and the datasheet. Programming and Debugging @@ -48,4 +48,4 @@ References .. target-notes:: -.. _Nordic Semiconductor Infocenter: http://infocenter.nordicsemi.com/ +.. _Nordic Thingy:53 Hardware guide: https://docs.nordicsemi.com/bundle/ug_thingy53/page/UG/thingy53/intro/frontpage.html From 026d0507ea3e97c7e9865235a175579d062ce955 Mon Sep 17 00:00:00 2001 From: Daniel DeGrasse Date: Mon, 3 Jun 2024 16:13:01 -0500 Subject: [PATCH 1877/2849] boards: shields: adafruit_2_8_tft_touch_v2: fix RW612 board overlay RW612 board overlay should remove the MIPI DBI nodes defined at the board and at the shield level, because the LCDIC peripheral on this SOC can support the MIPI DBI protocol directly without the emulated Zephyr driver. Signed-off-by: Daniel DeGrasse --- .../adafruit_2_8_tft_touch_v2/boards/rd_rw612_bga.overlay | 1 + 1 file changed, 1 insertion(+) diff --git a/boards/shields/adafruit_2_8_tft_touch_v2/boards/rd_rw612_bga.overlay b/boards/shields/adafruit_2_8_tft_touch_v2/boards/rd_rw612_bga.overlay index 59136c9b45bca..8c44347e63f1d 100644 --- a/boards/shields/adafruit_2_8_tft_touch_v2/boards/rd_rw612_bga.overlay +++ b/boards/shields/adafruit_2_8_tft_touch_v2/boards/rd_rw612_bga.overlay @@ -16,6 +16,7 @@ * directly and does not require the MIPI DBI SPI node */ /delete-node/ mipi_dbi; + /delete-node/ adafruit_2_8_tft_touch_v2_mipi_dbi; }; &lcdic { From c77b956de5a7b5e6b3ce822bbdc1f09188c43837 Mon Sep 17 00:00:00 2001 From: Daniel DeGrasse Date: Mon, 3 Jun 2024 15:59:52 -0500 Subject: [PATCH 1878/2849] soc: nxp: imxrt11xx: support configuration of ARM PLL Add support for configuration of the ARM PLL on the iMXRT1170/1160 series SOCs. This PLL is used to generate the M7 core frequency, and is an integer pll. Provide default configurations for the RT1160 and RT1170 targeting 600MHz and 1GHz respectively. Signed-off-by: Daniel DeGrasse --- boards/nxp/mimxrt1160_evk/mimxrt1160_evk.dtsi | 1 + boards/nxp/mimxrt1170_evk/mimxrt1170_evk.dtsi | 1 + boards/nxp/vmu_rt1170/vmu_rt1170.dtsi | 1 + dts/arm/nxp/nxp_rt1160.dtsi | 11 ++++++ dts/arm/nxp/nxp_rt1170.dtsi | 11 ++++++ dts/arm/nxp/nxp_rt11xx.dtsi | 12 +++++++ soc/nxp/imxrt/imxrt11xx/soc.c | 36 +++++++++++-------- 7 files changed, 59 insertions(+), 14 deletions(-) create mode 100644 dts/arm/nxp/nxp_rt1160.dtsi create mode 100644 dts/arm/nxp/nxp_rt1170.dtsi diff --git a/boards/nxp/mimxrt1160_evk/mimxrt1160_evk.dtsi b/boards/nxp/mimxrt1160_evk/mimxrt1160_evk.dtsi index 62d3bd59998e8..54a8cfceecc82 100644 --- a/boards/nxp/mimxrt1160_evk/mimxrt1160_evk.dtsi +++ b/boards/nxp/mimxrt1160_evk/mimxrt1160_evk.dtsi @@ -5,6 +5,7 @@ */ #include "mimxrt1160_evk-pinctrl.dtsi" +#include #include / { diff --git a/boards/nxp/mimxrt1170_evk/mimxrt1170_evk.dtsi b/boards/nxp/mimxrt1170_evk/mimxrt1170_evk.dtsi index e70890f911d4f..685179d800307 100644 --- a/boards/nxp/mimxrt1170_evk/mimxrt1170_evk.dtsi +++ b/boards/nxp/mimxrt1170_evk/mimxrt1170_evk.dtsi @@ -5,6 +5,7 @@ */ #include "mimxrt1170_evk-pinctrl.dtsi" +#include #include / { diff --git a/boards/nxp/vmu_rt1170/vmu_rt1170.dtsi b/boards/nxp/vmu_rt1170/vmu_rt1170.dtsi index 075dc1860dc36..432fb4cc6d2c8 100644 --- a/boards/nxp/vmu_rt1170/vmu_rt1170.dtsi +++ b/boards/nxp/vmu_rt1170/vmu_rt1170.dtsi @@ -5,6 +5,7 @@ */ #include "vmu_rt1170-pinctrl.dtsi" +#include / { aliases { diff --git a/dts/arm/nxp/nxp_rt1160.dtsi b/dts/arm/nxp/nxp_rt1160.dtsi new file mode 100644 index 0000000000000..1794204a80f30 --- /dev/null +++ b/dts/arm/nxp/nxp_rt1160.dtsi @@ -0,0 +1,11 @@ +/* + * Copyright 2024 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* Configure ARM PLL to 600MHz */ +&arm_pll { + clock-mult = <100>; + clock-div = <4>; +}; diff --git a/dts/arm/nxp/nxp_rt1170.dtsi b/dts/arm/nxp/nxp_rt1170.dtsi new file mode 100644 index 0000000000000..555225b94fd93 --- /dev/null +++ b/dts/arm/nxp/nxp_rt1170.dtsi @@ -0,0 +1,11 @@ +/* + * Copyright 2024 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* Configure ARM PLL to 996MHz */ +&arm_pll { + clock-mult = <83>; + clock-div = <2>; +}; diff --git a/dts/arm/nxp/nxp_rt11xx.dtsi b/dts/arm/nxp/nxp_rt11xx.dtsi index fc0a169080010..a118ba0fb38ed 100644 --- a/dts/arm/nxp/nxp_rt11xx.dtsi +++ b/dts/arm/nxp/nxp_rt11xx.dtsi @@ -169,6 +169,18 @@ reg = <0x40cc0000 0x4000>; #clock-cells = <3>; + + /* + * ARM PLL is an integer PLL, with an input clock + * of 24MHz. The PLL features a loop divider and + * post divider. The output frequency is calculated + * as Fout = 24MHz * (clock-mult / clock-div) + */ + arm_pll: arm-pll { + compatible = "fixed-factor-clock"; + #clock-cells = <0>; + }; + }; gpio1: gpio@4012c000 { diff --git a/soc/nxp/imxrt/imxrt11xx/soc.c b/soc/nxp/imxrt/imxrt11xx/soc.c index 642708af9871d..be06e59c34bd4 100644 --- a/soc/nxp/imxrt/imxrt11xx/soc.c +++ b/soc/nxp/imxrt/imxrt11xx/soc.c @@ -55,22 +55,30 @@ #endif #ifdef CONFIG_INIT_ARM_PLL -static const clock_arm_pll_config_t armPllConfig = { -#if defined(CONFIG_SOC_MIMXRT1176_CM4) || defined(CONFIG_SOC_MIMXRT1176_CM7) - /* resulting frequency: 24 * (166/(2* 2)) = 984MHz */ - /* Post divider, 0 - DIV by 2, 1 - DIV by 4, 2 - DIV by 8, 3 - DIV by 1 */ - .postDivider = kCLOCK_PllPostDiv2, - /* PLL Loop divider, Fout = Fin * ( loopDivider / ( 2 * postDivider ) ) */ - .loopDivider = 166, -#elif defined(CONFIG_SOC_MIMXRT1166_CM4) || defined(CONFIG_SOC_MIMXRT1166_CM7) - /* resulting frequency: 24 * (200/(2 * 4)) = 600MHz */ - /* Post divider, 0 - DIV by 2, 1 - DIV by 4, 2 - DIV by 8, 3 - DIV by 1 */ - .postDivider = kCLOCK_PllPostDiv4, - /* PLL Loop divider, Fout = Fin * ( loopDivider / ( 2 * postDivider ) ) */ - .loopDivider = 200, + +#if defined(CONFIG_SOC_MIMXRT1176) +#define DEFAULT_LOOPDIV 83 +#define DEFAULT_POSTDIV 2 +#elif defined(CONFIG_SOC_MIMXRT1166) +#define DEFAULT_LOOPDIV 100 +#define DEFAULT_POSTDIV 4 #else - #error "Unknown SOC, no pll configuration defined" +/* + * Check that the ARM PLL has a multiplier and divider set + */ +BUILD_ASSERT(DT_NODE_HAS_PROP(DT_NODELABEL(arm_pll), clock_mult), + "ARM PLL must have clock-mult property"); +BUILD_ASSERT(DT_NODE_HAS_PROP(DT_NODELABEL(arm_pll), clock_div), + "ARM PLL must have clock-div property"); #endif + + +static const clock_arm_pll_config_t armPllConfig = { + .postDivider = CONCAT(kCLOCK_PllPostDiv, + DT_PROP_OR(DT_NODELABEL(arm_pll), clock_div, + DEFAULT_POSTDIV)), + .loopDivider = DT_PROP_OR(DT_NODELABEL(arm_pll), clock_mult, + DEFAULT_LOOPDIV) * 2, }; #endif From 9addbe77fc45c84a00a646418b9941b9984f4ca8 Mon Sep 17 00:00:00 2001 From: Peter van der Perk Date: Tue, 28 May 2024 17:10:06 +0200 Subject: [PATCH 1879/2849] drivers: pwm: pwm_mcux_qtmr: Add QTMR driver. PWM driver for QTMR peripheral Signed-off-by: Peter van der Perk --- drivers/pwm/CMakeLists.txt | 1 + drivers/pwm/Kconfig | 2 + drivers/pwm/Kconfig.mcux_qtmr | 10 ++ drivers/pwm/pwm_mcux_qtmr.c | 173 +++++++++++++++++++++++++++++ dts/bindings/pwm/nxp,qtmr-pwm.yaml | 23 ++++ 5 files changed, 209 insertions(+) create mode 100644 drivers/pwm/Kconfig.mcux_qtmr create mode 100644 drivers/pwm/pwm_mcux_qtmr.c create mode 100644 dts/bindings/pwm/nxp,qtmr-pwm.yaml diff --git a/drivers/pwm/CMakeLists.txt b/drivers/pwm/CMakeLists.txt index 2ac86d3e38ebc..81fe37b170f2b 100644 --- a/drivers/pwm/CMakeLists.txt +++ b/drivers/pwm/CMakeLists.txt @@ -18,6 +18,7 @@ zephyr_library_sources_ifdef(CONFIG_MCPWM_ESP32 pwm_mc_esp32.c) zephyr_library_sources_ifdef(CONFIG_PWM_SAM pwm_sam.c) zephyr_library_sources_ifdef(CONFIG_PWM_MCUX pwm_mcux.c) zephyr_library_sources_ifdef(CONFIG_PWM_MCUX_SCTIMER pwm_mcux_sctimer.c) +zephyr_library_sources_ifdef(CONFIG_PWM_MCUX_QTMR pwm_mcux_qtmr.c) zephyr_library_sources_ifdef(CONFIG_PWM_XEC pwm_mchp_xec.c) zephyr_library_sources_ifdef(CONFIG_PWM_LITEX pwm_litex.c) zephyr_library_sources_ifdef(CONFIG_PWM_RV32M1_TPM pwm_rv32m1_tpm.c) diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig index d8a412078f9b6..6ae5f59750f0d 100644 --- a/drivers/pwm/Kconfig +++ b/drivers/pwm/Kconfig @@ -58,6 +58,8 @@ source "drivers/pwm/Kconfig.mcux" source "drivers/pwm/Kconfig.mcux_sctimer" +source "drivers/pwm/Kconfig.mcux_qtmr" + source "drivers/pwm/Kconfig.xec" source "drivers/pwm/Kconfig.litex" diff --git a/drivers/pwm/Kconfig.mcux_qtmr b/drivers/pwm/Kconfig.mcux_qtmr new file mode 100644 index 0000000000000..bb8329bbdaade --- /dev/null +++ b/drivers/pwm/Kconfig.mcux_qtmr @@ -0,0 +1,10 @@ +# Copyright 2024 NXP +# SPDX-License-Identifier: Apache-2.0 + +config PWM_MCUX_QTMR + bool "MCUX QMTR PWM driver" + default y + depends on DT_HAS_NXP_QTMR_PWM_ENABLED + depends on CLOCK_CONTROL && PINCTRL + help + Enable QTMR based pwm driver. diff --git a/drivers/pwm/pwm_mcux_qtmr.c b/drivers/pwm/pwm_mcux_qtmr.c new file mode 100644 index 0000000000000..b78f43b0436b1 --- /dev/null +++ b/drivers/pwm/pwm_mcux_qtmr.c @@ -0,0 +1,173 @@ +/* + * Copyright (c) 2024, NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT nxp_qtmr_pwm + +#include +#include +#include +#include +#include +#include +#include + +#include + +LOG_MODULE_REGISTER(pwm_mcux_qtmr, CONFIG_PWM_LOG_LEVEL); + +#define CHANNEL_COUNT TMR_CNTR_COUNT + +struct pwm_mcux_qtmr_config { + TMR_Type *base; + uint32_t prescaler; + const struct pinctrl_dev_config *pincfg; + const struct device *clock_dev; + clock_control_subsys_t clock_subsys; +}; + +struct pwm_mcux_qtmr_data { + struct k_mutex lock; +}; + +static int mcux_qtmr_pwm_set_cycles(const struct device *dev, uint32_t channel, + uint32_t period_cycles, uint32_t pulse_cycles, + pwm_flags_t flags) +{ + const struct pwm_mcux_qtmr_config *config = dev->config; + struct pwm_mcux_qtmr_data *data = dev->data; + uint32_t periodCount, highCount, lowCount; + uint16_t reg; + + if (channel >= CHANNEL_COUNT) { + LOG_ERR("Invalid channel"); + return -EINVAL; + } + + /* Counter values to generate a PWM signal */ + periodCount = period_cycles; + highCount = pulse_cycles; + lowCount = period_cycles - pulse_cycles; + + if (highCount > 0U) { + highCount -= 1U; + } + if (lowCount > 0U) { + lowCount -= 1U; + } + + if ((highCount > 0xFFFFU) || (lowCount > 0xFFFFU)) { + /* This should not be a 16-bit overflow value. If it is, change to a larger divider + * for clock source. + */ + return -EINVAL; + } + + k_mutex_lock(&data->lock, K_FOREVER); + + /* Set OFLAG pin for output mode and force out a low on the pin */ + config->base->CHANNEL[channel].SCTRL |= (TMR_SCTRL_FORCE_MASK | TMR_SCTRL_OEN_MASK); + + QTMR_StopTimer(config->base, channel); + + /* Setup the compare registers for PWM output */ + config->base->CHANNEL[channel].COMP1 = (uint16_t)lowCount; + config->base->CHANNEL[channel].COMP2 = (uint16_t)highCount; + + /* Setup the pre-load registers for PWM output */ + config->base->CHANNEL[channel].CMPLD1 = (uint16_t)lowCount; + config->base->CHANNEL[channel].CMPLD2 = (uint16_t)highCount; + + reg = config->base->CHANNEL[channel].CSCTRL; + /* Setup the compare load control for COMP1 and COMP2. + * Load COMP1 when CSCTRL[TCF2] is asserted, load COMP2 when CSCTRL[TCF1] is asserted + */ + reg &= (uint16_t)(~(TMR_CSCTRL_CL1_MASK | TMR_CSCTRL_CL2_MASK)); + reg |= (TMR_CSCTRL_CL1(kQTMR_LoadOnComp2) | TMR_CSCTRL_CL2(kQTMR_LoadOnComp1)); + config->base->CHANNEL[channel].CSCTRL = reg; + + reg = config->base->CHANNEL[channel].CTRL; + reg &= ~(uint16_t)TMR_CTRL_OUTMODE_MASK; + if (highCount == periodCount) { + /* Set OFLAG output on compare */ + reg |= (TMR_CTRL_LENGTH_MASK | TMR_CTRL_OUTMODE(kQTMR_SetOnCompare)); + } else if (periodCount == 0U) { + /* Clear OFLAG output on compare */ + reg |= (TMR_CTRL_LENGTH_MASK | TMR_CTRL_OUTMODE(kQTMR_ClearOnCompare)); + } else { + /* Toggle OFLAG output using alternating compare register */ + reg |= (TMR_CTRL_LENGTH_MASK | TMR_CTRL_OUTMODE(kQTMR_ToggleOnAltCompareReg)); + } + + config->base->CHANNEL[channel].CTRL = reg; + + QTMR_StartTimer(config->base, channel, kQTMR_PriSrcRiseEdge); + + k_mutex_unlock(&data->lock); + + return 0; +} + +static int mcux_qtmr_pwm_get_cycles_per_sec(const struct device *dev, uint32_t channel, + uint64_t *cycles) +{ + const struct pwm_mcux_qtmr_config *config = dev->config; + uint32_t clock_freq; + + if (clock_control_get_rate(config->clock_dev, config->clock_subsys, &clock_freq)) { + return -EINVAL; + } + + *cycles = clock_freq / config->prescaler; + + return 0; +} + +static int mcux_qtmr_pwm_init(const struct device *dev) +{ + const struct pwm_mcux_qtmr_config *config = dev->config; + struct pwm_mcux_qtmr_data *data = dev->data; + qtmr_config_t qtmr_config; + int err; + + err = pinctrl_apply_state(config->pincfg, PINCTRL_STATE_DEFAULT); + if (err) { + return err; + } + + k_mutex_init(&data->lock); + + QTMR_GetDefaultConfig(&qtmr_config); + qtmr_config.primarySource = kQTMR_ClockDivide_1 + (31 - __builtin_clz(config->prescaler)); + + for (int i = 0; i < CHANNEL_COUNT; i++) { + QTMR_Init(config->base, i, &qtmr_config); + } + + return 0; +} + +static const struct pwm_driver_api pwm_mcux_qtmr_driver_api = { + .set_cycles = mcux_qtmr_pwm_set_cycles, + .get_cycles_per_sec = mcux_qtmr_pwm_get_cycles_per_sec, +}; + +#define PWM_MCUX_QTMR_DEVICE_INIT(n) \ + PINCTRL_DT_INST_DEFINE(n); \ + static struct pwm_mcux_qtmr_data pwm_mcux_qtmr_data_##n; \ + \ + static const struct pwm_mcux_qtmr_config pwm_mcux_qtmr_config_##n = { \ + .base = (TMR_Type *)DT_INST_REG_ADDR(n), \ + .prescaler = DT_INST_PROP(n, prescaler), \ + .pincfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n), \ + .clock_dev = DEVICE_DT_GET(DT_INST_CLOCKS_CTLR(n)), \ + .clock_subsys = (clock_control_subsys_t)DT_INST_CLOCKS_CELL(n, name), \ + }; \ + \ + DEVICE_DT_INST_DEFINE(n, mcux_qtmr_pwm_init, NULL, &pwm_mcux_qtmr_data_##n, \ + &pwm_mcux_qtmr_config_##n, POST_KERNEL, CONFIG_PWM_INIT_PRIORITY, \ + &pwm_mcux_qtmr_driver_api); + +DT_INST_FOREACH_STATUS_OKAY(PWM_MCUX_QTMR_DEVICE_INIT) diff --git a/dts/bindings/pwm/nxp,qtmr-pwm.yaml b/dts/bindings/pwm/nxp,qtmr-pwm.yaml new file mode 100644 index 0000000000000..587c32e3c4a7d --- /dev/null +++ b/dts/bindings/pwm/nxp,qtmr-pwm.yaml @@ -0,0 +1,23 @@ +# Copyright (c) 2024, NXP +# SPDX-License-Identifier: Apache-2.0 + +description: NXP QTMR PWM + +compatible: "nxp,qtmr-pwm" + +include: [pwm-controller.yaml, pinctrl-device.yaml, base.yaml] + +properties: + prescaler: + type: int + required: true + description: prescale factor from the qtmr clock. + enum: [1, 2, 4, 8, 16, 32, 64, 128] + + "#pwm-cells": + const: 3 + +pwm-cells: + - channel + - period + - flags From af52f1b290d34a2c83f1bcdcc21b72acad1c6277 Mon Sep 17 00:00:00 2001 From: Peter van der Perk Date: Tue, 28 May 2024 17:12:20 +0200 Subject: [PATCH 1880/2849] clock: mcux_ccm: add qtmr clock Add defines for QTMR peripheral Signed-off-by: Peter van der Perk --- drivers/clock_control/clock_control_mcux_ccm_rev2.c | 9 +++++++++ include/zephyr/dt-bindings/clock/imx_ccm_rev2.h | 7 +++++++ 2 files changed, 16 insertions(+) diff --git a/drivers/clock_control/clock_control_mcux_ccm_rev2.c b/drivers/clock_control/clock_control_mcux_ccm_rev2.c index f3e7c59aea36c..28389a4a22852 100644 --- a/drivers/clock_control/clock_control_mcux_ccm_rev2.c +++ b/drivers/clock_control/clock_control_mcux_ccm_rev2.c @@ -139,6 +139,15 @@ static int mcux_ccm_get_subsys_rate(const struct device *dev, break; #endif +#ifdef CONFIG_PWM_MCUX_QTMR + case IMX_CCM_QTMR1_CLK: + case IMX_CCM_QTMR2_CLK: + case IMX_CCM_QTMR3_CLK: + case IMX_CCM_QTMR4_CLK: + clock_root = kCLOCK_Root_Bus; + break; +#endif + #ifdef CONFIG_MEMC_MCUX_FLEXSPI case IMX_CCM_FLEXSPI_CLK: clock_root = kCLOCK_Root_Flexspi1; diff --git a/include/zephyr/dt-bindings/clock/imx_ccm_rev2.h b/include/zephyr/dt-bindings/clock/imx_ccm_rev2.h index f21844a149047..75369dc92e9b1 100644 --- a/include/zephyr/dt-bindings/clock/imx_ccm_rev2.h +++ b/include/zephyr/dt-bindings/clock/imx_ccm_rev2.h @@ -114,4 +114,11 @@ #define IMX_CCM_TPM5_CLK 0x1604UL #define IMX_CCM_TPM6_CLK 0x1605UL +/* QTMR */ +#define IMX_CCM_QTMR_CLK 0x6000UL +#define IMX_CCM_QTMR1_CLK 0x6000UL +#define IMX_CCM_QTMR2_CLK 0x6001UL +#define IMX_CCM_QTMR3_CLK 0x6002UL +#define IMX_CCM_QTMR4_CLK 0x6003UL + #endif /* ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_IMX_CCM_REV2_H_ */ From 49e7944d595c6007d59617ae29abc80408d9bd22 Mon Sep 17 00:00:00 2001 From: Peter van der Perk Date: Tue, 28 May 2024 17:13:25 +0200 Subject: [PATCH 1881/2849] soc: nxp: rt11xx: Enable NXP QTMR Adds QTMR dts entries Signed-off-by: Peter van der Perk --- dts/arm/nxp/nxp_rt11xx.dtsi | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/dts/arm/nxp/nxp_rt11xx.dtsi b/dts/arm/nxp/nxp_rt11xx.dtsi index a118ba0fb38ed..6df4cd1e27819 100644 --- a/dts/arm/nxp/nxp_rt11xx.dtsi +++ b/dts/arm/nxp/nxp_rt11xx.dtsi @@ -164,6 +164,38 @@ clocks = <&ccm IMX_CCM_GPT_CLK 0x45 0>; }; + qtmr1: qtmr@4015c000 { + compatible = "nxp,qtmr-pwm"; + reg = <0x4015c000 0x4000>; + interrupts = <171 0>; + status = "disabled"; + clocks = <&ccm IMX_CCM_QTMR1_CLK 0x0 0>; + }; + + qtmr2: qtmr@40160000 { + compatible = "nxp,qtmr-pwm"; + reg = <0x40160000 0x4000>; + interrupts = <172 0>; + status = "disabled"; + clocks = <&ccm IMX_CCM_QTMR2_CLK 0x0 0>; + }; + + qtmr3: qtmr@40164000 { + compatible = "nxp,qtmr-pwm"; + reg = <0x40164000 0x4000>; + interrupts = <173 0>; + status = "disabled"; + clocks = <&ccm IMX_CCM_QTMR3_CLK 0x0 0>; + }; + + qtmr4: qtmr@40168000 { + compatible = "nxp,qtmr-pwm"; + reg = <0x40168000 0x4000>; + interrupts = <174 0>; + status = "disabled"; + clocks = <&ccm IMX_CCM_QTMR4_CLK 0x0 0>; + }; + ccm: ccm@40cc0000 { compatible = "nxp,imx-ccm-rev2"; reg = <0x40cc0000 0x4000>; From 0eee622621ccf70a819941dd44dd9093aa467832 Mon Sep 17 00:00:00 2001 From: Peter van der Perk Date: Tue, 28 May 2024 17:15:08 +0200 Subject: [PATCH 1882/2849] boards: nxp: vmu_rt1170: Add Buzzer and QTMR entries Allows to control buzzer with QTMR PWM Signed-off-by: Peter van der Perk --- boards/nxp/vmu_rt1170/vmu_rt1170-pinctrl.dtsi | 8 ++++++++ .../vmu_rt1170/vmu_rt1170_mimxrt1176_cm7.dts | 17 +++++++++++++++++ 2 files changed, 25 insertions(+) diff --git a/boards/nxp/vmu_rt1170/vmu_rt1170-pinctrl.dtsi b/boards/nxp/vmu_rt1170/vmu_rt1170-pinctrl.dtsi index e7ab7ce896b55..1390fb6805839 100644 --- a/boards/nxp/vmu_rt1170/vmu_rt1170-pinctrl.dtsi +++ b/boards/nxp/vmu_rt1170/vmu_rt1170-pinctrl.dtsi @@ -156,6 +156,14 @@ }; }; + pinmux_qtmr_pwm_buzzer: pinmux_qtmr_pwm_buzzer { + group0 { + pinmux = <&iomuxc_gpio_emc_b2_09_qtimer1_timer0>; + drive-strength = "high"; + slew-rate = "fast"; + }; + }; + pinmux_lpadc1: pinmux_lpadc1 { group0 { pinmux = <&iomuxc_gpio_ad_10_adc1_ch2a>; diff --git a/boards/nxp/vmu_rt1170/vmu_rt1170_mimxrt1176_cm7.dts b/boards/nxp/vmu_rt1170/vmu_rt1170_mimxrt1176_cm7.dts index c2ea2f474967b..c3e84a3fbf13b 100644 --- a/boards/nxp/vmu_rt1170/vmu_rt1170_mimxrt1176_cm7.dts +++ b/boards/nxp/vmu_rt1170/vmu_rt1170_mimxrt1176_cm7.dts @@ -21,6 +21,7 @@ watchdog0 = &wdog1; sdhc0 = &usdhc1; sw0 = &arming_button; + pwm-led0 = &buzzer0; }; chosen { @@ -121,6 +122,13 @@ regulator-always-on; status = "okay"; }; + + pwm_shell: pwm_shell { + compatible = "pwm-leds"; + buzzer0: buzzer0 { + pwms = <&qtmr1 0 PWM_HZ(50) PWM_POLARITY_NORMAL>; + }; + }; }; @@ -392,6 +400,15 @@ capture-channel = <1>; }; +&qtmr1 { + compatible = "nxp,qtmr-pwm"; + pinctrl-0 = <&pinmux_qtmr_pwm_buzzer>; + pinctrl-names = "default"; + #pwm-cells = <3>; + prescaler = <128>; + status = "okay"; +}; + &usdhc1 { status = "okay"; no-1-8-v; From 388ca7febd586458c0a61e6eaaaeb9790e40b1f8 Mon Sep 17 00:00:00 2001 From: Peter van der Perk Date: Tue, 28 May 2024 17:15:37 +0200 Subject: [PATCH 1883/2849] vmu_rt1170: update docs Add QTMR and FlexTimer peripherals, update pinmuxing Signed-off-by: Peter van der Perk --- boards/nxp/vmu_rt1170/doc/index.rst | 398 +++++++++++++++++++++++----- 1 file changed, 332 insertions(+), 66 deletions(-) diff --git a/boards/nxp/vmu_rt1170/doc/index.rst b/boards/nxp/vmu_rt1170/doc/index.rst index a683fc8ad1ed4..c98d867d5677a 100644 --- a/boards/nxp/vmu_rt1170/doc/index.rst +++ b/boards/nxp/vmu_rt1170/doc/index.rst @@ -94,7 +94,7 @@ following hardware features: +-----------+------------+-------------------------------------+ | I2C | on-chip | i2c | +-----------+------------+-------------------------------------+ -| PWM | on-chip | pwm | +| PWM | on-chip | flexpwm, qtmr | +-----------+------------+-------------------------------------+ | ADC | on-chip | adc | +-----------+------------+-------------------------------------+ @@ -134,71 +134,337 @@ Connections and I/Os The MIMXRT1170 SoC has six pairs of pinmux/gpio controllers. -+---------------------------+----------------+------------------+ -| Name | Function | Usage | -+---------------------------+----------------+------------------+ -| WAKEUP | GPIO | SW7 | -+---------------------------+----------------+------------------+ -| GPIO_AD_04 | GPIO | LED | -+---------------------------+----------------+------------------+ -| GPIO_AD_24 | LPUART1_TX | UART Console | -+---------------------------+----------------+------------------+ -| GPIO_AD_25 | LPUART1_RX | UART Console | -+---------------------------+----------------+------------------+ -| GPIO_LPSR_00 | CAN3_TX | flexcan | -+---------------------------+----------------+------------------+ -| GPIO_LPSR_01 | CAN3_RX | flexcan | -+---------------------------+----------------+------------------+ -| GPIO_AD_29 | SPI1_CS0 | spi | -+---------------------------+----------------+------------------+ -| GPIO_AD_28 | SPI1_CLK | spi | -+---------------------------+----------------+------------------+ -| GPIO_AD_30 | SPI1_SDO | spi | -+---------------------------+----------------+------------------+ -| GPIO_AD_31 | SPI1_SDI | spi | -+---------------------------+----------------+------------------+ -| GPIO_AD_08 | LPI2C1_SCL | i2c | -+---------------------------+----------------+------------------+ -| GPIO_AD_09 | LPI2C1_SDA | i2c | -+---------------------------+----------------+------------------+ -| GPIO_LPSR_05 | LPI2C5_SCL | i2c | -+---------------------------+----------------+------------------+ -| GPIO_LPSR_04 | LPI2C5_SDA | i2c | -+---------------------------+----------------+------------------+ -| GPIO_AD_04 | FLEXPWM1_PWM2 | pwm | -+---------------------------+----------------+------------------+ -| GPIO_AD_32 | ENET_MDC | Ethernet | -+---------------------------+----------------+------------------+ -| GPIO_AD_33 | ENET_MDIO | Ethernet | -+---------------------------+----------------+------------------+ -| GPIO_DISP_B2_02 | ENET_TX_DATA00 | Ethernet | -+---------------------------+----------------+------------------+ -| GPIO_DISP_B2_03 | ENET_TX_DATA01 | Ethernet | -+---------------------------+----------------+------------------+ -| GPIO_DISP_B2_04 | ENET_TX_EN | Ethernet | -+---------------------------+----------------+------------------+ -| GPIO_DISP_B2_05 | ENET_REF_CLK | Ethernet | -+---------------------------+----------------+------------------+ -| GPIO_DISP_B2_06 | ENET_RX_DATA00 | Ethernet | -+---------------------------+----------------+------------------+ -| GPIO_DISP_B2_07 | ENET_RX_DATA01 | Ethernet | -+---------------------------+----------------+------------------+ -| GPIO_DISP_B2_08 | ENET_RX_EN | Ethernet | -+---------------------------+----------------+------------------+ -| GPIO_DISP_B2_09 | ENET_RX_ER | Ethernet | -+---------------------------+----------------+------------------+ -| GPIO_AD_17_SAI1_MCLK | SAI_MCLK | SAI | -+---------------------------+----------------+------------------+ -| GPIO_AD_21_SAI1_TX_DATA00 | SAI1_TX_DATA | SAI | -+---------------------------+----------------+------------------+ -| GPIO_AD_22_SAI1_TX_BCLK | SAI1_TX_BCLK | SAI | -+---------------------------+----------------+------------------+ -| GPIO_AD_23_SAI1_TX_SYNC | SAI1_TX_SYNC | SAI | -+---------------------------+----------------+------------------+ -| GPIO_AD_17_SAI1_MCLK | SAI1_MCLK | SAI | -+---------------------------+----------------+------------------+ -| GPIO_AD_20_SAI1_RX_DATA00 | SAI1_RX_DATA00 | SAI | -+---------------------------+----------------+------------------+ ++-----------------+--------------------------------+----------------------------+ +| Name | Function | Usage | ++-----------------+--------------------------------+----------------------------+ +| GPIO_AD_00 | FLEXCAN2_TX | CAN2_TX | ++-----------------+--------------------------------+----------------------------+ +| GPIO_AD_01 | FLEXCAN2_RX | CAN2_RX | ++-----------------+--------------------------------+----------------------------+ +| GPIO_AD_02 | LPUART8_TXD | UART8_TX_TELEM2 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_AD_03 | LPUART8_RXD | UART8_RX_TELEM2 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_AD_04 | LPUART8_CTS_B | UART8_CTS_TELEM2 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_AD_05 | LPUART8_RTS_B | UART8_RTS_TELEM2 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_AD_06 | FLEXCAN1_TX | CAN1_TX | ++-----------------+--------------------------------+----------------------------+ +| GPIO_AD_07 | FLEXCAN1_RX | CAN1_RX | ++-----------------+--------------------------------+----------------------------+ +| GPIO_AD_08 | LPI2C1_SCL | I2C1_SCL_GPS1 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_AD_09 | LPI2C1_SDA | I2C1_SDA_GPS1 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_AD_10 | LPADC1_CH2A | SCALED_VDD_3V3_SENSORS1 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_AD_11 | LPADC1_CH2B | SCALED_VDD_3V3_SENSORS2 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_AD_12 | LPADC1_CH3A | SCALED_VDD_3V3_SENSORS3 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_AD_13 | LPADC1_CH3B | SCALED_V5 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_AD_14 | LPADC1_CH4A | ADC_6V6 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_AD_15 | LPUART10_TXD | UART10_TX_TELEM3 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_AD_16 | LPADC1_CH5A | ADC_3V3 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_AD_17 | LPADC1_CHB | SCALED_VDD_3V3_SENSORS4 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_AD_18 | LPI2C2_SCL | I2C2_SCL_GPS2 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_AD_19 | LPI2C2_SDA | I2C2_SDA_GPS2 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_AD_20 | GPIO3_IO19 | SPI1_DRDY1_SENSOR1 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_AD_21 | GPIO3_IO20 | SPI3_DRDY1_SENSOR3 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_AD_22 | LPADC2_CH2A | HW_VER_SENSE | ++-----------------+--------------------------------+----------------------------+ +| GPIO_AD_23 | LPADC2_CH2B | HW_REV_SENSE | ++-----------------+--------------------------------+----------------------------+ +| GPIO_AD_24 | LPSPI2_SCK | SPI2_SCK_SENSOR2 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_AD_25 | LPSPI2_PCS0 | SPI2_nCS0_SENSOR2 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_AD_26 | LPSPI2_SOUT | SPI2_MOSI_SENSOR2 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_AD_27 | LPSPI2_SIN | SPI2_MISO_SENSOR2 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_AD_28 | LPUART5_TXD | UART5_TX_GPS2 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_AD_29 | LPUART5_RXD | UART5_RX_GPS2 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_AD_30 | LPUART3_TXD | UART3_TX_GPS1 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_AD_31 | LPUART3_RXD | UART3_RX_GPS1 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_AD_32 | USDHC1_CD_B | USDHC1_CD | ++-----------------+--------------------------------+----------------------------+ +| GPIO_AD_33 | LPUART10_RXD | UART10_RX_TELEM3 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_AD_34 | LPUART10_CTS_B | UART10_CTS_TELEM3 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_AD_35 | LPUART10_RTS_B | UART10_RTS_TELEM3 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_DISP_B1_00 | ENET_1G_RX_EN | ETH_CRS_DV | ++-----------------+--------------------------------+----------------------------+ +| GPIO_DISP_B1_01 | ENET_1G_RX_ER | ETH_RX_ER | ++-----------------+--------------------------------+----------------------------+ +| GPIO_DISP_B1_02 | LPUART1_TXD | UART1_TX_DEBUG | ++-----------------+--------------------------------+----------------------------+ +| GPIO_DISP_B1_03 | LPUART1_RXD | UART1_RX_DEBUG | ++-----------------+--------------------------------+----------------------------+ +| GPIO_DISP_B1_04 | LPUART4_RXD | UART4_RX_TELEM1 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_DISP_B1_05 | LPUART4_CTS_B | UART4_CTS_TELEM1 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_DISP_B1_06 | LPUART4_TXD | UART4_TX_TELEM1 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_DISP_B1_07 | LPUART4_RTS_B | UART4_RTS_TELEM1 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_DISP_B1_08 | ENET_1G_TDATA1 | ETH_TXD1 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_DISP_B1_09 | ENET_1G_TDATA0 | ETH_TXD0 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_DISP_B1_10 | ENET_1G_TX_EN | ETH_TX_EN | ++-----------------+--------------------------------+----------------------------+ +| GPIO_DISP_B1_11 | ENET_1G_REF_CLK | ETH_REF_CLK | ++-----------------+--------------------------------+----------------------------+ +| GPIO_DISP_B2_00 | GPIO5_IO01 | nLED_RED | ++-----------------+--------------------------------+----------------------------+ +| GPIO_DISP_B2_01 | GPIO5_IO02 | nLED_GREEN | ++-----------------+--------------------------------+----------------------------+ +| GPIO_DISP_B2_02 | ARM_TRACE0 | TRACED0 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_DISP_B2_03 | ARM_TRACE1 | TRACED1 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_DISP_B2_04 | ARM_TRACE2 | TRACED2 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_DISP_B2_05 | ARM_TRACE3 | TRACED3 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_DISP_B2_06 | ARM_TRACE_CLK | TRACECLK | ++-----------------+--------------------------------+----------------------------+ +| GPIO_DISP_B2_07 | ARM_TRACE_SWO | TRACESWO | ++-----------------+--------------------------------+----------------------------+ +| GPIO_DISP_B2_08 | GPIO5_IO09 | ETH_POWER_EN | ++-----------------+--------------------------------+----------------------------+ +| GPIO_DISP_B2_09 | GPIO5_IO10 | ETH_PHY_nINT | ++-----------------+--------------------------------+----------------------------+ +| GPIO_DISP_B2_10 | LPI2C3_SCL | I2C3_SCL_FMU | ++-----------------+--------------------------------+----------------------------+ +| GPIO_DISP_B2_11 | LPI2C3_SDA | I2C3_SDA_FMU | ++-----------------+--------------------------------+----------------------------+ +| GPIO_DISP_B2_12 | LPSPI4_SCK | SPI4_SCK_SENSOR4 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_DISP_B2_13 | LPSPI4_SIN | SPI4_MISO_SENSOR4 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_DISP_B2_14 | LPSPI4_SOUT | SPI4_MOSI_SENSOR4 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_DISP_B2_15 | LPSPI4_PCS0 | SPI4_nCS0_SENSOR4 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_EMC_B1_00 | FLEXPWM4_PWM0_A + FLEXIO1_IO00 | FMU_CH11 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_EMC_B1_01 | GPIO1_IO01 | VDD_3V3_SD_CARD_EN | ++-----------------+--------------------------------+----------------------------+ +| GPIO_EMC_B1_02 | FLEXPWM4_PWM1_A + FLEXIO1_IO02 | FMU_CH12 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_EMC_B1_03 | GPIO1_IO03 | FMU_nSAFETY_SWITCH_LED_OUT | ++-----------------+--------------------------------+----------------------------+ +| GPIO_EMC_B1_04 | GPIO1_IO04 | NFC_GPIO | ++-----------------+--------------------------------+----------------------------+ +| GPIO_EMC_B1_05 | GPIO1_IO05 | SPI6_DRDY1_EXTERNAL1 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_EMC_B1_06 | FLEXPWM2_PWM0_A + FLEXIO1_IO06 | FMU_CH4 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_EMC_B1_07 | GPIO1_IO07 | SPI6_DRDY2_EXTERNAL1 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_EMC_B1_08 | FLEXPWM2_PWM1_A + FLEXIO1_IO08 | FMU_CH5 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_EMC_B1_09 | GPT5_CAPTURE1 | FMU_PPM_INPUT | ++-----------------+--------------------------------+----------------------------+ +| GPIO_EMC_B1_10 | FLEXPWM2_PWM2_A + FLEXIO1_IO10 | FMU_CH6 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_EMC_B1_11 | GPIO1_IO11 | SPI6_nRESET_EXTERNAL1 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_EMC_B1_12 | GPIO1_IO12 | VDD_5V_HIPOWER_nOC | ++-----------------+--------------------------------+----------------------------+ +| GPIO_EMC_B1_13 | GPIO1_IO13 | nLED_BLUE | ++-----------------+--------------------------------+----------------------------+ +| GPIO_EMC_B1_14 | GPIO1_IO14 | VDD_3V3_SENSORS3_EN | ++-----------------+--------------------------------+----------------------------+ +| GPIO_EMC_B1_15 | GPIO1_IO15 | VDD_5V_PERIPH_nOC | ++-----------------+--------------------------------+----------------------------+ +| GPIO_EMC_B1_16 | GPIO1_IO16 | SPI4_DRDY1_SENSOR4 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_EMC_B1_17 | GPIO1_IO17 | nARMED | ++-----------------+--------------------------------+----------------------------+ +| GPIO_EMC_B1_18 | TMR2_TIMER0 | SPIX_SYNC | ++-----------------+--------------------------------+----------------------------+ +| GPIO_EMC_B1_19 | FLEXPWM2_PWM3_A + FLEXIO1_IO19 | FMU_CH7 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_EMC_B1_20 | TMR4_TIMER0 | FMU_CAP1 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_EMC_B1_21 | FLEXPWM3_PWM3_A + FLEXIO1_IO21 | FMU_CH10 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_EMC_B1_22 | GPIO1_IO22 | VDD_3V3_SENSORS2_EN | ++-----------------+--------------------------------+----------------------------+ +| GPIO_EMC_B1_23 | FLEXPWM1_PWM0_A | FMU_CH1 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_EMC_B1_24 | GPIO1_IO24 | FMU_SAFETY_SWITCH_IN | ++-----------------+--------------------------------+----------------------------+ +| GPIO_EMC_B1_25 | FLEXPWM1_PWM1_A + FLEXIO1_IO25 | FMU_CH2 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_EMC_B1_26 | GPIO1_IO26 | HW_VER_REV_DRIVE | ++-----------------+--------------------------------+----------------------------+ +| GPIO_EMC_B1_27 | FLEXPWM1_PWM2_A + FLEXIO1_IO27 | FMU_CH3 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_EMC_B1_28 | GPIO1_IO28 | nPOWER_IN_A | ++-----------------+--------------------------------+----------------------------+ +| GPIO_EMC_B1_29 | FLEXPWM3_PWM0_A + FLEXIO1_IO29 | FMU_CH8 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_EMC_B1_30 | GPIO1_IO30 | nPOWER_IN_B | ++-----------------+--------------------------------+----------------------------+ +| GPIO_EMC_B1_31 | FLEXPWM3_PWM1_A + FLEXIO1_IO31 | FMU_CH9 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_EMC_B1_32 | GPIO2_IO00 | nPOWER_IN_C | ++-----------------+--------------------------------+----------------------------+ +| GPIO_EMC_B1_33 | GPIO2_IO01 | VDD_3V3_SENSORS1_EN | ++-----------------+--------------------------------+----------------------------+ +| GPIO_EMC_B1_34 | GPIO2_IO02 | VDD_5V_PERIPH_nEN | ++-----------------+--------------------------------+----------------------------+ +| GPIO_EMC_B1_35 | GPIO2_IO03 | I2C2_DRDY1 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_EMC_B1_36 | GPIO2_IO04 | VDD_3V3_SENSORS4_EN | ++-----------------+--------------------------------+----------------------------+ +| GPIO_EMC_B1_37 | GPIO2_IO05 | VDD_5V_HIPOWER_nEN | ++-----------------+--------------------------------+----------------------------+ +| GPIO_EMC_B1_38 | GPIO2_IO06 | VDD_3V3_SPEKTRUM_POWER_EN | ++-----------------+--------------------------------+----------------------------+ +| GPIO_EMC_B1_39 | GPIO2_IO07 | SPI2_DRDY1_SENSOR2 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_EMC_B1_40 | LPUART6_TXD | UART6_TX_TO_IO__RC_INPUT | ++-----------------+--------------------------------+----------------------------+ +| GPIO_EMC_B1_41 | LPUART6_RXD | UART6_RX_FROM_IO__NC | ++-----------------+--------------------------------+----------------------------+ +| GPIO_EMC_B2_00 | LPSPI1_SCK | SPI1_SCK_SENSOR1 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_EMC_B2_01 | LPSPI1_PCS0 | SPI1_nCS0_SENSOR1 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_EMC_B2_02 | LPSPI1_SOUT | SPI1_MOSI_SENSOR1 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_EMC_B2_03 | LPSPI1_SIN | SPI1_MISO_SENSOR1 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_EMC_B2_04 | LPSPI3_SCK | SPI3_SCK_SENSOR3 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_EMC_B2_05 | LPSPI3_PCS0 | SPI3_nCS0_SENSOR3 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_EMC_B2_06 | LPSPI3_SOUT | SPI3_MOSI_SENSOR3 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_EMC_B2_07 | LPSPI3_SIN | SPI3_MISO_SENSOR3 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_EMC_B2_08 | LPSPI3_PCS1 | SPI3_nCS1_SENSOR3 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_EMC_B2_09 | TMR1_TIMER0 | BUZZER_1 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_EMC_B2_10 | FLEXSPI2_A_SCLK | FLEXSPI2_SCK_FRAM | ++-----------------+--------------------------------+----------------------------+ +| GPIO_EMC_B2_11 | FLEXSPI2_A_SS0_B | FLEXSPI2_nCS0_FRAM | ++-----------------+--------------------------------+----------------------------+ +| GPIO_EMC_B2_12 | GPIO2_IO22 | GPIO_EMC_B2_12 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_EMC_B2_13 | FLEXSPI2_A_DATA0 | FLEXSPI2_DATA0_FRAM | ++-----------------+--------------------------------+----------------------------+ +| GPIO_EMC_B2_14 | FLEXSPI2_A_DATA1 | FLEXSPI2_DATA1_FRAM | ++-----------------+--------------------------------+----------------------------+ +| GPIO_EMC_B2_15 | ENET_1G_RDATA0 | ETH_RXD0 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_EMC_B2_16 | ENET_1G_RDATA1 | ETH_RXD1 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_EMC_B2_17 | TMR3_TIMER0 | HEATER | ++-----------------+--------------------------------+----------------------------+ +| GPIO_EMC_B2_18 | GPIO2_IO28 | SPI3_DRDY2_SENSOR3 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_EMC_B2_19 | ENET_1G_MDC | ETH_MDC | ++-----------------+--------------------------------+----------------------------+ +| GPIO_EMC_B2_20 | ENET_1G_MDIO | ETH_MDIO | ++-----------------+--------------------------------+----------------------------+ +| GPIO_LPSR_00 | FLEXCAN3_TX | CAN3_TX | ++-----------------+--------------------------------+----------------------------+ +| GPIO_LPSR_01 | FLEXCAN3_RX | CAN3_RX | ++-----------------+--------------------------------+----------------------------+ +| GPIO_LPSR_02 | SRC_BOOT_MODE00 | BT_MODE0 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_LPSR_03 | SRC_BOOT_MODE01 | BT_MODE1 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_LPSR_04 | LPUART11_TXD | UART11_TX_EXTERNAL2 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_LPSR_05 | LPUART11_RXD | UART11_RX_EXTERNAL2 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_LPSR_06 | LPI2C6_SDA | I2C6_SDA_EXTERNAL2 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_LPSR_07 | LPI2C6_SCL | I2C6_SCL_EXTERNAL2 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_LPSR_08 | LPSPI6_PCS1 | SPI6_nCS1_EXTERNAL1 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_LPSR_09 | LPSPI6_PCS0 | SPI6_nCS0 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_LPSR_10 | LPSPI6_SCK | SPI6_SCK_EXTERNAL1 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_LPSR_11 | LPSPI6_SOUT | SPI6_MOSI_EXTERNAL1 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_LPSR_12 | LPSPI6_SIN | SPI6_MISO_EXTERNAL1 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_LPSR_13 | JTAG_MOD | NC_JTAG_MOD_PD | ++-----------------+--------------------------------+----------------------------+ +| GPIO_LPSR_14 | SWD_CLK | FMU_SWCLK | ++-----------------+--------------------------------+----------------------------+ +| GPIO_LPSR_15 | SWD_DIO | FMU_SWDIO | ++-----------------+--------------------------------+----------------------------+ +| GPIO_SD_B1_00 | USDHC1_CMD | USDHC1_CMD | ++-----------------+--------------------------------+----------------------------+ +| GPIO_SD_B1_01 | USDHC1_CLK | USDHC1_CLK | ++-----------------+--------------------------------+----------------------------+ +| GPIO_SD_B1_02 | USDHC1_DATA0 | USDHC1_DATA0 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_SD_B1_03 | USDHC1_DATA1 | USDHC1_DATA1 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_SD_B1_04 | USDHC1_DATA2 | USDHC1_DATA2 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_SD_B1_05 | USDHC1_DATA3 | USDHC1_DATA3 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_SD_B2_00 | FLEXSPI1_B_DATA3 | FLEXSPI1_DATA7_HYPERFLASH | ++-----------------+--------------------------------+----------------------------+ +| GPIO_SD_B2_01 | FLEXSPI1_B_DATA2 | FLEXSPI1_DATA6_HYPERFLASH | ++-----------------+--------------------------------+----------------------------+ +| GPIO_SD_B2_02 | FLEXSPI1_B_DATA1 | FLEXSPI1_DATA5_HYPERFLASH | ++-----------------+--------------------------------+----------------------------+ +| GPIO_SD_B2_03 | FLEXSPI1_B_DATA0 | FLEXSPI1_DATA4_HYPERFLASH | ++-----------------+--------------------------------+----------------------------+ +| GPIO_SD_B2_04 | FLEXSPI1_B_SCLK | FLEXSPI1_nSCK_HYPERFLASH | ++-----------------+--------------------------------+----------------------------+ +| GPIO_SD_B2_05 | FLEXSPI1_A_DQS | FLEXSPI1_DQS_HYPERFLASH | ++-----------------+--------------------------------+----------------------------+ +| GPIO_SD_B2_06 | FLEXSPI1_A_SS0_B | FLEXSPI1_nCS0_HYPERFLASH | ++-----------------+--------------------------------+----------------------------+ +| GPIO_SD_B2_07 | FLEXSPI1_A_SCLK | FLEXSPI1_SCK_HYPERFLASH | ++-----------------+--------------------------------+----------------------------+ +| GPIO_SD_B2_08 | FLEXSPI1_A_DATA0 | FLEXSPI1_DATA0_HYPERFLASH | ++-----------------+--------------------------------+----------------------------+ +| GPIO_SD_B2_09 | FLEXSPI1_A_DATA0 | FLEXSPI1_DATA1_HYPERFLASH | ++-----------------+--------------------------------+----------------------------+ +| GPIO_SD_B2_10 | FLEXSPI1_A_DATA2 | FLEXSPI1_DATA2_HYPERFLASH | ++-----------------+--------------------------------+----------------------------+ +| GPIO_SD_B2_11 | FLEXSPI1_A_DATA3 | FLEXSPI1_DATA3_HYPERFLASH | ++-----------------+--------------------------------+----------------------------+ +| USB1_DN | USB_OG1_DN | USB_D_N | ++-----------------+--------------------------------+----------------------------+ +| USB1_DP | USB_OTG1_DP | USB_D_P | ++-----------------+--------------------------------+----------------------------+ +| USB1_VBUS | USB_OTG1_VBUS | VBUS | ++-----------------+--------------------------------+----------------------------+ Serial Port =========== From 76ced4a82d9bd89c55c5221b4e15be7b295ae3e9 Mon Sep 17 00:00:00 2001 From: Tim Lin Date: Wed, 29 May 2024 20:44:15 +0800 Subject: [PATCH 1884/2849] drivers: pinctrl: ITE: Add a property configure pin current strength Add the property of drive-strength to drive a high or low current selection. If this property is not configured, it is the default setting. According to the SPEC, the default drive current selection varies from different pins. Define the high level 0b: 8mA low level 1b: 4mA or 2mA Signed-off-by: Tim Lin --- drivers/pinctrl/pinctrl_ite_it8xxx2.c | 16 ++++++++ dts/bindings/pinctrl/ite,it8xxx2-pinctrl.yaml | 13 +++++++ dts/riscv/ite/it81xx2.dtsi | 39 ++++++++++++------- dts/riscv/ite/it82xx2.dtsi | 39 ++++++++++++------- soc/ite/ec/common/pinctrl_soc.h | 18 ++++++++- 5 files changed, 98 insertions(+), 27 deletions(-) diff --git a/drivers/pinctrl/pinctrl_ite_it8xxx2.c b/drivers/pinctrl/pinctrl_ite_it8xxx2.c index 33ed9130b62e2..f7d71adc43e5f 100644 --- a/drivers/pinctrl/pinctrl_ite_it8xxx2.c +++ b/drivers/pinctrl/pinctrl_ite_it8xxx2.c @@ -20,6 +20,8 @@ LOG_MODULE_REGISTER(pinctrl_ite_it8xxx2, LOG_LEVEL_ERR); struct pinctrl_it8xxx2_gpio { /* gpio port control register (byte mapping to pin) */ uint8_t *reg_gpcr; + /* port driving select control */ + uint8_t *reg_pdsc; /* function 3 general control register */ uintptr_t func3_gcr[GPIO_GROUP_MEMBERS]; /* function 3 enable mask */ @@ -74,6 +76,7 @@ static int pinctrl_it8xxx2_set(const pinctrl_soc_pin_t *pins) uint8_t pin = pins->pin; volatile uint8_t *reg_gpcr = (uint8_t *)gpio->reg_gpcr + pin; volatile uint8_t *reg_volt_sel = (uint8_t *)(gpio->volt_sel[pin]); + volatile uint8_t *reg_pdsc = (uint8_t *)gpio->reg_pdsc; /* Setting pull-up or pull-down. */ switch (IT8XXX2_DT_PINCFG_PUPDR(pincfg)) { @@ -125,6 +128,18 @@ static int pinctrl_it8xxx2_set(const pinctrl_soc_pin_t *pins) GPCR_PORT_PIN_MODE_PULLDOWN); } + /* Driving current selection. */ + if (reg_pdsc != NULL && + IT8XXX2_DT_PINCFG_DRIVE_CURRENT(pincfg) != IT8XXX2_DRIVE_DEFAULT) { + if (IT8XXX2_DT_PINCFG_DRIVE_CURRENT(pincfg) & IT8XXX2_PDSCX_MASK) { + /* Driving current selects low. */ + *reg_pdsc |= BIT(pin); + } else { + /* Driving current selects high. */ + *reg_pdsc &= ~BIT(pin); + } + } + return 0; } @@ -366,6 +381,7 @@ static int pinctrl_it8xxx2_init(const struct device *dev) COND_CODE_1(DT_INST_PROP(inst, gpio_group), \ (.gpio = { \ .reg_gpcr = (uint8_t *)DT_INST_REG_ADDR_BY_IDX(inst, 0), \ + .reg_pdsc = (uint8_t *)DT_INST_REG_ADDR_BY_IDX(inst, 1), \ .func3_gcr = DT_INST_PROP(inst, func3_gcr), \ .func3_en_mask = DT_INST_PROP(inst, func3_en_mask), \ .func3_ext = DT_INST_PROP_OR(inst, func3_ext, {0}), \ diff --git a/dts/bindings/pinctrl/ite,it8xxx2-pinctrl.yaml b/dts/bindings/pinctrl/ite,it8xxx2-pinctrl.yaml index 01a1c758a9c55..40c688a0b8b47 100644 --- a/dts/bindings/pinctrl/ite,it8xxx2-pinctrl.yaml +++ b/dts/bindings/pinctrl/ite,it8xxx2-pinctrl.yaml @@ -96,3 +96,16 @@ child-binding: enum: - "3v3" - "1v8" + + drive-strength: + type: string + description: | + We can configure this property to drive a high or low current selection. + If this property is not configured, it is the default setting. + According to the SPEC, the default drive current selection varies from + different pins. + Define the high level 0b: 8mA + low level 1b: 4mA or 2mA + enum: + - "high" + - "low" diff --git a/dts/riscv/ite/it81xx2.dtsi b/dts/riscv/ite/it81xx2.dtsi index 252ddfe120bfd..53dd3b0cdc935 100644 --- a/dts/riscv/ite/it81xx2.dtsi +++ b/dts/riscv/ite/it81xx2.dtsi @@ -61,7 +61,8 @@ pinctrla: pinctrl@f01610 { compatible = "ite,it8xxx2-pinctrl-func"; - reg = <0x00f01610 8>; /* GPCR */ + reg = <0x00f01610 8 /* GPCR */ + NO_FUNC 1>; func3-gcr = ; func3-en-mask = <0 0 0 0 @@ -80,7 +81,8 @@ pinctrlb: pinctrl@f01618 { compatible = "ite,it8xxx2-pinctrl-func"; - reg = <0x00f01618 8>; /* GPCR */ + reg = <0x00f01618 8 /* GPCR */ + NO_FUNC 1>; func3-gcr = <0xf016f5 0xf016f5 NO_FUNC NO_FUNC NO_FUNC NO_FUNC NO_FUNC 0xf01600>; func3-en-mask = <0x01 0x02 0 0 @@ -99,7 +101,8 @@ pinctrlc: pinctrl@f01620 { compatible = "ite,it8xxx2-pinctrl-func"; - reg = <0x00f01620 8>; /* GPCR */ + reg = <0x00f01620 8 /* GPCR */ + NO_FUNC 1>; func3-gcr = ; func3-en-mask = <0 0 0 0x10 @@ -118,7 +121,8 @@ pinctrld: pinctrl@f01628 { compatible = "ite,it8xxx2-pinctrl-func"; - reg = <0x00f01628 8>; /* GPCR */ + reg = <0x00f01628 8 /* GPCR */ + NO_FUNC 1>; func3-gcr = ; func3-en-mask = <0 0 0 0 @@ -137,7 +141,8 @@ pinctrle: pinctrl@f01630 { compatible = "ite,it8xxx2-pinctrl-func"; - reg = <0x00f01630 8>; /* GPCR */ + reg = <0x00f01630 8 /* GPCR */ + NO_FUNC 1>; func3-gcr = <0xf02032 NO_FUNC NO_FUNC NO_FUNC NO_FUNC 0xf016f0 NO_FUNC 0xf02032>; func3-en-mask = <0x01 0 0 0 @@ -156,7 +161,8 @@ pinctrlf: pinctrl@f01638 { compatible = "ite,it8xxx2-pinctrl-func"; - reg = <0x00f01638 8>; /* GPCR */ + reg = <0x00f01638 8 /* GPCR */ + NO_FUNC 1>; func3-gcr = ; func3-en-mask = <0 0 0x02 0x02 @@ -175,7 +181,8 @@ pinctrlg: pinctrl@f01640 { compatible = "ite,it8xxx2-pinctrl-func"; - reg = <0x00f01640 8>; /* GPCR */ + reg = <0x00f01640 8 /* GPCR */ + NO_FUNC 1>; func3-gcr = <0xf016f0 0xf016f0 0xf016f0 NO_FUNC NO_FUNC NO_FUNC 0xf016f0 NO_FUNC>; func3-en-mask = <0x20 0x08 0x10 0 @@ -194,7 +201,8 @@ pinctrlh: pinctrl@f01648 { compatible = "ite,it8xxx2-pinctrl-func"; - reg = <0x00f01648 8>; /* GPCR */ + reg = <0x00f01648 8 /* GPCR */ + NO_FUNC 1>; func3-gcr = ; func3-en-mask = <0 0x20 0x20 0 @@ -217,7 +225,8 @@ pinctrli: pinctrl@f01650 { compatible = "ite,it8xxx2-pinctrl-func"; - reg = <0x00f01650 8>; /* GPCR */ + reg = <0x00f01650 8 /* GPCR */ + NO_FUNC 1>; func3-gcr = ; func3-en-mask = <0 0 0 0 @@ -236,7 +245,8 @@ pinctrlj: pinctrl@f01658 { compatible = "ite,it8xxx2-pinctrl-func"; - reg = <0x00f01658 8>; /* GPCR */ + reg = <0x00f01658 8 /* GPCR */ + NO_FUNC 1>; func3-gcr = <0xf016f4 NO_FUNC 0xf016f4 0xf016f4 0xf016f0 0xf016f0 NO_FUNC NO_FUNC>; func3-en-mask = <0x01 0 0x01 0x02 @@ -255,7 +265,8 @@ pinctrlk: pinctrl@f01690 { compatible = "ite,it8xxx2-pinctrl-func"; - reg = <0x00f01690 8>; /* GPCR */ + reg = <0x00f01690 8 /* GPCR */ + NO_FUNC 1>; func3-gcr = ; func3-en-mask = <0 0 0 0 @@ -274,7 +285,8 @@ pinctrll: pinctrl@f01698 { compatible = "ite,it8xxx2-pinctrl-func"; - reg = <0x00f01698 8>; /* GPCR */ + reg = <0x00f01698 8 /* GPCR */ + NO_FUNC 1>; func3-gcr = ; func3-en-mask = <0 0 0 0 @@ -293,7 +305,8 @@ pinctrlm: pinctrl@f016a0 { compatible = "ite,it8xxx2-pinctrl-func"; - reg = <0x00f016a0 8>; /* GPCR */ + reg = <0x00f016a0 8 /* GPCR */ + NO_FUNC 1>; func3-gcr = ; func3-en-mask = <0 0 0 0 diff --git a/dts/riscv/ite/it82xx2.dtsi b/dts/riscv/ite/it82xx2.dtsi index a9ab8b206cf05..4e5bae980b6b7 100644 --- a/dts/riscv/ite/it82xx2.dtsi +++ b/dts/riscv/ite/it82xx2.dtsi @@ -447,7 +447,8 @@ pinctrla: pinctrl@f01660 { compatible = "ite,it8xxx2-pinctrl-func"; - reg = <0x00f01660 8>; /* GPCR */ + reg = <0x00f01660 8 /* GPCR */ + 0x00f03e30 1>; /* PDSCA */ func3-gcr = ; func3-en-mask = <0 0 0 0 @@ -466,7 +467,8 @@ pinctrlb: pinctrl@f01668 { compatible = "ite,it8xxx2-pinctrl-func"; - reg = <0x00f01668 8>; /* GPCR */ + reg = <0x00f01668 8 /* GPCR */ + 0x00f03e31 1>; /* PDSCB */ func3-gcr = <0xf03e15 0xf03e15 0xf03e11 NO_FUNC NO_FUNC 0xf03e11 NO_FUNC NO_FUNC>; func3-en-mask = <0x01 0x02 0x20 0 @@ -489,7 +491,8 @@ pinctrlc: pinctrl@f01670 { compatible = "ite,it8xxx2-pinctrl-func"; - reg = <0x00f01670 8>; /* GPCR */ + reg = <0x00f01670 8 /* GPCR */ + 0x00f03e32 1>; /* PDSCC */ func3-gcr = ; func3-en-mask = <0 0 0 0x10 @@ -508,7 +511,8 @@ pinctrld: pinctrl@f01678 { compatible = "ite,it8xxx2-pinctrl-func"; - reg = <0x00f01678 8>; /* GPCR */ + reg = <0x00f01678 8 /* GPCR */ + 0x00f03e33 1>; /* PDSCD */ func3-gcr = ; func3-en-mask = <0 0 0 0 @@ -527,7 +531,8 @@ pinctrle: pinctrl@f01680 { compatible = "ite,it8xxx2-pinctrl-func"; - reg = <0x00f01680 8>; /* GPCR */ + reg = <0x00f01680 8 /* GPCR */ + 0x00f03e34 1>; /* PDSCE */ func3-gcr = ; func3-en-mask = <0 0x20 0x20 0 @@ -550,7 +555,8 @@ pinctrlf: pinctrl@f01688 { compatible = "ite,it8xxx2-pinctrl-func"; - reg = <0x00f01688 8>; /* GPCR */ + reg = <0x00f01688 8 /* GPCR */ + 0x00f03e35 1>; /* PDSCF */ func3-gcr = <0xf03e15 0xf03e15 0xf03e10 0xf03e10 NO_FUNC NO_FUNC 0xf03e11 NO_FUNC>; func3-en-mask = <0x04 0x08 0x02 0x02 @@ -569,7 +575,8 @@ pinctrlg: pinctrl@f01690 { compatible = "ite,it8xxx2-pinctrl-func"; - reg = <0x00f01690 8>; /* GPCR */ + reg = <0x00f01690 8 /* GPCR */ + 0x00f03e36 1>; /* PDSCG */ func3-gcr = <0xf03e10 0xf03e10 0xf03e10 NO_FUNC NO_FUNC NO_FUNC 0xf03e10 NO_FUNC>; func3-en-mask = <0x20 0x08 0x10 0 @@ -588,7 +595,8 @@ pinctrlh: pinctrl@f01698 { compatible = "ite,it8xxx2-pinctrl-func"; - reg = <0x00f01698 8>; /* GPCR */ + reg = <0x00f01698 8 /* GPCR */ + 0x00f03e37 1>; /* PDSCH */ func3-gcr = ; func3-en-mask = <0 0x20 0x20 0 @@ -607,7 +615,8 @@ pinctrli: pinctrl@f016a0 { compatible = "ite,it8xxx2-pinctrl-func"; - reg = <0x00f016a0 8>; /* GPCR */ + reg = <0x00f016a0 8 /* GPCR */ + NO_FUNC 1>; func3-gcr = ; func3-en-mask = <0 0 0 0 @@ -626,7 +635,8 @@ pinctrlj: pinctrl@f016a8 { compatible = "ite,it8xxx2-pinctrl-func"; - reg = <0x00f016a8 8>; /* GPCR */ + reg = <0x00f016a8 8 /* GPCR */ + 0x00f03e39 1>; /* PDSCJ */ func3-gcr = <0xf03e14 NO_FUNC 0xf03e14 0xf03e14 0xf03e10 0xf03e10 NO_FUNC NO_FUNC>; func3-en-mask = <0x01 0 0x01 0x02 @@ -645,7 +655,8 @@ pinctrlk: pinctrl@f016b0 { compatible = "ite,it8xxx2-pinctrl-func"; - reg = <0x00f016b0 8>; /* GPCR */ + reg = <0x00f016b0 8 /* GPCR */ + 0x00f03e3A 1>; /* PDSCK */ func3-gcr = ; func3-en-mask = <0 0 0 0 @@ -664,7 +675,8 @@ pinctrll: pinctrl@f016b8 { compatible = "ite,it8xxx2-pinctrl-func"; - reg = <0x00f016b8 8>; /* GPCR */ + reg = <0x00f016b8 8 /* GPCR */ + 0x00f03e3B 1>; /* PDSCL */ func3-gcr = ; func3-en-mask = <0 0 0 0 @@ -683,7 +695,8 @@ pinctrlm: pinctrl@f016c0 { compatible = "ite,it8xxx2-pinctrl-func"; - reg = <0x00f016c0 8>; /* GPCR */ + reg = <0x00f016c0 8 /* GPCR */ + NO_FUNC 1>; func3-gcr = ; func3-en-mask = <0 0 0 0 diff --git a/soc/ite/ec/common/pinctrl_soc.h b/soc/ite/ec/common/pinctrl_soc.h index ba8678477e174..daad29efcd81b 100644 --- a/soc/ite/ec/common/pinctrl_soc.h +++ b/soc/ite/ec/common/pinctrl_soc.h @@ -42,6 +42,8 @@ typedef struct pinctrl_soc_pin pinctrl_soc_pin_t; * Pin voltage selection [ 8 ] * Pin input enable config [ 12 ] * Pin push-pull/open-drain [ 16 ] + * Pin drive current high/low[ 20 ] + * Pin drive current default [ 21 ] */ #define IT8XXX2_HIGH_IMPEDANCE 0x1U #define IT8XXX2_PULL_PIN_DEFAULT 0x0U @@ -52,6 +54,8 @@ typedef struct pinctrl_soc_pin pinctrl_soc_pin_t; #define IT8XXX2_INPUT_ENABLE 0x1U #define IT8XXX2_PUSH_PULL 0x0U #define IT8XXX2_OPEN_DRAIN 0x1U +#define IT8XXX2_DRIVE_STRENGTH 0x1U +#define IT8XXX2_DRIVE_DEFAULT 0x2U /* Pin tri-state mode. */ #define IT8XXX2_IMPEDANCE_SHIFT 0U @@ -69,6 +73,9 @@ typedef struct pinctrl_soc_pin pinctrl_soc_pin_t; /* Pin push-pull/open-drain mode */ #define IT8XXX2_PP_OD_SHIFT 16U #define IT8XXX2_PP_OD_MASK BIT_MASK(1) +/* Pin driving select control */ +#define IT8XXX2_PDSCX_SHIFT 20U +#define IT8XXX2_PDSCX_MASK BIT_MASK(2) /** * @brief Utility macro to obtain configuration of tri-state. @@ -106,6 +113,12 @@ typedef struct pinctrl_soc_pin pinctrl_soc_pin_t; #define IT8XXX2_DT_PINCFG_PP_OD(__mode) \ (((__mode) >> IT8XXX2_PP_OD_SHIFT) & IT8XXX2_PP_OD_MASK) +/** + * @brief Utility macro to obtain configuration of driving current selection. + */ +#define IT8XXX2_DT_PINCFG_DRIVE_CURRENT(__mode) \ + (((__mode) >> IT8XXX2_PDSCX_SHIFT) & IT8XXX2_PDSCX_MASK) + /** * @brief Utility macro to initialize pincfg field in #pinctrl_pin_t. * @@ -125,7 +138,10 @@ typedef struct pinctrl_soc_pin pinctrl_soc_pin_t; ((IT8XXX2_INPUT_ENABLE * DT_PROP(node_id, input_enable)) \ << IT8XXX2_INPUT_SHIFT) | \ ((IT8XXX2_OPEN_DRAIN * DT_PROP(node_id, drive_open_drain)) \ - << IT8XXX2_PP_OD_SHIFT)) + << IT8XXX2_PP_OD_SHIFT) | \ + ((IT8XXX2_DRIVE_STRENGTH * \ + DT_ENUM_IDX_OR(node_id, drive_strength, IT8XXX2_DRIVE_DEFAULT)) \ + << IT8XXX2_PDSCX_SHIFT)) /** * @brief Utility macro to initialize pinctrls of pinmuxs field in #pinctrl_pin_t. From 4f995bd0ff46388bd4edc6a4d6aa1e7d471d09e2 Mon Sep 17 00:00:00 2001 From: Francois Ramu Date: Tue, 13 Feb 2024 16:09:28 +0100 Subject: [PATCH 1885/2849] soc: arm: stm32h7RS introduce stm32h7R/h7S devices Add the new STM32HRSX serie with stm32H7R3, stm32H7R7, stm32H7S3, stm32H7S7 devices from STMicroelectronics Same MPU regions as stm32h7 device. Signed-off-by: Francois Ramu --- soc/st/stm32/soc.yml | 6 ++ soc/st/stm32/stm32h7rsx/CMakeLists.txt | 10 +++ soc/st/stm32/stm32h7rsx/Kconfig | 16 ++++ soc/st/stm32/stm32h7rsx/Kconfig.defconfig | 16 ++++ .../stm32h7rsx/Kconfig.defconfig.stm32h7r3xx | 11 +++ .../stm32h7rsx/Kconfig.defconfig.stm32h7r7xx | 11 +++ .../stm32h7rsx/Kconfig.defconfig.stm32h7s3xx | 11 +++ .../stm32h7rsx/Kconfig.defconfig.stm32h7s7xx | 11 +++ soc/st/stm32/stm32h7rsx/Kconfig.soc | 33 ++++++++ soc/st/stm32/stm32h7rsx/soc.c | 78 +++++++++++++++++++ soc/st/stm32/stm32h7rsx/soc.h | 16 ++++ 11 files changed, 219 insertions(+) create mode 100644 soc/st/stm32/stm32h7rsx/CMakeLists.txt create mode 100644 soc/st/stm32/stm32h7rsx/Kconfig create mode 100644 soc/st/stm32/stm32h7rsx/Kconfig.defconfig create mode 100644 soc/st/stm32/stm32h7rsx/Kconfig.defconfig.stm32h7r3xx create mode 100644 soc/st/stm32/stm32h7rsx/Kconfig.defconfig.stm32h7r7xx create mode 100644 soc/st/stm32/stm32h7rsx/Kconfig.defconfig.stm32h7s3xx create mode 100644 soc/st/stm32/stm32h7rsx/Kconfig.defconfig.stm32h7s7xx create mode 100644 soc/st/stm32/stm32h7rsx/Kconfig.soc create mode 100644 soc/st/stm32/stm32h7rsx/soc.c create mode 100644 soc/st/stm32/stm32h7rsx/soc.h diff --git a/soc/st/stm32/soc.yml b/soc/st/stm32/soc.yml index ac27dee7f6233..50326de858eab 100644 --- a/soc/st/stm32/soc.yml +++ b/soc/st/stm32/soc.yml @@ -102,6 +102,12 @@ family: - name: stm32h562xx - name: stm32h563xx - name: stm32h573xx + - name: stm32h7rsx + socs: + - name: stm32h7r3xx + - name: stm32h7r7xx + - name: stm32h7s3xx + - name: stm32h7s7xx - name: stm32h7x socs: - name: stm32h7a3xx diff --git a/soc/st/stm32/stm32h7rsx/CMakeLists.txt b/soc/st/stm32/stm32h7rsx/CMakeLists.txt new file mode 100644 index 0000000000000..eebd281cd96be --- /dev/null +++ b/soc/st/stm32/stm32h7rsx/CMakeLists.txt @@ -0,0 +1,10 @@ +# 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/st/stm32/stm32h7rsx/Kconfig b/soc/st/stm32/stm32h7rsx/Kconfig new file mode 100644 index 0000000000000..4b97d272a9e26 --- /dev/null +++ b/soc/st/stm32/stm32h7rsx/Kconfig @@ -0,0 +1,16 @@ +# STMicroelectronics STM32H7RS MCU series + +# Copyright (c) 2024 STMicroelectronics +# SPDX-License-Identifier: Apache-2.0 + +config SOC_SERIES_STM32H7RSX + select ARM + select CPU_CORTEX_M7 + select CPU_CORTEX_M_HAS_DWT + select CPU_HAS_FPU + select HAS_STM32CUBE + select CPU_HAS_ARM_MPU + select HAS_SWO + select CPU_HAS_FPU_DOUBLE_PRECISION + select CPU_HAS_ICACHE + select CPU_HAS_DCACHE diff --git a/soc/st/stm32/stm32h7rsx/Kconfig.defconfig b/soc/st/stm32/stm32h7rsx/Kconfig.defconfig new file mode 100644 index 0000000000000..a5ed72502b0f5 --- /dev/null +++ b/soc/st/stm32/stm32h7rsx/Kconfig.defconfig @@ -0,0 +1,16 @@ +# ST Microelectronics STM32H7RS MCU line + +# Copyright (c) 2024 STMicroelectronics +# SPDX-License-Identifier: Apache-2.0 + +# Kconfig symbols common to STM32H7RS series + +if SOC_SERIES_STM32H7RSX + +rsource "Kconfig.defconfig.stm32h7*" + +config ROM_START_OFFSET + default 0x400 if BOOTLOADER_MCUBOOT + default 0x0 if !BOOTLOADER_MCUBOOT + +endif # SOC_SERIES_STM32H7RSX diff --git a/soc/st/stm32/stm32h7rsx/Kconfig.defconfig.stm32h7r3xx b/soc/st/stm32/stm32h7rsx/Kconfig.defconfig.stm32h7r3xx new file mode 100644 index 0000000000000..5476f9d9cf02f --- /dev/null +++ b/soc/st/stm32/stm32h7rsx/Kconfig.defconfig.stm32h7r3xx @@ -0,0 +1,11 @@ +# ST STM32H7R3X MCU configuration options + +# Copyright (c) 2024 STMicroelectronics +# SPDX-License-Identifier: Apache-2.0 + +if SOC_STM32H7R3XX + +config NUM_IRQS + default 156 + +endif # SOC_STM32H7R3XX diff --git a/soc/st/stm32/stm32h7rsx/Kconfig.defconfig.stm32h7r7xx b/soc/st/stm32/stm32h7rsx/Kconfig.defconfig.stm32h7r7xx new file mode 100644 index 0000000000000..8a166bfd849cd --- /dev/null +++ b/soc/st/stm32/stm32h7rsx/Kconfig.defconfig.stm32h7r7xx @@ -0,0 +1,11 @@ +# ST STM32H7R7X MCU configuration options + +# Copyright (c) 2024 STMicroelectronics +# SPDX-License-Identifier: Apache-2.0 + +if SOC_STM32H7R7XX + +config NUM_IRQS + default 156 + +endif # SOC_STM32H7R7XX diff --git a/soc/st/stm32/stm32h7rsx/Kconfig.defconfig.stm32h7s3xx b/soc/st/stm32/stm32h7rsx/Kconfig.defconfig.stm32h7s3xx new file mode 100644 index 0000000000000..939949ffff583 --- /dev/null +++ b/soc/st/stm32/stm32h7rsx/Kconfig.defconfig.stm32h7s3xx @@ -0,0 +1,11 @@ +# ST STM32H7S3X MCU configuration options + +# Copyright (c) 2024 STMicroelectronics +# SPDX-License-Identifier: Apache-2.0 + +if SOC_STM32H7S3XX + +config NUM_IRQS + default 156 + +endif # SOC_STM32H7S3XX diff --git a/soc/st/stm32/stm32h7rsx/Kconfig.defconfig.stm32h7s7xx b/soc/st/stm32/stm32h7rsx/Kconfig.defconfig.stm32h7s7xx new file mode 100644 index 0000000000000..ee546cb803d28 --- /dev/null +++ b/soc/st/stm32/stm32h7rsx/Kconfig.defconfig.stm32h7s7xx @@ -0,0 +1,11 @@ +# ST STM32H7S7X MCU configuration options + +# Copyright (c) 2024 STMicroelectronics +# SPDX-License-Identifier: Apache-2.0 + +if SOC_STM32H7S7XX + +config NUM_IRQS + default 156 + +endif # SOC_STM32H7S7XX diff --git a/soc/st/stm32/stm32h7rsx/Kconfig.soc b/soc/st/stm32/stm32h7rsx/Kconfig.soc new file mode 100644 index 0000000000000..d410771c57f64 --- /dev/null +++ b/soc/st/stm32/stm32h7rsx/Kconfig.soc @@ -0,0 +1,33 @@ +# ST Microelectronics STM32H7RS MCU line + +# Copyright (c) 2024 STMicroelectronics +# SPDX-License-Identifier: Apache-2.0 + +config SOC_SERIES_STM32H7RSX + bool + select SOC_FAMILY_STM32 + +config SOC_SERIES + default "stm32h7rsx" if SOC_SERIES_STM32H7RSX + +config SOC_STM32H7R3XX + bool + select SOC_SERIES_STM32H7RSX + +config SOC_STM32H7R7XX + bool + select SOC_SERIES_STM32H7RSX + +config SOC_STM32H7S3XX + bool + select SOC_SERIES_STM32H7RSX + +config SOC_STM32H7S7XX + bool + select SOC_SERIES_STM32H7RSX + +config SOC + default "stm32h7r3xx" if SOC_STM32H7R3XX + default "stm32h7r7xx" if SOC_STM32H7R7XX + default "stm32h7s3xx" if SOC_STM32H7S3XX + default "stm32h7s7xx" if SOC_STM32H7S7XX diff --git a/soc/st/stm32/stm32h7rsx/soc.c b/soc/st/stm32/stm32h7rsx/soc.c new file mode 100644 index 0000000000000..87d62a3c0635c --- /dev/null +++ b/soc/st/stm32/stm32h7rsx/soc.c @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2024 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * @brief System/hardware module for STM32H7RS CM7 processor + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + + +/** + * @brief Perform basic hardware initialization at boot. + * + * This needs to be run from the very beginning. + * So the init priority has to be 0 (zero). + * + * @return 0 + */ +static int stm32h7rs_init(void) +{ + sys_cache_instr_enable(); + sys_cache_data_enable(); + + /* Update CMSIS SystemCoreClock variable (HCLK) */ + /* At reset, system core clock is set to 64 MHz from HSI */ + SystemCoreClock = 64000000; + + /* Power Configuration */ +#if !defined(SMPS) && \ + (defined(CONFIG_POWER_SUPPLY_DIRECT_SMPS) || \ + defined(CONFIG_POWER_SUPPLY_SMPS_1V8_SUPPLIES_LDO) || \ + defined(CONFIG_POWER_SUPPLY_SMPS_2V5_SUPPLIES_LDO) || \ + defined(CONFIG_POWER_SUPPLY_SMPS_1V8_SUPPLIES_EXT_AND_LDO) || \ + defined(CONFIG_POWER_SUPPLY_SMPS_2V5_SUPPLIES_EXT_AND_LDO) || \ + defined(CONFIG_POWER_SUPPLY_SMPS_1V8_SUPPLIES_EXT) || \ + defined(CONFIG_POWER_SUPPLY_SMPS_2V5_SUPPLIES_EXT)) +#error Unsupported configuration: Selected SoC do not support SMPS +#endif +#if defined(CONFIG_POWER_SUPPLY_DIRECT_SMPS) + LL_PWR_ConfigSupply(LL_PWR_DIRECT_SMPS_SUPPLY); +#elif defined(CONFIG_POWER_SUPPLY_SMPS_1V8_SUPPLIES_LDO) + LL_PWR_ConfigSupply(LL_PWR_SMPS_1V8_SUPPLIES_LDO); +#elif defined(CONFIG_POWER_SUPPLY_SMPS_2V5_SUPPLIES_LDO) + LL_PWR_ConfigSupply(LL_PWR_SMPS_2V5_SUPPLIES_LDO); +#elif defined(CONFIG_POWER_SUPPLY_SMPS_1V8_SUPPLIES_EXT_AND_LDO) + LL_PWR_ConfigSupply(LL_PWR_SMPS_1V8_SUPPLIES_EXT_AND_LDO); +#elif defined(CONFIG_POWER_SUPPLY_SMPS_2V5_SUPPLIES_EXT_AND_LDO) + LL_PWR_ConfigSupply(LL_PWR_SMPS_2V5_SUPPLIES_EXT_AND_LDO); +#elif defined(CONFIG_POWER_SUPPLY_SMPS_1V8_SUPPLIES_EXT) + LL_PWR_ConfigSupply(LL_PWR_SMPS_1V8_SUPPLIES_EXT); +#elif defined(CONFIG_POWER_SUPPLY_SMPS_2V5_SUPPLIES_EXT) + LL_PWR_ConfigSupply(LL_PWR_SMPS_2V5_SUPPLIES_EXT); +#elif defined(CONFIG_POWER_SUPPLY_EXTERNAL_SOURCE) + LL_PWR_ConfigSupply(LL_PWR_EXTERNAL_SOURCE_SUPPLY); +#else + LL_PWR_ConfigSupply(LL_PWR_LDO_SUPPLY); +#endif + LL_PWR_SetRegulVoltageScaling(LL_PWR_REGU_VOLTAGE_SCALE1); + while (LL_PWR_IsActiveFlag_VOSRDY() == 0) { + } + + return 0; +} + +SYS_INIT(stm32h7rs_init, PRE_KERNEL_1, 0); diff --git a/soc/st/stm32/stm32h7rsx/soc.h b/soc/st/stm32/stm32h7rsx/soc.h new file mode 100644 index 0000000000000..f6c8cc64b78a3 --- /dev/null +++ b/soc/st/stm32/stm32h7rsx/soc.h @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2024 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef _STM32H7RS_SOC_H_ +#define _STM32H7RS_SOC_H_ + +#ifndef _ASMLANGUAGE + +#include + +#endif /* !_ASMLANGUAGE */ + +#endif /* _STM32H7RS_SOC_H_ */ From f909c4aee227071eb74e086d8560a9ac15e35990 Mon Sep 17 00:00:00 2001 From: Francois Ramu Date: Tue, 12 Mar 2024 16:22:52 +0100 Subject: [PATCH 1886/2849] soc: st: stm32 common soc config introduce stm32h7R/h7S devices Add the new STM32HRSX serie from STMicroelectronics Signed-off-by: Francois Ramu --- soc/st/stm32/Kconfig | 18 +++++++++--------- soc/st/stm32/common/soc_config.c | 6 ++++-- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/soc/st/stm32/Kconfig b/soc/st/stm32/Kconfig index 9c2d29ca202ec..4f3371ab79b48 100644 --- a/soc/st/stm32/Kconfig +++ b/soc/st/stm32/Kconfig @@ -59,8 +59,8 @@ config STM32_WKUP_PINS choice POWER_SUPPLY_CHOICE prompt "STM32 power supply configuration" default POWER_SUPPLY_LDO - depends on SOC_SERIES_STM32H7X || SOC_SERIES_STM32U5X || \ - SOC_STM32WBA55XX + depends on SOC_SERIES_STM32H7X || SOC_SERIES_STM32H7RSX || \ + SOC_SERIES_STM32U5X || SOC_STM32WBA55XX config POWER_SUPPLY_LDO bool "LDO supply" @@ -70,31 +70,31 @@ config POWER_SUPPLY_DIRECT_SMPS config POWER_SUPPLY_SMPS_1V8_SUPPLIES_LDO bool "SMPS 1.8V supplies LDO (no external supply)" - depends on SOC_SERIES_STM32H7X + depends on SOC_SERIES_STM32H7X || SOC_SERIES_STM32H7RSX config POWER_SUPPLY_SMPS_2V5_SUPPLIES_LDO bool "SMPS 2.5V supplies LDO (no external supply)" - depends on SOC_SERIES_STM32H7X + depends on SOC_SERIES_STM32H7X || SOC_SERIES_STM32H7RSX config POWER_SUPPLY_SMPS_1V8_SUPPLIES_EXT_AND_LDO bool "External SMPS 1.8V supply, supplies LDO" - depends on SOC_SERIES_STM32H7X + depends on SOC_SERIES_STM32H7X || SOC_SERIES_STM32H7RSX config POWER_SUPPLY_SMPS_2V5_SUPPLIES_EXT_AND_LDO bool "External SMPS 2.5V supply, supplies LDO" - depends on SOC_SERIES_STM32H7X + depends on SOC_SERIES_STM32H7X || SOC_SERIES_STM32H7RSX config POWER_SUPPLY_SMPS_1V8_SUPPLIES_EXT bool "External SMPS 1.8V supply and bypass" - depends on SOC_SERIES_STM32H7X + depends on SOC_SERIES_STM32H7X || SOC_SERIES_STM32H7RSX config POWER_SUPPLY_SMPS_2V5_SUPPLIES_EXT bool "External SMPS 2.5V supply and bypass" - depends on SOC_SERIES_STM32H7X + depends on SOC_SERIES_STM32H7X || SOC_SERIES_STM32H7RSX config POWER_SUPPLY_EXTERNAL_SOURCE bool "Bypass" - depends on SOC_SERIES_STM32H7X + depends on SOC_SERIES_STM32H7X || SOC_SERIES_STM32H7RSX endchoice diff --git a/soc/st/stm32/common/soc_config.c b/soc/st/stm32/common/soc_config.c index f5e65a146cc9c..70f270cf49418 100644 --- a/soc/st/stm32/common/soc_config.c +++ b/soc/st/stm32/common/soc_config.c @@ -65,7 +65,8 @@ static int st_stm32_common_config(void) #if defined(CONFIG_STM32_ENABLE_DEBUG_SLEEP_STOP) -#if defined(CONFIG_SOC_SERIES_STM32H7X) || defined(CONFIG_SOC_SERIES_STM32MP1X) +#if defined(CONFIG_SOC_SERIES_STM32H7X) || defined(CONFIG_SOC_SERIES_STM32H7RSX) \ + || defined(CONFIG_SOC_SERIES_STM32MP1X) HAL_EnableDBGStopMode(); #elif defined(CONFIG_SOC_SERIES_STM32G0X) || defined(CONFIG_SOC_SERIES_STM32C0X) LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_DBGMCU); @@ -86,7 +87,8 @@ static int st_stm32_common_config(void) #else /* keeping in mind that debugging draws a lot of power we explcitly disable when not needed */ -#if defined(CONFIG_SOC_SERIES_STM32H7X) || defined(CONFIG_SOC_SERIES_STM32MP1X) +#if defined(CONFIG_SOC_SERIES_STM32H7X) || defined(CONFIG_SOC_SERIES_STM32H7RSX) \ + || defined(CONFIG_SOC_SERIES_STM32MP1X) HAL_DisableDBGStopMode(); #elif defined(CONFIG_SOC_SERIES_STM32G0X) || defined(CONFIG_SOC_SERIES_STM32C0X) LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_DBGMCU); From c08f27d84ddd73e529d1a1d157262175d7bb87c6 Mon Sep 17 00:00:00 2001 From: Francois Ramu Date: Fri, 16 Feb 2024 12:20:04 +0100 Subject: [PATCH 1887/2849] dts: bindings: stm32 rcc and exti controller for the stm32H7RS Introduce the stm32h7RS serie to the clock rcc controller, and the exti interrupt controller based on the stm32h7 rcc bindings. Three PLL clocks are available. Signed-off-by: Francois Ramu --- .../clock/st,stm32h7rs-pll-clock.yaml | 40 ++++++ dts/bindings/clock/st,stm32h7rs-rcc.yaml | 135 ++++++++++++++++++ .../st,stm32h7rs-exti.yaml | 12 ++ 3 files changed, 187 insertions(+) create mode 100644 dts/bindings/clock/st,stm32h7rs-pll-clock.yaml create mode 100644 dts/bindings/clock/st,stm32h7rs-rcc.yaml create mode 100644 dts/bindings/interrupt-controller/st,stm32h7rs-exti.yaml diff --git a/dts/bindings/clock/st,stm32h7rs-pll-clock.yaml b/dts/bindings/clock/st,stm32h7rs-pll-clock.yaml new file mode 100644 index 0000000000000..0d03cc7272a9e --- /dev/null +++ b/dts/bindings/clock/st,stm32h7rs-pll-clock.yaml @@ -0,0 +1,40 @@ +# Copyright (c) 2024 STMicroelectronics +# SPDX-License-Identifier: Apache-2.0 + +description: | + PLL node binding for STM32H7RS devices + + It can be used to describe 3 different PLLs: PLL1 (Main PLL), PLL2 and PLL3. + + These PLLs could take one of clk_hse, clk_hsi or clk_csi as input clock, with + an input frequency from 1 to 16 MHz. PLLM factor is used to set the input + clock in this acceptable range. + + Each PLL can have up to 5 output clocks and for each output clock, the + frequency can be computed with the following formulae: + + f(PLL_Px) = f(VCOx clock) / PLLPx -> pllx_p_ck ((pll1_p_ck : sys_ck)) + f(PLL_Qx) = f(VCOx clock) / PLLQx -> pllx_q_ck + f(PLL_Rx) = f(VCOx clock) / PLLRx -> pllx_r_ck + f(PLL_Sx) = f(VCOx clock) / PLLSx -> pllx_s_ck + f(PLL_Tx) = f(VCOx clock) / PLLTx -> pllx_t_ck (only for PLL2) + + with f(VCOx clock) = f(REFx_CK) × (PLLNx / PLLMx) + + +compatible: "st,stm32h7rs-pll-clock" + +include: st,stm32h7-pll-clock.yaml + +properties: + div-s: + type: int + description: | + PLL division factor for pllx_s_ck + Valid range: 1 - 8 + + div-t: + type: int + description: | + PLL division factor for pllx_t_ck + Valid range: 1 - 8 diff --git a/dts/bindings/clock/st,stm32h7rs-rcc.yaml b/dts/bindings/clock/st,stm32h7rs-rcc.yaml new file mode 100644 index 0000000000000..780c84564f447 --- /dev/null +++ b/dts/bindings/clock/st,stm32h7rs-rcc.yaml @@ -0,0 +1,135 @@ +# Copyright (c) 2024, STMicroelectronics +# SPDX-License-Identifier: Apache-2.0 + +description: | + STM32 Reset and Clock controller node for STM32H7RS devices + This node is in charge of system clock ('SYSCLK') source selection and + System Clock Generation. + + Configuring STM32 Reset and Clock controller node: + + System clock source should be selected amongst the clock nodes available in "clocks" + node (typically 'clk_hse, clk_csi', 'pll', ...). + As part of this node configuration, SYSCLK frequency should also be defined, using + "clock-frequency" property. + Last, bus clocks (typically HCLK, PCLK1, PCLK2) should be configured using matching + prescaler properties. + Here is an example of correctly configured rcc node: + &rcc { + clocks = <&pll>; /* Set pll as SYSCLK source */ + clock-frequency = ; /* SYSCLK runs at 280MHz */ + dcpre = <1>; + hpre = <1>; + ppre1 = <1>; + ppre2 = <1>; + ppre4 = <1>; + ppre5 = <1>; + } + + Confere st,stm32-rcc binding for information about domain clocks configuration. + +compatible: "st,stm32h7rs-rcc" + +include: [clock-controller.yaml, base.yaml] + +properties: + reg: + required: true + + "#clock-cells": + const: 2 + + clock-frequency: + required: true + type: int + description: | + default frequency in Hz for clock output + + dcpre: + type: int + required: true + enum: + - 1 + - 2 + - 4 + - 8 + - 16 + - 64 + - 128 + - 256 + - 512 + description: | + CPU clock prescaler. Sets a HCLK frequency (feeding Cortex-M Systick) + lower than SYSCLK frequency (actual core frequency). + Zephyr doesn't make a difference today between these two clocks. + Changing this prescaler is not allowed until it is made possible to + use them independently in Zephyr clock subsystem. + + hpre: + type: int + required: true + description: | + peripheral clock to the Bus Matrix APB (1/2/4/5) and AHB(1/2/3/4/5) peripheral + divider of the CPU clock by this prescaler (BMPRE register) + enum: + - 1 + - 2 + - 4 + - 8 + - 16 + - 64 + - 128 + - 256 + - 512 + + ppre1: + type: int + required: true + description: | + APB1 peripheral prescaler + enum: + - 1 + - 2 + - 4 + - 8 + - 16 + + ppre2: + type: int + required: true + description: | + APB2 peripheral prescaler + enum: + - 1 + - 2 + - 4 + - 8 + - 16 + + ppre4: + type: int + required: true + description: | + APB4 peripheral prescaler + enum: + - 1 + - 2 + - 4 + - 8 + - 16 + + ppre5: + type: int + required: true + description: | + APB5 peripheral prescaler + enum: + - 1 + - 2 + - 4 + - 8 + - 16 + +clock-cells: + - bus + - bits diff --git a/dts/bindings/interrupt-controller/st,stm32h7rs-exti.yaml b/dts/bindings/interrupt-controller/st,stm32h7rs-exti.yaml new file mode 100644 index 0000000000000..1e441fb47b80b --- /dev/null +++ b/dts/bindings/interrupt-controller/st,stm32h7rs-exti.yaml @@ -0,0 +1,12 @@ +# Copyright (c) 2024, STMicroelectronics + +# SPDX-License-Identifier: Apache-2.0 + +description: | + STM32 controller + This compatible stands for the stm32H7RS interrupt-controller block + with two dedicated Rising and Falling interrupt pending registers + +compatible: "st,stm32h7rs-exti" + +include: st,stm32-exti.yaml From 715b246a2a502d59c572ce8e90f2ab78d051feb1 Mon Sep 17 00:00:00 2001 From: Francois Ramu Date: Fri, 23 Feb 2024 09:13:58 +0100 Subject: [PATCH 1888/2849] include: reset bindings add the stm32h7rs serie Add the support of the STM32H7RSX to the include/zephyr/dt-bindings/reset/stm32h7_reset.h which differs from the stm32h7 with an APB5 bus Signed-off-by: Francois Ramu --- .../dt-bindings/reset/stm32h7rs_reset.h | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 include/zephyr/dt-bindings/reset/stm32h7rs_reset.h diff --git a/include/zephyr/dt-bindings/reset/stm32h7rs_reset.h b/include/zephyr/dt-bindings/reset/stm32h7rs_reset.h new file mode 100644 index 0000000000000..a4a90a9cc1015 --- /dev/null +++ b/include/zephyr/dt-bindings/reset/stm32h7rs_reset.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2022 Google Inc + * Copyright (c) 2024 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_RESET_STM32H7RS_RESET_H_ +#define ZEPHYR_INCLUDE_DT_BINDINGS_RESET_STM32H7RS_RESET_H_ + +#include "stm32-common.h" + +/* RCC bus reset register offset */ +#define STM32_RESET_BUS_AHB1 0x80 +#define STM32_RESET_BUS_AHB2 0x84 +#define STM32_RESET_BUS_AHB3 0xA4 +#define STM32_RESET_BUS_AHB5 0x7C +#define STM32_RESET_BUS_APB5 0x8C +#define STM32_RESET_BUS_AHB4 0x88 +#define STM32_RESET_BUS_APB1L 0x90 +#define STM32_RESET_BUS_APB1H 0x94 +#define STM32_RESET_BUS_APB2 0x98 +#define STM32_RESET_BUS_APB4 0x9C + +#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_RESET_STM32H7RS_RESET_H_ */ From 332eb17995037ea8202047c3936f25a67d8f01fc Mon Sep 17 00:00:00 2001 From: Francois Ramu Date: Thu, 15 Feb 2024 15:03:25 +0100 Subject: [PATCH 1889/2849] dts: arm: stm32h7 introduce stm32h7R/h7S devices Add the new stm32h7rs serie with stm32H7R3, stm32H7R7, stm32H7S3, stm32H7S7 devices from STMicroelectronics Signed-off-by: Francois Ramu --- dts/arm/st/h7rs/stm32h7r3.dtsi | 16 + dts/arm/st/h7rs/stm32h7r3X8.dtsi | 17 + dts/arm/st/h7rs/stm32h7r7.dtsi | 17 + dts/arm/st/h7rs/stm32h7r7X8.dtsi | 17 + dts/arm/st/h7rs/stm32h7rs.dtsi | 704 +++++++++++++++++++++++++++++++ dts/arm/st/h7rs/stm32h7s3.dtsi | 17 + dts/arm/st/h7rs/stm32h7s3X8.dtsi | 17 + dts/arm/st/h7rs/stm32h7s7.dtsi | 17 + dts/arm/st/h7rs/stm32h7s7X8.dtsi | 17 + 9 files changed, 839 insertions(+) create mode 100644 dts/arm/st/h7rs/stm32h7r3.dtsi create mode 100644 dts/arm/st/h7rs/stm32h7r3X8.dtsi create mode 100644 dts/arm/st/h7rs/stm32h7r7.dtsi create mode 100644 dts/arm/st/h7rs/stm32h7r7X8.dtsi create mode 100644 dts/arm/st/h7rs/stm32h7rs.dtsi create mode 100644 dts/arm/st/h7rs/stm32h7s3.dtsi create mode 100644 dts/arm/st/h7rs/stm32h7s3X8.dtsi create mode 100644 dts/arm/st/h7rs/stm32h7s7.dtsi create mode 100644 dts/arm/st/h7rs/stm32h7s7X8.dtsi diff --git a/dts/arm/st/h7rs/stm32h7r3.dtsi b/dts/arm/st/h7rs/stm32h7r3.dtsi new file mode 100644 index 0000000000000..57a2c057b92d8 --- /dev/null +++ b/dts/arm/st/h7rs/stm32h7r3.dtsi @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2024 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +/ { + soc { + + compatible = "st,stm32h7r3", "st,stm32h7rs", "simple-bus"; + + }; +}; diff --git a/dts/arm/st/h7rs/stm32h7r3X8.dtsi b/dts/arm/st/h7rs/stm32h7r3X8.dtsi new file mode 100644 index 0000000000000..5bdb944644816 --- /dev/null +++ b/dts/arm/st/h7rs/stm32h7r3X8.dtsi @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2024 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +/ { + soc { + flash-controller@52002000 { + flash0: flash@8000000 { + reg = <0x08000000 DT_SIZE_K(64)>; + }; + }; + }; +}; diff --git a/dts/arm/st/h7rs/stm32h7r7.dtsi b/dts/arm/st/h7rs/stm32h7r7.dtsi new file mode 100644 index 0000000000000..bdc347798c8ca --- /dev/null +++ b/dts/arm/st/h7rs/stm32h7r7.dtsi @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2024 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +/* + * STM32H7R7 line contains the same peripherals as STM32H7R3. + */ +/ { + soc { + compatible = "st,stm32h7r7", "st,stm32h7rs", "simple-bus"; + }; +}; diff --git a/dts/arm/st/h7rs/stm32h7r7X8.dtsi b/dts/arm/st/h7rs/stm32h7r7X8.dtsi new file mode 100644 index 0000000000000..3755e88f26bbf --- /dev/null +++ b/dts/arm/st/h7rs/stm32h7r7X8.dtsi @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2024 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +/ { + soc { + flash-controller@52002000 { + flash0: flash@8000000 { + reg = <0x08000000 DT_SIZE_K(64)>; + }; + }; + }; +}; diff --git a/dts/arm/st/h7rs/stm32h7rs.dtsi b/dts/arm/st/h7rs/stm32h7rs.dtsi new file mode 100644 index 0000000000000..d0f5712eb263b --- /dev/null +++ b/dts/arm/st/h7rs/stm32h7rs.dtsi @@ -0,0 +1,704 @@ +/* + * Copyright (c) 2024 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * STM32H7RS line contains has many common peripherals with STM32H7. + */ + +/ { + chosen { + zephyr,flash-controller = &flash; + }; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu0: cpu@0 { + device_type = "cpu"; + compatible = "arm,cortex-m7"; + reg = <0>; + #address-cells = <1>; + #size-cells = <1>; + + mpu: mpu@e000ed90 { + compatible = "arm,armv7m-mpu"; + reg = <0xe000ed90 0x40>; + }; + }; + }; + + /* System data RAM accessible over AXI bus: AXI SRAM1 in CD domain */ + sram0: memory@24000000 { + compatible = "mmio-sram"; + reg = <0x24000000 DT_SIZE_K(128)>; + }; + + /* System data RAM accessible over AHB bus: SRAM1 in D2 domain */ + sram1: memory@30000000 { + reg = <0x30000000 DT_SIZE_K(16)>; + compatible = "zephyr,memory-region", "mmio-sram"; + zephyr,memory-region = "SRAM1"; + }; + + /* System data RAM accessible over AHB bus: SRAM2 in D2 domain */ + sram2: memory@30004000 { + compatible = "zephyr,memory-region", "mmio-sram"; + reg = <0x30004000 DT_SIZE_K(16)>; + zephyr,memory-region = "SRAM2"; + }; + + dtcm: memory@20000000 { + compatible = "zephyr,memory-region", "arm,dtcm"; + reg = <0x20000000 DT_SIZE_K(128)>; + zephyr,memory-region = "DTCM"; + }; + + itcm: memory@0 { + compatible = "zephyr,memory-region", "arm,itcm"; + reg = <0x00000000 DT_SIZE_K(64)>; + zephyr,memory-region = "ITCM"; + }; + + ext_memory: memory@70000000 { + compatible = "zephyr,memory-region"; + reg = <0x70000000 DT_SIZE_M(256)>; + zephyr,memory-region = "EXTMEM"; + zephyr,memory-attr = <( DT_MEM_ARM(ATTR_MPU_EXTMEM) )>; + }; + + clocks { + #address-cells = <1>; + #size-cells = <0>; + + clk_hse: clk-hse { + #clock-cells = <0>; + compatible = "st,stm32-hse-clock"; + status = "disabled"; + }; + + clk_hsi: clk-hsi { + #clock-cells = <0>; + compatible = "st,stm32h7-hsi-clock"; + clock-frequency = ; + status = "disabled"; + }; + + clk_hsi48: clk-hsi48 { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = ; + status = "disabled"; + }; + + clk_csi: clk-csi { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = ; + status = "disabled"; + }; + + clk_lse: clk-lse { + #clock-cells = <0>; + compatible = "st,stm32-lse-clock"; + clock-frequency = <32768>; + driving-capability = <0>; + status = "disabled"; + }; + + clk_lsi: clk-lsi { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = ; + status = "disabled"; + }; + + pll: pll@0 { + #clock-cells = <0>; + compatible = "st,stm32h7rs-pll-clock"; + reg = <0>; + status = "disabled"; + }; + + pll2: pll@1 { + #clock-cells = <0>; + compatible = "st,stm32h7rs-pll-clock"; + reg = <1>; + status = "disabled"; + }; + + pll3: pll@2 { + #clock-cells = <0>; + compatible = "st,stm32h7rs-pll-clock"; + reg = <2>; + status = "disabled"; + }; + + perck: perck { + #clock-cells = <0>; + compatible = "st,stm32-clock-mux"; + status = "disabled"; + }; + }; + + soc { + flash: flash-controller@52002000 { + compatible = "st,stm32-flash-controller", "st,stm32h7-flash-controller"; + reg = <0x52002000 0x400>; + interrupts = <8 0>; + + #address-cells = <1>; + #size-cells = <1>; + }; + + rcc: rcc@58024400 { + compatible = "st,stm32h7rs-rcc"; + #clock-cells = <2>; + reg = <0x58024400 0x400>; + + rctl: reset-controller { + compatible = "st,stm32-rcc-rctl"; + #reset-cells = <1>; + }; + }; + + exti: interrupt-controller@58000000 { + compatible = "st,stm32h7rs-exti", "st,stm32-exti"; + interrupt-controller; + #interrupt-cells = <1>; + #address-cells = <1>; + reg = <0x58000000 0x400>; + /* SBS for interrupt */ + num-lines = <16>; + interrupts = <16 0>, <17 0>, <18 0>, <19 0>, + <20 0>, <21 0>, <22 0>, <23 0>, + <24 0>, <25 0>, <26 0>, <27 0>, + <28 0>, <29 0>, <30 0>, <31 0>; + interrupt-names = "line0", "line1", "line2", "line3", + "line4", "line5", "line6", "line7", + "line8", "line9", "line10", "line11", + "line12", "line13", "line14", "line15"; + line-ranges = <0 1>, <1 1>, <2 1>, <3 1>, + <4 1>, <5 1>, <6 1>, <7 1>, + <8 1>, <9 1>, <10 1>, <11 1>, + <12 1>, <13 1>, <14 1>, <15 1>; + }; + + pinctrl: pin-controller@58020000 { + compatible = "st,stm32-pinctrl"; + #address-cells = <1>; + #size-cells = <1>; + reg = <0x58020000 0x2400>; + + gpioa: gpio@58020000 { + compatible = "st,stm32-gpio"; + gpio-controller; + #gpio-cells = <2>; + reg = <0x58020000 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_AHB4 0x00000001>; + }; + + gpiob: gpio@58020400 { + compatible = "st,stm32-gpio"; + gpio-controller; + #gpio-cells = <2>; + reg = <0x58020400 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_AHB4 0x00000002>; + }; + + gpioc: gpio@58020800 { + compatible = "st,stm32-gpio"; + gpio-controller; + #gpio-cells = <2>; + reg = <0x58020800 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_AHB4 0x00000004>; + }; + + gpiod: gpio@58020C00 { + compatible = "st,stm32-gpio"; + gpio-controller; + #gpio-cells = <2>; + reg = <0x58020C00 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_AHB4 0x00000008>; + }; + + gpioe: gpio@58021000 { + compatible = "st,stm32-gpio"; + gpio-controller; + #gpio-cells = <2>; + reg = <0x58021000 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_AHB4 0x00000010>; + }; + + gpiof: gpio@58021400 { + compatible = "st,stm32-gpio"; + gpio-controller; + #gpio-cells = <2>; + reg = <0x58021400 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_AHB4 0x00000020>; + }; + + gpiog: gpio@58021800 { + compatible = "st,stm32-gpio"; + gpio-controller; + #gpio-cells = <2>; + reg = <0x58021800 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_AHB4 0x00000040>; + }; + + gpioh: gpio@58021c00 { + compatible = "st,stm32-gpio"; + gpio-controller; + #gpio-cells = <2>; + reg = <0x58021c00 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_AHB4 0x00000080>; + }; + + gpiom: gpio@58023000 { + compatible = "st,stm32-gpio"; + gpio-controller; + #gpio-cells = <2>; + reg = <0x58023000 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_AHB4 0x00001000>; + }; + + gpion: gpio@58023400 { + compatible = "st,stm32-gpio"; + gpio-controller; + #gpio-cells = <2>; + reg = <0x58023400 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_AHB4 0x00002000>; + }; + + gpioo: gpio@58023800 { + compatible = "st,stm32-gpio"; + gpio-controller; + #gpio-cells = <2>; + reg = <0x58023800 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_AHB4 0x00004000>; + }; + + gpiop: gpio@58023c00 { + compatible = "st,stm32-gpio"; + gpio-controller; + #gpio-cells = <2>; + reg = <0x58023c00 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_AHB4 0x00008000>; + }; + }; + + usart1: serial@42001000 { + compatible = "st,stm32-usart", "st,stm32-uart"; + reg = <0x42001000 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_APB2 0x00000010>; + resets = <&rctl STM32_RESET(APB2, 4U)>; + interrupts = <82 0>; + status = "disabled"; + }; + usart2: serial@40004400 { + compatible = "st,stm32-usart", "st,stm32-uart"; + reg = <0x40004400 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_APB1 0x00020000>; + resets = <&rctl STM32_RESET(APB1L, 17U)>; + interrupts = <83 0>; + status = "disabled"; + }; + usart3: serial@40004800 { + compatible = "st,stm32-usart", "st,stm32-uart"; + reg = <0x40004800 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_APB1 0x00040000>; + resets = <&rctl STM32_RESET(APB1L, 18U)>; + interrupts = <84 0>; + status = "disabled"; + }; + uart4: serial@40004c00 { + compatible ="st,stm32-uart"; + reg = <0x40004c00 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_APB1 0x00080000>; + resets = <&rctl STM32_RESET(APB1L, 19U)>; + interrupts = <85 0>; + status = "disabled"; + }; + uart5: serial@40005000 { + compatible = "st,stm32-uart"; + reg = <0x40005000 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_APB1 0x00100000>; + resets = <&rctl STM32_RESET(APB1L, 20U)>; + interrupts = <86 0>; + status = "disabled"; + }; + uart7: serial@40007800 { + compatible = "st,stm32-uart"; + reg = <0x40007800 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_APB1 0x40000000>; + resets = <&rctl STM32_RESET(APB1L, 30U)>; + interrupts = <87 0>; + status = "disabled"; + }; + uart8: serial@40007c00 { + compatible = "st,stm32-uart"; + reg = <0x40007c00 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_APB1 0x80000000>; + resets = <&rctl STM32_RESET(APB1L, 31U)>; + interrupts = <88 0>; + status = "disabled"; + }; + + lpuart1: serial@58000c00 { + compatible = "st,stm32-lpuart", "st,stm32-uart"; + reg = <0x58000c00 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_APB4 0x00000008>; + resets = <&rctl STM32_RESET(APB4, 3U)>; + interrupts = <131 0>; + status = "disabled"; + }; + + i2c1: i2c@40005400 { + compatible = "st,stm32-i2c-v2"; + clock-frequency = ; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x40005400 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_APB1 0x00200000>; + interrupts = <76 0>, <77 0>; + interrupt-names = "event", "error"; + status = "disabled"; + }; + + i2c2: i2c@40005800 { + compatible = "st,stm32-i2c-v2"; + clock-frequency = ; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x40005800 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_APB1 0x00400000>; + interrupts = <78 0>, <79 0>; + interrupt-names = "event", "error"; + status = "disabled"; + }; + + i2c3: i2c@40005c00 { + compatible = "st,stm32-i2c-v2"; + clock-frequency = ; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x40005c00 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_APB1 0x00800000>; + interrupts = <80 0>, <81 0>; + interrupt-names = "event", "error"; + status = "disabled"; + }; + + spi1: spi@42003000 { + compatible = "st,stm32h7-spi", "st,stm32-spi-fifo", "st,stm32-spi"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x42003000 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_APB2 0x00001000>, + <&rcc STM32_SRC_PLL1_Q SPI1_SEL(0)>; + interrupts = <58 0>; + status = "disabled"; + }; + + spi2: spi@40003800 { + compatible = "st,stm32h7-spi", "st,stm32-spi-fifo", "st,stm32-spi"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x40003800 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_APB1 0x00004000>, + <&rcc STM32_SRC_PLL1_Q SPI23_SEL(0)>; + interrupts = <59 0>; + status = "disabled"; + }; + + spi3: spi@40003c00 { + compatible = "st,stm32h7-spi", "st,stm32-spi-fifo", "st,stm32-spi"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x40003c00 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_APB1 0x00008000>, + <&rcc STM32_SRC_PLL1_Q SPI23_SEL(0)>; + interrupts = <60 0>; + status = "disabled"; + }; + + spi4: spi@42003400 { + compatible = "st,stm32h7-spi", "st,stm32-spi-fifo", "st,stm32-spi"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x42003400 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_APB2 0x00002000>; + interrupts = <61 0>; + status = "disabled"; + }; + + spi5: spi@42005000 { + compatible = "st,stm32h7-spi", "st,stm32-spi-fifo", "st,stm32-spi"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x42005000 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_APB2 0x00100000>; + interrupts = <62 0>; + status = "disabled"; + }; + + i2s1: i2s@40013000 { + compatible = "st,stm32h7-i2s", "st,stm32-i2s"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x40013000 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_APB2 0x00001000>, + <&rcc STM32_SRC_PLL1_Q SPI1_SEL(0)>; + interrupts = <35 3>; + status = "disabled"; + }; + + timers1: timers@42000000 { + compatible = "st,stm32-timers"; + reg = <0x42000000 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_APB2 0x00000001>; + resets = <&rctl STM32_RESET(APB2, 0U)>; + interrupts = <47 0>, <48 0>, <49 0>, <50 0>; + interrupt-names = "brk", "up", "trgcom", "cc"; + st,prescaler = <0>; + status = "disabled"; + + pwm { + compatible = "st,stm32-pwm"; + status = "disabled"; + #pwm-cells = <3>; + }; + }; + + timers2: timers@40000000 { + compatible = "st,stm32-timers"; + reg = <0x40000000 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_APB1 0x00000001>; + resets = <&rctl STM32_RESET(APB1L, 0U)>; + interrupts = <51 0>; + interrupt-names = "global"; + st,prescaler = <0>; + status = "disabled"; + + pwm { + compatible = "st,stm32-pwm"; + status = "disabled"; + #pwm-cells = <3>; + }; + + counter { + compatible = "st,stm32-counter"; + status = "disabled"; + }; + }; + + timers3: timers@40000400 { + compatible = "st,stm32-timers"; + reg = <0x40000400 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_APB1 0x00000002>; + resets = <&rctl STM32_RESET(APB1L, 1U)>; + interrupts = <52 0>; + interrupt-names = "global"; + st,prescaler = <0>; + status = "disabled"; + + pwm { + compatible = "st,stm32-pwm"; + status = "disabled"; + #pwm-cells = <3>; + }; + + counter { + compatible = "st,stm32-counter"; + status = "disabled"; + }; + }; + + timers4: timers@40000800 { + compatible = "st,stm32-timers"; + reg = <0x40000800 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_APB1 0x00000004>; + resets = <&rctl STM32_RESET(APB1L, 2U)>; + interrupts = <53 0>; + interrupt-names = "global"; + st,prescaler = <0>; + status = "disabled"; + + pwm { + compatible = "st,stm32-pwm"; + status = "disabled"; + #pwm-cells = <3>; + }; + + counter { + compatible = "st,stm32-counter"; + status = "disabled"; + }; + }; + + timers5: timers@40000c00 { + compatible = "st,stm32-timers"; + reg = <0x40000c00 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_APB1 0x00000008>; + resets = <&rctl STM32_RESET(APB1L, 3U)>; + interrupts = <54 0>; + interrupt-names = "global"; + st,prescaler = <0>; + status = "disabled"; + + pwm { + compatible = "st,stm32-pwm"; + status = "disabled"; + #pwm-cells = <3>; + }; + + counter { + compatible = "st,stm32-counter"; + status = "disabled"; + }; + }; + + timers6: timers@40001000 { + compatible = "st,stm32-timers"; + reg = <0x40001000 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_APB1 0x00000010>; + resets = <&rctl STM32_RESET(APB1L, 4U)>; + interrupts = <55 0>; + interrupt-names = "global"; + st,prescaler = <0>; + status = "disabled"; + + counter { + compatible = "st,stm32-counter"; + status = "disabled"; + }; + }; + + timers7: timers@40001400 { + compatible = "st,stm32-timers"; + reg = <0x40001400 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_APB1 0x00000020>; + resets = <&rctl STM32_RESET(APB1L, 5U)>; + interrupts = <56 0>; + interrupt-names = "global"; + st,prescaler = <0>; + status = "disabled"; + + counter { + compatible = "st,stm32-counter"; + status = "disabled"; + }; + }; + + timers9: timers@42004c00 { + compatible = "st,stm32-timers"; + reg = <0x42004c00 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_APB2 0x00080000>; + resets = <&rctl STM32_RESET(APB2, 19U)>; + interrupts = <57 0>; + interrupt-names = "global"; + st,prescaler = <0>; + status = "disabled"; + + counter { + compatible = "st,stm32-counter"; + status = "disabled"; + }; + }; + + timers15: timers@42004000 { + compatible = "st,stm32-timers"; + reg = <0x42004000 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_APB2 0x00010000>; + resets = <&rctl STM32_RESET(APB2, 16U)>; + interrupts = <116 0>; + interrupt-names = "global"; + st,prescaler = <0>; + status = "disabled"; + + pwm { + compatible = "st,stm32-pwm"; + status = "disabled"; + #pwm-cells = <3>; + }; + + counter { + compatible = "st,stm32-counter"; + status = "disabled"; + }; + }; + + timers16: timers@42004400 { + compatible = "st,stm32-timers"; + reg = <0x42004400 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_APB1 0x00020000>; + resets = <&rctl STM32_RESET(APB2, 17U)>; + interrupts = <117 0>; + interrupt-names = "global"; + st,prescaler = <0>; + status = "disabled"; + + pwm { + compatible = "st,stm32-pwm"; + status = "disabled"; + #pwm-cells = <3>; + }; + + counter { + compatible = "st,stm32-counter"; + status = "disabled"; + }; + }; + + timers17: timers@42004800 { + compatible = "st,stm32-timers"; + reg = <0x42004800 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_APB1 0x00040000>; + resets = <&rctl STM32_RESET(APB2, 18U)>; + interrupts = <118 0>; + interrupt-names = "global"; + st,prescaler = <0>; + status = "disabled"; + + pwm { + compatible = "st,stm32-pwm"; + status = "disabled"; + #pwm-cells = <3>; + }; + + counter { + compatible = "st,stm32-counter"; + status = "disabled"; + }; + }; + + lptim1: timers@40002400 { + compatible = "st,stm32-lptim"; + clocks = <&rcc STM32_CLOCK_BUS_APB1 0x00000200>; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x40002400 0x400>; + interrupts = <119 1>; + interrupt-names = "wakeup"; + status = "disabled"; + }; + }; +}; + +&nvic { + arm,num-irq-priority-bits = <4>; +}; diff --git a/dts/arm/st/h7rs/stm32h7s3.dtsi b/dts/arm/st/h7rs/stm32h7s3.dtsi new file mode 100644 index 0000000000000..f1d490266b7dd --- /dev/null +++ b/dts/arm/st/h7rs/stm32h7s3.dtsi @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2024 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +/* + * STM32H7S3 line contains the same peripherals as STM32H7R3. + */ +/ { + soc { + compatible = "st,stm32h7s3", "st,stm32h7rs", "simple-bus"; + }; +}; diff --git a/dts/arm/st/h7rs/stm32h7s3X8.dtsi b/dts/arm/st/h7rs/stm32h7s3X8.dtsi new file mode 100644 index 0000000000000..4eca0e58ab2c7 --- /dev/null +++ b/dts/arm/st/h7rs/stm32h7s3X8.dtsi @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2024 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +/ { + soc { + flash-controller@52002000 { + flash0: flash@8000000 { + reg = <0x08000000 DT_SIZE_K(64)>; + }; + }; + }; +}; diff --git a/dts/arm/st/h7rs/stm32h7s7.dtsi b/dts/arm/st/h7rs/stm32h7s7.dtsi new file mode 100644 index 0000000000000..7566df2cfe9c8 --- /dev/null +++ b/dts/arm/st/h7rs/stm32h7s7.dtsi @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2024 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +/* + * STM32H7S7 line contains the same peripherals as STM32H7R7. + */ +/ { + soc { + compatible = "st,stm32h7s7", "st,stm32h7rs", "simple-bus"; + }; +}; diff --git a/dts/arm/st/h7rs/stm32h7s7X8.dtsi b/dts/arm/st/h7rs/stm32h7s7X8.dtsi new file mode 100644 index 0000000000000..2c31b66b586e3 --- /dev/null +++ b/dts/arm/st/h7rs/stm32h7s7X8.dtsi @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2024 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +/ { + soc { + flash-controller@52002000 { + flash0: flash@8000000 { + reg = <0x08000000 DT_SIZE_K(64)>; + }; + }; + }; +}; From e6ebb044aca5ea809ff1a3b211e89502677efe33 Mon Sep 17 00:00:00 2001 From: Francois Ramu Date: Fri, 16 Feb 2024 12:17:59 +0100 Subject: [PATCH 1890/2849] drivers: clock: stm32 clock driver supporting the stm32H7RS Introduce the stm32h7RS serie to the clock_controller, based on the stm32h7 clock driver Datasheet DS14359 rev 1 gives CPU max freq of 500MHz Signed-off-by: Francois Ramu --- drivers/clock_control/CMakeLists.txt | 2 + drivers/clock_control/Kconfig.stm32 | 21 +- drivers/clock_control/clock_stm32_ll_h7.c | 212 +++++++++++++++++- drivers/clock_control/clock_stm32_ll_mco.h | 3 +- .../clock/st,stm32h7rs-pll-clock.yaml | 4 +- .../clock_control/stm32_clock_control.h | 31 ++- .../dt-bindings/clock/stm32h7rs_clock.h | 131 +++++++++++ 7 files changed, 389 insertions(+), 15 deletions(-) create mode 100644 include/zephyr/dt-bindings/clock/stm32h7rs_clock.h diff --git a/drivers/clock_control/CMakeLists.txt b/drivers/clock_control/CMakeLists.txt index 949d87d1a666d..43f86e8c7d38c 100644 --- a/drivers/clock_control/CMakeLists.txt +++ b/drivers/clock_control/CMakeLists.txt @@ -38,6 +38,8 @@ if(CONFIG_SOC_SERIES_STM32MP1X) zephyr_library_sources(clock_stm32_ll_mp1.c) elseif(CONFIG_SOC_SERIES_STM32H7X) zephyr_library_sources(clock_stm32_ll_h7.c) +elseif(CONFIG_SOC_SERIES_STM32H7RSX) + zephyr_library_sources(clock_stm32_ll_h7.c) elseif(CONFIG_SOC_SERIES_STM32H5X) zephyr_library_sources(clock_stm32_ll_h5.c) elseif(CONFIG_SOC_SERIES_STM32U5X) diff --git a/drivers/clock_control/Kconfig.stm32 b/drivers/clock_control/Kconfig.stm32 index c5f4f27364622..484b331db7c24 100644 --- a/drivers/clock_control/Kconfig.stm32 +++ b/drivers/clock_control/Kconfig.stm32 @@ -9,7 +9,7 @@ menuconfig CLOCK_CONTROL_STM32_CUBE depends on SOC_FAMILY_STM32 select USE_STM32_LL_UTILS select USE_STM32_LL_RCC if (SOC_SERIES_STM32MP1X || SOC_SERIES_STM32H7X || \ - SOC_SERIES_STM32F4X || SOC_SERIES_STM32F7X) + SOC_SERIES_STM32H7RSX || SOC_SERIES_STM32F4X || SOC_SERIES_STM32F7X) select RUNTIME_NMI if ($(dt_nodelabel_enabled,clk_hse) && \ $(dt_nodelabel_has_prop,clk_hse,css-enabled)) help @@ -69,6 +69,7 @@ config CLOCK_STM32_MCO1_SRC_LSE SOC_SERIES_STM32F7X || \ SOC_SERIES_STM32L4X || \ SOC_SERIES_STM32H7X || \ + SOC_SERIES_STM32H7RSX || \ SOC_SERIES_STM32H5X help Use LSE as source of MCO1 @@ -80,6 +81,7 @@ config CLOCK_STM32_MCO1_SRC_HSE SOC_SERIES_STM32F7X || \ SOC_SERIES_STM32L4X || \ SOC_SERIES_STM32H7X || \ + SOC_SERIES_STM32H7RSX || \ SOC_SERIES_STM32H5X help Use HSE as source of MCO1 @@ -102,6 +104,7 @@ config CLOCK_STM32_MCO1_SRC_HSI SOC_SERIES_STM32F4X || \ SOC_SERIES_STM32F7X || \ SOC_SERIES_STM32H7X || \ + SOC_SERIES_STM32H7RSX || \ SOC_SERIES_STM32H5X help Use HSI as source of MCO1 @@ -116,6 +119,7 @@ config CLOCK_STM32_MCO1_SRC_HSI48 bool "HSI48" depends on SOC_SERIES_STM32L4X || \ SOC_SERIES_STM32H7X || \ + SOC_SERIES_STM32H7RSX || \ SOC_SERIES_STM32H5X help Use HSI48 as source of MCO1 @@ -129,6 +133,7 @@ config CLOCK_STM32_MCO1_SRC_PLLCLK config CLOCK_STM32_MCO1_SRC_PLLQCLK bool "PLLQ" depends on SOC_SERIES_STM32H7X || \ + SOC_SERIES_STM32H7RSX || \ SOC_SERIES_STM32H5X help Use PLLQ as source of MCO1 @@ -171,11 +176,12 @@ config CLOCK_STM32_MCO1_DIV SOC_SERIES_STM32F7X || \ SOC_SERIES_STM32L4X || \ SOC_SERIES_STM32H7X || \ + SOC_SERIES_STM32H7RSX || \ SOC_SERIES_STM32H5X \ ) default 1 range 1 5 if SOC_SERIES_STM32F4X || SOC_SERIES_STM32F7X - range 1 15 if SOC_SERIES_STM32H7X || SOC_SERIES_STM32H5X + range 1 15 if SOC_SERIES_STM32H7X || SOC_SERIES_STM32H7RSX || SOC_SERIES_STM32H5X range 1 16 if SOC_SERIES_STM32L4X help Prescaler for MCO1 output clock @@ -194,6 +200,7 @@ config CLOCK_STM32_MCO2_SRC_SYSCLK depends on SOC_SERIES_STM32F4X || \ SOC_SERIES_STM32F7X || \ SOC_SERIES_STM32H7X || \ + SOC_SERIES_STM32H7RSX || \ SOC_SERIES_STM32H5X help Use SYSCLK as source of MCO2 @@ -209,6 +216,7 @@ config CLOCK_STM32_MCO2_SRC_HSE depends on SOC_SERIES_STM32F4X || \ SOC_SERIES_STM32F7X || \ SOC_SERIES_STM32H7X || \ + SOC_SERIES_STM32H7RSX || \ SOC_SERIES_STM32H5X help Use HSE as source of MCO2 @@ -216,6 +224,7 @@ config CLOCK_STM32_MCO2_SRC_HSE config CLOCK_STM32_MCO2_SRC_LSI bool "LSI" depends on SOC_SERIES_STM32H7X || \ + SOC_SERIES_STM32H7RSX || \ SOC_SERIES_STM32H5X help Use LSI as source of MCO2 @@ -223,6 +232,7 @@ config CLOCK_STM32_MCO2_SRC_LSI config CLOCK_STM32_MCO2_SRC_CSI bool "CSI" depends on SOC_SERIES_STM32H7X || \ + SOC_SERIES_STM32H7RSX || \ SOC_SERIES_STM32H5X help Use CSI as source of MCO2 @@ -236,6 +246,7 @@ config CLOCK_STM32_MCO2_SRC_PLLCLK config CLOCK_STM32_MCO2_SRC_PLLPCLK bool "PLLPCLK" depends on SOC_SERIES_STM32H7X || \ + SOC_SERIES_STM32H7RSX || \ SOC_SERIES_STM32H5X help Use PLLPCLK as source of MC02 @@ -243,6 +254,7 @@ config CLOCK_STM32_MCO2_SRC_PLLPCLK config CLOCK_STM32_MCO2_SRC_PLL2PCLK bool "PLL2PCLK" depends on SOC_SERIES_STM32H7X || \ + SOC_SERIES_STM32H7RSX || \ SOC_SERIES_STM32H5X help Use PLL2PCLK as source of MC02 @@ -254,11 +266,12 @@ config CLOCK_STM32_MCO2_DIV SOC_SERIES_STM32F4X || \ SOC_SERIES_STM32F7X || \ SOC_SERIES_STM32H5X || \ - SOC_SERIES_STM32H7X \ + SOC_SERIES_STM32H7X || \ + SOC_SERIES_STM32H7RSX \ ) default 1 range 1 5 if SOC_SERIES_STM32F4X || SOC_SERIES_STM32F7X - range 1 15 if SOC_SERIES_STM32H7X || SOC_SERIES_STM32H5X + range 1 15 if SOC_SERIES_STM32H7X || SOC_SERIES_STM32H7RSX || SOC_SERIES_STM32H5X help Prescaler for MCO2 output clock diff --git a/drivers/clock_control/clock_stm32_ll_h7.c b/drivers/clock_control/clock_stm32_ll_h7.c index b11e2b5c9f5b6..c9b7653556f0c 100644 --- a/drivers/clock_control/clock_stm32_ll_h7.c +++ b/drivers/clock_control/clock_stm32_ll_h7.c @@ -21,7 +21,11 @@ /* Macros to fill up prescaler values */ +#if defined(CONFIG_SOC_SERIES_STM32H7RSX) +#define z_hsi_divider(v) LL_RCC_HSI_DIV_ ## v +#else #define z_hsi_divider(v) LL_RCC_HSI_DIV ## v +#endif #define hsi_divider(v) z_hsi_divider(v) #define z_sysclk_prescaler(v) LL_RCC_SYSCLK_DIV_ ## v @@ -42,6 +46,9 @@ #define z_apb4_prescaler(v) LL_RCC_APB4_DIV_ ## v #define apb4_prescaler(v) z_apb4_prescaler(v) +#define z_apb5_prescaler(v) LL_RCC_APB5_DIV_ ## v +#define apb5_prescaler(v) z_apb5_prescaler(v) + /* Macro to check for clock feasibility */ /* It is Cortex M7's responsibility to setup clock tree */ /* This check should only be performed for the M7 core code */ @@ -81,12 +88,21 @@ #endif /* ARM Sys CPU Clock before HPRE prescaler */ +#if defined(CONFIG_SOC_SERIES_STM32H7RSX) +#define SYSCLK_FREQ ((SYSCLKSRC_FREQ)/(STM32_D1CPRE)) +#define AHB_FREQ ((SYSCLK_FREQ)/(STM32_HPRE)) +#define APB1_FREQ ((AHB_FREQ)/(STM32_PPRE1)) +#define APB2_FREQ ((AHB_FREQ)/(STM32_PPRE2)) +#define APB4_FREQ ((AHB_FREQ)/(STM32_PPRE4)) +#define APB5_FREQ ((AHB_FREQ)/(STM32_PPRE5)) +#else #define SYSCLK_FREQ ((SYSCLKSRC_FREQ)/(STM32_D1CPRE)) #define AHB_FREQ ((SYSCLK_FREQ)/(STM32_HPRE)) #define APB1_FREQ ((AHB_FREQ)/(STM32_D2PPRE1)) #define APB2_FREQ ((AHB_FREQ)/(STM32_D2PPRE2)) #define APB3_FREQ ((AHB_FREQ)/(STM32_D1PPRE)) #define APB4_FREQ ((AHB_FREQ)/(STM32_D3PPRE)) +#endif /* CONFIG_SOC_SERIES_STM32H7RSX */ /* Datasheet maximum frequency definitions */ #if defined(CONFIG_SOC_STM32H743XX) ||\ @@ -112,6 +128,11 @@ #define SYSCLK_FREQ_MAX 280000000UL #define AHB_FREQ_MAX 280000000UL #define APBx_FREQ_MAX 140000000UL +#elif defined(CONFIG_SOC_SERIES_STM32H7RSX) +/* All h7RS SoC with maximum 500MHz SYSCLK (refer to Datasheet DS14359 rev 1) */ +#define SYSCLK_FREQ_MAX 500000000UL +#define AHB_FREQ_MAX 250000000UL +#define APBx_FREQ_MAX 125000000UL #else /* Default: All h7 SoC with maximum 280MHz SYSCLK */ #define SYSCLK_FREQ_MAX 280000000UL @@ -154,7 +175,7 @@ * So, changing this prescaler is not allowed until it is made possible to * use them independently in zephyr clock subsystem. */ -#error "D1CPRE presacler can't be higher than 1" +#error "D1CPRE prescaler can't be higher than 1" #endif #endif /* CONFIG_CPU_CORTEX_M7 */ @@ -255,7 +276,11 @@ static int32_t prepare_regulator_voltage_scale(void) /* Make sure to put the CPU in highest Voltage scale during clock configuration */ /* Highest voltage is SCALE0 */ LL_PWR_SetRegulVoltageScaling(LL_PWR_REGU_VOLTAGE_SCALE0); +#if defined(CONFIG_SOC_SERIES_STM32H7RSX) + while (LL_PWR_IsActiveFlag_VOSRDY() == 0) { +#else while (LL_PWR_IsActiveFlag_VOS() == 0) { +#endif } return 0; } @@ -290,8 +315,12 @@ static int32_t optimize_regulator_voltage_scale(uint32_t sysclk_freq) LL_PWR_ConfigSupply(LL_PWR_LDO_SUPPLY); #endif LL_PWR_SetRegulVoltageScaling(LL_PWR_REGU_VOLTAGE_SCALE0); +#if defined(CONFIG_SOC_SERIES_STM32H7RSX) + while (LL_PWR_IsActiveFlag_VOSRDY() == 0) { +#else while (LL_PWR_IsActiveFlag_VOS() == 0) { - } +#endif + }; return 0; } @@ -448,10 +477,17 @@ static int stm32_clock_control_get_subsys_rate(const struct device *clock, #else uint32_t ahb_clock = get_bus_clock(SystemCoreClock, STM32_HPRE); #endif +#if defined(CONFIG_SOC_SERIES_STM32H7RSX) + uint32_t apb1_clock = get_bus_clock(ahb_clock, STM32_PPRE1); + uint32_t apb2_clock = get_bus_clock(ahb_clock, STM32_PPRE2); + uint32_t apb4_clock = get_bus_clock(ahb_clock, STM32_PPRE4); + uint32_t apb5_clock = get_bus_clock(ahb_clock, STM32_PPRE5); +#else uint32_t apb1_clock = get_bus_clock(ahb_clock, STM32_D2PPRE1); uint32_t apb2_clock = get_bus_clock(ahb_clock, STM32_D2PPRE2); uint32_t apb3_clock = get_bus_clock(ahb_clock, STM32_D1PPRE); uint32_t apb4_clock = get_bus_clock(ahb_clock, STM32_D3PPRE); +#endif ARG_UNUSED(clock); @@ -469,12 +505,22 @@ static int stm32_clock_control_get_subsys_rate(const struct device *clock, case STM32_CLOCK_BUS_APB2: *rate = apb2_clock; break; +#if !defined(CONFIG_SOC_SERIES_STM32H7RSX) case STM32_CLOCK_BUS_APB3: *rate = apb3_clock; break; +#endif /* !CONFIG_SOC_SERIES_STM32H7RSX */ case STM32_CLOCK_BUS_APB4: *rate = apb4_clock; break; +#if defined(CONFIG_SOC_SERIES_STM32H7RSX) + case STM32_CLOCK_BUS_APB5: + *rate = apb5_clock; + break; + case STM32_CLOCK_BUS_AHB5: + *rate = ahb_clock; + break; +#endif /* CONFIG_SOC_SERIES_STM32H7RSX */ case STM32_SRC_SYSCLK: *rate = get_hclk_frequency(); break; @@ -522,6 +568,15 @@ static int stm32_clock_control_get_subsys_rate(const struct device *clock, STM32_PLL_N_MULTIPLIER, STM32_PLL_R_DIVISOR); break; +#if defined(CONFIG_SOC_SERIES_STM32H7RSX) + case STM32_SRC_PLL1_S: + *rate = get_pllout_frequency(get_pllsrc_frequency(), + STM32_PLL_M_DIVISOR, + STM32_PLL_N_MULTIPLIER, + STM32_PLL_S_DIVISOR); + break; + /* PLL 1 has no T-divider */ +#endif /* CONFIG_SOC_SERIES_STM32H7RSX */ #endif /* STM32_PLL_ENABLED */ #if defined(STM32_PLL2_ENABLED) case STM32_SRC_PLL2_P: @@ -542,6 +597,20 @@ static int stm32_clock_control_get_subsys_rate(const struct device *clock, STM32_PLL2_N_MULTIPLIER, STM32_PLL2_R_DIVISOR); break; +#if defined(CONFIG_SOC_SERIES_STM32H7RSX) + case STM32_SRC_PLL2_S: + *rate = get_pllout_frequency(get_pllsrc_frequency(), + STM32_PLL2_M_DIVISOR, + STM32_PLL2_N_MULTIPLIER, + STM32_PLL2_S_DIVISOR); + break; + case STM32_SRC_PLL2_T: + *rate = get_pllout_frequency(get_pllsrc_frequency(), + STM32_PLL2_M_DIVISOR, + STM32_PLL2_N_MULTIPLIER, + STM32_PLL2_T_DIVISOR); + break; +#endif /* CONFIG_SOC_SERIES_STM32H7RSX */ #endif /* STM32_PLL2_ENABLED */ #if defined(STM32_PLL3_ENABLED) case STM32_SRC_PLL3_P: @@ -562,6 +631,15 @@ static int stm32_clock_control_get_subsys_rate(const struct device *clock, STM32_PLL3_N_MULTIPLIER, STM32_PLL3_R_DIVISOR); break; +#if defined(CONFIG_SOC_SERIES_STM32H7RSX) + case STM32_SRC_PLL3_S: + *rate = get_pllout_frequency(get_pllsrc_frequency(), + STM32_PLL3_M_DIVISOR, + STM32_PLL3_N_MULTIPLIER, + STM32_PLL3_S_DIVISOR); + break; + /* PLL 3 has no T-divider */ +#endif /* CONFIG_SOC_SERIES_STM32H7RSX */ #endif /* STM32_PLL3_ENABLED */ default: return -ENOTSUP; @@ -739,6 +817,12 @@ static int set_up_plls(void) LL_RCC_PLL1R_Enable(); } +#if defined(CONFIG_SOC_SERIES_STM32H7RSX) + if (IS_ENABLED(STM32_PLL_S_ENABLED)) { + LL_RCC_PLL1_SetS(STM32_PLL_S_DIVISOR); + LL_RCC_PLL1S_Enable(); + } +#endif /* CONFIG_SOC_SERIES_STM32H7RSX */ LL_RCC_PLL1_Enable(); while (LL_RCC_PLL1_IsReady() != 1U) { } @@ -777,6 +861,18 @@ static int set_up_plls(void) LL_RCC_PLL2R_Enable(); } +#if defined(CONFIG_SOC_SERIES_STM32H7RSX) + if (IS_ENABLED(STM32_PLL2_S_ENABLED)) { + LL_RCC_PLL2_SetS(STM32_PLL2_S_DIVISOR); + LL_RCC_PLL2S_Enable(); + } + + if (IS_ENABLED(STM32_PLL2_T_ENABLED)) { + LL_RCC_PLL2_SetT(STM32_PLL2_T_DIVISOR); + LL_RCC_PLL2T_Enable(); + } + +#endif /* CONFIG_SOC_SERIES_STM32H7RSX */ LL_RCC_PLL2_Enable(); while (LL_RCC_PLL2_IsReady() != 1U) { } @@ -815,6 +911,13 @@ static int set_up_plls(void) LL_RCC_PLL3R_Enable(); } +#if defined(CONFIG_SOC_SERIES_STM32H7RSX) + if (IS_ENABLED(STM32_PLL3_S_ENABLED)) { + LL_RCC_PLL3_SetS(STM32_PLL3_S_DIVISOR); + LL_RCC_PLL3S_Enable(); + } + +#endif /* CONFIG_SOC_SERIES_STM32H7RSX */ LL_RCC_PLL3_Enable(); while (LL_RCC_PLL3_IsReady() != 1U) { } @@ -830,6 +933,91 @@ static int set_up_plls(void) return 0; } +#if defined(CONFIG_SOC_SERIES_STM32H7RSX) +/* adapted from the stm32cube SystemCoreClockUpdate*/ +void stm32_system_clock_update(void) +{ + uint32_t sysclk, hsivalue, pllsource, pllm, pllp, core_presc; + float_t pllfracn, pllvco; + + /* Get SYSCLK source */ + switch (RCC->CFGR & RCC_CFGR_SWS) { + case 0x00: /* HSI used as system clock source (default after reset) */ + sysclk = (HSI_VALUE >> ((RCC->CR & RCC_CR_HSIDIV) + >> RCC_CR_HSIDIV_Pos)); + break; + + case 0x08: /* CSI used as system clock source */ + sysclk = CSI_VALUE; + break; + + case 0x10: /* HSE used as system clock source */ + sysclk = HSE_VALUE; + break; + + case 0x18: /* PLL1 used as system clock source */ + /* + * PLL1_VCO = (HSE_VALUE or HSI_VALUE or CSI_VALUE/ PLLM) * PLLN + * SYSCLK = PLL1_VCO / PLL1R + */ + pllsource = (RCC->PLLCKSELR & RCC_PLLCKSELR_PLLSRC); + pllm = ((RCC->PLLCKSELR & RCC_PLLCKSELR_DIVM1) >> RCC_PLLCKSELR_DIVM1_Pos); + + if ((RCC->PLLCFGR & RCC_PLLCFGR_PLL1FRACEN) != 0U) { + pllfracn = (float_t)(uint32_t)(((RCC->PLL1FRACR & RCC_PLL1FRACR_FRACN) + >> RCC_PLL1FRACR_FRACN_Pos)); + } else { + pllfracn = (float_t)0U; + } + + if (pllm != 0U) { + switch (pllsource) { + case 0x02: /* HSE used as PLL1 clock source */ + pllvco = ((float_t)HSE_VALUE / (float_t)pllm) * + ((float_t)(uint32_t)(RCC->PLL1DIVR1 & RCC_PLL1DIVR1_DIVN) + + (pllfracn/(float_t)0x2000) + (float_t)1); + break; + + case 0x01: /* CSI used as PLL1 clock source */ + pllvco = ((float_t)CSI_VALUE / (float_t)pllm) * + ((float_t)(uint32_t)(RCC->PLL1DIVR1 & RCC_PLL1DIVR1_DIVN) + + (pllfracn/(float_t)0x2000) + (float_t)1); + break; + + case 0x00: /* HSI used as PLL1 clock source */ + default: + hsivalue = (HSI_VALUE >> ((RCC->CR & RCC_CR_HSIDIV) >> + RCC_CR_HSIDIV_Pos)); + pllvco = ((float_t)hsivalue / (float_t)pllm) * + ((float_t)(uint32_t)(RCC->PLL1DIVR1 & RCC_PLL1DIVR1_DIVN) + + (pllfracn/(float_t)0x2000) + (float_t)1); + break; + } + + pllp = (((RCC->PLL1DIVR1 & RCC_PLL1DIVR1_DIVP) >> + RCC_PLL1DIVR1_DIVP_Pos) + 1U); + sysclk = (uint32_t)(float_t)(pllvco/(float_t)pllp); + } else { + sysclk = 0U; + } + break; + + default: /* Unexpected, default to HSI used as system clk source (default after reset) */ + sysclk = (HSI_VALUE >> ((RCC->CR & RCC_CR_HSIDIV) >> RCC_CR_HSIDIV_Pos)); + break; + } + + /* system clock frequency : CM7 CPU frequency */ + core_presc = (RCC->CDCFGR & RCC_CDCFGR_CPRE); + + if (core_presc >= 8U) { + SystemCoreClock = (sysclk >> (core_presc - RCC_CDCFGR_CPRE_3 + 1U)); + } else { + SystemCoreClock = sysclk; + } +} +#endif /* CONFIG_SOC_SERIES_STM32H7RSX */ + int stm32_clock_control_init(const struct device *dev) { int r = 0; @@ -843,10 +1031,10 @@ int stm32_clock_control_init(const struct device *dev) defined(CONFIG_SOC_STM32H7B0XX) || defined(CONFIG_SOC_STM32H7B0XXQ) || \ defined(CONFIG_SOC_STM32H7B3XX) || defined(CONFIG_SOC_STM32H7B3XXQ) LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_HSEM); -#else +#elif !defined(CONFIG_SOC_SERIES_STM32H7RSX) + /* The stm32h7RS serie has no HSEM peripheral */ LL_AHB4_GRP1_EnableClock(LL_AHB4_GRP1_PERIPH_HSEM); #endif - z_stm32_hsem_lock(CFG_HW_RCC_SEMID, HSEM_LOCK_DEFAULT_RETRY); /* Configure MCO1/MCO2 based on Kconfig */ @@ -871,22 +1059,38 @@ int stm32_clock_control_init(const struct device *dev) STM32_HPRE); /* Set flash latency */ + /* AHB/AXI/HCLK clock is SYSCLK / HPRE */ /* If freq increases, set flash latency before any clock setting */ if (new_hclk_freq > old_hclk_freq) { LL_SetFlashLatency(new_hclk_freq); } +#if defined(CONFIG_SOC_SERIES_STM32H7RSX) + /* + * The default Flash latency is 3 WS which is not enough, + * set higher and correct later if needed + */ + LL_FLASH_SetLatency(LL_FLASH_LATENCY_6); +#endif /* CONFIG_SOC_SERIES_STM32H7RSX */ /* Preset the prescalers prior to choosing SYSCLK */ /* Prevents APB clock to go over limits */ /* Set buses (Sys,AHB, APB1, APB2 & APB4) prescalers */ LL_RCC_SetSysPrescaler(sysclk_prescaler(STM32_D1CPRE)); LL_RCC_SetAHBPrescaler(ahb_prescaler(STM32_HPRE)); +#if defined(CONFIG_SOC_SERIES_STM32H7RSX) + LL_RCC_SetAPB1Prescaler(apb1_prescaler(STM32_PPRE1)); + LL_RCC_SetAPB2Prescaler(apb2_prescaler(STM32_PPRE2)); + LL_RCC_SetAPB4Prescaler(apb4_prescaler(STM32_PPRE4)); + LL_RCC_SetAPB5Prescaler(apb5_prescaler(STM32_PPRE5)); + +#else LL_RCC_SetAPB1Prescaler(apb1_prescaler(STM32_D2PPRE1)); LL_RCC_SetAPB2Prescaler(apb2_prescaler(STM32_D2PPRE2)); LL_RCC_SetAPB3Prescaler(apb3_prescaler(STM32_D1PPRE)); LL_RCC_SetAPB4Prescaler(apb4_prescaler(STM32_D3PPRE)); +#endif /* Set up sys clock */ if (IS_ENABLED(STM32_SYSCLK_SRC_PLL)) { /* Set PLL1 as System Clock Source */ diff --git a/drivers/clock_control/clock_stm32_ll_mco.h b/drivers/clock_control/clock_stm32_ll_mco.h index d98c4a116e8e1..b526f13a1b22d 100644 --- a/drivers/clock_control/clock_stm32_ll_mco.h +++ b/drivers/clock_control/clock_stm32_ll_mco.h @@ -33,7 +33,8 @@ #elif CONFIG_CLOCK_STM32_MCO1_SRC_PLLQCLK #if (CONFIG_SOC_SERIES_STM32G0X || CONFIG_SOC_SERIES_STM32WLX) #define MCO1_SOURCE LL_RCC_MCO1SOURCE_PLLQCLK - #elif (CONFIG_SOC_SERIES_STM32H5X || CONFIG_SOC_SERIES_STM32H7X) + #elif (CONFIG_SOC_SERIES_STM32H5X || \ + CONFIG_SOC_SERIES_STM32H7X || CONFIG_SOC_SERIES_STM32H7RSX) #define MCO1_SOURCE LL_RCC_MCO1SOURCE_PLL1QCLK #else #error "PLLQCLK is not a valid clock source on your SOC" diff --git a/dts/bindings/clock/st,stm32h7rs-pll-clock.yaml b/dts/bindings/clock/st,stm32h7rs-pll-clock.yaml index 0d03cc7272a9e..cb2980dd39c5a 100644 --- a/dts/bindings/clock/st,stm32h7rs-pll-clock.yaml +++ b/dts/bindings/clock/st,stm32h7rs-pll-clock.yaml @@ -30,11 +30,11 @@ properties: div-s: type: int description: | - PLL division factor for pllx_s_ck + PLL division factor for pllx_s_ck : valid for PLL1, 2, 3 Valid range: 1 - 8 div-t: type: int description: | - PLL division factor for pllx_t_ck + PLL division factor for pllx_t_ck : valid for PLL2 Valid range: 1 - 8 diff --git a/include/zephyr/drivers/clock_control/stm32_clock_control.h b/include/zephyr/drivers/clock_control/stm32_clock_control.h index 062fae034e311..a9ce911e5c7f0 100644 --- a/include/zephyr/drivers/clock_control/stm32_clock_control.h +++ b/include/zephyr/drivers/clock_control/stm32_clock_control.h @@ -44,6 +44,8 @@ #include #elif defined(CONFIG_SOC_SERIES_STM32H7X) #include +#elif defined(CONFIG_SOC_SERIES_STM32H7RSX) +#include #elif defined(CONFIG_SOC_SERIES_STM32U5X) #include #elif defined(CONFIG_SOC_SERIES_STM32WBAX) @@ -61,6 +63,7 @@ #define STM32_APB1_PRESCALER DT_PROP(DT_NODELABEL(rcc), apb1_prescaler) #define STM32_APB2_PRESCALER DT_PROP(DT_NODELABEL(rcc), apb2_prescaler) #define STM32_APB3_PRESCALER DT_PROP(DT_NODELABEL(rcc), apb3_prescaler) +#define STM32_APB5_PRESCALER DT_PROP(DT_NODELABEL(rcc), apb5_prescaler) #define STM32_APB7_PRESCALER DT_PROP(DT_NODELABEL(rcc), apb7_prescaler) #define STM32_AHB3_PRESCALER DT_PROP(DT_NODELABEL(rcc), ahb3_prescaler) #define STM32_AHB4_PRESCALER DT_PROP(DT_NODELABEL(rcc), ahb4_prescaler) @@ -86,13 +89,22 @@ #define STM32_ADC12_PRESCALER DT_PROP(DT_NODELABEL(rcc), adc12_prescaler) #define STM32_ADC34_PRESCALER DT_PROP(DT_NODELABEL(rcc), adc34_prescaler) -/** STM2H7 specifics RCC dividers */ +/** STM2H7RS specific RCC dividers */ +#if defined(CONFIG_SOC_SERIES_STM32H7RSX) +#define STM32_D1CPRE DT_PROP(DT_NODELABEL(rcc), dcpre) +#define STM32_HPRE DT_PROP(DT_NODELABEL(rcc), hpre) +#define STM32_PPRE1 DT_PROP(DT_NODELABEL(rcc), ppre1) +#define STM32_PPRE2 DT_PROP(DT_NODELABEL(rcc), ppre2) +#define STM32_PPRE4 DT_PROP(DT_NODELABEL(rcc), ppre4) +#define STM32_PPRE5 DT_PROP(DT_NODELABEL(rcc), ppre5) +#else #define STM32_D1CPRE DT_PROP(DT_NODELABEL(rcc), d1cpre) #define STM32_HPRE DT_PROP(DT_NODELABEL(rcc), hpre) #define STM32_D2PPRE1 DT_PROP(DT_NODELABEL(rcc), d2ppre1) #define STM32_D2PPRE2 DT_PROP(DT_NODELABEL(rcc), d2ppre2) #define STM32_D1PPRE DT_PROP(DT_NODELABEL(rcc), d1ppre) #define STM32_D3PPRE DT_PROP(DT_NODELABEL(rcc), d3ppre) +#endif /* CONFIG_SOC_SERIES_STM32H7RSX */ /** STM2WBA specifics RCC dividers */ #define STM32_AHB5_DIV DT_PROP(DT_NODELABEL(rcc), ahb5_div) @@ -133,7 +145,8 @@ DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(pll), st_stm32u5_pll_clock, okay) || \ DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(pll), st_stm32wb_pll_clock, okay) || \ DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(pll), st_stm32wba_pll_clock, okay) || \ - DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(pll), st_stm32h7_pll_clock, okay) + DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(pll), st_stm32h7_pll_clock, okay) || \ + DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(pll), st_stm32h7rs_pll_clock, okay) #define STM32_PLL_ENABLED 1 #define STM32_PLL_M_DIVISOR DT_PROP(DT_NODELABEL(pll), div_m) #define STM32_PLL_N_MULTIPLIER DT_PROP(DT_NODELABEL(pll), mul_n) @@ -143,6 +156,8 @@ #define STM32_PLL_Q_DIVISOR DT_PROP_OR(DT_NODELABEL(pll), div_q, 1) #define STM32_PLL_R_ENABLED DT_NODE_HAS_PROP(DT_NODELABEL(pll), div_r) #define STM32_PLL_R_DIVISOR DT_PROP_OR(DT_NODELABEL(pll), div_r, 1) +#define STM32_PLL_S_ENABLED DT_NODE_HAS_PROP(DT_NODELABEL(pll), div_s) +#define STM32_PLL_S_DIVISOR DT_PROP_OR(DT_NODELABEL(pll), div_s, 1) #define STM32_PLL_FRACN_ENABLED DT_NODE_HAS_PROP(DT_NODELABEL(pll), fracn) #define STM32_PLL_FRACN_VALUE DT_PROP_OR(DT_NODELABEL(pll), fracn, 1) #endif @@ -164,7 +179,8 @@ #endif #if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(pll2), st_stm32u5_pll_clock, okay) || \ - DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(pll2), st_stm32h7_pll_clock, okay) + DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(pll2), st_stm32h7_pll_clock, okay) || \ + DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(pll2), st_stm32h7rs_pll_clock, okay) #define STM32_PLL2_ENABLED 1 #define STM32_PLL2_M_DIVISOR DT_PROP(DT_NODELABEL(pll2), div_m) #define STM32_PLL2_N_MULTIPLIER DT_PROP(DT_NODELABEL(pll2), mul_n) @@ -174,12 +190,17 @@ #define STM32_PLL2_Q_DIVISOR DT_PROP_OR(DT_NODELABEL(pll2), div_q, 1) #define STM32_PLL2_R_ENABLED DT_NODE_HAS_PROP(DT_NODELABEL(pll2), div_r) #define STM32_PLL2_R_DIVISOR DT_PROP_OR(DT_NODELABEL(pll2), div_r, 1) +#define STM32_PLL2_S_ENABLED DT_NODE_HAS_PROP(DT_NODELABEL(pll2), div_s) +#define STM32_PLL2_S_DIVISOR DT_PROP_OR(DT_NODELABEL(pll2), div_s, 1) +#define STM32_PLL2_T_ENABLED DT_NODE_HAS_PROP(DT_NODELABEL(pll2), div_t) +#define STM32_PLL2_T_DIVISOR DT_PROP_OR(DT_NODELABEL(pll2), div_t, 1) #define STM32_PLL2_FRACN_ENABLED DT_NODE_HAS_PROP(DT_NODELABEL(pll2), fracn) #define STM32_PLL2_FRACN_VALUE DT_PROP_OR(DT_NODELABEL(pll2), fracn, 1) #endif #if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(pll3), st_stm32h7_pll_clock, okay) || \ - DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(pll3), st_stm32u5_pll_clock, okay) + DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(pll3), st_stm32u5_pll_clock, okay) || \ + DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(pll3), st_stm32h7rs_pll_clock, okay) #define STM32_PLL3_ENABLED 1 #define STM32_PLL3_M_DIVISOR DT_PROP(DT_NODELABEL(pll3), div_m) #define STM32_PLL3_N_MULTIPLIER DT_PROP(DT_NODELABEL(pll3), mul_n) @@ -189,6 +210,8 @@ #define STM32_PLL3_Q_DIVISOR DT_PROP_OR(DT_NODELABEL(pll3), div_q, 1) #define STM32_PLL3_R_ENABLED DT_NODE_HAS_PROP(DT_NODELABEL(pll3), div_r) #define STM32_PLL3_R_DIVISOR DT_PROP_OR(DT_NODELABEL(pll3), div_r, 1) +#define STM32_PLL3_S_ENABLED DT_NODE_HAS_PROP(DT_NODELABEL(pll3), div_s) +#define STM32_PLL3_S_DIVISOR DT_PROP_OR(DT_NODELABEL(pll3), div_s, 1) #define STM32_PLL3_FRACN_ENABLED DT_NODE_HAS_PROP(DT_NODELABEL(pll3), fracn) #define STM32_PLL3_FRACN_VALUE DT_PROP_OR(DT_NODELABEL(pll3), fracn, 1) #endif diff --git a/include/zephyr/dt-bindings/clock/stm32h7rs_clock.h b/include/zephyr/dt-bindings/clock/stm32h7rs_clock.h new file mode 100644 index 0000000000000..579ae56b0e250 --- /dev/null +++ b/include/zephyr/dt-bindings/clock/stm32h7rs_clock.h @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2024 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ +#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_STM32H7RS_CLOCK_H_ +#define ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_STM32H7RS_CLOCK_H_ + +#include "stm32_common_clocks.h" + +/** Domain clocks */ + +/* RM0477 */ + +/** System clock */ +/* defined in stm32_common_clocks.h */ + +/** Fixed clocks */ +/* Low speed clocks defined in stm32_common_clocks.h */ +#define STM32_SRC_HSE (STM32_SRC_LSI + 1) +#define STM32_SRC_HSI48 (STM32_SRC_HSE + 1) +#define STM32_SRC_HSI_KER (STM32_SRC_HSI48 + 1) /* HSI + HSIKERON */ +#define STM32_SRC_CSI_KER (STM32_SRC_HSI_KER + 1) /* CSI + CSIKERON */ +/** PLL outputs */ +#define STM32_SRC_PLL1_P (STM32_SRC_CSI_KER + 1) +#define STM32_SRC_PLL1_Q (STM32_SRC_PLL1_P + 1) +#define STM32_SRC_PLL1_R (STM32_SRC_PLL1_Q + 1) +#define STM32_SRC_PLL1_S (STM32_SRC_PLL1_R + 1) +#define STM32_SRC_PLL2_P (STM32_SRC_PLL1_S + 1) +#define STM32_SRC_PLL2_Q (STM32_SRC_PLL2_P + 1) +#define STM32_SRC_PLL2_R (STM32_SRC_PLL2_Q + 1) +#define STM32_SRC_PLL2_S (STM32_SRC_PLL2_R + 1) +#define STM32_SRC_PLL2_T (STM32_SRC_PLL2_S + 1) +#define STM32_SRC_PLL3_P (STM32_SRC_PLL2_T + 1) +#define STM32_SRC_PLL3_Q (STM32_SRC_PLL3_P + 1) +#define STM32_SRC_PLL3_R (STM32_SRC_PLL3_Q + 1) +#define STM32_SRC_PLL3_S (STM32_SRC_PLL3_R + 1) + +/** Clock muxes */ +#define STM32_SRC_CKPER (STM32_SRC_PLL3_S + 1) +/** Others: Not yet supported */ + +/** Bus clocks */ +#define STM32_CLOCK_BUS_AHB1 0x138 +#define STM32_CLOCK_BUS_AHB2 0x13C +#define STM32_CLOCK_BUS_AHB3 0x158 +#define STM32_CLOCK_BUS_AHB4 0x140 +#define STM32_CLOCK_BUS_AHB5 0x134 +#define STM32_CLOCK_BUS_APB1 0x148 +#define STM32_CLOCK_BUS_APB1_2 0x14C +#define STM32_CLOCK_BUS_APB2 0x150 +#define STM32_CLOCK_BUS_APB4 0x154 +#define STM32_CLOCK_BUS_APB5 0x144 +#define STM32_PERIPH_BUS_MIN STM32_CLOCK_BUS_AHB5 +#define STM32_PERIPH_BUS_MAX STM32_CLOCK_BUS_AHB3 + +#define STM32_CLOCK_REG_MASK 0xFFU +#define STM32_CLOCK_REG_SHIFT 0U +#define STM32_CLOCK_SHIFT_MASK 0x1FU +#define STM32_CLOCK_SHIFT_SHIFT 8U +#define STM32_CLOCK_MASK_MASK 0x7U +#define STM32_CLOCK_MASK_SHIFT 13U +#define STM32_CLOCK_VAL_MASK 0x7U +#define STM32_CLOCK_VAL_SHIFT 16U + +/** + * @brief STM32H7RS clock configuration bit field. + * + * - reg (0/1) [ 0 : 7 ] + * - shift (0..31) [ 8 : 12 ] + * - mask (0x1, 0x3, 0x7) [ 13 : 15 ] + * - val (0..3) [ 16 : 18 ] + * + * @param reg RCC_DxCCIP register offset + * @param shift Position within RCC_DxCCIP. + * @param mask Mask for the RCC_DxCCIP field. + * @param val Clock value (0, 1, 2 or 3). + */ +#define STM32_CLOCK(val, mask, shift, reg) \ + ((((reg) & STM32_CLOCK_REG_MASK) << STM32_CLOCK_REG_SHIFT) | \ + (((shift) & STM32_CLOCK_SHIFT_MASK) << STM32_CLOCK_SHIFT_SHIFT) | \ + (((mask) & STM32_CLOCK_MASK_MASK) << STM32_CLOCK_MASK_SHIFT) | \ + (((val) & STM32_CLOCK_VAL_MASK) << STM32_CLOCK_VAL_SHIFT)) + +/** @brief RCC_DxCCIP register offset (RM0477.pdf) */ +#define D1CCIPR_REG 0x4C +#define D2CCIPR_REG 0x50 +#define D3CCIPR_REG 0x54 +#define D4CCIPR_REG 0x58 + +/** @brief RCC_BDCR register offset */ +#define BDCR_REG 0x70 + +/** @brief Device domain clocks selection helpers (RM0477.pdf) */ + +/* TODO to be completed */ + +/** D1CCIPR devices */ +#define FMC_SEL(val) STM32_CLOCK(val, 3, 0, D1CCIPR_REG) +#define SDMMC_SEL(val) STM32_CLOCK(val, 1, 2, D1CCIPR_REG) +#define XSPI1_SEL(val) STM32_CLOCK(val, 3, 4, D1CCIPR_REG) +#define XSPI2_SEL(val) STM32_CLOCK(val, 3, 6, D1CCIPR_REG) +#define ADC_SEL(val) STM32_CLOCK(val, 3, 24, D1CCIPR_REG) +#define CKPER_SEL(val) STM32_CLOCK(val, 3, 28, D1CCIPR_REG) + +/** D2CCIPR devices */ +#define USART234578_SEL(val) STM32_CLOCK(val, 7, 0, D2CCIPR_REG) +#define SPI23_SEL(val) STM32_CLOCK(val, 7, 4, D2CCIPR_REG) +#define I2C23_SEL(val) STM32_CLOCK(val, 3, 8, D2CCIPR_REG) +#define I2C1_SEL(val) STM32_CLOCK(val, 3, 12, D2CCIPR_REG) +#define I3C1_SEL(val) STM32_CLOCK(val, 3, 12, D2CCIPR_REG) +#define LPTIM1_SEL(val) STM32_CLOCK(val, 7, 16, D2CCIPR_REG) +#define FDCAN_SEL(val) STM32_CLOCK(val, 3, 22, D2CCIPR_REG) + +/** D3CCIPR devices */ +#define USART1_SEL(val) STM32_CLOCK(val, 7, 0, D3CCIPR_REG) +#define SPI45_SEL(val) STM32_CLOCK(val, 7, 4, D3CCIPR_REG) +#define SPI1_SEL(val) STM32_CLOCK(val, 7, 8, D3CCIPR_REG) +#define SAI1_SEL(val) STM32_CLOCK(val, 7, 16, D3CCIPR_REG) +#define SAI2_SEL(val) STM32_CLOCK(val, 7, 20, D3CCIPR_REG) + +/** D4CCIPR devices */ +#define LPUART1_SEL(val) STM32_CLOCK(val, 7, 0, D4CCIPR_REG) +#define SPI6_SEL(val) STM32_CLOCK(val, 7, 4, D4CCIPR_REG) +#define LPTIM23_SEL(val) STM32_CLOCK(val, 7, 8, D4CCIPR_REG) +#define LPTIM45_SEL(val) STM32_CLOCK(val, 7, 12, D4CCIPR_REG) + +/** BDCR devices */ +#define RTC_SEL(val) STM32_CLOCK(val, 3, 8, BDCR_REG) + +#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_STM32H7RS_CLOCK_H_ */ From c0750e9867f6b0f347d0c07f381253c8e147f880 Mon Sep 17 00:00:00 2001 From: Francois Ramu Date: Wed, 6 Mar 2024 18:04:22 +0100 Subject: [PATCH 1891/2849] drivers: pinctrl: stm32 pinctrl driver supporting the stm32H7RS Introduce the stm32h7RS serie to the pin control driver, New GPIO port M, N, O, P Then add the complete list and from A to P (16 port coded on 5 bits) Signed-off-by: Francois Ramu --- drivers/pinctrl/pinctrl_stm32.c | 5 +++++ include/zephyr/dt-bindings/pinctrl/stm32-pinctrl-common.h | 6 +++++- include/zephyr/dt-bindings/pinctrl/stm32-pinctrl.h | 6 +++--- 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/drivers/pinctrl/pinctrl_stm32.c b/drivers/pinctrl/pinctrl_stm32.c index b6a1b550e8bfb..9dc3e26f37cca 100644 --- a/drivers/pinctrl/pinctrl_stm32.c +++ b/drivers/pinctrl/pinctrl_stm32.c @@ -58,6 +58,11 @@ static const struct device *const gpio_ports[] = { DEVICE_DT_GET_OR_NULL(DT_NODELABEL(gpioi)), DEVICE_DT_GET_OR_NULL(DT_NODELABEL(gpioj)), DEVICE_DT_GET_OR_NULL(DT_NODELABEL(gpiok)), + DEVICE_DT_GET_OR_NULL(DT_NODELABEL(gpiol)), + DEVICE_DT_GET_OR_NULL(DT_NODELABEL(gpiom)), + DEVICE_DT_GET_OR_NULL(DT_NODELABEL(gpion)), + DEVICE_DT_GET_OR_NULL(DT_NODELABEL(gpioo)), + DEVICE_DT_GET_OR_NULL(DT_NODELABEL(gpiop)), }; /** Number of GPIO ports. */ diff --git a/include/zephyr/dt-bindings/pinctrl/stm32-pinctrl-common.h b/include/zephyr/dt-bindings/pinctrl/stm32-pinctrl-common.h index 0e752e54d4e0e..0c5933c580e50 100644 --- a/include/zephyr/dt-bindings/pinctrl/stm32-pinctrl-common.h +++ b/include/zephyr/dt-bindings/pinctrl/stm32-pinctrl-common.h @@ -22,9 +22,13 @@ #define STM32_PORTI 8 #define STM32_PORTJ 9 #define STM32_PORTK 10 /* IO port K */ +#define STM32_PORTM 12 /* IO port M (0xC) */ +#define STM32_PORTN 13 +#define STM32_PORTO 14 +#define STM32_PORTP 15 /* IO port P (0xF) */ #ifndef STM32_PORTS_MAX -#define STM32_PORTS_MAX (STM32_PORTK + 1) +#define STM32_PORTS_MAX (STM32_PORTP + 1) #endif /** diff --git a/include/zephyr/dt-bindings/pinctrl/stm32-pinctrl.h b/include/zephyr/dt-bindings/pinctrl/stm32-pinctrl.h index f5d0309897a86..52612f6948d51 100644 --- a/include/zephyr/dt-bindings/pinctrl/stm32-pinctrl.h +++ b/include/zephyr/dt-bindings/pinctrl/stm32-pinctrl.h @@ -44,7 +44,7 @@ #define STM32_LINE_SHIFT 5U #define STM32_LINE_MASK 0xFU #define STM32_PORT_SHIFT 9U -#define STM32_PORT_MASK 0xFU +#define STM32_PORT_MASK 0x1FU /** * @brief Pin configuration configuration bit field. @@ -53,9 +53,9 @@ * * - mode [ 0 : 4 ] * - line [ 5 : 8 ] - * - port [ 9 : 12 ] + * - port [ 9 : 13 ] * - * @param port Port ('A'..'K') + * @param port Port ('A'..'P') * @param line Pin (0..15) * @param mode Mode (ANALOG, GPIO_IN, ALTERNATE). */ From bde663f4840f79601d10dd74a7d11ffc84e9c0a7 Mon Sep 17 00:00:00 2001 From: Francois Ramu Date: Wed, 6 Mar 2024 18:01:12 +0100 Subject: [PATCH 1892/2849] drivers: gpio: stm32 gpio driver supporting the stm32H7RS Introduce the stm32h7RS serie to the gpio driver, based on the stm32h7 The SBS controller is used to configure the EXTI line among the different GPIO port. Signed-off-by: Francois Ramu --- drivers/gpio/gpio_stm32.c | 28 +++++++++++++++++++++++++++- drivers/gpio/gpio_stm32.h | 14 ++++++++++++++ 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/drivers/gpio/gpio_stm32.c b/drivers/gpio/gpio_stm32.c index 2c3a9fc6ca202..6ba545560da6f 100644 --- a/drivers/gpio/gpio_stm32.c +++ b/drivers/gpio/gpio_stm32.c @@ -305,11 +305,16 @@ static inline uint32_t gpio_stm32_pin_to_exti_line(int pin) return ((pin % 4 * 4) << 16) | (pin / 4); #elif DT_HAS_COMPAT_STATUS_OKAY(st_stm32g0_exti) return ((pin & 0x3) << (16 + 3)) | (pin >> 2); +#elif DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7rs_exti) + /* Gives the LL_SBS_EXTI_LINEn corresponding to the pin */ + return (((pin % 4 * 4) << LL_SBS_REGISTER_PINPOS_SHFT) | (pin / 4)); #else return (0xF << ((pin % 4 * 4) + 16)) | (pin / 4); #endif } + +/* Set the EXTI line corresponding to the PORT [STM32_PORTA .. ] and pin [0..15] */ static void gpio_stm32_set_exti_source(int port, int pin) { uint32_t line = gpio_stm32_pin_to_exti_line(pin); @@ -332,12 +337,15 @@ static void gpio_stm32_set_exti_source(int port, int pin) #elif DT_HAS_COMPAT_STATUS_OKAY(st_stm32g0_exti) LL_EXTI_SetEXTISource(port, line); +#elif DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7rs_exti) + LL_SBS_SetEXTISource(port, line); #else LL_SYSCFG_SetEXTISource(port, line); #endif z_stm32_hsem_unlock(CFG_HW_EXTI_SEMID); } +/* Gives the PORT [STM32_PORTA .. ] corresponding to the EXTI line of the pin [0..15] */ static int gpio_stm32_get_exti_source(int pin) { uint32_t line = gpio_stm32_pin_to_exti_line(pin); @@ -347,6 +355,8 @@ static int gpio_stm32_get_exti_source(int pin) port = LL_GPIO_AF_GetEXTISource(line); #elif DT_HAS_COMPAT_STATUS_OKAY(st_stm32g0_exti) port = LL_EXTI_GetEXTISource(line); +#elif DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7rs_exti) + port = LL_SBS_GetEXTISource(line); #else port = LL_SYSCFG_GetEXTISource(line); #endif @@ -375,14 +385,18 @@ static int gpio_stm32_enable_int(int port, int pin) defined(CONFIG_SOC_SERIES_STM32F4X) || \ defined(CONFIG_SOC_SERIES_STM32F7X) || \ defined(CONFIG_SOC_SERIES_STM32H7X) || \ + defined(CONFIG_SOC_SERIES_STM32H7RSX) || \ defined(CONFIG_SOC_SERIES_STM32L1X) || \ defined(CONFIG_SOC_SERIES_STM32L4X) || \ defined(CONFIG_SOC_SERIES_STM32G4X) const struct device *const clk = DEVICE_DT_GET(STM32_CLOCK_CONTROL_NODE); struct stm32_pclken pclken = { -#ifdef CONFIG_SOC_SERIES_STM32H7X +#if defined(CONFIG_SOC_SERIES_STM32H7X) .bus = STM32_CLOCK_BUS_APB4, .enr = LL_APB4_GRP1_PERIPH_SYSCFG +#elif defined(CONFIG_SOC_SERIES_STM32H7RSX) + .bus = STM32_CLOCK_BUS_APB4, + .enr = LL_APB4_GRP1_PERIPH_SBS #else .bus = STM32_CLOCK_BUS_APB2, .enr = LL_APB2_GRP1_PERIPH_SYSCFG @@ -828,3 +842,15 @@ GPIO_DEVICE_INIT_STM32(j, J); #if DT_NODE_HAS_STATUS(DT_NODELABEL(gpiok), okay) GPIO_DEVICE_INIT_STM32(k, K); #endif /* DT_NODE_HAS_STATUS(DT_NODELABEL(gpiok), okay) */ +#if DT_NODE_HAS_STATUS(DT_NODELABEL(gpiom), okay) +GPIO_DEVICE_INIT_STM32(m, M); +#endif /* DT_NODE_HAS_STATUS(DT_NODELABEL(gpiom), okay) */ +#if DT_NODE_HAS_STATUS(DT_NODELABEL(gpion), okay) +GPIO_DEVICE_INIT_STM32(n, N); +#endif /* DT_NODE_HAS_STATUS(DT_NODELABEL(gpion), okay) */ +#if DT_NODE_HAS_STATUS(DT_NODELABEL(gpioo), okay) +GPIO_DEVICE_INIT_STM32(o, O); +#endif /* DT_NODE_HAS_STATUS(DT_NODELABEL(gpioo), okay) */ +#if DT_NODE_HAS_STATUS(DT_NODELABEL(gpiop), okay) +GPIO_DEVICE_INIT_STM32(p, P); +#endif /* DT_NODE_HAS_STATUS(DT_NODELABEL(gpiop), okay) */ diff --git a/drivers/gpio/gpio_stm32.h b/drivers/gpio/gpio_stm32.h index 5e9da057ea95a..9aa83a546e972 100644 --- a/drivers/gpio/gpio_stm32.h +++ b/drivers/gpio/gpio_stm32.h @@ -100,6 +100,20 @@ #define STM32_PERIPH_GPIOI LL_AHB4_GRP1_PERIPH_GPIOI #define STM32_PERIPH_GPIOJ LL_AHB4_GRP1_PERIPH_GPIOJ #define STM32_PERIPH_GPIOK LL_AHB4_GRP1_PERIPH_GPIOK +#elif CONFIG_SOC_SERIES_STM32H7RSX +#define STM32_CLOCK_BUS_GPIO STM32_CLOCK_BUS_AHB4 +#define STM32_PERIPH_GPIOA LL_AHB4_GRP1_PERIPH_GPIOA +#define STM32_PERIPH_GPIOB LL_AHB4_GRP1_PERIPH_GPIOB +#define STM32_PERIPH_GPIOC LL_AHB4_GRP1_PERIPH_GPIOC +#define STM32_PERIPH_GPIOD LL_AHB4_GRP1_PERIPH_GPIOD +#define STM32_PERIPH_GPIOE LL_AHB4_GRP1_PERIPH_GPIOE +#define STM32_PERIPH_GPIOF LL_AHB4_GRP1_PERIPH_GPIOF +#define STM32_PERIPH_GPIOG LL_AHB4_GRP1_PERIPH_GPIOG +#define STM32_PERIPH_GPIOH LL_AHB4_GRP1_PERIPH_GPIOH +#define STM32_PERIPH_GPIOM LL_AHB4_GRP1_PERIPH_GPIOM +#define STM32_PERIPH_GPION LL_AHB4_GRP1_PERIPH_GPION +#define STM32_PERIPH_GPIOO LL_AHB4_GRP1_PERIPH_GPIOO +#define STM32_PERIPH_GPIOP LL_AHB4_GRP1_PERIPH_GPIOP #elif CONFIG_SOC_SERIES_STM32G0X #define STM32_CLOCK_BUS_GPIO STM32_CLOCK_BUS_IOP #define STM32_PERIPH_GPIOA LL_IOP_GRP1_PERIPH_GPIOA From 8cd4d8aa7e3422055a910a1701cea858a780e344 Mon Sep 17 00:00:00 2001 From: Francois Ramu Date: Thu, 15 Feb 2024 15:05:28 +0100 Subject: [PATCH 1893/2849] boards: arm: stm32h7s78 disco kit Introduce the stm32h7s78_dk disco kit from STMicroelectronics Based on the stm32H7S7 mcu Use STM32CubeProgrammer v2.16.0 as runner. Signed-off-by: Francois Ramu --- boards/st/stm32h7s78_dk/Kconfig.defconfig | 17 + boards/st/stm32h7s78_dk/Kconfig.stm32h7s78_dk | 9 + .../stm32h7s78_dk/arduino_r3_connector.dtsi | 39 +++ boards/st/stm32h7s78_dk/board.cmake | 8 + boards/st/stm32h7s78_dk/board.yml | 5 + .../stm32h7s78_dk/doc/img/stm32h7s78_dk.jpg | Bin 0 -> 52583 bytes boards/st/stm32h7s78_dk/doc/index.rst | 300 ++++++++++++++++++ boards/st/stm32h7s78_dk/stm32h7s78.yaml | 13 + boards/st/stm32h7s78_dk/stm32h7s78_dk.dts | 142 +++++++++ .../st/stm32h7s78_dk/stm32h7s78_dk_defconfig | 26 ++ boards/st/stm32h7s78_dk/support/openocd.cfg | 41 +++ 11 files changed, 600 insertions(+) create mode 100644 boards/st/stm32h7s78_dk/Kconfig.defconfig create mode 100644 boards/st/stm32h7s78_dk/Kconfig.stm32h7s78_dk create mode 100644 boards/st/stm32h7s78_dk/arduino_r3_connector.dtsi create mode 100644 boards/st/stm32h7s78_dk/board.cmake create mode 100644 boards/st/stm32h7s78_dk/board.yml create mode 100644 boards/st/stm32h7s78_dk/doc/img/stm32h7s78_dk.jpg create mode 100644 boards/st/stm32h7s78_dk/doc/index.rst create mode 100644 boards/st/stm32h7s78_dk/stm32h7s78.yaml create mode 100644 boards/st/stm32h7s78_dk/stm32h7s78_dk.dts create mode 100644 boards/st/stm32h7s78_dk/stm32h7s78_dk_defconfig create mode 100644 boards/st/stm32h7s78_dk/support/openocd.cfg diff --git a/boards/st/stm32h7s78_dk/Kconfig.defconfig b/boards/st/stm32h7s78_dk/Kconfig.defconfig new file mode 100644 index 0000000000000..d8a0c6ecdcd50 --- /dev/null +++ b/boards/st/stm32h7s78_dk/Kconfig.defconfig @@ -0,0 +1,17 @@ +# STM32H7S78 DISCOVERY KIT board configuration +# +# Copyright (c) 2024 STMicroelectronics +# +# SPDX-License-Identifier: Apache-2.0 +# + +if BOARD_STM32H7S78_DK + +if NETWORKING + +config NET_L2_ETHERNET + default y + +endif # NETWORKING + +endif # BOARD_STM32H7S78_DK diff --git a/boards/st/stm32h7s78_dk/Kconfig.stm32h7s78_dk b/boards/st/stm32h7s78_dk/Kconfig.stm32h7s78_dk new file mode 100644 index 0000000000000..d3c5737a28933 --- /dev/null +++ b/boards/st/stm32h7s78_dk/Kconfig.stm32h7s78_dk @@ -0,0 +1,9 @@ +# STM32H7S78-DK Discovery kit board configuration +# +# Copyright (c) 2024 STMicroelectronics +# +# SPDX-License-Identifier: Apache-2.0 +# + +config BOARD_STM32H7S78_DK + select SOC_STM32H7S7XX diff --git a/boards/st/stm32h7s78_dk/arduino_r3_connector.dtsi b/boards/st/stm32h7s78_dk/arduino_r3_connector.dtsi new file mode 100644 index 0000000000000..c1d06e17bc13e --- /dev/null +++ b/boards/st/stm32h7s78_dk/arduino_r3_connector.dtsi @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2024 STMicroelectronics + * + * 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 &gpioc 2 0>, /* A1 */ + <2 0 &gpioc 3 0>, /* A2 */ + <3 0 &gpiof 12 0>, /* A3 */ + <4 0 &gpiof 13 0>, /* A4 */ + <5 0 &gpioc 1 0>, /* A5 */ + <6 0 &gpioe 7 0>, /* D0 */ + <7 0 &gpioe 8 0>, /* D1 */ + <8 0 &gpiof 1 0>, /* D2 */ + <9 0 &gpiod 12 0>, /* D3 */ + <10 0 &gpiof 2 0>, /* D4 */ + <11 0 &gpiod 13 0>, /* D5 */ + <12 0 &gpiod 15 0>, /* D6 */ + <13 0 &gpiof 3 0>, /* D7 */ + <14 0 &gpiof 4 0>, /* D8 */ + <15 0 &gpiof 6 0>, /* D9 */ + <16 0 &gpiof 8 0>, /* D10 */ + <17 0 &gpioe 14 0>, /* D11 */ + <18 0 &gpioe 13 0>, /* D12 */ + <19 0 &gpioe 12 0>, /* D13 */ + <20 0 &gpiob 9 0>, /* D14 */ + <21 0 &gpiob 6 0>; /* D15 */ + }; +}; + +arduino_spi: &spi4 {}; +arduino_i2c: &i2c1 {}; diff --git a/boards/st/stm32h7s78_dk/board.cmake b/boards/st/stm32h7s78_dk/board.cmake new file mode 100644 index 0000000000000..04b6ed24de460 --- /dev/null +++ b/boards/st/stm32h7s78_dk/board.cmake @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: Apache-2.0 + +board_runner_args(stm32cubeprogrammer "--erase" "--port=swd" "--reset-mode=hw") +board_runner_args(openocd --target-handle=_CHIPNAME.cpu0) + +include(${ZEPHYR_BASE}/boards/common/stm32cubeprogrammer.board.cmake) +# FIXME: openocd runner not yet available. +include(${ZEPHYR_BASE}/boards/common/openocd.board.cmake) diff --git a/boards/st/stm32h7s78_dk/board.yml b/boards/st/stm32h7s78_dk/board.yml new file mode 100644 index 0000000000000..c17be71480c2d --- /dev/null +++ b/boards/st/stm32h7s78_dk/board.yml @@ -0,0 +1,5 @@ +board: + name: stm32h7s78_dk + vendor: st + socs: + - name: stm32h7s7xx diff --git a/boards/st/stm32h7s78_dk/doc/img/stm32h7s78_dk.jpg b/boards/st/stm32h7s78_dk/doc/img/stm32h7s78_dk.jpg new file mode 100644 index 0000000000000000000000000000000000000000..523ff89970c715d668d601bb93e1f5ba78eac25f GIT binary patch literal 52583 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 +#include +#include "arduino_r3_connector.dtsi" +#include + +/ { + model = "STMicroelectronics STM32H7S78 DISCOVERY KIT board"; + compatible = "st,stm32h7s78-dk"; + + chosen { + zephyr,console = &uart4; + zephyr,shell-uart = &uart4; + zephyr,flash = &flash0; + zephyr,sram = &sram0; + }; + + leds { + compatible = "gpio-leds"; + green_led: led_1 { + gpios = <&gpioo 1 GPIO_ACTIVE_LOW>; + label = "User LD1"; + }; + orange_led: led_2 { + gpios = <&gpioo 5 GPIO_ACTIVE_LOW>; + label = "User LD2"; + }; + red_led: led_3 { + gpios = <&gpiom 2 GPIO_ACTIVE_LOW>; + label = "User LD3"; + }; + blue_led: led_4 { + gpios = <&gpiom 3 GPIO_ACTIVE_LOW>; + label = "User LD4"; + }; + }; + + gpio_keys { + compatible = "gpio-keys"; + user_button: button { + label = "User"; + gpios = <&gpioc 13 GPIO_ACTIVE_LOW>; + zephyr,code = ; + }; + }; + + aliases { + led0 = &blue_led; + sw0 = &user_button; + }; +}; + +&clk_hsi48 { + status = "okay"; +}; + +&clk_lse { + status = "okay"; +}; + +&clk_hse { + clock-frequency = ; + hse-bypass; /* X3 is a 24MHz oscillator on PH0 */ + status = "okay"; +}; + +&pll { + div-m = <12>; + mul-n = <250>; + div-p = <2>; + div-q = <2>; + div-r = <2>; + div-s = <2>; + div-t = <2>; + clocks = <&clk_hse>; + status = "okay"; +}; + +&rcc { + clocks = <&pll>; + clock-frequency = ; + dcpre = <1>; + hpre = <1>; + ppre1 = <2>; + ppre2 = <2>; + ppre4 = <2>; + ppre5 = <2>; +}; + +&uart4 { + pinctrl-0 = <&uart4_tx_pd1 &uart4_rx_pd0>; + pinctrl-names = "default"; + current-speed = <115200>; + status = "okay"; +}; + +&uart7 { + pinctrl-0 = <&uart7_tx_pe8 &uart7_rx_pe7>; + pinctrl-names = "default"; + current-speed = <115200>; + status = "okay"; +}; + +&timers2 { + st,prescaler = <10000>; + status = "okay"; + + pwm2: pwm { + status = "okay"; + pinctrl-0 = <&tim2_ch4_pa3>; + pinctrl-names = "default"; + }; +}; + +&timers3 { + st,prescaler = <10000>; + status = "okay"; + + pwm3: pwm { + status = "okay"; + pinctrl-0 = <&tim3_ch2_pb5>; + pinctrl-names = "default"; + }; +}; + +&spi4 { + pinctrl-0 = <&spi4_nss_pe4 &spi4_sck_pe12 + &spi4_miso_pe13 &spi4_mosi_pe14>; + pinctrl-names = "default"; + status = "okay"; +}; + +&i2c1 { + pinctrl-0 = <&i2c1_scl_pb6 &i2c1_sda_pb9>; + pinctrl-names = "default"; +}; diff --git a/boards/st/stm32h7s78_dk/stm32h7s78_dk_defconfig b/boards/st/stm32h7s78_dk/stm32h7s78_dk_defconfig new file mode 100644 index 0000000000000..d8caa7276387a --- /dev/null +++ b/boards/st/stm32h7s78_dk/stm32h7s78_dk_defconfig @@ -0,0 +1,26 @@ +# Copyright (c) 2024 STMicroelectronics +# SPDX-License-Identifier: Apache-2.0 + +# Enable SMPS +CONFIG_POWER_SUPPLY_DIRECT_SMPS=y + +# Enable MPU +CONFIG_ARM_MPU=y + +# Enable HW stack protection +CONFIG_HW_STACK_PROTECTION=y + +# enable uart driver +CONFIG_SERIAL=y +# enable console +CONFIG_CONSOLE=y +CONFIG_UART_CONSOLE=y + +# enable GPIO +CONFIG_GPIO=y + +# Enable Clocks +CONFIG_CLOCK_CONTROL=y + +# enable pin controller +CONFIG_PINCTRL=y diff --git a/boards/st/stm32h7s78_dk/support/openocd.cfg b/boards/st/stm32h7s78_dk/support/openocd.cfg new file mode 100644 index 0000000000000..b32c9f26c2ca2 --- /dev/null +++ b/boards/st/stm32h7s78_dk/support/openocd.cfg @@ -0,0 +1,41 @@ +source [find interface/stlink-dap.cfg] +transport select "dapdirect_swd" + +set WORKAREASIZE 0x8000 +set CHIPNAME STM32H7S7XX +set BOARDNAME STM32H7S78_DK + +# Enable debug when in low power modes +set ENABLE_LOW_POWER 1 + +# Stop Watchdog counters when halt +set STOP_WATCHDOG 1 + +# 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 + +source [find target/stm32h7rx.cfg] + + +$_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 a736f150f7e64a63df8d1c7fb3d5321bd2357078 Mon Sep 17 00:00:00 2001 From: Qianru Huang Date: Thu, 16 May 2024 11:04:37 +0800 Subject: [PATCH 1894/2849] tests: subsys: sensing: add sensing test skeleton Add the test cases for Sensing(Sensing Subsystem) to verify the functionality of sensing portion of subsystem. The test cases are based on native_sim platform. Signed-off-by: Qianru Huang --- tests/subsys/sensing/CMakeLists.txt | 8 ++ tests/subsys/sensing/README.rst | 21 +++++ tests/subsys/sensing/boards/native_sim.conf | 5 + .../subsys/sensing/boards/native_sim.overlay | 58 ++++++++++++ tests/subsys/sensing/prj.conf | 3 + tests/subsys/sensing/src/main.c | 92 +++++++++++++++++++ tests/subsys/sensing/testcase.yaml | 4 + 7 files changed, 191 insertions(+) create mode 100644 tests/subsys/sensing/CMakeLists.txt create mode 100644 tests/subsys/sensing/README.rst create mode 100644 tests/subsys/sensing/boards/native_sim.conf create mode 100644 tests/subsys/sensing/boards/native_sim.overlay create mode 100644 tests/subsys/sensing/prj.conf create mode 100644 tests/subsys/sensing/src/main.c create mode 100644 tests/subsys/sensing/testcase.yaml diff --git a/tests/subsys/sensing/CMakeLists.txt b/tests/subsys/sensing/CMakeLists.txt new file mode 100644 index 0000000000000..797ab22d1d285 --- /dev/null +++ b/tests/subsys/sensing/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(test_sensing) + +FILE(GLOB app_sources src/*.c) +target_sources(app PRIVATE ${app_sources}) diff --git a/tests/subsys/sensing/README.rst b/tests/subsys/sensing/README.rst new file mode 100644 index 0000000000000..457a1034bf12c --- /dev/null +++ b/tests/subsys/sensing/README.rst @@ -0,0 +1,21 @@ +.. _sensing_test: + +Sensing Subsystem Test Sample +############################ + +Overview +******** + +This test sample is used to test the Sensing Subsystem APIs. It is based +on bmi160 emulator on native_sim platform. + +Building and Testing +******************** + +This application can be built and executed on native_sim as follows: + +.. code-block:: console + $ ./scripts/twister -p native_sim -T tests/subsys/sensing +To build for another board, change "native_sim" above to that board's name. + +At the current stage, it only supports native_sim. diff --git a/tests/subsys/sensing/boards/native_sim.conf b/tests/subsys/sensing/boards/native_sim.conf new file mode 100644 index 0000000000000..b5a8eb94dc8e3 --- /dev/null +++ b/tests/subsys/sensing/boards/native_sim.conf @@ -0,0 +1,5 @@ +#Enable BMI160 and BMI160 Emulator +CONFIG_BMI160_TRIGGER_NONE=y +CONFIG_EMUL_BMI160=y +CONFIG_SENSOR=y +CONFIG_SENSOR_INFO=y diff --git a/tests/subsys/sensing/boards/native_sim.overlay b/tests/subsys/sensing/boards/native_sim.overlay new file mode 100644 index 0000000000000..38096e477714c --- /dev/null +++ b/tests/subsys/sensing/boards/native_sim.overlay @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2024 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +&i2c0 { + bmi160_i2c: bmi@68 { + compatible = "bosch,bmi160"; + reg = <0x68>; + }; +}; + +&spi0 { + bmi160_spi: bmi@3 { + compatible = "bosch,bmi160"; + spi-max-frequency = <50000000>; + reg = <0x3>; + }; +}; + +/ { + sensing: sensing-node { + compatible = "zephyr,sensing"; + status = "okay"; + + base_accel_gyro: base-accel-gyro { + compatible = "zephyr,sensing-phy-3d-sensor"; + status = "okay"; + sensor-types = ; + friendly-name = "Base Accel Gyro Sensor"; + minimal-interval = <625>; + underlying-device = <&bmi160_i2c>; + }; + + lid_accel_gyro: lid-accel-gyro { + compatible = "zephyr,sensing-phy-3d-sensor"; + status = "okay"; + sensor-types = ; + friendly-name = "Lid Accel Gyro Sensor"; + minimal-interval = <625>; + underlying-device = <&bmi160_spi>; + }; + + hinge_angle: hinge-angle { + compatible = "zephyr,sensing-hinge-angle"; + status = "okay"; + sensor-types = ; + friendly-name = "Hinge Angle Sensor"; + reporters = <&base_accel_gyro &lid_accel_gyro>; + reporters-index = <0 0>; + minimal-interval = <100000>; + stream-mode; + }; + }; +}; diff --git a/tests/subsys/sensing/prj.conf b/tests/subsys/sensing/prj.conf new file mode 100644 index 0000000000000..bf12dc1f6cea0 --- /dev/null +++ b/tests/subsys/sensing/prj.conf @@ -0,0 +1,3 @@ +CONFIG_TEST=y +CONFIG_ZTEST=y +CONFIG_LOG=y diff --git a/tests/subsys/sensing/src/main.c b/tests/subsys/sensing/src/main.c new file mode 100644 index 0000000000000..6f9a5acbe8039 --- /dev/null +++ b/tests/subsys/sensing/src/main.c @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2024 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include + +#define DT_DRV_COMPAT zephyr_sensing +#define MAX_SENSOR_TYPES 2 +#define DT_SENSOR_INFO(node) \ + { \ + .name = DT_NODE_FULL_NAME(node), \ + .friendly_name = DT_PROP(node, friendly_name), \ + .sensor_types = DT_PROP(node, sensor_types), \ + .sensor_type_count = DT_PROP_LEN(node, sensor_types), \ + } + +struct sensor_info_t { + const char *name; + const char *friendly_name; + const int sensor_types[MAX_SENSOR_TYPES]; + int sensor_type_count; +}; + +static const struct sensor_info_t sensors[] = { + DT_FOREACH_CHILD_STATUS_OKAY_SEP(DT_DRV_INST(0), DT_SENSOR_INFO, (,)) +}; + +static int get_total_sensor_counts(void) +{ + int total = 0; + + for (int i = 0; i < ARRAY_SIZE(sensors); i++) { + total += sensors[i].sensor_type_count; + } + return total; +} + +static bool check_sensor_type(const struct sensing_sensor_info *info, + const struct sensor_info_t *sensor) +{ + for (int i = 0; i < sensor->sensor_type_count; ++i) { + if (info->type == sensor->sensor_types[i]) { + return true; + } + } + return false; +} + +/** + * @brief Test Get Sensors + * + * This test verifies sensing_get_sensors. + */ +ZTEST(sensing_tests, test_sensing_get_sensors) +{ + const struct sensing_sensor_info *info; + int ret, total_sensor_counts = get_total_sensor_counts(); + int num = total_sensor_counts; + + ret = sensing_get_sensors(&num, &info); + zassert_equal(ret, 0, "Sensing Get Sensors failed"); + zassert_equal(num, total_sensor_counts, "Expected %d sensors, but got %d", + total_sensor_counts, num); + zassert_not_null(info, "Expected sensor info to be not null"); + + for (int i = 0; i < num; ++i) { + bool found = false; + + for (int j = 0; j < ARRAY_SIZE(sensors); ++j) { + if (strcmp(info[i].name, sensors[j].name) == 0) { + zassert_true(strcmp(info[i].friendly_name, + sensors[j].friendly_name) == 0, + "Mismatch in friendly name for sensor '%s'", + info[i].name); + zassert_true(check_sensor_type(&info[i], &sensors[j]), + "Mismatch in sensor type for sensor '%s'", + info[i].name); + found = true; + break; + } + } + zassert_true(found, "Sensor '%s' not found", info[i].name); + } +} + +ZTEST_SUITE(sensing_tests, NULL, NULL, NULL, NULL, NULL); diff --git a/tests/subsys/sensing/testcase.yaml b/tests/subsys/sensing/testcase.yaml new file mode 100644 index 0000000000000..4a152fb2179a5 --- /dev/null +++ b/tests/subsys/sensing/testcase.yaml @@ -0,0 +1,4 @@ +tests: + subsys.sensing: + platform_allow: native_sim + tags: sensing From 46572f797f516ddb4d0ea686e49fb9f34536cf69 Mon Sep 17 00:00:00 2001 From: Grzegorz Swiderski Date: Wed, 13 Dec 2023 13:47:25 +0100 Subject: [PATCH 1895/2849] dtlib: Allow deleting the root node Previously, dtlib would fail to parse the following: /delete-node/ &{/}; This is accepted by dtc, so dtlib should be aligned. The expected behavior is that the contents of the "deleted" root node are emptied, but the node itself remains in the tree. This means that it's possible to put that statement at the end of a DTS file and still get a valid output. A small test case for this scenario is included. Signed-off-by: Grzegorz Swiderski --- .../python-devicetree/src/devicetree/dtlib.py | 8 ++++- .../dts/python-devicetree/tests/test_dtlib.py | 32 +++++++++++++++++++ 2 files changed, 39 insertions(+), 1 deletion(-) diff --git a/scripts/dts/python-devicetree/src/devicetree/dtlib.py b/scripts/dts/python-devicetree/src/devicetree/dtlib.py index d74fbc67d37d4..cc510ced40356 100644 --- a/scripts/dts/python-devicetree/src/devicetree/dtlib.py +++ b/scripts/dts/python-devicetree/src/devicetree/dtlib.py @@ -166,7 +166,13 @@ def _get_prop(self, name: str) -> 'Property': return prop def _del(self) -> None: - # Removes the node from the tree + # Removes the node from the tree. When called on the root node, + # this method will leave it empty but still part of the tree. + + if self.parent is None: + self.nodes.clear() + self.props.clear() + return self.parent.nodes.pop(self.name) # type: ignore def __str__(self): diff --git a/scripts/dts/python-devicetree/tests/test_dtlib.py b/scripts/dts/python-devicetree/tests/test_dtlib.py index b1b6ce33fd5a2..f7c8a31cc673c 100644 --- a/scripts/dts/python-devicetree/tests/test_dtlib.py +++ b/scripts/dts/python-devicetree/tests/test_dtlib.py @@ -911,6 +911,15 @@ def test_deletion(): verify_parse(""" /dts-v1/; +/ { + x = "foo"; + sub0 { + x = "bar"; + }; +}; + +/delete-node/ &{/}; + / { sub1 { x = < 1 >; @@ -940,6 +949,29 @@ def test_deletion(): x = < 0x1 >; }; }; +""") + + verify_parse(""" +/dts-v1/; + +/ { + x: x = < &sub >, ⊂ + + sub1 { + x = < &sub >, ⊂ + }; + sub2: sub2 { + x = < &sub >, ⊂ + }; +}; + +/delete-node/ &{/}; +""", +""" +/dts-v1/; + +/ { +}; """) verify_error_endswith(""" From 0f2aead57de14de23d9a79dc8305ddf3d48c5f7f Mon Sep 17 00:00:00 2001 From: Sreeram Tatapudi Date: Wed, 29 May 2024 23:20:56 -0700 Subject: [PATCH 1896/2849] driver: watchdog: infineon: cyw20829 watchdog - Enable watchdog for the cyw920829m2evk_02 board Signed-off-by: Sreeram Tatapudi --- boards/infineon/cyw920829m2evk_02/cyw920829m2evk_02.dts | 8 ++++++++ boards/infineon/cyw920829m2evk_02/cyw920829m2evk_02.yaml | 1 + 2 files changed, 9 insertions(+) diff --git a/boards/infineon/cyw920829m2evk_02/cyw920829m2evk_02.dts b/boards/infineon/cyw920829m2evk_02/cyw920829m2evk_02.dts index 638f3efa8815f..7e1ba5ba006fd 100644 --- a/boards/infineon/cyw920829m2evk_02/cyw920829m2evk_02.dts +++ b/boards/infineon/cyw920829m2evk_02/cyw920829m2evk_02.dts @@ -13,6 +13,10 @@ model = "The Infineon AIROC™ CYW20829 Bluetooth® LE evaluation kit (CYW92089M2EVK-02)"; compatible = "infineon,cyw920829m2evk_02", "infineon,CYW20829"; + aliases { + watchdog0 = &watchdog0; + }; + chosen { zephyr,sram = &sram0; zephyr,flash = &app_region; @@ -71,6 +75,10 @@ uart2: &scb2 { status = "okay"; }; +&watchdog0 { + status = "okay"; +}; + / { flash0: flash@60000000 { compatible = "soc-nv-flash"; diff --git a/boards/infineon/cyw920829m2evk_02/cyw920829m2evk_02.yaml b/boards/infineon/cyw920829m2evk_02/cyw920829m2evk_02.yaml index 590385dc4ec7a..caf90502fb251 100644 --- a/boards/infineon/cyw920829m2evk_02/cyw920829m2evk_02.yaml +++ b/boards/infineon/cyw920829m2evk_02/cyw920829m2evk_02.yaml @@ -17,5 +17,6 @@ supported: - uart - clock_control - bluetooth + - watchdog vendor: infineon From 0b599c6600126380b6ede6145d4d7b18fa5f8013 Mon Sep 17 00:00:00 2001 From: Sreeram Tatapudi Date: Mon, 3 Jun 2024 22:54:58 -0700 Subject: [PATCH 1897/2849] tests: drivers: Enable driver tests for cyw20829 Add overlays to enable GPIO and I2C driver tests Signed-off-by: Sreeram Tatapudi --- .../cyw920829m2evk_02/cyw920829m2evk_02.yaml | 2 ++ .../cyw920829m2evk_02/support/openocd.cfg | 4 +++ .../boards/cyw920829m2evk_02.overlay | 12 +++++++ .../i2c_api/boards/cyw920829m2evk_02.overlay | 31 +++++++++++++++++++ 4 files changed, 49 insertions(+) create mode 100644 tests/drivers/gpio/gpio_basic_api/boards/cyw920829m2evk_02.overlay create mode 100644 tests/drivers/i2c/i2c_api/boards/cyw920829m2evk_02.overlay diff --git a/boards/infineon/cyw920829m2evk_02/cyw920829m2evk_02.yaml b/boards/infineon/cyw920829m2evk_02/cyw920829m2evk_02.yaml index caf90502fb251..a02da7d193780 100644 --- a/boards/infineon/cyw920829m2evk_02/cyw920829m2evk_02.yaml +++ b/boards/infineon/cyw920829m2evk_02/cyw920829m2evk_02.yaml @@ -18,5 +18,7 @@ supported: - clock_control - bluetooth - watchdog + - spi + - i2c vendor: infineon diff --git a/boards/infineon/cyw920829m2evk_02/support/openocd.cfg b/boards/infineon/cyw920829m2evk_02/support/openocd.cfg index 419ffc13abc1a..fe70fb383a8a3 100644 --- a/boards/infineon/cyw920829m2evk_02/support/openocd.cfg +++ b/boards/infineon/cyw920829m2evk_02/support/openocd.cfg @@ -8,3 +8,7 @@ source [find interface/kitprog3.cfg] transport select swd source [find target/cyw20829.cfg] + +if { [info exists _ZEPHYR_BOARD_SERIAL] } { + adapter serial $_ZEPHYR_BOARD_SERIAL +} diff --git a/tests/drivers/gpio/gpio_basic_api/boards/cyw920829m2evk_02.overlay b/tests/drivers/gpio/gpio_basic_api/boards/cyw920829m2evk_02.overlay new file mode 100644 index 0000000000000..2f71743fe3e59 --- /dev/null +++ b/tests/drivers/gpio/gpio_basic_api/boards/cyw920829m2evk_02.overlay @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2024 Cypress Semiconductor Corporation. + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + resources { + compatible = "test-gpio-basic-api"; + out-gpios = <&gpio_prt1 4 0>; + in-gpios = <&gpio_prt1 5 0>; + }; +}; diff --git a/tests/drivers/i2c/i2c_api/boards/cyw920829m2evk_02.overlay b/tests/drivers/i2c/i2c_api/boards/cyw920829m2evk_02.overlay new file mode 100644 index 0000000000000..4d24e9f4641ce --- /dev/null +++ b/tests/drivers/i2c/i2c_api/boards/cyw920829m2evk_02.overlay @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2024 Cypress Semiconductor Corporation. + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + aliases { + gy271 = &i2c0; + i2c-0 =&i2c0; + }; +}; + +i2c0: &scb0 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "infineon,cat1-i2c"; + status = "okay"; + pinctrl-0 = <&p0_2_scb0_i2c_scl &p0_3_scb0_i2c_sda>; + pinctrl-names = "default"; +}; + +/* Configure pin control bias mode for i2c pins */ +&p0_2_scb0_i2c_scl { + drive-open-drain; + input-enable; +}; + +&p0_3_scb0_i2c_sda { + drive-open-drain; + input-enable; +}; From 69f9d7319753aa436c04b0c1e420955e65495840 Mon Sep 17 00:00:00 2001 From: Sreeram Tatapudi Date: Tue, 4 Jun 2024 13:16:09 -0700 Subject: [PATCH 1898/2849] boards: infineon: cyw920829m2evk_02: Fix index.rst Update index.rst to use the right description for code Signed-off-by: Sreeram Tatapudi --- boards/infineon/cyw920829m2evk_02/doc/index.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/boards/infineon/cyw920829m2evk_02/doc/index.rst b/boards/infineon/cyw920829m2evk_02/doc/index.rst index ac92f59d12a90..4f349c0a154f7 100644 --- a/boards/infineon/cyw920829m2evk_02/doc/index.rst +++ b/boards/infineon/cyw920829m2evk_02/doc/index.rst @@ -98,14 +98,14 @@ The CYW920829M2EVK-02 includes an onboard programmer/debugger (KitProg3) to prov On Windows: -.. code-block:: console +.. code-block:: shell 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 +.. code-block:: shell west flash --openocd path/to/infineon/openocd/bin/openocd west debug --openocd path/to/infineon/openocd/bin/openocd From f32a41d4ddb9fe71f791755d6743b585d03956bf Mon Sep 17 00:00:00 2001 From: Tom Burdick Date: Thu, 12 Oct 2023 11:50:28 -0500 Subject: [PATCH 1899/2849] rtio: Exclude platforms from CI testing Running lock free algorithms on renode seem to cause timeouts so exclude renode platforms. Signed-off-by: Tom Burdick --- tests/subsys/rtio/rtio_api/testcase.yaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/subsys/rtio/rtio_api/testcase.yaml b/tests/subsys/rtio/rtio_api/testcase.yaml index 52480644fc0c4..8631dffc80417 100644 --- a/tests/subsys/rtio/rtio_api/testcase.yaml +++ b/tests/subsys/rtio/rtio_api/testcase.yaml @@ -1,5 +1,6 @@ common: - platform_exclude: m2gl025_miv + # renode causes timeouts unfortunately + platform_exclude: m2gl025_miv m5stack_core2 hifive1 platform_key: - arch - simulation From d95caa51a4489e3ddacc3ea69e39f997dfbb8245 Mon Sep 17 00:00:00 2001 From: Tom Burdick Date: Tue, 3 Oct 2023 10:01:32 -0500 Subject: [PATCH 1900/2849] sys: Add a lockfree mpsc and spsc queues Moves the rtio_ prefixed lockfree queues to sys alongside existing mpsc/spsc pbuf, ringbuf, and similar queue-like data structures. Signed-off-by: Tom Burdick --- doc/kernel/data_structures/index.rst | 2 + doc/kernel/data_structures/mpsc_lockfree.rst | 14 ++ doc/kernel/data_structures/spsc_lockfree.rst | 12 ++ doc/services/rtio/index.rst | 10 -- drivers/i2c/i2c_rtio.c | 10 +- drivers/spi/spi_mcux_lpspi.c | 6 +- drivers/spi/spi_sam.c | 6 +- include/zephyr/drivers/i2c/rtio.h | 2 +- include/zephyr/rtio/rtio.h | 56 ++++---- .../{rtio/rtio_mpsc.h => sys/mpsc_lockfree.h} | 96 ++++++------- .../{rtio/rtio_spsc.h => sys/spsc_lockfree.h} | 136 +++++++++--------- .../sensor_batch_processing/src/vnd_sensor.c | 6 +- subsys/rtio/rtio_executor.c | 8 +- subsys/rtio/rtio_init.c | 5 +- tests/lib/cpp/cxx/src/main.cpp | 4 +- tests/lib/lockfree/CMakeLists.txt | 12 ++ tests/lib/lockfree/prj.conf | 2 + .../lockfree/src/test_mpsc.c} | 100 +++++++------ .../lockfree/src/test_spsc.c} | 112 ++++++++------- tests/lib/lockfree/testcase.yaml | 7 + tests/subsys/rtio/rtio_api/CMakeLists.txt | 2 +- tests/subsys/rtio/rtio_api/src/rtio_api.h | 19 --- .../rtio/rtio_api/src/rtio_iodev_test.h | 12 +- .../subsys/rtio/rtio_api/src/test_rtio_api.c | 1 - 24 files changed, 337 insertions(+), 303 deletions(-) create mode 100644 doc/kernel/data_structures/mpsc_lockfree.rst create mode 100644 doc/kernel/data_structures/spsc_lockfree.rst rename include/zephyr/{rtio/rtio_mpsc.h => sys/mpsc_lockfree.h} (71%) rename include/zephyr/{rtio/rtio_spsc.h => sys/spsc_lockfree.h} (66%) create mode 100644 tests/lib/lockfree/CMakeLists.txt create mode 100644 tests/lib/lockfree/prj.conf rename tests/{subsys/rtio/rtio_api/src/test_rtio_mpsc.c => lib/lockfree/src/test_mpsc.c} (71%) rename tests/{subsys/rtio/rtio_api/src/test_rtio_spsc.c => lib/lockfree/src/test_spsc.c} (63%) create mode 100644 tests/lib/lockfree/testcase.yaml delete mode 100644 tests/subsys/rtio/rtio_api/src/rtio_api.h diff --git a/doc/kernel/data_structures/index.rst b/doc/kernel/data_structures/index.rst index ccdc2349225fe..f7e7c5ad35422 100644 --- a/doc/kernel/data_structures/index.rst +++ b/doc/kernel/data_structures/index.rst @@ -34,3 +34,5 @@ needed will be provided by the user. spsc_pbuf.rst rbtree.rst ring_buffers.rst + mpsc_lockfree.rst + spsc_lockfree.rst diff --git a/doc/kernel/data_structures/mpsc_lockfree.rst b/doc/kernel/data_structures/mpsc_lockfree.rst new file mode 100644 index 0000000000000..6b919125166b3 --- /dev/null +++ b/doc/kernel/data_structures/mpsc_lockfree.rst @@ -0,0 +1,14 @@ +.. _mpsc_lockfree: + +Multi Producer Single Consumer Lock Free Queue +============================================== + +A :dfn:`Multi Producer Single Consumer Lock Free Queue (MPSC)` is an lockfree +intrusive queue based on atomic pointer swaps as described by Dmitry Vyukov +at `1024cores `_. + + +API Reference +************* + +.. doxygengroup:: mpsc_lockfree diff --git a/doc/kernel/data_structures/spsc_lockfree.rst b/doc/kernel/data_structures/spsc_lockfree.rst new file mode 100644 index 0000000000000..dcd9939112c38 --- /dev/null +++ b/doc/kernel/data_structures/spsc_lockfree.rst @@ -0,0 +1,12 @@ +.. _spsc_lockfree: + +Single Producer Single Consumer Lock Free Queue +=============================================== + +A :dfn:`Single Producer Single Consumer Lock Free Queue (MPSC)` is a lock free +atomic ring buffer based queue. + +API Reference +************* + +.. doxygengroup:: spsc_lockfree diff --git a/doc/services/rtio/index.rst b/doc/services/rtio/index.rst index df6e75d7702c8..cb33a3ffbeb6a 100644 --- a/doc/services/rtio/index.rst +++ b/doc/services/rtio/index.rst @@ -216,13 +216,3 @@ API Reference ************* .. doxygengroup:: rtio - -MPSC Lock-free Queue API -======================== - -.. doxygengroup:: rtio_mpsc - -SPSC Lock-free Queue API -======================== - -.. doxygengroup:: rtio_spsc diff --git a/drivers/i2c/i2c_rtio.c b/drivers/i2c/i2c_rtio.c index 7fd90c3b89da1..e31c64bedf6cb 100644 --- a/drivers/i2c/i2c_rtio.c +++ b/drivers/i2c/i2c_rtio.c @@ -7,7 +7,7 @@ #include #include #include -#include +#include #include #define LOG_LEVEL CONFIG_I2C_LOG_LEVEL @@ -55,14 +55,14 @@ struct rtio_sqe *i2c_rtio_copy(struct rtio *r, struct rtio_iodev *iodev, const s void i2c_rtio_init(struct i2c_rtio *ctx, const struct device *dev) { k_sem_init(&ctx->lock, 1, 1); - rtio_mpsc_init(&ctx->io_q); + mpsc_init(&ctx->io_q); ctx->txn_curr = NULL; ctx->txn_head = NULL; ctx->dt_spec.bus = dev; ctx->iodev.data = &ctx->dt_spec; ctx->iodev.api = &i2c_iodev_api; /* TODO drop the builtin submission queue? */ - rtio_mpsc_init(&ctx->iodev.iodev_sq); + mpsc_init(&ctx->iodev.iodev_sq); } /** @@ -82,7 +82,7 @@ static bool i2c_rtio_next(struct i2c_rtio *ctx, bool completion) return false; } - struct rtio_mpsc_node *next = rtio_mpsc_pop(&ctx->io_q); + struct mpsc_node *next = mpsc_pop(&ctx->io_q); /* Nothing left to do */ if (next == NULL) { @@ -119,7 +119,7 @@ bool i2c_rtio_complete(struct i2c_rtio *ctx, int status) } bool i2c_rtio_submit(struct i2c_rtio *ctx, struct rtio_iodev_sqe *iodev_sqe) { - rtio_mpsc_push(&ctx->io_q, &iodev_sqe->q); + mpsc_push(&ctx->io_q, &iodev_sqe->q); return i2c_rtio_next(ctx, false); } diff --git a/drivers/spi/spi_mcux_lpspi.c b/drivers/spi/spi_mcux_lpspi.c index 5432debd68a3e..b0038fddfd511 100644 --- a/drivers/spi/spi_mcux_lpspi.c +++ b/drivers/spi/spi_mcux_lpspi.c @@ -702,7 +702,7 @@ static int spi_mcux_init(const struct device *dev) data->dt_spec.bus = dev; data->iodev.api = &spi_iodev_api; data->iodev.data = &data->dt_spec; - rtio_mpsc_init(&data->iodev.iodev_sq); + mpsc_init(&data->iodev.iodev_sq); #endif err = pinctrl_apply_state(config->pincfg, PINCTRL_STATE_DEFAULT); @@ -803,7 +803,7 @@ static void spi_mcux_iodev_next(const struct device *dev, bool completion) return; } - struct rtio_mpsc_node *next = rtio_mpsc_pop(&data->iodev.iodev_sq); + struct mpsc_node *next = mpsc_pop(&data->iodev.iodev_sq); if (next != NULL) { struct rtio_iodev_sqe *next_sqe = CONTAINER_OF(next, struct rtio_iodev_sqe, q); @@ -832,7 +832,7 @@ static void spi_mcux_iodev_submit(const struct device *dev, { struct spi_mcux_data *data = dev->data; - rtio_mpsc_push(&data->iodev.iodev_sq, &iodev_sqe->q); + mpsc_push(&data->iodev.iodev_sq, &iodev_sqe->q); spi_mcux_iodev_next(dev, false); } diff --git a/drivers/spi/spi_sam.c b/drivers/spi/spi_sam.c index 7cb6e8dc90c6f..7b8dd2ae35ef5 100644 --- a/drivers/spi/spi_sam.c +++ b/drivers/spi/spi_sam.c @@ -691,7 +691,7 @@ static void spi_sam_iodev_next(const struct device *dev, bool completion) return; } - struct rtio_mpsc_node *next = rtio_mpsc_pop(&data->iodev.iodev_sq); + struct mpsc_node *next = mpsc_pop(&data->iodev.iodev_sq); if (next != NULL) { struct rtio_iodev_sqe *next_sqe = CONTAINER_OF(next, struct rtio_iodev_sqe, q); @@ -736,7 +736,7 @@ static void spi_sam_iodev_submit(const struct device *dev, { struct spi_sam_data *data = dev->data; - rtio_mpsc_push(&data->iodev.iodev_sq, &iodev_sqe->q); + mpsc_push(&data->iodev.iodev_sq, &iodev_sqe->q); spi_sam_iodev_next(dev, false); } #endif @@ -866,7 +866,7 @@ static int spi_sam_init(const struct device *dev) data->dt_spec.bus = dev; data->iodev.api = &spi_iodev_api; data->iodev.data = &data->dt_spec; - rtio_mpsc_init(&data->iodev.iodev_sq); + mpsc_init(&data->iodev.iodev_sq); #endif spi_context_unlock_unconditionally(&data->ctx); diff --git a/include/zephyr/drivers/i2c/rtio.h b/include/zephyr/drivers/i2c/rtio.h index d4dc6c32ae22e..2f094540f7011 100644 --- a/include/zephyr/drivers/i2c/rtio.h +++ b/include/zephyr/drivers/i2c/rtio.h @@ -22,7 +22,7 @@ struct i2c_rtio { struct k_sem lock; struct k_spinlock slock; struct rtio *r; - struct rtio_mpsc io_q; + struct mpsc io_q; struct rtio_iodev iodev; struct rtio_iodev_sqe *txn_head; struct rtio_iodev_sqe *txn_curr; diff --git a/include/zephyr/rtio/rtio.h b/include/zephyr/rtio/rtio.h index 75ab879f9499d..f44c09450b69e 100644 --- a/include/zephyr/rtio/rtio.h +++ b/include/zephyr/rtio/rtio.h @@ -31,12 +31,12 @@ #include #include #include -#include #include #include #include #include #include +#include #ifdef __cplusplus extern "C" { @@ -292,7 +292,7 @@ BUILD_ASSERT(sizeof(struct rtio_sqe) <= 64); * @brief A completion queue event */ struct rtio_cqe { - struct rtio_mpsc_node q; + struct mpsc_node q; int32_t result; /**< Result from operation */ void *userdata; /**< Associated userdata with operation */ @@ -300,14 +300,14 @@ struct rtio_cqe { }; struct rtio_sqe_pool { - struct rtio_mpsc free_q; + struct mpsc free_q; const uint16_t pool_size; uint16_t pool_free; struct rtio_iodev_sqe *pool; }; struct rtio_cqe_pool { - struct rtio_mpsc free_q; + struct mpsc free_q; const uint16_t pool_size; uint16_t pool_free; struct rtio_cqe *pool; @@ -362,10 +362,10 @@ struct rtio { #endif /* Submission queue */ - struct rtio_mpsc sq; + struct mpsc sq; /* Completion queue */ - struct rtio_mpsc cq; + struct mpsc cq; }; /** The memory partition associated with all RTIO context information */ @@ -422,7 +422,7 @@ static inline uint16_t __rtio_compute_mempool_block_index(const struct rtio *r, */ struct rtio_iodev_sqe { struct rtio_sqe sqe; - struct rtio_mpsc_node q; + struct mpsc_node q; struct rtio_iodev_sqe *next; struct rtio *r; }; @@ -450,7 +450,7 @@ struct rtio_iodev { const struct rtio_iodev_api *api; /* Queue of RTIO contexts with requests */ - struct rtio_mpsc iodev_sq; + struct mpsc iodev_sq; /* Data associated with this iodev */ void *data; @@ -625,7 +625,7 @@ static inline void rtio_sqe_prep_transceive(struct rtio_sqe *sqe, static inline struct rtio_iodev_sqe *rtio_sqe_pool_alloc(struct rtio_sqe_pool *pool) { - struct rtio_mpsc_node *node = rtio_mpsc_pop(&pool->free_q); + struct mpsc_node *node = mpsc_pop(&pool->free_q); if (node == NULL) { return NULL; @@ -640,14 +640,14 @@ static inline struct rtio_iodev_sqe *rtio_sqe_pool_alloc(struct rtio_sqe_pool *p static inline void rtio_sqe_pool_free(struct rtio_sqe_pool *pool, struct rtio_iodev_sqe *iodev_sqe) { - rtio_mpsc_push(&pool->free_q, &iodev_sqe->q); + mpsc_push(&pool->free_q, &iodev_sqe->q); pool->pool_free++; } static inline struct rtio_cqe *rtio_cqe_pool_alloc(struct rtio_cqe_pool *pool) { - struct rtio_mpsc_node *node = rtio_mpsc_pop(&pool->free_q); + struct mpsc_node *node = mpsc_pop(&pool->free_q); if (node == NULL) { return NULL; @@ -664,7 +664,7 @@ static inline struct rtio_cqe *rtio_cqe_pool_alloc(struct rtio_cqe_pool *pool) static inline void rtio_cqe_pool_free(struct rtio_cqe_pool *pool, struct rtio_cqe *cqe) { - rtio_mpsc_push(&pool->free_q, &cqe->q); + mpsc_push(&pool->free_q, &cqe->q); pool->pool_free++; } @@ -732,14 +732,14 @@ static inline void rtio_block_pool_free(struct rtio *r, void *buf, uint32_t buf_ #define RTIO_IODEV_DEFINE(name, iodev_api, iodev_data) \ STRUCT_SECTION_ITERABLE(rtio_iodev, name) = { \ .api = (iodev_api), \ - .iodev_sq = RTIO_MPSC_INIT((name.iodev_sq)), \ + .iodev_sq = MPSC_INIT((name.iodev_sq)), \ .data = (iodev_data), \ } #define Z_RTIO_SQE_POOL_DEFINE(name, sz) \ static struct rtio_iodev_sqe CONCAT(_sqe_pool_, name)[sz]; \ STRUCT_SECTION_ITERABLE(rtio_sqe_pool, name) = { \ - .free_q = RTIO_MPSC_INIT((name.free_q)), \ + .free_q = MPSC_INIT((name.free_q)), \ .pool_size = sz, \ .pool_free = sz, \ .pool = CONCAT(_sqe_pool_, name), \ @@ -749,7 +749,7 @@ static inline void rtio_block_pool_free(struct rtio *r, void *buf, uint32_t buf_ #define Z_RTIO_CQE_POOL_DEFINE(name, sz) \ static struct rtio_cqe CONCAT(_cqe_pool_, name)[sz]; \ STRUCT_SECTION_ITERABLE(rtio_cqe_pool, name) = { \ - .free_q = RTIO_MPSC_INIT((name.free_q)), \ + .free_q = MPSC_INIT((name.free_q)), \ .pool_size = sz, \ .pool_free = sz, \ .pool = CONCAT(_cqe_pool_, name), \ @@ -797,8 +797,8 @@ static inline void rtio_block_pool_free(struct rtio *r, void *buf, uint32_t buf_ .sqe_pool = _sqe_pool, \ .cqe_pool = _cqe_pool, \ IF_ENABLED(CONFIG_RTIO_SYS_MEM_BLOCKS, (.block_pool = _block_pool,)) \ - .sq = RTIO_MPSC_INIT((name.sq)), \ - .cq = RTIO_MPSC_INIT((name.cq)), \ + .sq = MPSC_INIT((name.sq)), \ + .cq = MPSC_INIT((name.cq)), \ } /** @@ -910,7 +910,7 @@ static inline struct rtio_sqe *rtio_sqe_acquire(struct rtio *r) return NULL; } - rtio_mpsc_push(&r->sq, &iodev_sqe->q); + mpsc_push(&r->sq, &iodev_sqe->q); return &iodev_sqe->sqe; } @@ -923,12 +923,12 @@ static inline struct rtio_sqe *rtio_sqe_acquire(struct rtio *r) static inline void rtio_sqe_drop_all(struct rtio *r) { struct rtio_iodev_sqe *iodev_sqe; - struct rtio_mpsc_node *node = rtio_mpsc_pop(&r->sq); + struct mpsc_node *node = mpsc_pop(&r->sq); while (node != NULL) { iodev_sqe = CONTAINER_OF(node, struct rtio_iodev_sqe, q); rtio_sqe_pool_free(r->sqe_pool, iodev_sqe); - node = rtio_mpsc_pop(&r->sq); + node = mpsc_pop(&r->sq); } } @@ -953,7 +953,7 @@ static inline struct rtio_cqe *rtio_cqe_acquire(struct rtio *r) */ static inline void rtio_cqe_produce(struct rtio *r, struct rtio_cqe *cqe) { - rtio_mpsc_push(&r->cq, &cqe->q); + mpsc_push(&r->cq, &cqe->q); } /** @@ -969,7 +969,7 @@ static inline void rtio_cqe_produce(struct rtio *r, struct rtio_cqe *cqe) */ static inline struct rtio_cqe *rtio_cqe_consume(struct rtio *r) { - struct rtio_mpsc_node *node; + struct mpsc_node *node; struct rtio_cqe *cqe = NULL; #ifdef CONFIG_RTIO_CONSUME_SEM @@ -978,7 +978,7 @@ static inline struct rtio_cqe *rtio_cqe_consume(struct rtio *r) } #endif - node = rtio_mpsc_pop(&r->cq); + node = mpsc_pop(&r->cq); if (node == NULL) { return NULL; } @@ -999,16 +999,16 @@ static inline struct rtio_cqe *rtio_cqe_consume(struct rtio *r) */ static inline struct rtio_cqe *rtio_cqe_consume_block(struct rtio *r) { - struct rtio_mpsc_node *node; + struct mpsc_node *node; struct rtio_cqe *cqe; #ifdef CONFIG_RTIO_CONSUME_SEM k_sem_take(r->consume_sem, K_FOREVER); #endif - node = rtio_mpsc_pop(&r->cq); + node = mpsc_pop(&r->cq); while (node == NULL) { Z_SPIN_DELAY(1); - node = rtio_mpsc_pop(&r->cq); + node = mpsc_pop(&r->cq); } cqe = CONTAINER_OF(node, struct rtio_cqe, q); @@ -1136,13 +1136,13 @@ static inline void rtio_iodev_sqe_err(struct rtio_iodev_sqe *iodev_sqe, int resu static inline void rtio_iodev_cancel_all(struct rtio_iodev *iodev) { /* Clear pending requests as -ENODATA */ - struct rtio_mpsc_node *node = rtio_mpsc_pop(&iodev->iodev_sq); + struct mpsc_node *node = mpsc_pop(&iodev->iodev_sq); while (node != NULL) { struct rtio_iodev_sqe *iodev_sqe = CONTAINER_OF(node, struct rtio_iodev_sqe, q); rtio_iodev_sqe_err(iodev_sqe, -ECANCELED); - node = rtio_mpsc_pop(&iodev->iodev_sq); + node = mpsc_pop(&iodev->iodev_sq); } } diff --git a/include/zephyr/rtio/rtio_mpsc.h b/include/zephyr/sys/mpsc_lockfree.h similarity index 71% rename from include/zephyr/rtio/rtio_mpsc.h rename to include/zephyr/sys/mpsc_lockfree.h index 9551d1c5cc412..66f513072e4b4 100644 --- a/include/zephyr/rtio/rtio_mpsc.h +++ b/include/zephyr/sys/mpsc_lockfree.h @@ -1,12 +1,12 @@ /* * Copyright (c) 2010-2011 Dmitry Vyukov - * Copyright (c) 2022 Intel Corporation + * Copyright (c) 2023 Intel Corporation * * SPDX-License-Identifier: Apache-2.0 */ -#ifndef ZEPHYR_RTIO_MPSC_H_ -#define ZEPHYR_RTIO_MPSC_H_ +#ifndef ZEPHYR_SYS_MPSC_LOCKFREE_H_ +#define ZEPHYR_SYS_MPSC_LOCKFREE_H_ #include #include @@ -18,12 +18,28 @@ extern "C" { #endif /** - * @brief RTIO Multiple Producer Single Consumer (MPSC) Queue API - * @defgroup rtio_mpsc RTIO MPSC API - * @ingroup rtio + * @brief Multiple Producer Single Consumer (MPSC) Lockfree Queue API + * @defgroup mpsc_lockfree MPSC Lockfree Queue API + * @ingroup datastructure_apis * @{ */ +/** + * @file mpsc_lockfree.h + * + * @brief A wait-free intrusive multi producer single consumer (MPSC) queue using + * a singly linked list. Ordering is First-In-First-Out. + * + * Based on the well known and widely used wait-free MPSC queue described by + * Dmitry Vyukov with some slight changes to account for needs of an + * RTOS on a variety of archs. Both consumer and producer are wait free. No CAS + * loop or lock is needed. + * + * An MPSC queue is safe to produce or consume in an ISR with O(1) push/pop. + * + * @warning MPSC is *not* safe to consume in multiple execution contexts. + */ + /* * On single core systems atomics are unnecessary * and cause a lot of unnecessary cache invalidation @@ -35,17 +51,17 @@ extern "C" { * are updated in the correct order and the values are * updated core caches correctly. */ -#if defined(CONFIG_SMP) +#if IS_ENABLED(CONFIG_SMP) typedef atomic_ptr_t mpsc_ptr_t; -#define mpsc_ptr_get(ptr) atomic_ptr_get(&(ptr)) -#define mpsc_ptr_set(ptr, val) atomic_ptr_set(&(ptr), val) +#define mpsc_ptr_get(ptr) atomic_ptr_get(&(ptr)) +#define mpsc_ptr_set(ptr, val) atomic_ptr_set(&(ptr), val) #define mpsc_ptr_set_get(ptr, val) atomic_ptr_set(&(ptr), val) -#else +#else /* IS_ENABLED(CONFIG_SMP) */ -typedef struct rtio_mpsc_node *mpsc_ptr_t; +typedef struct mpsc_node *mpsc_ptr_t; #define mpsc_ptr_get(ptr) ptr #define mpsc_ptr_set(ptr, val) ptr = val @@ -56,38 +72,22 @@ typedef struct rtio_mpsc_node *mpsc_ptr_t; tmp; \ }) -#endif - -/** - * @file rtio_mpsc.h - * - * @brief A wait-free intrusive multi producer single consumer (MPSC) queue using - * a singly linked list. Ordering is First-In-First-Out. - * - * Based on the well known and widely used wait-free MPSC queue described by - * Dmitry Vyukov with some slight changes to account for needs of an - * RTOS on a variety of archs. Both consumer and producer are wait free. No CAS - * loop or lock is needed. - * - * An MPSC queue is safe to produce or consume in an ISR with O(1) push/pop. - * - * @warning MPSC is *not* safe to consume in multiple execution contexts. - */ +#endif /* IS_ENABLED(CONFIG_SMP) */ /** * @brief Queue member */ -struct rtio_mpsc_node { +struct mpsc_node { mpsc_ptr_t next; }; /** * @brief MPSC Queue */ -struct rtio_mpsc { +struct mpsc { mpsc_ptr_t head; - struct rtio_mpsc_node *tail; - struct rtio_mpsc_node stub; + struct mpsc_node *tail; + struct mpsc_node stub; }; /** @@ -97,10 +97,10 @@ struct rtio_mpsc { * * @param symbol name of the queue */ -#define RTIO_MPSC_INIT(symbol) \ +#define MPSC_INIT(symbol) \ { \ - .head = (struct rtio_mpsc_node *)&symbol.stub, \ - .tail = (struct rtio_mpsc_node *)&symbol.stub, \ + .head = (struct mpsc_node *)&symbol.stub, \ + .tail = (struct mpsc_node *)&symbol.stub, \ .stub = { \ .next = NULL, \ }, \ @@ -111,7 +111,7 @@ struct rtio_mpsc { * * @param q Queue to initialize or reset */ -static inline void rtio_mpsc_init(struct rtio_mpsc *q) +static inline void mpsc_init(struct mpsc *q) { mpsc_ptr_set(q->head, &q->stub); q->tail = &q->stub; @@ -124,15 +124,15 @@ static inline void rtio_mpsc_init(struct rtio_mpsc *q) * @param q Queue to push the node to * @param n Node to push into the queue */ -static ALWAYS_INLINE void rtio_mpsc_push(struct rtio_mpsc *q, struct rtio_mpsc_node *n) +static ALWAYS_INLINE void mpsc_push(struct mpsc *q, struct mpsc_node *n) { - struct rtio_mpsc_node *prev; + struct mpsc_node *prev; int key; mpsc_ptr_set(n->next, NULL); key = arch_irq_lock(); - prev = (struct rtio_mpsc_node *)mpsc_ptr_set_get(q->head, n); + prev = (struct mpsc_node *)mpsc_ptr_set_get(q->head, n); mpsc_ptr_set(prev->next, n); arch_irq_unlock(key); } @@ -143,11 +143,11 @@ static ALWAYS_INLINE void rtio_mpsc_push(struct rtio_mpsc *q, struct rtio_mpsc_n * @retval NULL When no node is available * @retval node When node is available */ -static inline struct rtio_mpsc_node *rtio_mpsc_pop(struct rtio_mpsc *q) +static inline struct mpsc_node *mpsc_pop(struct mpsc *q) { - struct rtio_mpsc_node *head; - struct rtio_mpsc_node *tail = q->tail; - struct rtio_mpsc_node *next = (struct rtio_mpsc_node *)mpsc_ptr_get(tail->next); + struct mpsc_node *head; + struct mpsc_node *tail = q->tail; + struct mpsc_node *next = (struct mpsc_node *)mpsc_ptr_get(tail->next); /* Skip over the stub/sentinel */ if (tail == &q->stub) { @@ -157,7 +157,7 @@ static inline struct rtio_mpsc_node *rtio_mpsc_pop(struct rtio_mpsc *q) q->tail = next; tail = next; - next = (struct rtio_mpsc_node *)mpsc_ptr_get(next->next); + next = (struct mpsc_node *)mpsc_ptr_get(next->next); } /* If next is non-NULL then a valid node is found, return it */ @@ -166,7 +166,7 @@ static inline struct rtio_mpsc_node *rtio_mpsc_pop(struct rtio_mpsc *q) return tail; } - head = (struct rtio_mpsc_node *)mpsc_ptr_get(q->head); + head = (struct mpsc_node *)mpsc_ptr_get(q->head); /* If next is NULL, and the tail != HEAD then the queue has pending * updates that can't yet be accessed. @@ -175,9 +175,9 @@ static inline struct rtio_mpsc_node *rtio_mpsc_pop(struct rtio_mpsc *q) return NULL; } - rtio_mpsc_push(q, &q->stub); + mpsc_push(q, &q->stub); - next = (struct rtio_mpsc_node *)mpsc_ptr_get(tail->next); + next = (struct mpsc_node *)mpsc_ptr_get(tail->next); if (next != NULL) { q->tail = next; @@ -195,4 +195,4 @@ static inline struct rtio_mpsc_node *rtio_mpsc_pop(struct rtio_mpsc *q) } #endif -#endif /* ZEPHYR_RTIO_MPSC_H_ */ +#endif /* ZEPHYR_SYS_MPSC_LOCKFREE_H_ */ diff --git a/include/zephyr/rtio/rtio_spsc.h b/include/zephyr/sys/spsc_lockfree.h similarity index 66% rename from include/zephyr/rtio/rtio_spsc.h rename to include/zephyr/sys/spsc_lockfree.h index 07872e7d4b020..3f769bfbd1689 100644 --- a/include/zephyr/rtio/rtio_spsc.h +++ b/include/zephyr/sys/spsc_lockfree.h @@ -1,12 +1,11 @@ /* - * Copyright (c) 2022 Intel Corporation + * Copyright (c) 2023 Intel Corporation * * SPDX-License-Identifier: Apache-2.0 */ - -#ifndef ZEPHYR_RTIO_SPSC_H_ -#define ZEPHYR_RTIO_SPSC_H_ +#ifndef ZEPHYR_SYS_SPSC_LOCKFREE_H_ +#define ZEPHYR_SYS_SPSC_LOCKFREE_H_ #include #include @@ -15,14 +14,14 @@ #include /** - * @brief RTIO Single Producer Single Consumer (SPSC) Queue API - * @defgroup rtio_spsc RTIO SPSC API - * @ingroup rtio + * @brief Single Producer Single Consumer (SPSC) Lockfree Queue API + * @defgroup spsc_lockfree SPSC API + * @ingroup datastructure_apis * @{ */ /** - * @file rtio_spsc.h + * @file spsc_lockfree.h * * @brief A lock-free and type safe power of 2 fixed sized single producer * single consumer (SPSC) queue using a ringbuffer and atomics to ensure @@ -57,7 +56,7 @@ * * @warning Not to be manipulated without the macros! */ -struct rtio_spsc { +struct spsc { /* private value only the producer thread should mutate */ unsigned long acquire; @@ -75,53 +74,54 @@ struct rtio_spsc { }; /** - * @brief Statically initialize an rtio_spsc + * @brief Statically initialize an spsc * * @param sz Size of the spsc, must be power of 2 (ex: 2, 4, 8) * @param buf Buffer pointer */ -#define RTIO_SPSC_INITIALIZER(sz, buf) \ - { \ - ._spsc = { \ - .acquire = 0, \ - .consume = 0, \ - .in = ATOMIC_INIT(0), \ - .out = ATOMIC_INIT(0), \ - .mask = sz - 1, \ - }, \ - .buffer = buf, \ +#define SPSC_INITIALIZER(sz, buf) \ + { \ + ._spsc = \ + { \ + .acquire = 0, \ + .consume = 0, \ + .in = ATOMIC_INIT(0), \ + .out = ATOMIC_INIT(0), \ + .mask = sz - 1, \ + }, \ + .buffer = buf, \ } /** - * @brief Declare an anonymous struct type for an rtio_spsc + * @brief Declare an anonymous struct type for an spsc * * @param name Name of the spsc symbol to be provided * @param type Type stored in the spsc */ -#define RTIO_SPSC_DECLARE(name, type) \ - static struct rtio_spsc_##name { \ - struct rtio_spsc _spsc; \ - type * const buffer; \ +#define SPSC_DECLARE(name, type) \ + static struct spsc_##name { \ + struct spsc _spsc; \ + type * const buffer; \ } /** - * @brief Define an rtio_spsc with a fixed size + * @brief Define an spsc with a fixed size * * @param name Name of the spsc symbol to be provided * @param type Type stored in the spsc * @param sz Size of the spsc, must be power of 2 (ex: 2, 4, 8) */ -#define RTIO_SPSC_DEFINE(name, type, sz) \ - BUILD_ASSERT(IS_POWER_OF_TWO(sz)); \ - static type __spsc_buf_##name[sz]; \ - RTIO_SPSC_DECLARE(name, type) name = RTIO_SPSC_INITIALIZER(sz, __spsc_buf_##name); +#define SPSC_DEFINE(name, type, sz) \ + BUILD_ASSERT(IS_POWER_OF_TWO(sz)); \ + static type __spsc_buf_##name[sz]; \ + SPSC_DECLARE(name, type) name = SPSC_INITIALIZER(sz, __spsc_buf_##name); /** * @brief Size of the SPSC queue * * @param spsc SPSC reference */ -#define rtio_spsc_size(spsc) ((spsc)->_spsc.mask + 1) +#define spsc_size(spsc) ((spsc)->_spsc.mask + 1) /** * @private @@ -130,20 +130,19 @@ struct rtio_spsc { * @param spsc SPSC reference * @param i Value to modulo to the size of the spsc */ -#define z_rtio_spsc_mask(spsc, i) ((i) & (spsc)->_spsc.mask) - +#define z_spsc_mask(spsc, i) ((i) & (spsc)->_spsc.mask) /** * @private * @brief Load the current "in" index from the spsc as an unsigned long */ -#define z_rtio_spsc_in(spsc) (unsigned long)atomic_get(&(spsc)->_spsc.in) +#define z_spsc_in(spsc) (unsigned long)atomic_get(&(spsc)->_spsc.in) /** * @private * @brief Load the current "out" index from the spsc as an unsigned long */ -#define z_rtio_spsc_out(spsc) (unsigned long)atomic_get(&(spsc)->_spsc.out) +#define z_spsc_out(spsc) (unsigned long)atomic_get(&(spsc)->_spsc.out) /** * @brief Initialize/reset a spsc such that its empty @@ -153,7 +152,7 @@ struct rtio_spsc { * * @param spsc SPSC to initialize/reset */ -#define rtio_spsc_reset(spsc) \ +#define spsc_reset(spsc) \ ({ \ (spsc)->_spsc.consume = 0; \ (spsc)->_spsc.acquire = 0; \ @@ -168,14 +167,14 @@ struct rtio_spsc { * * @return A pointer to the acquired element or null if the spsc is full */ -#define rtio_spsc_acquire(spsc) \ +#define spsc_acquire(spsc) \ ({ \ - unsigned long idx = z_rtio_spsc_in(spsc) + (spsc)->_spsc.acquire; \ - bool spsc_acq = (idx - z_rtio_spsc_out(spsc)) < rtio_spsc_size(spsc); \ + unsigned long idx = z_spsc_in(spsc) + (spsc)->_spsc.acquire; \ + bool spsc_acq = (idx - z_spsc_out(spsc)) < spsc_size(spsc); \ if (spsc_acq) { \ (spsc)->_spsc.acquire += 1; \ } \ - spsc_acq ? &((spsc)->buffer[z_rtio_spsc_mask(spsc, idx)]) : NULL; \ + spsc_acq ? &((spsc)->buffer[z_spsc_mask(spsc, idx)]) : NULL; \ }) /** @@ -185,7 +184,7 @@ struct rtio_spsc { * * @param spsc SPSC to produce the previously acquired element or do nothing */ -#define rtio_spsc_produce(spsc) \ +#define spsc_produce(spsc) \ ({ \ if ((spsc)->_spsc.acquire > 0) { \ (spsc)->_spsc.acquire -= 1; \ @@ -201,7 +200,7 @@ struct rtio_spsc { * * @param spsc SPSC to produce all previously acquired elements or do nothing */ -#define rtio_spsc_produce_all(spsc) \ +#define spsc_produce_all(spsc) \ ({ \ if ((spsc)->_spsc.acquire > 0) { \ unsigned long acquired = (spsc)->_spsc.acquire; \ @@ -217,9 +216,9 @@ struct rtio_spsc { * * @param spsc SPSC to drop all previously acquired elements or do nothing */ -#define rtio_spsc_drop_all(spsc) \ - do { \ - (spsc)->_spsc.acquire = 0; \ +#define spsc_drop_all(spsc) \ + do { \ + (spsc)->_spsc.acquire = 0; \ } while (false) /** @@ -229,14 +228,14 @@ struct rtio_spsc { * * @return Pointer to element or null if no consumable elements left */ -#define rtio_spsc_consume(spsc) \ +#define spsc_consume(spsc) \ ({ \ - unsigned long idx = z_rtio_spsc_out(spsc) + (spsc)->_spsc.consume; \ - bool has_consumable = (idx != z_rtio_spsc_in(spsc)); \ + unsigned long idx = z_spsc_out(spsc) + (spsc)->_spsc.consume; \ + bool has_consumable = (idx != z_spsc_in(spsc)); \ if (has_consumable) { \ (spsc)->_spsc.consume += 1; \ } \ - has_consumable ? &((spsc)->buffer[z_rtio_spsc_mask(spsc, idx)]) : NULL; \ + has_consumable ? &((spsc)->buffer[z_spsc_mask(spsc, idx)]) : NULL; \ }) /** @@ -244,7 +243,7 @@ struct rtio_spsc { * * @param spsc SPSC to release consumed element or do nothing */ -#define rtio_spsc_release(spsc) \ +#define spsc_release(spsc) \ ({ \ if ((spsc)->_spsc.consume > 0) { \ (spsc)->_spsc.consume -= 1; \ @@ -252,13 +251,12 @@ struct rtio_spsc { } \ }) - /** * @brief Release all consumed elements * * @param spsc SPSC to release consumed elements or do nothing */ -#define rtio_spsc_release_all(spsc) \ +#define spsc_release_all(spsc) \ ({ \ if ((spsc)->_spsc.consume > 0) { \ unsigned long consumed = (spsc)->_spsc.consume; \ @@ -272,19 +270,15 @@ struct rtio_spsc { * * @param spsc SPSC to get item count for */ -#define rtio_spsc_acquirable(spsc) \ - ({ \ - (((spsc)->_spsc.in + (spsc)->_spsc.acquire) - (spsc)->_spsc.out) - \ - rtio_spsc_size(spsc); \ - }) +#define spsc_acquirable(spsc) \ + ({ (((spsc)->_spsc.in + (spsc)->_spsc.acquire) - (spsc)->_spsc.out) - spsc_size(spsc); }) /** * @brief Count of consumables in spsc * * @param spsc SPSC to get item count for */ -#define rtio_spsc_consumable(spsc) \ - ({ (spsc)->_spsc.in - (spsc)->_spsc.out - (spsc)->_spsc.consume; }) +#define spsc_consumable(spsc) ({ (spsc)->_spsc.in - (spsc)->_spsc.out - (spsc)->_spsc.consume; }) /** * @brief Peek at the first available item in queue @@ -293,11 +287,11 @@ struct rtio_spsc { * * @return Pointer to element or null if no consumable elements left */ -#define rtio_spsc_peek(spsc) \ +#define spsc_peek(spsc) \ ({ \ - unsigned long idx = z_rtio_spsc_out(spsc) + (spsc)->_spsc.consume; \ - bool has_consumable = (idx != z_rtio_spsc_in(spsc)); \ - has_consumable ? &((spsc)->buffer[z_rtio_spsc_mask(spsc, idx)]) : NULL; \ + unsigned long idx = z_spsc_out(spsc) + (spsc)->_spsc.consume; \ + bool has_consumable = (idx != z_spsc_in(spsc)); \ + has_consumable ? &((spsc)->buffer[z_spsc_mask(spsc, idx)]) : NULL; \ }) /** @@ -309,12 +303,12 @@ struct rtio_spsc { * * @return Pointer to element or null if none left */ -#define rtio_spsc_next(spsc, item) \ +#define spsc_next(spsc, item) \ ({ \ unsigned long idx = ((item) - (spsc)->buffer); \ - bool has_next = z_rtio_spsc_mask(spsc, (idx + 1)) != \ - (z_rtio_spsc_mask(spsc, z_rtio_spsc_in(spsc))); \ - has_next ? &((spsc)->buffer[z_rtio_spsc_mask((spsc), idx + 1)]) : NULL; \ + bool has_next = \ + z_spsc_mask(spsc, (idx + 1)) != (z_spsc_mask(spsc, z_spsc_in(spsc))); \ + has_next ? &((spsc)->buffer[z_spsc_mask((spsc), idx + 1)]) : NULL; \ }) /** @@ -325,15 +319,15 @@ struct rtio_spsc { * * @return Pointer to element or null if none left */ -#define rtio_spsc_prev(spsc, item) \ +#define spsc_prev(spsc, item) \ ({ \ unsigned long idx = ((item) - &(spsc)->buffer[0]) / sizeof((spsc)->buffer[0]); \ - bool has_prev = idx != z_rtio_spsc_mask(spsc, z_rtio_spsc_out(spsc)); \ - has_prev ? &((spsc)->buffer[z_rtio_spsc_mask(spsc, idx - 1)]) : NULL; \ + bool has_prev = idx != z_spsc_mask(spsc, z_spsc_out(spsc)); \ + has_prev ? &((spsc)->buffer[z_spsc_mask(spsc, idx - 1)]) : NULL; \ }) /** * @} */ -#endif /* ZEPHYR_RTIO_SPSC_H_ */ +#endif /* ZEPHYR_SYS_SPSC_LOCKFREE_H_ */ diff --git a/samples/subsys/rtio/sensor_batch_processing/src/vnd_sensor.c b/samples/subsys/rtio/sensor_batch_processing/src/vnd_sensor.c index a8662c0499870..ead3c64a64847 100644 --- a/samples/subsys/rtio/sensor_batch_processing/src/vnd_sensor.c +++ b/samples/subsys/rtio/sensor_batch_processing/src/vnd_sensor.c @@ -83,13 +83,13 @@ static void vnd_sensor_iodev_submit(struct rtio_iodev_sqe *iodev_sqe) { struct vnd_sensor_data *data = (struct vnd_sensor_data *) iodev_sqe->sqe.iodev; - rtio_mpsc_push(&data->iodev.iodev_sq, &iodev_sqe->q); + mpsc_push(&data->iodev.iodev_sq, &iodev_sqe->q); } static void vnd_sensor_handle_int(const struct device *dev) { struct vnd_sensor_data *data = dev->data; - struct rtio_mpsc_node *node = rtio_mpsc_pop(&data->iodev.iodev_sq); + struct mpsc_node *node = mpsc_pop(&data->iodev.iodev_sq); if (node != NULL) { struct rtio_iodev_sqe *iodev_sqe = CONTAINER_OF(node, struct rtio_iodev_sqe, q); @@ -116,7 +116,7 @@ static int vnd_sensor_init(const struct device *dev) data->dev = dev; - rtio_mpsc_init(&data->iodev.iodev_sq); + mpsc_init(&data->iodev.iodev_sq); k_timer_init(&data->timer, vnd_sensor_timer_expiry, NULL); diff --git a/subsys/rtio/rtio_executor.c b/subsys/rtio/rtio_executor.c index 13fd6a7e4ddf0..651ab64d5d25a 100644 --- a/subsys/rtio/rtio_executor.c +++ b/subsys/rtio/rtio_executor.c @@ -61,7 +61,7 @@ static inline void rtio_iodev_submit(struct rtio_iodev_sqe *iodev_sqe) void rtio_executor_submit(struct rtio *r) { const uint16_t cancel_no_response = (RTIO_SQE_CANCELED | RTIO_SQE_NO_RESPONSE); - struct rtio_mpsc_node *node = rtio_mpsc_pop(&r->sq); + struct mpsc_node *node = mpsc_pop(&r->sq); while (node != NULL) { struct rtio_iodev_sqe *iodev_sqe = CONTAINER_OF(node, struct rtio_iodev_sqe, q); @@ -83,7 +83,7 @@ void rtio_executor_submit(struct rtio *r) __ASSERT(transaction != chained, "Expected chained or transaction flag, not both"); #endif - node = rtio_mpsc_pop(&iodev_sqe->r->sq); + node = mpsc_pop(&iodev_sqe->r->sq); next = CONTAINER_OF(node, struct rtio_iodev_sqe, q); /* If the current submission was cancelled before submit, @@ -106,7 +106,7 @@ void rtio_executor_submit(struct rtio *r) rtio_iodev_submit(iodev_sqe); - node = rtio_mpsc_pop(&r->sq); + node = mpsc_pop(&r->sq); } } @@ -134,7 +134,7 @@ static inline void rtio_executor_handle_multishot(struct rtio *r, struct rtio_io } if (!is_canceled) { /* Request was not canceled, put the SQE back in the queue */ - rtio_mpsc_push(&r->sq, &curr->q); + mpsc_push(&r->sq, &curr->q); rtio_executor_submit(r); } } diff --git a/subsys/rtio/rtio_init.c b/subsys/rtio/rtio_init.c index e4deb14b723a3..1332529907bba 100644 --- a/subsys/rtio/rtio_init.c +++ b/subsys/rtio/rtio_init.c @@ -5,6 +5,7 @@ #include #include +#include #include #include #include @@ -17,13 +18,13 @@ int rtio_init(void) { STRUCT_SECTION_FOREACH(rtio_sqe_pool, sqe_pool) { for (int i = 0; i < sqe_pool->pool_size; i++) { - rtio_mpsc_push(&sqe_pool->free_q, &sqe_pool->pool[i].q); + mpsc_push(&sqe_pool->free_q, &sqe_pool->pool[i].q); } } STRUCT_SECTION_FOREACH(rtio_cqe_pool, cqe_pool) { for (int i = 0; i < cqe_pool->pool_size; i++) { - rtio_mpsc_push(&cqe_pool->free_q, &cqe_pool->pool[i].q); + mpsc_push(&cqe_pool->free_q, &cqe_pool->pool[i].q); } } diff --git a/tests/lib/cpp/cxx/src/main.cpp b/tests/lib/cpp/cxx/src/main.cpp index dd377c015b8da..b8b77c6c26a5a 100644 --- a/tests/lib/cpp/cxx/src/main.cpp +++ b/tests/lib/cpp/cxx/src/main.cpp @@ -79,8 +79,8 @@ /* Add RTIO headers to make sure they're CXX compatible */ #include -#include -#include +#include +#include #include diff --git a/tests/lib/lockfree/CMakeLists.txt b/tests/lib/lockfree/CMakeLists.txt new file mode 100644 index 0000000000000..4cc3b1f3d9733 --- /dev/null +++ b/tests/lib/lockfree/CMakeLists.txt @@ -0,0 +1,12 @@ +# Copyright (c) 2023 Intel Corporation. +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(lockfree_test) + +target_sources(app PRIVATE src/test_spsc.c src/test_mpsc.c) + +target_include_directories(app PRIVATE + ${ZEPHYR_BASE}/include + ${ZEPHYR_BASE}/arch/${ARCH}/include) diff --git a/tests/lib/lockfree/prj.conf b/tests/lib/lockfree/prj.conf new file mode 100644 index 0000000000000..49b37026ea3d7 --- /dev/null +++ b/tests/lib/lockfree/prj.conf @@ -0,0 +1,2 @@ +CONFIG_ZTEST=y +CONFIG_TIMING_FUNCTIONS=y diff --git a/tests/subsys/rtio/rtio_api/src/test_rtio_mpsc.c b/tests/lib/lockfree/src/test_mpsc.c similarity index 71% rename from tests/subsys/rtio/rtio_api/src/test_rtio_mpsc.c rename to tests/lib/lockfree/src/test_mpsc.c index a656c119b9e87..91381d58d2cc7 100644 --- a/tests/subsys/rtio/rtio_api/src/test_rtio_mpsc.c +++ b/tests/lib/lockfree/src/test_mpsc.c @@ -4,32 +4,31 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include "zephyr/irq.h" #include #include #include #include -#include -#include +#include +#include -#include "rtio_api.h" - -static struct rtio_mpsc push_pop_q; -static struct rtio_mpsc_node push_pop_nodes[2]; +static struct mpsc push_pop_q; +static struct mpsc_node push_pop_nodes[2]; /* * @brief Push and pop one element * - * @see rtio_mpsc_push(), rtio_mpsc_pop() + * @see mpsc_push(), mpsc_pop() * - * @ingroup rtio_tests + * @ingroup tests */ -ZTEST(rtio_mpsc, test_push_pop) +ZTEST(mpsc, test_push_pop) { mpsc_ptr_t node, head; - struct rtio_mpsc_node *stub, *next, *tail; + struct mpsc_node *stub, *next, *tail; - rtio_mpsc_init(&push_pop_q); + mpsc_init(&push_pop_q); head = mpsc_ptr_get(push_pop_q.head); tail = push_pop_q.tail; @@ -40,10 +39,10 @@ ZTEST(rtio_mpsc, test_push_pop) zassert_equal(tail, stub, "Tail should point at stub"); zassert_is_null(next, "Next should be null"); - node = rtio_mpsc_pop(&push_pop_q); + node = mpsc_pop(&push_pop_q); zassert_is_null(node, "Pop on empty queue should return null"); - rtio_mpsc_push(&push_pop_q, &push_pop_nodes[0]); + mpsc_push(&push_pop_q, &push_pop_nodes[0]); head = mpsc_ptr_get(push_pop_q.head); @@ -56,7 +55,7 @@ ZTEST(rtio_mpsc, test_push_pop) stub = &push_pop_q.stub; zassert_equal(tail, stub, "Tail should point at stub"); - node = rtio_mpsc_pop(&push_pop_q); + node = mpsc_pop(&push_pop_q); stub = &push_pop_q.stub; zassert_not_equal(node, stub, "Pop should not return stub"); @@ -65,7 +64,7 @@ ZTEST(rtio_mpsc, test_push_pop) "Pop should return push_pop_node %p, instead was %p", &push_pop_nodes[0], node); - node = rtio_mpsc_pop(&push_pop_q); + node = mpsc_pop(&push_pop_q); zassert_is_null(node, "Pop on empty queue should return null"); } @@ -74,31 +73,38 @@ ZTEST(rtio_mpsc, test_push_pop) #define MPSC_STACK_SIZE (512 + CONFIG_TEST_EXTRA_STACK_SIZE) #define MPSC_THREADS_NUM 4 +struct thread_info { + k_tid_t tid; + int executed; + int priority; + int cpu_id; +}; + static struct thread_info mpsc_tinfo[MPSC_THREADS_NUM]; static struct k_thread mpsc_thread[MPSC_THREADS_NUM]; static K_THREAD_STACK_ARRAY_DEFINE(mpsc_stack, MPSC_THREADS_NUM, MPSC_STACK_SIZE); -struct mpsc_node { +struct test_mpsc_node { uint32_t id; - struct rtio_mpsc_node n; + struct mpsc_node n; }; -struct rtio_spsc_node_sq { - struct rtio_spsc _spsc; - struct mpsc_node *const buffer; +struct spsc_node_sq { + struct spsc _spsc; + struct test_mpsc_node *const buffer; }; -#define SPSC_DEFINE(n, sz) RTIO_SPSC_DEFINE(_spsc_##n, struct mpsc_node, sz) -#define SPSC_NAME(n, _) (struct rtio_spsc_node_sq *)&_spsc_##n +#define TEST_SPSC_DEFINE(n, sz) SPSC_DEFINE(_spsc_##n, struct test_mpsc_node, sz) +#define SPSC_NAME(n, _) (struct spsc_node_sq *)&_spsc_##n -LISTIFY(MPSC_THREADS_NUM, SPSC_DEFINE, (;), MPSC_FREEQ_SZ) +LISTIFY(MPSC_THREADS_NUM, TEST_SPSC_DEFINE, (;), MPSC_FREEQ_SZ) -struct rtio_spsc_node_sq *node_q[MPSC_THREADS_NUM] = { +struct spsc_node_sq *node_q[MPSC_THREADS_NUM] = { LISTIFY(MPSC_THREADS_NUM, SPSC_NAME, (,)) }; -static struct rtio_mpsc mpsc_q; +static struct mpsc mpsc_q; static void mpsc_consumer(void *p1, void *p2, void *p3) { @@ -106,12 +112,12 @@ static void mpsc_consumer(void *p1, void *p2, void *p3) ARG_UNUSED(p2); ARG_UNUSED(p3); - struct rtio_mpsc_node *n; - struct mpsc_node *nn; + struct mpsc_node *n; + struct test_mpsc_node *nn; for (int i = 0; i < (MPSC_ITERATIONS)*(MPSC_THREADS_NUM - 1); i++) { do { - n = rtio_mpsc_pop(&mpsc_q); + n = mpsc_pop(&mpsc_q); if (n == NULL) { k_yield(); } @@ -119,10 +125,10 @@ static void mpsc_consumer(void *p1, void *p2, void *p3) zassert_not_equal(n, &mpsc_q.stub, "mpsc should not produce stub"); - nn = CONTAINER_OF(n, struct mpsc_node, n); + nn = CONTAINER_OF(n, struct test_mpsc_node, n); - rtio_spsc_acquire(node_q[nn->id]); - rtio_spsc_produce(node_q[nn->id]); + spsc_acquire(node_q[nn->id]); + spsc_produce(node_q[nn->id]); } } @@ -132,20 +138,20 @@ static void mpsc_producer(void *p1, void *p2, void *p3) ARG_UNUSED(p2); ARG_UNUSED(p3); - struct mpsc_node *n; + struct test_mpsc_node *n; uint32_t id = (uint32_t)(uintptr_t)p1; for (int i = 0; i < MPSC_ITERATIONS; i++) { do { - n = rtio_spsc_consume(node_q[id]); + n = spsc_consume(node_q[id]); if (n == NULL) { k_yield(); } } while (n == NULL); - rtio_spsc_release(node_q[id]); + spsc_release(node_q[id]); n->id = id; - rtio_mpsc_push(&mpsc_q, &n->n); + mpsc_push(&mpsc_q, &n->n); } } @@ -155,17 +161,17 @@ static void mpsc_producer(void *p1, void *p2, void *p3) * This can and should be validated on SMP machines where incoherent * memory could cause issues. */ -ZTEST(rtio_mpsc, test_mpsc_threaded) +ZTEST(mpsc, test_mpsc_threaded) { - rtio_mpsc_init(&mpsc_q); + mpsc_init(&mpsc_q); TC_PRINT("setting up mpsc producer free queues\n"); /* Setup node free queues */ for (int i = 0; i < MPSC_THREADS_NUM; i++) { for (int j = 0; j < MPSC_FREEQ_SZ; j++) { - rtio_spsc_acquire(node_q[i]); + spsc_acquire(node_q[i]); } - rtio_spsc_produce_all(node_q[i]); + spsc_produce_all(node_q[i]); } TC_PRINT("starting consumer\n"); @@ -194,23 +200,27 @@ ZTEST(rtio_mpsc, test_mpsc_threaded) #define THROUGHPUT_ITERS 100000 -ZTEST(rtio_mpsc, test_mpsc_throughput) +ZTEST(mpsc, test_mpsc_throughput) { - struct rtio_mpsc_node node; + struct mpsc_node node; timing_t start_time, end_time; - rtio_mpsc_init(&mpsc_q); + mpsc_init(&mpsc_q); timing_init(); timing_start(); start_time = timing_counter_get(); + int key = irq_lock(); + for (int i = 0; i < THROUGHPUT_ITERS; i++) { - rtio_mpsc_push(&mpsc_q, &node); + mpsc_push(&mpsc_q, &node); - rtio_mpsc_pop(&mpsc_q); + mpsc_pop(&mpsc_q); } + irq_unlock(key); + end_time = timing_counter_get(); uint64_t cycles = timing_cycles_get(&start_time, &end_time); @@ -220,4 +230,4 @@ ZTEST(rtio_mpsc, test_mpsc_throughput) THROUGHPUT_ITERS, ns/THROUGHPUT_ITERS); } -ZTEST_SUITE(rtio_mpsc, NULL, NULL, NULL, NULL, NULL); +ZTEST_SUITE(mpsc, NULL, NULL, NULL, NULL, NULL); diff --git a/tests/subsys/rtio/rtio_api/src/test_rtio_spsc.c b/tests/lib/lockfree/src/test_spsc.c similarity index 63% rename from tests/subsys/rtio/rtio_api/src/test_rtio_spsc.c rename to tests/lib/lockfree/src/test_spsc.c index 12fe9476f3fb9..e2539ca6ccdf9 100644 --- a/tests/subsys/rtio/rtio_api/src/test_rtio_spsc.c +++ b/tests/lib/lockfree/src/test_spsc.c @@ -6,61 +6,60 @@ #include #include -#include -#include "rtio_api.h" +#include /* * @brief Produce and Consume a single uint32_t in the same execution context * - * @see rtio_spsc_acquire(), rtio_spsc_produce(), rtio_spsc_consume(), rtio_spsc_release() + * @see spsc_acquire(), spsc_produce(), spsc_consume(), spsc_release() * - * @ingroup rtio_tests + * @ingroup tests */ -ZTEST(rtio_spsc, test_produce_consume_size1) +ZTEST(spsc, test_produce_consume_size1) { - RTIO_SPSC_DEFINE(ezspsc, uint32_t, 1); + SPSC_DEFINE(ezspsc, uint32_t, 1); const uint32_t magic = 43219876; - uint32_t *acq = rtio_spsc_acquire(&ezspsc); + uint32_t *acq = spsc_acquire(&ezspsc); zassert_not_null(acq, "Acquire should succeed"); *acq = magic; - uint32_t *acq2 = rtio_spsc_acquire(&ezspsc); + uint32_t *acq2 = spsc_acquire(&ezspsc); zassert_is_null(acq2, "Acquire should fail"); - uint32_t *cons = rtio_spsc_consume(&ezspsc); + uint32_t *cons = spsc_consume(&ezspsc); zassert_is_null(cons, "Consume should fail"); - zassert_equal(rtio_spsc_consumable(&ezspsc), 0, "Consumables should be 0"); + zassert_equal(spsc_consumable(&ezspsc), 0, "Consumables should be 0"); - rtio_spsc_produce(&ezspsc); + spsc_produce(&ezspsc); - zassert_equal(rtio_spsc_consumable(&ezspsc), 1, "Consumables should be 1"); + zassert_equal(spsc_consumable(&ezspsc), 1, "Consumables should be 1"); - uint32_t *cons2 = rtio_spsc_consume(&ezspsc); + uint32_t *cons2 = spsc_consume(&ezspsc); - zassert_equal(rtio_spsc_consumable(&ezspsc), 0, "Consumables should be 0"); + zassert_equal(spsc_consumable(&ezspsc), 0, "Consumables should be 0"); zassert_not_null(cons2, "Consume should not fail"); zassert_equal(*cons2, magic, "Consume value should equal magic"); - uint32_t *cons3 = rtio_spsc_consume(&ezspsc); + uint32_t *cons3 = spsc_consume(&ezspsc); zassert_is_null(cons3, "Consume should fail"); - uint32_t *acq3 = rtio_spsc_acquire(&ezspsc); + uint32_t *acq3 = spsc_acquire(&ezspsc); zassert_is_null(acq3, "Acquire should not succeed"); - rtio_spsc_release(&ezspsc); + spsc_release(&ezspsc); - uint32_t *acq4 = rtio_spsc_acquire(&ezspsc); + uint32_t *acq4 = spsc_acquire(&ezspsc); zassert_not_null(acq4, "Acquire should succeed"); } @@ -69,34 +68,34 @@ ZTEST(rtio_spsc, test_produce_consume_size1) * @brief Produce and Consume 3 items at a time in a spsc of size 4 to validate masking * and wrap around reads/writes. * - * @see rtio_spsc_acquire(), rtio_spsc_produce(), rtio_spsc_consume(), rtio_spsc_release() + * @see spsc_acquire(), spsc_produce(), spsc_consume(), spsc_release() * - * @ingroup rtio_tests + * @ingroup tests */ -ZTEST(rtio_spsc, test_produce_consume_wrap_around) +ZTEST(spsc, test_produce_consume_wrap_around) { - RTIO_SPSC_DEFINE(ezspsc, uint32_t, 4); + SPSC_DEFINE(ezspsc, uint32_t, 4); for (int i = 0; i < 10; i++) { - zassert_equal(rtio_spsc_consumable(&ezspsc), 0, "Consumables should be 0"); + zassert_equal(spsc_consumable(&ezspsc), 0, "Consumables should be 0"); for (int j = 0; j < 3; j++) { - uint32_t *entry = rtio_spsc_acquire(&ezspsc); + uint32_t *entry = spsc_acquire(&ezspsc); zassert_not_null(entry, "Acquire should succeed"); *entry = i * 3 + j; - rtio_spsc_produce(&ezspsc); + spsc_produce(&ezspsc); } - zassert_equal(rtio_spsc_consumable(&ezspsc), 3, "Consumables should be 3"); + zassert_equal(spsc_consumable(&ezspsc), 3, "Consumables should be 3"); for (int k = 0; k < 3; k++) { - uint32_t *entry = rtio_spsc_consume(&ezspsc); + uint32_t *entry = spsc_consume(&ezspsc); zassert_not_null(entry, "Consume should succeed"); zassert_equal(*entry, i * 3 + k, "Consume value should equal i*3+k"); - rtio_spsc_release(&ezspsc); + spsc_release(&ezspsc); } - zassert_equal(rtio_spsc_consumable(&ezspsc), 0, "Consumables should be 0"); + zassert_equal(spsc_consumable(&ezspsc), 0, "Consumables should be 0"); } } @@ -107,28 +106,28 @@ ZTEST(rtio_spsc, test_produce_consume_wrap_around) * Done by setting all values to UINTPTR_MAX - 2 and writing and reading enough * to ensure integer wraps occur. */ -ZTEST(rtio_spsc, test_int_wrap_around) +ZTEST(spsc, test_int_wrap_around) { - RTIO_SPSC_DEFINE(ezspsc, uint32_t, 4); + SPSC_DEFINE(ezspsc, uint32_t, 4); ezspsc._spsc.in = ATOMIC_INIT(UINTPTR_MAX - 2); ezspsc._spsc.out = ATOMIC_INIT(UINTPTR_MAX - 2); for (int j = 0; j < 3; j++) { - uint32_t *entry = rtio_spsc_acquire(&ezspsc); + uint32_t *entry = spsc_acquire(&ezspsc); zassert_not_null(entry, "Acquire should succeed"); *entry = j; - rtio_spsc_produce(&ezspsc); + spsc_produce(&ezspsc); } zassert_equal(atomic_get(&ezspsc._spsc.in), UINTPTR_MAX + 1, "Spsc in should wrap"); for (int k = 0; k < 3; k++) { - uint32_t *entry = rtio_spsc_consume(&ezspsc); + uint32_t *entry = spsc_consume(&ezspsc); zassert_not_null(entry, "Consume should succeed"); zassert_equal(*entry, k, "Consume value should equal i*3+k"); - rtio_spsc_release(&ezspsc); + spsc_release(&ezspsc); } zassert_equal(atomic_get(&ezspsc._spsc.out), UINTPTR_MAX + 1, "Spsc out should wrap"); @@ -137,14 +136,14 @@ ZTEST(rtio_spsc, test_int_wrap_around) #define MAX_RETRIES 5 #define SMP_ITERATIONS 100 -RTIO_SPSC_DEFINE(spsc, uint32_t, 4); +SPSC_DEFINE(spsc, uint32_t, 4); static void t1_consume(void *p1, void *p2, void *p3) { ARG_UNUSED(p2); ARG_UNUSED(p3); - struct rtio_spsc_spsc *ezspsc = p1; + struct spsc_spsc *ezspsc = p1; uint32_t retries = 0; uint32_t *val = NULL; @@ -152,11 +151,11 @@ static void t1_consume(void *p1, void *p2, void *p3) val = NULL; retries = 0; while (val == NULL && retries < MAX_RETRIES) { - val = rtio_spsc_consume(ezspsc); + val = spsc_consume(ezspsc); retries++; } if (val != NULL) { - rtio_spsc_release(ezspsc); + spsc_release(ezspsc); } else { k_yield(); } @@ -168,7 +167,7 @@ static void t2_produce(void *p1, void *p2, void *p3) ARG_UNUSED(p2); ARG_UNUSED(p3); - struct rtio_spsc_spsc *ezspsc = p1; + struct spsc_spsc *ezspsc = p1; uint32_t retries = 0; uint32_t *val = NULL; @@ -176,12 +175,12 @@ static void t2_produce(void *p1, void *p2, void *p3) val = NULL; retries = 0; while (val == NULL && retries < MAX_RETRIES) { - val = rtio_spsc_acquire(ezspsc); + val = spsc_acquire(ezspsc); retries++; } if (val != NULL) { *val = SMP_ITERATIONS; - rtio_spsc_produce(ezspsc); + spsc_produce(ezspsc); } else { k_yield(); } @@ -192,6 +191,13 @@ static void t2_produce(void *p1, void *p2, void *p3) #define STACK_SIZE (384 + CONFIG_TEST_EXTRA_STACK_SIZE) #define THREADS_NUM 2 +struct thread_info { + k_tid_t tid; + int executed; + int priority; + int cpu_id; +}; + static struct thread_info tinfo[THREADS_NUM]; static struct k_thread tthread[THREADS_NUM]; static K_THREAD_STACK_ARRAY_DEFINE(tstack, THREADS_NUM, STACK_SIZE); @@ -202,7 +208,7 @@ static K_THREAD_STACK_ARRAY_DEFINE(tstack, THREADS_NUM, STACK_SIZE); * This can and should be validated on SMP machines where incoherent * memory could cause issues. */ -ZTEST(rtio_spsc, test_spsc_threaded) +ZTEST(spsc, test_spsc_threaded) { tinfo[0].tid = @@ -224,7 +230,7 @@ ZTEST(rtio_spsc, test_spsc_threaded) #define THROUGHPUT_ITERS 100000 -ZTEST(rtio_spsc, test_spsc_throughput) +ZTEST(spsc, test_spsc_throughput) { timing_t start_time, end_time; @@ -235,15 +241,19 @@ ZTEST(rtio_spsc, test_spsc_throughput) uint32_t *x, *y; + int key = irq_lock(); + for (int i = 0; i < THROUGHPUT_ITERS; i++) { - x = rtio_spsc_acquire(&spsc); + x = spsc_acquire(&spsc); *x = i; - rtio_spsc_produce(&spsc); + spsc_produce(&spsc); - y = rtio_spsc_consume(&spsc); - rtio_spsc_release(&spsc); + y = spsc_consume(&spsc); + spsc_release(&spsc); } + irq_unlock(key); + end_time = timing_counter_get(); uint64_t cycles = timing_cycles_get(&start_time, &end_time); @@ -253,11 +263,11 @@ ZTEST(rtio_spsc, test_spsc_throughput) THROUGHPUT_ITERS, ns/THROUGHPUT_ITERS); } -static void rtio_spsc_before(void *data) +static void spsc_before(void *data) { ARG_UNUSED(data); - rtio_spsc_reset(&spsc); + spsc_reset(&spsc); } -ZTEST_SUITE(rtio_spsc, NULL, NULL, rtio_spsc_before, NULL, NULL); +ZTEST_SUITE(spsc, NULL, NULL, spsc_before, NULL, NULL); diff --git a/tests/lib/lockfree/testcase.yaml b/tests/lib/lockfree/testcase.yaml new file mode 100644 index 0000000000000..e541a6904a77f --- /dev/null +++ b/tests/lib/lockfree/testcase.yaml @@ -0,0 +1,7 @@ +tests: + libraries.lockfree: + platform_exclude: + - m5stack_core2 # renode times out + - m2gl025_miv # renode times out + tags: + - lockfree diff --git a/tests/subsys/rtio/rtio_api/CMakeLists.txt b/tests/subsys/rtio/rtio_api/CMakeLists.txt index 3ece5f0c51e2d..88d15b5f0da54 100644 --- a/tests/subsys/rtio/rtio_api/CMakeLists.txt +++ b/tests/subsys/rtio/rtio_api/CMakeLists.txt @@ -5,7 +5,7 @@ cmake_minimum_required(VERSION 3.20.0) find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) project(rtio_api_test) -target_sources(app PRIVATE src/test_rtio_spsc.c src/test_rtio_mpsc.c src/test_rtio_api.c) +target_sources(app PRIVATE src/test_rtio_api.c) target_include_directories(app PRIVATE ${ZEPHYR_BASE}/include diff --git a/tests/subsys/rtio/rtio_api/src/rtio_api.h b/tests/subsys/rtio/rtio_api/src/rtio_api.h deleted file mode 100644 index df8d46ae1f7d8..0000000000000 --- a/tests/subsys/rtio/rtio_api/src/rtio_api.h +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright (c) 2023 Intel Corporation. - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#ifndef ZEPHYR_TEST_RTIO_API_H_ -#define ZEPHYR_TEST_RTIO_API_H_ - -#include - -struct thread_info { - k_tid_t tid; - int executed; - int priority; - int cpu_id; -}; - -#endif /* ZEPHYR_TEST_RTIO_API_H_ */ diff --git a/tests/subsys/rtio/rtio_api/src/rtio_iodev_test.h b/tests/subsys/rtio/rtio_api/src/rtio_iodev_test.h index f478ec695ccdb..fab099e7158ce 100644 --- a/tests/subsys/rtio/rtio_api/src/rtio_iodev_test.h +++ b/tests/subsys/rtio/rtio_api/src/rtio_iodev_test.h @@ -5,8 +5,8 @@ */ #include -#include #include +#include #include #ifndef RTIO_IODEV_TEST_H_ @@ -17,7 +17,7 @@ struct rtio_iodev_test_data { struct k_timer timer; /* Queue of requests */ - struct rtio_mpsc io_q; + struct mpsc io_q; /* Currently executing transaction */ struct rtio_iodev_sqe *txn_head; @@ -40,7 +40,7 @@ static void rtio_iodev_test_next(struct rtio_iodev_test_data *data, bool complet goto out; } - struct rtio_mpsc_node *next = rtio_mpsc_pop(&data->io_q); + struct mpsc_node *next = mpsc_pop(&data->io_q); /* Nothing left to do, cleanup */ if (next == NULL) { @@ -110,8 +110,8 @@ static void rtio_iodev_test_submit(struct rtio_iodev_sqe *iodev_sqe) atomic_inc(&data->submit_count); - /* The only safe operation is enqueuing without a lock */ - rtio_mpsc_push(&data->io_q, &iodev_sqe->q); + /* The only safe operation is enqueuing */ + mpsc_push(&data->io_q, &iodev_sqe->q); rtio_iodev_test_next(data, false); } @@ -124,7 +124,7 @@ void rtio_iodev_test_init(struct rtio_iodev *test) { struct rtio_iodev_test_data *data = test->data; - rtio_mpsc_init(&data->io_q); + mpsc_init(&data->io_q); data->txn_head = NULL; data->txn_curr = NULL; k_timer_init(&data->timer, rtio_iodev_timer_fn, NULL); diff --git a/tests/subsys/rtio/rtio_api/src/test_rtio_api.c b/tests/subsys/rtio/rtio_api/src/test_rtio_api.c index 7a92859eba1dc..d101f3bcc2944 100644 --- a/tests/subsys/rtio/rtio_api/src/test_rtio_api.c +++ b/tests/subsys/rtio/rtio_api/src/test_rtio_api.c @@ -672,7 +672,6 @@ void rtio_callback_chaining_cb(struct rtio *r, const struct rtio_sqe *sqe, void */ void test_rtio_callback_chaining_(struct rtio *r) { - int res; int32_t userdata[4] = {0, 1, 2, 3}; int32_t ordering[4] = { -1, -1, -1, -1}; From c5e591bf44f90bd0ad93e173663e419d68c86d55 Mon Sep 17 00:00:00 2001 From: Tom Burdick Date: Wed, 13 Sep 2023 09:16:21 -0500 Subject: [PATCH 1901/2849] sys: MPSC doc comment cleanup The doc comment relating to mpsc atomics was worded poorly. Remove the poorly worded doc comment related to atomics and caches. Signed-off-by: Tom Burdick --- include/zephyr/sys/mpsc_lockfree.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/include/zephyr/sys/mpsc_lockfree.h b/include/zephyr/sys/mpsc_lockfree.h index 66f513072e4b4..3e6c89d99a051 100644 --- a/include/zephyr/sys/mpsc_lockfree.h +++ b/include/zephyr/sys/mpsc_lockfree.h @@ -48,8 +48,7 @@ extern "C" { * by the compiler generated op codes is enough. * * On SMP atomics *must* be used to ensure the pointers - * are updated in the correct order and the values are - * updated core caches correctly. + * are updated in the correct order. */ #if IS_ENABLED(CONFIG_SMP) From e1347ded489e935ca56c7c1ba3a2ebe6252b0577 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20B=C3=B8e?= Date: Mon, 27 May 2024 09:58:10 +0200 Subject: [PATCH 1902/2849] soc: nordic: nrf53: Remove broken PM_S2RAM support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove dead code that cannot be enabled. Kconfig prevents us from enabling PM_S2RAM on 53 because it is not supported any more. But we still have some dead code left over in soc.c, so we delete this code. Signed-off-by: Sebastian Bøe --- soc/nordic/nrf53/soc.c | 35 ----------------------------------- 1 file changed, 35 deletions(-) diff --git a/soc/nordic/nrf53/soc.c b/soc/nordic/nrf53/soc.c index 3542ef3e9149e..4cbd1d2a9fdb2 100644 --- a/soc/nordic/nrf53/soc.c +++ b/soc/nordic/nrf53/soc.c @@ -31,9 +31,6 @@ #elif defined(CONFIG_SOC_NRF5340_CPUNET) #include #endif -#if defined(CONFIG_PM_S2RAM) -#include -#endif #include #include #include @@ -61,34 +58,6 @@ #define LOG_LEVEL CONFIG_SOC_LOG_LEVEL LOG_MODULE_REGISTER(soc); -#if defined(CONFIG_PM_S2RAM) - -#if defined(CONFIG_SOC_NRF5340_CPUAPP) -#define RAM_N_BLOCK (8) -#elif defined(CONFIG_SOC_NRF5340_CPUNET) -#define RAM_N_BLOCK (4) -#endif /* CONFIG_SOC_NRF5340_CPUAPP || CONFIG_SOC_NRF5340_CPUNET */ - -#define MASK_ALL_SECT (VMC_RAM_POWER_S0RETENTION_Msk | VMC_RAM_POWER_S1RETENTION_Msk | \ - VMC_RAM_POWER_S2RETENTION_Msk | VMC_RAM_POWER_S3RETENTION_Msk | \ - VMC_RAM_POWER_S4RETENTION_Msk | VMC_RAM_POWER_S5RETENTION_Msk | \ - VMC_RAM_POWER_S6RETENTION_Msk | VMC_RAM_POWER_S7RETENTION_Msk | \ - VMC_RAM_POWER_S8RETENTION_Msk | VMC_RAM_POWER_S9RETENTION_Msk | \ - VMC_RAM_POWER_S10RETENTION_Msk | VMC_RAM_POWER_S11RETENTION_Msk | \ - VMC_RAM_POWER_S12RETENTION_Msk | VMC_RAM_POWER_S13RETENTION_Msk | \ - VMC_RAM_POWER_S14RETENTION_Msk | VMC_RAM_POWER_S15RETENTION_Msk) - -static void enable_ram_retention(void) -{ - /* - * Enable RAM retention for *ALL* the SRAM - */ - for (size_t n = 0; n < RAM_N_BLOCK; n++) { - nrf_vmc_ram_block_retention_set(NRF_VMC, n, MASK_ALL_SECT); - } - -} -#endif /* CONFIG_PM_S2RAM */ #if defined(CONFIG_SOC_NRF53_ANOMALY_160_WORKAROUND) /* This code prevents the CPU from entering sleep again if it already @@ -574,10 +543,6 @@ static int nordicsemi_nrf53_init(void) #endif -#if defined(CONFIG_PM_S2RAM) - enable_ram_retention(); -#endif /* CONFIG_PM_S2RAM */ - return 0; } From 742c728c7eaba11b34fb8bc40903ea70948b798e Mon Sep 17 00:00:00 2001 From: Grzegorz Swiderski Date: Wed, 17 Apr 2024 13:51:37 +0200 Subject: [PATCH 1903/2849] dts: nordic: Add RESETINFO Add devicetree nodes for the Reset Information registers on nRF54H20, along with a new binding. Signed-off-by: Grzegorz Swiderski --- dts/bindings/arm/nordic,nrf-resetinfo.yaml | 12 ++++++++++++ dts/common/nordic/nrf54h20.dtsi | 10 ++++++++++ soc/nordic/validate_base_addresses.c | 2 ++ 3 files changed, 24 insertions(+) create mode 100644 dts/bindings/arm/nordic,nrf-resetinfo.yaml diff --git a/dts/bindings/arm/nordic,nrf-resetinfo.yaml b/dts/bindings/arm/nordic,nrf-resetinfo.yaml new file mode 100644 index 0000000000000..c8585e5897e50 --- /dev/null +++ b/dts/bindings/arm/nordic,nrf-resetinfo.yaml @@ -0,0 +1,12 @@ +# Copyright (c) 2024 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +description: Nordic RESETINFO (Reset Information) + +compatible: "nordic,nrf-resetinfo" + +include: base.yaml + +properties: + reg: + required: true diff --git a/dts/common/nordic/nrf54h20.dtsi b/dts/common/nordic/nrf54h20.dtsi index 231fbb3067edb..7d2a63883c995 100644 --- a/dts/common/nordic/nrf54h20.dtsi +++ b/dts/common/nordic/nrf54h20.dtsi @@ -189,6 +189,11 @@ interrupts = <21 NRF_DEFAULT_IRQ_PRIORITY>; }; + cpuapp_resetinfo: resetinfo@1e000 { + compatible = "nordic,nrf-resetinfo"; + reg = <0x1e000 0x1000>; + }; + cpuapp_ieee802154: ieee802154 { compatible = "nordic,nrf-ieee802154"; status = "disabled"; @@ -227,6 +232,11 @@ interrupts = <20 NRF_DEFAULT_IRQ_PRIORITY>; }; + cpurad_resetinfo: resetinfo@1e000 { + compatible = "nordic,nrf-resetinfo"; + reg = <0x1e000 0x1000>; + }; + dppic020: dppic@22000 { compatible = "nordic,nrf-dppic-local"; reg = <0x22000 0x1000>; diff --git a/soc/nordic/validate_base_addresses.c b/soc/nordic/validate_base_addresses.c index 4fca3501e27a4..abcc214c54a44 100644 --- a/soc/nordic/validate_base_addresses.c +++ b/soc/nordic/validate_base_addresses.c @@ -245,6 +245,8 @@ CHECK_DT_REG(qdec131, NRF_QDEC131); CHECK_DT_REG(radio, NRF_RADIO); CHECK_DT_REG(regulators, NRF_REGULATORS); CHECK_DT_REG(reset, NRF_RESET); +CHECK_DT_REG(cpuapp_resetinfo, NRF_APPLICATION_RESETINFO); +CHECK_DT_REG(cpurad_resetinfo, NRF_RADIOCORE_RESETINFO); CHECK_DT_REG(rng, NRF_RNG); CHECK_DT_REG(rtc, NRF_RTC); CHECK_DT_REG(rtc0, NRF_RTC0); From 1f05b22acb599247630f18ee54a613529613df3c Mon Sep 17 00:00:00 2001 From: Grzegorz Swiderski Date: Wed, 17 Apr 2024 13:51:37 +0200 Subject: [PATCH 1904/2849] boards: nordic: nrf54h20dk: Add aliases for RESETINFO Each local RESETINFO instance can be used in samples. Signed-off-by: Grzegorz Swiderski --- 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 2b071c8703887..241539554e868 100644 --- a/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpuapp.dts +++ b/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpuapp.dts @@ -35,6 +35,7 @@ led1 = &led1; led2 = &led2; led3 = &led3; + resetinfo = &cpuapp_resetinfo; sw0 = &button0; sw1 = &button1; sw2 = &button2; diff --git a/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpurad.dts b/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpurad.dts index f8aff548436c8..8bba620c45639 100644 --- a/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpurad.dts +++ b/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpurad.dts @@ -31,6 +31,7 @@ }; aliases { ipc-to-cpusys = &cpurad_cpusys_ipc; + resetinfo = &cpurad_resetinfo; }; }; From 92c459a9bc9bcb616e6182b22f0639912167a602 Mon Sep 17 00:00:00 2001 From: Fabio Baltieri Date: Thu, 6 Jun 2024 11:17:17 +0100 Subject: [PATCH 1905/2849] tests: subsys: sensing: set CONFIG_EMUL=y The test is broken in CI because the emulated spi bus is not built in, adding an explicit CONFIG_EMUL=y to the test config. Signed-off-by: Fabio Baltieri --- tests/subsys/sensing/prj.conf | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/subsys/sensing/prj.conf b/tests/subsys/sensing/prj.conf index bf12dc1f6cea0..5658149374564 100644 --- a/tests/subsys/sensing/prj.conf +++ b/tests/subsys/sensing/prj.conf @@ -1,3 +1,4 @@ CONFIG_TEST=y CONFIG_ZTEST=y CONFIG_LOG=y +CONFIG_EMUL=y From 19bf8c363122957b6125ff9e4eed1a492a470ad0 Mon Sep 17 00:00:00 2001 From: Fabio Baltieri Date: Thu, 6 Jun 2024 11:20:59 +0100 Subject: [PATCH 1906/2849] MAINTAINERS: add the test path to the sensing area Make sure sensing test changes are assigned. Signed-off-by: Fabio Baltieri --- MAINTAINERS.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/MAINTAINERS.yml b/MAINTAINERS.yml index 4f2c3a7f9fd9c..0add03fb474d8 100644 --- a/MAINTAINERS.yml +++ b/MAINTAINERS.yml @@ -2981,6 +2981,7 @@ Sensor Subsystem: - doc/services/sensing/ - subsys/sensing/ - samples/subsys/sensing/ + - tests/subsys/sensing/ labels: - "area: Sensor Subsystem" tests: From 94b97909416d80613324985e06c830d830c96b04 Mon Sep 17 00:00:00 2001 From: Anas Nashif Date: Wed, 5 Jun 2024 15:39:42 -0400 Subject: [PATCH 1907/2849] ci: test_plan: fix handling of v2 boards Handling of board changes was broken and did not support v2 boards, fix this to optimize CI execution on localized changes of board files. Signed-off-by: Anas Nashif --- scripts/ci/test_plan.py | 60 ++++++++++++++++++++--------------- scripts/ci/twister_ignore.txt | 2 ++ 2 files changed, 37 insertions(+), 25 deletions(-) diff --git a/scripts/ci/test_plan.py b/scripts/ci/test_plan.py index edbbbf2d923be..54ead52819594 100755 --- a/scripts/ci/test_plan.py +++ b/scripts/ci/test_plan.py @@ -17,6 +17,11 @@ from git import Repo from west.manifest import Manifest +try: + from yaml import CSafeLoader as SafeLoader +except ImportError: + from yaml import SafeLoader + if "ZEPHYR_BASE" not in os.environ: exit("$ZEPHYR_BASE environment variable undefined.") @@ -26,13 +31,13 @@ repository_path = zephyr_base repo_to_scan = Repo(zephyr_base) args = None - - logging.basicConfig(format='%(levelname)s: %(message)s', level=logging.INFO) +logging.getLogger("pykwalify.core").setLevel(50) sys.path.append(os.path.join(zephyr_base, 'scripts')) import list_boards + def _get_match_fn(globs, regexes): # Constructs a single regex that tests for matches against the globs in # 'globs' and the regexes in 'regexes'. Parts are joined with '|' (OR). @@ -214,45 +219,50 @@ def find_archs(self): self.get_plan(_options, True) def find_boards(self): - boards = set() - all_boards = set() - resolved = [] + changed_boards = set() + matched_boards = {} + resolved_files = [] - for f in self.modified_files: - if f.endswith(".rst") or f.endswith(".png") or f.endswith(".jpg"): + for file in self.modified_files: + if file.endswith(".rst") or file.endswith(".png") or file.endswith(".jpg"): continue - p = re.match(r"^boards\/[^/]+\/([^/]+)\/", f) - if p and p.groups(): - boards.add(p.group(1)) - resolved.append(f) + if file.startswith("boards/"): + changed_boards.add(file) + resolved_files.append(file) roots = [zephyr_base] if repository_path != zephyr_base: roots.append(repository_path) # Look for boards in monitored repositories - lb_args = argparse.Namespace(**{'arch_roots': roots, 'board_roots': roots, 'board': None, + lb_args = argparse.Namespace(**{'arch_roots': roots, 'board_roots': roots, 'board': None, 'soc_roots':roots, 'board_dir': None}) - known_boards = list_boards.find_boards(lb_args) - for b in boards: - name_re = re.compile(b) - for kb in known_boards: - if name_re.search(kb.name): - all_boards.add(kb.name) - - # If modified file is catched by "find_boards" workflow (change in "boards" dir AND board recognized) + known_boards = list_boards.find_v2_boards(lb_args) + + for changed in changed_boards: + for board in known_boards: + c = (zephyr_base / changed).resolve() + if c.is_relative_to(board.dir.resolve()): + for file in glob.glob(os.path.join(board.dir, f"{board.name}*.yaml")): + with open(file, 'r') as f: + b = yaml.load(f.read(), Loader=SafeLoader) + matched_boards[b['identifier']] = board + + + logging.info(f"found boards: {','.join(matched_boards.keys())}") + # If modified file is caught by "find_boards" workflow (change in "boards" dir AND board recognized) # it means a proper testing scope for this file was found and this file can be removed # from further consideration - for board in all_boards: - self.resolved_files.extend(list(filter(lambda f: board in f, resolved))) + for _, board in matched_boards.items(): + self.resolved_files.extend(list(filter(lambda f: str(board.dir.relative_to(zephyr_base)) in f, resolved_files))) _options = [] - if len(all_boards) > 20: - logging.warning(f"{len(boards)} boards changed, this looks like a global change, skipping test handling, revert to default.") + if len(matched_boards) > 20: + logging.warning(f"{len(matched_boards)} boards changed, this looks like a global change, skipping test handling, revert to default.") self.full_twister = True return - for board in all_boards: + for board in matched_boards: _options.extend(["-p", board ]) if _options: diff --git a/scripts/ci/twister_ignore.txt b/scripts/ci/twister_ignore.txt index 8db6878be3ae8..329a26d4d1e07 100644 --- a/scripts/ci/twister_ignore.txt +++ b/scripts/ci/twister_ignore.txt @@ -31,6 +31,8 @@ doc/* # GH action have no impact on code .github/* *.rst +*.jpg +*.png *.md # if we change this file or associated script, it should not trigger a full # twister. From 331b404185280669d888b9d11763f99e73d6cb6b Mon Sep 17 00:00:00 2001 From: Henrik Brix Andersen Date: Tue, 4 Jun 2024 08:21:16 +0000 Subject: [PATCH 1908/2849] twister: hardwaremap: avoid exceptions when generating hardware map Avoid exceptions when generating persistent hardware maps on Linux with no devices available. Signed-off-by: Henrik Brix Andersen --- scripts/pylib/twister/twisterlib/hardwaremap.py | 7 +++++-- scripts/tests/twister/test_hardwaremap.py | 7 ++++++- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/scripts/pylib/twister/twisterlib/hardwaremap.py b/scripts/pylib/twister/twisterlib/hardwaremap.py index e60ba35dd5622..c07e777ca7545 100644 --- a/scripts/pylib/twister/twisterlib/hardwaremap.py +++ b/scripts/pylib/twister/twisterlib/hardwaremap.py @@ -288,8 +288,11 @@ def scan(self, persistent=False): def readlink(link): return str((by_id / link).resolve()) - persistent_map = {readlink(link): str(link) - for link in by_id.iterdir()} + if by_id.exists(): + persistent_map = {readlink(link): str(link) + for link in by_id.iterdir()} + else: + persistent_map = {} else: persistent_map = {} diff --git a/scripts/tests/twister/test_hardwaremap.py b/scripts/tests/twister/test_hardwaremap.py index 57c028bfea69a..65440362f6971 100644 --- a/scripts/tests/twister/test_hardwaremap.py +++ b/scripts/tests/twister/test_hardwaremap.py @@ -383,6 +383,9 @@ def mock_iterdir(path): Path(path / 'basic-file2-link') ] + def mock_exists(path): + return True + mocked_hm.manufacturer = ['dummy manufacturer', 'Texas Instruments'] mocked_hm.runner_mapping = { 'dummy runner': ['product[0-9]+',], @@ -433,7 +436,9 @@ def mock_iterdir(path): mock.patch('twisterlib.hardwaremap.Path.resolve', autospec=True, side_effect=mock_resolve), \ mock.patch('twisterlib.hardwaremap.Path.iterdir', - autospec=True, side_effect=mock_iterdir): + autospec=True, side_effect=mock_iterdir), \ + mock.patch('twisterlib.hardwaremap.Path.exists', + autospec=True, side_effect=mock_exists): mocked_hm.scan(persistent) assert sorted([d.__repr__() for d in mocked_hm.detected]) == \ From a42ada8426a5f49b11c0c997d039b4d2f68b426b Mon Sep 17 00:00:00 2001 From: Declan Snyder Date: Tue, 4 Jun 2024 13:27:22 -0500 Subject: [PATCH 1909/2849] drivers: nxp_enet: Disable hw accel with IPV6 As far as I can tell it appears that the hardware does not support acceleration of ICMPV6 checksums. For now, the easiest way to fix the runtime failure of IPV6 is just to disable the hardware acceleration if IPV6 is expected to be used. Signed-off-by: Declan Snyder --- drivers/ethernet/nxp_enet/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/ethernet/nxp_enet/Kconfig b/drivers/ethernet/nxp_enet/Kconfig index d2eb4d071358c..1deb614f70c4e 100644 --- a/drivers/ethernet/nxp_enet/Kconfig +++ b/drivers/ethernet/nxp_enet/Kconfig @@ -48,6 +48,7 @@ config ETH_NXP_ENET_USE_DTCM_FOR_DMA_BUFFER config ETH_NXP_ENET_HW_ACCELERATION bool "Hardware acceleration" default y + depends on !NET_IPV6 help Enable hardware acceleration for the following: - IPv4, UDP and TCP checksum (both Rx and Tx) From 5df6aa8efa137e38e77b80757bbaad78df5f5d2a Mon Sep 17 00:00:00 2001 From: Andrej Butok Date: Tue, 4 Jun 2024 13:22:27 +0200 Subject: [PATCH 1910/2849] boards: nxp: mimxrt11xx: fix non-optimal sector distribution - Optimize slot sizes for MCUBoot swap move algorithm for mimxrt1160/70 boards. - Use DT_SIZE_K/M macros for slot sizes. - Limit mcuboot max size to 128KB. Signed-off-by: Andrej Butok --- boards/nxp/mimxrt1160_evk/mimxrt1160_evk.dtsi | 17 ++++++------ boards/nxp/mimxrt1170_evk/mimxrt1170_evk.dtsi | 16 ++++++------ .../mimxrt1170_evk_mimxrt1176_cm4_B.overlay | 21 ++++++--------- .../mimxrt1170_evk_mimxrt1176_cm7_B.overlay | 26 ++++++++----------- boards/nxp/vmu_rt1170/vmu_rt1170.dtsi | 16 +++++++----- 5 files changed, 44 insertions(+), 52 deletions(-) diff --git a/boards/nxp/mimxrt1160_evk/mimxrt1160_evk.dtsi b/boards/nxp/mimxrt1160_evk/mimxrt1160_evk.dtsi index 54a8cfceecc82..6600e40bc6a35 100644 --- a/boards/nxp/mimxrt1160_evk/mimxrt1160_evk.dtsi +++ b/boards/nxp/mimxrt1160_evk/mimxrt1160_evk.dtsi @@ -92,7 +92,7 @@ reg = <0x400cc000 0x4000>, <0x30000000 DT_SIZE_M(16)>; is25wp128: is25wp128@0 { compatible = "nxp,imx-flexspi-nor"; - size = <134217728>; + size = ; reg = <0>; spi-max-frequency = <133000000>; status = "okay"; @@ -104,25 +104,24 @@ compatible = "fixed-partitions"; #address-cells = <1>; #size-cells = <1>; - boot_partition: partition@0 { label = "mcuboot"; reg = <0x00000000 DT_SIZE_K(128)>; }; - /* Note slot 0 has one additional sector, - * this is intended for use with the swap move algorithm + /* The MCUBoot swap-move algorithm uses the last 3 sectors + * of the primary slot0 for swap status and move. */ slot0_partition: partition@20000 { label = "image-0"; - reg = <0x00020000 0x301000>; + reg = <0x00020000 (DT_SIZE_M(7) + DT_SIZE_K(12))>; }; - slot1_partition: partition@321000 { + slot1_partition: partition@723000 { label = "image-1"; - reg = <0x00321000 0x300000>; + reg = <0x00723000 DT_SIZE_M(7)>; }; - storage_partition: partition@621000 { + storage_partition: partition@E23000 { label = "storage"; - reg = <0x00621000 DT_SIZE_K(1984)>; + reg = <0x00E23000 (DT_SIZE_M(2) - DT_SIZE_K(140))>; }; }; }; diff --git a/boards/nxp/mimxrt1170_evk/mimxrt1170_evk.dtsi b/boards/nxp/mimxrt1170_evk/mimxrt1170_evk.dtsi index 685179d800307..48a39410964a1 100644 --- a/boards/nxp/mimxrt1170_evk/mimxrt1170_evk.dtsi +++ b/boards/nxp/mimxrt1170_evk/mimxrt1170_evk.dtsi @@ -191,7 +191,7 @@ reg = <0x400cc000 0x4000>, <0x30000000 DT_SIZE_M(16)>; is25wp128: is25wp128@0 { compatible = "nxp,imx-flexspi-nor"; - size = <134217728>; + size = ; reg = <0>; spi-max-frequency = <133000000>; status = "okay"; @@ -208,20 +208,20 @@ label = "mcuboot"; reg = <0x00000000 DT_SIZE_K(128)>; }; - /* Note slot 0 has one additional sector, - * this is intended for use with the swap move algorithm + /* The MCUBoot swap-move algorithm uses the last 3 sectors + * of the primary slot0 for swap status and move. */ slot0_partition: partition@20000 { label = "image-0"; - reg = <0x00020000 0x301000>; + reg = <0x00020000 (DT_SIZE_M(7) + DT_SIZE_K(12))>; }; - slot1_partition: partition@321000 { + slot1_partition: partition@723000 { label = "image-1"; - reg = <0x00321000 0x300000>; + reg = <0x00723000 DT_SIZE_M(7)>; }; - storage_partition: partition@621000 { + storage_partition: partition@E23000 { label = "storage"; - reg = <0x00621000 DT_SIZE_K(1984)>; + reg = <0x00E23000 (DT_SIZE_M(2) - DT_SIZE_K(140))>; }; }; }; diff --git a/boards/nxp/mimxrt1170_evk/mimxrt1170_evk_mimxrt1176_cm4_B.overlay b/boards/nxp/mimxrt1170_evk/mimxrt1170_evk_mimxrt1176_cm4_B.overlay index c92d197f548de..b65621ee63261 100644 --- a/boards/nxp/mimxrt1170_evk/mimxrt1170_evk_mimxrt1176_cm4_B.overlay +++ b/boards/nxp/mimxrt1170_evk/mimxrt1170_evk_mimxrt1176_cm4_B.overlay @@ -22,9 +22,8 @@ status = "okay"; reg = <0x400cc000 0x4000>, <0x30000000 DT_SIZE_M(64)>; w25q512nw:w25q512nw@0 { - /* IS25WP128 flash chip not currently enabled */ compatible = "nxp,imx-flexspi-nor"; - size = ; + size = ; reg = <0>; spi-max-frequency = <133000000>; status = "okay"; @@ -32,10 +31,6 @@ erase-block-size = <4096>; write-block-size = <1>; - /* - * Partitions are present to support dual core operation. - * as flash write is not supported, MCUBoot is not enabled. - */ partitions { compatible = "fixed-partitions"; #address-cells = <1>; @@ -45,20 +40,20 @@ label = "mcuboot"; reg = <0x00000000 DT_SIZE_K(128)>; }; - /* Note slot 0 has one additional sector, - * this is intended for use with the swap move algorithm + /* The MCUBoot swap-move algorithm uses the last 3 sectors + * of the primary slot0 for swap status and move. */ slot0_partition: partition@20000 { label = "image-0"; - reg = <0x00020000 0x301000>; + reg = <0x00020000 (DT_SIZE_M(7) + DT_SIZE_K(12))>; }; - slot1_partition: partition@321000 { + slot1_partition: partition@723000 { label = "image-1"; - reg = <0x00321000 0x300000>; + reg = <0x00723000 DT_SIZE_M(7)>; }; - storage_partition: partition@621000 { + storage_partition: partition@E23000 { label = "storage"; - reg = <0x00621000 DT_SIZE_K(1984)>; + reg = <0x00E23000 (DT_SIZE_M(50) - DT_SIZE_K(140))>; }; }; }; diff --git a/boards/nxp/mimxrt1170_evk/mimxrt1170_evk_mimxrt1176_cm7_B.overlay b/boards/nxp/mimxrt1170_evk/mimxrt1170_evk_mimxrt1176_cm7_B.overlay index a43339de27b61..f88f99fba5ce0 100644 --- a/boards/nxp/mimxrt1170_evk/mimxrt1170_evk_mimxrt1176_cm7_B.overlay +++ b/boards/nxp/mimxrt1170_evk/mimxrt1170_evk_mimxrt1176_cm7_B.overlay @@ -7,8 +7,9 @@ / { chosen { zephyr,flash = &w25q512nw; - /delete-property/ zephyr,flash-controller; - /delete-property/ zephyr,code-partition; + zephyr,flash-controller = &w25q512nw; + zephyr,flash = &w25q512nw; + zephyr,code-partition = &slot0_partition; }; aliases { @@ -23,9 +24,8 @@ status = "okay"; reg = <0x400cc000 0x4000>, <0x30000000 DT_SIZE_M(64)>; w25q512nw:w25q512nw@0 { - /* IS25WP128 flash chip not currently enabled */ compatible = "nxp,imx-flexspi-nor"; - size = ; + size = ; reg = <0>; spi-max-frequency = <133000000>; status = "okay"; @@ -33,10 +33,6 @@ erase-block-size = <4096>; write-block-size = <1>; - /* - * Partitions are present to support dual core operation. - * as flash write is not supported, MCUBoot is not enabled. - */ partitions { compatible = "fixed-partitions"; #address-cells = <1>; @@ -46,20 +42,20 @@ label = "mcuboot"; reg = <0x00000000 DT_SIZE_K(128)>; }; - /* Note slot 0 has one additional sector, - * this is intended for use with the swap move algorithm + /* The MCUBoot swap-move algorithm uses the last 3 sectors + * of the primary slot0 for swap status and move. */ slot0_partition: partition@20000 { label = "image-0"; - reg = <0x00020000 0x301000>; + reg = <0x00020000 (DT_SIZE_M(7) + DT_SIZE_K(12))>; }; - slot1_partition: partition@321000 { + slot1_partition: partition@723000 { label = "image-1"; - reg = <0x00321000 0x300000>; + reg = <0x00723000 DT_SIZE_M(7)>; }; - storage_partition: partition@621000 { + storage_partition: partition@E23000 { label = "storage"; - reg = <0x00621000 DT_SIZE_K(1984)>; + reg = <0x00E23000 (DT_SIZE_M(50) - DT_SIZE_K(140))>; }; }; }; diff --git a/boards/nxp/vmu_rt1170/vmu_rt1170.dtsi b/boards/nxp/vmu_rt1170/vmu_rt1170.dtsi index 432fb4cc6d2c8..9d251e9357717 100644 --- a/boards/nxp/vmu_rt1170/vmu_rt1170.dtsi +++ b/boards/nxp/vmu_rt1170/vmu_rt1170.dtsi @@ -178,7 +178,7 @@ ahb-prefetch; ahb-read-addr-opt; rx-clock-source = <1>; - reg = <0x400cc000 0x4000>, <0x30000000 DT_SIZE_M(16)>; + reg = <0x400cc000 0x4000>, <0x30000000 DT_SIZE_M(64)>; mx25um51345g: mx25um51345g@0 { compatible = "nxp,imx-flexspi-mx25um51345g"; /* MX25UM51245G is 64MB, 512MBit flash part */ @@ -194,22 +194,24 @@ compatible = "fixed-partitions"; #address-cells = <1>; #size-cells = <1>; - boot_partition: partition@0 { label = "mcuboot"; reg = <0x00000000 DT_SIZE_K(128)>; }; + /* The MCUBoot swap-move algorithm uses the last 14 sectors + * of the primary slot0 for swap status and move. + */ slot0_partition: partition@20000 { label = "image-0"; - reg = <0x00020000 DT_SIZE_K(3076)>; + reg = <0x00020000 (DT_SIZE_M(3) + DT_SIZE_K(56))>; }; - slot1_partition: partition@321000 { + slot1_partition: partition@32E000 { label = "image-1"; - reg = <0x00321000 DT_SIZE_K(3072)>; + reg = <0x0032E000 DT_SIZE_M(3)>; }; - storage_partition: partition@621000 { + storage_partition: partition@62E000 { label = "storage"; - reg = <0x00621000 DT_SIZE_M(57)>; + reg = <0x0062E000 (DT_SIZE_M(58) - DT_SIZE_K(184))>; }; }; }; From d8b4ff5531a8fa7e10a818dffe026cd046aa5629 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20Cab=C3=A9?= Date: Tue, 4 Jun 2024 09:45:44 +0200 Subject: [PATCH 1911/2849] samples: drivers: clock_control_litex: clean up DTS snippet in README MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Clean up the DTS snippet in the README file to make it more readable. Signed-off-by: Benjamin Cabé --- samples/drivers/clock_control_litex/README.rst | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/samples/drivers/clock_control_litex/README.rst b/samples/drivers/clock_control_litex/README.rst index c2fa951bd3803..0a7d7878cb2b5 100644 --- a/samples/drivers/clock_control_litex/README.rst +++ b/samples/drivers/clock_control_litex/README.rst @@ -21,16 +21,22 @@ Configuration Basic configuration of the driver, including default settings for clock outputs, is held in Device Tree clock control nodes. .. literalinclude:: ../../../dts/riscv/riscv32-litex-vexriscv.dtsi + :language: dts :start-at: clk0: clock-controller@0 { :end-at: }; + :dedent: .. literalinclude:: ../../../dts/riscv/riscv32-litex-vexriscv.dtsi + :language: dts :start-at: clk1: clock-controller@1 { :end-at: }; + :dedent: .. literalinclude:: ../../../dts/riscv/riscv32-litex-vexriscv.dtsi + :language: dts :start-at: clock0: clock@e0004800 { :end-at: }; + :dedent: This configuration defines 2 clock outputs: ``clk0`` and ``clk1`` with default frequency set to 100MHz, 0 degrees phase offset and 50% duty cycle. Special care should be taken when defining values for FPGA-specific configuration (parameters from ``litex,divclk-divide-min`` to ``litex,vco-margin``). From 96ff0f1e04c157c130e71921897fdc9b6e39d004 Mon Sep 17 00:00:00 2001 From: Zhengwei Wang Date: Wed, 7 Feb 2024 15:02:15 +0800 Subject: [PATCH 1912/2849] drivers: timer: Optimized the ambiq stimer driver The original driver has two defects: 1. When setting the next timeout value the original implementation simply sets a delta value equal to ticks * CYC_PER_TICK. This operation is reckless and may incorrectly "reset" the fractional tick, causing clock skew. 2. The original implementation doesn't handle the counter overflow situation. When the counter overflows from 0xffffffff to 0x0, the uptimer counter becomes incorrect. We have fixed above issue by rewriting most of the functions in this driver and verified it by running all tests under tests/kernel/timer folder. Signed-off-by: Zhengwei Wang --- drivers/timer/ambiq_stimer.c | 115 +++++++++++++++++++++++++++-------- 1 file changed, 88 insertions(+), 27 deletions(-) diff --git a/drivers/timer/ambiq_stimer.c b/drivers/timer/ambiq_stimer.c index e2c9d9976f471..e0cfa948aa13d 100644 --- a/drivers/timer/ambiq_stimer.c +++ b/drivers/timer/ambiq_stimer.c @@ -35,12 +35,41 @@ const int32_t z_sys_timer_irq_for_test = TIMER_IRQ; #endif -/* Value of STIMER counter when the previous kernel tick was announced */ -static atomic_t g_last_count; +/* Elapsed ticks since the previous kernel tick was announced, It will get accumulated every time + * stimer_isr is triggered, or sys_clock_set_timeout/sys_clock_elapsed API is called. + * It will be cleared after sys_clock_announce is called,. + */ +static uint32_t g_tick_elapsed; + +/* Value of STIMER counter when the previous timer API is called, this value is + * aligned to tick boundary. It is updated along with the g_tick_elapsed value. + */ +static uint32_t g_last_time_stamp; /* Spinlock to sync between Compare ISR and update of Compare register */ static struct k_spinlock g_lock; +static void update_tick_counter(void) +{ + /* Read current cycle count. */ + uint32_t now = am_hal_stimer_counter_get(); + + /* If current cycle count is smaller than the last time stamp, a counter overflow happened. + * We need to extend the current counter value to 64 bits and add it with 0xFFFFFFFF + * to get the correct elapsed cycles. + */ + uint64_t now_64 = (g_last_time_stamp <= now) ? (uint64_t)now : (uint64_t)now + COUNTER_MAX; + + /* Get elapsed cycles */ + uint32_t elapsed_cycle = (now_64 - g_last_time_stamp); + + /* Get elapsed ticks. */ + uint32_t dticks = elapsed_cycle / CYC_PER_TICK; + + g_last_time_stamp += dticks * CYC_PER_TICK; + g_tick_elapsed += dticks; +} + static void stimer_isr(const void *arg) { ARG_UNUSED(arg); @@ -52,22 +81,34 @@ static void stimer_isr(const void *arg) k_spinlock_key_t key = k_spin_lock(&g_lock); - uint32_t now = am_hal_stimer_counter_get(); - uint32_t dticks = (uint32_t)((now - g_last_count) / CYC_PER_TICK); - - g_last_count += dticks * CYC_PER_TICK; + /*Calculate the elapsed ticks based on the current cycle count*/ + update_tick_counter(); if (!IS_ENABLED(CONFIG_TICKLESS_KERNEL)) { - uint32_t next = g_last_count + CYC_PER_TICK; - if ((int32_t)(next - now) < MIN_DELAY) { - next += CYC_PER_TICK; - } - am_hal_stimer_compare_delta_set(0, next - g_last_count); + /* Get the counter value to trigger the next tick interrupt. */ + uint64_t next = (uint64_t)g_last_time_stamp + CYC_PER_TICK; + + /* Read current cycle count. */ + uint32_t now = am_hal_stimer_counter_get(); + + /* If current cycle count is smaller than the last time stamp, a counter + * overflow happened. We need to extend the current counter value to 64 bits + * and add 0xFFFFFFFF to get the correct elapsed cycles. + */ + uint64_t now_64 = (g_last_time_stamp <= now) ? (uint64_t)now + : (uint64_t)now + COUNTER_MAX; + + uint32_t delta = (now_64 + MIN_DELAY < next) ? (next - now_64) : MIN_DELAY; + + /* Set delta. */ + am_hal_stimer_compare_delta_set(0, delta); } k_spin_unlock(&g_lock, key); - sys_clock_announce(dticks); + + sys_clock_announce(g_tick_elapsed); + g_tick_elapsed = 0; } } @@ -79,17 +120,40 @@ void sys_clock_set_timeout(int32_t ticks, bool idle) return; } - if (ticks == K_TICKS_FOREVER) { - return; - } - - ticks = MIN(MAX_TICKS, ticks); - /* If tick is 0, set delta cyc to MIN_DELAY to trigger tick isr asap */ - uint32_t cyc = MAX(ticks * CYC_PER_TICK, MIN_DELAY); + /* Adjust the ticks to the range of [1, MAX_TICKS]. */ + ticks = (ticks == K_TICKS_FOREVER) ? MAX_TICKS : ticks; + ticks = CLAMP(ticks, 1, (int32_t)MAX_TICKS); k_spinlock_key_t key = k_spin_lock(&g_lock); - am_hal_stimer_compare_delta_set(0, cyc); + /* Update the internal tick counter*/ + update_tick_counter(); + + /* Get current hardware counter value.*/ + uint32_t now = am_hal_stimer_counter_get(); + + /* last: the last recorded counter value. + * now_64: current counter value. Extended to uint64_t to easy the handing of hardware + * counter overflow. + * next: counter values where to trigger the scheduled timeout. + * last < now_64 < next + */ + uint64_t last = (uint64_t)g_last_time_stamp; + uint64_t now_64 = (g_last_time_stamp <= now) ? (uint64_t)now : (uint64_t)now + COUNTER_MAX; + uint64_t next = now_64 + ticks * CYC_PER_TICK; + + uint32_t gap = next - last; + uint32_t gap_aligned = (gap / CYC_PER_TICK) * CYC_PER_TICK; + uint64_t next_aligned = last + gap_aligned; + + uint32_t delta = next_aligned - now_64; + + if (delta <= MIN_DELAY) { + /*If the delta value is smaller than MIN_DELAY, trigger a interrupt immediately*/ + am_hal_stimer_int_set(AM_HAL_STIMER_INT_COMPAREA); + } else { + am_hal_stimer_compare_delta_set(0, delta); + } k_spin_unlock(&g_lock, key); } @@ -101,10 +165,10 @@ 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; - + update_tick_counter(); k_spin_unlock(&g_lock, key); - return ret; + + return g_tick_elapsed; } uint32_t sys_clock_cycle_get_32(void) @@ -115,7 +179,6 @@ uint32_t sys_clock_cycle_get_32(void) static int stimer_init(void) { uint32_t oldCfg; - k_spinlock_key_t key = k_spin_lock(&g_lock); oldCfg = am_hal_stimer_config(AM_HAL_STIMER_CFG_FREEZE); @@ -126,9 +189,7 @@ static int stimer_init(void) 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); + g_last_time_stamp = am_hal_stimer_counter_get(); NVIC_ClearPendingIRQ(TIMER_IRQ); IRQ_CONNECT(TIMER_IRQ, 0, stimer_isr, 0, 0); From 5ac6335505805acaa34db5de4a7c6fbbb5e57095 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Ju=C5=99ena?= Date: Thu, 30 May 2024 18:36:27 +0200 Subject: [PATCH 1913/2849] drivers: pinctrl: esp32: Use BIT macro when writing pin value MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit GPIO registers w1ts and w1tc expects bitfield of pins to set/clean. Signed-off-by: Tomáš Juřena --- drivers/pinctrl/pinctrl_esp32.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/pinctrl/pinctrl_esp32.c b/drivers/pinctrl/pinctrl_esp32.c index ee3811604511e..71049f5b1cb5d 100644 --- a/drivers/pinctrl/pinctrl_esp32.c +++ b/drivers/pinctrl/pinctrl_esp32.c @@ -242,12 +242,12 @@ static int esp32_pin_configure(const uint32_t pin_mux, const uint32_t pin_cfg) if (ESP32_PORT_IDX(pin_num) == 0) { gpio_dev_t *const gpio_dev = (gpio_dev_t *)DT_REG_ADDR(DT_NODELABEL(gpio0)); - gpio_dev->out_w1ts = pin_num; + gpio_dev->out_w1ts = BIT(pin_num); #if DT_NODE_HAS_STATUS(DT_NODELABEL(gpio1), okay) } else { gpio_dev_t *const gpio_dev = (gpio_dev_t *)DT_REG_ADDR(DT_NODELABEL(gpio1)); - gpio_dev->out1_w1ts.data = pin_num; + gpio_dev->out1_w1ts.data = BIT(pin_num - 32); #endif } } @@ -256,12 +256,12 @@ static int esp32_pin_configure(const uint32_t pin_mux, const uint32_t pin_cfg) if (ESP32_PORT_IDX(pin_num) == 0) { gpio_dev_t *const gpio_dev = (gpio_dev_t *)DT_REG_ADDR(DT_NODELABEL(gpio0)); - gpio_dev->out_w1tc = pin_num; + gpio_dev->out_w1tc = BIT(pin_num); #if DT_NODE_HAS_STATUS(DT_NODELABEL(gpio1), okay) } else { gpio_dev_t *const gpio_dev = (gpio_dev_t *)DT_REG_ADDR(DT_NODELABEL(gpio1)); - gpio_dev->out1_w1tc.data = pin_num; + gpio_dev->out1_w1tc.data = BIT(pin_num - 32); #endif } } From e2afcafca508f507a894df0c305a2bc5cae533f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mo=C5=84?= Date: Wed, 29 May 2024 13:06:09 +0200 Subject: [PATCH 1914/2849] drivers: udc_dwc2: Abort wait when PHY is not clocked MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On nRF54H20DK the USB PHY is powered from VBUS. When the USB cable is not connected, the PHY is not powered and the PHY clock disappears. Because the GOUTNAKEFF and INEPNAKEFF can only ever be set when PHY clock is active, the waits for these bits do timeout if cable is disconnected. Workaround the issue by aborting the wait if vendor quirk indicates that PHY clock has abruptly vanished. Signed-off-by: Tomasz Moń --- drivers/usb/udc/udc_dwc2.c | 18 +++++++++++++----- drivers/usb/udc/udc_dwc2.h | 3 +++ drivers/usb/udc/udc_dwc2_vendor_quirks.h | 6 ++++++ 3 files changed, 22 insertions(+), 5 deletions(-) diff --git a/drivers/usb/udc/udc_dwc2.c b/drivers/usb/udc/udc_dwc2.c index 98ded9e4b5de2..9845efb42889e 100644 --- a/drivers/usb/udc/udc_dwc2.c +++ b/drivers/usb/udc/udc_dwc2.c @@ -1176,7 +1176,8 @@ static int dwc2_unset_dedicated_fifo(const struct device *dev, return 0; } -static void dwc2_wait_for_bit(mem_addr_t addr, uint32_t bit) +static void dwc2_wait_for_bit(const struct device *dev, + mem_addr_t addr, uint32_t bit) { k_timepoint_t timeout = sys_timepoint_calc(K_MSEC(100)); @@ -1187,6 +1188,13 @@ static void dwc2_wait_for_bit(mem_addr_t addr, uint32_t bit) * Busy looping is most likely fine unless profiling shows otherwise. */ while (!(sys_read32(addr) & bit)) { + if (dwc2_quirk_is_phy_clk_off(dev)) { + /* No point in waiting, because the bit can only be set + * when the PHY is actively clocked. + */ + return; + } + if (sys_timepoint_expired(timeout)) { LOG_ERR("Timeout waiting for bit 0x%08X at 0x%08X", bit, (uint32_t)addr); @@ -1241,7 +1249,7 @@ static void udc_dwc2_ep_disable(const struct device *dev, dctl &= ~USB_DWC2_DCTL_SGOUTNAK; } - dwc2_wait_for_bit(gintsts_reg, USB_DWC2_GINTSTS_GOUTNAKEFF); + dwc2_wait_for_bit(dev, gintsts_reg, USB_DWC2_GINTSTS_GOUTNAKEFF); /* The application cannot disable control OUT endpoint 0. */ if (ep_idx != 0) { @@ -1257,7 +1265,7 @@ static void udc_dwc2_ep_disable(const struct device *dev, sys_write32(dxepctl, dxepctl_reg); if (ep_idx != 0) { - dwc2_wait_for_bit(doepint_reg, USB_DWC2_DOEPINT_EPDISBLD); + dwc2_wait_for_bit(dev, doepint_reg, USB_DWC2_DOEPINT_EPDISBLD); } /* Clear Endpoint Disabled interrupt */ @@ -1277,12 +1285,12 @@ static void udc_dwc2_ep_disable(const struct device *dev, } sys_write32(dxepctl, dxepctl_reg); - dwc2_wait_for_bit(diepint_reg, USB_DWC2_DIEPINT_INEPNAKEFF); + dwc2_wait_for_bit(dev, 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); + dwc2_wait_for_bit(dev, diepint_reg, USB_DWC2_DIEPINT_EPDISBLD); /* Clear Endpoint Disabled interrupt */ sys_write32(USB_DWC2_DIEPINT_EPDISBLD, diepint_reg); diff --git a/drivers/usb/udc/udc_dwc2.h b/drivers/usb/udc/udc_dwc2.h index b54cb82fd2a71..07cd71bcb9c85 100644 --- a/drivers/usb/udc/udc_dwc2.h +++ b/drivers/usb/udc/udc_dwc2.h @@ -28,6 +28,8 @@ struct dwc2_vendor_quirks { int (*irq_clear)(const struct device *dev); /* Called on driver pre-init */ int (*caps)(const struct device *dev); + /* Called while waiting for bits that require PHY to be clocked */ + int (*is_phy_clk_off)(const struct device *dev); }; /* Driver configuration per instance */ @@ -69,5 +71,6 @@ DWC2_QUIRK_FUNC_DEFINE(disable) DWC2_QUIRK_FUNC_DEFINE(shutdown) DWC2_QUIRK_FUNC_DEFINE(irq_clear) DWC2_QUIRK_FUNC_DEFINE(caps) +DWC2_QUIRK_FUNC_DEFINE(is_phy_clk_off) #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 2311dd803086a..57ff4c4de0441 100644 --- a/drivers/usb/udc/udc_dwc2_vendor_quirks.h +++ b/drivers/usb/udc/udc_dwc2_vendor_quirks.h @@ -244,6 +244,11 @@ static inline int usbhs_init_caps(const struct device *dev) return 0; } +static inline int usbhs_is_phy_clk_off(const struct device *dev) +{ + return !k_event_test(&usbhs_events, USBHS_VBUS_READY); +} + #define QUIRK_NRF_USBHS_DEFINE(n) \ struct dwc2_vendor_quirks dwc2_vendor_quirks_##n = { \ .init = usbhs_enable_nrfs_service, \ @@ -252,6 +257,7 @@ static inline int usbhs_init_caps(const struct device *dev) .shutdown = usbhs_disable_nrfs_service, \ .irq_clear = usbhs_irq_clear, \ .caps = usbhs_init_caps, \ + .is_phy_clk_off = usbhs_is_phy_clk_off, \ }; DT_INST_FOREACH_STATUS_OKAY(QUIRK_NRF_USBHS_DEFINE) From 3ba44c9bdd25bebea6a748ea62ed7bebe0980079 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fin=20Maa=C3=9F?= Date: Fri, 3 May 2024 15:50:59 +0200 Subject: [PATCH 1915/2849] boards: esp32: don't enable spiram for mcuboot MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit don't enable ESP_SPIRAM for mcuboot. Signed-off-by: Fin Maaß --- boards/espressif/esp32_ethernet_kit/Kconfig.defconfig | 2 +- boards/hardkernel/odroid_go/Kconfig.defconfig | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/boards/espressif/esp32_ethernet_kit/Kconfig.defconfig b/boards/espressif/esp32_ethernet_kit/Kconfig.defconfig index e7f2edb7c059f..c1c49d1e0fdbb 100644 --- a/boards/espressif/esp32_ethernet_kit/Kconfig.defconfig +++ b/boards/espressif/esp32_ethernet_kit/Kconfig.defconfig @@ -6,7 +6,7 @@ if BOARD_ESP32_ETHERNET_KIT_ESP32_PROCPU config ESP_SPIRAM - default y + default y if !MCUBOOT choice SPIRAM_TYPE default SPIRAM_TYPE_ESPPSRAM64 diff --git a/boards/hardkernel/odroid_go/Kconfig.defconfig b/boards/hardkernel/odroid_go/Kconfig.defconfig index 345a0f4f64ee6..8b9cb59d3f354 100644 --- a/boards/hardkernel/odroid_go/Kconfig.defconfig +++ b/boards/hardkernel/odroid_go/Kconfig.defconfig @@ -12,7 +12,7 @@ config SPI default y if DISK_DRIVER_SDMMC config ESP_SPIRAM - default y + default y if !MCUBOOT choice SPIRAM_TYPE default SPIRAM_TYPE_ESPPSRAM64 From 7054d01dc861d2d6d072fe15f233bd0e25183d85 Mon Sep 17 00:00:00 2001 From: Nelson Ferragut Date: Wed, 24 Apr 2024 16:46:37 -0400 Subject: [PATCH 1916/2849] doc: unittest: add instructions Add instructions for implementing unit testing. Signed-off-by: Nelson Ferragut --- doc/develop/test/ztest.rst | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/doc/develop/test/ztest.rst b/doc/develop/test/ztest.rst index 124fd415c2306..da3f9b209b81a 100644 --- a/doc/develop/test/ztest.rst +++ b/doc/develop/test/ztest.rst @@ -351,6 +351,21 @@ efforts into the specific module in question. This will speed up testing since only the module will have to be compiled in, and the tested functions will be called directly. +Examples of unit tests can be found in ``tests/unit/``. In the following +example CMakeLists.txt, note the use of ``COMPONENTS unittest`` in the +``find_package()`` command and the use of ``testbinary`` in the +``target_sources()`` command. + +.. code-block:: cmake + + # SPDX-License-Identifier: Apache-2.0 + + cmake_minimum_required(VERSION 3.20.0) + + project(app) + find_package(Zephyr COMPONENTS unittest REQUIRED HINTS $ENV{ZEPHYR_BASE}) + target_sources(testbinary PRIVATE main.c) + Since you won't be including basic kernel data structures that most code depends on, you have to provide function stubs in the test. Ztest provides some helpers for mocking functions, as demonstrated below. @@ -361,7 +376,7 @@ interaction with an object occurred, and if required, to assert the order of that interaction. Best practices for declaring the test suite -=========================================== +******************************************* *twister* and other validation tools need to obtain the list of subcases that a Zephyr *ztest* test image will expose. From 0d56a3c3f4c333b08b0fecde02a9c032ee6c2d2f Mon Sep 17 00:00:00 2001 From: Nelson Ferragut Date: Wed, 15 May 2024 07:53:14 -0400 Subject: [PATCH 1917/2849] doc: unittest: add instructions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Implemented suggestions from Benjamin Cabé. Signed-off-by: Nelson Ferragut --- doc/develop/test/ztest.rst | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/doc/develop/test/ztest.rst b/doc/develop/test/ztest.rst index da3f9b209b81a..e589bc907f8bf 100644 --- a/doc/develop/test/ztest.rst +++ b/doc/develop/test/ztest.rst @@ -351,15 +351,14 @@ efforts into the specific module in question. This will speed up testing since only the module will have to be compiled in, and the tested functions will be called directly. -Examples of unit tests can be found in ``tests/unit/``. In the following -example CMakeLists.txt, note the use of ``COMPONENTS unittest`` in the -``find_package()`` command and the use of ``testbinary`` in the -``target_sources()`` command. +Examples of unit tests can be found in the :zephyr_file:`tests/unit/` folder. +In order to declare the unit tests present in a source folder, you need to add +the relevant source files to the ``testbinary`` target from the CMake +:zephyr_file:`unittest ` component. See a minimal +example below: .. code-block:: cmake - # SPDX-License-Identifier: Apache-2.0 - cmake_minimum_required(VERSION 3.20.0) project(app) From d7e54517996bbf3d497b4692beb6df2d418768ba Mon Sep 17 00:00:00 2001 From: Lorenz Clijnen Date: Fri, 31 May 2024 17:13:29 +0200 Subject: [PATCH 1918/2849] modules: lvgl: input: Fix invalid encoder readout When the encoder button was pressed, it would send a LV_KEY_LEFT/RIGHT instead of a LV_KEY_ENTER event. This clears the enc_diff field, and set the key field to LV_KEY_ENTER for button events. Fixes #73529 Signed-off-by: Lorenz Clijnen --- modules/lvgl/input/lvgl_encoder_input.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/modules/lvgl/input/lvgl_encoder_input.c b/modules/lvgl/input/lvgl_encoder_input.c index b68ca67b87149..e87352799f29c 100644 --- a/modules/lvgl/input/lvgl_encoder_input.c +++ b/modules/lvgl/input/lvgl_encoder_input.c @@ -28,6 +28,8 @@ static void lvgl_encoder_process_event(const struct device *dev, struct input_ev data->pending_event.enc_diff = evt->value; } else if (evt->code == cfg->button_input_code) { data->pending_event.state = evt->value ? LV_INDEV_STATE_PR : LV_INDEV_STATE_REL; + data->pending_event.enc_diff = 0; + data->pending_event.key = LV_KEY_ENTER; } else { LOG_DBG("Ignored input event: %u", evt->code); return; From 1d88d7d139f4f9939101f243b8f90062ba32d3f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fin=20Maa=C3=9F?= Date: Thu, 23 May 2024 10:34:38 +0200 Subject: [PATCH 1919/2849] soc: riscv: litex: add reboot MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit this makes it possible to reboot a litex SoC. Signed-off-by: Fin Maaß --- .../litex_vexriscv/litex_vexriscv.dts | 4 ++++ dts/bindings/riscv/litex,soc-controller.yaml | 12 +++++++++++ dts/riscv/riscv32-litex-vexriscv.dtsi | 9 +++++++++ soc/litex/litex_vexriscv/CMakeLists.txt | 2 ++ soc/litex/litex_vexriscv/Kconfig.defconfig | 4 ++++ soc/litex/litex_vexriscv/reboot.c | 20 +++++++++++++++++++ 6 files changed, 51 insertions(+) create mode 100644 dts/bindings/riscv/litex,soc-controller.yaml create mode 100644 soc/litex/litex_vexriscv/reboot.c diff --git a/boards/enjoydigital/litex_vexriscv/litex_vexriscv.dts b/boards/enjoydigital/litex_vexriscv/litex_vexriscv.dts index eab0c15266616..98971ae4f1a46 100644 --- a/boards/enjoydigital/litex_vexriscv/litex_vexriscv.dts +++ b/boards/enjoydigital/litex_vexriscv/litex_vexriscv.dts @@ -23,6 +23,10 @@ }; }; +&ctrl0 { + status = "okay"; +}; + &uart0 { status = "okay"; current-speed = <115200>; diff --git a/dts/bindings/riscv/litex,soc-controller.yaml b/dts/bindings/riscv/litex,soc-controller.yaml new file mode 100644 index 0000000000000..3b78aae8df15d --- /dev/null +++ b/dts/bindings/riscv/litex,soc-controller.yaml @@ -0,0 +1,12 @@ +# Copyright 2024 Vogl Electronic GmbH +# SPDX-License-Identifier: Apache-2.0 + +description: LiteX SoC Controller driver + +compatible: "litex,soc-controller" + +include: base.yaml + +properties: + reg: + required: true diff --git a/dts/riscv/riscv32-litex-vexriscv.dtsi b/dts/riscv/riscv32-litex-vexriscv.dtsi index 71b32e95b8886..6ae55a82016b5 100644 --- a/dts/riscv/riscv32-litex-vexriscv.dtsi +++ b/dts/riscv/riscv32-litex-vexriscv.dtsi @@ -34,6 +34,15 @@ #size-cells = <1>; compatible = "litex,vexriscv"; ranges; + ctrl0: soc_controller@e0000000 { + compatible = "litex,soc-controller"; + reg = <0xe0000000 0x4 + 0xe0000004 0x4 + 0xe0000008 0x4>; + reg-names = "reset", + "scratch", + "bus_errors"; + }; intc0: interrupt-controller@bc0 { compatible = "litex,vexriscv-intc0"; #address-cells = <0>; diff --git a/soc/litex/litex_vexriscv/CMakeLists.txt b/soc/litex/litex_vexriscv/CMakeLists.txt index 3272d0359a12c..ad42267143933 100644 --- a/soc/litex/litex_vexriscv/CMakeLists.txt +++ b/soc/litex/litex_vexriscv/CMakeLists.txt @@ -9,6 +9,8 @@ zephyr_sources( ${ZEPHYR_BASE}/soc/common/riscv-privileged/vector.S ) +zephyr_sources_ifdef(CONFIG_REBOOT reboot.c) + zephyr_include_directories(.) set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/riscv/common/linker.ld CACHE INTERNAL "") diff --git a/soc/litex/litex_vexriscv/Kconfig.defconfig b/soc/litex/litex_vexriscv/Kconfig.defconfig index d2bb5c9ae73e3..40241c150fa83 100644 --- a/soc/litex/litex_vexriscv/Kconfig.defconfig +++ b/soc/litex/litex_vexriscv/Kconfig.defconfig @@ -9,4 +9,8 @@ config SYS_CLOCK_HW_CYCLES_PER_SEC config NUM_IRQS default 12 +config REBOOT + depends on DT_HAS_LITEX_SOC_CONTROLLER_ENABLED + default y + endif # SOC_LITEX_VEXRISCV diff --git a/soc/litex/litex_vexriscv/reboot.c b/soc/litex/litex_vexriscv/reboot.c new file mode 100644 index 0000000000000..ac8162ffc6cec --- /dev/null +++ b/soc/litex/litex_vexriscv/reboot.c @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2024 Vogl Electronic GmbH + * + * SPDX-License-Identifier: Apache-2.0 + */ +#define DT_DRV_COMPAT litex_soc_controller + +#include +#include +#include +#include + +#define LITEX_CTRL_RESET DT_INST_REG_ADDR_BY_NAME(0, reset) + +void sys_arch_reboot(int type) +{ + ARG_UNUSED(type); + /* SoC Reset on BIT(0)*/ + litex_write8(BIT(0), LITEX_CTRL_RESET); +} From f9c630f7c4bbcfdb19976ae3cf92b515d9135115 Mon Sep 17 00:00:00 2001 From: Henrik Brix Andersen Date: Wed, 8 May 2024 14:03:48 +0000 Subject: [PATCH 1920/2849] drivers: clock control: mcux: syscon: add FlexCAN clock support Add support for FlexCAN0 and FlexCAN1 clocks present on the MCXN94x. Signed-off-by: Henrik Brix Andersen --- .../clock_control/clock_control_mcux_syscon.c | 22 +++++++++++++++++++ .../dt-bindings/clock/mcux_lpc_syscon_clock.h | 3 +++ 2 files changed, 25 insertions(+) diff --git a/drivers/clock_control/clock_control_mcux_syscon.c b/drivers/clock_control/clock_control_mcux_syscon.c index 93a9f1db4ac71..9818e4872d828 100644 --- a/drivers/clock_control/clock_control_mcux_syscon.c +++ b/drivers/clock_control/clock_control_mcux_syscon.c @@ -71,6 +71,19 @@ static int mcux_lpc_syscon_clock_control_on(const struct device *dev, } #endif +#if defined(CONFIG_CAN_MCUX_FLEXCAN) + switch ((uint32_t)sub_system) { + case MCUX_FLEXCAN0_CLK: + CLOCK_EnableClock(kCLOCK_Flexcan0); + break; + case MCUX_FLEXCAN1_CLK: + CLOCK_EnableClock(kCLOCK_Flexcan1); + break; + default: + break; + } +#endif /* defined(CONFIG_CAN_MCUX_MCAN) */ + return 0; } @@ -312,6 +325,15 @@ static int mcux_lpc_syscon_clock_control_get_subsys_rate( break; #endif #endif /* CONFIG_ADC_MCUX_LPADC */ + +#if defined(CONFIG_CAN_MCUX_FLEXCAN) + case MCUX_FLEXCAN0_CLK: + *rate = CLOCK_GetFlexcanClkFreq(0); + break; + case MCUX_FLEXCAN1_CLK: + *rate = CLOCK_GetFlexcanClkFreq(1); + break; +#endif /* defined(CONFIG_CAN_MCUX_FLEXCAN) */ } return 0; diff --git a/include/zephyr/dt-bindings/clock/mcux_lpc_syscon_clock.h b/include/zephyr/dt-bindings/clock/mcux_lpc_syscon_clock.h index 4d5f20f371e00..3b92b3d578b93 100644 --- a/include/zephyr/dt-bindings/clock/mcux_lpc_syscon_clock.h +++ b/include/zephyr/dt-bindings/clock/mcux_lpc_syscon_clock.h @@ -81,4 +81,7 @@ #define MCUX_LPADC1_CLK MCUX_LPC_CLK_ID(0x0F, 0x00) #define MCUX_LPADC2_CLK MCUX_LPC_CLK_ID(0x0F, 0x01) +#define MCUX_FLEXCAN0_CLK MCUX_LPC_CLK_ID(0x10, 0x00) +#define MCUX_FLEXCAN1_CLK MCUX_LPC_CLK_ID(0x10, 0x01) + #endif /* ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_MCUX_LPC_SYSCON_H_ */ From 12fdac4c915c724a5dabd07fc6b63d31e55ea67a Mon Sep 17 00:00:00 2001 From: Henrik Brix Andersen Date: Wed, 8 May 2024 14:06:38 +0000 Subject: [PATCH 1921/2849] dts: arm: nxp: mcxn94x: add flexcan0 and flexcan1 devicetree nodes Add devicetree nodes for the two FlexCAN instances present on the MCXN94x. Only CAN classic is enabled for now due to issues with FlexCAN FD in relation to the implementation on this SoC. Signed-off-by: Henrik Brix Andersen --- dts/arm/nxp/nxp_mcxn94x_common.dtsi | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/dts/arm/nxp/nxp_mcxn94x_common.dtsi b/dts/arm/nxp/nxp_mcxn94x_common.dtsi index ba6e8c1c5c990..1f3bb811a434c 100644 --- a/dts/arm/nxp/nxp_mcxn94x_common.dtsi +++ b/dts/arm/nxp/nxp_mcxn94x_common.dtsi @@ -874,6 +874,26 @@ status = "disabled"; #io-channel-cells = <2>; }; + + flexcan0: can@d4000 { + compatible = "nxp,flexcan-fd", "nxp,flexcan"; + reg = <0xd4000 0x4000>; + interrupts = <62 0>; + interrupt-names = "common"; + clocks = <&syscon MCUX_FLEXCAN0_CLK>; + clk-source = <0>; + status = "disabled"; + }; + + flexcan1: can@d8000 { + compatible = "nxp,flexcan-fd", "nxp,flexcan"; + reg = <0xd8000 0x4000>; + interrupts = <63 0>; + interrupt-names = "common"; + clocks = <&syscon MCUX_FLEXCAN1_CLK>; + clk-source = <0>; + status = "disabled"; + }; }; &systick { From 0c3114cc0153e6067c6abb6f34bccd2ded109b52 Mon Sep 17 00:00:00 2001 From: Henrik Brix Andersen Date: Wed, 8 May 2024 14:09:22 +0000 Subject: [PATCH 1922/2849] boards: nxp: frdm_mcxn947: enable flexcan0 Enable FlexCAN0 on the NXP FRDM-MCXN947 board. Signed-off-by: Henrik Brix Andersen --- boards/nxp/frdm_mcxn947/board.c | 24 +++++++++++++++++++ boards/nxp/frdm_mcxn947/doc/index.rst | 2 ++ .../frdm_mcxn947/frdm_mcxn947-pinctrl.dtsi | 10 ++++++++ boards/nxp/frdm_mcxn947/frdm_mcxn947.dtsi | 5 ++++ .../frdm_mcxn947_mcxn947_cpu0.dts | 5 ++++ .../frdm_mcxn947_mcxn947_cpu0.yaml | 1 + dts/arm/nxp/nxp_mcxn94x_common.dtsi | 4 ++-- 7 files changed, 49 insertions(+), 2 deletions(-) diff --git a/boards/nxp/frdm_mcxn947/board.c b/boards/nxp/frdm_mcxn947/board.c index 87c4beb200591..15d33e7f87d82 100644 --- a/boards/nxp/frdm_mcxn947/board.c +++ b/boards/nxp/frdm_mcxn947/board.c @@ -106,6 +106,25 @@ static int frdm_mcxn947_init(void) CLOCK_SetupExtClocking(BOARD_XTAL0_CLK_HZ); +#if DT_NODE_HAS_STATUS(DT_NODELABEL(flexcan0), okay) + /* Set up PLL1 for 80 MHz FlexCAN clock */ + const pll_setup_t pll1Setup = { + .pllctrl = SCG_SPLLCTRL_SOURCE(1U) | SCG_SPLLCTRL_SELI(27U) | + SCG_SPLLCTRL_SELP(13U), + .pllndiv = SCG_SPLLNDIV_NDIV(3U), + .pllpdiv = SCG_SPLLPDIV_PDIV(1U), + .pllmdiv = SCG_SPLLMDIV_MDIV(10U), + .pllRate = 80000000U + }; + + /* Configure PLL1 to the desired values */ + CLOCK_SetPLL1Freq(&pll1Setup); + /* PLL1 Monitor is disabled */ + CLOCK_SetPll1MonitorMode(kSCG_Pll1MonitorDisable); + /* Set PLL1 CLK0 divider to value 1 */ + CLOCK_SetClkDiv(kCLOCK_DivPLL1Clk0, 1U); +#endif + #if DT_NODE_HAS_STATUS(DT_NODELABEL(flexcomm1), okay) CLOCK_SetClkDiv(kCLOCK_DivFlexcom1Clk, 1u); CLOCK_AttachClk(kFRO12M_to_FLEXCOMM1); @@ -203,6 +222,11 @@ static int frdm_mcxn947_init(void) CLOCK_AttachClk(kPLL0_to_CTIMER4); #endif +#if DT_NODE_HAS_STATUS(DT_NODELABEL(flexcan0), okay) + CLOCK_SetClkDiv(kCLOCK_DivFlexcan0Clk, 1U); + CLOCK_AttachClk(kPLL1_CLK0_to_FLEXCAN0); +#endif + #if DT_NODE_HAS_STATUS(DT_NODELABEL(usdhc0), okay) CLOCK_SetClkDiv(kCLOCK_DivUSdhcClk, 1u); CLOCK_AttachClk(kFRO_HF_to_USDHC); diff --git a/boards/nxp/frdm_mcxn947/doc/index.rst b/boards/nxp/frdm_mcxn947/doc/index.rst index d85421664a609..5839134c14bc2 100644 --- a/boards/nxp/frdm_mcxn947/doc/index.rst +++ b/boards/nxp/frdm_mcxn947/doc/index.rst @@ -92,6 +92,8 @@ The FRDM-MCXN947 board configuration supports the following hardware features: +-----------+------------+-------------------------------------+ | LPCMP | on-chip | sensor(comparator) | +-----------+------------+-------------------------------------+ +| FLEXCAN | on-chip | CAN | ++-----------+------------+-------------------------------------+ Targets available ================== diff --git a/boards/nxp/frdm_mcxn947/frdm_mcxn947-pinctrl.dtsi b/boards/nxp/frdm_mcxn947/frdm_mcxn947-pinctrl.dtsi index 6cf8e3ad6b036..13e6f47f5e5e8 100644 --- a/boards/nxp/frdm_mcxn947/frdm_mcxn947-pinctrl.dtsi +++ b/boards/nxp/frdm_mcxn947/frdm_mcxn947-pinctrl.dtsi @@ -166,4 +166,14 @@ bias-pull-up; }; }; + + pinmux_flexcan0: pinmux_flexcan0 { + group0 { + 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 5d3942fc4596a..b776f2380d33e 100644 --- a/boards/nxp/frdm_mcxn947/frdm_mcxn947.dtsi +++ b/boards/nxp/frdm_mcxn947/frdm_mcxn947.dtsi @@ -196,3 +196,8 @@ pinctrl-0 = <&pinmux_lpcmp0>; pinctrl-names = "default"; }; + +&flexcan0 { + pinctrl-0 = <&pinmux_flexcan0>; + 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 2f30bffe5c892..ee67cf71792ef 100644 --- a/boards/nxp/frdm_mcxn947/frdm_mcxn947_mcxn947_cpu0.dts +++ b/boards/nxp/frdm_mcxn947/frdm_mcxn947_mcxn947_cpu0.dts @@ -24,6 +24,7 @@ zephyr,code-partition = &slot0_partition; zephyr,console = &flexcomm4_lpuart4; zephyr,shell-uart = &flexcomm4_lpuart4; + zephyr,canbus = &flexcan0; }; aliases{ @@ -142,6 +143,10 @@ status = "okay"; }; +&flexcan0 { + status = "okay"; +}; + &ctimer0 { 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 ef6ea7114dc96..76f937fb1e562 100644 --- a/boards/nxp/frdm_mcxn947/frdm_mcxn947_mcxn947_cpu0.yaml +++ b/boards/nxp/frdm_mcxn947/frdm_mcxn947_mcxn947_cpu0.yaml @@ -15,6 +15,7 @@ toolchain: - gnuarmemb - xtools supported: + - can - dma - gpio - spi diff --git a/dts/arm/nxp/nxp_mcxn94x_common.dtsi b/dts/arm/nxp/nxp_mcxn94x_common.dtsi index 1f3bb811a434c..b2b63408edbad 100644 --- a/dts/arm/nxp/nxp_mcxn94x_common.dtsi +++ b/dts/arm/nxp/nxp_mcxn94x_common.dtsi @@ -876,7 +876,7 @@ }; flexcan0: can@d4000 { - compatible = "nxp,flexcan-fd", "nxp,flexcan"; + compatible = "nxp,flexcan"; reg = <0xd4000 0x4000>; interrupts = <62 0>; interrupt-names = "common"; @@ -886,7 +886,7 @@ }; flexcan1: can@d8000 { - compatible = "nxp,flexcan-fd", "nxp,flexcan"; + compatible = "nxp,flexcan"; reg = <0xd8000 0x4000>; interrupts = <63 0>; interrupt-names = "common"; From 06f02eb3840358d444014a199665d292bd9e3f8c Mon Sep 17 00:00:00 2001 From: Henrik Brix Andersen Date: Wed, 8 May 2024 14:10:32 +0000 Subject: [PATCH 1923/2849] tests: drivers: can: timing: enable full timing test on frdm_mcxn947 Enable the full range of CAN timing tests on the NXP FRDM-MCXN947 board. Signed-off-by: Henrik Brix Andersen --- tests/drivers/can/timing/boards/frdm_mcxn947_mcxn947_cpu0.conf | 1 + 1 file changed, 1 insertion(+) create mode 100644 tests/drivers/can/timing/boards/frdm_mcxn947_mcxn947_cpu0.conf diff --git a/tests/drivers/can/timing/boards/frdm_mcxn947_mcxn947_cpu0.conf b/tests/drivers/can/timing/boards/frdm_mcxn947_mcxn947_cpu0.conf new file mode 100644 index 0000000000000..7b071f3a54f51 --- /dev/null +++ b/tests/drivers/can/timing/boards/frdm_mcxn947_mcxn947_cpu0.conf @@ -0,0 +1 @@ +CONFIG_TEST_ALL_BITRATES=y From 2c08e9698ddccf4caa1201a93c31746abcefb154 Mon Sep 17 00:00:00 2001 From: Bartosz Bilas Date: Tue, 4 Jun 2024 16:46:33 +0200 Subject: [PATCH 1924/2849] drivers: spi: remove deprecated functions `spi_transceive_async`, `spi_read_async` and `spi_write_async` are deprecated since v3.2. Signed-off-by: Bartosz Bilas --- doc/develop/api/terminology.rst | 2 +- doc/releases/release-notes-3.7.rst | 3 ++ include/zephyr/drivers/spi.h | 44 ++---------------------------- 3 files changed, 6 insertions(+), 43 deletions(-) diff --git a/doc/develop/api/terminology.rst b/doc/develop/api/terminology.rst index dacf937727237..593ce5929f45b 100644 --- a/doc/develop/api/terminology.rst +++ b/doc/develop/api/terminology.rst @@ -184,7 +184,7 @@ Explanation Be aware that **async** is orthogonal to context-switching. Some APIs may provide completion information through a callback, but may suspend while waiting for the resource necessary to initiate the operation; an -example is :c:func:`spi_transceive_async`. +example is :c:func:`spi_transceive_signal`. If a function is both **no-wait** and **async** then selecting the no-wait path only guarantees that the function will not sleep. It does diff --git a/doc/releases/release-notes-3.7.rst b/doc/releases/release-notes-3.7.rst index 5bec18d4e20d4..e4a33ceef94d2 100644 --- a/doc/releases/release-notes-3.7.rst +++ b/doc/releases/release-notes-3.7.rst @@ -116,6 +116,9 @@ Deprecated in this release * SPI * Deprecated :c:func:`spi_is_ready` API function has been removed. + * Deprecated :c:func:`spi_transceive_async` API function has been removed. + * Deprecated :c:func:`spi_read_async` API function has been removed. + * Deprecated :c:func:`spi_write_async` API function has been removed. Architectures ************* diff --git a/include/zephyr/drivers/spi.h b/include/zephyr/drivers/spi.h index a24a63a209ad4..6e394ba8b2b40 100644 --- a/include/zephyr/drivers/spi.h +++ b/include/zephyr/drivers/spi.h @@ -615,7 +615,7 @@ typedef void (*spi_callback_t)(const struct device *dev, int result, void *data) /** * @typedef spi_api_io * @brief Callback API for asynchronous I/O - * See spi_transceive_async() for argument descriptions + * See spi_transceive_signal() for argument descriptions */ typedef int (*spi_api_io_async)(const struct device *dev, const struct spi_config *config, @@ -932,20 +932,6 @@ static inline int spi_transceive_signal(const struct device *dev, return api->transceive_async(dev, config, tx_bufs, rx_bufs, cb, sig); } -/** - * @brief Alias for spi_transceive_signal for backwards compatibility - * - * @deprecated Use @ref spi_transceive_signal instead. - */ -__deprecated static inline int spi_transceive_async(const struct device *dev, - const struct spi_config *config, - const struct spi_buf_set *tx_bufs, - const struct spi_buf_set *rx_bufs, - struct k_poll_signal *sig) -{ - return spi_transceive_signal(dev, config, tx_bufs, rx_bufs, sig); -} - /** * @brief Read the specified amount of data from the SPI driver. * @@ -978,25 +964,12 @@ static inline int spi_read_signal(const struct device *dev, return spi_transceive_signal(dev, config, NULL, rx_bufs, sig); } -/** - * @brief Alias for spi_read_signal for backwards compatibility - * - * @deprecated Use @ref spi_read_signal instead. - */ -__deprecated static inline int spi_read_async(const struct device *dev, - const struct spi_config *config, - const struct spi_buf_set *rx_bufs, - struct k_poll_signal *sig) -{ - return spi_read_signal(dev, config, rx_bufs, sig); -} - /** * @brief Write the specified amount of data from the SPI driver. * * @note This function is asynchronous. * - * @note This function is a helper function calling spi_transceive_async. + * @note This function is a helper function calling spi_transceive_signal. * * @note This function is available only if @kconfig{CONFIG_SPI_ASYNC} * and @kconfig{CONFIG_POLL} are selected. @@ -1022,19 +995,6 @@ static inline int spi_write_signal(const struct device *dev, return spi_transceive_signal(dev, config, tx_bufs, NULL, sig); } -/** - * @brief Alias for spi_write_signal for backwards compatibility - * - * @deprecated Use @ref spi_write_signal instead. - */ -__deprecated static inline int spi_write_async(const struct device *dev, - const struct spi_config *config, - const struct spi_buf_set *tx_bufs, - struct k_poll_signal *sig) -{ - return spi_write_signal(dev, config, tx_bufs, sig); -} - #endif /* CONFIG_POLL */ #endif /* CONFIG_SPI_ASYNC */ From d1d45b65b7784d214f17d1e88824b5ef70dffdcf Mon Sep 17 00:00:00 2001 From: Glenn Andrews Date: Tue, 4 Jun 2024 07:38:34 -0700 Subject: [PATCH 1925/2849] maintainers: add glenn-andrews as SMF collaborator Add myself as a collaborator to help with the State Machine Framework PRs Signed-off-by: Glenn Andrews --- MAINTAINERS.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/MAINTAINERS.yml b/MAINTAINERS.yml index 0add03fb474d8..a22323b69fa80 100644 --- a/MAINTAINERS.yml +++ b/MAINTAINERS.yml @@ -3098,11 +3098,13 @@ State machine framework: - sambhurst collaborators: - keith-zephyr + - glenn-andrews files: - doc/services/smf/ - include/zephyr/smf.h - lib/smf/ - tests/lib/smf/ + - samples/subsys/smf/ labels: - "area: State Machine Framework" tests: From 59a2d84f4590bcba3d3d0a684f6bac545fa64534 Mon Sep 17 00:00:00 2001 From: Marcin Niestroj Date: Tue, 7 May 2024 15:15:10 +0200 Subject: [PATCH 1926/2849] drivers: nsos: introduce nsos_poll_if_blocking() helper function Introduce nsos_poll_if_blocking(), which replaces common code in: * nsos_accept_with_poll() * nsos_recvfrom_with_poll() This will allow to introduce similar behavior for other blocking APIs in subsequent commits. Signed-off-by: Marcin Niestroj --- drivers/net/nsos_sockets.c | 169 +++++++++++++++++-------------------- 1 file changed, 78 insertions(+), 91 deletions(-) diff --git a/drivers/net/nsos_sockets.c b/drivers/net/nsos_sockets.c index 1c7df2af830d9..a4ded55942b17 100644 --- a/drivers/net/nsos_sockets.c +++ b/drivers/net/nsos_sockets.c @@ -481,6 +481,65 @@ static int sockaddr_from_nsos_mid(struct sockaddr *addr, socklen_t *addrlen, return -NSOS_MID_EINVAL; } +static int nsos_wait_for_poll(struct nsos_socket *sock, int events, + k_timeout_t timeout) +{ + struct zsock_pollfd pfd = { + .fd = sock->fd, + .events = events, + }; + struct k_poll_event poll_events[1]; + struct k_poll_event *pev = poll_events; + struct k_poll_event *pev_end = poll_events + ARRAY_SIZE(poll_events); + int ret; + + ret = nsos_poll_prepare(sock, &pfd, &pev, pev_end); + if (ret == -EALREADY) { + ret = 0; + goto poll_update; + } else if (ret < 0) { + goto return_ret; + } + + ret = k_poll(poll_events, ARRAY_SIZE(poll_events), timeout); + if (ret != 0 && ret != -EAGAIN && ret != -EINTR) { + goto poll_update; + } + + ret = 0; + +poll_update: + pev = poll_events; + nsos_poll_update(sock, &pfd, &pev); + +return_ret: + if (ret < 0) { + return -errno_to_nsos_mid(-ret); + } + + return 0; +} + +static int nsos_poll_if_blocking(struct nsos_socket *sock, int events, + k_timeout_t timeout, int flags) +{ + int sock_flags; + bool non_blocking; + + if (flags & ZSOCK_MSG_DONTWAIT) { + non_blocking = true; + } else { + sock_flags = nsos_adapt_fcntl_getfl(sock->pollfd.fd); + non_blocking = sock_flags & NSOS_MID_O_NONBLOCK; + } + + if (!non_blocking) { + return nsos_wait_for_poll(sock, events, timeout); + } + + return 0; +} + static int nsos_bind(void *obj, const struct sockaddr *addr, socklen_t addrlen) { struct nsos_socket *sock = obj; @@ -543,59 +602,6 @@ static int nsos_listen(void *obj, int backlog) return ret; } -static int nsos_wait_for_pollin(struct nsos_socket *sock) -{ - struct zsock_pollfd pfd = { - .fd = sock->fd, - .events = ZSOCK_POLLIN, - }; - struct k_poll_event poll_events[1]; - struct k_poll_event *pev = poll_events; - struct k_poll_event *pev_end = poll_events + ARRAY_SIZE(poll_events); - int ret; - - ret = nsos_poll_prepare(sock, &pfd, &pev, pev_end); - if (ret == -EALREADY) { - return 0; - } else if (ret < 0) { - return ret; - } - - ret = k_poll(poll_events, ARRAY_SIZE(poll_events), sock->recv_timeout); - if (ret != 0 && ret != -EAGAIN && ret != -EINTR) { - return ret; - } - - pev = poll_events; - nsos_poll_update(sock, &pfd, &pev); - - return 0; -} - -static int nsos_accept_with_poll(struct nsos_socket *sock, - struct nsos_mid_sockaddr *addr_mid, - size_t *addrlen_mid) -{ - int ret = 0; - int flags; - - flags = nsos_adapt_fcntl_getfl(sock->pollfd.fd); - - if (!(flags & NSOS_MID_O_NONBLOCK)) { - ret = nsos_wait_for_pollin(sock); - if (ret < 0) { - return ret; - } - } - - ret = nsos_adapt_accept(sock->pollfd.fd, addr_mid, addrlen_mid); - if (ret < 0) { - return -errno_from_nsos_mid(-ret); - } - - return ret; -} - static int nsos_accept(void *obj, struct sockaddr *addr, socklen_t *addrlen) { struct nsos_socket *accept_sock = obj; @@ -607,29 +613,33 @@ static int nsos_accept(void *obj, struct sockaddr *addr, socklen_t *addrlen) struct nsos_socket *conn_sock; int ret; - ret = nsos_accept_with_poll(accept_sock, addr_mid, &addrlen_mid); + ret = nsos_poll_if_blocking(accept_sock, ZSOCK_POLLIN, + accept_sock->recv_timeout, 0); if (ret < 0) { - errno = errno_from_nsos_mid(-ret); - return -1; + goto return_ret; + } + + ret = nsos_adapt_accept(accept_sock->pollfd.fd, addr_mid, &addrlen_mid); + if (ret < 0) { + goto return_ret; } adapt_fd = ret; ret = sockaddr_from_nsos_mid(addr, addrlen, addr_mid, addrlen_mid); if (ret < 0) { - errno = errno_from_nsos_mid(-ret); goto close_adapt_fd; } zephyr_fd = z_reserve_fd(); if (zephyr_fd < 0) { - errno = -zephyr_fd; + ret = -errno_to_nsos_mid(-zephyr_fd); goto close_adapt_fd; } conn_sock = k_malloc(sizeof(*conn_sock)); if (!conn_sock) { - errno = ENOMEM; + ret = -NSOS_MID_ENOMEM; goto free_zephyr_fd; } @@ -646,6 +656,8 @@ static int nsos_accept(void *obj, struct sockaddr *addr, socklen_t *addrlen) close_adapt_fd: nsi_host_close(adapt_fd); +return_ret: + errno = errno_from_nsos_mid(-ret); return -1; } @@ -738,36 +750,6 @@ static ssize_t nsos_sendmsg(void *obj, const struct msghdr *msg, int flags) return ret; } -static int nsos_recvfrom_with_poll(struct nsos_socket *sock, void *buf, size_t len, int flags, - struct nsos_mid_sockaddr *addr_mid, size_t *addrlen_mid) -{ - int ret = 0; - int sock_flags; - bool non_blocking; - - if (flags & ZSOCK_MSG_DONTWAIT) { - non_blocking = true; - } else { - sock_flags = nsos_adapt_fcntl_getfl(sock->pollfd.fd); - non_blocking = sock_flags & NSOS_MID_O_NONBLOCK; - } - - if (!non_blocking) { - ret = nsos_wait_for_pollin(sock); - if (ret < 0) { - return ret; - } - } - - ret = nsos_adapt_recvfrom(sock->pollfd.fd, buf, len, flags, - addr_mid, addrlen_mid); - if (ret < 0) { - return -errno_from_nsos_mid(-ret); - } - - return ret; -} - static ssize_t nsos_recvfrom(void *obj, void *buf, size_t len, int flags, struct sockaddr *addr, socklen_t *addrlen) { @@ -785,8 +767,13 @@ static ssize_t nsos_recvfrom(void *obj, void *buf, size_t len, int flags, flags_mid = ret; - ret = nsos_recvfrom_with_poll(sock, buf, len, flags_mid, - addr_mid, &addrlen_mid); + ret = nsos_poll_if_blocking(sock, ZSOCK_POLLIN, sock->recv_timeout, flags); + if (ret < 0) { + goto return_ret; + } + + ret = nsos_adapt_recvfrom(sock->pollfd.fd, buf, len, flags_mid, + addr_mid, &addrlen_mid); if (ret < 0) { goto return_ret; } From f45d3c81cca7feb7fa6dfd3aadb1ddca50f4e5b1 Mon Sep 17 00:00:00 2001 From: Marcin Niestroj Date: Mon, 20 May 2024 13:48:25 +0200 Subject: [PATCH 1927/2849] drivers: nsos: handle multiple blocking APIs on single socket So far only a single blocking API could be handled simultaneously, due to epoll_ctl(..., EPOLL_CTL_ADD, ...) returning -EEXIST when same file descriptor was added twice. Follow 'man epoll' advice about using dup() syscall to create a duplicate file descriptor, which can be used with different events masks. Use such duplicate for each blocking API except ioctl() (for handling Zephyr poll() syscall). Signed-off-by: Marcin Niestroj --- drivers/net/nsos.h | 2 + drivers/net/nsos_adapt.c | 12 ++++ drivers/net/nsos_sockets.c | 133 +++++++++++++++++++++---------------- 3 files changed, 90 insertions(+), 57 deletions(-) diff --git a/drivers/net/nsos.h b/drivers/net/nsos.h index 911e49dff2c3e..f1e2f12eb553f 100644 --- a/drivers/net/nsos.h +++ b/drivers/net/nsos.h @@ -140,6 +140,8 @@ int nsos_adapt_fcntl_setfl(int fd, int flags); int nsos_adapt_fionread(int fd, int *avail); +int nsos_adapt_dup(int oldfd); + 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 af9acd1e40e7e..5514bb4a13446 100644 --- a/drivers/net/nsos_adapt.c +++ b/drivers/net/nsos_adapt.c @@ -1001,6 +1001,18 @@ int nsos_adapt_fionread(int fd, int *avail) return 0; } +int nsos_adapt_dup(int oldfd) +{ + int ret; + + ret = dup(oldfd); + if (ret < 0) { + return -errno_to_nsos_mid(errno); + } + + return ret; +} + 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 a4ded55942b17..910472ee7156f 100644 --- a/drivers/net/nsos_sockets.c +++ b/drivers/net/nsos_sockets.c @@ -37,17 +37,24 @@ BUILD_ASSERT(CONFIG_HEAP_MEM_POOL_SIZE > 0); #define NSOS_IRQ_FLAGS (0) #define NSOS_IRQ_PRIORITY (2) +struct nsos_socket; + +struct nsos_socket_poll { + struct nsos_mid_pollfd mid; + struct k_poll_signal signal; + + sys_dnode_t node; +}; + struct nsos_socket { int fd; - struct nsos_mid_pollfd pollfd; - struct k_poll_signal poll; k_timeout_t recv_timeout; - sys_dnode_t node; + struct nsos_socket_poll poll; }; -static sys_dlist_t nsos_sockets = SYS_DLIST_STATIC_INIT(&nsos_sockets); +static sys_dlist_t nsos_polls = SYS_DLIST_STATIC_INIT(&nsos_polls); static int socket_family_to_nsos_mid(int family, int *family_mid) { @@ -184,9 +191,9 @@ 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) { - errno = errno_from_nsos_mid(-sock->pollfd.fd); + sock->poll.mid.fd = nsos_adapt_socket(family_mid, type_mid, proto_mid); + if (sock->poll.mid.fd < 0) { + errno = errno_from_nsos_mid(-sock->poll.mid.fd); goto free_sock; } @@ -213,7 +220,7 @@ static ssize_t nsos_read(void *obj, void *buf, size_t sz) struct nsos_socket *sock = obj; int ret; - ret = nsi_host_read(sock->pollfd.fd, buf, sz); + ret = nsi_host_read(sock->poll.mid.fd, buf, sz); if (ret < 0) { errno = nsos_adapt_get_zephyr_errno(); } @@ -226,7 +233,7 @@ static ssize_t nsos_write(void *obj, const void *buf, size_t sz) struct nsos_socket *sock = obj; int ret; - ret = nsi_host_write(sock->pollfd.fd, buf, sz); + ret = nsi_host_write(sock->poll.mid.fd, buf, sz); if (ret < 0) { errno = nsos_adapt_get_zephyr_errno(); } @@ -239,7 +246,7 @@ static int nsos_close(void *obj) struct nsos_socket *sock = obj; int ret; - ret = nsi_host_close(sock->pollfd.fd); + ret = nsi_host_close(sock->poll.mid.fd); if (ret < 0) { errno = nsos_adapt_get_zephyr_errno(); } @@ -247,33 +254,34 @@ static int nsos_close(void *obj) return ret; } -static void pollcb(struct nsos_mid_pollfd *pollfd) +static void pollcb(struct nsos_mid_pollfd *mid) { - struct nsos_socket *sock = CONTAINER_OF(pollfd, struct nsos_socket, pollfd); + struct nsos_socket_poll *poll = CONTAINER_OF(mid, struct nsos_socket_poll, mid); - k_poll_signal_raise(&sock->poll, sock->pollfd.revents); + k_poll_signal_raise(&poll->signal, poll->mid.revents); } static int nsos_poll_prepare(struct nsos_socket *sock, struct zsock_pollfd *pfd, - struct k_poll_event **pev, struct k_poll_event *pev_end) + struct k_poll_event **pev, struct k_poll_event *pev_end, + struct nsos_socket_poll *poll) { unsigned int signaled; int flags; - sock->pollfd.events = pfd->events; - sock->pollfd.revents = 0; - sock->pollfd.cb = pollcb; + poll->mid.events = pfd->events; + poll->mid.revents = 0; + poll->mid.cb = pollcb; if (*pev == pev_end) { return -ENOMEM; } - k_poll_signal_init(&sock->poll); - k_poll_event_init(*pev, K_POLL_TYPE_SIGNAL, K_POLL_MODE_NOTIFY_ONLY, &sock->poll); + k_poll_signal_init(&poll->signal); + k_poll_event_init(*pev, K_POLL_TYPE_SIGNAL, K_POLL_MODE_NOTIFY_ONLY, &poll->signal); - sys_dlist_append(&nsos_sockets, &sock->node); + sys_dlist_append(&nsos_polls, &poll->node); - nsos_adapt_poll_add(&sock->pollfd); + nsos_adapt_poll_add(&poll->mid); /* Let other sockets use another k_poll_event */ (*pev)++; @@ -281,7 +289,7 @@ static int nsos_poll_prepare(struct nsos_socket *sock, struct zsock_pollfd *pfd, signaled = 0; flags = 0; - k_poll_signal_check(&sock->poll, &signaled, &flags); + k_poll_signal_check(&poll->signal, &signaled, &flags); if (!signaled) { return 0; } @@ -291,7 +299,7 @@ static int nsos_poll_prepare(struct nsos_socket *sock, struct zsock_pollfd *pfd, } static int nsos_poll_update(struct nsos_socket *sock, struct zsock_pollfd *pfd, - struct k_poll_event **pev) + struct k_poll_event **pev, struct nsos_socket_poll *poll) { unsigned int signaled; int flags; @@ -301,15 +309,15 @@ static int nsos_poll_update(struct nsos_socket *sock, struct zsock_pollfd *pfd, signaled = 0; flags = 0; - if (!sys_dnode_is_linked(&sock->node)) { - nsos_adapt_poll_update(&sock->pollfd); + if (!sys_dnode_is_linked(&poll->node)) { + nsos_adapt_poll_update(&poll->mid); return 0; } - nsos_adapt_poll_remove(&sock->pollfd); - sys_dlist_remove(&sock->node); + nsos_adapt_poll_remove(&poll->mid); + sys_dlist_remove(&poll->node); - k_poll_signal_check(&sock->poll, &signaled, &flags); + k_poll_signal_check(&poll->signal, &signaled, &flags); if (!signaled) { return 0; } @@ -333,7 +341,7 @@ static int nsos_ioctl(void *obj, unsigned int request, va_list args) pev = va_arg(args, struct k_poll_event **); pev_end = va_arg(args, struct k_poll_event *); - return nsos_poll_prepare(obj, pfd, pev, pev_end); + return nsos_poll_prepare(obj, pfd, pev, pev_end, &sock->poll); } case ZFD_IOCTL_POLL_UPDATE: { @@ -343,7 +351,7 @@ static int nsos_ioctl(void *obj, unsigned int request, va_list args) pfd = va_arg(args, struct zsock_pollfd *); pev = va_arg(args, struct k_poll_event **); - return nsos_poll_update(obj, pfd, pev); + return nsos_poll_update(obj, pfd, pev, &sock->poll); } case ZFD_IOCTL_POLL_OFFLOAD: @@ -352,7 +360,7 @@ static int nsos_ioctl(void *obj, unsigned int request, va_list args) case F_GETFL: { int flags; - flags = nsos_adapt_fcntl_getfl(sock->pollfd.fd); + flags = nsos_adapt_fcntl_getfl(sock->poll.mid.fd); return fl_from_nsos_mid(flags); } @@ -366,7 +374,7 @@ static int nsos_ioctl(void *obj, unsigned int request, va_list args) return -errno_from_nsos_mid(-ret); } - ret = nsos_adapt_fcntl_setfl(sock->pollfd.fd, flags); + ret = nsos_adapt_fcntl_setfl(sock->poll.mid.fd, flags); return -errno_from_nsos_mid(-ret); } @@ -375,7 +383,7 @@ static int nsos_ioctl(void *obj, unsigned int request, va_list args) int *avail = va_arg(args, int *); int ret; - ret = nsos_adapt_fionread(sock->pollfd.fd, avail); + ret = nsos_adapt_fionread(sock->poll.mid.fd, avail); return -errno_from_nsos_mid(-ret); } @@ -491,14 +499,22 @@ static int nsos_wait_for_poll(struct nsos_socket *sock, int events, struct k_poll_event poll_events[1]; struct k_poll_event *pev = poll_events; struct k_poll_event *pev_end = poll_events + ARRAY_SIZE(poll_events); + struct nsos_socket_poll socket_poll = {}; int ret; - ret = nsos_poll_prepare(sock, &pfd, &pev, pev_end); + ret = nsos_adapt_dup(sock->poll.mid.fd); + if (ret < 0) { + goto return_ret; + } + + socket_poll.mid.fd = ret; + + ret = nsos_poll_prepare(sock, &pfd, &pev, pev_end, &socket_poll); if (ret == -EALREADY) { ret = 0; goto poll_update; } else if (ret < 0) { - goto return_ret; + goto close_dup; } ret = k_poll(poll_events, ARRAY_SIZE(poll_events), timeout); @@ -510,7 +526,10 @@ static int nsos_wait_for_poll(struct nsos_socket *sock, int events, poll_update: pev = poll_events; - nsos_poll_update(sock, &pfd, &pev); + nsos_poll_update(sock, &pfd, &pev, &socket_poll); + +close_dup: + nsi_host_close(socket_poll.mid.fd); return_ret: if (ret < 0) { @@ -529,7 +548,7 @@ static int nsos_poll_if_blocking(struct nsos_socket *sock, int events, if (flags & ZSOCK_MSG_DONTWAIT) { non_blocking = true; } else { - sock_flags = nsos_adapt_fcntl_getfl(sock->pollfd.fd); + sock_flags = nsos_adapt_fcntl_getfl(sock->poll.mid.fd); non_blocking = sock_flags & NSOS_MID_O_NONBLOCK; } @@ -553,7 +572,7 @@ static int nsos_bind(void *obj, const struct sockaddr *addr, socklen_t addrlen) goto return_ret; } - ret = nsos_adapt_bind(sock->pollfd.fd, addr_mid, addrlen_mid); + ret = nsos_adapt_bind(sock->poll.mid.fd, addr_mid, addrlen_mid); return_ret: if (ret < 0) { @@ -577,7 +596,7 @@ static int nsos_connect(void *obj, const struct sockaddr *addr, socklen_t addrle goto return_ret; } - ret = nsos_adapt_connect(sock->pollfd.fd, addr_mid, addrlen_mid); + ret = nsos_adapt_connect(sock->poll.mid.fd, addr_mid, addrlen_mid); return_ret: if (ret < 0) { @@ -593,7 +612,7 @@ static int nsos_listen(void *obj, int backlog) struct nsos_socket *sock = obj; int ret; - ret = nsos_adapt_listen(sock->pollfd.fd, backlog); + ret = nsos_adapt_listen(sock->poll.mid.fd, backlog); if (ret < 0) { errno = errno_from_nsos_mid(-ret); return -1; @@ -619,7 +638,7 @@ static int nsos_accept(void *obj, struct sockaddr *addr, socklen_t *addrlen) goto return_ret; } - ret = nsos_adapt_accept(accept_sock->pollfd.fd, addr_mid, &addrlen_mid); + ret = nsos_adapt_accept(accept_sock->poll.mid.fd, addr_mid, &addrlen_mid); if (ret < 0) { goto return_ret; } @@ -644,7 +663,7 @@ static int nsos_accept(void *obj, struct sockaddr *addr, socklen_t *addrlen) } conn_sock->fd = zephyr_fd; - conn_sock->pollfd.fd = adapt_fd; + conn_sock->poll.mid.fd = adapt_fd; z_finalize_fd(zephyr_fd, conn_sock, &nsos_socket_fd_op_vtable.fd_vtable); @@ -683,7 +702,7 @@ static ssize_t nsos_sendto(void *obj, const void *buf, size_t len, int flags, goto return_ret; } - ret = nsos_adapt_sendto(sock->pollfd.fd, buf, len, flags_mid, + ret = nsos_adapt_sendto(sock->poll.mid.fd, buf, len, flags_mid, addr_mid, addrlen_mid); return_ret: @@ -737,7 +756,7 @@ static ssize_t nsos_sendmsg(void *obj, const struct msghdr *msg, int flags) msg_mid.msg_controllen = 0; msg_mid.msg_flags = 0; - ret = nsos_adapt_sendmsg(sock->pollfd.fd, &msg_mid, flags_mid); + ret = nsos_adapt_sendmsg(sock->poll.mid.fd, &msg_mid, flags_mid); k_free(msg_iov); @@ -772,7 +791,7 @@ static ssize_t nsos_recvfrom(void *obj, void *buf, size_t len, int flags, goto return_ret; } - ret = nsos_adapt_recvfrom(sock->pollfd.fd, buf, len, flags_mid, + ret = nsos_adapt_recvfrom(sock->poll.mid.fd, buf, len, flags_mid, addr_mid, &addrlen_mid); if (ret < 0) { goto return_ret; @@ -878,7 +897,7 @@ static int nsos_getsockopt_int(struct nsos_socket *sock, int nsos_mid_level, int return -1; } - err = nsos_adapt_getsockopt(sock->pollfd.fd, NSOS_MID_SOL_SOCKET, + err = nsos_adapt_getsockopt(sock->poll.mid.fd, NSOS_MID_SOL_SOCKET, NSOS_MID_SO_KEEPALIVE, optval, &nsos_mid_optlen); if (err) { errno = errno_from_nsos_mid(-err); @@ -907,7 +926,7 @@ static int nsos_getsockopt(void *obj, int level, int optname, return -1; } - err = nsos_adapt_getsockopt(sock->pollfd.fd, NSOS_MID_SOL_SOCKET, + err = nsos_adapt_getsockopt(sock->poll.mid.fd, NSOS_MID_SOL_SOCKET, NSOS_MID_SO_ERROR, &nsos_mid_err, NULL); if (err) { errno = errno_from_nsos_mid(-err); @@ -927,7 +946,7 @@ static int nsos_getsockopt(void *obj, int level, int optname, return -1; } - err = nsos_adapt_getsockopt(sock->pollfd.fd, NSOS_MID_SOL_SOCKET, + err = nsos_adapt_getsockopt(sock->poll.mid.fd, NSOS_MID_SOL_SOCKET, NSOS_MID_SO_TYPE, &nsos_mid_type, NULL); if (err) { errno = errno_from_nsos_mid(-err); @@ -951,7 +970,7 @@ static int nsos_getsockopt(void *obj, int level, int optname, return -1; } - err = nsos_adapt_getsockopt(sock->pollfd.fd, NSOS_MID_SOL_SOCKET, + err = nsos_adapt_getsockopt(sock->poll.mid.fd, NSOS_MID_SOL_SOCKET, NSOS_MID_SO_PROTOCOL, &nsos_mid_proto, NULL); if (err) { errno = errno_from_nsos_mid(-err); @@ -975,7 +994,7 @@ static int nsos_getsockopt(void *obj, int level, int optname, return -1; } - err = nsos_adapt_getsockopt(sock->pollfd.fd, NSOS_MID_SOL_SOCKET, + err = nsos_adapt_getsockopt(sock->poll.mid.fd, NSOS_MID_SOL_SOCKET, NSOS_MID_SO_DOMAIN, &nsos_mid_family, NULL); if (err) { errno = errno_from_nsos_mid(-err); @@ -1055,7 +1074,7 @@ static int nsos_setsockopt_int(struct nsos_socket *sock, int nsos_mid_level, int return -1; } - err = nsos_adapt_setsockopt(sock->pollfd.fd, nsos_mid_level, nsos_mid_optname, + err = nsos_adapt_setsockopt(sock->poll.mid.fd, nsos_mid_level, nsos_mid_optname, optval, optlen); if (err) { errno = errno_from_nsos_mid(-err); @@ -1084,7 +1103,7 @@ static int nsos_setsockopt(void *obj, int level, int optname, nsos_mid_priority = *(uint8_t *)optval; - err = nsos_adapt_setsockopt(sock->pollfd.fd, NSOS_MID_SOL_SOCKET, + err = nsos_adapt_setsockopt(sock->poll.mid.fd, NSOS_MID_SOL_SOCKET, NSOS_MID_SO_PRIORITY, &nsos_mid_priority, sizeof(nsos_mid_priority)); if (err) { @@ -1107,7 +1126,7 @@ static int nsos_setsockopt(void *obj, int level, int optname, 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, + err = nsos_adapt_setsockopt(sock->poll.mid.fd, NSOS_MID_SOL_SOCKET, NSOS_MID_SO_RCVTIMEO, &nsos_mid_tv, sizeof(nsos_mid_tv)); if (err) { @@ -1359,11 +1378,11 @@ static const struct socket_dns_offload nsos_dns_ops = { static void nsos_isr(const void *obj) { - struct nsos_socket *sock; + struct nsos_socket_poll *poll; - SYS_DLIST_FOR_EACH_CONTAINER(&nsos_sockets, sock, node) { - if (sock->pollfd.revents) { - sock->pollfd.cb(&sock->pollfd); + SYS_DLIST_FOR_EACH_CONTAINER(&nsos_polls, poll, node) { + if (poll->mid.revents) { + poll->mid.cb(&poll->mid); } } } From b5e16b13807187fa552677cdf7ff373ae0c8a7b4 Mon Sep 17 00:00:00 2001 From: Marcin Niestroj Date: Tue, 7 May 2024 15:41:19 +0200 Subject: [PATCH 1928/2849] drivers: nsos: handle sendto() blocking call Use poll(), similar to accept() and recvfrom() APIs. Signed-off-by: Marcin Niestroj --- drivers/net/nsos_sockets.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/net/nsos_sockets.c b/drivers/net/nsos_sockets.c index 910472ee7156f..17e419579803b 100644 --- a/drivers/net/nsos_sockets.c +++ b/drivers/net/nsos_sockets.c @@ -702,6 +702,11 @@ static ssize_t nsos_sendto(void *obj, const void *buf, size_t len, int flags, goto return_ret; } + ret = nsos_poll_if_blocking(sock, ZSOCK_POLLOUT, K_FOREVER, flags); + if (ret < 0) { + goto return_ret; + } + ret = nsos_adapt_sendto(sock->poll.mid.fd, buf, len, flags_mid, addr_mid, addrlen_mid); From a150458d3586ae448a1e63cc35a89f9714494782 Mon Sep 17 00:00:00 2001 From: Marcin Niestroj Date: Tue, 7 May 2024 15:19:26 +0200 Subject: [PATCH 1929/2849] drivers: nsos: handle sendmsg() blocking call Use poll(), similar to sendto() and accept() APIs. Signed-off-by: Marcin Niestroj --- drivers/net/nsos_sockets.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/net/nsos_sockets.c b/drivers/net/nsos_sockets.c index 17e419579803b..9a9594579a237 100644 --- a/drivers/net/nsos_sockets.c +++ b/drivers/net/nsos_sockets.c @@ -761,8 +761,14 @@ static ssize_t nsos_sendmsg(void *obj, const struct msghdr *msg, int flags) msg_mid.msg_controllen = 0; msg_mid.msg_flags = 0; + ret = nsos_poll_if_blocking(sock, ZSOCK_POLLOUT, K_FOREVER, flags); + if (ret < 0) { + goto free_msg_iov; + } + ret = nsos_adapt_sendmsg(sock->poll.mid.fd, &msg_mid, flags_mid); +free_msg_iov: k_free(msg_iov); return_ret: From 66c966f0bddc858a6a53fd63d66c155210901015 Mon Sep 17 00:00:00 2001 From: Marcin Niestroj Date: Tue, 4 Jun 2024 14:08:41 +0200 Subject: [PATCH 1930/2849] drivers: nsos: handle setsockopt(SO_SNDTIMEO) Handle SO_SNDTIMEO similar to how SO_RCVTIMEO is handled. Signed-off-by: Marcin Niestroj --- drivers/net/nsos_adapt.c | 16 ++++++++++++++++ drivers/net/nsos_sockets.c | 35 +++++++++++++++++++++++++++++++++-- 2 files changed, 49 insertions(+), 2 deletions(-) diff --git a/drivers/net/nsos_adapt.c b/drivers/net/nsos_adapt.c index 5514bb4a13446..91be0b4cf5b48 100644 --- a/drivers/net/nsos_adapt.c +++ b/drivers/net/nsos_adapt.c @@ -692,6 +692,22 @@ int nsos_adapt_setsockopt(int fd, int nsos_mid_level, int nsos_mid_optname, return 0; } + case NSOS_MID_SO_SNDTIMEO: { + 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_SNDTIMEO, + &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_sockets.c b/drivers/net/nsos_sockets.c index 9a9594579a237..4337e689fb193 100644 --- a/drivers/net/nsos_sockets.c +++ b/drivers/net/nsos_sockets.c @@ -50,6 +50,7 @@ struct nsos_socket { int fd; k_timeout_t recv_timeout; + k_timeout_t send_timeout; struct nsos_socket_poll poll; }; @@ -190,6 +191,7 @@ static int nsos_socket_create(int family, int type, int proto) sock->fd = fd; sock->recv_timeout = K_FOREVER; + sock->send_timeout = K_FOREVER; sock->poll.mid.fd = nsos_adapt_socket(family_mid, type_mid, proto_mid); if (sock->poll.mid.fd < 0) { @@ -702,7 +704,7 @@ static ssize_t nsos_sendto(void *obj, const void *buf, size_t len, int flags, goto return_ret; } - ret = nsos_poll_if_blocking(sock, ZSOCK_POLLOUT, K_FOREVER, flags); + ret = nsos_poll_if_blocking(sock, ZSOCK_POLLOUT, sock->send_timeout, flags); if (ret < 0) { goto return_ret; } @@ -761,7 +763,7 @@ static ssize_t nsos_sendmsg(void *obj, const struct msghdr *msg, int flags) msg_mid.msg_controllen = 0; msg_mid.msg_flags = 0; - ret = nsos_poll_if_blocking(sock, ZSOCK_POLLOUT, K_FOREVER, flags); + ret = nsos_poll_if_blocking(sock, ZSOCK_POLLOUT, sock->send_timeout, flags); if (ret < 0) { goto free_msg_iov; } @@ -1153,6 +1155,35 @@ static int nsos_setsockopt(void *obj, int level, int optname, return 0; } + case SO_SNDTIMEO: { + 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->poll.mid.fd, NSOS_MID_SOL_SOCKET, + NSOS_MID_SO_SNDTIMEO, &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->send_timeout = K_FOREVER; + } else { + sock->send_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 f7269059698832fa3d9cd35361916db2897dd397 Mon Sep 17 00:00:00 2001 From: Marcin Niestroj Date: Tue, 4 Jun 2024 14:08:48 +0200 Subject: [PATCH 1931/2849] drivers: nsos: handle connect() blocking call Use poll() to wait for connect attempt to complete or timeout. That way connect() does not block Native Simulator on host syscall. Signed-off-by: Marcin Niestroj --- drivers/net/nsos_sockets.c | 53 +++++++++++++++++++++++++++++++++++++- 1 file changed, 52 insertions(+), 1 deletion(-) diff --git a/drivers/net/nsos_sockets.c b/drivers/net/nsos_sockets.c index 4337e689fb193..1e6c03abca8c9 100644 --- a/drivers/net/nsos_sockets.c +++ b/drivers/net/nsos_sockets.c @@ -13,6 +13,9 @@ #undef _POSIX_C_SOURCE #define _POSIX_C_SOURCE 200809L +#include +LOG_MODULE_REGISTER(nsos_sockets); + #include #include #include @@ -585,12 +588,54 @@ static int nsos_bind(void *obj, const struct sockaddr *addr, socklen_t addrlen) return ret; } +static int nsos_connect_blocking(struct nsos_socket *sock, + struct nsos_mid_sockaddr *addr_mid, + size_t addrlen_mid, + int fcntl_flags) +{ + int clear_nonblock_ret; + int ret; + + ret = nsos_adapt_fcntl_setfl(sock->poll.mid.fd, fcntl_flags | NSOS_MID_O_NONBLOCK); + if (ret < 0) { + return ret; + } + + ret = nsos_adapt_connect(sock->poll.mid.fd, addr_mid, addrlen_mid); + if (ret == -NSOS_MID_EINPROGRESS) { + int so_err; + size_t so_err_len = sizeof(so_err); + + ret = nsos_wait_for_poll(sock, ZSOCK_POLLOUT, sock->send_timeout); + if (ret < 0) { + goto clear_nonblock; + } + + ret = nsos_adapt_getsockopt(sock->poll.mid.fd, NSOS_MID_SOL_SOCKET, + NSOS_MID_SO_ERROR, &so_err, &so_err_len); + if (ret < 0) { + goto clear_nonblock; + } + + ret = so_err; + } + +clear_nonblock: + clear_nonblock_ret = nsos_adapt_fcntl_setfl(sock->poll.mid.fd, fcntl_flags); + if (clear_nonblock_ret < 0) { + LOG_ERR("Failed to clear O_NONBLOCK: %d", clear_nonblock_ret); + } + + return ret; +} + static int nsos_connect(void *obj, const struct sockaddr *addr, socklen_t addrlen) { struct nsos_socket *sock = obj; struct nsos_mid_sockaddr_storage addr_storage_mid; struct nsos_mid_sockaddr *addr_mid = (struct nsos_mid_sockaddr *)&addr_storage_mid; size_t addrlen_mid; + int flags; int ret; ret = sockaddr_to_nsos_mid(addr, addrlen, &addr_mid, &addrlen_mid); @@ -598,7 +643,13 @@ static int nsos_connect(void *obj, const struct sockaddr *addr, socklen_t addrle goto return_ret; } - ret = nsos_adapt_connect(sock->poll.mid.fd, addr_mid, addrlen_mid); + flags = nsos_adapt_fcntl_getfl(sock->poll.mid.fd); + + if (flags & NSOS_MID_O_NONBLOCK) { + ret = nsos_adapt_connect(sock->poll.mid.fd, addr_mid, addrlen_mid); + } else { + ret = nsos_connect_blocking(sock, addr_mid, addrlen_mid, flags); + } return_ret: if (ret < 0) { From 3bf11d19dc804cbf80ce4f6ec1f34509d707eca5 Mon Sep 17 00:00:00 2001 From: Phi Bang Nguyen Date: Mon, 3 Jun 2024 14:45:24 +0200 Subject: [PATCH 1932/2849] samples: video: tcpserversink: Run clang-format Run clang-format before making any changes Signed-off-by: Phi Bang Nguyen --- samples/subsys/video/tcpserversink/src/main.c | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/samples/subsys/video/tcpserversink/src/main.c b/samples/subsys/video/tcpserversink/src/main.c index 3b4cf3ba223ae..478bffc64078c 100644 --- a/samples/subsys/video/tcpserversink/src/main.c +++ b/samples/subsys/video/tcpserversink/src/main.c @@ -15,7 +15,7 @@ #include LOG_MODULE_REGISTER(main); -#define MY_PORT 5000 +#define MY_PORT 5000 #define MAX_CLIENT_QUEUE 1 static ssize_t sendall(int sock, const void *buf, size_t len) @@ -78,10 +78,9 @@ int main(void) return 0; } - printk("Video device detected, format: %c%c%c%c %ux%u\n", - (char)fmt.pixelformat, (char)(fmt.pixelformat >> 8), - (char)(fmt.pixelformat >> 16), (char)(fmt.pixelformat >> 24), - fmt.width, fmt.height); + printk("Video device detected, format: %c%c%c%c %ux%u\n", (char)fmt.pixelformat, + (char)(fmt.pixelformat >> 8), (char)(fmt.pixelformat >> 16), + (char)(fmt.pixelformat >> 24), fmt.width, fmt.height); /* Alloc Buffers */ for (i = 0; i < ARRAY_SIZE(buffers); i++) { @@ -96,8 +95,7 @@ int main(void) do { printk("TCP: Waiting for client...\n"); - client = accept(sock, (struct sockaddr *)&client_addr, - &client_addr_len); + client = accept(sock, (struct sockaddr *)&client_addr, &client_addr_len); if (client < 0) { printk("Failed to accept: %d\n", errno); return 0; @@ -121,8 +119,7 @@ int main(void) /* Capture loop */ i = 0; do { - ret = video_dequeue(video, VIDEO_EP_OUT, &vbuf, - K_FOREVER); + ret = video_dequeue(video, VIDEO_EP_OUT, &vbuf, K_FOREVER); if (ret) { LOG_ERR("Unable to dequeue video buf"); return 0; @@ -149,8 +146,7 @@ int main(void) /* Flush remaining buffers */ do { - ret = video_dequeue(video, VIDEO_EP_OUT, - &vbuf, K_NO_WAIT); + ret = video_dequeue(video, VIDEO_EP_OUT, &vbuf, K_NO_WAIT); } while (!ret); } while (1); From ba1d5fcc8640f93e1bc7777a581e5901922f71e7 Mon Sep 17 00:00:00 2001 From: Phi Bang Nguyen Date: Mon, 3 Jun 2024 17:34:24 +0200 Subject: [PATCH 1933/2849] samples: video: tcpserversink: Add a new line after printk Add a new line so that logs are easier to be read. Signed-off-by: Phi Bang Nguyen --- samples/subsys/video/tcpserversink/src/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/subsys/video/tcpserversink/src/main.c b/samples/subsys/video/tcpserversink/src/main.c index 478bffc64078c..24daf0af2bab2 100644 --- a/samples/subsys/video/tcpserversink/src/main.c +++ b/samples/subsys/video/tcpserversink/src/main.c @@ -125,7 +125,7 @@ int main(void) return 0; } - printk("\rSending frame %d", i++); + printk("\rSending frame %d\n", i++); /* Send video buffer to TCP client */ ret = sendall(client, vbuf->buffer, vbuf->bytesused); From 7ece993029e0251010f5e630c124ae201f16e325 Mon Sep 17 00:00:00 2001 From: Phi Bang Nguyen Date: Mon, 3 Jun 2024 16:00:33 +0200 Subject: [PATCH 1934/2849] samples: video: tcpserversink: Update default camera resolution The default resolution of mt9m114 camera is now changed to 480x272. Update the sample documentation to reflect this change. Signed-off-by: Phi Bang Nguyen --- samples/subsys/video/tcpserversink/README.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/samples/subsys/video/tcpserversink/README.rst b/samples/subsys/video/tcpserversink/README.rst index 6c7fc89afde4e..91638d3bb9afb 100644 --- a/samples/subsys/video/tcpserversink/README.rst +++ b/samples/subsys/video/tcpserversink/README.rst @@ -42,7 +42,7 @@ Sample Output .. code-block:: console - Video device detected, format: RGBP 640x480 + Video device detected, format: RGBP 480x272 TCP: Waiting for client... Then from a peer on the same network you can connect and grab frames. @@ -52,7 +52,7 @@ Example with gstreamer: .. code-block:: console gst-launch-1.0 tcpclientsrc host=192.0.2.1 port=5000 \ - ! videoparse format=rgb16 width=640 height=480 \ + ! videoparse format=rgb16 width=480 height=272 \ ! queue \ ! videoconvert \ ! fpsdisplaysink sync=false From 020ffe6104b0ae3ad3dad58bc7c3e4a765b33010 Mon Sep 17 00:00:00 2001 From: Phi Bang Nguyen Date: Mon, 3 Jun 2024 15:11:19 +0200 Subject: [PATCH 1935/2849] samples: video: tcpserversink: Use mt9m114 camera shield Update the sample to use a camera shield with a camera chosen node. This is not only because the camera nodes in the mimxrt1064 device tree has been now moved to a separate mt9m114 shield but also to make the sample more generic. Signed-off-by: Phi Bang Nguyen --- samples/subsys/video/tcpserversink/README.rst | 1 + samples/subsys/video/tcpserversink/sample.yaml | 4 ++++ samples/subsys/video/tcpserversink/src/main.c | 2 +- 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/samples/subsys/video/tcpserversink/README.rst b/samples/subsys/video/tcpserversink/README.rst index 91638d3bb9afb..f310e81fcd311 100644 --- a/samples/subsys/video/tcpserversink/README.rst +++ b/samples/subsys/video/tcpserversink/README.rst @@ -34,6 +34,7 @@ For :ref:`mimxrt1064_evk`, build this sample application with the following comm .. zephyr-app-commands:: :zephyr-app: samples/subsys/video/tcpserversink :board: mimxrt1064_evk + :shield: dvp_fpc24_mt9m114 :goals: build :compact: diff --git a/samples/subsys/video/tcpserversink/sample.yaml b/samples/subsys/video/tcpserversink/sample.yaml index 6019ce0341ed7..e95ef1beaf34e 100644 --- a/samples/subsys/video/tcpserversink/sample.yaml +++ b/samples/subsys/video/tcpserversink/sample.yaml @@ -2,14 +2,18 @@ sample: name: Video TCP server sink tests: sample.video.tcpserversink: + filter: dt_chosen_enabled("zephyr,camera") build_only: true tags: - video - net - socket + - shield platform_allow: mimxrt1064_evk depends_on: - video - netif integration_platforms: - mimxrt1064_evk + extra_args: + - platform:mimxrt1064_evk:SHIELD=dvp_fpc24_mt9m114 diff --git a/samples/subsys/video/tcpserversink/src/main.c b/samples/subsys/video/tcpserversink/src/main.c index 24daf0af2bab2..765102e93aa9d 100644 --- a/samples/subsys/video/tcpserversink/src/main.c +++ b/samples/subsys/video/tcpserversink/src/main.c @@ -40,7 +40,7 @@ int main(void) struct video_buffer *buffers[2], *vbuf; int i, ret, sock, client; struct video_format fmt; - const struct device *const video = DEVICE_DT_GET_ANY(nxp_imx_csi); + const struct device *const video = DEVICE_DT_GET(DT_CHOSEN(zephyr_camera)); /* Prepare Network */ (void)memset(&addr, 0, sizeof(addr)); From 70c0c334a49bf67a884e8751c9a37521a11503f2 Mon Sep 17 00:00:00 2001 From: Phi Bang Nguyen Date: Mon, 3 Jun 2024 15:56:17 +0200 Subject: [PATCH 1936/2849] samples: video: tcpserversink: Add support for software generator Add support for video software generator in case of a real video capture device is missing. Signed-off-by: Phi Bang Nguyen --- samples/subsys/video/tcpserversink/README.rst | 6 ++++-- .../subsys/video/tcpserversink/sample.yaml | 1 - samples/subsys/video/tcpserversink/src/main.c | 19 ++++++++++++++----- 3 files changed, 18 insertions(+), 8 deletions(-) diff --git a/samples/subsys/video/tcpserversink/README.rst b/samples/subsys/video/tcpserversink/README.rst index f310e81fcd311..83e9a62d9534d 100644 --- a/samples/subsys/video/tcpserversink/README.rst +++ b/samples/subsys/video/tcpserversink/README.rst @@ -29,12 +29,13 @@ interface. Ethernet cable must be connected to RJ45 connector. Building and Running ******************** -For :ref:`mimxrt1064_evk`, build this sample application with the following commands: +For :ref:`mimxrt1064_evk`, the sample can be built with the following command. +If a mt9m114 camera shield is missing, video software generator will be used instead. .. zephyr-app-commands:: :zephyr-app: samples/subsys/video/tcpserversink :board: mimxrt1064_evk - :shield: dvp_fpc24_mt9m114 + :shield: [dvp_fpc24_mt9m114] :goals: build :compact: @@ -58,6 +59,7 @@ Example with gstreamer: ! videoconvert \ ! fpsdisplaysink sync=false +For video software generator, the default resolution should be width=320 and height=160. References ********** diff --git a/samples/subsys/video/tcpserversink/sample.yaml b/samples/subsys/video/tcpserversink/sample.yaml index e95ef1beaf34e..717923a6fa199 100644 --- a/samples/subsys/video/tcpserversink/sample.yaml +++ b/samples/subsys/video/tcpserversink/sample.yaml @@ -2,7 +2,6 @@ sample: name: Video TCP server sink tests: sample.video.tcpserversink: - filter: dt_chosen_enabled("zephyr,camera") build_only: true tags: - video diff --git a/samples/subsys/video/tcpserversink/src/main.c b/samples/subsys/video/tcpserversink/src/main.c index 765102e93aa9d..90946be44bd88 100644 --- a/samples/subsys/video/tcpserversink/src/main.c +++ b/samples/subsys/video/tcpserversink/src/main.c @@ -15,6 +15,7 @@ #include LOG_MODULE_REGISTER(main); +#define VIDEO_DEV_SW "VIDEO_SW_GENERATOR" #define MY_PORT 5000 #define MAX_CLIENT_QUEUE 1 @@ -40,8 +41,21 @@ int main(void) struct video_buffer *buffers[2], *vbuf; int i, ret, sock, client; struct video_format fmt; +#if DT_HAS_CHOSEN(zephyr_camera) const struct device *const video = DEVICE_DT_GET(DT_CHOSEN(zephyr_camera)); + if (!device_is_ready(video)) { + LOG_ERR("%s: video device not ready.", video->name); + return 0; + } +#else + const struct device *const video = device_get_binding(VIDEO_DEV_SW); + + if (video == NULL) { + LOG_ERR("%s: video device not found or failed to initialized.", VIDEO_DEV_SW); + return 0; + } +#endif /* Prepare Network */ (void)memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; @@ -67,11 +81,6 @@ int main(void) return 0; } - if (!device_is_ready(video)) { - LOG_ERR("%s: device not ready.\n", video->name); - return 0; - } - /* Get default/native format */ if (video_get_format(video, VIDEO_EP_OUT, &fmt)) { LOG_ERR("Unable to retrieve video format"); From 1e96b3bc8f906e736d57df3199e4183a148c8bb3 Mon Sep 17 00:00:00 2001 From: Jordan Yates Date: Sun, 26 May 2024 16:47:21 +1000 Subject: [PATCH 1937/2849] Revert "samples: drivers: jesd216: add nRF54H20 overlay" This reverts commit b1de9a6c46217b4edc7befb928a9cb2e6d010ca3. Signed-off-by: Jordan Yates --- .../jesd216/boards/nrf54h20dk_nrf54h20_cpuapp.overlay | 9 --------- 1 file changed, 9 deletions(-) delete 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 deleted file mode 100644 index b8f138ad2b2e2..0000000000000 --- a/samples/drivers/jesd216/boards/nrf54h20dk_nrf54h20_cpuapp.overlay +++ /dev/null @@ -1,9 +0,0 @@ -/* - * Copyright (c) 2024 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: Apache-2.0 - */ - -&mx25uw63 { - status = "okay"; -}; From fd8d9336eea0c077774d8302b32cfc8d94cb21cb Mon Sep 17 00:00:00 2001 From: Jordan Yates Date: Sun, 26 May 2024 16:48:30 +1000 Subject: [PATCH 1938/2849] Revert "samples: drivers: spi_flash: Add nRF54H20DK support" This reverts commit 29f81872ce2751bf2a6f69dda1428e65a0366763. Signed-off-by: Jordan Yates --- .../boards/nrf54h20dk_nrf54h20_cpuapp.overlay | 16 ---------------- 1 file changed, 16 deletions(-) delete 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 deleted file mode 100644 index d03419690bdf6..0000000000000 --- a/samples/drivers/spi_flash/boards/nrf54h20dk_nrf54h20_cpuapp.overlay +++ /dev/null @@ -1,16 +0,0 @@ -/* - * Copyright (c) 2024 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: Apache-2.0 - */ - -&mx25uw63 { - status = "okay"; -}; - - -/ { - aliases { - spi-flash0 = &mx25uw63; - }; -}; From 54e61b025e43136df285c611488a1304a787a795 Mon Sep 17 00:00:00 2001 From: Jordan Yates Date: Sun, 26 May 2024 16:29:44 +1000 Subject: [PATCH 1939/2849] samples: spi_flash: node from compat, not alias Get the flash device from the node compatible, instead of an alias. This removes the need for the `spi-flash0` alias on every board with one of these drivers. Signed-off-by: Jordan Yates --- samples/drivers/spi_flash/README.rst | 4 ++-- samples/drivers/spi_flash/src/main.c | 16 +++++++++++++++- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/samples/drivers/spi_flash/README.rst b/samples/drivers/spi_flash/README.rst index 3767444b3a2c8..1d48c19af1154 100644 --- a/samples/drivers/spi_flash/README.rst +++ b/samples/drivers/spi_flash/README.rst @@ -15,8 +15,8 @@ savings is correctly implemented. Building and Running ******************** -The application will build only for a target that has a :ref:`devicetree ` -``spi-flash0`` alias that refers to an entry with one of the following bindings as a compatible: +The application will build only for a target that has a devicetree node with one of the +following bindings as a compatible: * :dtcompatible:`jedec,spi-nor`, * :dtcompatible:`st,stm32-qspi-nor`, diff --git a/samples/drivers/spi_flash/src/main.c b/samples/drivers/spi_flash/src/main.c index e456b51103090..b84359ae05bb1 100644 --- a/samples/drivers/spi_flash/src/main.c +++ b/samples/drivers/spi_flash/src/main.c @@ -32,6 +32,20 @@ #define SPI_FLASH_MULTI_SECTOR_TEST #endif +#if DT_HAS_COMPAT_STATUS_OKAY(jedec_spi_nor) +#define SPI_FLASH_COMPAT jedec_spi_nor +#elif DT_HAS_COMPAT_STATUS_OKAY(st_stm32_qspi_nor) +#define SPI_FLASH_COMPAT st_stm32_qspi_nor +#elif DT_HAS_COMPAT_STATUS_OKAY(st_stm32_ospi_nor) +#define SPI_FLASH_COMPAT st_stm32_ospi_nor +#elif DT_HAS_COMPAT_STATUS_OKAY(st_stm32_xspi_nor) +#define SPI_FLASH_COMPAT st_stm32_xspi_nor +#elif DT_HAS_COMPAT_STATUS_OKAY(nordic_qspi_nor) +#define SPI_FLASH_COMPAT nordic_qspi_nor +#else +#define SPI_FLASH_COMPAT invalid +#endif + const uint8_t erased[] = { 0xff, 0xff, 0xff, 0xff }; void single_sector_test(const struct device *flash_dev) @@ -192,7 +206,7 @@ void multi_sector_test(const struct device *flash_dev) int main(void) { - const struct device *flash_dev = DEVICE_DT_GET(DT_ALIAS(spi_flash0)); + const struct device *flash_dev = DEVICE_DT_GET_ONE(SPI_FLASH_COMPAT); if (!device_is_ready(flash_dev)) { printk("%s: device not ready.\n", flash_dev->name); From 90bbf19d6a2501adf61d2add5584b95e3c3abfc4 Mon Sep 17 00:00:00 2001 From: Jordan Yates Date: Sun, 26 May 2024 16:38:03 +1000 Subject: [PATCH 1940/2849] boards: remove `spi-flash0` alias As `samples/drivers/spi_flash` no longer needs this alias, there is no use for it on boards. Signed-off-by: Jordan Yates --- .../actinius/icarus/actinius_icarus_common_2_0_0.dtsi | 4 ---- .../icarus_bee/actinius_icarus_bee_common.dtsi | 1 - .../icarus_som_dk/actinius_icarus_som_dk_common.dtsi | 1 - boards/adafruit/feather/adafruit_feather_nrf52840.dts | 1 - .../feather_stm32f405/adafruit_feather_stm32f405.dts | 1 - .../itsybitsy/adafruit_itsybitsy_nrf52840.dts | 1 - boards/adi/eval_adin1110ebz/adi_eval_adin1110ebz.dts | 1 - boards/adi/eval_adin2111ebz/adi_eval_adin2111ebz.dts | 1 - .../alientek/pandora_stm32l475/pandora_stm32l475.dts | 2 -- .../giga_r1/arduino_giga_r1_stm32h747xx_m7.dts | 1 - .../arduino/nicla_sense_me/arduino_nicla_sense_me.dts | 1 - .../beagleconnect_freedom/beagleconnect_freedom.dts | 1 - .../feather/circuitdojo_feather_nrf9160_common.dtsi | 1 - .../digilent/arty_a7/dts/arty_a7_arm_designstart.dtsi | 1 - .../bl5340_dvk/bl5340_dvk_nrf5340_cpuapp_common.dtsi | 1 - boards/ezurio/bt610/bt610.dts | 1 - boards/ezurio/mg100/mg100.dts | 1 - boards/ezurio/pinnacle_100_dvk/pinnacle_100_dvk.dts | 1 - boards/ezurio/rm1xx_dvk/rm1xx_dvk.dts | 1 - boards/fanke/fk7b0m1_vbt6/fk7b0m1_vbt6.dts | 1 - boards/gaisler/gr716a_mini/gr716a_mini.dts | 4 +--- boards/gd/gd32a503v_eval/gd32a503v_eval.dts | 1 - boards/gd/gd32f450i_eval/gd32f450i_eval.dts | 1 - boards/gd/gd32f450z_eval/gd32f450z_eval.dts | 1 - boards/gd/gd32f470i_eval/gd32f470i_eval.dts | 1 - boards/gd/gd32vf103v_eval/gd32vf103v_eval.dts | 1 - boards/makerdiary/nrf52840_mdk/nrf52840_mdk.dts | 1 - boards/nordic/nrf52840dk/nrf52840dk_nrf52840.dts | 1 - boards/nordic/nrf5340dk/nrf5340_cpuapp_common.dtsi | 1 - boards/nordic/nrf54l15pdk/nrf54l15_cpuapp_common.dtsi | 4 ---- boards/nordic/nrf9131ek/nrf9131ek_nrf9131_common.dtsi | 1 - boards/nordic/nrf9151dk/nrf9151dk_nrf9151_common.dtsi | 1 - .../nrf9160dk/nrf9160dk_nrf9160_common_0_14_0.dtsi | 6 ------ boards/nordic/nrf9161dk/nrf9161dk_nrf9161_common.dtsi | 1 - .../nrf9161dk/nrf9161dk_nrf9161_common_0_7_0.dtsi | 6 ------ boards/nuvoton/npcx4m8f_evb/npcx4m8f_evb.dts | 1 - boards/nuvoton/npcx7m6fb_evb/npcx7m6fb_evb.dts | 2 -- boards/nuvoton/npcx9m6f_evb/npcx9m6f_evb.dts | 2 -- boards/nxp/frdm_k82f/frdm_k82f.dts | 1 - .../rv32m1_vega/rv32m1_vega_openisa_rv32m1_ri5cy.dts | 4 ---- boards/others/black_f407ve/black_f407ve.dts | 1 - .../pan1783/pan1783_nrf5340_cpuapp_common.dtsi | 1 - boards/particle/argon/dts/mesh_feather.dtsi | 1 - boards/particle/boron/dts/mesh_feather.dtsi | 1 - boards/particle/xenon/particle_xenon.dts | 1 - boards/seagate/legend/legend.dts | 1 - boards/seeed/xiao_ble/xiao_ble_common.dtsi | 1 - boards/silabs/efr32_radio/efr32_radio.dtsi | 1 - .../efr32_radio/efr32_radio_efr32bg13p632f512gm48.dts | 4 ---- .../efr32_radio/efr32_radio_efr32fg1p133f256gm48.dts | 1 - .../efr32_radio_efr32mg12p432f1024gl125.dts | 4 ---- .../efr32_radio_efr32mg12p433f1024gm68.dts | 4 ---- .../silabs/efr32_thunderboard/efr32bg22_brd4184.dtsi | 1 - .../silabs/efr32_thunderboard/efr32bg27_brd2602a.dts | 1 - boards/silabs/efr32mg_sltb004a/efr32mg_sltb004a.dts | 1 - .../em_starterkit/em_starterkit_emsk_em7d_2_3.overlay | 1 - boards/snps/em_starterkit/em_starterkit_r23.dtsi | 4 ---- boards/snps/emsdp/emsdp_emsdp_em11d.dts | 1 - boards/snps/emsdp/emsdp_emsdp_em4.dts | 1 - boards/snps/emsdp/emsdp_emsdp_em5d.dts | 1 - boards/snps/emsdp/emsdp_emsdp_em6.dts | 1 - boards/snps/emsdp/emsdp_emsdp_em7d.dts | 1 - boards/snps/emsdp/emsdp_emsdp_em7d_esp.dts | 1 - boards/snps/emsdp/emsdp_emsdp_em9d.dts | 1 - boards/st/b_l4s5i_iot01a/b_l4s5i_iot01a.dts | 1 - boards/st/b_u585i_iot02a/b_u585i_iot02a-common.dtsi | 1 - boards/st/disco_l475_iot1/disco_l475_iot1.dts | 1 - boards/st/stm32f723e_disco/stm32f723e_disco.dts | 1 - boards/st/stm32f746g_disco/stm32f746g_disco.dts | 1 - boards/st/stm32f7508_dk/stm32f7508_dk.dts | 1 - boards/st/stm32f769i_disco/stm32f769i_disco.dts | 1 - boards/st/stm32h573i_dk/stm32h573i_dk.dts | 1 - .../stm32h747i_disco_stm32h747xx_m7.dts | 1 - boards/st/stm32h750b_dk/stm32h750b_dk.dts | 1 - boards/st/stm32h7b3i_dk/stm32h7b3i_dk.dts | 1 - boards/st/stm32l496g_disco/stm32l496g_disco.dts | 1 - boards/st/stm32l4r9i_disco/stm32l4r9i_disco.dts | 1 - boards/st/stm32l562e_dk/stm32l562e_dk_common.dtsi | 1 - .../u-blox/ubx_bmd340eval/ubx_bmd340eval_nrf52840.dts | 1 - .../u-blox/ubx_bmd345eval/ubx_bmd345eval_nrf52840.dts | 1 - .../u-blox/ubx_bmd380eval/ubx_bmd380eval_nrf52840.dts | 1 - boards/weact/mini_stm32h743/mini_stm32h743.dts | 1 - .../drivers/spi_flash/boards/adp_xc7k_ae350.overlay | 11 ----------- .../spi_flash/boards/mec172xevb_assy6906.overlay | 6 ------ .../common/boards/nrf52840dk_mx25l51245g.overlay | 6 ------ .../common/boards/nrf52840dk_mx25r_high_perf.overlay | 6 ------ .../flash/common/boards/nrf52840dk_spi_nor.overlay | 6 ------ .../common/boards/nrf52840dk_spi_nor_wp_hold.overlay | 6 ------ 88 files changed, 1 insertion(+), 159 deletions(-) delete mode 100644 samples/drivers/spi_flash/boards/adp_xc7k_ae350.overlay diff --git a/boards/actinius/icarus/actinius_icarus_common_2_0_0.dtsi b/boards/actinius/icarus/actinius_icarus_common_2_0_0.dtsi index 9c63a8de3351c..802437900a8de 100644 --- a/boards/actinius/icarus/actinius_icarus_common_2_0_0.dtsi +++ b/boards/actinius/icarus/actinius_icarus_common_2_0_0.dtsi @@ -39,10 +39,6 @@ }; / { - aliases { - spi-flash0 = &w25q64; - }; - charger_enable: charger-enable { compatible = "actinius-charger-enable"; gpios = <&gpio0 7 GPIO_ACTIVE_LOW>; diff --git a/boards/actinius/icarus_bee/actinius_icarus_bee_common.dtsi b/boards/actinius/icarus_bee/actinius_icarus_bee_common.dtsi index 0bc57cd205acd..f4972923e6907 100644 --- a/boards/actinius/icarus_bee/actinius_icarus_bee_common.dtsi +++ b/boards/actinius/icarus_bee/actinius_icarus_bee_common.dtsi @@ -79,7 +79,6 @@ mcuboot-button0 = &button0; mcuboot-led0 = &blue_led; watchdog0 = &wdt0; - spi-flash0 = &w25q64; accel0 = &lis2dh12_accel; }; diff --git a/boards/actinius/icarus_som_dk/actinius_icarus_som_dk_common.dtsi b/boards/actinius/icarus_som_dk/actinius_icarus_som_dk_common.dtsi index 317b0d153b7a7..683edc7bc5793 100644 --- a/boards/actinius/icarus_som_dk/actinius_icarus_som_dk_common.dtsi +++ b/boards/actinius/icarus_som_dk/actinius_icarus_som_dk_common.dtsi @@ -55,7 +55,6 @@ mcuboot-led0 = &blue_led; watchdog0 = &wdt0; accel0 = &lis2dh12_accel; - spi-flash0 = &w25q64; led-strip = &neopixel_led; }; diff --git a/boards/adafruit/feather/adafruit_feather_nrf52840.dts b/boards/adafruit/feather/adafruit_feather_nrf52840.dts index 2333e5becbeda..5c5eba7c503a1 100644 --- a/boards/adafruit/feather/adafruit_feather_nrf52840.dts +++ b/boards/adafruit/feather/adafruit_feather_nrf52840.dts @@ -60,7 +60,6 @@ led1 = &led1; sw0 = &button0; watchdog0 = &wdt0; - spi-flash0 = &gd25q16; }; }; diff --git a/boards/adafruit/feather_stm32f405/adafruit_feather_stm32f405.dts b/boards/adafruit/feather_stm32f405/adafruit_feather_stm32f405.dts index cc1cb7020626b..7995e35959307 100644 --- a/boards/adafruit/feather_stm32f405/adafruit_feather_stm32f405.dts +++ b/boards/adafruit/feather_stm32f405/adafruit_feather_stm32f405.dts @@ -31,7 +31,6 @@ aliases { led0 = &led; - spi-flash0 = &gd25q16; }; }; diff --git a/boards/adafruit/itsybitsy/adafruit_itsybitsy_nrf52840.dts b/boards/adafruit/itsybitsy/adafruit_itsybitsy_nrf52840.dts index 45827a7bcec82..af2640954a5f0 100644 --- a/boards/adafruit/itsybitsy/adafruit_itsybitsy_nrf52840.dts +++ b/boards/adafruit/itsybitsy/adafruit_itsybitsy_nrf52840.dts @@ -48,7 +48,6 @@ led0 = &led0; sw0 = &button0; watchdog0 = &wdt0; - spi-flash0 = &gd25q16; led-strip = &apa102; }; }; diff --git a/boards/adi/eval_adin1110ebz/adi_eval_adin1110ebz.dts b/boards/adi/eval_adin1110ebz/adi_eval_adin1110ebz.dts index 171e57963bcd8..3b6934062e9cd 100644 --- a/boards/adi/eval_adin1110ebz/adi_eval_adin1110ebz.dts +++ b/boards/adi/eval_adin1110ebz/adi_eval_adin1110ebz.dts @@ -54,7 +54,6 @@ aliases { led0 = &green_led; watchdog0 = &iwdg; - spi-flash0 = &mx25r6435f; ambient-temp0 = &adt7420; }; diff --git a/boards/adi/eval_adin2111ebz/adi_eval_adin2111ebz.dts b/boards/adi/eval_adin2111ebz/adi_eval_adin2111ebz.dts index 83a3343ca351d..3a990815857f0 100644 --- a/boards/adi/eval_adin2111ebz/adi_eval_adin2111ebz.dts +++ b/boards/adi/eval_adin2111ebz/adi_eval_adin2111ebz.dts @@ -48,7 +48,6 @@ aliases { led0 = &blue_led; watchdog0 = &iwdg; - spi-flash0 = &flash_ext; }; }; diff --git a/boards/alientek/pandora_stm32l475/pandora_stm32l475.dts b/boards/alientek/pandora_stm32l475/pandora_stm32l475.dts index 1c28f6c817636..567e88a01523f 100644 --- a/boards/alientek/pandora_stm32l475/pandora_stm32l475.dts +++ b/boards/alientek/pandora_stm32l475/pandora_stm32l475.dts @@ -27,8 +27,6 @@ zephyr,shell-uart = &usart1; zephyr,sram = &sram0; zephyr,flash = &flash0; - - spi-flash0 = &w25q128jv; }; leds { 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 0ffb4f75380fb..af7f0d673bedc 100644 --- a/boards/arduino/giga_r1/arduino_giga_r1_stm32h747xx_m7.dts +++ b/boards/arduino/giga_r1/arduino_giga_r1_stm32h747xx_m7.dts @@ -37,7 +37,6 @@ led0 = &red_led; led1 = &green_led; sw0 = &user_button; - spi-flash0 = &n25q128a1; }; }; diff --git a/boards/arduino/nicla_sense_me/arduino_nicla_sense_me.dts b/boards/arduino/nicla_sense_me/arduino_nicla_sense_me.dts index 87d1affecd604..52e376ed1405e 100644 --- a/boards/arduino/nicla_sense_me/arduino_nicla_sense_me.dts +++ b/boards/arduino/nicla_sense_me/arduino_nicla_sense_me.dts @@ -38,7 +38,6 @@ aliases { sw0 = &user_button; watchdog0 = &wdt0; - spi-flash0 = &mx25r1635f; }; }; diff --git a/boards/beagle/beagleconnect_freedom/beagleconnect_freedom.dts b/boards/beagle/beagleconnect_freedom/beagleconnect_freedom.dts index 9f8c84df95601..f3eb05c6eb9b7 100644 --- a/boards/beagle/beagleconnect_freedom/beagleconnect_freedom.dts +++ b/boards/beagle/beagleconnect_freedom/beagleconnect_freedom.dts @@ -23,7 +23,6 @@ mcuboot-button0 = &button0; sensor0 = &light; sensor1 = &humidity; - spi-flash0 = &spi_flash0; }; chosen { diff --git a/boards/circuitdojo/feather/circuitdojo_feather_nrf9160_common.dtsi b/boards/circuitdojo/feather/circuitdojo_feather_nrf9160_common.dtsi index 00ce5dcf6c00c..ced868614da98 100644 --- a/boards/circuitdojo/feather/circuitdojo_feather_nrf9160_common.dtsi +++ b/boards/circuitdojo/feather/circuitdojo_feather_nrf9160_common.dtsi @@ -50,7 +50,6 @@ mcuboot-button0 = &button0; mcuboot-led0 = &blue_led; watchdog0 = &wdt0; - spi-flash0 = &w25q32jv; accel0 = &lis2dh; }; diff --git a/boards/digilent/arty_a7/dts/arty_a7_arm_designstart.dtsi b/boards/digilent/arty_a7/dts/arty_a7_arm_designstart.dtsi index 0f51819e18076..8162b47d7d3d7 100644 --- a/boards/digilent/arty_a7/dts/arty_a7_arm_designstart.dtsi +++ b/boards/digilent/arty_a7/dts/arty_a7_arm_designstart.dtsi @@ -26,7 +26,6 @@ sw1 = &sw1; sw2 = &sw2; sw3 = &sw3; - spi-flash0 = &flash0; }; leds { diff --git a/boards/ezurio/bl5340_dvk/bl5340_dvk_nrf5340_cpuapp_common.dtsi b/boards/ezurio/bl5340_dvk/bl5340_dvk_nrf5340_cpuapp_common.dtsi index b515b62693c3b..1f4d3f46a2032 100644 --- a/boards/ezurio/bl5340_dvk/bl5340_dvk_nrf5340_cpuapp_common.dtsi +++ b/boards/ezurio/bl5340_dvk/bl5340_dvk_nrf5340_cpuapp_common.dtsi @@ -105,7 +105,6 @@ watchdog0 = &wdt0; accel0 = &lis3dh; bbram0 = &extrtc0; - spi-flash0 = &mx25r64; }; mipi_dbi { diff --git a/boards/ezurio/bt610/bt610.dts b/boards/ezurio/bt610/bt610.dts index 8eb52c0139f11..9570f499d5463 100644 --- a/boards/ezurio/bt610/bt610.dts +++ b/boards/ezurio/bt610/bt610.dts @@ -78,7 +78,6 @@ mcuboot-button0 = &button1; mcuboot-led0 = &led1; watchdog0 = &wdt0; - spi-flash0 = &mx25r64; }; mag1: mag_1 { diff --git a/boards/ezurio/mg100/mg100.dts b/boards/ezurio/mg100/mg100.dts index 3f69d46febf9c..a9b782eb67cee 100644 --- a/boards/ezurio/mg100/mg100.dts +++ b/boards/ezurio/mg100/mg100.dts @@ -66,7 +66,6 @@ mcuboot-button0 = &button1; mcuboot-led0 = &led1; watchdog0 = &wdt0; - spi-flash0 = &mx25r64; }; }; diff --git a/boards/ezurio/pinnacle_100_dvk/pinnacle_100_dvk.dts b/boards/ezurio/pinnacle_100_dvk/pinnacle_100_dvk.dts index acb5c4e42374a..175f71938c73a 100644 --- a/boards/ezurio/pinnacle_100_dvk/pinnacle_100_dvk.dts +++ b/boards/ezurio/pinnacle_100_dvk/pinnacle_100_dvk.dts @@ -82,7 +82,6 @@ mcuboot-button0 = &button1; mcuboot-led0 = &led1; watchdog0 = &wdt0; - spi-flash0 = &mx25r64; }; }; diff --git a/boards/ezurio/rm1xx_dvk/rm1xx_dvk.dts b/boards/ezurio/rm1xx_dvk/rm1xx_dvk.dts index 1db61912dfb0c..f0b860ac45381 100644 --- a/boards/ezurio/rm1xx_dvk/rm1xx_dvk.dts +++ b/boards/ezurio/rm1xx_dvk/rm1xx_dvk.dts @@ -38,7 +38,6 @@ sw0 = &button2; lora0 = &lora0; watchdog0 = &wdt0; - spi-flash0 = &at25; }; }; diff --git a/boards/fanke/fk7b0m1_vbt6/fk7b0m1_vbt6.dts b/boards/fanke/fk7b0m1_vbt6/fk7b0m1_vbt6.dts index 090a29a198187..a8db5b677f23e 100644 --- a/boards/fanke/fk7b0m1_vbt6/fk7b0m1_vbt6.dts +++ b/boards/fanke/fk7b0m1_vbt6/fk7b0m1_vbt6.dts @@ -41,7 +41,6 @@ aliases { led0 = &user_led; sw0 = &user_button; - spi-flash0 = &w25q64jvssiq_spi; }; }; diff --git a/boards/gaisler/gr716a_mini/gr716a_mini.dts b/boards/gaisler/gr716a_mini/gr716a_mini.dts index 745caa64f671b..fb42de635a066 100644 --- a/boards/gaisler/gr716a_mini/gr716a_mini.dts +++ b/boards/gaisler/gr716a_mini/gr716a_mini.dts @@ -12,9 +12,7 @@ / { model = "GR716-MINI Development Board"; compatible = "gaisler,gr716a-mini"; - aliases { - spi-flash0 = &flash0; - }; + chosen { zephyr,console = &uart0; zephyr,shell-uart = &uart0; diff --git a/boards/gd/gd32a503v_eval/gd32a503v_eval.dts b/boards/gd/gd32a503v_eval/gd32a503v_eval.dts index dc6e0325452be..41fd7b2d75d97 100644 --- a/boards/gd/gd32a503v_eval/gd32a503v_eval.dts +++ b/boards/gd/gd32a503v_eval/gd32a503v_eval.dts @@ -35,7 +35,6 @@ aliases { led0 = &led1; led1 = &led2; - spi-flash0 = &nor_flash; }; }; diff --git a/boards/gd/gd32f450i_eval/gd32f450i_eval.dts b/boards/gd/gd32f450i_eval/gd32f450i_eval.dts index 4e2f87c4015b8..4a9f9d4fb6a88 100644 --- a/boards/gd/gd32f450i_eval/gd32f450i_eval.dts +++ b/boards/gd/gd32f450i_eval/gd32f450i_eval.dts @@ -71,7 +71,6 @@ sw0 = &user_key; pwm-led0 = &pwm_led; eeprom-0 = &eeprom0; - spi-flash0 = &nor_flash; watchdog0 = &fwdgt; }; }; diff --git a/boards/gd/gd32f450z_eval/gd32f450z_eval.dts b/boards/gd/gd32f450z_eval/gd32f450z_eval.dts index c636a5647c7d0..f01fd488b4c3e 100644 --- a/boards/gd/gd32f450z_eval/gd32f450z_eval.dts +++ b/boards/gd/gd32f450z_eval/gd32f450z_eval.dts @@ -71,7 +71,6 @@ sw0 = &user_key; pwm-led0 = &pwm_led; eeprom-0 = &eeprom0; - spi-flash0 = &nor_flash; watchdog0 = &fwdgt; }; }; diff --git a/boards/gd/gd32f470i_eval/gd32f470i_eval.dts b/boards/gd/gd32f470i_eval/gd32f470i_eval.dts index 306d190b3d4a8..1bff660f1c6f6 100644 --- a/boards/gd/gd32f470i_eval/gd32f470i_eval.dts +++ b/boards/gd/gd32f470i_eval/gd32f470i_eval.dts @@ -71,7 +71,6 @@ sw0 = &user_key; pwm-led0 = &pwm_led; eeprom-0 = &eeprom0; - spi-flash0 = &nor_flash; watchdog0 = &fwdgt; }; }; diff --git a/boards/gd/gd32vf103v_eval/gd32vf103v_eval.dts b/boards/gd/gd32vf103v_eval/gd32vf103v_eval.dts index cea9c00b7e99e..bee944f7fdc9f 100644 --- a/boards/gd/gd32vf103v_eval/gd32vf103v_eval.dts +++ b/boards/gd/gd32vf103v_eval/gd32vf103v_eval.dts @@ -84,7 +84,6 @@ led1 = &led2; sw0 = &key_cet; pwm-led0 = &pwm_led; - spi-flash0 = &nor_flash; watchdog0 = &fwdgt; }; }; diff --git a/boards/makerdiary/nrf52840_mdk/nrf52840_mdk.dts b/boards/makerdiary/nrf52840_mdk/nrf52840_mdk.dts index 2439b0c2aca0b..e405794d79573 100644 --- a/boards/makerdiary/nrf52840_mdk/nrf52840_mdk.dts +++ b/boards/makerdiary/nrf52840_mdk/nrf52840_mdk.dts @@ -82,7 +82,6 @@ red-pwm-led = &pwm_led1_red; blue-pwm-led = &pwm_led2_blue; watchdog0 = &wdt0; - spi-flash0 = &mx25r64; }; }; diff --git a/boards/nordic/nrf52840dk/nrf52840dk_nrf52840.dts b/boards/nordic/nrf52840dk/nrf52840dk_nrf52840.dts index 60c3ecf55a127..2bcffc80b0ab9 100644 --- a/boards/nordic/nrf52840dk/nrf52840dk_nrf52840.dts +++ b/boards/nordic/nrf52840dk/nrf52840dk_nrf52840.dts @@ -131,7 +131,6 @@ mcuboot-button0 = &button0; mcuboot-led0 = &led0; watchdog0 = &wdt0; - spi-flash0 = &mx25r64; }; }; diff --git a/boards/nordic/nrf5340dk/nrf5340_cpuapp_common.dtsi b/boards/nordic/nrf5340dk/nrf5340_cpuapp_common.dtsi index 70ba32524500e..b32519dd02b13 100644 --- a/boards/nordic/nrf5340dk/nrf5340_cpuapp_common.dtsi +++ b/boards/nordic/nrf5340dk/nrf5340_cpuapp_common.dtsi @@ -133,7 +133,6 @@ mcuboot-button0 = &button0; mcuboot-led0 = &led0; watchdog0 = &wdt0; - spi-flash0 = &mx25r64; }; }; diff --git a/boards/nordic/nrf54l15pdk/nrf54l15_cpuapp_common.dtsi b/boards/nordic/nrf54l15pdk/nrf54l15_cpuapp_common.dtsi index 2fa2ec36428da..eb93c1fee9636 100644 --- a/boards/nordic/nrf54l15pdk/nrf54l15_cpuapp_common.dtsi +++ b/boards/nordic/nrf54l15pdk/nrf54l15_cpuapp_common.dtsi @@ -18,10 +18,6 @@ zephyr,flash = &cpuapp_rram; zephyr,ieee802154 = &ieee802154; }; - - aliases { - spi-flash0 = &mx25r64; - }; }; &cpuapp_sram { diff --git a/boards/nordic/nrf9131ek/nrf9131ek_nrf9131_common.dtsi b/boards/nordic/nrf9131ek/nrf9131ek_nrf9131_common.dtsi index 2c3b8481d2ae8..9b87986d6f440 100644 --- a/boards/nordic/nrf9131ek/nrf9131ek_nrf9131_common.dtsi +++ b/boards/nordic/nrf9131ek/nrf9131ek_nrf9131_common.dtsi @@ -67,7 +67,6 @@ mcuboot-button0 = &button0; mcuboot-led0 = &led0; watchdog0 = &wdt0; - spi-flash0 = &gd25wb256; }; }; diff --git a/boards/nordic/nrf9151dk/nrf9151dk_nrf9151_common.dtsi b/boards/nordic/nrf9151dk/nrf9151dk_nrf9151_common.dtsi index 958e864c63cdc..ad4b623cf8f82 100644 --- a/boards/nordic/nrf9151dk/nrf9151dk_nrf9151_common.dtsi +++ b/boards/nordic/nrf9151dk/nrf9151dk_nrf9151_common.dtsi @@ -128,7 +128,6 @@ mcuboot-button0 = &button0; mcuboot-led0 = &led0; watchdog0 = &wdt0; - spi-flash0 = &gd25wb256; }; }; diff --git a/boards/nordic/nrf9160dk/nrf9160dk_nrf9160_common_0_14_0.dtsi b/boards/nordic/nrf9160dk/nrf9160dk_nrf9160_common_0_14_0.dtsi index ee4f736bf8b76..896531d75808f 100644 --- a/boards/nordic/nrf9160dk/nrf9160dk_nrf9160_common_0_14_0.dtsi +++ b/boards/nordic/nrf9160dk/nrf9160dk_nrf9160_common_0_14_0.dtsi @@ -4,12 +4,6 @@ * SPDX-License-Identifier: Apache-2.0 */ -/ { - aliases { - spi-flash0 = &mx25r64; - }; -}; - &interface_to_nrf52840 { gpio-map = <0 0 &gpio0 17 0>, <1 0 &gpio0 18 0>, diff --git a/boards/nordic/nrf9161dk/nrf9161dk_nrf9161_common.dtsi b/boards/nordic/nrf9161dk/nrf9161dk_nrf9161_common.dtsi index 8168a8317e417..93c9c140c6a6f 100644 --- a/boards/nordic/nrf9161dk/nrf9161dk_nrf9161_common.dtsi +++ b/boards/nordic/nrf9161dk/nrf9161dk_nrf9161_common.dtsi @@ -128,7 +128,6 @@ mcuboot-button0 = &button0; mcuboot-led0 = &led0; watchdog0 = &wdt0; - spi-flash0 = &gd25wb256; }; }; diff --git a/boards/nordic/nrf9161dk/nrf9161dk_nrf9161_common_0_7_0.dtsi b/boards/nordic/nrf9161dk/nrf9161dk_nrf9161_common_0_7_0.dtsi index ae67df77b2244..5336ca3ba0667 100644 --- a/boards/nordic/nrf9161dk/nrf9161dk_nrf9161_common_0_7_0.dtsi +++ b/boards/nordic/nrf9161dk/nrf9161dk_nrf9161_common_0_7_0.dtsi @@ -23,9 +23,3 @@ t-exit-dpd = <30000>; }; }; - -/ { - aliases { - spi-flash0 = &gd25lb256; - }; -}; diff --git a/boards/nuvoton/npcx4m8f_evb/npcx4m8f_evb.dts b/boards/nuvoton/npcx4m8f_evb/npcx4m8f_evb.dts index b90d94b0c9e93..2993b816956d3 100644 --- a/boards/nuvoton/npcx4m8f_evb/npcx4m8f_evb.dts +++ b/boards/nuvoton/npcx4m8f_evb/npcx4m8f_evb.dts @@ -26,7 +26,6 @@ i2c-0 = &i2c0_0; watchdog0 = &twd0; peci-0 = &peci0; - spi-flash0 = &int_flash; kscan0 = &kscan_input; }; diff --git a/boards/nuvoton/npcx7m6fb_evb/npcx7m6fb_evb.dts b/boards/nuvoton/npcx7m6fb_evb/npcx7m6fb_evb.dts index a1c6d72403be6..34a8cc9de74d5 100644 --- a/boards/nuvoton/npcx7m6fb_evb/npcx7m6fb_evb.dts +++ b/boards/nuvoton/npcx7m6fb_evb/npcx7m6fb_evb.dts @@ -28,8 +28,6 @@ i2c-0 = &i2c0_0; watchdog0 = &twd0; peci-0 = &peci0; - /* For samples/drivers/spi_flash */ - spi-flash0 = &int_flash; /* For kscan test suites */ kscan0 = &kscan_input; }; diff --git a/boards/nuvoton/npcx9m6f_evb/npcx9m6f_evb.dts b/boards/nuvoton/npcx9m6f_evb/npcx9m6f_evb.dts index 841883cc38c22..fe186dca26207 100644 --- a/boards/nuvoton/npcx9m6f_evb/npcx9m6f_evb.dts +++ b/boards/nuvoton/npcx9m6f_evb/npcx9m6f_evb.dts @@ -31,8 +31,6 @@ /* For watchdog sample */ watchdog0 = &twd0; peci-0 = &peci0; - /* For samples/drivers/spi_flash */ - spi-flash0 = &int_flash; /* For kscan test suites */ kscan0 = &kscan_input; }; diff --git a/boards/nxp/frdm_k82f/frdm_k82f.dts b/boards/nxp/frdm_k82f/frdm_k82f.dts index 44b88975f4d71..e649cb2fa24ab 100644 --- a/boards/nxp/frdm_k82f/frdm_k82f.dts +++ b/boards/nxp/frdm_k82f/frdm_k82f.dts @@ -27,7 +27,6 @@ sw1 = &user_button_1; magn0 = &fxos8700; accel0 = &fxos8700; - spi-flash0 = &mx25u32; }; chosen { diff --git a/boards/openisa/rv32m1_vega/rv32m1_vega_openisa_rv32m1_ri5cy.dts b/boards/openisa/rv32m1_vega/rv32m1_vega_openisa_rv32m1_ri5cy.dts index b21e9b960ec1a..c985318455360 100644 --- a/boards/openisa/rv32m1_vega/rv32m1_vega_openisa_rv32m1_ri5cy.dts +++ b/boards/openisa/rv32m1_vega/rv32m1_vega_openisa_rv32m1_ri5cy.dts @@ -20,10 +20,6 @@ zephyr,uart-pipe = &lpuart0; zephyr,code-partition = &slot0_partition; }; - - aliases { - spi-flash0 = &mx25r32; - }; }; &m4_flash { diff --git a/boards/others/black_f407ve/black_f407ve.dts b/boards/others/black_f407ve/black_f407ve.dts index 539f9838fbf4b..2411e0e5a945c 100644 --- a/boards/others/black_f407ve/black_f407ve.dts +++ b/boards/others/black_f407ve/black_f407ve.dts @@ -57,7 +57,6 @@ led0 = &green_led_1; led1 = &green_led_2; sw0 = &user_button_UP; - spi-flash0 = &w25q16cv; }; }; diff --git a/boards/panasonic/pan1783/pan1783_nrf5340_cpuapp_common.dtsi b/boards/panasonic/pan1783/pan1783_nrf5340_cpuapp_common.dtsi index fae7f566fccfe..8fd97ed8ce26e 100644 --- a/boards/panasonic/pan1783/pan1783_nrf5340_cpuapp_common.dtsi +++ b/boards/panasonic/pan1783/pan1783_nrf5340_cpuapp_common.dtsi @@ -156,7 +156,6 @@ mcuboot-button0 = &evb_sw1; mcuboot-led0 = &evb_led1; watchdog0 = &wdt0; - spi-flash0 = &mx25r64; }; }; diff --git a/boards/particle/argon/dts/mesh_feather.dtsi b/boards/particle/argon/dts/mesh_feather.dtsi index ee3c4340d5bbc..889fc75f83517 100644 --- a/boards/particle/argon/dts/mesh_feather.dtsi +++ b/boards/particle/argon/dts/mesh_feather.dtsi @@ -20,7 +20,6 @@ led3 = &status_blue; sw0 = &mode_button; sw1 = &reset_button; - spi-flash0 = &mx25l32; }; chosen { diff --git a/boards/particle/boron/dts/mesh_feather.dtsi b/boards/particle/boron/dts/mesh_feather.dtsi index 0005ca547ff26..13b7e238230db 100644 --- a/boards/particle/boron/dts/mesh_feather.dtsi +++ b/boards/particle/boron/dts/mesh_feather.dtsi @@ -20,7 +20,6 @@ led3 = &status_blue; sw0 = &mode_button; sw1 = &reset_button; - spi-flash0 = &mx25l32; }; chosen { diff --git a/boards/particle/xenon/particle_xenon.dts b/boards/particle/xenon/particle_xenon.dts index 2d64ba119b299..c297014ff363f 100644 --- a/boards/particle/xenon/particle_xenon.dts +++ b/boards/particle/xenon/particle_xenon.dts @@ -29,7 +29,6 @@ aliases { watchdog0 = &wdt0; - spi-flash0 = &mx25l32; }; }; diff --git a/boards/seagate/legend/legend.dts b/boards/seagate/legend/legend.dts index 245d2c8de7da9..d230345dd0794 100644 --- a/boards/seagate/legend/legend.dts +++ b/boards/seagate/legend/legend.dts @@ -21,7 +21,6 @@ aliases { watchdog0 = &iwdg; - spi-flash0 = &spi_nor; led-strip = &led_strip_spi; }; diff --git a/boards/seeed/xiao_ble/xiao_ble_common.dtsi b/boards/seeed/xiao_ble/xiao_ble_common.dtsi index d031ce4b5b3d4..8ce71198e176e 100644 --- a/boards/seeed/xiao_ble/xiao_ble_common.dtsi +++ b/boards/seeed/xiao_ble/xiao_ble_common.dtsi @@ -54,7 +54,6 @@ bootloader-led0 = &led0; mcuboot-led0 = &led0; watchdog0 = &wdt0; - spi-flash0 = &p25q16h; }; }; diff --git a/boards/silabs/efr32_radio/efr32_radio.dtsi b/boards/silabs/efr32_radio/efr32_radio.dtsi index 361b66b72df38..b70e1419fbc4a 100644 --- a/boards/silabs/efr32_radio/efr32_radio.dtsi +++ b/boards/silabs/efr32_radio/efr32_radio.dtsi @@ -23,7 +23,6 @@ sw0 = &button0; sw1 = &button1; watchdog0 = &wdog0; - spi-flash0 = &mx25r80; }; leds { diff --git a/boards/silabs/efr32_radio/efr32_radio_efr32bg13p632f512gm48.dts b/boards/silabs/efr32_radio/efr32_radio_efr32bg13p632f512gm48.dts index 9ded71ef5598a..4dde0cfd1ce28 100644 --- a/boards/silabs/efr32_radio/efr32_radio_efr32bg13p632f512gm48.dts +++ b/boards/silabs/efr32_radio/efr32_radio_efr32bg13p632f512gm48.dts @@ -11,10 +11,6 @@ / { model = "Silicon Labs BRD4104A (Blue Gecko Radio Board)"; compatible = "silabs,efr32_radio_brd4104a", "silabs,efr32bg13p"; - - aliases { - spi-flash0 = &mx25r80; - }; }; &cpu0 { diff --git a/boards/silabs/efr32_radio/efr32_radio_efr32fg1p133f256gm48.dts b/boards/silabs/efr32_radio/efr32_radio_efr32fg1p133f256gm48.dts index 2167b1b69b786..885537593d148 100644 --- a/boards/silabs/efr32_radio/efr32_radio_efr32fg1p133f256gm48.dts +++ b/boards/silabs/efr32_radio/efr32_radio_efr32fg1p133f256gm48.dts @@ -23,7 +23,6 @@ aliases { pwm-led0 = &pwm_led0; - spi-flash0 = &mx25r80; }; }; diff --git a/boards/silabs/efr32_radio/efr32_radio_efr32mg12p432f1024gl125.dts b/boards/silabs/efr32_radio/efr32_radio_efr32mg12p432f1024gl125.dts index 64b9dce560dd8..fd2baf0e87a01 100644 --- a/boards/silabs/efr32_radio/efr32_radio_efr32mg12p432f1024gl125.dts +++ b/boards/silabs/efr32_radio/efr32_radio_efr32mg12p432f1024gl125.dts @@ -11,10 +11,6 @@ / { model = "Silicon Labs BRD4161A (Mighty Gecko Radio Board)"; compatible = "silabs,efr32_radio_brd4161a", "silabs,efr32mg12p"; - - aliases { - spi-flash0 = &mx25r80; - }; }; &cpu0 { diff --git a/boards/silabs/efr32_radio/efr32_radio_efr32mg12p433f1024gm68.dts b/boards/silabs/efr32_radio/efr32_radio_efr32mg12p433f1024gm68.dts index effd66a8515b9..2aabcf7fafff6 100644 --- a/boards/silabs/efr32_radio/efr32_radio_efr32mg12p433f1024gm68.dts +++ b/boards/silabs/efr32_radio/efr32_radio_efr32mg12p433f1024gm68.dts @@ -11,10 +11,6 @@ / { model = "Silicon Labs BRD4170A (Mighty Gecko Radio Board)"; compatible = "silabs,efr32_radio_brd4170a", "silabs,efr32mg12p"; - - aliases { - spi-flash0 = &mx25r80; - }; }; &cpu0 { diff --git a/boards/silabs/efr32_thunderboard/efr32bg22_brd4184.dtsi b/boards/silabs/efr32_thunderboard/efr32bg22_brd4184.dtsi index 7badab451585f..13576e3f295a8 100644 --- a/boards/silabs/efr32_thunderboard/efr32bg22_brd4184.dtsi +++ b/boards/silabs/efr32_thunderboard/efr32bg22_brd4184.dtsi @@ -11,7 +11,6 @@ aliases { led0 = &led0; sw0 = &button0; - spi-flash0 = &mx25r80; spi0 = &usart0; watchdog0 = &wdog0; /* If enabled, MCUboot uses this for recovery mode entrance */ diff --git a/boards/silabs/efr32_thunderboard/efr32bg27_brd2602a.dts b/boards/silabs/efr32_thunderboard/efr32bg27_brd2602a.dts index b267cd8356bad..beb019ca0b11a 100644 --- a/boards/silabs/efr32_thunderboard/efr32bg27_brd2602a.dts +++ b/boards/silabs/efr32_thunderboard/efr32bg27_brd2602a.dts @@ -18,7 +18,6 @@ aliases { led0 = &led0; sw0 = &button0; - spi-flash0 = &mx25r80; spi0 = &usart0; watchdog0 = &wdog0; /* If enabled, MCUboot uses this for recovery mode entrance */ diff --git a/boards/silabs/efr32mg_sltb004a/efr32mg_sltb004a.dts b/boards/silabs/efr32mg_sltb004a/efr32mg_sltb004a.dts index 3819bd6ca94cf..375fe50556b1b 100644 --- a/boards/silabs/efr32mg_sltb004a/efr32mg_sltb004a.dts +++ b/boards/silabs/efr32mg_sltb004a/efr32mg_sltb004a.dts @@ -22,7 +22,6 @@ sw1 = &button1; watchdog0 = &wdog0; watchdog1 = &wdog1; - spi-flash0 = &mx25r80; }; chosen { diff --git a/boards/snps/em_starterkit/em_starterkit_emsk_em7d_2_3.overlay b/boards/snps/em_starterkit/em_starterkit_emsk_em7d_2_3.overlay index bb7e6a3ee9bd7..590d0aefb8a8c 100644 --- a/boards/snps/em_starterkit/em_starterkit_emsk_em7d_2_3.overlay +++ b/boards/snps/em_starterkit/em_starterkit_emsk_em7d_2_3.overlay @@ -19,7 +19,6 @@ uart-0 = &uart0; uart-1 = &uart1; uart-2 = &uart2; - spi-flash0 = &w25q128bv; }; chosen { diff --git a/boards/snps/em_starterkit/em_starterkit_r23.dtsi b/boards/snps/em_starterkit/em_starterkit_r23.dtsi index 3de7425d97501..ef93abcfd46d3 100644 --- a/boards/snps/em_starterkit/em_starterkit_r23.dtsi +++ b/boards/snps/em_starterkit/em_starterkit_r23.dtsi @@ -5,10 +5,6 @@ */ / { - aliases { - spi-flash0 = &w25q128bv; - }; - soc { i2c@f0004000 { interrupts = <25 1>; diff --git a/boards/snps/emsdp/emsdp_emsdp_em11d.dts b/boards/snps/emsdp/emsdp_emsdp_em11d.dts index 6a24a9ec5bd6f..d3a9a10d0e73a 100644 --- a/boards/snps/emsdp/emsdp_emsdp_em11d.dts +++ b/boards/snps/emsdp/emsdp_emsdp_em11d.dts @@ -17,7 +17,6 @@ aliases { uart-0 = &uart0; - spi-flash0 = &s25fl256s; }; chosen { diff --git a/boards/snps/emsdp/emsdp_emsdp_em4.dts b/boards/snps/emsdp/emsdp_emsdp_em4.dts index 0d0306065c09d..04414f10c6e64 100644 --- a/boards/snps/emsdp/emsdp_emsdp_em4.dts +++ b/boards/snps/emsdp/emsdp_emsdp_em4.dts @@ -15,7 +15,6 @@ aliases { uart-0 = &uart0; - spi-flash0 = &s25fl256s; }; chosen { diff --git a/boards/snps/emsdp/emsdp_emsdp_em5d.dts b/boards/snps/emsdp/emsdp_emsdp_em5d.dts index 66a544e95ef76..57ba196e1dde3 100644 --- a/boards/snps/emsdp/emsdp_emsdp_em5d.dts +++ b/boards/snps/emsdp/emsdp_emsdp_em5d.dts @@ -15,7 +15,6 @@ aliases { uart-0 = &uart0; - spi-flash0 = &s25fl256s; }; chosen { diff --git a/boards/snps/emsdp/emsdp_emsdp_em6.dts b/boards/snps/emsdp/emsdp_emsdp_em6.dts index 0d0306065c09d..04414f10c6e64 100644 --- a/boards/snps/emsdp/emsdp_emsdp_em6.dts +++ b/boards/snps/emsdp/emsdp_emsdp_em6.dts @@ -15,7 +15,6 @@ aliases { uart-0 = &uart0; - spi-flash0 = &s25fl256s; }; chosen { diff --git a/boards/snps/emsdp/emsdp_emsdp_em7d.dts b/boards/snps/emsdp/emsdp_emsdp_em7d.dts index 66a544e95ef76..57ba196e1dde3 100644 --- a/boards/snps/emsdp/emsdp_emsdp_em7d.dts +++ b/boards/snps/emsdp/emsdp_emsdp_em7d.dts @@ -15,7 +15,6 @@ aliases { uart-0 = &uart0; - spi-flash0 = &s25fl256s; }; chosen { diff --git a/boards/snps/emsdp/emsdp_emsdp_em7d_esp.dts b/boards/snps/emsdp/emsdp_emsdp_em7d_esp.dts index 89fc30499b7fb..1880de517b964 100644 --- a/boards/snps/emsdp/emsdp_emsdp_em7d_esp.dts +++ b/boards/snps/emsdp/emsdp_emsdp_em7d_esp.dts @@ -15,7 +15,6 @@ aliases { uart-0 = &uart0; - spi-flash0 = &s25fl256s; }; chosen { diff --git a/boards/snps/emsdp/emsdp_emsdp_em9d.dts b/boards/snps/emsdp/emsdp_emsdp_em9d.dts index c28956b9f6002..c87bfe3e7f6a8 100644 --- a/boards/snps/emsdp/emsdp_emsdp_em9d.dts +++ b/boards/snps/emsdp/emsdp_emsdp_em9d.dts @@ -16,7 +16,6 @@ aliases { uart-0 = &uart0; - spi-flash0 = &s25fl256s; }; chosen { diff --git a/boards/st/b_l4s5i_iot01a/b_l4s5i_iot01a.dts b/boards/st/b_l4s5i_iot01a/b_l4s5i_iot01a.dts index 531c5a5b20d93..7f2863f78f4be 100644 --- a/boards/st/b_l4s5i_iot01a/b_l4s5i_iot01a.dts +++ b/boards/st/b_l4s5i_iot01a/b_l4s5i_iot01a.dts @@ -50,7 +50,6 @@ sw0 = &user_button; watchdog0 = &iwdg; accel0 = &lsm6dsl; - spi-flash0 = &mx25r6435f; }; }; 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 97fe4e0be57b7..b3227455f6fc4 100644 --- a/boards/st/b_u585i_iot02a/b_u585i_iot02a-common.dtsi +++ b/boards/st/b_u585i_iot02a/b_u585i_iot02a-common.dtsi @@ -35,7 +35,6 @@ aliases { watchdog0 = &iwdg; - spi-flash0 = &mx25lm51245; die-temp0 = &die_temp; volt-sensor0 = &vref1; volt-sensor1 = &vbat4; diff --git a/boards/st/disco_l475_iot1/disco_l475_iot1.dts b/boards/st/disco_l475_iot1/disco_l475_iot1.dts index 572e8768c9e01..26276225d2044 100644 --- a/boards/st/disco_l475_iot1/disco_l475_iot1.dts +++ b/boards/st/disco_l475_iot1/disco_l475_iot1.dts @@ -67,7 +67,6 @@ sw0 = &user_button; eswifi0 = &wifi0; watchdog0 = &iwdg; - spi-flash0 = &mx25r6435f; accel0 = &lsm6dsl; volt-sensor0 = &vref; volt-sensor1 = &vbat; diff --git a/boards/st/stm32f723e_disco/stm32f723e_disco.dts b/boards/st/stm32f723e_disco/stm32f723e_disco.dts index 4c6641c7f2c75..a9ca03675df18 100644 --- a/boards/st/stm32f723e_disco/stm32f723e_disco.dts +++ b/boards/st/stm32f723e_disco/stm32f723e_disco.dts @@ -52,7 +52,6 @@ led1 = &red_led; led2 = &green_led; sw0 = &user_button; - spi-flash0 = &mx25r512; }; }; diff --git a/boards/st/stm32f746g_disco/stm32f746g_disco.dts b/boards/st/stm32f746g_disco/stm32f746g_disco.dts index 6250c4e8e80d8..2c31fef1c92c4 100644 --- a/boards/st/stm32f746g_disco/stm32f746g_disco.dts +++ b/boards/st/stm32f746g_disco/stm32f746g_disco.dts @@ -59,7 +59,6 @@ aliases { led0 = &green_led_1; sw0 = &user_button; - spi-flash0 = &n25q128a1; }; }; diff --git a/boards/st/stm32f7508_dk/stm32f7508_dk.dts b/boards/st/stm32f7508_dk/stm32f7508_dk.dts index b98cf5aeed9e4..100fd6e661d9b 100644 --- a/boards/st/stm32f7508_dk/stm32f7508_dk.dts +++ b/boards/st/stm32f7508_dk/stm32f7508_dk.dts @@ -59,7 +59,6 @@ aliases { led0 = &green_led_1; sw0 = &user_button; - spi-flash0 = &n25q128a1; }; }; diff --git a/boards/st/stm32f769i_disco/stm32f769i_disco.dts b/boards/st/stm32f769i_disco/stm32f769i_disco.dts index 03ff90c729baa..9ad4f4ef3bc57 100644 --- a/boards/st/stm32f769i_disco/stm32f769i_disco.dts +++ b/boards/st/stm32f769i_disco/stm32f769i_disco.dts @@ -77,7 +77,6 @@ led2 = &green_led_3; led3 = &red_led_4; sw0 = &user_button; - spi-flash0 = &mx25l51245g; }; quadspi_memory_avail: memory-avail@90000000 { diff --git a/boards/st/stm32h573i_dk/stm32h573i_dk.dts b/boards/st/stm32h573i_dk/stm32h573i_dk.dts index 721cea3ab6aeb..a02d042e25d4c 100644 --- a/boards/st/stm32h573i_dk/stm32h573i_dk.dts +++ b/boards/st/stm32h573i_dk/stm32h573i_dk.dts @@ -56,7 +56,6 @@ led0 = &blue_led_0; sw0 = &user_button; watchdog0 = &iwdg; - spi-flash0 = &mx25lm51245; die-temp0 = &die_temp; volt-sensor0 = &vref; volt-sensor1 = &vbat; diff --git a/boards/st/stm32h747i_disco/stm32h747i_disco_stm32h747xx_m7.dts b/boards/st/stm32h747i_disco/stm32h747i_disco_stm32h747xx_m7.dts index a660f92af1772..1dd5acda5223b 100644 --- a/boards/st/stm32h747i_disco/stm32h747i_disco_stm32h747xx_m7.dts +++ b/boards/st/stm32h747i_disco/stm32h747i_disco_stm32h747xx_m7.dts @@ -55,7 +55,6 @@ led0 = &green_led_1; led1 = &orange_led_2; sw0 = &wake_up; - spi-flash0 = &mt25ql512ab1; }; }; diff --git a/boards/st/stm32h750b_dk/stm32h750b_dk.dts b/boards/st/stm32h750b_dk/stm32h750b_dk.dts index bb90724deadcb..d8eb6bfcf90bd 100644 --- a/boards/st/stm32h750b_dk/stm32h750b_dk.dts +++ b/boards/st/stm32h750b_dk/stm32h750b_dk.dts @@ -54,7 +54,6 @@ led0 = &green_led; led1 = &red_led; sw0 = &user_button; - spi-flash0 = &mt25ql512ab1; }; }; diff --git a/boards/st/stm32h7b3i_dk/stm32h7b3i_dk.dts b/boards/st/stm32h7b3i_dk/stm32h7b3i_dk.dts index f05809f523ba5..95325e254b557 100644 --- a/boards/st/stm32h7b3i_dk/stm32h7b3i_dk.dts +++ b/boards/st/stm32h7b3i_dk/stm32h7b3i_dk.dts @@ -78,7 +78,6 @@ led0 = &blue_led; led1 = &red_led; sw0 = &user_button; - spi-flash0 = &mx25lm51245; }; }; diff --git a/boards/st/stm32l496g_disco/stm32l496g_disco.dts b/boards/st/stm32l496g_disco/stm32l496g_disco.dts index e2a70f6163d52..a6d1e876f4e81 100644 --- a/boards/st/stm32l496g_disco/stm32l496g_disco.dts +++ b/boards/st/stm32l496g_disco/stm32l496g_disco.dts @@ -68,7 +68,6 @@ sw4 = &joy_left; volt-sensor0 = &vref; volt-sensor1 = &vbat; - spi-flash0 = &mx25r6435; }; }; diff --git a/boards/st/stm32l4r9i_disco/stm32l4r9i_disco.dts b/boards/st/stm32l4r9i_disco/stm32l4r9i_disco.dts index 3d54fbc3cdf62..49737c68c8f56 100644 --- a/boards/st/stm32l4r9i_disco/stm32l4r9i_disco.dts +++ b/boards/st/stm32l4r9i_disco/stm32l4r9i_disco.dts @@ -44,7 +44,6 @@ die-temp0 = &die_temp; volt-sensor0 = &vref; volt-sensor1 = &vbat; - spi-flash0 = &mx25lm51245; }; }; diff --git a/boards/st/stm32l562e_dk/stm32l562e_dk_common.dtsi b/boards/st/stm32l562e_dk/stm32l562e_dk_common.dtsi index ccd74b46ece55..cd798b72d03db 100644 --- a/boards/st/stm32l562e_dk/stm32l562e_dk_common.dtsi +++ b/boards/st/stm32l562e_dk/stm32l562e_dk_common.dtsi @@ -32,7 +32,6 @@ }; aliases { - spi-flash0 = &mx25lm51245; die-temp0 = &die_temp; volt-sensor0 = &vref; volt-sensor1 = &vbat; diff --git a/boards/u-blox/ubx_bmd340eval/ubx_bmd340eval_nrf52840.dts b/boards/u-blox/ubx_bmd340eval/ubx_bmd340eval_nrf52840.dts index d06986a8afa29..070730c69d2c5 100644 --- a/boards/u-blox/ubx_bmd340eval/ubx_bmd340eval_nrf52840.dts +++ b/boards/u-blox/ubx_bmd340eval/ubx_bmd340eval_nrf52840.dts @@ -129,7 +129,6 @@ sw2 = &button2; sw3 = &button3; watchdog0 = &wdt0; - spi-flash0 = &mx25r64; }; }; diff --git a/boards/u-blox/ubx_bmd345eval/ubx_bmd345eval_nrf52840.dts b/boards/u-blox/ubx_bmd345eval/ubx_bmd345eval_nrf52840.dts index ef145eabe5408..68b3755123b28 100644 --- a/boards/u-blox/ubx_bmd345eval/ubx_bmd345eval_nrf52840.dts +++ b/boards/u-blox/ubx_bmd345eval/ubx_bmd345eval_nrf52840.dts @@ -141,7 +141,6 @@ mcuboot-button0 = &button0; mcuboot-led0 = &led0; watchdog0 = &wdt0; - spi-flash0 = &mx25r64; }; }; diff --git a/boards/u-blox/ubx_bmd380eval/ubx_bmd380eval_nrf52840.dts b/boards/u-blox/ubx_bmd380eval/ubx_bmd380eval_nrf52840.dts index 404678ad95299..d7a21c98b444e 100644 --- a/boards/u-blox/ubx_bmd380eval/ubx_bmd380eval_nrf52840.dts +++ b/boards/u-blox/ubx_bmd380eval/ubx_bmd380eval_nrf52840.dts @@ -90,7 +90,6 @@ sw2 = &button2; sw3 = &button3; watchdog0 = &wdt0; - spi-flash0 = &mx25r64; }; }; diff --git a/boards/weact/mini_stm32h743/mini_stm32h743.dts b/boards/weact/mini_stm32h743/mini_stm32h743.dts index 3a6c1a055ca22..9968b82d7d7b4 100644 --- a/boards/weact/mini_stm32h743/mini_stm32h743.dts +++ b/boards/weact/mini_stm32h743/mini_stm32h743.dts @@ -80,7 +80,6 @@ aliases { led0 = &user_led; sw0 = &user_button; - spi-flash0 = &w25q64_spi; watchdog0 = &iwdg; sdhc0 = &sdmmc1; }; diff --git a/samples/drivers/spi_flash/boards/adp_xc7k_ae350.overlay b/samples/drivers/spi_flash/boards/adp_xc7k_ae350.overlay deleted file mode 100644 index 653722098eacb..0000000000000 --- a/samples/drivers/spi_flash/boards/adp_xc7k_ae350.overlay +++ /dev/null @@ -1,11 +0,0 @@ -/* - * Copyright (c) 2023 Andes Technology Corporation - * - * SPDX-License-Identifier: Apache-2.0 - */ - -/ { - aliases { - spi-flash0 = &mx25u16; - }; -}; diff --git a/samples/drivers/spi_flash/boards/mec172xevb_assy6906.overlay b/samples/drivers/spi_flash/boards/mec172xevb_assy6906.overlay index f9fdc2e53680a..54f2957791cc3 100644 --- a/samples/drivers/spi_flash/boards/mec172xevb_assy6906.overlay +++ b/samples/drivers/spi_flash/boards/mec172xevb_assy6906.overlay @@ -4,12 +4,6 @@ * SPDX-License-Identifier: Apache-2.0 */ -/ { - aliases { - spi-flash0 = &spi1_cs0_flash; - }; -}; - &spi0 { status = "okay"; compatible = "microchip,xec-qmspi-ldma"; diff --git a/tests/drivers/flash/common/boards/nrf52840dk_mx25l51245g.overlay b/tests/drivers/flash/common/boards/nrf52840dk_mx25l51245g.overlay index 1b39dd94d1e84..737723307913c 100644 --- a/tests/drivers/flash/common/boards/nrf52840dk_mx25l51245g.overlay +++ b/tests/drivers/flash/common/boards/nrf52840dk_mx25l51245g.overlay @@ -4,12 +4,6 @@ * SPDX-License-Identifier: Apache-2.0 */ -/ { - aliases { - spi-flash0 = &mx25l51; - }; -}; - /delete-node/ &mx25r64; &pinctrl { diff --git a/tests/drivers/flash/common/boards/nrf52840dk_mx25r_high_perf.overlay b/tests/drivers/flash/common/boards/nrf52840dk_mx25r_high_perf.overlay index a67f25e46c08b..7e0d89cd92e71 100644 --- a/tests/drivers/flash/common/boards/nrf52840dk_mx25r_high_perf.overlay +++ b/tests/drivers/flash/common/boards/nrf52840dk_mx25r_high_perf.overlay @@ -27,9 +27,3 @@ mxicy,mx25r-power-mode = "high-performance"; }; }; - -/ { - aliases { - spi-flash0 = &mx25r64; - }; -}; diff --git a/tests/drivers/flash/common/boards/nrf52840dk_spi_nor.overlay b/tests/drivers/flash/common/boards/nrf52840dk_spi_nor.overlay index 1042b429ee378..922ab42beb47f 100644 --- a/tests/drivers/flash/common/boards/nrf52840dk_spi_nor.overlay +++ b/tests/drivers/flash/common/boards/nrf52840dk_spi_nor.overlay @@ -6,12 +6,6 @@ * Build test for jedec,spi-nor compatible (drivers/flash/spi_nor.c) */ -/ { - aliases { - spi-flash0 = &mx25v1635fzui; - }; -}; - /delete-node/ &mx25r64; &pinctrl { diff --git a/tests/drivers/flash/common/boards/nrf52840dk_spi_nor_wp_hold.overlay b/tests/drivers/flash/common/boards/nrf52840dk_spi_nor_wp_hold.overlay index f17febff6c305..c4bcbf280baa8 100644 --- a/tests/drivers/flash/common/boards/nrf52840dk_spi_nor_wp_hold.overlay +++ b/tests/drivers/flash/common/boards/nrf52840dk_spi_nor_wp_hold.overlay @@ -6,12 +6,6 @@ * Build test for jedec,spi-nor compatible (drivers/flash/spi_nor.c) wp-gpios and hold-gpios */ -/ { - aliases { - spi-flash0 = &mx25v1635fzui; - }; -}; - /delete-node/ &mx25r64; &pinctrl { From 16e7e46478f792980853cdd69f8aea3ae0d393bd Mon Sep 17 00:00:00 2001 From: Karsten Koenig Date: Thu, 23 May 2024 10:39:48 +0200 Subject: [PATCH 1941/2849] soc: nordic: nrf54h: Retrigger TASK_FREQ_CHANGE A single trigger of the TASK_FREQ_CHANGE task might not be enough, so trigger twice to make sure the frequency gets updated. Signed-off-by: Karsten Koenig --- soc/nordic/nrf54h/soc.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/soc/nordic/nrf54h/soc.c b/soc/nordic/nrf54h/soc.c index ce5af2e25af90..bc79cffed40dd 100644 --- a/soc/nordic/nrf54h/soc.c +++ b/soc/nordic/nrf54h/soc.c @@ -73,6 +73,8 @@ static int trim_hsfll(void) DT_PROP(DT_CLOCKS_CTLR(HSFLL_NODE), clock_frequency)); nrf_hsfll_trim_set(hsfll, &trim); + nrf_hsfll_task_trigger(hsfll, NRF_HSFLL_TASK_FREQ_CHANGE); + /* HSFLL task frequency change needs to be triggered twice to take effect.*/ nrf_hsfll_task_trigger(hsfll, NRF_HSFLL_TASK_FREQ_CHANGE); LOG_DBG("NRF_HSFLL->TRIM.VSUP = %d", hsfll->TRIM.VSUP); From 4fe57de7dfb3f3d70fd53a5804fe672f1564240c Mon Sep 17 00:00:00 2001 From: Francois Ramu Date: Mon, 13 May 2024 14:35:03 +0200 Subject: [PATCH 1942/2849] bindings: qspi: stm32 qspi supporting Dual Flash Mode Configure the quad-spi in DualFlash Mode This property of the stm32 boards will access simultaneously two identical quad-flash external memories connected to 2 quad-spi banks (pins). Dual Flash Mode is possible on stm32 series with QUADSPI_CR_DFM Signed-off-by: Francois Ramu --- dts/bindings/qspi/st,stm32-qspi.yaml | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/dts/bindings/qspi/st,stm32-qspi.yaml b/dts/bindings/qspi/st,stm32-qspi.yaml index 04aa6e4d02083..f656bd90586ef 100644 --- a/dts/bindings/qspi/st,stm32-qspi.yaml +++ b/dts/bindings/qspi/st,stm32-qspi.yaml @@ -59,12 +59,22 @@ properties: For example dma-names = "tx_rx"; + dual-flash: + type: boolean + description: | + configuration to enable the dual flash mode of the QSPI peripheral + where two external quad SPI Flash memories (FLASH 1 and FLASH 2) are used + in order to send/receive 8 bits (or 16 bits in DDR mode) every cycle, + effectively doubling the throughput as well as the capacity. + When true, the Flash ID number is useless. + flash-id: type: int description: | - FLash ID number. This number, if defined, helps to select the right - QSPI GPIO banks (defined as 'quadspi_bk[12]' in pinctrl property) + Flash ID number. This number, if defined, helps to select the right + QSPI GPIO banks (defined as 'quadspi_bk[1/2]' in pinctrl property) to communicate with flash memory. + Valid only if the is not set. For example flash-id = <2>; From f6a9e0aef2d428ee17da25b3ce7e6247a6160038 Mon Sep 17 00:00:00 2001 From: Francois Ramu Date: Thu, 1 Feb 2024 10:16:10 +0100 Subject: [PATCH 1943/2849] drivers: flash: stm32 qspi driver in Dual Flash Mode when MemoryMapped Configure the quad-spi in DualFlash Mode when enabling the MemoryMapped then reading is possible with memcopy. DUAL flash mode is possible on stm32 series with QUADSPI_CR_DFM Signed-off-by: Francois Ramu --- drivers/flash/flash_stm32_qspi.c | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/drivers/flash/flash_stm32_qspi.c b/drivers/flash/flash_stm32_qspi.c index adec32e8e4e6f..95372307b2ce8 100644 --- a/drivers/flash/flash_stm32_qspi.c +++ b/drivers/flash/flash_stm32_qspi.c @@ -35,7 +35,7 @@ #define STM32_QSPI_BASE_ADDRESS DT_INST_REG_ADDR(0) #define STM32_QSPI_RESET_GPIO DT_INST_NODE_HAS_PROP(0, reset_gpios) -#define STM32_QSPI_RESET_CMD DT_INST_NODE_HAS_PROP(0, reset_cmd) +#define STM32_QSPI_RESET_CMD DT_PROP(DT_NODELABEL(quadspi), set_cmd) #include @@ -1392,6 +1392,19 @@ static int flash_stm32_qspi_init(const struct device *dev) dev_data->hqspi.Init.ClockPrescaler = prescaler; /* Give a bit position from 0 to 31 to the HAL init minus 1 for the DCR1 reg */ dev_data->hqspi.Init.FlashSize = find_lsb_set(dev_cfg->flash_size) - 2; +#if DT_PROP(DT_NODELABEL(quadspi), dual_flash) && defined(QUADSPI_CR_DFM) + /* + * When the DTS has , it means Dual Flash Mode + * Even in DUAL flash config, the SDFP is read from one single quad-NOR + * else the magic nb is wrong (0x46465353) + * That means that the Dual Flash config is set after the SFDP sequence + */ + dev_data->hqspi.Init.SampleShifting = QSPI_SAMPLE_SHIFTING_HALFCYCLE; + dev_data->hqspi.Init.ChipSelectHighTime = QSPI_CS_HIGH_TIME_3_CYCLE; + dev_data->hqspi.Init.DualFlash = QSPI_DUALFLASH_DISABLE; + /* Set Dual Flash Mode only on MemoryMapped */ + dev_data->hqspi.Init.FlashID = QSPI_FLASH_ID_1; +#endif /* dual_flash */ HAL_QSPI_Init(&dev_data->hqspi); @@ -1485,6 +1498,16 @@ static int flash_stm32_qspi_init(const struct device *dev) #endif /* CONFIG_FLASH_PAGE_LAYOUT */ #ifdef CONFIG_STM32_MEMMAP +#if DT_PROP(DT_NODELABEL(quadspi), dual_flash) && defined(QUADSPI_CR_DFM) + /* + * When the DTS has dual_flash, it means Dual Flash Mode for Memory MAPPED + * Force Dual Flash mode now, after the SFDP sequence which is reading + * one quad-NOR only + */ + MODIFY_REG(dev_data->hqspi.Instance->CR, (QUADSPI_CR_DFM), QSPI_DUALFLASH_ENABLE); + LOG_DBG("Dual Flash Mode"); +#endif /* dual_flash */ + ret = stm32_qspi_set_memory_mapped(dev); if (ret != 0) { LOG_ERR("Failed to enable memory-mapped mode: %d", ret); From 81baad1480b8ba5acdf6793036b2640fdaa971ac Mon Sep 17 00:00:00 2001 From: Francois Ramu Date: Wed, 31 Jan 2024 17:51:09 +0100 Subject: [PATCH 1944/2849] boards: arm: stm32h7xx disco kits can flash external dual-quad NOR Change the board.cmake to add the external loader option to the STM32CubeProgrammer to flash the external NOR flash and internal memory The address of the external flash is not needed when flashing a hex file. Signed-off-by: Francois Ramu --- .../stm32h745i_disco_stm32h745xx_m7.dts | 11 ++++++++++- .../stm32h747i_disco_stm32h747xx_m7.dts | 9 +++++++++ boards/st/stm32h750b_dk/stm32h750b_dk.dts | 10 +++++++++- 3 files changed, 28 insertions(+), 2 deletions(-) diff --git a/boards/st/stm32h745i_disco/stm32h745i_disco_stm32h745xx_m7.dts b/boards/st/stm32h745i_disco/stm32h745i_disco_stm32h745xx_m7.dts index eb33539d8799c..09b8177b7c449 100644 --- a/boards/st/stm32h745i_disco/stm32h745i_disco_stm32h745xx_m7.dts +++ b/boards/st/stm32h745i_disco/stm32h745i_disco_stm32h745xx_m7.dts @@ -42,10 +42,19 @@ zephyr,memory-attr = <( DT_MEM_ARM(ATTR_MPU_RAM) )>; }; + ext_memory: memory@90000000 { + compatible = "zephyr,memory-region"; + reg = <0x90000000 DT_SIZE_M(64)>; /* 512 Mbits */ + zephyr,memory-region = "EXTMEM"; + /* The ATTR_MPU_EXTMEM attribut causing a MPU FAULT */ + zephyr,memory-attr = <( DT_MEM_ARM(ATTR_MPU_IO) )>; + }; + aliases { led0 = &green_led; pwm-led0 = &green_pwm_led; sw0 = &user_button; + spi-flash0 = &mt25ql512ab1; }; }; @@ -167,7 +176,7 @@ &quadspi_bk2_io0_ph2 &quadspi_bk2_io1_ph3 >; - flash-id = <1>; + dual-flash; status = "okay"; mt25ql512ab1: qspi-nor-flash-1@90000000 { diff --git a/boards/st/stm32h747i_disco/stm32h747i_disco_stm32h747xx_m7.dts b/boards/st/stm32h747i_disco/stm32h747i_disco_stm32h747xx_m7.dts index 1dd5acda5223b..f1de8789781d6 100644 --- a/boards/st/stm32h747i_disco/stm32h747i_disco_stm32h747xx_m7.dts +++ b/boards/st/stm32h747i_disco/stm32h747i_disco_stm32h747xx_m7.dts @@ -31,6 +31,14 @@ zephyr,memory-attr = <( DT_MEM_ARM(ATTR_MPU_RAM) )>; }; + ext_memory: memory@90000000 { + compatible = "zephyr,memory-region"; + reg = <0x90000000 DT_SIZE_M(64)>; /* 512 Mbits */ + zephyr,memory-region = "EXTMEM"; + /* The ATTR_MPU_EXTMEM attribut causing a MPU FAULT */ + zephyr,memory-attr = <( DT_MEM_ARM(ATTR_MPU_IO) )>; + }; + leds { green_led_1:led_1 { status = "okay"; @@ -239,6 +247,7 @@ zephyr_udc0: &usbotg_hs { &quadspi_bk2_io0_ph2 &quadspi_bk2_io1_ph3 &quadspi_bk2_io2_pg9 &quadspi_bk2_io3_pg14>; pinctrl-names = "default"; + dual-flash; status = "okay"; mt25ql512ab1: qspi-nor-flash-1@90000000 { diff --git a/boards/st/stm32h750b_dk/stm32h750b_dk.dts b/boards/st/stm32h750b_dk/stm32h750b_dk.dts index d8eb6bfcf90bd..ad0ecf065f3a4 100644 --- a/boards/st/stm32h750b_dk/stm32h750b_dk.dts +++ b/boards/st/stm32h750b_dk/stm32h750b_dk.dts @@ -29,6 +29,14 @@ zephyr,memory-attr = <( DT_MEM_ARM(ATTR_MPU_RAM) )>; }; + ext_memory: memory@90000000 { + compatible = "zephyr,memory-region"; + reg = <0x90000000 DT_SIZE_M(256)>; /* max addressable area */ + zephyr,memory-region = "EXTMEM"; + /* The ATTR_MPU_EXTMEM attribut causing a MPU FAULT */ + zephyr,memory-attr = <( DT_MEM_ARM(ATTR_MPU_IO) )>; + }; + leds { compatible = "gpio-leds"; red_led: led_1 { @@ -102,7 +110,7 @@ &quadspi_bk1_io2_pf7 &quadspi_bk1_io3_pf6 &quadspi_bk2_io0_ph2 &quadspi_bk2_io1_ph3 &quadspi_bk2_io2_pg9 &quadspi_bk2_io3_pg14>; - flash-id = <1>; + dual-flash; status = "okay"; mt25ql512ab1: qspi-nor-flash-1@90000000 { From ffca987cee5282b7a57daf648ad4dce77c8c0927 Mon Sep 17 00:00:00 2001 From: Francois Ramu Date: Wed, 31 Jan 2024 17:51:09 +0100 Subject: [PATCH 1945/2849] boards: arm: stm32H7 disco kit can flash on external NOR Change the board.cmake to add the external loader option to the STM32CubeProgrammer to flash the external NOR flash and internal memory The address of the external flash is not needed when flashing a hex file. Signed-off-by: Francois Ramu --- boards/st/stm32h745i_disco/board.cmake | 9 ++++++++- boards/st/stm32h747i_disco/board.cmake | 9 ++++++++- boards/st/stm32h750b_dk/board.cmake | 9 +++++++++ 3 files changed, 25 insertions(+), 2 deletions(-) diff --git a/boards/st/stm32h745i_disco/board.cmake b/boards/st/stm32h745i_disco/board.cmake index 699e51ae5959f..94731b3e0f996 100644 --- a/boards/st/stm32h745i_disco/board.cmake +++ b/boards/st/stm32h745i_disco/board.cmake @@ -8,8 +8,15 @@ board_runner_args(openocd --target-handle=_CHIPNAME.cpu0) elseif(CONFIG_BOARD_STM32H745I_DISCO_STM32H745XX_M4) board_runner_args(openocd --target-handle=_CHIPNAME.cpu1) endif() + +if(CONFIG_STM32_MEMMAP) +board_runner_args(stm32cubeprogrammer "--port=swd" "--reset-mode=hw") +board_runner_args(stm32cubeprogrammer "--hex-file=${ZEPHYR_BASE}/build/zephyr/zephyr.hex") +board_runner_args(stm32cubeprogrammer "--extload=MT25TL01G_STM32H745I-DISCO.stldr") +else() board_runner_args(stm32cubeprogrammer "--port=swd" "--reset-mode=hw") +endif() -include(${ZEPHYR_BASE}/boards/common/openocd.board.cmake) 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/stm32h747i_disco/board.cmake b/boards/st/stm32h747i_disco/board.cmake index 93b40d3634d37..288e16557cfd6 100644 --- a/boards/st/stm32h747i_disco/board.cmake +++ b/boards/st/stm32h747i_disco/board.cmake @@ -10,8 +10,15 @@ elseif(CONFIG_BOARD_STM32H747I_DISCO_STM32H747XX_M4) board_runner_args(openocd "--config=${BOARD_DIR}/support/openocd_stm32h747i_disco_m4.cfg") board_runner_args(openocd --target-handle=_CHIPNAME.cpu1) endif() + +if(CONFIG_STM32_MEMMAP) +board_runner_args(stm32cubeprogrammer "--port=swd" "--reset-mode=hw") +board_runner_args(stm32cubeprogrammer "--hex-file=${ZEPHYR_BASE}/build/zephyr/zephyr.hex") +board_runner_args(stm32cubeprogrammer "--extload=MT25TL01G_STM32H747I-DISCO.stldr") +else() board_runner_args(stm32cubeprogrammer "--port=swd" "--reset-mode=hw") +endif() -include(${ZEPHYR_BASE}/boards/common/openocd.board.cmake) 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/stm32h750b_dk/board.cmake b/boards/st/stm32h750b_dk/board.cmake index 6500e7b1a4a91..56e0e8df96a2a 100644 --- a/boards/st/stm32h750b_dk/board.cmake +++ b/boards/st/stm32h750b_dk/board.cmake @@ -3,5 +3,14 @@ board_runner_args(jlink "--device=STM32H735IG" "--speed=4000") board_runner_args(openocd --target-handle=_CHIPNAME.cpu0) +if(CONFIG_STM32_MEMMAP) +board_runner_args(stm32cubeprogrammer "--port=swd" "--reset-mode=hw") +board_runner_args(stm32cubeprogrammer "--hex-file=${ZEPHYR_BASE}/build/zephyr/zephyr.hex") +board_runner_args(stm32cubeprogrammer "--extload=MT25TL01G_STM32H750B-DISCO.stldr") +else() +board_runner_args(stm32cubeprogrammer "--erase" "--port=swd" "--reset-mode=hw" ) +endif() + +include(${ZEPHYR_BASE}/boards/common/stm32cubeprogrammer.board.cmake) include(${ZEPHYR_BASE}/boards/common/openocd.board.cmake) include(${ZEPHYR_BASE}/boards/common/jlink.board.cmake) From a9be65bec586f99875c5ef865670339f876a5809 Mon Sep 17 00:00:00 2001 From: Francois Ramu Date: Mon, 20 May 2024 15:25:24 +0200 Subject: [PATCH 1946/2849] samples: code relocation in external memory of stm32H7 disco kit Define the configuration to run the code_relocation application on the external memory dual quad flash of the stm32h745i/stm32h750b disco kits in XIP Signed-off-by: Francois Ramu --- .../code_relocation_nocopy/boards/stm32h745i_disco_m7.conf | 2 ++ .../code_relocation_nocopy/boards/stm32h747i_disco_m7.conf | 2 ++ .../code_relocation_nocopy/boards/stm32h750b_dk.conf | 2 ++ .../application_development/code_relocation_nocopy/sample.yaml | 3 +++ 4 files changed, 9 insertions(+) create mode 100644 samples/application_development/code_relocation_nocopy/boards/stm32h745i_disco_m7.conf create mode 100644 samples/application_development/code_relocation_nocopy/boards/stm32h747i_disco_m7.conf create mode 100644 samples/application_development/code_relocation_nocopy/boards/stm32h750b_dk.conf diff --git a/samples/application_development/code_relocation_nocopy/boards/stm32h745i_disco_m7.conf b/samples/application_development/code_relocation_nocopy/boards/stm32h745i_disco_m7.conf new file mode 100644 index 0000000000000..eac2504a7850e --- /dev/null +++ b/samples/application_development/code_relocation_nocopy/boards/stm32h745i_disco_m7.conf @@ -0,0 +1,2 @@ +CONFIG_FLASH=y +CONFIG_STM32_MEMMAP=y diff --git a/samples/application_development/code_relocation_nocopy/boards/stm32h747i_disco_m7.conf b/samples/application_development/code_relocation_nocopy/boards/stm32h747i_disco_m7.conf new file mode 100644 index 0000000000000..eac2504a7850e --- /dev/null +++ b/samples/application_development/code_relocation_nocopy/boards/stm32h747i_disco_m7.conf @@ -0,0 +1,2 @@ +CONFIG_FLASH=y +CONFIG_STM32_MEMMAP=y diff --git a/samples/application_development/code_relocation_nocopy/boards/stm32h750b_dk.conf b/samples/application_development/code_relocation_nocopy/boards/stm32h750b_dk.conf new file mode 100644 index 0000000000000..eac2504a7850e --- /dev/null +++ b/samples/application_development/code_relocation_nocopy/boards/stm32h750b_dk.conf @@ -0,0 +1,2 @@ +CONFIG_FLASH=y +CONFIG_STM32_MEMMAP=y diff --git a/samples/application_development/code_relocation_nocopy/sample.yaml b/samples/application_development/code_relocation_nocopy/sample.yaml index b653213fa4d6e..79c6bb65c5f65 100644 --- a/samples/application_development/code_relocation_nocopy/sample.yaml +++ b/samples/application_development/code_relocation_nocopy/sample.yaml @@ -9,6 +9,9 @@ tests: - stm32f769i_disco - stm32h7b3i_dk - b_u585i_iot02a + - stm32h745i_disco/stm32h745xx/m7 + - stm32h750b_dk + - stm32f746g_disco integration_platforms: - qemu_cortex_m3 tags: linker From 45795d35b6a74bd30bf4622af4c0c339b0cad953 Mon Sep 17 00:00:00 2001 From: Rico Ganahl Date: Wed, 27 Mar 2024 11:25:36 +0100 Subject: [PATCH 1947/2849] boards: introduce bytesatwork byteSENSI-L The byteSENSI-L is a fun LoRa device based on nRF52 MCU that integrates many sensors. Signed-off-by: Rico Ganahl Signed-off-by: Guy Morand --- boards/bytesatwork/bytesensi_l/Kconfig | 8 + .../bytesensi_l/Kconfig.bytesensi_l | 6 + .../bytesatwork/bytesensi_l/Kconfig.defconfig | 9 + boards/bytesatwork/bytesensi_l/board.cmake | 5 + boards/bytesatwork/bytesensi_l/board.yml | 7 + .../bytesatwork/bytesensi_l/bytesensi_l.dts | 151 +++++++++++++++++ .../bytesatwork/bytesensi_l/bytesensi_l.yaml | 18 ++ .../bytesensi_l/bytesensi_l_defconfig | 16 ++ .../bytesensi_l/bytesensi_l_pinctrl.dtsi | 54 ++++++ .../bytesensi_l/doc/img/byteSENSI-L.jpg | Bin 0 -> 39845 bytes boards/bytesatwork/bytesensi_l/doc/index.rst | 157 ++++++++++++++++++ .../bytesensi_l/pre_dt_board.cmake | 7 + boards/bytesatwork/index.rst | 10 ++ dts/bindings/vendor-prefixes.txt | 1 + 14 files changed, 449 insertions(+) create mode 100644 boards/bytesatwork/bytesensi_l/Kconfig create mode 100644 boards/bytesatwork/bytesensi_l/Kconfig.bytesensi_l create mode 100644 boards/bytesatwork/bytesensi_l/Kconfig.defconfig create mode 100644 boards/bytesatwork/bytesensi_l/board.cmake create mode 100644 boards/bytesatwork/bytesensi_l/board.yml create mode 100644 boards/bytesatwork/bytesensi_l/bytesensi_l.dts create mode 100644 boards/bytesatwork/bytesensi_l/bytesensi_l.yaml create mode 100644 boards/bytesatwork/bytesensi_l/bytesensi_l_defconfig create mode 100644 boards/bytesatwork/bytesensi_l/bytesensi_l_pinctrl.dtsi create mode 100644 boards/bytesatwork/bytesensi_l/doc/img/byteSENSI-L.jpg create mode 100644 boards/bytesatwork/bytesensi_l/doc/index.rst create mode 100644 boards/bytesatwork/bytesensi_l/pre_dt_board.cmake create mode 100644 boards/bytesatwork/index.rst diff --git a/boards/bytesatwork/bytesensi_l/Kconfig b/boards/bytesatwork/bytesensi_l/Kconfig new file mode 100644 index 0000000000000..fd8429f038965 --- /dev/null +++ b/boards/bytesatwork/bytesensi_l/Kconfig @@ -0,0 +1,8 @@ +# Copyright (c) 2024 bytesatwork AG +# SPDX-License-Identifier: Apache-2.0 + +config BOARD_ENABLE_DCDC + bool "DCDC mode" + select SOC_DCDC_NRF52X + default y + depends on BOARD_BYTESENSI_L diff --git a/boards/bytesatwork/bytesensi_l/Kconfig.bytesensi_l b/boards/bytesatwork/bytesensi_l/Kconfig.bytesensi_l new file mode 100644 index 0000000000000..530e716b540d4 --- /dev/null +++ b/boards/bytesatwork/bytesensi_l/Kconfig.bytesensi_l @@ -0,0 +1,6 @@ +# Copyright (c) 2024 bytesatwork AG +# SPDX-License-Identifier: Apache-2.0 + +config BOARD_BYTESENSI_L + bool "bytesatwork bytesSENSI-L nRF52832" + select SOC_NRF52832_QFAA diff --git a/boards/bytesatwork/bytesensi_l/Kconfig.defconfig b/boards/bytesatwork/bytesensi_l/Kconfig.defconfig new file mode 100644 index 0000000000000..52c2d397af856 --- /dev/null +++ b/boards/bytesatwork/bytesensi_l/Kconfig.defconfig @@ -0,0 +1,9 @@ +# Copyright (c) 2024 bytesatwork AG +# SPDX-License-Identifier: Apache-2.0 + +if BOARD_BYTESENSI_L + +config BT_CTLR + default BT + +endif # BOARD_BYTESENSI_L diff --git a/boards/bytesatwork/bytesensi_l/board.cmake b/boards/bytesatwork/bytesensi_l/board.cmake new file mode 100644 index 0000000000000..efeed46003eff --- /dev/null +++ b/boards/bytesatwork/bytesensi_l/board.cmake @@ -0,0 +1,5 @@ +# Copyright (c) 2024 bytesatwork AG +# SPDX-License-Identifier: Apache-2.0 + +board_runner_args(jlink "--device=nRF52832_xxAA" "--speed=4000") +include(${ZEPHYR_BASE}/boards/common/jlink.board.cmake) diff --git a/boards/bytesatwork/bytesensi_l/board.yml b/boards/bytesatwork/bytesensi_l/board.yml new file mode 100644 index 0000000000000..04e4cd9ad1153 --- /dev/null +++ b/boards/bytesatwork/bytesensi_l/board.yml @@ -0,0 +1,7 @@ +# Copyright (c) 2024 bytesatwork AG +# SPDX-License-Identifier: Apache-2.0 +board: + name: bytesensi_l + vendor: bytesatwork + socs: + - name: nrf52832 diff --git a/boards/bytesatwork/bytesensi_l/bytesensi_l.dts b/boards/bytesatwork/bytesensi_l/bytesensi_l.dts new file mode 100644 index 0000000000000..e54908293fb2b --- /dev/null +++ b/boards/bytesatwork/bytesensi_l/bytesensi_l.dts @@ -0,0 +1,151 @@ +/* + * Copyrigtt (c) 2024 bytesatwork AG + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; + +#include +#include "bytesensi_l_pinctrl.dtsi" + +#include + +/ { + model = "bytesatwork BLE/LORA sensor board"; + compatible = "bytesatwork,bytesensi-l"; + + chosen { + zephyr,console = &uart0; + zephyr,sram = &sram0; + zephyr,flash = &flash0; + zephyr,code-partition = &slot0_partition; + }; + + aliases { + /* Alias for lora samples */ + lora0 = &lora; + }; +}; + +&flash0 { + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + boot_partition: partition@0 { + label = "mcuboot"; + reg = <0x00000000 0xc000>; + }; + slot0_partition: partition@c000 { + label = "image-0"; + reg = <0x0000C000 0x32000>; + }; + slot1_partition: partition@3e000 { + label = "image-1"; + reg = <0x0003E000 0x32000>; + }; + scratch_partition: partition@70000 { + label = "image-scratch"; + reg = <0x00070000 0xa000>; + }; + storage_partition: partition@7a000 { + label = "storage"; + reg = <0x0007a000 0x00005000>; + }; + }; +}; + +&gpiote { + status = "okay"; +}; + +&gpio0 { + status = "okay"; + + /* Enable 1-wire to enable i2c bus as well */ + one-wire-gpio { + gpio-hog; + gpios = <7 GPIO_ACTIVE_HIGH>; + output-high; + }; +}; + +&i2c0 { + compatible = "nordic,nrf-twi"; + status = "okay"; + clock-frequency = ; + pinctrl-0 = <&i2c0_default>; + pinctrl-1 = <&i2c0_sleep>; + pinctrl-names = "default", "sleep"; + + light_sensor: apds9960@39 { + status = "okay"; + compatible = "avago,apds9960"; + reg = <0x39>; + int-gpios = <&gpio0 25 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>; + }; + + temperature_sensor: tmp116@4a { + status = "okay"; + compatible = "ti,tmp116"; + reg = <0x4a>; + #address-cells = <1>; + #size-cells = <0>; + + eeprom: ti_tmp116_eeprom@0 { + compatible = "ti,tmp116-eeprom"; + reg = <0x0>; + read-only; + }; + }; + + gas_sensor: ccs811@5a { + status = "okay"; + compatible = "ams,ccs811"; + reg = <0x5a>; + irq-gpios = <&gpio0 28 GPIO_ACTIVE_LOW>; + wake-gpios = <&gpio0 27 GPIO_ACTIVE_LOW>; + }; + + pressure_sensor: lps22hb-press@5c { + status = "okay"; + compatible = "st,lps22hb-press"; + reg = <0x5c>; + }; +}; + +&spi1 { + status = "okay"; + compatible = "nordic,nrf-spi"; + pinctrl-0 = <&spi1_default>; + pinctrl-1 = <&spi1_sleep>; + pinctrl-names = "default", "sleep"; + cs-gpios = <&gpio0 6 GPIO_ACTIVE_LOW>, + <&gpio0 5 GPIO_ACTIVE_LOW>; + + lora: lora@0 { + status = "okay"; + compatible = "semtech,sx1276"; + reg = <0>; + reset-gpios = <&gpio0 17 GPIO_ACTIVE_LOW>; + dio-gpios = + <&gpio0 19 (GPIO_PULL_DOWN | GPIO_ACTIVE_HIGH)>, + <&gpio0 20 (GPIO_PULL_DOWN | GPIO_ACTIVE_HIGH)>, + <&gpio0 22 (GPIO_PULL_DOWN | GPIO_ACTIVE_HIGH)>, + <&gpio0 23 (GPIO_PULL_DOWN | GPIO_ACTIVE_HIGH)>; + spi-max-frequency = <1000000>; + power-amplifier-output = "pa-boost"; + }; + + nor_flash: mx25r6435f@1 { + status = "okay"; + compatible ="jedec,spi-nor"; + size = <0x4000000>; + reg = <1>; + spi-max-frequency = <8000000>; + status = "okay"; + jedec-id = [c2 28 17]; + }; +}; diff --git a/boards/bytesatwork/bytesensi_l/bytesensi_l.yaml b/boards/bytesatwork/bytesensi_l/bytesensi_l.yaml new file mode 100644 index 0000000000000..362508e67a2fa --- /dev/null +++ b/boards/bytesatwork/bytesensi_l/bytesensi_l.yaml @@ -0,0 +1,18 @@ +# Copyright (c) 2024 bytesatwork AG +# SPDX-License-Identifier: Apache-2.0 +identifier: bytesensi_l +name: bytesatwork byteSENSI-L +type: mcu +arch: arm +toolchain: + - zephyr + - gnuarmemb +ram: 64 +flash: 512 +supported: + - ble + - gpio + - i2c + - lora + - spi +vendor: bytesatwork diff --git a/boards/bytesatwork/bytesensi_l/bytesensi_l_defconfig b/boards/bytesatwork/bytesensi_l/bytesensi_l_defconfig new file mode 100644 index 0000000000000..80cef47e86781 --- /dev/null +++ b/boards/bytesatwork/bytesensi_l/bytesensi_l_defconfig @@ -0,0 +1,16 @@ +# Copyright (c) 2024 bytesatwork AG +# SPDX-License-Identifier: Apache-2.0 + +# Enable MPU +CONFIG_ARM_MPU=y + +# enable GPIO +CONFIG_GPIO=y + +# Enable hardware stack protection +CONFIG_HW_STACK_PROTECTION=y + +# enable console over segger RTT +CONFIG_CONSOLE=y +CONFIG_RTT_CONSOLE=y +CONFIG_USE_SEGGER_RTT=y diff --git a/boards/bytesatwork/bytesensi_l/bytesensi_l_pinctrl.dtsi b/boards/bytesatwork/bytesensi_l/bytesensi_l_pinctrl.dtsi new file mode 100644 index 0000000000000..8b31ab2d3b04a --- /dev/null +++ b/boards/bytesatwork/bytesensi_l/bytesensi_l_pinctrl.dtsi @@ -0,0 +1,54 @@ +/* + * Copyrigtt (c) 2024 bytesatwork AG + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&pinctrl { + uart0_default: uart0_default { + group1 { + psels = , + ; + }; + }; + + uart0_sleep: uart0_sleep { + group1 { + psels = , + ; + low-power-enable; + }; + }; + + i2c0_default: i2c0_default { + group1 { + psels = , + ; + }; + }; + + i2c0_sleep: i2c0_sleep { + group1 { + psels = , + ; + low-power-enable; + }; + }; + + spi1_default: spi1_default{ + group1 { + psels = , + , + ; + }; + }; + + spi1_sleep: spi1_sleep{ + group1 { + psels = , + , + ; + low-power-enable; + }; + }; +}; diff --git a/boards/bytesatwork/bytesensi_l/doc/img/byteSENSI-L.jpg b/boards/bytesatwork/bytesensi_l/doc/img/byteSENSI-L.jpg new file mode 100644 index 0000000000000000000000000000000000000000..5baccde618f445c2f99f398a9c2e9ffc5236acb3 GIT binary patch literal 39845 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

} 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 H>~H_sZ3uP+ literal 0 HcmV?d00001 diff --git a/boards/bytesatwork/bytesensi_l/doc/index.rst b/boards/bytesatwork/bytesensi_l/doc/index.rst new file mode 100644 index 0000000000000..5c9ca7f7b9ffc --- /dev/null +++ b/boards/bytesatwork/bytesensi_l/doc/index.rst @@ -0,0 +1,157 @@ +.. _bytesensi_l: + +bytesatwork byteSENSI-L +####################### + +Overview +******** + +The byteSENSI-L is a fun LoRa device based on nRF52 MCU that integrates many +sensors. + +.. image:: img/byteSENSI-L.jpg + :width: 800px + :align: center + :alt: byteSENSI-L + +Hardware +******** + +Supported Features +================== + ++-----------+------------+----------------------+ +| Interface | Controller | Driver/Component | ++===========+============+======================+ +| CLOCK | on-chip | clock_control | ++-----------+------------+----------------------+ +| FLASH | on-chip | flash | ++-----------+------------+----------------------+ +| GPIO | on-chip | gpio | ++-----------+------------+----------------------+ +| I2C(M) | on-chip | i2c | ++-----------+------------+----------------------+ +| MPU | on-chip | arch/arm | ++-----------+------------+----------------------+ +| NVIC | on-chip | arch/arm | ++-----------+------------+----------------------+ +| RADIO | on-chip | Bluetooth | ++-----------+------------+----------------------+ +| RADIO | Semtech | LoRa | ++-----------+------------+----------------------+ +| RTC | on-chip | system clock | ++-----------+------------+----------------------+ +| RTT | Segger | console | ++-----------+------------+----------------------+ +| WDT | on-chip | watchdog | ++-----------+------------+----------------------+ + +Connections and IOs +=================== + +External Connectors +------------------- + +External Supply @ X1 + ++-------+--------------+---------------------------------------+ +| PIN # | Signal Name | Function | ++=======+==============+=======================================+ +| 1 | VBAT | Power input instead of CR2477 battery | ++-------+--------------+---------------------------------------+ +| 2 | GND | Ground | ++-------+--------------+---------------------------------------+ + +Programming Connector @ SL1 + ++-------+--------------+ +| PIN # | Signal Name | ++=======+==============+ +| 1 | VBAT | ++-------+--------------+ +| 2 | SWDIO | ++-------+--------------+ +| 3 | GND | ++-------+--------------+ +| 4 | SWDCLK | ++-------+--------------+ +| 5 | GND | ++-------+--------------+ +| 6 | NC (SWO) | ++-------+--------------+ +| 7 | NC (Key) | ++-------+--------------+ +| 8 | NC | ++-------+--------------+ +| 9 | GND | ++-------+--------------+ +| 10 | nReset | ++-------+--------------+ + +I2C Sensor @ X3 + ++-------+--------------+-------------------------+ +| PIN # | Signal Name | Function | ++=======+==============+=========================+ +| 1 | VBAT | Power out | ++-------+--------------+-------------------------+ +| 2 | SCL | I2C clock at P0.15 | ++-------+--------------+-------------------------+ +| 3 | SDA | I2C data at P0.16 | ++-------+--------------+-------------------------+ +| 4 | INT | Interrupt at P0.13 | ++-------+--------------+-------------------------+ +| 5 | I2C_ADDR | tied to VBAT | ++-------+--------------+-------------------------+ +| 6 | GND | Ground | ++-------+--------------+-------------------------+ + +One Wire Sensor @ X2 + ++-------+----------------+-------------------------+ +| PIN # | Signal Name | Function | ++=======+================+=========================+ +| 1 | VDD | 4V8 | ++-------+----------------+-------------------------+ +| 2 | IO | One Wire | ++-------+----------------+-------------------------+ +| 3 | GND | Ground | ++-------+----------------+-------------------------+ + +External BLE Antenna @ J1 + +External LoRa Antenna @ J2 + +External GPS Antenna @ J3 + +Programming and Debugging +************************* + +Flashing +======== +The byteSENSI-L board can be flashed with the SEGGER JLink programmer. + +You can build and flash applications in the usual way. Here is an example for +the :ref:`hello_world` application. + + .. zephyr-app-commands:: + :zephyr-app: samples/hello_world + :board: bytesensi_l + :goals: build flash + :compact: + +Debugging +========= + +Debugging your application can be done with ``west debug``. + +Serial console +============== + +The byteSENSI-L board only uses Segger's RTT console for providing serial +console. There is no physical serial port available. + +References +********** +* `bytesatwork website `_ +* `bytesatwork wiki `_ diff --git a/boards/bytesatwork/bytesensi_l/pre_dt_board.cmake b/boards/bytesatwork/bytesensi_l/pre_dt_board.cmake new file mode 100644 index 0000000000000..4bcc2f7a610ae --- /dev/null +++ b/boards/bytesatwork/bytesensi_l/pre_dt_board.cmake @@ -0,0 +1,7 @@ +# Copyright (c) 2024 bytesatwork AG +# 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/bytesatwork/index.rst b/boards/bytesatwork/index.rst new file mode 100644 index 0000000000000..cb47fbff33325 --- /dev/null +++ b/boards/bytesatwork/index.rst @@ -0,0 +1,10 @@ +.. _boards-bytesatwork: + +bytesatwork +########### + +.. toctree:: + :maxdepth: 1 + :glob: + + **/* diff --git a/dts/bindings/vendor-prefixes.txt b/dts/bindings/vendor-prefixes.txt index 2af0085632bc0..eb50435550816 100644 --- a/dts/bindings/vendor-prefixes.txt +++ b/dts/bindings/vendor-prefixes.txt @@ -111,6 +111,7 @@ broadmobi Shanghai Broadmobi Communication Technology Co.,Ltd. bticino Bticino International buffalo Buffalo, Inc. bur B&R Industrial Automation GmbH +bytesatwork bytesatwork AG calaosystems CALAO Systems SAS calxeda Calxeda canaan Canaan, Inc. From 1b47a1b75c3720ad4c0b5fd14d4009ea75314678 Mon Sep 17 00:00:00 2001 From: Chauncy Liu Date: Sun, 19 May 2024 11:46:28 -0400 Subject: [PATCH 1948/2849] include: posix: Avoid compiler warning about return type mismatched Cast variables to correct type to avoid compilation warnings. Signed-off-by: Chauncy Liu --- include/zephyr/posix/time.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/zephyr/posix/time.h b/include/zephyr/posix/time.h index 7ab609877573f..f0ca07284bc84 100644 --- a/include/zephyr/posix/time.h +++ b/include/zephyr/posix/time.h @@ -87,7 +87,7 @@ extern "C" { static inline int32_t _ts_to_ms(const struct timespec *to) { - return (to->tv_sec * MSEC_PER_SEC) + (to->tv_nsec / NSEC_PER_MSEC); + return (int32_t)(to->tv_sec * MSEC_PER_SEC) + (int32_t)(to->tv_nsec / NSEC_PER_MSEC); } int clock_gettime(clockid_t clock_id, struct timespec *ts); From e017006be4b989dfed538a5fe18a6515afb1321a Mon Sep 17 00:00:00 2001 From: Peter van der Perk Date: Thu, 11 Apr 2024 23:08:26 +0200 Subject: [PATCH 1949/2849] drivers: input: sbus remote controller support Add support SBUS RC controller connected through UART Signed-off-by: Peter van der Perk --- boards/nxp/vmu_rt1170/doc/index.rst | 4 + .../vmu_rt1170/vmu_rt1170_mimxrt1176_cm7.dts | 35 ++ drivers/input/CMakeLists.txt | 1 + drivers/input/Kconfig | 1 + drivers/input/Kconfig.sbus | 54 +++ drivers/input/input_sbus.c | 376 ++++++++++++++++++ dts/bindings/input/futaba,sbus.yaml | 70 ++++ dts/bindings/vendor-prefixes.txt | 1 + 8 files changed, 542 insertions(+) create mode 100644 drivers/input/Kconfig.sbus create mode 100644 drivers/input/input_sbus.c create mode 100644 dts/bindings/input/futaba,sbus.yaml diff --git a/boards/nxp/vmu_rt1170/doc/index.rst b/boards/nxp/vmu_rt1170/doc/index.rst index c98d867d5677a..2ab8c20b27f94 100644 --- a/boards/nxp/vmu_rt1170/doc/index.rst +++ b/boards/nxp/vmu_rt1170/doc/index.rst @@ -61,6 +61,10 @@ Hardware - CAN bus JST-GH connectors +- RC IN + + - RC input connector for SBUS compatible RC receivers + For more information about the MIMXRT1176 SoC and VMU RT1170 board, see these references: diff --git a/boards/nxp/vmu_rt1170/vmu_rt1170_mimxrt1176_cm7.dts b/boards/nxp/vmu_rt1170/vmu_rt1170_mimxrt1176_cm7.dts index c3e84a3fbf13b..b38931865ee4a 100644 --- a/boards/nxp/vmu_rt1170/vmu_rt1170_mimxrt1176_cm7.dts +++ b/boards/nxp/vmu_rt1170/vmu_rt1170_mimxrt1176_cm7.dts @@ -178,6 +178,41 @@ current-speed = <115200>; }; +&lpuart6 { + status = "okay"; + single-wire; + rx-invert; + + sbus { + compatible = "futaba,sbus"; + right_stick_x { + channel = <1>; + type = ; + zephyr,code = ; + }; + right_stick_y { + channel = <2>; + type = ; + zephyr,code = ; + }; + left_stick_y { + channel = <3>; + type = ; + zephyr,code = ; + }; + left_stick_x { + channel = <4>; + type = ; + zephyr,code = ; + }; + kill_switch { + channel = <5>; + type = ; + zephyr,code = ; + }; + }; +}; + &flexcan1 { status = "okay"; diff --git a/drivers/input/CMakeLists.txt b/drivers/input/CMakeLists.txt index bab58e5c6d302..a996cb93ead3b 100644 --- a/drivers/input/CMakeLists.txt +++ b/drivers/input/CMakeLists.txt @@ -24,6 +24,7 @@ zephyr_library_sources_ifdef(CONFIG_INPUT_PAT912X input_pat912x.c) zephyr_library_sources_ifdef(CONFIG_INPUT_PAW32XX input_paw32xx.c) zephyr_library_sources_ifdef(CONFIG_INPUT_PINNACLE input_pinnacle.c) zephyr_library_sources_ifdef(CONFIG_INPUT_PMW3610 input_pmw3610.c) +zephyr_library_sources_ifdef(CONFIG_INPUT_SBUS input_sbus.c) zephyr_library_sources_ifdef(CONFIG_INPUT_STMPE811 input_stmpe811.c) zephyr_library_sources_ifdef(CONFIG_INPUT_XEC_KBD input_xec_kbd.c) zephyr_library_sources_ifdef(CONFIG_INPUT_XPT2046 input_xpt2046.c) diff --git a/drivers/input/Kconfig b/drivers/input/Kconfig index e810b5b0914c4..34363e3eca94c 100644 --- a/drivers/input/Kconfig +++ b/drivers/input/Kconfig @@ -26,6 +26,7 @@ source "drivers/input/Kconfig.pat912x" source "drivers/input/Kconfig.paw32xx" source "drivers/input/Kconfig.pinnacle" source "drivers/input/Kconfig.pmw3610" +source "drivers/input/Kconfig.sbus" source "drivers/input/Kconfig.sdl" source "drivers/input/Kconfig.stmpe811" source "drivers/input/Kconfig.xec" diff --git a/drivers/input/Kconfig.sbus b/drivers/input/Kconfig.sbus new file mode 100644 index 0000000000000..a3d1532161ed7 --- /dev/null +++ b/drivers/input/Kconfig.sbus @@ -0,0 +1,54 @@ +# Copyright (c) 2024 NXP Semiconductors +# SPDX-License-Identifier: Apache-2.0 + +config INPUT_SBUS + bool "SBUS driver" + default y + depends on DT_HAS_FUTABA_SBUS_ENABLED + depends on UART_INTERRUPT_DRIVEN + select UART_USE_RUNTIME_CONFIGURE + help + Enable driver for SBUS Remote controller. + +if INPUT_SBUS + +config INPUT_SBUS_THREAD_STACK_SIZE + int "Stack size for the sbus thread" + default 1024 + help + Size of the stack used for the sbus thread. + +config INPUT_SBUS_THREAD_PRIORITY + int "Priority for the sbus thread" + default 0 + help + Priority level of the sbus thread. + +config INPUT_SBUS_REPORT_FILTER + int "Minimal change in signal to report" + default 1 + help + SBUS tends to be a bit noisy you can increase the threshold to + to lower the amounts of input events. Set to 0 for no filtering + +config INPUT_SBUS_SEND_SYNC + bool "Send Sync to input subsys on each SBUS frame" + default y + help + Sends sync message to input subsys with sync bit. + +config INPUT_SBUS_CHANNEL_VALUE_ONE + int "Threshold value > for INPUT_EV_KEY value 1" + default 1800 + help + SBUS sends analogue values for digital switches. This config value + sets the threshold to interperted the analogue value as an logic 1 + +config INPUT_SBUS_CHANNEL_VALUE_ZERO + int "Threshold value < for INPUT_EV_KEY value 0" + default 1200 + help + SBUS sends analogue values for digital switches. This config value + sets the threshold to interperted the analogue value as an logic 0 + +endif # INPUT_SBUS diff --git a/drivers/input/input_sbus.c b/drivers/input/input_sbus.c new file mode 100644 index 0000000000000..ef88f5fc677f0 --- /dev/null +++ b/drivers/input/input_sbus.c @@ -0,0 +1,376 @@ +/* + * Copyright (c) 2024 CogniPilot Foundation + * Copyright (c) 2024 NXP Semiconductors + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT futaba_sbus + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +LOG_MODULE_REGISTER(futaba_sbus, CONFIG_INPUT_LOG_LEVEL); + +/* Driver config */ +struct sbus_input_channel { + uint32_t sbus_channel; + uint32_t type; + uint32_t zephyr_code; +}; + +const struct uart_config uart_cfg_sbus = { + .baudrate = 100000, + .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 +}; + +struct input_sbus_config { + uint8_t num_channels; + const struct sbus_input_channel *channel_info; + const struct device *uart_dev; + uart_irq_callback_user_data_t cb; +}; + +#define SBUS_FRAME_LEN 25 +#define SBUS_HEADER 0x0F +#define SBUS_FOOTER 0x00 + +#define SBUS_SERVO_LEN 22 +#define SBUS_SERVO_CH_MASK 0x7FF + +#define SBUS_BYTE24_IDX 23 +#define SBUS_BYTE24_CH17 0x01 +#define SBUS_BYTE24_CH18 0x02 +#define SBUS_BYTE24_FRAME_LOST 0x04 +#define SBUS_BYTE24_FAILSAFE 0x08 + +#define SBUS_TRANSMISSION_TIME_MS 4 /* Max transmission of a single SBUS frame */ +#define SBUS_INTERFRAME_SPACING_MS 20 /* Max spacing between SBUS frames */ +#define SBUS_CHANNEL_COUNT 16 + +#define REPORT_FILTER CONFIG_INPUT_SBUS_REPORT_FILTER +#define CHANNEL_VALUE_ZERO CONFIG_INPUT_SBUS_CHANNEL_VALUE_ZERO +#define CHANNEL_VALUE_ONE CONFIG_INPUT_SBUS_CHANNEL_VALUE_ONE + +struct input_sbus_data { + struct k_thread thread; + struct k_sem report_lock; + + uint16_t xfer_bytes; + uint8_t rd_data[SBUS_FRAME_LEN]; + uint8_t sbus_frame[SBUS_FRAME_LEN]; + bool partial_sync; + bool in_sync; + uint32_t last_rx_time; + + uint16_t last_reported_value[SBUS_CHANNEL_COUNT]; + int8_t channel_mapping[SBUS_CHANNEL_COUNT]; + + K_KERNEL_STACK_MEMBER(thread_stack, CONFIG_INPUT_SBUS_THREAD_STACK_SIZE); +}; + +static void input_sbus_report(const struct device *dev, unsigned int sbus_channel, + unsigned int value) +{ + const struct input_sbus_config *const config = dev->config; + struct input_sbus_data *const data = dev->data; + + int channel = data->channel_mapping[sbus_channel]; + + /* Not Mapped */ + if (channel == -1) { + return; + } + + if (value >= (data->last_reported_value[channel] + REPORT_FILTER) || + value <= (data->last_reported_value[channel] - REPORT_FILTER)) { + switch (config->channel_info[channel].type) { + case INPUT_EV_ABS: + case INPUT_EV_MSC: + input_report(dev, config->channel_info[channel].type, + config->channel_info[channel].zephyr_code, value, false, + K_FOREVER); + break; + + default: + if (value > CHANNEL_VALUE_ONE) { + input_report_key(dev, config->channel_info[channel].zephyr_code, 1, + false, K_FOREVER); + } else if (value < CHANNEL_VALUE_ZERO) { + input_report_key(dev, config->channel_info[channel].zephyr_code, 0, + false, K_FOREVER); + } + } + data->last_reported_value[channel] = value; + } +} + +static void input_sbus_input_report_thread(const struct device *dev, void *dummy2, void *dummy3) +{ + struct input_sbus_data *const data = dev->data; + + ARG_UNUSED(dummy2); + ARG_UNUSED(dummy3); + + uint8_t i, channel; + uint8_t *sbus_channel_data = &data->sbus_frame[1]; /* Omit header */ + uint16_t value; + int bits_read; + unsigned int key; + int ret; + bool connected_reported = false; + + while (true) { + if (!data->in_sync) { + k_sem_take(&data->report_lock, K_FOREVER); + if (data->in_sync) { + LOG_DBG("SBUS receiver connected"); + } else { + continue; + } + } else { + ret = k_sem_take(&data->report_lock, K_MSEC(SBUS_INTERFRAME_SPACING_MS)); + if (ret == -EBUSY) { + continue; + } else if (ret < 0 || !data->in_sync) { + /* We've lost sync with the UART receiver */ + key = irq_lock(); + + data->partial_sync = false; + data->in_sync = false; + data->xfer_bytes = 0; + irq_unlock(key); + + connected_reported = false; + LOG_DBG("SBUS receiver connection lost"); + + /* Report connection lost */ + continue; + } + } + + if (connected_reported && + data->sbus_frame[SBUS_BYTE24_IDX] & SBUS_BYTE24_FRAME_LOST) { + LOG_DBG("SBUS controller connection lost"); + connected_reported = false; + } else if (!connected_reported && + !(data->sbus_frame[SBUS_BYTE24_IDX] & SBUS_BYTE24_FRAME_LOST)) { + LOG_DBG("SBUS controller connected"); + connected_reported = true; + } + + /* Parse the data */ + channel = 0; + value = 0; + bits_read = 0; + + for (i = 0; i < SBUS_SERVO_LEN; i++) { + /* Read the next byte */ + unsigned char byte = sbus_channel_data[i]; + + /* Extract bits and construct the 11-bit value */ + value |= byte << bits_read; + bits_read += 8; + + /* Check if we've read enough bits to form a full 11-bit value */ + while (bits_read >= 11) { + input_sbus_report(dev, channel, value & SBUS_SERVO_CH_MASK); + + /* Shift right to prepare for the next 11 bits */ + value >>= 11; + bits_read -= 11; + channel++; + } + } + +#ifdef CONFIG_INPUT_SBUS_SEND_SYNC + input_report(dev, 0, 0, 0, true, K_FOREVER); +#endif + } +} + +static void sbus_resync(const struct device *uart_dev, struct input_sbus_data *const data) +{ + uint8_t *rd_data = data->rd_data; + + if (data->partial_sync) { + data->xfer_bytes += uart_fifo_read(uart_dev, &rd_data[data->xfer_bytes], + SBUS_FRAME_LEN - data->xfer_bytes); + if (data->xfer_bytes == SBUS_FRAME_LEN) { + /* Transfer took longer then 4ms probably faulty */ + if (k_uptime_get_32() - data->last_rx_time > SBUS_TRANSMISSION_TIME_MS) { + data->xfer_bytes = 0; + data->partial_sync = false; + } else if (rd_data[0] == SBUS_HEADER && + rd_data[SBUS_FRAME_LEN - 1] == SBUS_FOOTER) { + data->in_sync = true; + } else { + /* Dummy read to clear fifo */ + uart_fifo_read(uart_dev, &rd_data[0], 1); + data->xfer_bytes = 0; + data->partial_sync = false; + } + } + } else { + if (uart_fifo_read(uart_dev, &rd_data[0], 1) == 1) { + if (rd_data[0] == SBUS_HEADER) { + data->partial_sync = true; + data->xfer_bytes = 1; + data->last_rx_time = k_uptime_get_32(); + } + } + } +} + +static void sbus_uart_isr(const struct device *uart_dev, void *user_data) +{ + const struct device *dev = user_data; + struct input_sbus_data *const data = dev->data; + uint8_t *rd_data = data->rd_data; + + if (uart_dev == NULL) { + LOG_DBG("UART device is NULL"); + return; + } + + if (!uart_irq_update(uart_dev)) { + LOG_DBG("Unable to start processing interrupts"); + return; + } + + while (uart_irq_rx_ready(uart_dev) && data->xfer_bytes <= SBUS_FRAME_LEN) { + if (data->in_sync) { + if (data->xfer_bytes == 0) { + data->last_rx_time = k_uptime_get_32(); + } + data->xfer_bytes += uart_fifo_read(uart_dev, &rd_data[data->xfer_bytes], + SBUS_FRAME_LEN - data->xfer_bytes); + } else { + sbus_resync(uart_dev, data); + } + } + + if (data->in_sync && (k_uptime_get_32() - data->last_rx_time > + SBUS_INTERFRAME_SPACING_MS)) { + data->partial_sync = false; + data->in_sync = false; + data->xfer_bytes = 0; + k_sem_give(&data->report_lock); + } else if (data->in_sync && data->xfer_bytes == SBUS_FRAME_LEN) { + data->xfer_bytes = 0; + + if (rd_data[0] == SBUS_HEADER && rd_data[SBUS_FRAME_LEN - 1] == SBUS_FOOTER) { + memcpy(data->sbus_frame, rd_data, SBUS_FRAME_LEN); + k_sem_give(&data->report_lock); + } else { + data->partial_sync = false; + data->in_sync = false; + } + } +} + +/* + * @brief Initialize sbus driver + */ +static int input_sbus_init(const struct device *dev) +{ + const struct input_sbus_config *const config = dev->config; + struct input_sbus_data *const data = dev->data; + int i, ret; + + uart_irq_rx_disable(config->uart_dev); + uart_irq_tx_disable(config->uart_dev); + + LOG_DBG("Initializing SBUS driver"); + + for (i = 0; i < SBUS_CHANNEL_COUNT; i++) { + data->last_reported_value[i] = 0; + data->channel_mapping[i] = -1; + } + + data->xfer_bytes = 0; + data->in_sync = false; + data->partial_sync = false; + data->last_rx_time = 0; + + for (i = 0; i < config->num_channels; i++) { + data->channel_mapping[config->channel_info[i].sbus_channel - 1] = i; + } + + ret = uart_configure(config->uart_dev, &uart_cfg_sbus); + if (ret < 0) { + LOG_ERR("Unable to configure UART port: %d", ret); + return ret; + } + + ret = uart_irq_callback_user_data_set(config->uart_dev, config->cb, (void *)dev); + if (ret < 0) { + if (ret == -ENOTSUP) { + LOG_ERR("Interrupt-driven UART API support not enabled"); + } else if (ret == -ENOSYS) { + LOG_ERR("UART device does not support interrupt-driven API"); + } else { + LOG_ERR("Error setting UART callback: %d", ret); + } + return ret; + } + + uart_irq_rx_enable(config->uart_dev); + + k_sem_init(&data->report_lock, 0, 1); + + k_thread_create(&data->thread, data->thread_stack, + K_KERNEL_STACK_SIZEOF(data->thread_stack), + (k_thread_entry_t)input_sbus_input_report_thread, (void *)dev, NULL, NULL, + CONFIG_INPUT_SBUS_THREAD_PRIORITY, 0, K_NO_WAIT); + + k_thread_name_set(&data->thread, dev->name); + + return ret; +} + +#define INPUT_CHANNEL_CHECK(input_channel_id) \ + BUILD_ASSERT(IN_RANGE(DT_PROP(input_channel_id, channel), 1, 16), \ + "invalid channel number"); \ + BUILD_ASSERT(DT_PROP(input_channel_id, type) == INPUT_EV_ABS || \ + DT_PROP(input_channel_id, type) == INPUT_EV_KEY || \ + DT_PROP(input_channel_id, type) == INPUT_EV_MSC, \ + "invalid channel type"); + +#define SBUS_INPUT_CHANNEL_INITIALIZER(input_channel_id) \ + { \ + .sbus_channel = DT_PROP(input_channel_id, channel), \ + .type = DT_PROP(input_channel_id, type), \ + .zephyr_code = DT_PROP(input_channel_id, zephyr_code), \ + }, + +#define INPUT_SBUS_INIT(n) \ + \ + static const struct sbus_input_channel input_##id[] = { \ + DT_INST_FOREACH_CHILD(n, SBUS_INPUT_CHANNEL_INITIALIZER) \ + }; \ + DT_INST_FOREACH_CHILD(n, INPUT_CHANNEL_CHECK) \ + \ + static struct input_sbus_data sbus_data_##n; \ + \ + static const struct input_sbus_config sbus_cfg_##n = { \ + .channel_info = input_##id, \ + .uart_dev = DEVICE_DT_GET(DT_INST_BUS(n)), \ + .num_channels = ARRAY_SIZE(input_##id), \ + .cb = sbus_uart_isr, \ + }; \ + \ + DEVICE_DT_INST_DEFINE(n, input_sbus_init, NULL, &sbus_data_##n, &sbus_cfg_##n, \ + POST_KERNEL, CONFIG_INPUT_INIT_PRIORITY, NULL); + +DT_INST_FOREACH_STATUS_OKAY(INPUT_SBUS_INIT) diff --git a/dts/bindings/input/futaba,sbus.yaml b/dts/bindings/input/futaba,sbus.yaml new file mode 100644 index 0000000000000..574c7ef7ff809 --- /dev/null +++ b/dts/bindings/input/futaba,sbus.yaml @@ -0,0 +1,70 @@ +# Copyright (c) 2024 NXP Semiconductors +# SPDX-License-Identifier: Apache-2.0 + +description: | + SBUS input driver using + This driver implements the SBUS protocol used on RC radio's + to send out analogue joystick and switches output. + SBUS is an single-wire inverted serial protocol to either you need to + to the rx-invert feature of your serial driver or use an external signal inverter. + The driver binds this to the Zephyr input system using INPUT_EV_CODES. + + The following examples defines a a binding of 2 joysticks and a button using 5 channels. + + &lpuart6 { + status = "okay"; + + sbus { + compatible = "futaba,sbus"; + right_stick_x { + channel = <1>; + type = ; + zephyr,code = ; + }; + right_stick_y { + channel = <2>; + type = ; + zephyr,code = ; + }; + left_stick_x { + channel = <3>; + type = ; + zephyr,code = ; + }; + left_stick_y { + channel = <4>; + type = ; + zephyr,code = ; + }; + kill_switch { + channel = <5>; + type = ; + zephyr,code = ; + }; + }; + }; + +compatible: "futaba,sbus" + +include: [base.yaml, uart-device.yaml] + +child-binding: + description: | + SBUS Channel to input-event-code binding + INPUT_EV_ABS & INPUT_EV_MSC gives raw input value + INPUT_EV_KEY emulates a key + properties: + channel: + type: int + required: true + description: | + SBUS input channel + Valid range: 1 - 16 + type: + type: int + required: true + description: Input event types see INPUT_EV_CODES + zephyr,code: + type: int + required: true + description: Code to emit. diff --git a/dts/bindings/vendor-prefixes.txt b/dts/bindings/vendor-prefixes.txt index eb50435550816..30b2e93bc0a38 100644 --- a/dts/bindings/vendor-prefixes.txt +++ b/dts/bindings/vendor-prefixes.txt @@ -245,6 +245,7 @@ friendlyarm Guangzhou FriendlyARM Computer Tech Co., Ltd fsl Freescale Semiconductor ftdi Future Technology Devices International Ltd. fujitsu Fujitsu Ltd. +futaba Futaba Corporation gaisler Gaisler galaxycore Galaxycore, Inc. gardena GARDENA GmbH From 8c65c73cf8458914b262eb6f065fa6ef017bbbda Mon Sep 17 00:00:00 2001 From: Daniel Leung Date: Tue, 4 Jun 2024 15:41:31 -0700 Subject: [PATCH 1950/2849] tests: lib/c_lib/thrd: config overlay for intel_adsp/ace30_ptl This sets CONFIG_MAX_THREAD_BYTES to 3 as the tests need a few more bits to build for board intel_adsp/ace30_ptl. Signed-off-by: Daniel Leung --- tests/lib/c_lib/thrd/boards/intel_adsp_ace30_ptl.conf | 1 + 1 file changed, 1 insertion(+) create mode 100644 tests/lib/c_lib/thrd/boards/intel_adsp_ace30_ptl.conf diff --git a/tests/lib/c_lib/thrd/boards/intel_adsp_ace30_ptl.conf b/tests/lib/c_lib/thrd/boards/intel_adsp_ace30_ptl.conf new file mode 100644 index 0000000000000..922c1e4b05f34 --- /dev/null +++ b/tests/lib/c_lib/thrd/boards/intel_adsp_ace30_ptl.conf @@ -0,0 +1 @@ +CONFIG_MAX_THREAD_BYTES=3 From 1a93191f457e8b25f635decf83357abb67c7a93a Mon Sep 17 00:00:00 2001 From: Daniel Leung Date: Tue, 4 Jun 2024 15:47:29 -0700 Subject: [PATCH 1951/2849] tests: mem_protect/sys_sem: config for intel_adsp/ace30_ptl This sets CONFIG_MAX_THREAD_BYTES to 3 as the tests need a few more bits to build for board intel_adsp/ace30_ptl. Signed-off-by: Daniel Leung --- .../kernel/mem_protect/sys_sem/boards/intel_adsp_ace30_ptl.conf | 1 + 1 file changed, 1 insertion(+) create mode 100644 tests/kernel/mem_protect/sys_sem/boards/intel_adsp_ace30_ptl.conf diff --git a/tests/kernel/mem_protect/sys_sem/boards/intel_adsp_ace30_ptl.conf b/tests/kernel/mem_protect/sys_sem/boards/intel_adsp_ace30_ptl.conf new file mode 100644 index 0000000000000..922c1e4b05f34 --- /dev/null +++ b/tests/kernel/mem_protect/sys_sem/boards/intel_adsp_ace30_ptl.conf @@ -0,0 +1 @@ +CONFIG_MAX_THREAD_BYTES=3 From f50ac58b1d3fb372234443b75f5d7d318bcafdd9 Mon Sep 17 00:00:00 2001 From: Daniel Leung Date: Tue, 4 Jun 2024 15:48:28 -0700 Subject: [PATCH 1952/2849] tests: mutex/sys_mutex: config overlay for intel_adsp/ace30_ptl This sets CONFIG_MAX_THREAD_BYTES to 3 as the tests need a few more bits to build for board intel_adsp/ace30_ptl. Signed-off-by: Daniel Leung --- tests/kernel/mutex/sys_mutex/boards/intel_adsp_ace30_ptl.conf | 1 + 1 file changed, 1 insertion(+) create mode 100644 tests/kernel/mutex/sys_mutex/boards/intel_adsp_ace30_ptl.conf diff --git a/tests/kernel/mutex/sys_mutex/boards/intel_adsp_ace30_ptl.conf b/tests/kernel/mutex/sys_mutex/boards/intel_adsp_ace30_ptl.conf new file mode 100644 index 0000000000000..922c1e4b05f34 --- /dev/null +++ b/tests/kernel/mutex/sys_mutex/boards/intel_adsp_ace30_ptl.conf @@ -0,0 +1 @@ +CONFIG_MAX_THREAD_BYTES=3 From 86a63627b093cd31c50d221380625063fa350da6 Mon Sep 17 00:00:00 2001 From: Daniel Leung Date: Tue, 4 Jun 2024 15:46:37 -0700 Subject: [PATCH 1953/2849] tests: kernel/queue: config overlay for intel_adsp/ace30_ptl This sets CONFIG_MAX_THREAD_BYTES to 3 as the tests need a few more bits to build for board intel_adsp/ace30_ptl. Signed-off-by: Daniel Leung --- tests/kernel/queue/boards/intel_adsp_ace30_ptl.conf | 1 + 1 file changed, 1 insertion(+) create mode 100644 tests/kernel/queue/boards/intel_adsp_ace30_ptl.conf diff --git a/tests/kernel/queue/boards/intel_adsp_ace30_ptl.conf b/tests/kernel/queue/boards/intel_adsp_ace30_ptl.conf new file mode 100644 index 0000000000000..922c1e4b05f34 --- /dev/null +++ b/tests/kernel/queue/boards/intel_adsp_ace30_ptl.conf @@ -0,0 +1 @@ +CONFIG_MAX_THREAD_BYTES=3 From 5df1df2e7ae3c8a9e57f4cd29c07ffcda78c58d0 Mon Sep 17 00:00:00 2001 From: Anas Nashif Date: Fri, 17 May 2024 12:53:01 +0000 Subject: [PATCH 1954/2849] Revert "drivers/console/xtensa_sim_console: force `\r\n` byte sequence" This reverts commit 99aa65c72532315a614871648034af83cd29e442. With this change, various simulators fail with no output with this change. Signed-off-by: Anas Nashif --- drivers/console/xtensa_sim_console.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/drivers/console/xtensa_sim_console.c b/drivers/console/xtensa_sim_console.c index 1d52f93af73e2..316162ddc0c1a 100644 --- a/drivers/console/xtensa_sim_console.c +++ b/drivers/console/xtensa_sim_console.c @@ -25,14 +25,6 @@ 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 c1a3bfb5f4a6760111f08167e1e6afdfa6a5cf3c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20J=C3=A4ger?= Date: Tue, 4 Jun 2024 14:42:32 +0200 Subject: [PATCH 1955/2849] scripts: set_assignees.py: Use "size: XS" label for one-liners MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Previously, one-line changes were tagged as "Trivial". The description of the "Trivial" label states: "Changes that can be reviewed by anyone, i.e. doc changes, minor build system tweaks, etc.". Just because a change only affects a single line of code, it does not mean that it is a trivial change. It may have difficult to understand implications which require approval of the responsible maintainer. For this reason, change the label to "size: XS" and let humans judge if a PR is trivial or not. Signed-off-by: Martin Jäger --- scripts/set_assignees.py | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/scripts/set_assignees.py b/scripts/set_assignees.py index d209193158592..679735414c3ed 100755 --- a/scripts/set_assignees.py +++ b/scripts/set_assignees.py @@ -70,15 +70,12 @@ def process_pr(gh, maintainer_file, number): all_areas = set() fn = list(pr.get_files()) - manifest_change = False for changed_file in fn: if changed_file.filename in ['west.yml','submanifests/optional.yaml']: - manifest_change = True break - # one liner PRs should be trivial - if pr.commits == 1 and (pr.additions <= 1 and pr.deletions <= 1) and not manifest_change: - labels = {'Trivial'} + if pr.commits == 1 and (pr.additions <= 1 and pr.deletions <= 1): + labels = {'size: XS'} if len(fn) > 500: log(f"Too many files changed ({len(fn)}), skipping....") From 6f7fd7a306ffbd2ea2ce5a75359ffbf8280a3732 Mon Sep 17 00:00:00 2001 From: David Leach Date: Mon, 3 Jun 2024 21:58:53 -0500 Subject: [PATCH 1956/2849] doc: project roles: reviewer and assignee clarification Clarification of reviewer expectations and role. Emphasis on clarifying when a PR can be closed. Highlighting reviewers and assignee objective to guide PR to a mergeable state, if possible. Signed-off-by: David Leach --- doc/contribute/contributor_expectations.rst | 8 ++++++++ doc/project/project_roles.rst | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/doc/contribute/contributor_expectations.rst b/doc/contribute/contributor_expectations.rst index cba1627a1b9be..88fe625c00525 100644 --- a/doc/contribute/contributor_expectations.rst +++ b/doc/contribute/contributor_expectations.rst @@ -276,6 +276,9 @@ Reviewer Expectations #. PRs assigned to the reviewer as the area maintainer. #. All other PRs. +- Reviewers shall strive to advance the PR to a mergeable state with their + feedback and engagement with the PR author. + - Try to provide feedback on the entire PR in one shot. This provides the contributor an opportunity to address all comments in the next PR update. @@ -305,6 +308,11 @@ Reviewer Expectations the PR in question and following the contribution and style guidelines of the project. +- Reviewers shall not close a PR due to technical or structural disagreement. + If requested changes cannot be resolved within the review process, the + :ref:`pr_technical_escalation` path shall be used for any potential resolution + path, which may include closing the PR. + .. _Code of Conduct: https://github.com/zephyrproject-rtos/zephyr/blob/main/CODE_OF_CONDUCT.md .. _Zephyr Release Plan: https://github.com/orgs/zephyrproject-rtos/projects/13 diff --git a/doc/project/project_roles.rst b/doc/project/project_roles.rst index a57a7b46def4b..f354ba26cdd6c 100644 --- a/doc/project/project_roles.rst +++ b/doc/project/project_roles.rst @@ -159,6 +159,7 @@ Assignees are set either automatically based on the code being changed or set by the other Maintainers, the Release Engineering team can set an assignee when the latter is not possible. +* Responsibility to drive the pull request to a mergeable state * Right to dismiss stale and unrelated reviews or reviews not following :ref:`expectations ` from reviewers and seek reviews from additional maintainers, developers and contributors @@ -166,7 +167,6 @@ the latter is not possible. requested are addressed * Responsibility to re-assign a pull request if they are the original submitter of the code -* Responsibility to drive the pull request to a mergeable state * Solicit approvals from maintainers of the subsystems affected * Responsibility to drive the :ref:`pr_technical_escalation` process From dc5f27395f393bd62f244a6fc32af3809c56dd29 Mon Sep 17 00:00:00 2001 From: Jordan Yates Date: Mon, 27 May 2024 21:11:14 +1000 Subject: [PATCH 1957/2849] testsuite: add dependency to `COVERAGE_GCOV_HEAP_SIZE` Add missing dependency on `COVERAGE_GCOV` to prevent the symbol from appearing in every application. Signed-off-by: Jordan Yates --- subsys/testsuite/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/subsys/testsuite/Kconfig b/subsys/testsuite/Kconfig index 2ae331eb438a3..490fec5cdce88 100644 --- a/subsys/testsuite/Kconfig +++ b/subsys/testsuite/Kconfig @@ -74,6 +74,7 @@ endchoice config COVERAGE_GCOV_HEAP_SIZE int "Size of heap allocated for gcov coverage data dump" + depends on COVERAGE_GCOV default 32768 if X86 || SOC_SERIES_MPS2 default 16384 help From 6f0c836337329620f7838dbdc7b14649dd53133a Mon Sep 17 00:00:00 2001 From: Fengming Ye Date: Wed, 29 May 2024 17:59:17 +0900 Subject: [PATCH 1958/2849] hostap: add crypto backend alt for enterprise and DPP Add kconfig CONFIG_WIFI_NM_WPA_SUPPLICANT_CRYPTO_ALT to get more mbedtls functionality for enterprise and DPP. Split cmake sources related to hostap SME and crypto backend. Default backend CONFIG_WIFI_NM_WPA_SUPPLICANT_CRYPTO use internal crypto and some mbedtls apis. Backend CONFIG_WIFI_NM_WPA_SUPPLICANT_CRYPTO_ALT use most mbedtls apis and PSA apis, except some apis no longer supported in mbedtls 3.x, or called in the middle of hostap and mbedtls. Signed-off-by: Fengming Ye --- modules/hostap/CMakeLists.txt | 111 ++++++++++++++++++++-------------- modules/hostap/Kconfig | 22 +++++++ 2 files changed, 88 insertions(+), 45 deletions(-) diff --git a/modules/hostap/CMakeLists.txt b/modules/hostap/CMakeLists.txt index b340c3882c8b7..66968e0e249eb 100644 --- a/modules/hostap/CMakeLists.txt +++ b/modules/hostap/CMakeLists.txt @@ -225,17 +225,6 @@ zephyr_library_sources_ifndef(CONFIG_WIFI_NM_WPA_SUPPLICANT_CRYPTO_NONE ${HOSTAP_SRC_BASE}/rsn_supp/wpa.c ${HOSTAP_SRC_BASE}/rsn_supp/preauth.c ${HOSTAP_SRC_BASE}/rsn_supp/wpa_ie.c - ${HOSTAP_SRC_BASE}/crypto/crypto_mbedtls-bignum.c - ${HOSTAP_SRC_BASE}/crypto/crypto_mbedtls-ec.c - ${HOSTAP_SRC_BASE}/crypto/crypto_mbedtls.c - ${HOSTAP_SRC_BASE}/crypto/tls_mbedtls.c - ${HOSTAP_SRC_BASE}/crypto/aes-wrap.c - ${HOSTAP_SRC_BASE}/crypto/aes-unwrap.c - ${HOSTAP_SRC_BASE}/crypto/rc4.c - ${HOSTAP_SRC_BASE}/crypto/sha1-prf.c - ${HOSTAP_SRC_BASE}/crypto/sha256-prf.c - ${HOSTAP_SRC_BASE}/crypto/sha256-prf.c - ${HOSTAP_SRC_BASE}/crypto/sha384-prf.c ) zephyr_library_sources_ifdef(CONFIG_WIFI_NM_WPA_SUPPLICANT_WPA3 @@ -243,7 +232,6 @@ zephyr_library_sources_ifdef(CONFIG_WIFI_NM_WPA_SUPPLICANT_WPA3 ${HOSTAP_SRC_BASE}/common/dragonfly.c ${HOSTAP_SRC_BASE}/crypto/dh_groups.c - ${HOSTAP_SRC_BASE}/crypto/sha256-kdf.c ) zephyr_library_compile_definitions_ifdef(CONFIG_WIFI_NM_WPA_SUPPLICANT_WPA3 @@ -255,9 +243,6 @@ zephyr_library_include_directories_ifndef(CONFIG_WIFI_NM_WPA_SUPPLICANT_CRYPTO_N ${CMAKE_SOURCE_DIR} ) -zephyr_library_link_libraries_ifndef(CONFIG_WIFI_NM_WPA_SUPPLICANT_CRYPTO_NONE - mbedTLS) - zephyr_library_sources_ifdef(CONFIG_WIFI_NM_WPA_SUPPLICANT_P2P ${WIFI_NM_WPA_SUPPLICANT_BASE}/p2p_supplicant.c ${WIFI_NM_WPA_SUPPLICANT_BASE}/p2p_supplicant_sd.c @@ -305,26 +290,7 @@ zephyr_library_compile_definitions_ifdef(CONFIG_WIFI_NM_WPA_SUPPLICANT_WPS EAP_WSC ) -zephyr_library_sources_ifndef(CONFIG_WIFI_NM_WPA_SUPPLICANT_CRYPTO_NONE - ${HOSTAP_SRC_BASE}/common/wpa_common.c - ${HOSTAP_SRC_BASE}/rsn_supp/wpa.c - ${HOSTAP_SRC_BASE}/rsn_supp/preauth.c - ${HOSTAP_SRC_BASE}/rsn_supp/wpa_ie.c - - ${HOSTAP_SRC_BASE}/crypto/crypto_mbedtls-bignum.c - ${HOSTAP_SRC_BASE}/crypto/crypto_mbedtls-ec.c - ${HOSTAP_SRC_BASE}/crypto/crypto_mbedtls.c - ${HOSTAP_SRC_BASE}/crypto/aes-wrap.c - ${HOSTAP_SRC_BASE}/crypto/aes-unwrap.c - ${HOSTAP_SRC_BASE}/crypto/rc4.c - ${HOSTAP_SRC_BASE}/crypto/sha1-prf.c - ${HOSTAP_SRC_BASE}/crypto/sha256-prf.c - ${HOSTAP_SRC_BASE}/crypto/sha256-prf.c - ${HOSTAP_SRC_BASE}/crypto/sha384-prf.c -) - zephyr_library_sources_ifdef(CONFIG_WIFI_NM_WPA_SUPPLICANT_CRYPTO_ENTERPRISE - ${HOSTAP_SRC_BASE}/crypto/tls_mbedtls.c ${HOSTAP_SRC_BASE}/eap_peer/eap_tls.c ${HOSTAP_SRC_BASE}/eap_peer/eap_tls_common.c @@ -364,17 +330,6 @@ zephyr_library_sources_ifdef(CONFIG_WIFI_NM_WPA_SUPPLICANT_CRYPTO_ENTERPRISE ${HOSTAP_SRC_BASE}/eap_common/eap_ikev2_common.c ${HOSTAP_SRC_BASE}/eap_common/ikev2_common.c - # common - ${HOSTAP_SRC_BASE}/crypto/sha384-tlsprf.c - ${HOSTAP_SRC_BASE}/crypto/sha256-tlsprf.c - ${HOSTAP_SRC_BASE}/crypto/sha1-tlsprf.c - ${HOSTAP_SRC_BASE}/crypto/sha1-tprf.c - ${HOSTAP_SRC_BASE}/crypto/ms_funcs.c - ${HOSTAP_SRC_BASE}/crypto/aes-eax.c - # MD4 removed from MbedTLS - ${HOSTAP_SRC_BASE}/crypto/md4-internal - ${HOSTAP_SRC_BASE}/crypto/aes-encblock.c - ) zephyr_library_compile_definitions_ifdef(CONFIG_WIFI_NM_WPA_SUPPLICANT_CRYPTO_ENTERPRISE @@ -410,4 +365,70 @@ zephyr_library_compile_definitions_ifdef(CONFIG_WIFI_NM_WPA_SUPPLICANT_EAPOL zephyr_library_compile_definitions_ifdef(CONFIG_WIFI_NM_WPA_SUPPLICANT_NW_SEL_RELIABILITY CONFIG_NW_SEL_RELIABILITY ) + +# crypto mbedtls related +if(CONFIG_WIFI_NM_WPA_SUPPLICANT_CRYPTO) +zephyr_library_sources( + ${HOSTAP_SRC_BASE}/crypto/crypto_mbedtls-bignum.c + ${HOSTAP_SRC_BASE}/crypto/crypto_mbedtls-ec.c + ${HOSTAP_SRC_BASE}/crypto/crypto_mbedtls.c + ${HOSTAP_SRC_BASE}/crypto/tls_mbedtls.c + ${HOSTAP_SRC_BASE}/crypto/aes-internal.c + ${HOSTAP_SRC_BASE}/crypto/aes-wrap.c + ${HOSTAP_SRC_BASE}/crypto/aes-unwrap.c + ${HOSTAP_SRC_BASE}/crypto/rc4.c + ${HOSTAP_SRC_BASE}/crypto/sha1-internal.c + ${HOSTAP_SRC_BASE}/crypto/sha1-prf.c + ${HOSTAP_SRC_BASE}/crypto/sha1-tlsprf.c + ${HOSTAP_SRC_BASE}/crypto/sha256-prf.c + ${HOSTAP_SRC_BASE}/crypto/sha256-kdf.c + ${HOSTAP_SRC_BASE}/crypto/sha384-prf.c + ${HOSTAP_SRC_BASE}/crypto/sha384-kdf.c + ${HOSTAP_SRC_BASE}/crypto/sha512-internal.c + ${HOSTAP_SRC_BASE}/crypto/sha512.c + ${HOSTAP_SRC_BASE}/crypto/sha512-prf.c + ${HOSTAP_SRC_BASE}/crypto/sha512-kdf.c +) + +zephyr_library_sources_ifdef(CONFIG_WIFI_NM_WPA_SUPPLICANT_WPA3 + ${HOSTAP_SRC_BASE}/crypto/sha256-kdf.c +) + +zephyr_library_sources_ifdef(CONFIG_WIFI_NM_WPA_SUPPLICANT_CRYPTO_ENTERPRISE + # common + ${HOSTAP_SRC_BASE}/crypto/sha384-tlsprf.c + ${HOSTAP_SRC_BASE}/crypto/sha256-tlsprf.c + ${HOSTAP_SRC_BASE}/crypto/sha1-tlsprf.c + ${HOSTAP_SRC_BASE}/crypto/sha1-tprf.c + ${HOSTAP_SRC_BASE}/crypto/ms_funcs.c + ${HOSTAP_SRC_BASE}/crypto/aes-eax.c + # MD4 removed from MbedTLS + ${HOSTAP_SRC_BASE}/crypto/md4-internal.c + ${HOSTAP_SRC_BASE}/crypto/aes-encblock.c +) +endif() + +if(CONFIG_WIFI_NM_WPA_SUPPLICANT_CRYPTO_ALT) +zephyr_include_directories( + ${HOSTAP_BASE}/port/mbedtls +) + +zephyr_library_sources( + ${HOSTAP_SRC_BASE}/crypto/crypto_mbedtls_alt.c + ${HOSTAP_SRC_BASE}/crypto/tls_mbedtls_alt.c + ${HOSTAP_SRC_BASE}/crypto/rc4.c +) + +zephyr_library_sources_ifdef(CONFIG_WIFI_NM_WPA_SUPPLICANT_CRYPTO_ENTERPRISE + ${HOSTAP_SRC_BASE}/crypto/ms_funcs.c + ${HOSTAP_SRC_BASE}/crypto/aes-eax.c + ${HOSTAP_SRC_BASE}/crypto/md4-internal.c + ${HOSTAP_SRC_BASE}/crypto/fips_prf_internal.c + ${HOSTAP_SRC_BASE}/crypto/milenage.c +) +endif() + +zephyr_library_link_libraries_ifndef(CONFIG_WIFI_NM_WPA_SUPPLICANT_CRYPTO_NONE + mbedTLS) + endif() diff --git a/modules/hostap/Kconfig b/modules/hostap/Kconfig index 18bfc036c0578..6ee245a11efe4 100644 --- a/modules/hostap/Kconfig +++ b/modules/hostap/Kconfig @@ -106,6 +106,8 @@ choice WIFI_NM_WPA_SUPPLICANT_CRYPTO_BACKEND default WIFI_NM_WPA_SUPPLICANT_CRYPTO help Select the crypto implementation to use for WPA supplicant. + WIFI_NM_WPA_SUPPLICANT_CRYPTO_ALT support enterprise + and DPP. And use Mbedtls PSA apis for HW acceleration. config WIFI_NM_WPA_SUPPLICANT_CRYPTO bool "Crypto support for WiFi" @@ -125,6 +127,26 @@ config WIFI_NM_WPA_SUPPLICANT_CRYPTO select MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED select MBEDTLS_KEY_EXCHANGE_ALL_ENABLED +config WIFI_NM_WPA_SUPPLICANT_CRYPTO_ALT + bool "Crypto Mbedtls alt support for WiFi" + select MBEDTLS + select MBEDTLS_CIPHER_MODE_CTR_ENABLED + select MBEDTLS_CIPHER_MODE_CBC_ENABLED + select MBEDTLS_ECP_C + select MBEDTLS_ECP_ALL_ENABLED + select MBEDTLS_CMAC + select MBEDTLS_PKCS5_C + select MBEDTLS_PK_WRITE_C + select MBEDTLS_ECDH_C + select MBEDTLS_ECDSA_C + select MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED + select MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED + select MBEDTLS_NIST_KW_C + select MBEDTLS_DHM_C + select MBEDTLS_HKDF_C + select MBEDTLS_SERVER_NAME_INDICATION + select MBEDTLS_X509_CRL_PARSE_C + config WIFI_NM_WPA_SUPPLICANT_CRYPTO_NONE bool "No Crypto support for WiFi" From d3b3aa1c35e9ff73e1197113653fa713f4e40208 Mon Sep 17 00:00:00 2001 From: Fengming Ye Date: Wed, 29 May 2024 18:09:41 +0900 Subject: [PATCH 1959/2849] hostap: add PSA apis support for mbedtls 3.x Add Platform Secure Architecture support support to use HW acceleration, which needs to be called under PSA driver wrapper in mbedtls 3.x. Signed-off-by: Fengming Ye --- modules/hostap/CMakeLists.txt | 4 ++++ modules/hostap/Kconfig | 6 ++++++ modules/hostap/src/supp_main.c | 7 +++++++ 3 files changed, 17 insertions(+) diff --git a/modules/hostap/CMakeLists.txt b/modules/hostap/CMakeLists.txt index 66968e0e249eb..de1c18f8e93a3 100644 --- a/modules/hostap/CMakeLists.txt +++ b/modules/hostap/CMakeLists.txt @@ -419,6 +419,10 @@ zephyr_library_sources( ${HOSTAP_SRC_BASE}/crypto/rc4.c ) +zephyr_library_sources_ifdef(CONFIG_WIFI_NM_WPA_SUPPLICANT_CRYPTO_MBEDTLS_PSA + ${HOSTAP_BASE}/port/mbedtls/supp_psa_api.c +) + zephyr_library_sources_ifdef(CONFIG_WIFI_NM_WPA_SUPPLICANT_CRYPTO_ENTERPRISE ${HOSTAP_SRC_BASE}/crypto/ms_funcs.c ${HOSTAP_SRC_BASE}/crypto/aes-eax.c diff --git a/modules/hostap/Kconfig b/modules/hostap/Kconfig index 6ee245a11efe4..18db195690b85 100644 --- a/modules/hostap/Kconfig +++ b/modules/hostap/Kconfig @@ -152,6 +152,12 @@ config WIFI_NM_WPA_SUPPLICANT_CRYPTO_NONE endchoice +config WIFI_NM_WPA_SUPPLICANT_CRYPTO_MBEDTLS_PSA + bool "Crypto Platform Secure Architecture support for WiFi" + default y if WIFI_NM_WPA_SUPPLICANT_CRYPTO_ALT + help + Support Mbedtls 3.x to use PSA apis instead of legacy apis. + config WIFI_NM_WPA_SUPPLICANT_CRYPTO_ENTERPRISE bool "Enterprise Crypto support for WiFi" depends on !WIFI_NM_WPA_SUPPLICANT_CRYPTO_NONE diff --git a/modules/hostap/src/supp_main.c b/modules/hostap/src/supp_main.c index 69a4dd8438b11..80d90c70fb6d8 100644 --- a/modules/hostap/src/supp_main.c +++ b/modules/hostap/src/supp_main.c @@ -14,6 +14,9 @@ LOG_MODULE_REGISTER(wifi_supplicant, CONFIG_WIFI_NM_WPA_SUPPLICANT_LOG_LEVEL); #if !defined(CONFIG_WIFI_NM_WPA_SUPPLICANT_CRYPTO_NONE) && !defined(CONFIG_MBEDTLS_ENABLE_HEAP) #include #endif /* !CONFIG_WIFI_NM_WPA_SUPPLICANT_CRYPTO_NONE && !CONFIG_MBEDTLS_ENABLE_HEAP */ +#ifdef CONFIG_WIFI_NM_WPA_SUPPLICANT_CRYPTO_MBEDTLS_PSA +#include "supp_psa_api.h" +#endif #include #include @@ -523,6 +526,10 @@ static void handler(void) mbedtls_platform_set_calloc_free(calloc, free); #endif /* !CONFIG_WIFI_NM_WPA_SUPPLICANT_CRYPTO_NONE && !CONFIG_MBEDTLS_ENABLE_HEAP */ +#ifdef CONFIG_WIFI_NM_WPA_SUPPLICANT_CRYPTO_MBEDTLS_PSA + supp_psa_crypto_init(); +#endif + ctx = get_default_context(); k_work_queue_init(&ctx->iface_wq); From 271d7084b5349e77b0d6debc6bdbd1b867b3647b Mon Sep 17 00:00:00 2001 From: Fengming Ye Date: Wed, 29 May 2024 18:13:18 +0900 Subject: [PATCH 1960/2849] hostap: add DPP support Add kconfig and cmake to support DPP (Easy Connect). Signed-off-by: Fengming Ye --- modules/hostap/CMakeLists.txt | 27 +++++++++++++++++++++++++++ modules/hostap/Kconfig | 24 ++++++++++++++++++++++++ 2 files changed, 51 insertions(+) diff --git a/modules/hostap/CMakeLists.txt b/modules/hostap/CMakeLists.txt index de1c18f8e93a3..5ed4d052ab692 100644 --- a/modules/hostap/CMakeLists.txt +++ b/modules/hostap/CMakeLists.txt @@ -366,6 +366,33 @@ zephyr_library_compile_definitions_ifdef(CONFIG_WIFI_NM_WPA_SUPPLICANT_NW_SEL_RE CONFIG_NW_SEL_RELIABILITY ) +zephyr_library_sources_ifdef(CONFIG_WIFI_NM_WPA_SUPPLICANT_DPP + ${WIFI_NM_WPA_SUPPLICANT_BASE}/dpp_supplicant.c + ${WIFI_NM_WPA_SUPPLICANT_BASE}/offchannel.c + ${WIFI_NM_WPA_SUPPLICANT_BASE}/gas_query.c + + ${HOSTAP_SRC_BASE}/ap/dpp_hostapd.c + ${HOSTAP_SRC_BASE}/ap/gas_query_ap.c + ${HOSTAP_SRC_BASE}/ap/gas_serv.c + + ${HOSTAP_SRC_BASE}/common/dpp_tcp.c + ${HOSTAP_SRC_BASE}/common/dpp.c + ${HOSTAP_SRC_BASE}/common/dpp_pkex.c + ${HOSTAP_SRC_BASE}/common/dpp_crypto.c + ${HOSTAP_SRC_BASE}/common/dpp_auth.c + ${HOSTAP_SRC_BASE}/common/dpp_reconfig.c + ${HOSTAP_SRC_BASE}/common/gas_server.c + ${HOSTAP_SRC_BASE}/common/gas.c + ${HOSTAP_SRC_BASE}/common/dpp_backup.c + + ${HOSTAP_SRC_BASE}/crypto/aes-siv.c + + ${HOSTAP_SRC_BASE}/utils/json.c + ${HOSTAP_SRC_BASE}/utils/ip_addr.c + + ${HOSTAP_SRC_BASE}/tls/asn1.c +) + # crypto mbedtls related if(CONFIG_WIFI_NM_WPA_SUPPLICANT_CRYPTO) zephyr_library_sources( diff --git a/modules/hostap/Kconfig b/modules/hostap/Kconfig index 18db195690b85..eec675e9f22ef 100644 --- a/modules/hostap/Kconfig +++ b/modules/hostap/Kconfig @@ -202,6 +202,18 @@ config WIFI_NM_WPA_SUPPLICANT_BSS_MAX_IDLE_TIME config WIFI_NM_WPA_SUPPLICANT_NO_DEBUG bool "Disable printing of debug messages, saves code size significantly" + +config WIFI_NM_WPA_SUPPLICANT_DPP + bool "WFA Easy Connect DPP" + select DPP + select DPP2 + select DPP3 + select GAS + select GAS_SERVER + select OFFCHANNEL + select MBEDTLS_X509_CSR_WRITE_C + select MBEDTLS_X509_CSR_PARSE_C + # Create hidden config options that are used in hostap. This way we do not need # to mark them as allowed for CI checks, and also someone else cannot use the # same name options. @@ -282,6 +294,9 @@ config P2P config GAS bool +config GAS_SERVER + bool + config OFFCHANNEL bool @@ -386,6 +401,15 @@ config RRM config WMM_AC bool +config DPP + bool + +config DPP2 + bool + +config DPP3 + bool + config NW_SEL_RELIABILITY bool default y From bdb0768882b8bf4051e96e416407067d065dd42f Mon Sep 17 00:00:00 2001 From: Fengming Ye Date: Wed, 29 May 2024 18:18:01 +0900 Subject: [PATCH 1961/2849] hostap: remove CONFIG_NO_PBKDF2 and CONFIG_NO_CONFIG_BLOBS in cmake Remove CONFIG_NO_PBKDF2 and CONFIG_NO_CONFIG_BLOBS definition and let them be decided in kconfig. CONFIG_NO_PBKDF2 is default y when crypto backend is WIFI_NM_WPA_SUPPLICANT_CRYPTO_NONE. CONFIG_NO_CONFIG_BLOBS is default y when both DPP and enterprise disable. Signed-off-by: Fengming Ye --- modules/hostap/CMakeLists.txt | 5 ----- modules/hostap/Kconfig | 4 ++-- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/modules/hostap/CMakeLists.txt b/modules/hostap/CMakeLists.txt index 5ed4d052ab692..2fcc11730ce9c 100644 --- a/modules/hostap/CMakeLists.txt +++ b/modules/hostap/CMakeLists.txt @@ -25,7 +25,6 @@ zephyr_library_compile_definitions( TLS_DEFAULT_CIPHERS=\""DEFAULT:!EXP:!LOW"\" CONFIG_SME CONFIG_NO_CONFIG_WRITE - CONFIG_NO_CONFIG_BLOBS CONFIG_CTRL_IFACE CONFIG_NO_RANDOM_POOL CONFIG_SHA256 @@ -76,10 +75,6 @@ zephyr_library_include_directories( ${ZEPHYR_BASE}/include/net ) -zephyr_library_compile_definitions_ifndef(CONFIG_WIFI_NM_WPA_SUPPLICANT_CRYPTO - CONFIG_NO_PBKDF2 -) - zephyr_library_compile_definitions_ifdef(CONFIG_WIFI_NM_WPA_SUPPLICANT_NO_DEBUG CONFIG_NO_STDOUT_DEBUG ) diff --git a/modules/hostap/Kconfig b/modules/hostap/Kconfig index eec675e9f22ef..f90ab2c0b8833 100644 --- a/modules/hostap/Kconfig +++ b/modules/hostap/Kconfig @@ -228,7 +228,7 @@ config NO_CONFIG_WRITE config NO_CONFIG_BLOBS bool - default y + default y if !WIFI_NM_WPA_SUPPLICANT_DPP && !WIFI_NM_WPA_SUPPLICANT_CRYPTO_ENTERPRISE config CTRL_IFACE bool @@ -251,7 +251,7 @@ config NO_WPA config NO_PBKDF2 bool - default y + default y if WIFI_NM_WPA_SUPPLICANT_CRYPTO_NONE config SAE_PK bool From 1bfa73d036fe37aafdb2c894122a0ed8e8047d91 Mon Sep 17 00:00:00 2001 From: Fengming Ye Date: Wed, 29 May 2024 18:22:09 +0900 Subject: [PATCH 1962/2849] hostap: add enterprise source files in cmake Add enterprise needed source files. Signed-off-by: Fengming Ye --- modules/hostap/CMakeLists.txt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/modules/hostap/CMakeLists.txt b/modules/hostap/CMakeLists.txt index 2fcc11730ce9c..a7e3aa334bdfa 100644 --- a/modules/hostap/CMakeLists.txt +++ b/modules/hostap/CMakeLists.txt @@ -288,6 +288,7 @@ zephyr_library_compile_definitions_ifdef(CONFIG_WIFI_NM_WPA_SUPPLICANT_WPS zephyr_library_sources_ifdef(CONFIG_WIFI_NM_WPA_SUPPLICANT_CRYPTO_ENTERPRISE ${HOSTAP_SRC_BASE}/eap_peer/eap_tls.c ${HOSTAP_SRC_BASE}/eap_peer/eap_tls_common.c + ${HOSTAP_SRC_BASE}/eap_common/eap_common.c ${HOSTAP_SRC_BASE}/eap_peer/eap_peap.c ${HOSTAP_SRC_BASE}/eap_common/eap_peap_common.c @@ -325,6 +326,10 @@ zephyr_library_sources_ifdef(CONFIG_WIFI_NM_WPA_SUPPLICANT_CRYPTO_ENTERPRISE ${HOSTAP_SRC_BASE}/eap_common/eap_ikev2_common.c ${HOSTAP_SRC_BASE}/eap_common/ikev2_common.c + ${HOSTAP_SRC_BASE}/eap_peer/eap_sim.c + ${HOSTAP_SRC_BASE}/eap_common/eap_sim_common.c + + ${HOSTAP_SRC_BASE}/eap_peer/eap_aka.c ) zephyr_library_compile_definitions_ifdef(CONFIG_WIFI_NM_WPA_SUPPLICANT_CRYPTO_ENTERPRISE From edd0ed733969a08784bdb5e2217f710ddafd9f1c Mon Sep 17 00:00:00 2001 From: Fengming Ye Date: Mon, 27 May 2024 19:05:43 +0900 Subject: [PATCH 1963/2849] mbedtls: add kconfig options Add MBEDTLS_NIST_KW_C, MBEDTLS_DHM_C and X509 CRL, CSR options. Signed-off-by: Fengming Ye --- modules/mbedtls/Kconfig.tls-generic | 28 ++++++++++++++++++++ modules/mbedtls/configs/config-tls-generic.h | 21 +++++++++++++++ 2 files changed, 49 insertions(+) diff --git a/modules/mbedtls/Kconfig.tls-generic b/modules/mbedtls/Kconfig.tls-generic index 7a7105287a505..0fc2d57818b6d 100644 --- a/modules/mbedtls/Kconfig.tls-generic +++ b/modules/mbedtls/Kconfig.tls-generic @@ -510,4 +510,32 @@ config MBEDTLS_SSL_DTLS_CONNECTION_ID which allows to identify DTLS connections across changes in the underlying transport. + +config MBEDTLS_NIST_KW_C + bool "NIST key wrap" + depends on MBEDTLS_CIPHER_AES_ENABLED + help + Key Wrapping mode for 128-bit block ciphers, + as defined in NIST SP 800-38F. + +config MBEDTLS_DHM_C + bool "Diffie-Hellman-Merkle mode" + help + Used by the following key exchanges, + DHE-RSA, DHE-PSK + +config MBEDTLS_X509_CRL_PARSE_C + bool "X509 CRL parsing" + help + Used by X509 CRL parsing + +config MBEDTLS_X509_CSR_WRITE_C + bool "X509 Certificate Signing Requests writing" + help + For X.509 certificate request writing. + +config MBEDTLS_X509_CSR_PARSE_C + bool "X509 Certificate Signing Request parsing" + help + For reading X.509 certificate request. endmenu diff --git a/modules/mbedtls/configs/config-tls-generic.h b/modules/mbedtls/configs/config-tls-generic.h index 850b27d80d671..623986777dd24 100644 --- a/modules/mbedtls/configs/config-tls-generic.h +++ b/modules/mbedtls/configs/config-tls-generic.h @@ -485,6 +485,27 @@ #define MBEDTLS_SSL_DTLS_CONNECTION_ID #endif +#if defined(CONFIG_MBEDTLS_NIST_KW_C) +#define MBEDTLS_NIST_KW_C +#endif + +#if defined(CONFIG_MBEDTLS_DHM_C) +#define MBEDTLS_DHM_C +#endif + +#if defined(CONFIG_MBEDTLS_X509_CRL_PARSE_C) +#define MBEDTLS_X509_CRL_PARSE_C +#endif + +#if defined(CONFIG_MBEDTLS_X509_CSR_WRITE_C) +#define MBEDTLS_X509_CSR_WRITE_C +#define MBEDTLS_X509_CREATE_C +#endif + +#if defined(CONFIG_MBEDTLS_X509_CSR_PARSE_C) +#define MBEDTLS_X509_CSR_PARSE_C +#endif + #if defined(CONFIG_MBEDTLS_USER_CONFIG_FILE) #include CONFIG_MBEDTLS_USER_CONFIG_FILE #endif From 3ce3ed38ba462bce1a7a625211da775a43c61351 Mon Sep 17 00:00:00 2001 From: Daniel DeGrasse Date: Wed, 15 May 2024 22:26:04 +0000 Subject: [PATCH 1964/2849] drivers: video: ov7670: introduce driver for ov7670 camera Introduce driver for ov7670 camera, supporting QCIF,QVGA,CIF, and VGA resolution in YUV and RGB mode. Support was verified on the FRDM-MCXN947, using the SmartDMA camera engine, which is enabled in the following PR: https://github.com/zephyrproject-rtos/zephyr/pull/72827 Signed-off-by: Daniel DeGrasse --- drivers/video/CMakeLists.txt | 1 + drivers/video/Kconfig | 2 + drivers/video/Kconfig.ov7670 | 10 + drivers/video/ov7670.c | 488 ++++++++++++++++++++++++++++ dts/bindings/video/ovti,ov7670.yaml | 20 ++ 5 files changed, 521 insertions(+) create mode 100644 drivers/video/Kconfig.ov7670 create mode 100644 drivers/video/ov7670.c create mode 100644 dts/bindings/video/ovti,ov7670.yaml diff --git a/drivers/video/CMakeLists.txt b/drivers/video/CMakeLists.txt index 19ad0e2bc797e..2e52d1f66ea88 100644 --- a/drivers/video/CMakeLists.txt +++ b/drivers/video/CMakeLists.txt @@ -12,3 +12,4 @@ 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) +zephyr_library_sources_ifdef(CONFIG_VIDEO_OV7670 ov7670.c) diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index 787311622e0cc..d6a6bd3ccce66 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -47,4 +47,6 @@ source "drivers/video/Kconfig.stm32_dcmi" source "drivers/video/Kconfig.ov5640" +source "drivers/video/Kconfig.ov7670" + endif # VIDEO diff --git a/drivers/video/Kconfig.ov7670 b/drivers/video/Kconfig.ov7670 new file mode 100644 index 0000000000000..9a2a1d70f3d90 --- /dev/null +++ b/drivers/video/Kconfig.ov7670 @@ -0,0 +1,10 @@ +# Copyright 2024 NXP +# SPDX-License-Identifier: Apache-2.0 + +config VIDEO_OV7670 + bool "OV7670 CMOS digital image sensor" + select I2C + depends on DT_HAS_OVTI_OV7670_ENABLED + default y + help + Enable driver for OV7670 CMOS digital image sensor device. diff --git a/drivers/video/ov7670.c b/drivers/video/ov7670.c new file mode 100644 index 0000000000000..96cb3f860db1f --- /dev/null +++ b/drivers/video/ov7670.c @@ -0,0 +1,488 @@ +/* + * Copyright 2024 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT ovti_ov7670 + +#include +#include +#include + +#define LOG_LEVEL CONFIG_LOG_DEFAULT_LEVEL +#include +LOG_MODULE_REGISTER(ov7670); + +/* Initialization register structure */ +struct ov7670_reg { + uint8_t reg; + uint8_t cmd; +}; + +struct ov7670_config { + struct i2c_dt_spec bus; +#if DT_ANY_INST_HAS_PROP_STATUS_OKAY(reset_gpios) + struct gpio_dt_spec reset; +#endif +#if DT_ANY_INST_HAS_PROP_STATUS_OKAY(pwdn_gpios) + struct gpio_dt_spec pwdn; +#endif +}; + +struct ov7670_data { + struct video_format fmt; +}; + +/* OV7670 registers */ +#define OV7670_PID 0x0A +#define OV7670_COM7 0x12 +#define OV7670_MVFP 0x1E +#define OV7670_COM10 0x15 +#define OV7670_COM12 0x3C +#define OV7670_BRIGHT 0x55 +#define OV7670_CLKRC 0x11 +#define OV7670_SCALING_PCLK_DIV 0x73 +#define OV7670_COM14 0x3E +#define OV7670_DBLV 0x6B +#define OV7670_SCALING_XSC 0x70 +#define OV7670_SCALING_YSC 0x71 +#define OV7670_COM2 0x09 +#define OV7670_SCALING_PCLK_DELAY 0xA2 +#define OV7670_BD50MAX 0xA5 +#define OV7670_BD60MAX 0xAB +#define OV7670_HAECC7 0xAA +#define OV7670_COM3 0x0C +#define OV7670_COM4 0x0D +#define OV7670_COM6 0x0F +#define OV7670_COM11 0x3B +#define OV7670_EDGE 0x3F +#define OV7670_DNSTH 0x4C +#define OV7670_DM_LNL 0x92 +#define OV7670_DM_LNH 0x93 +#define OV7670_COM15 0x40 +#define OV7670_TSLB 0x3A +#define OV7670_COM13 0x3D +#define OV7670_MANU 0x67 +#define OV7670_MANV 0x68 +#define OV7670_HSTART 0x17 +#define OV7670_HSTOP 0x18 +#define OV7670_VSTRT 0x19 +#define OV7670_VSTOP 0x1A +#define OV7670_HREF 0x32 +#define OV7670_VREF 0x03 +#define OV7670_SCALING_DCWCTR 0x72 +#define OV7670_GAIN 0x00 +#define OV7670_AECHH 0x07 +#define OV7670_AECH 0x10 +#define OV7670_COM8 0x13 +#define OV7670_COM9 0x14 +#define OV7670_AEW 0x24 +#define OV7670_AEB 0x25 +#define OV7670_VPT 0x26 +#define OV7670_AWBC1 0x43 +#define OV7670_AWBC2 0x44 +#define OV7670_AWBC3 0x45 +#define OV7670_AWBC4 0x46 +#define OV7670_AWBC5 0x47 +#define OV7670_AWBC6 0x48 +#define OV7670_MTX1 0x4F +#define OV7670_MTX2 0x50 +#define OV7670_MTX3 0x51 +#define OV7670_MTX4 0x52 +#define OV7670_MTX5 0x53 +#define OV7670_MTX6 0x54 +#define OV7670_LCC1 0x62 +#define OV7670_LCC2 0x63 +#define OV7670_LCC3 0x64 +#define OV7670_LCC4 0x65 +#define OV7670_LCC5 0x66 +#define OV7670_LCC6 0x94 +#define OV7670_LCC7 0x95 +#define OV7670_SLOP 0x7A +#define OV7670_GAM1 0x7B +#define OV7670_GAM2 0x7C +#define OV7670_GAM3 0x7D +#define OV7670_GAM4 0x7E +#define OV7670_GAM5 0x7F +#define OV7670_GAM6 0x80 +#define OV7670_GAM7 0x81 +#define OV7670_GAM8 0x82 +#define OV7670_GAM9 0x83 +#define OV7670_GAM10 0x84 +#define OV7670_GAM11 0x85 +#define OV7670_GAM12 0x86 +#define OV7670_GAM13 0x87 +#define OV7670_GAM14 0x88 +#define OV7670_GAM15 0x89 +#define OV7670_HAECC1 0x9F +#define OV7670_HAECC2 0xA0 +#define OV7670_HSYEN 0x31 +#define OV7670_HAECC3 0xA6 +#define OV7670_HAECC4 0xA7 +#define OV7670_HAECC5 0xA8 +#define OV7670_HAECC6 0xA9 + +/* OV7670 definitions */ +#define OV7670_PROD_ID 0x76 + +#define OV7670_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[] = { + OV7670_VIDEO_FORMAT_CAP(176, 144, VIDEO_PIX_FMT_RGB565), /* QCIF */ + OV7670_VIDEO_FORMAT_CAP(320, 240, VIDEO_PIX_FMT_RGB565), /* QVGA */ + OV7670_VIDEO_FORMAT_CAP(352, 288, VIDEO_PIX_FMT_RGB565), /* CIF */ + OV7670_VIDEO_FORMAT_CAP(640, 480, VIDEO_PIX_FMT_RGB565), /* VGA */ + OV7670_VIDEO_FORMAT_CAP(176, 144, VIDEO_PIX_FMT_YUYV), /* QCIF */ + OV7670_VIDEO_FORMAT_CAP(320, 240, VIDEO_PIX_FMT_YUYV), /* QVGA */ + OV7670_VIDEO_FORMAT_CAP(352, 288, VIDEO_PIX_FMT_YUYV), /* CIF */ + OV7670_VIDEO_FORMAT_CAP(640, 480, VIDEO_PIX_FMT_YUYV), /* VGA */ + {0}}; + +/* This initialization table is based on the MCUX SDK driver for the OV7670 */ +static const struct ov7670_reg ov7670_init_regtbl[] = { + {OV7670_MVFP, 0x20}, /* MVFP: Mirror/VFlip,Normal image */ + + /* configure the output timing */ + /* PCLK does not toggle during horizontal blank, one PCLK, one pixel */ + {OV7670_COM10, 0x20}, /* COM10 */ + {OV7670_COM12, 0x00}, /* COM12,No HREF when VSYNC is low */ + /* Brightness Control, with signal -128 to +128, 0x00 is middle value */ + {OV7670_BRIGHT, 0x2f}, + + /* Internal clock pre-scalar,F(internal clock) = F(input clock)/(Bit[5:0]+1) */ + {OV7670_CLKRC, 0x81}, /* Clock Div, Input/(n+1), bit6 set to 1 to disable divider */ + + /* SCALING_PCLK_DIV, */ + {OV7670_SCALING_PCLK_DIV, 0x00}, /* 0: Enable clock divider,010: Divided by 4 */ + /* Common Control 14,Bit[4]: DCW and scaling PCLK enable,Bit[3]: Manual scaling */ + {OV7670_COM14, 0x00}, + + /* DBLV,Bit[7:6]: PLL control */ + /* 0:Bypass PLL.,40: Input clock x4 , 80: Input clock x6 ,C0: Input clock x8 */ + {OV7670_DBLV, 0x40}, + + /* test pattern, useful in some case */ + {OV7670_SCALING_XSC, 0x0}, + {OV7670_SCALING_YSC, 0}, + + /* Output Drive Capability */ + {OV7670_COM2, 0x00}, /* Common Control 2, Output Drive Capability: 1x */ + {OV7670_SCALING_PCLK_DELAY, 0x02}, + {OV7670_BD50MAX, 0x05}, + {OV7670_BD60MAX, 0x07}, + {OV7670_HAECC7, 0x94}, + + {OV7670_COM3, 0x00}, + {OV7670_COM4, 0x00}, + {OV7670_COM6, 0x4b}, + {OV7670_COM11, 0x9F}, /* Night mode */ + {OV7670_EDGE, 0x04}, /* Edge Enhancement Adjustment */ + {OV7670_DNSTH, 0x00}, /* De-noise Strength */ + + {OV7670_DM_LNL, 0x00}, + {OV7670_DM_LNH, 0x00}, + + /* reserved */ + {0x16, 0x02}, + {0x21, 0x02}, + {0x22, 0x91}, + {0x29, 0x07}, + {0x35, 0x0b}, + {0x33, 0x0b}, + {0x37, 0x1d}, + {0x38, 0x71}, + {0x39, 0x2a}, + {0x0e, 0x61}, + {0x56, 0x40}, + {0x57, 0x80}, + {0x69, 0x00}, + {0x74, 0x19}, + + /* display , need retain */ + {OV7670_COM15, 0xD0}, /* Common Control 15 */ + {OV7670_TSLB, 0x0C}, /* Line Buffer Test Option */ + {OV7670_COM13, 0x80}, /* Common Control 13 */ + {OV7670_MANU, 0x11}, /* Manual U Value */ + {OV7670_MANV, 0xFF}, /* Manual V Value */ + /* config the output window data, this can be configed later */ + {OV7670_HSTART, 0x16}, /* HSTART */ + {OV7670_HSTOP, 0x04}, /* HSTOP */ + {OV7670_VSTRT, 0x02}, /* VSTRT */ + {OV7670_VSTOP, 0x7a}, /* VSTOP */ + {OV7670_HREF, 0x80}, /* HREF */ + {OV7670_VREF, 0x0a}, /* VREF */ + + /* DCW Control, */ + {OV7670_SCALING_DCWCTR, 0x11}, + + /* AGC/AEC - Automatic Gain Control/Automatic exposure Control */ + {OV7670_GAIN, 0x00}, /* AGC */ + {OV7670_AECHH, 0x3F}, /* Exposure Value */ + {OV7670_AECH, 0xFF}, + {OV7670_COM8, 0x66}, + {OV7670_COM9, 0x21}, /* limit the max gain */ + {OV7670_AEW, 0x75}, + {OV7670_AEB, 0x63}, + {OV7670_VPT, 0xA5}, + /* Automatic white balance control */ + {OV7670_AWBC1, 0x14}, + {OV7670_AWBC2, 0xf0}, + {OV7670_AWBC3, 0x34}, + {OV7670_AWBC4, 0x58}, + {OV7670_AWBC5, 0x28}, + {OV7670_AWBC6, 0x3a}, + /* Matrix Coefficient */ + {OV7670_MTX1, 0x80}, + {OV7670_MTX2, 0x80}, + {OV7670_MTX3, 0x00}, + {OV7670_MTX4, 0x22}, + {OV7670_MTX5, 0x5e}, + {OV7670_MTX6, 0x80}, + /* AWB Control */ + {0x59, 0x88}, + {0x5a, 0x88}, + {0x5b, 0x44}, + {0x5c, 0x67}, + {0x5d, 0x49}, + {0x5e, 0x0e}, + {0x6c, 0x0a}, + {0x6d, 0x55}, + {0x6e, 0x11}, + {0x6f, 0x9f}, + /* Lens Correction Option */ + {OV7670_LCC1, 0x00}, + {OV7670_LCC2, 0x00}, + {OV7670_LCC3, 0x04}, + {OV7670_LCC4, 0x20}, + {OV7670_LCC5, 0x05}, + {OV7670_LCC6, 0x04}, /* effective only when LCC5[2] is high */ + {OV7670_LCC7, 0x08}, /* effective only when LCC5[2] is high */ + /* Gamma Curve, needn't config */ + {OV7670_SLOP, 0x20}, + {OV7670_GAM1, 0x1c}, + {OV7670_GAM2, 0x28}, + {OV7670_GAM3, 0x3c}, + {OV7670_GAM4, 0x55}, + {OV7670_GAM5, 0x68}, + {OV7670_GAM6, 0x76}, + {OV7670_GAM7, 0x80}, + {OV7670_GAM8, 0x88}, + {OV7670_GAM9, 0x8f}, + {OV7670_GAM10, 0x96}, + {OV7670_GAM11, 0xa3}, + {OV7670_GAM12, 0xaf}, + {OV7670_GAM13, 0xc4}, + {OV7670_GAM14, 0xd7}, + {OV7670_GAM15, 0xe8}, + /* Histogram-based AEC/AGC Control */ + {OV7670_HAECC1, 0x78}, + {OV7670_HAECC2, 0x68}, + {OV7670_HSYEN, 0xff}, + {0xa1, 0x03}, + {OV7670_HAECC3, 0xdf}, + {OV7670_HAECC4, 0xdf}, + {OV7670_HAECC5, 0xf0}, + {OV7670_HAECC6, 0x90}, + /* Automatic black Level Compensation */ + {0xb0, 0x84}, + {0xb1, 0x0c}, + {0xb2, 0x0e}, + {0xb3, 0x82}, + {0xb8, 0x0a}, +}; + +static int ov7670_get_caps(const struct device *dev, enum video_endpoint_id ep, + struct video_caps *caps) +{ + caps->format_caps = fmts; + return 0; +} + +static int ov7670_set_fmt(const struct device *dev, enum video_endpoint_id ep, + struct video_format *fmt) +{ + const struct ov7670_config *config = dev->config; + struct ov7670_data *data = dev->data; + uint8_t com7 = 0U; + uint8_t i = 0U; + + if (fmt->pixelformat != VIDEO_PIX_FMT_RGB565 && fmt->pixelformat != VIDEO_PIX_FMT_YUYV) { + LOG_ERR("Only RGB565 and YUYV supported!"); + return -ENOTSUP; + } + + if (!memcmp(&data->fmt, fmt, sizeof(data->fmt))) { + /* nothing to do */ + return 0; + } + + memcpy(&data->fmt, fmt, sizeof(data->fmt)); + + if (fmt->pixelformat == VIDEO_PIX_FMT_RGB565) { + com7 |= 0x4; + } + + /* Set output resolution */ + while (fmts[i].pixelformat) { + if (fmts[i].width_min == fmt->width && fmts[i].height_min == fmt->height && + fmts[i].pixelformat == fmt->pixelformat) { + /* Set output format */ + switch (fmts[i].width_min) { + case 176: /* QCIF */ + com7 |= BIT(3); + break; + case 320: /* QVGA */ + com7 |= BIT(4); + break; + case 352: /* CIF */ + com7 |= BIT(5); + break; + default: /* VGA */ + break; + } + /* Program COM7 to set format */ + return i2c_reg_write_byte_dt(&config->bus, OV7670_COM7, com7); + } + i++; + } + LOG_ERR("Unsupported format"); + return -ENOTSUP; +} + +static int ov7670_get_fmt(const struct device *dev, enum video_endpoint_id ep, + struct video_format *fmt) +{ + struct ov7670_data *data = dev->data; + + if (fmt == NULL) { + return -EINVAL; + } + memcpy(fmt, &data->fmt, sizeof(data->fmt)); + return 0; +} + +static int ov7670_init(const struct device *dev) +{ + const struct ov7670_config *config = dev->config; + int ret, i; + uint8_t pid; + struct video_format fmt; + const struct ov7670_reg *reg; + + if (!i2c_is_ready_dt(&config->bus)) { + /* I2C device is not ready, return */ + return -ENODEV; + } + +#if DT_ANY_INST_HAS_PROP_STATUS_OKAY(pwdn_gpios) + /* Power up camera module */ + if (config->pwdn.port != NULL) { + if (!gpio_is_ready_dt(&config->pwdn)) { + return -ENODEV; + } + ret = gpio_pin_configure_dt(&config->pwdn, GPIO_OUTPUT_INACTIVE); + if (ret < 0) { + LOG_ERR("Could not clear power down pin: %d", ret); + return ret; + } + } +#endif +#if DT_ANY_INST_HAS_PROP_STATUS_OKAY(reset_gpios) + /* Reset camera module */ + if (config->reset.port != NULL) { + if (!gpio_is_ready_dt(&config->reset)) { + return -ENODEV; + } + ret = gpio_pin_configure_dt(&config->reset, GPIO_OUTPUT); + if (ret < 0) { + LOG_ERR("Could not set reset pin: %d", ret); + return ret; + } + /* Reset is active low, has 1ms settling time*/ + gpio_pin_set_dt(&config->reset, 0); + k_msleep(1); + gpio_pin_set_dt(&config->reset, 1); + k_msleep(1); + } +#endif + + /* + * Read product ID from camera. This camera implements the SCCB, + * spec- which *should* be I2C compatible, but in practice does + * not seem to respond when I2C repeated start commands are used. + * To work around this, use a write then a read to interface with + * registers. + */ + uint8_t cmd = OV7670_PID; + + ret = i2c_write_dt(&config->bus, &cmd, sizeof(cmd)); + if (ret < 0) { + LOG_ERR("Could not request product ID: %d", ret); + return ret; + } + ret = i2c_read_dt(&config->bus, &pid, sizeof(pid)); + if (ret < 0) { + LOG_ERR("Could not read product ID: %d", ret); + return ret; + } + + if (pid != OV7670_PROD_ID) { + LOG_ERR("Incorrect product ID: 0x%02X", pid); + return -ENODEV; + } + + /* Set default camera format (QVGA, YUYV) */ + fmt.pixelformat = VIDEO_PIX_FMT_YUYV; + fmt.width = 640; + fmt.height = 480; + fmt.pitch = fmt.width * 2; + ret = ov7670_set_fmt(dev, VIDEO_EP_OUT, &fmt); + if (ret < 0) { + return ret; + } + + /* Write initialization values to OV7670 */ + for (i = 0; i < ARRAY_SIZE(ov7670_init_regtbl); i++) { + reg = &ov7670_init_regtbl[i]; + ret = i2c_reg_write_byte_dt(&config->bus, reg->reg, reg->cmd); + if (ret < 0) { + return ret; + } + } + + return 0; +} + +static const struct video_driver_api ov7670_api = { + .set_format = ov7670_set_fmt, + .get_format = ov7670_get_fmt, + .get_caps = ov7670_get_caps, +}; + +#if DT_ANY_INST_HAS_PROP_STATUS_OKAY(reset_gpios) +#define OV7670_RESET_GPIO(inst) .reset = GPIO_DT_SPEC_INST_GET_OR(inst, reset_gpios, {}), +#else +#define OV7670_RESET_GPIO(inst) +#endif + +#if DT_ANY_INST_HAS_PROP_STATUS_OKAY(pwdn_gpios) +#define OV7670_PWDN_GPIO(inst) .pwdn = GPIO_DT_SPEC_INST_GET_OR(inst, pwdn_gpios, {}), +#else +#define OV7670_PWDN_GPIO(inst) +#endif + +#define OV7670_INIT(inst) \ + const struct ov7670_config ov7670_config_##inst = {.bus = I2C_DT_SPEC_INST_GET(inst), \ + OV7670_RESET_GPIO(inst) \ + OV7670_PWDN_GPIO(inst)}; \ + struct ov7670_data ov7670_data_##inst; \ + \ + DEVICE_DT_INST_DEFINE(inst, ov7670_init, NULL, &ov7670_data_##inst, &ov7670_config_##inst, \ + POST_KERNEL, CONFIG_VIDEO_INIT_PRIORITY, &ov7670_api); + +DT_INST_FOREACH_STATUS_OKAY(OV7670_INIT) diff --git a/dts/bindings/video/ovti,ov7670.yaml b/dts/bindings/video/ovti,ov7670.yaml new file mode 100644 index 0000000000000..4b8fa88f1170b --- /dev/null +++ b/dts/bindings/video/ovti,ov7670.yaml @@ -0,0 +1,20 @@ +# Copyright 2024 NXP +# SPDX-License-Identifier: Apache-2.0 + +description: OV7670 CMOS video sensor + +compatible: "ovti,ov7670" + +properties: + reset-gpios: + type: phandle-array + description: | + The RESETn pin is asserted to disable the sensor causing a hard + reset. The sensor receives this as an active-low signal. + pwdn-gpios: + type: phandle-array + description: | + The PWDN pin is asserted to power down the sensor. The sensor + receives this as an active high signal + +include: i2c-device.yaml From 1ef42731fd43d21d5e3f306ab6da06ac693212bc Mon Sep 17 00:00:00 2001 From: Daniel DeGrasse Date: Wed, 15 May 2024 21:31:38 +0000 Subject: [PATCH 1965/2849] test: drivers: build_all: video: add ov7670 to build test Add ov7670 camera driver to build test for video drivers Signed-off-by: Daniel DeGrasse --- tests/drivers/build_all/video/app.overlay | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tests/drivers/build_all/video/app.overlay b/tests/drivers/build_all/video/app.overlay index e06d2940817a9..a095e461da581 100644 --- a/tests/drivers/build_all/video/app.overlay +++ b/tests/drivers/build_all/video/app.overlay @@ -54,6 +54,11 @@ reset-gpios = <&test_gpio 0 0>; powerdown-gpios = <&test_gpio 1 0>; }; + + test_i2c_ov7670: ov7670@4 { + compatible = "ovti,ov7670"; + reg = <0x4>; + }; }; }; }; From a425db20b1a7fee630de15c385f2a1c24f5ab127 Mon Sep 17 00:00:00 2001 From: Dmitrii Golovanov Date: Tue, 7 May 2024 23:58:22 +0200 Subject: [PATCH 1966/2849] twister: Add test suite filtering on twister.json compose When Twister composes resulting twister.json reports, add optional filtering by a test instance resulting status and/or its individual properties to be allowed/denied on output to the JSON file. This internal feature is introduced to facilitate JSON reports with a custom data schema. Signed-off-by: Dmitrii Golovanov --- scripts/pylib/twister/twisterlib/reports.py | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/scripts/pylib/twister/twisterlib/reports.py b/scripts/pylib/twister/twisterlib/reports.py index 4bc352e4f1d97..5521ec868c777 100644 --- a/scripts/pylib/twister/twisterlib/reports.py +++ b/scripts/pylib/twister/twisterlib/reports.py @@ -234,7 +234,7 @@ def xunit_report(self, json_file, filename, selected_platform=None, full_report= with open(filename, 'wb') as report: report.write(result) - def json_report(self, filename, version="NA", platform=None): + def json_report(self, filename, version="NA", platform=None, filters=None): logger.info(f"Writing JSON report {filename}") if self.env.options.report_all_options: @@ -261,6 +261,14 @@ def json_report(self, filename, version="NA", platform=None): continue if instance.status == "filtered" and not self.env.options.report_filtered: continue + if (filters and 'allow_status' in filters and instance.status not in filters['allow_status']): + logger.debug(f"Skip test suite '{instance.testsuite.name}' status '{instance.status}' " + f"not allowed for {filename}") + continue + if (filters and 'deny_status' in filters and instance.status in filters['deny_status']): + logger.debug(f"Skip test suite '{instance.testsuite.name}' status '{instance.status}' " + f"denied for {filename}") + continue suite = {} handler_log = os.path.join(instance.build_dir, "handler.log") pytest_log = os.path.join(instance.build_dir, "twister_harness.log") @@ -366,6 +374,13 @@ def json_report(self, filename, version="NA", platform=None): if instance.recording is not None: suite['recording'] = instance.recording + # Pass suite properties through the context filters. + if filters and 'allow_suite' in filters: + suite = {k:v for k,v in suite.items() if k in filters['allow_suite']} + + if filters and 'deny_suite' in filters: + suite = {k:v for k,v in suite.items() if k not in filters['deny_suite']} + suites.append(suite) report["testsuites"] = suites From eebbd5c4115ac5326812e2d5258e63fa2b96fe99 Mon Sep 17 00:00:00 2001 From: Dmitrii Golovanov Date: Tue, 30 Apr 2024 10:33:32 +0200 Subject: [PATCH 1967/2849] twister: footprint: Add optional detailed JSON report on symbols New Twister option `--footprint-report` is introduced to collect and write detailed memory footprint results for symbols as an additional JSON file. By default, the new option is disabled. The new option implies and extends `--create-rom-ram-report`, so there are three choices: 'ROM', 'RAM', and 'all' to select what memory area symbols to report in `twister_footprint.json`. In case of the custom report name, or per-platform report, it is always composed with the rightmost '_footprint.json' suffix. The memory footprint report has similar structure as `twister.json` and compelements it having reduced set of test suite properties: - instead of `testcases` it contains `footprint` object with `rom.json` and `ram.json` artifacts embedded there; - other properites are limited to represent only the essential test suite context, thus to allow further data processing consistently and independently from the `twister.json`. - 'filtered' test instances are not included into the footprint report. Signed-off-by: Dmitrii Golovanov --- .../pylib/twister/twisterlib/environment.py | 15 ++++++ scripts/pylib/twister/twisterlib/reports.py | 52 +++++++++++++++++-- scripts/pylib/twister/twisterlib/runner.py | 2 + 3 files changed, 65 insertions(+), 4 deletions(-) diff --git a/scripts/pylib/twister/twisterlib/environment.py b/scripts/pylib/twister/twisterlib/environment.py index 3d818e4e96446..8a7b5b2f84f9a 100644 --- a/scripts/pylib/twister/twisterlib/environment.py +++ b/scripts/pylib/twister/twisterlib/environment.py @@ -385,6 +385,18 @@ def add_parse_arguments(parser = None): help="Generate detailed json reports with ROM/RAM symbol sizes for each test image built " "using additional build option `--target footprint`.") + footprint_group.add_argument( + "--footprint-report", + nargs="?", + default=None, + choices=['all', 'ROM', 'RAM'], + const="all", + help="Select which memory area symbols' data to collect as 'footprint' property " + "of each test suite built, and report in 'twister_footprint.json' together " + "with the relevant execution metadata the same way as in `twister.json`. " + "Implies '--create-rom-ram-report' to generate the footprint data files. " + "No value means '%(const)s'. Default: %(default)s""") + footprint_group.add_argument( "--enable-size-report", action="store_true", @@ -790,6 +802,9 @@ def parse_arguments(parser, args, options = None, on_init=True): if options.last_metrics or options.compare_report: options.enable_size_report = True + if options.footprint_report: + options.create_rom_ram_report = True + if options.aggressive_no_clean: options.no_clean = True diff --git a/scripts/pylib/twister/twisterlib/reports.py b/scripts/pylib/twister/twisterlib/reports.py index 5521ec868c777..c688542080364 100644 --- a/scripts/pylib/twister/twisterlib/reports.py +++ b/scripts/pylib/twister/twisterlib/reports.py @@ -18,6 +18,16 @@ class Reporting: + json_filters = { + 'twister.json': { + 'deny_suite': ['footprint'] + }, + 'footprint.json': { + 'deny_status': ['filtered'], + 'deny_suite': ['testcases', 'execution_time', 'recording', 'retries', 'runnable'] + } + } + def __init__(self, plan, env) -> None: self.plan = plan #FIXME self.instances = plan.instances @@ -28,6 +38,7 @@ def __init__(self, plan, env) -> None: self.timestamp = datetime.now().isoformat() self.outdir = os.path.abspath(env.options.outdir) self.instance_fail_count = plan.instance_fail_count + self.footprint = None @staticmethod def process_log(log_file): @@ -374,6 +385,13 @@ def json_report(self, filename, version="NA", platform=None, filters=None): if instance.recording is not None: suite['recording'] = instance.recording + if (instance.status + and instance.status not in ["error", "filtered"] + and self.env.options.create_rom_ram_report + and self.env.options.footprint_report is not None): + # Init as empty data preparing for filtering properties. + suite['footprint'] = {} + # Pass suite properties through the context filters. if filters and 'allow_suite' in filters: suite = {k:v for k,v in suite.items() if k in filters['allow_suite']} @@ -381,6 +399,22 @@ def json_report(self, filename, version="NA", platform=None, filters=None): if filters and 'deny_suite' in filters: suite = {k:v for k,v in suite.items() if k not in filters['deny_suite']} + # Compose external data only to these properties which pass filtering. + if 'footprint' in suite: + do_all = 'all' in self.env.options.footprint_report + footprint_files = { 'ROM': 'rom.json', 'RAM': 'ram.json' } + for k,v in footprint_files.items(): + if do_all or k in self.env.options.footprint_report: + footprint_fname = os.path.join(instance.build_dir, v) + try: + with open(footprint_fname, "rt") as footprint_json: + logger.debug(f"Collect footprint.{k} for '{instance.name}'") + suite['footprint'][k] = json.load(footprint_json) + except FileNotFoundError: + logger.error(f"Missing footprint.{k} for '{instance.name}'") + # + # + suites.append(suite) report["testsuites"] = suites @@ -585,7 +619,11 @@ def save_reports(self, name, suffix, report_dir, no_update, platform_reports): if not no_update: json_file = filename + ".json" - self.json_report(json_file, version=self.env.version) + self.json_report(json_file, version=self.env.version, + filters=self.json_filters['twister.json']) + if self.env.options.footprint_report is not None: + self.json_report(filename + "_footprint.json", version=self.env.version, + filters=self.json_filters['footprint.json']) self.xunit_report(json_file, filename + ".xml", full_report=False) self.xunit_report(json_file, filename + "_report.xml", full_report=True) self.xunit_report_suites(json_file, filename + "_suite_report.xml") @@ -599,9 +637,15 @@ def target_report(self, json_file, outdir, suffix): 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)) + json_platform_file = os.path.join(outdir,"{}_{}".format(platform.normalized_name, suffix)) else: filename = os.path.join(outdir,"{}.xml".format(platform.normalized_name)) - json_platform_file = os.path.join(outdir,"{}.json".format(platform.normalized_name)) + json_platform_file = os.path.join(outdir, platform.normalized_name) self.xunit_report(json_file, filename, platform.name, full_report=True) - self.json_report(json_platform_file, version=self.env.version, platform=platform.name) + self.json_report(json_platform_file + ".json", + version=self.env.version, platform=platform.name, + filters=self.json_filters['twister.json']) + if self.env.options.footprint_report is not None: + self.json_report(json_platform_file + "_footprint.json", + version=self.env.version, platform=platform.name, + filters=self.json_filters['footprint.json']) diff --git a/scripts/pylib/twister/twisterlib/runner.py b/scripts/pylib/twister/twisterlib/runner.py index 6725134cc24eb..1ea52904607be 100644 --- a/scripts/pylib/twister/twisterlib/runner.py +++ b/scripts/pylib/twister/twisterlib/runner.py @@ -764,6 +764,8 @@ def cleanup_artifacts(self, additional_keep: List[str] = []): 'build.log', 'device.log', 'recording.csv', + 'rom.json', + 'ram.json', # below ones are needed to make --test-only work as well 'Makefile', 'CMakeCache.txt', From 6b0a4b0c85b91b0d9b4664ac5fe673d163af297b Mon Sep 17 00:00:00 2001 From: Stanislav Poboril Date: Mon, 19 Feb 2024 15:09:56 +0100 Subject: [PATCH 1968/2849] drivers: clock_control: mcux_ccm_rev2: Add ENET_1G clock Add ENET_1G clock value to the RT11XX CCM version. Implemented enabling ENET_1G clock and getting its frequency. Signed-off-by: Stanislav Poboril --- drivers/clock_control/clock_control_mcux_ccm_rev2.c | 5 +++++ include/zephyr/dt-bindings/clock/imx_ccm_rev2.h | 2 ++ 2 files changed, 7 insertions(+) diff --git a/drivers/clock_control/clock_control_mcux_ccm_rev2.c b/drivers/clock_control/clock_control_mcux_ccm_rev2.c index 28389a4a22852..188fe976df4f9 100644 --- a/drivers/clock_control/clock_control_mcux_ccm_rev2.c +++ b/drivers/clock_control/clock_control_mcux_ccm_rev2.c @@ -20,6 +20,10 @@ static int mcux_ccm_on(const struct device *dev, #ifdef CONFIG_ETH_NXP_ENET if ((uint32_t)sub_system == IMX_CCM_ENET_CLK) { CLOCK_EnableClock(kCLOCK_Enet); +#ifdef CONFIG_ETH_NXP_ENET_1G + } else if ((uint32_t)sub_system == IMX_CCM_ENET1G_CLK) { + CLOCK_EnableClock(kCLOCK_Enet_1g); +#endif } #endif return 0; @@ -111,6 +115,7 @@ static int mcux_ccm_get_subsys_rate(const struct device *dev, #ifdef CONFIG_ETH_NXP_ENET case IMX_CCM_ENET_CLK: + case IMX_CCM_ENET1G_CLK: clock_root = kCLOCK_Root_Bus; break; #endif diff --git a/include/zephyr/dt-bindings/clock/imx_ccm_rev2.h b/include/zephyr/dt-bindings/clock/imx_ccm_rev2.h index 75369dc92e9b1..18c44cab86fdd 100644 --- a/include/zephyr/dt-bindings/clock/imx_ccm_rev2.h +++ b/include/zephyr/dt-bindings/clock/imx_ccm_rev2.h @@ -92,6 +92,8 @@ /* ENET */ #define IMX_CCM_ENET_CLK 0x1200UL #define IMX_CCM_ENET_PLL 0x1201UL +#define IMX_CCM_ENET1G_CLK 0x1202UL +#define IMX_CCM_ENET1G_PLL 0x1203UL /* FLEXSPI */ #define IMX_CCM_FLEXSPI_CLK 0x1300UL From 5774f47e89aec5911f7d9959ad0493abb8b90480 Mon Sep 17 00:00:00 2001 From: Stanislav Poboril Date: Mon, 19 Feb 2024 15:25:07 +0100 Subject: [PATCH 1969/2849] soc: rt11xx: support nxp_enet in soc Support NXP ENET_1G on RT11xx soc. Fixes: #66348 Signed-off-by: Stanislav Poboril --- soc/nxp/imxrt/imxrt11xx/soc.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/soc/nxp/imxrt/imxrt11xx/soc.c b/soc/nxp/imxrt/imxrt11xx/soc.c index be06e59c34bd4..048e820619dc6 100644 --- a/soc/nxp/imxrt/imxrt11xx/soc.c +++ b/soc/nxp/imxrt/imxrt11xx/soc.c @@ -431,11 +431,21 @@ static ALWAYS_INLINE void clock_init(void) #endif #endif #if DT_NODE_HAS_STATUS(DT_NODELABEL(enet1g), okay) + rootCfg.mux = kCLOCK_ENET2_ClockRoot_MuxSysPll1Div2; +#if DT_ENUM_HAS_VALUE(DT_CHILD(DT_NODELABEL(enet1g), ethernet), phy_connection_type, rgmii) + /* 125 MHz ENET1G clock */ + rootCfg.div = 4; + CLOCK_SetRootClock(kCLOCK_Root_Enet2, &rootCfg); + /* Set ENET1G TX_CLK to be driven by ENET2_CLK_ROOT and output on TX_CLK_IO pad */ + IOMUXC_GPR->GPR5 = (IOMUXC_GPR_GPR5_ENET1G_RGMII_EN(0x01U) | + (IOMUXC_GPR->GPR5 & ~IOMUXC_GPR_GPR5_ENET1G_TX_CLK_SEL(0x01U))); + /* Set ENET1G_REF_CLK as an input driven by PHY */ + IOMUXC_GPR->GPR5 &= ~IOMUXC_GPR_GPR5_ENET1G_REF_CLK_DIR(0x01U); +#else /* * 50 MHz clock for 10/100Mbit RMII PHY - * operate ENET1G just like ENET peripheral */ - rootCfg.mux = kCLOCK_ENET2_ClockRoot_MuxSysPll1Div2; rootCfg.div = 10; CLOCK_SetRootClock(kCLOCK_Root_Enet2, &rootCfg); #if CONFIG_ETH_MCUX_RMII_EXT_CLK @@ -449,6 +459,7 @@ static ALWAYS_INLINE void clock_init(void) #endif #endif #endif +#endif #if defined(CONFIG_PTP_CLOCK_MCUX) || defined(CONFIG_PTP_CLOCK_NXP_ENET) /* 24MHz PTP clock */ From 57a788880ea2a32fcc4ab5775b52e90e96adf134 Mon Sep 17 00:00:00 2001 From: Stanislav Poboril Date: Mon, 19 Feb 2024 15:53:14 +0100 Subject: [PATCH 1970/2849] dts: bindings: ethernet-controller: Add RGMII mode Add option for RGMII connection type between the MAC and the PHY device into the ethernet controller binding. Fixes: #66348 Signed-off-by: Stanislav Poboril --- dts/bindings/ethernet/ethernet-controller.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/dts/bindings/ethernet/ethernet-controller.yaml b/dts/bindings/ethernet/ethernet-controller.yaml index 8823459d3a9eb..bb4fa794152be 100644 --- a/dts/bindings/ethernet/ethernet-controller.yaml +++ b/dts/bindings/ethernet/ethernet-controller.yaml @@ -36,3 +36,4 @@ properties: - "mii" - "rmii" - "gmii" + - "rgmii" From c2dc897d221d520372400180182a9404446d9caf Mon Sep 17 00:00:00 2001 From: Stanislav Poboril Date: Mon, 19 Feb 2024 16:15:07 +0100 Subject: [PATCH 1971/2849] dts: bindings: Add RGMII mode definition to NXP ENET bindings Add RGMII mode definition to be used in bindings related to NXP ENET_1G IP. Fixes: #66348 Signed-off-by: Stanislav Poboril --- include/zephyr/dt-bindings/ethernet/nxp_enet.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/zephyr/dt-bindings/ethernet/nxp_enet.h b/include/zephyr/dt-bindings/ethernet/nxp_enet.h index e084825da4c75..0e307c9ebfc6f 100644 --- a/include/zephyr/dt-bindings/ethernet/nxp_enet.h +++ b/include/zephyr/dt-bindings/ethernet/nxp_enet.h @@ -1,5 +1,5 @@ /* - * Copyright 2023 NXP + * Copyright 2023-2024 NXP * * SPDX-License-Identifier: Apache-2.0 */ @@ -9,6 +9,7 @@ #define NXP_ENET_MII_MODE 0 #define NXP_ENET_RMII_MODE 1 +#define NXP_ENET_RGMII_MODE 2 #define NXP_ENET_INVALID_MII_MODE 100 #endif /* ZEPHYR_INCLUDE_DT_BINDINGS_NXP_ENET_H_ */ From cbb5c5b444ca05fc1dca3cecbea0d4a7c622b06b Mon Sep 17 00:00:00 2001 From: Stanislav Poboril Date: Mon, 19 Feb 2024 18:10:33 +0100 Subject: [PATCH 1972/2849] drivers: nxp_enet: Support RGMII mode for ENET_1G - Added nxp,enet1g compatible to distinguish between ENET (nxp,enet) and ENET_1G (nxp,enet1g) peripherals within the same driver. - Added config ETH_NXP_ENET_1G to enable 1G mode of operation on ENET_1G. - Support RGMII mode of connection between MDIO and PHY to be able to work with ENET_1G peripheral and support 1000M speed. - Removed performing of PHY reset before configuring link - it is not desirable for RTL8211F PHY connected to ENET_1G on RT1170. Reset of other PHYs can be performed by PHY driver itself if required. Fixes: #66348 Signed-off-by: Stanislav Poboril --- drivers/ethernet/nxp_enet/Kconfig | 7 ++ drivers/ethernet/nxp_enet/eth_nxp_enet.c | 100 +++++++++++++++++------ dts/bindings/ethernet/nxp,enet1g.yaml | 15 ++++ 3 files changed, 98 insertions(+), 24 deletions(-) create mode 100644 dts/bindings/ethernet/nxp,enet1g.yaml diff --git a/drivers/ethernet/nxp_enet/Kconfig b/drivers/ethernet/nxp_enet/Kconfig index 1deb614f70c4e..f83c05fb81ce0 100644 --- a/drivers/ethernet/nxp_enet/Kconfig +++ b/drivers/ethernet/nxp_enet/Kconfig @@ -38,6 +38,13 @@ endchoice if ETH_NXP_ENET +config ETH_NXP_ENET_1G + bool "1G mode for ENET1G instance" + default y + depends on DT_HAS_NXP_ENET1G_ENABLED + help + Enable the use of the ENET1G ethernet instance in 1G mode. + config ETH_NXP_ENET_USE_DTCM_FOR_DMA_BUFFER bool "Use DTCM for hardware DMA buffers" default y diff --git a/drivers/ethernet/nxp_enet/eth_nxp_enet.c b/drivers/ethernet/nxp_enet/eth_nxp_enet.c index befa92b91aed5..a5c0e13469d3c 100644 --- a/drivers/ethernet/nxp_enet/eth_nxp_enet.c +++ b/drivers/ethernet/nxp_enet/eth_nxp_enet.c @@ -260,9 +260,14 @@ static void eth_nxp_enet_iface_init(struct net_if *iface) static enum ethernet_hw_caps eth_nxp_enet_get_capabilities(const struct device *dev) { +#if defined(CONFIG_ETH_NXP_ENET_1G) + const struct nxp_enet_mac_config *config = dev->config; +#else ARG_UNUSED(dev); +#endif + enum ethernet_hw_caps caps; - return ETHERNET_LINK_10BASE_T | + caps = ETHERNET_LINK_10BASE_T | ETHERNET_HW_FILTERING | #if defined(CONFIG_NET_VLAN) ETHERNET_HW_VLAN | @@ -278,6 +283,13 @@ static enum ethernet_hw_caps eth_nxp_enet_get_capabilities(const struct device * ETHERNET_HW_RX_CHKSUM_OFFLOAD | #endif ETHERNET_LINK_100BASE_T; + + if (COND_CODE_1(IS_ENABLED(CONFIG_ETH_NXP_ENET_1G), + (config->phy_mode == NXP_ENET_RGMII_MODE), (0))) { + caps |= ETHERNET_LINK_1000BASE_T; + } + + return caps; } static int eth_nxp_enet_set_config(const struct device *dev, @@ -440,22 +452,18 @@ static void eth_nxp_enet_rx_thread(struct k_work *work) ENET_EnableInterrupts(config->base, kENET_RxFrameInterrupt); } -static int nxp_enet_phy_reset_and_configure(const struct device *phy) +static int nxp_enet_phy_configure(const struct device *phy, uint8_t phy_mode) { - int ret; + enum phy_link_speed speeds = LINK_HALF_10BASE_T | LINK_FULL_10BASE_T | + LINK_HALF_100BASE_T | LINK_FULL_100BASE_T; - /* Reset the PHY */ - ret = phy_write(phy, MII_BMCR, MII_BMCR_RESET); - if (ret) { - return ret; + if (COND_CODE_1(IS_ENABLED(CONFIG_ETH_NXP_ENET_1G), + (phy_mode == NXP_ENET_RGMII_MODE), (0))) { + speeds |= (LINK_HALF_1000BASE_T | LINK_FULL_1000BASE_T); } - /* 802.3u standard says reset takes up to 0.5s */ - k_busy_wait(500000); - /* Configure the PHY */ - return phy_configure_link(phy, LINK_HALF_10BASE_T | LINK_FULL_10BASE_T | - LINK_HALF_100BASE_T | LINK_FULL_100BASE_T); + return phy_configure_link(phy, speeds); } static void nxp_enet_phy_cb(const struct device *phy, @@ -464,19 +472,44 @@ static void nxp_enet_phy_cb(const struct device *phy, { const struct device *dev = eth_dev; struct nxp_enet_mac_data *data = dev->data; + const struct nxp_enet_mac_config *config = dev->config; + enet_mii_speed_t speed; + enet_mii_duplex_t duplex; + + if (state->is_up) { +#if defined(CONFIG_ETH_NXP_ENET_1G) + if (PHY_LINK_IS_SPEED_1000M(state->speed)) { + speed = kENET_MiiSpeed1000M; + } else if (PHY_LINK_IS_SPEED_100M(state->speed)) { +#else + if (PHY_LINK_IS_SPEED_100M(state->speed)) { +#endif + speed = kENET_MiiSpeed100M; + } else { + speed = kENET_MiiSpeed10M; + } + + if (PHY_LINK_IS_FULL_DUPLEX(state->speed)) { + duplex = kENET_MiiFullDuplex; + } else { + duplex = kENET_MiiHalfDuplex; + } + + ENET_SetMII(config->base, speed, duplex); + } if (!data->iface) { return; } + LOG_INF("Link is %s", state->is_up ? "up" : "down"); + if (!state->is_up) { net_eth_carrier_off(data->iface); - nxp_enet_phy_reset_and_configure(phy); + nxp_enet_phy_configure(phy, config->phy_mode); } else { net_eth_carrier_on(data->iface); } - - LOG_INF("Link is %s", state->is_up ? "up" : "down"); } @@ -485,7 +518,7 @@ static int nxp_enet_phy_init(const struct device *dev) const struct nxp_enet_mac_config *config = dev->config; int ret = 0; - ret = nxp_enet_phy_reset_and_configure(config->phy_dev); + ret = nxp_enet_phy_configure(config->phy_dev, config->phy_mode); if (ret) { return ret; } @@ -640,6 +673,10 @@ static int eth_nxp_enet_init(const struct device *dev) enet_config.miiMode = kENET_MiiMode; } else if (config->phy_mode == NXP_ENET_RMII_MODE) { enet_config.miiMode = kENET_RmiiMode; +#if defined(CONFIG_ETH_NXP_ENET_1G) + } else if (config->phy_mode == NXP_ENET_RGMII_MODE) { + enet_config.miiMode = kENET_RgmiiMode; +#endif } else { return -EINVAL; } @@ -783,7 +820,8 @@ static const struct ethernet_api api_funcs = { #define NXP_ENET_PHY_MODE(node_id) \ DT_ENUM_HAS_VALUE(node_id, phy_connection_type, mii) ? NXP_ENET_MII_MODE : \ (DT_ENUM_HAS_VALUE(node_id, phy_connection_type, rmii) ? NXP_ENET_RMII_MODE : \ - NXP_ENET_INVALID_MII_MODE) + (DT_ENUM_HAS_VALUE(node_id, phy_connection_type, rgmii) ? NXP_ENET_RGMII_MODE : \ + NXP_ENET_INVALID_MII_MODE)) #ifdef CONFIG_PTP_CLOCK_NXP_ENET #define NXP_ENET_PTP_DEV(n) .ptp_clock = DEVICE_DT_GET(DT_INST_PHANDLE(n, nxp_ptp_clock)), @@ -805,9 +843,18 @@ static const struct ethernet_api api_funcs = { DT_INST_PROP(n, nxp_unique_mac), \ "MAC address not specified on ENET DT node"); +#define NXP_ENET_NODE_PHY_MODE_CHECK(n) \ +BUILD_ASSERT(NXP_ENET_PHY_MODE(DT_DRV_INST(n)) != NXP_ENET_RGMII_MODE || \ + (IS_ENABLED(CONFIG_ETH_NXP_ENET_1G) && \ + DT_NODE_HAS_COMPAT(DT_INST_PARENT(n), nxp_enet1g)), \ + "RGMII mode requires nxp,enet1g compatible on ENET DT node" \ + " and CONFIG_ETH_NXP_ENET_1G enabled"); + #define NXP_ENET_MAC_INIT(n) \ NXP_ENET_NODE_HAS_MAC_ADDR_CHECK(n) \ \ + NXP_ENET_NODE_PHY_MODE_CHECK(n) \ + \ PINCTRL_DT_INST_DEFINE(n); \ \ NXP_ENET_FRAMEINFO_ARRAY(n) \ @@ -889,12 +936,9 @@ static const struct ethernet_api api_funcs = { DT_INST_FOREACH_STATUS_OKAY(NXP_ENET_MAC_INIT) -#undef DT_DRV_COMPAT -#define DT_DRV_COMPAT nxp_enet - -#define NXP_ENET_INIT(n) \ +#define NXP_ENET_INIT(n, compat) \ \ -int nxp_enet_##n##_init(void) \ +int compat##_##n##_init(void) \ { \ clock_control_on(DEVICE_DT_GET(DT_INST_CLOCKS_CTLR(n)), \ (void *)DT_INST_CLOCKS_CELL_BY_IDX(n, 0, name)); \ @@ -905,6 +949,14 @@ int nxp_enet_##n##_init(void) \ } \ \ /* Init the module before any of the MAC, MDIO, or PTP clock */ \ - SYS_INIT(nxp_enet_##n##_init, POST_KERNEL, 0); + SYS_INIT(compat##_##n##_init, POST_KERNEL, 0); + +#undef DT_DRV_COMPAT +#define DT_DRV_COMPAT nxp_enet + +DT_INST_FOREACH_STATUS_OKAY_VARGS(NXP_ENET_INIT, DT_DRV_COMPAT) + +#undef DT_DRV_COMPAT +#define DT_DRV_COMPAT nxp_enet1g -DT_INST_FOREACH_STATUS_OKAY(NXP_ENET_INIT) +DT_INST_FOREACH_STATUS_OKAY_VARGS(NXP_ENET_INIT, DT_DRV_COMPAT) diff --git a/dts/bindings/ethernet/nxp,enet1g.yaml b/dts/bindings/ethernet/nxp,enet1g.yaml new file mode 100644 index 0000000000000..3f79a33f060a1 --- /dev/null +++ b/dts/bindings/ethernet/nxp,enet1g.yaml @@ -0,0 +1,15 @@ +# Copyright 2024 NXP +# SPDX-License-Identifier: Apache-2.0 + +description: NXP ENET1G IP Module + +compatible: "nxp,enet1g" + +include: ["base.yaml"] + +properties: + reg: + required: true + + clocks: + required: true From ca6adbba617574d1bfb527a31347a4e538556930 Mon Sep 17 00:00:00 2001 From: Declan Snyder Date: Tue, 4 Jun 2024 09:25:34 -0500 Subject: [PATCH 1973/2849] scripts: kconfig: Add dt_compat_any_has_prop Add a kconfig preprocessor function to check if any node of a certain compatible has a specific property in DT. Signed-off-by: Declan Snyder --- scripts/kconfig/kconfigfunctions.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/scripts/kconfig/kconfigfunctions.py b/scripts/kconfig/kconfigfunctions.py index 75b964e0f72ac..35699e96cb608 100644 --- a/scripts/kconfig/kconfigfunctions.py +++ b/scripts/kconfig/kconfigfunctions.py @@ -749,6 +749,21 @@ def dt_compat_on_bus(kconf, _, compat, bus): return "n" +def dt_compat_any_has_prop(kconf, _, compat, prop): + """ + This function takes a 'compat' and a 'prop' and returns "y" if any + node with compatible 'compat' also has a valid property 'prop'. + It returns "n" otherwise. + """ + if doc_mode or edt is None: + return "n" + + if compat in edt.compat2okay: + for node in edt.compat2okay[compat]: + if prop in node.props: + return "y" + + return "n" def dt_nodelabel_has_compat(kconf, _, label, compat): """ @@ -916,6 +931,7 @@ def substring(kconf, _, string, start, stop=None): "dt_has_compat": (dt_has_compat, 1, 1), "dt_compat_enabled": (dt_compat_enabled, 1, 1), "dt_compat_on_bus": (dt_compat_on_bus, 2, 2), + "dt_compat_any_has_prop": (dt_compat_any_has_prop, 2, 2), "dt_chosen_label": (dt_chosen_label, 1, 1), "dt_chosen_enabled": (dt_chosen_enabled, 1, 1), "dt_chosen_path": (dt_chosen_path, 1, 1), From d124eec3c978c8de2ea31b00e562054c010ff7de Mon Sep 17 00:00:00 2001 From: Stanislav Poboril Date: Mon, 19 Feb 2024 18:23:16 +0100 Subject: [PATCH 1974/2849] drivers: ethernet: phy: Add Realtek RTL8211F PHY driver Add driver for Realtek RTL8211F 10/100/1000M ethernet PHY. This driver implements vendor specific behaviour like detecting link state change by GPIO interrupt, which is not present in the generic MII driver. Fixes: #66348 Signed-off-by: Stanislav Poboril --- drivers/ethernet/phy/CMakeLists.txt | 1 + drivers/ethernet/phy/Kconfig | 14 +- drivers/ethernet/phy/phy_realtek_rtl8211f.c | 634 ++++++++++++++++++++ dts/bindings/ethernet/realtek,rtl8211f.yaml | 16 + 4 files changed, 663 insertions(+), 2 deletions(-) create mode 100644 drivers/ethernet/phy/phy_realtek_rtl8211f.c create mode 100644 dts/bindings/ethernet/realtek,rtl8211f.yaml diff --git a/drivers/ethernet/phy/CMakeLists.txt b/drivers/ethernet/phy/CMakeLists.txt index ff25a9a4fa39c..65f9cd2e5938f 100644 --- a/drivers/ethernet/phy/CMakeLists.txt +++ b/drivers/ethernet/phy/CMakeLists.txt @@ -4,3 +4,4 @@ zephyr_library_sources_ifdef(CONFIG_PHY_GENERIC_MII phy_mii.c) zephyr_library_sources_ifdef(CONFIG_PHY_ADIN2111 phy_adin2111.c) zephyr_library_sources_ifdef(CONFIG_PHY_TJA1103 phy_tja1103.c) zephyr_library_sources_ifdef(CONFIG_PHY_MICROCHIP_KSZ8081 phy_microchip_ksz8081.c) +zephyr_library_sources_ifdef(CONFIG_PHY_REALTEK_RTL8211F phy_realtek_rtl8211f.c) diff --git a/drivers/ethernet/phy/Kconfig b/drivers/ethernet/phy/Kconfig index 8ff32b8fee2a7..9fb71571e0f02 100644 --- a/drivers/ethernet/phy/Kconfig +++ b/drivers/ethernet/phy/Kconfig @@ -41,13 +41,23 @@ config PHY_ADIN2111 Enable ADIN2111 PHY driver. config PHY_MICROCHIP_KSZ8081 - bool "Microchip KSZ8081 Phy Driver" + bool "Microchip KSZ8081 PHY Driver" default y depends on DT_HAS_MICROCHIP_KSZ8081_ENABLED depends on MDIO depends on GPIO help - Enable Microchip KSZ8081 Ethernet Phy Driver + Enable Microchip KSZ8081 Ethernet PHY Driver + +config PHY_REALTEK_RTL8211F + bool "Realtek RTL8211F PHY Driver" + default y + depends on DT_HAS_REALTEK_RTL8211F_ENABLED + depends on MDIO + depends on GPIO || (!$(dt_compat_any_has_prop,$(DT_COMPAT_REALTEK_RTL8211F),reset-gpios) && \ + !$(dt_compat_any_has_prop,$(DT_COMPAT_REALTEK_RTL8211F),int-gpios)) + help + Enable Realtek RTL8211F Ethernet PHY Driver config PHY_AUTONEG_TIMEOUT_MS int "Auto-negotiation timeout value in milliseconds" diff --git a/drivers/ethernet/phy/phy_realtek_rtl8211f.c b/drivers/ethernet/phy/phy_realtek_rtl8211f.c new file mode 100644 index 0000000000000..b1765a500bc5a --- /dev/null +++ b/drivers/ethernet/phy/phy_realtek_rtl8211f.c @@ -0,0 +1,634 @@ +/* + * Copyright 2023-2024 NXP + * + * Inspiration from phy_mii.c, which is: + * Copyright (c) 2021 IP-Logix Inc. + * Copyright 2022 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT realtek_rtl8211f + +#include +#include +#include +#include +#include +#include +#if DT_ANY_INST_HAS_PROP_STATUS_OKAY(reset_gpios) || DT_ANY_INST_HAS_PROP_STATUS_OKAY(int_gpios) +#include +#endif + +#define LOG_MODULE_NAME phy_rt_rtl8211f +#define LOG_LEVEL CONFIG_PHY_LOG_LEVEL +#include +LOG_MODULE_REGISTER(LOG_MODULE_NAME); + +#define REALTEK_OUI_MSB (0x1CU) + +#define PHY_RT_RTL8211F_PHYSR_REG (0x1A) + +#define PHY_RT_RTL8211F_PHYSR_LINKSTATUS_MASK BIT(2) +#define PHY_RT_RTL8211F_PHYSR_LINKDUPLEX_MASK BIT(3) +#define PHY_RT_RTL8211F_PHYSR_LINKSPEED_MASK (BIT(4) | BIT(5)) +#define PHY_RT_RTL8211F_PHYSR_LINKSPEED_SHIFT (4U) +#define PHY_RT_RTL8211F_PHYSR_LINKSPEED_10M (0U) +#define PHY_RT_RTL8211F_PHYSR_LINKSPEED_100M (1U) +#define PHY_RT_RTL8211F_PHYSR_LINKSPEED_1000M (2U) + +#define PHY_RT_RTL8211F_PAGSR_REG (0x1F) + +#define PHY_RT_RTL8211F_PAGE_INTR_PIN_ADDR (0xD40) +#define PHY_RT_RTL8211F_INTR_PIN_REG (0x16) +#define PHY_RT_RTL8211F_INTR_PIN_MASK BIT(5) + +#define PHY_RT_RTL8211F_PAGE_INTR_ADDR (0xA42U) +#define PHY_RT_RTL8211F_INER_REG (0x12U) +#define PHY_RT_RTL8211F_INER_LINKSTATUS_CHANGE_MASK BIT(4) +#define PHY_RT_RTL8211F_INSR_REG (0x1DU) + +#define PHY_RT_RTL8211F_RESET_HOLD_TIME_MS 10 + +struct rt_rtl8211f_config { + uint8_t addr; + const struct device *mdio_dev; +#if DT_ANY_INST_HAS_PROP_STATUS_OKAY(reset_gpios) + const struct gpio_dt_spec reset_gpio; +#endif +#if DT_ANY_INST_HAS_PROP_STATUS_OKAY(int_gpios) + const struct gpio_dt_spec interrupt_gpio; +#endif +}; + +struct rt_rtl8211f_data { + const struct device *dev; + struct phy_link_state state; + phy_callback_t cb; +#if DT_ANY_INST_HAS_PROP_STATUS_OKAY(int_gpios) + struct gpio_callback gpio_callback; +#endif + void *cb_data; + struct k_mutex mutex; + struct k_work_delayable phy_monitor_work; +}; + +static int phy_rt_rtl8211f_read(const struct device *dev, + uint16_t reg_addr, uint32_t *data) +{ + const struct rt_rtl8211f_config *config = dev->config; + int ret; + + /* Make sure excessive bits 16-31 are reset */ + *data = 0U; + + /* Read the PHY register */ + ret = mdio_read(config->mdio_dev, config->addr, reg_addr, (uint16_t *)data); + if (ret) { + return ret; + } + + return 0; +} + +static int phy_rt_rtl8211f_write(const struct device *dev, + uint16_t reg_addr, uint32_t data) +{ + const struct rt_rtl8211f_config *config = dev->config; + int ret; + + ret = mdio_write(config->mdio_dev, config->addr, reg_addr, (uint16_t)data); + if (ret) { + return ret; + } + + return 0; +} + +static int phy_rt_rtl8211f_reset(const struct device *dev) +{ + const struct rt_rtl8211f_config *config = dev->config; + uint32_t reg_val; + int ret; + +#if DT_ANY_INST_HAS_PROP_STATUS_OKAY(reset_gpios) + if (config->reset_gpio.port) { + /* Start reset */ + ret = gpio_pin_set_dt(&config->reset_gpio, 0); + if (ret) { + return ret; + } + + /* Hold reset for the minimum time specified by datasheet */ + k_busy_wait(USEC_PER_MSEC * PHY_RT_RTL8211F_RESET_HOLD_TIME_MS); + + /* Reset over */ + ret = gpio_pin_set_dt(&config->reset_gpio, 1); + if (ret) { + return ret; + } + + /* Wait another 30 ms (circuits settling time) before accessing registers */ + k_busy_wait(USEC_PER_MSEC * 30); + + goto finalize_reset; + } +#endif /* DT_ANY_INST_HAS_PROP_STATUS_OKAY(reset_gpios) */ + + /* Reset PHY using register */ + ret = phy_rt_rtl8211f_write(dev, MII_BMCR, MII_BMCR_RESET); + if (ret) { + LOG_ERR("Error writing phy (%d) basic control register", config->addr); + return ret; + } + + /* Wait for the minimum reset time specified by datasheet */ + k_busy_wait(USEC_PER_MSEC * PHY_RT_RTL8211F_RESET_HOLD_TIME_MS); + + /* Wait for the reset to be cleared */ + do { + ret = phy_rt_rtl8211f_read(dev, MII_BMCR, ®_val); + if (ret) { + LOG_ERR("Error reading phy (%d) basic control register", config->addr); + return ret; + } + } while (reg_val & MII_BMCR_RESET); + + goto finalize_reset; + +finalize_reset: + /* Wait until correct data can be read from registers */ + do { + ret = phy_rt_rtl8211f_read(dev, MII_PHYID1R, ®_val); + if (ret) { + LOG_ERR("Error reading phy (%d) identifier register 1", config->addr); + return ret; + } + } while (reg_val != REALTEK_OUI_MSB); + + return 0; +} + +static int phy_rt_rtl8211f_restart_autonegotiation(const struct device *dev) +{ + const struct rt_rtl8211f_config *config = dev->config; + uint32_t bmcr = 0; + int ret; + + /* Read control register to write back with autonegotiation bit */ + ret = phy_rt_rtl8211f_read(dev, MII_BMCR, &bmcr); + if (ret) { + LOG_ERR("Error reading phy (%d) basic control register", config->addr); + return ret; + } + + /* (re)start autonegotiation */ + LOG_DBG("PHY (%d) is entering autonegotiation sequence", config->addr); + bmcr |= MII_BMCR_AUTONEG_ENABLE | MII_BMCR_AUTONEG_RESTART; + + ret = phy_rt_rtl8211f_write(dev, MII_BMCR, bmcr); + if (ret) { + LOG_ERR("Error writing phy (%d) basic control register", config->addr); + return ret; + } + + return 0; +} + +static int phy_rt_rtl8211f_get_link(const struct device *dev, + struct phy_link_state *state) +{ + const struct rt_rtl8211f_config *config = dev->config; + struct rt_rtl8211f_data *data = dev->data; + int ret; + uint32_t physr = 0; + uint32_t duplex = 0; + struct phy_link_state old_state = data->state; + struct phy_link_state new_state = {}; + + /* Lock mutex */ + ret = k_mutex_lock(&data->mutex, K_FOREVER); + if (ret) { + LOG_ERR("PHY mutex lock error"); + return ret; + } + + /* Read PHY specific status register */ + ret = phy_rt_rtl8211f_read(dev, PHY_RT_RTL8211F_PHYSR_REG, &physr); + if (ret) { + LOG_ERR("Error reading phy (%d) specific status register", config->addr); + (void)k_mutex_unlock(&data->mutex); + return ret; + } + + /* Unlock mutex */ + (void)k_mutex_unlock(&data->mutex); + + new_state.is_up = physr & PHY_RT_RTL8211F_PHYSR_LINKSTATUS_MASK; + + if (!new_state.is_up) { + goto result; + } + + duplex = (physr & PHY_RT_RTL8211F_PHYSR_LINKDUPLEX_MASK); + switch ((physr & PHY_RT_RTL8211F_PHYSR_LINKSPEED_MASK) + >> PHY_RT_RTL8211F_PHYSR_LINKSPEED_SHIFT) { + case PHY_RT_RTL8211F_PHYSR_LINKSPEED_100M: + if (duplex) { + new_state.speed = LINK_FULL_100BASE_T; + } else { + new_state.speed = LINK_HALF_100BASE_T; + } + break; + case PHY_RT_RTL8211F_PHYSR_LINKSPEED_1000M: + if (duplex) { + new_state.speed = LINK_FULL_1000BASE_T; + } else { + new_state.speed = LINK_HALF_1000BASE_T; + } + break; + case PHY_RT_RTL8211F_PHYSR_LINKSPEED_10M: + default: + if (duplex) { + new_state.speed = LINK_FULL_10BASE_T; + } else { + new_state.speed = LINK_HALF_10BASE_T; + } + break; + } +result: + if (memcmp(&old_state, &new_state, sizeof(struct phy_link_state)) != 0) { + LOG_INF("PHY %d is %s", config->addr, new_state.is_up ? "up" : "down"); + if (new_state.is_up) { + LOG_INF("PHY (%d) Link speed %s Mb, %s duplex", config->addr, + (PHY_LINK_IS_SPEED_1000M(new_state.speed) ? "1000" : + (PHY_LINK_IS_SPEED_100M(new_state.speed) ? "100" : "10")), + PHY_LINK_IS_FULL_DUPLEX(new_state.speed) ? "full" : "half"); + } + } + + memcpy(state, &new_state, sizeof(struct phy_link_state)); + + return ret; +} + +static int phy_rt_rtl8211f_cfg_link(const struct device *dev, + enum phy_link_speed speeds) +{ + const struct rt_rtl8211f_config *config = dev->config; + struct rt_rtl8211f_data *data = dev->data; + uint32_t anar; + uint32_t gbcr; + int ret; + + /* Lock mutex */ + ret = k_mutex_lock(&data->mutex, K_FOREVER); + if (ret) { + LOG_ERR("PHY mutex lock error"); + return ret; + } + + /* We are going to reconfigure the phy, don't need to monitor until done */ +#if DT_ANY_INST_HAS_PROP_STATUS_OKAY(int_gpios) + if (!config->interrupt_gpio.port) { + k_work_cancel_delayable(&data->phy_monitor_work); + } +#else + k_work_cancel_delayable(&data->phy_monitor_work); +#endif /* DT_ANY_INST_HAS_PROP_STATUS_OKAY(int_gpios) */ + + /* Read ANAR register to write back */ + ret = phy_rt_rtl8211f_read(dev, MII_ANAR, &anar); + if (ret) { + LOG_ERR("Error reading phy (%d) advertising register", config->addr); + goto done; + } + + /* Read GBCR register to write back */ + ret = phy_rt_rtl8211f_read(dev, MII_1KTCR, &gbcr); + if (ret) { + LOG_ERR("Error reading phy (%d) 1000Base-T control register", config->addr); + goto done; + } + + /* Setup advertising register */ + if (speeds & LINK_FULL_100BASE_T) { + anar |= MII_ADVERTISE_100_FULL; + } else { + anar &= ~MII_ADVERTISE_100_FULL; + } + if (speeds & LINK_HALF_100BASE_T) { + anar |= MII_ADVERTISE_100_HALF; + } else { + anar &= ~MII_ADVERTISE_100_HALF; + } + if (speeds & LINK_FULL_10BASE_T) { + anar |= MII_ADVERTISE_10_FULL; + } else { + anar &= ~MII_ADVERTISE_10_FULL; + } + if (speeds & LINK_HALF_10BASE_T) { + anar |= MII_ADVERTISE_10_HALF; + } else { + anar &= ~MII_ADVERTISE_10_HALF; + } + + /* Setup 1000Base-T control register */ + if (speeds & LINK_FULL_1000BASE_T) { + gbcr |= MII_ADVERTISE_1000_FULL; + } else { + gbcr &= ~MII_ADVERTISE_1000_FULL; + } + + /* Write capabilities to advertising register */ + ret = phy_rt_rtl8211f_write(dev, MII_ANAR, anar); + if (ret) { + LOG_ERR("Error writing phy (%d) advertising register", config->addr); + goto done; + } + + /* Write capabilities to 1000Base-T control register */ + ret = phy_rt_rtl8211f_write(dev, MII_1KTCR, gbcr); + if (ret) { + LOG_ERR("Error writing phy (%d) 1000Base-T control register", config->addr); + goto done; + } + + /* (Re)start autonegotiation */ + ret = phy_rt_rtl8211f_restart_autonegotiation(dev); + if (ret) { + LOG_ERR("Error restarting autonegotiation"); + goto done; + } +done: + /* Unlock mutex */ + (void)k_mutex_unlock(&data->mutex); + + /* Start monitoring */ +#if DT_ANY_INST_HAS_PROP_STATUS_OKAY(int_gpios) + if (!config->interrupt_gpio.port) { + k_work_reschedule(&data->phy_monitor_work, K_MSEC(CONFIG_PHY_MONITOR_PERIOD)); + } +#else + k_work_reschedule(&data->phy_monitor_work, K_MSEC(CONFIG_PHY_MONITOR_PERIOD)); +#endif /* DT_ANY_INST_HAS_PROP_STATUS_OKAY(int_gpios) */ + + return ret; +} + +static int phy_rt_rtl8211f_link_cb_set(const struct device *dev, + phy_callback_t cb, void *user_data) +{ + struct rt_rtl8211f_data *data = dev->data; + + data->cb = cb; + data->cb_data = user_data; + + phy_rt_rtl8211f_get_link(dev, &data->state); + + data->cb(dev, &data->state, data->cb_data); + + return 0; +} + +#if DT_ANY_INST_HAS_PROP_STATUS_OKAY(int_gpios) +static int phy_rt_rtl8211f_clear_interrupt(struct rt_rtl8211f_data *data) +{ + const struct device *dev = data->dev; + const struct rt_rtl8211f_config *config = dev->config; + uint32_t reg_val; + int ret; + + /* Lock mutex */ + ret = k_mutex_lock(&data->mutex, K_FOREVER); + if (ret) { + LOG_ERR("PHY mutex lock error"); + return ret; + } + + /* Read/clear PHY interrupt status register */ + ret = phy_rt_rtl8211f_read(dev, PHY_RT_RTL8211F_INSR_REG, ®_val); + if (ret) { + LOG_ERR("Error reading phy (%d) interrupt status register", config->addr); + } + + /* Unlock mutex */ + (void)k_mutex_unlock(&data->mutex); + + return ret; +} + +static void phy_rt_rtl8211f_interrupt_handler(const struct device *port, + struct gpio_callback *cb, + gpio_port_pins_t pins) +{ + struct rt_rtl8211f_data *data = CONTAINER_OF(cb, struct rt_rtl8211f_data, gpio_callback); + int ret; + + ret = k_work_reschedule(&data->phy_monitor_work, K_NO_WAIT); + if (ret < 0) { + LOG_ERR("Failed to schedule phy_monitor_work from ISR"); + } +} +#endif /* DT_ANY_INST_HAS_PROP_STATUS_OKAY(int_gpios) */ + +static void phy_rt_rtl8211f_monitor_work_handler(struct k_work *work) +{ + struct k_work_delayable *dwork = k_work_delayable_from_work(work); + struct rt_rtl8211f_data *data = + CONTAINER_OF(dwork, struct rt_rtl8211f_data, phy_monitor_work); + const struct device *dev = data->dev; +#if DT_ANY_INST_HAS_PROP_STATUS_OKAY(int_gpios) + const struct rt_rtl8211f_config *config = dev->config; +#endif /* DT_ANY_INST_HAS_PROP_STATUS_OKAY(int_gpios) */ + struct phy_link_state state = {}; + int ret; + +#if DT_ANY_INST_HAS_PROP_STATUS_OKAY(int_gpios) + if (config->interrupt_gpio.port) { + ret = phy_rt_rtl8211f_clear_interrupt(data); + if (ret) { + return; + } + } +#endif /* DT_ANY_INST_HAS_PROP_STATUS_OKAY(int_gpios) */ + + ret = phy_rt_rtl8211f_get_link(dev, &state); + + if (ret == 0 && memcmp(&state, &data->state, sizeof(struct phy_link_state)) != 0) { + memcpy(&data->state, &state, sizeof(struct phy_link_state)); + if (data->cb) { + data->cb(dev, &data->state, data->cb_data); + } + } + +#if DT_ANY_INST_HAS_PROP_STATUS_OKAY(int_gpios) + if (!config->interrupt_gpio.port) { + k_work_reschedule(&data->phy_monitor_work, K_MSEC(CONFIG_PHY_MONITOR_PERIOD)); + } +#else + k_work_reschedule(&data->phy_monitor_work, K_MSEC(CONFIG_PHY_MONITOR_PERIOD)); +#endif /* DT_ANY_INST_HAS_PROP_STATUS_OKAY(int_gpios) */ +} + +static int phy_rt_rtl8211f_init(const struct device *dev) +{ + const struct rt_rtl8211f_config *config = dev->config; + struct rt_rtl8211f_data *data = dev->data; +#if DT_ANY_INST_HAS_PROP_STATUS_OKAY(int_gpios) + uint32_t reg_val; +#endif /* DT_ANY_INST_HAS_PROP_STATUS_OKAY(int_gpios) */ + int ret; + + data->dev = dev; + + ret = k_mutex_init(&data->mutex); + if (ret) { + return ret; + } + + mdio_bus_enable(config->mdio_dev); + +#if DT_ANY_INST_HAS_PROP_STATUS_OKAY(reset_gpios) + /* Configure reset pin */ + if (config->reset_gpio.port) { + ret = gpio_pin_configure_dt(&config->reset_gpio, GPIO_OUTPUT_ACTIVE); + if (ret) { + return ret; + } + } +#endif /* DT_ANY_INST_HAS_PROP_STATUS_OKAY(reset_gpios) */ + + /* Reset PHY */ + ret = phy_rt_rtl8211f_reset(dev); + if (ret) { + LOG_ERR("Failed to reset phy (%d)", config->addr); + return ret; + } + + k_work_init_delayable(&data->phy_monitor_work, phy_rt_rtl8211f_monitor_work_handler); + +#if DT_ANY_INST_HAS_PROP_STATUS_OKAY(int_gpios) + if (!config->interrupt_gpio.port) { + goto skip_int_gpio; + } + + /* Set INTB/PMEB pin to interrupt mode */ + ret = phy_rt_rtl8211f_write(dev, PHY_RT_RTL8211F_PAGSR_REG, + PHY_RT_RTL8211F_PAGE_INTR_PIN_ADDR); + if (ret) { + LOG_ERR("Error writing phy (%d) page select register", config->addr); + return ret; + } + ret = phy_rt_rtl8211f_read(dev, PHY_RT_RTL8211F_INTR_PIN_REG, ®_val); + if (!ret) { + reg_val &= ~PHY_RT_RTL8211F_INTR_PIN_MASK; + ret = phy_rt_rtl8211f_write(dev, PHY_RT_RTL8211F_INTR_PIN_REG, reg_val); + if (ret) { + LOG_ERR("Error writing phy (%d) interrupt pin setting register", + config->addr); + return ret; + } + } else { + LOG_ERR("Error reading phy (%d) interrupt pin setting register", config->addr); + return ret; + } + /* Restore to default page 0 */ + ret = phy_rt_rtl8211f_write(dev, PHY_RT_RTL8211F_PAGSR_REG, 0); + if (ret) { + LOG_ERR("Error writing phy (%d) page select register", config->addr); + return ret; + } + + /* Clear interrupt */ + ret = phy_rt_rtl8211f_clear_interrupt(data); + if (ret) { + return ret; + } + + /* Configure interrupt pin */ + ret = gpio_pin_configure_dt(&config->interrupt_gpio, GPIO_INPUT); + if (ret) { + return ret; + } + + gpio_init_callback(&data->gpio_callback, phy_rt_rtl8211f_interrupt_handler, + BIT(config->interrupt_gpio.pin)); + ret = gpio_add_callback_dt(&config->interrupt_gpio, &data->gpio_callback); + if (ret) { + return ret; + } + + ret = gpio_pin_interrupt_configure_dt(&config->interrupt_gpio, GPIO_INT_EDGE_TO_ACTIVE); + if (ret) { + return ret; + } + + /* Enable PHY interrupt. */ + ret = phy_rt_rtl8211f_write(dev, PHY_RT_RTL8211F_PAGSR_REG, + PHY_RT_RTL8211F_PAGE_INTR_ADDR); + if (ret) { + LOG_ERR("Error writing phy (%d) page select register", config->addr); + return ret; + } + ret = phy_rt_rtl8211f_read(dev, PHY_RT_RTL8211F_INER_REG, ®_val); + if (ret) { + LOG_ERR("Error reading phy (%d) interrupt enable register", config->addr); + return ret; + } + reg_val |= PHY_RT_RTL8211F_INER_LINKSTATUS_CHANGE_MASK; + ret = phy_rt_rtl8211f_write(dev, PHY_RT_RTL8211F_INER_REG, reg_val); + if (ret) { + LOG_ERR("Error writing phy (%d) interrupt enable register", config->addr); + return ret; + } + /* Restore to default page 0 */ + ret = phy_rt_rtl8211f_write(dev, PHY_RT_RTL8211F_PAGSR_REG, 0); + if (ret) { + LOG_ERR("Error writing phy (%d) page select register", config->addr); + return ret; + } +skip_int_gpio: +#endif /* DT_ANY_INST_HAS_PROP_STATUS_OKAY(int_gpios) */ + + return 0; +} + +static const struct ethphy_driver_api rt_rtl8211f_phy_api = { + .get_link = phy_rt_rtl8211f_get_link, + .cfg_link = phy_rt_rtl8211f_cfg_link, + .link_cb_set = phy_rt_rtl8211f_link_cb_set, + .read = phy_rt_rtl8211f_read, + .write = phy_rt_rtl8211f_write, +}; + +#if DT_ANY_INST_HAS_PROP_STATUS_OKAY(reset_gpios) +#define RESET_GPIO(n) \ + .reset_gpio = GPIO_DT_SPEC_INST_GET_OR(n, reset_gpios, {0}), +#else +#define RESET_GPIO(n) +#endif /* DT_ANY_INST_HAS_PROP_STATUS_OKAY(reset_gpios) */ + +#if DT_ANY_INST_HAS_PROP_STATUS_OKAY(int_gpios) +#define INTERRUPT_GPIO(n) \ + .interrupt_gpio = GPIO_DT_SPEC_INST_GET_OR(n, int_gpios, {0}), +#else +#define INTERRUPT_GPIO(n) +#endif /* DT_ANY_INST_HAS_PROP_STATUS_OKAY(int_gpios) */ + +#define REALTEK_RTL8211F_INIT(n) \ + static const struct rt_rtl8211f_config rt_rtl8211f_##n##_config = { \ + .addr = DT_INST_REG_ADDR(n), \ + .mdio_dev = DEVICE_DT_GET(DT_INST_PARENT(n)), \ + RESET_GPIO(n) \ + INTERRUPT_GPIO(n) \ + }; \ + \ + static struct rt_rtl8211f_data rt_rtl8211f_##n##_data; \ + \ + DEVICE_DT_INST_DEFINE(n, &phy_rt_rtl8211f_init, NULL, \ + &rt_rtl8211f_##n##_data, &rt_rtl8211f_##n##_config, \ + POST_KERNEL, CONFIG_PHY_INIT_PRIORITY, \ + &rt_rtl8211f_phy_api); + +DT_INST_FOREACH_STATUS_OKAY(REALTEK_RTL8211F_INIT) diff --git a/dts/bindings/ethernet/realtek,rtl8211f.yaml b/dts/bindings/ethernet/realtek,rtl8211f.yaml new file mode 100644 index 0000000000000..1f8cc22e71db3 --- /dev/null +++ b/dts/bindings/ethernet/realtek,rtl8211f.yaml @@ -0,0 +1,16 @@ +# Copyright 2023-2024 NXP +# SPDX-License-Identifier: Apache-2.0 + +description: Realtek RTL8211F Ethernet PHY device + +compatible: "realtek,rtl8211f" + +include: ethernet-phy.yaml + +properties: + reset-gpios: + type: phandle-array + description: GPIO connected to PHY reset signal pin. Reset is active low. + int-gpios: + type: phandle-array + description: GPIO for interrupt signal indicating PHY state change. From 684885a7f36b5c7020a22eeee4d761c3dd8d7d06 Mon Sep 17 00:00:00 2001 From: Stanislav Poboril Date: Mon, 19 Feb 2024 18:43:04 +0100 Subject: [PATCH 1975/2849] boards: nxp: Support NXP ENET_1G on mimxrt1170_evk Support NXP ENET_1G on mimxrt1170_evk/mimxrt1176/cm7 platform. Added test configuration sample.net.zperf.nxp_enet1g and documented the usage of the ethernet driver with ENET_1G peripheral. Fixes: #66348 Signed-off-by: Stanislav Poboril --- boards/nxp/mimxrt1170_evk/doc/index.rst | 12 +++- .../nxp/mimxrt1170_evk/dts/nxp,enet1g.overlay | 36 ++++++++++++ .../mimxrt1170_evk-pinctrl.dtsi | 58 +++++++++++++++++++ boards/nxp/mimxrt1170_evk/mimxrt1170_evk.dtsi | 28 +++++++++ dts/arm/nxp/nxp_rt11xx.dtsi | 30 ++++++---- samples/net/zperf/sample.yaml | 7 +++ 6 files changed, 158 insertions(+), 13 deletions(-) create mode 100644 boards/nxp/mimxrt1170_evk/dts/nxp,enet1g.overlay diff --git a/boards/nxp/mimxrt1170_evk/doc/index.rst b/boards/nxp/mimxrt1170_evk/doc/index.rst index d6a80009e7c79..5272c30e115af 100644 --- a/boards/nxp/mimxrt1170_evk/doc/index.rst +++ b/boards/nxp/mimxrt1170_evk/doc/index.rst @@ -144,8 +144,9 @@ RT1170 EVKB (`mimxrt1170_evk@B//cm7/cm4`) +-----------+------------+-------------------------------------+-----------------+-----------------+ | WATCHDOG | on-chip | watchdog | Supported (M7) | Supported (M7) | +-----------+------------+-------------------------------------+-----------------+-----------------+ -| ENET | on-chip | ethernet - 10/100M (ENET_QOS or | Supported (M7) | No support | -| ENET1G | | GigE not supported yet) | | | +| ENET | on-chip | ethernet - 10/100M | Supported (M7) | No support | ++-----------+------------+-------------------------------------+-----------------+-----------------+ +| ENET1G | on-chip | ethernet - 10/100/1000M | Supported (M7) | No support | +-----------+------------+-------------------------------------+-----------------+-----------------+ | SAI | on-chip | i2s | Supported | No support | +-----------+------------+-------------------------------------+-----------------+-----------------+ @@ -444,3 +445,10 @@ should see the following message in the terminal: .. _NXP MCUXpresso for Visual Studio Code: https://www.nxp.com/design/software/development-software/mcuxpresso-software-and-tools-/mcuxpresso-for-visual-studio-code:MCUXPRESSO-VSC + +ENET1G Driver +============= + +Current default of ethernet driver is to use 100M Ethernet instance ENET. +To use the 1G Ethernet instance ENET1G, include the overlay to west build with +the option `-DEXTRA_DTC_OVERLAY_FILE=nxp,enet1g.overlay` instead. diff --git a/boards/nxp/mimxrt1170_evk/dts/nxp,enet1g.overlay b/boards/nxp/mimxrt1170_evk/dts/nxp,enet1g.overlay new file mode 100644 index 0000000000000..cff3f6bad7c80 --- /dev/null +++ b/boards/nxp/mimxrt1170_evk/dts/nxp,enet1g.overlay @@ -0,0 +1,36 @@ +/* + * Copyright 2023-2024 NXP + * + * ENET_1G binding overlay + */ + +/ { + soc { + /delete-node/ ethernet@40424000; + }; +}; + +&enet1g { + status = "okay"; +}; + +&enet1g_mac { + status = "okay"; +}; + +&enet1g_mdio { + status = "okay"; + enet1g_phy: phy@1 { + status = "okay"; + }; +}; + +&enet1g_ptp_clock { + status = "okay"; +}; + +&pinctrl { + /delete-node/ pinmux_enet; + /delete-node/ pinmux_enet_mdio; + /delete-node/ pinmux_ptp; +}; diff --git a/boards/nxp/mimxrt1170_evk/mimxrt1170_evk-pinctrl.dtsi b/boards/nxp/mimxrt1170_evk/mimxrt1170_evk-pinctrl.dtsi index 43b1642da96f9..4031f2383f397 100644 --- a/boards/nxp/mimxrt1170_evk/mimxrt1170_evk-pinctrl.dtsi +++ b/boards/nxp/mimxrt1170_evk/mimxrt1170_evk-pinctrl.dtsi @@ -85,6 +85,64 @@ pinmux_ptp: pinmux_ptp { }; + pinmux_enet1g: pinmux_enet1g { + group0 { + pinmux = <&iomuxc_gpio_disp_b1_11_enet_1g_tx_clk_io>, // ENET_RGMII_TXC + <&iomuxc_gpio_disp_b1_01_enet_1g_rx_clk>; // ENET_RGMII_RXC + bias-disable; + drive-strength = "high"; + slew-rate = "fast"; + input-enable; + }; + group1 { + pinmux = <&iomuxc_gpio_disp_b1_09_enet_1g_tdata00>, // ENET_RGMII_TXD0 + <&iomuxc_gpio_disp_b1_08_enet_1g_tdata01>, // ENET_RGMII_TXD1 + <&iomuxc_gpio_disp_b1_07_enet_1g_tdata02>, // ENET_RGMII_TXD2 + <&iomuxc_gpio_disp_b1_06_enet_1g_tdata03>, // ENET_RGMII_TXD3 + <&iomuxc_gpio_disp_b1_10_enet_1g_tx_en>; // ENET_RGMII_TX_EN + drive-strength = "high"; + bias-pull-up; + slew-rate = "fast"; + }; + group2 { + pinmux = <&iomuxc_gpio_disp_b1_02_enet_1g_rdata00>, // ENET_RGMII_RXD0 + <&iomuxc_gpio_disp_b1_03_enet_1g_rdata01>, // ENET_RGMII_RXD1 + <&iomuxc_gpio_disp_b1_04_enet_1g_rdata02>, // ENET_RGMII_RXD2 + <&iomuxc_gpio_disp_b1_05_enet_1g_rdata03>, // ENET_RGMII_RXD3 + <&iomuxc_gpio_disp_b1_00_enet_1g_rx_en>; // ENET_RGMII_RX_EN + drive-strength = "high"; + bias-pull-down; + slew-rate = "fast"; + input-enable; + }; + }; + + pinmux_enet1g_mdio: pinmux_enet1g_mdio { + group0 { + pinmux = <&iomuxc_gpio_disp_b2_13_gpio11_io14>; // ETHPHY_RST_B + drive-strength = "high"; + bias-pull-down; + slew-rate = "slow"; + }; + group1 { + pinmux = <&iomuxc_gpio_disp_b2_12_gpio_mux5_io13>; // RGMII1_PHY_INTB + drive-strength = "high"; + bias-pull-down; + slew-rate = "fast"; + input-enable; + }; + group2 { + pinmux = <&iomuxc_gpio_emc_b2_19_enet_1g_mdc>, // ENET_RGMII_MDC + <&iomuxc_gpio_emc_b2_20_enet_1g_mdio>; // ENET_RGMII_MDIO + drive-strength = "high"; + bias-pull-down; + slew-rate = "fast"; + }; + }; + + pinmux_enet1g_ptp: pinmux_enet1g_ptp { + }; + pinmux_flexcan3: pinmux_flexcan3 { group0 { pinmux = <&iomuxc_lpsr_gpio_lpsr_01_can3_rx>, diff --git a/boards/nxp/mimxrt1170_evk/mimxrt1170_evk.dtsi b/boards/nxp/mimxrt1170_evk/mimxrt1170_evk.dtsi index 48a39410964a1..072c1b18f1e9b 100644 --- a/boards/nxp/mimxrt1170_evk/mimxrt1170_evk.dtsi +++ b/boards/nxp/mimxrt1170_evk/mimxrt1170_evk.dtsi @@ -126,6 +126,34 @@ pinctrl-names = "default"; }; +&enet1g_mac { + status = "disabled"; + pinctrl-0 = <&pinmux_enet1g>; + pinctrl-names = "default"; + phy-handle = <&enet1g_phy>; + phy-connection-type = "rgmii"; + zephyr,random-mac-address; +}; + +&enet1g_mdio { + status = "disabled"; + pinctrl-0 = <&pinmux_enet1g_mdio>; + pinctrl-names = "default"; + enet1g_phy: phy@1 { + compatible = "realtek,rtl8211f"; + reg = <1>; + status = "disabled"; + reset-gpios = <&gpio11 14 GPIO_ACTIVE_HIGH>; + int-gpios = <&gpio5 13 GPIO_ACTIVE_LOW>; + }; +}; + +&enet1g_ptp_clock { + status = "disabled"; + pinctrl-0 = <&pinmux_enet1g_ptp>; + pinctrl-names = "default"; +}; + &csi { pinctrl-0 = <&pinmux_csi>; pinctrl-names = "default"; diff --git a/dts/arm/nxp/nxp_rt11xx.dtsi b/dts/arm/nxp/nxp_rt11xx.dtsi index 6df4cd1e27819..c9c126f5173ed 100644 --- a/dts/arm/nxp/nxp_rt11xx.dtsi +++ b/dts/arm/nxp/nxp_rt11xx.dtsi @@ -776,22 +776,30 @@ }; }; - /* - * enet1g peripheral to use with kinetis-ethernet (eth_mcux) driver - * just like the enet peripheral (i.e. only 10/100Mbit for now) - */ enet1g: ethernet@40420000 { - compatible = "nxp,kinetis-ethernet"; + compatible = "nxp,enet1g"; reg = <0x40420000 0x628>; - interrupts = <141 0>; - interrupt-names = "COMMON"; + clocks = <&ccm IMX_CCM_ENET1G_CLK 0 0>; status = "disabled"; - phy-addr = <1>; - ptp1g: ptp { - compatible = "nxp,kinetis-ptp"; + enet1g_mac: ethernet { + compatible = "nxp,enet-mac"; + interrupts = <141 0>; + interrupt-names = "COMMON"; + nxp,mdio = <&enet1g_mdio>; + nxp,ptp-clock = <&enet1g_ptp_clock>; + status = "disabled"; + }; + enet1g_mdio: mdio { + compatible = "nxp,enet-mdio"; status = "disabled"; + #address-cells = <1>; + #size-cells = <0>; + }; + enet1g_ptp_clock: ptp_clock { + compatible = "nxp,enet-ptp-clock"; interrupts = <142 0>; - interrupt-names = "IEEE1588_TMR"; + status = "disabled"; + clocks = <&ccm IMX_CCM_ENET_PLL 0 0>; }; }; diff --git a/samples/net/zperf/sample.yaml b/samples/net/zperf/sample.yaml index 12c0cfd1bf2e3..35260fd723aa6 100644 --- a/samples/net/zperf/sample.yaml +++ b/samples/net/zperf/sample.yaml @@ -98,3 +98,10 @@ tests: depends_on: - arduino_spi - arduino_gpio + sample.net.zperf.nxp_enet1g: + extra_args: EXTRA_DTC_OVERLAY_FILE="nxp,enet1g.overlay" + tags: + - net + - zperf + platform_allow: + - mimxrt1170_evk/mimxrt1176/cm7 From db57c43bbb9967c933467abf3937cc121c9a59e4 Mon Sep 17 00:00:00 2001 From: Stanislav Poboril Date: Mon, 3 Jun 2024 13:30:35 +0200 Subject: [PATCH 1976/2849] boards: nxp: Adjusted device tree on vmu_rt1170 for updated ENET_1G. Adjusted the board's device tree after ENET_1G compatible changed from "nxp,kinetis-ethernet" to "nxp,enet1g". Signed-off-by: Stanislav Poboril --- boards/nxp/vmu_rt1170/Kconfig.defconfig | 3 -- boards/nxp/vmu_rt1170/vmu_rt1170-pinctrl.dtsi | 29 ++++++++++++++----- boards/nxp/vmu_rt1170/vmu_rt1170.dtsi | 22 ++++++++++++-- .../vmu_rt1170/vmu_rt1170_mimxrt1176_cm7.dts | 13 ++++++++- 4 files changed, 54 insertions(+), 13 deletions(-) diff --git a/boards/nxp/vmu_rt1170/Kconfig.defconfig b/boards/nxp/vmu_rt1170/Kconfig.defconfig index f0f7bffa888b0..4bf5b36250753 100644 --- a/boards/nxp/vmu_rt1170/Kconfig.defconfig +++ b/boards/nxp/vmu_rt1170/Kconfig.defconfig @@ -26,9 +26,6 @@ if NETWORKING config NET_L2_ETHERNET default y if CPU_CORTEX_M7 # No cache memory support is required for driver -config ETH_MCUX_PHY_RESET - default n - config ETH_MCUX_RMII_EXT_CLK default y diff --git a/boards/nxp/vmu_rt1170/vmu_rt1170-pinctrl.dtsi b/boards/nxp/vmu_rt1170/vmu_rt1170-pinctrl.dtsi index 1390fb6805839..e6d00911b1328 100644 --- a/boards/nxp/vmu_rt1170/vmu_rt1170-pinctrl.dtsi +++ b/boards/nxp/vmu_rt1170/vmu_rt1170-pinctrl.dtsi @@ -3,16 +3,15 @@ * SPDX-License-Identifier: Apache-2.0 * * Note: File generated by gen_board_pinctrl.py - * from vmu_rt1170.mex + * from vmu_rt1170.mex, then updated manually */ #include &pinctrl { - pinmux_enet: pinmux_enet { + pinmux_enet1g: pinmux_enet1g { group0 { - pinmux = <&iomuxc_gpio_disp_b2_09_gpio_mux5_io10>, - <&iomuxc_gpio_disp_b1_00_enet_1g_rx_en>, + pinmux = <&iomuxc_gpio_disp_b1_00_enet_1g_rx_en>, <&iomuxc_gpio_disp_b1_01_enet_1g_rx_er>; drive-strength = "high"; bias-pull-down; @@ -27,9 +26,7 @@ input-enable; }; group2 { - pinmux = <&iomuxc_gpio_emc_b2_19_enet_1g_mdc>, - <&iomuxc_gpio_emc_b2_20_enet_1g_mdio>, - <&iomuxc_gpio_disp_b1_09_enet_1g_tdata00>, + pinmux = <&iomuxc_gpio_disp_b1_09_enet_1g_tdata00>, <&iomuxc_gpio_disp_b1_08_enet_1g_tdata01>, <&iomuxc_gpio_disp_b1_10_enet_1g_tx_en>; drive-strength = "high"; @@ -44,6 +41,24 @@ }; }; + pinmux_enet1g_mdio: pinmux_enet1g_mdio { + group0 { + pinmux = <&iomuxc_gpio_emc_b2_19_enet_1g_mdc>, + <&iomuxc_gpio_emc_b2_20_enet_1g_mdio>; + drive-strength = "high"; + slew-rate = "fast"; + }; + group1 { + pinmux = <&iomuxc_gpio_disp_b2_09_gpio_mux5_io10>; + drive-strength = "high"; + bias-pull-down; + slew-rate = "fast"; + }; + }; + + pinmux_enet1g_ptp: pinmux_enet1g_ptp { + }; + pinmux_flexcan1: pinmux_flexcan1 { group0 { pinmux = <&iomuxc_gpio_ad_07_can1_rx>, diff --git a/boards/nxp/vmu_rt1170/vmu_rt1170.dtsi b/boards/nxp/vmu_rt1170/vmu_rt1170.dtsi index 9d251e9357717..ac8e6a1869461 100644 --- a/boards/nxp/vmu_rt1170/vmu_rt1170.dtsi +++ b/boards/nxp/vmu_rt1170/vmu_rt1170.dtsi @@ -98,8 +98,26 @@ status = "okay"; }; -&enet1g { - pinctrl-0 = <&pinmux_enet>; +&enet1g_mac { + pinctrl-0 = <&pinmux_enet1g>; + pinctrl-names = "default"; + phy-handle = <&enet1g_phy>; + phy-connection-type = "rmii"; + zephyr,random-mac-address; +}; + +&enet1g_mdio { + pinctrl-0 = <&pinmux_enet1g_mdio>; + pinctrl-names = "default"; + enet1g_phy: phy@1 { + compatible = "nxp,tja1103"; + reg = <1>; + master-slave = "master"; + }; +}; + +&enet1g_ptp_clock { + pinctrl-0 = <&pinmux_enet1g_ptp>; pinctrl-names = "default"; }; diff --git a/boards/nxp/vmu_rt1170/vmu_rt1170_mimxrt1176_cm7.dts b/boards/nxp/vmu_rt1170/vmu_rt1170_mimxrt1176_cm7.dts index b38931865ee4a..d4e9788faca05 100644 --- a/boards/nxp/vmu_rt1170/vmu_rt1170_mimxrt1176_cm7.dts +++ b/boards/nxp/vmu_rt1170/vmu_rt1170_mimxrt1176_cm7.dts @@ -481,7 +481,18 @@ &enet1g { status = "okay"; - int-gpios = <&gpio5 10 GPIO_ACTIVE_HIGH>; +}; + +&enet1g_mac { + status = "okay"; +}; + +&enet1g_mdio { + status = "okay"; + enet1g_phy: phy@1 { + status = "okay"; + int-gpios = <&gpio5 10 GPIO_ACTIVE_HIGH>; + }; }; zephyr_udc0: &usb1 { From 87fc25afc107c7ead8c38fc092f8f1c36425032d Mon Sep 17 00:00:00 2001 From: Tom Burdick Date: Thu, 6 Jun 2024 09:30:36 -0500 Subject: [PATCH 1977/2849] sensing: Fix build warning on invalid array index The assert was verifying that the current sensor address was greater or equal than the start of the iterable section - 1 which isn't quite right as the start is inclusive. Signed-off-by: Tom Burdick --- subsys/sensing/sensor_mgmt.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subsys/sensing/sensor_mgmt.h b/subsys/sensing/sensor_mgmt.h index 4672833e0096a..0cd05a3e313d8 100644 --- a/subsys/sensing/sensor_mgmt.h +++ b/subsys/sensing/sensor_mgmt.h @@ -26,7 +26,7 @@ extern "C" { STRUCT_SECTION_END_EXTERN(sensing_sensor); \ for (struct sensing_sensor *sensor = STRUCT_SECTION_END(sensing_sensor) \ - 1; \ - ({ __ASSERT(sensor >= STRUCT_SECTION_START(sensing_sensor) - 1, \ + ({ __ASSERT(sensor >= STRUCT_SECTION_START(sensing_sensor), \ "unexpected list start location"); \ sensor >= STRUCT_SECTION_START(sensing_sensor); }); \ sensor--) From 6069f946be1bd502a4cac3dae8a0ff4a3548dbea Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Tue, 4 Jun 2024 22:33:37 -0700 Subject: [PATCH 1978/2849] soc: intel_adsp: Avoid duplicate header adsp_memory.h is pretty much the same for all ace platforms. Generalize it getting register address from devicetree and and move it to a common place. Signed-off-by: Flavio Ceolin --- dts/xtensa/intel/intel_adsp_ace15_mtpm.dtsi | 15 ++ dts/xtensa/intel/intel_adsp_ace20_lnl.dtsi | 15 ++ dts/xtensa/intel/intel_adsp_ace30_ptl.dtsi | 15 ++ .../ace/include/ace15_mtpm/adsp_memory.h | 177 ------------------ .../ace/include/ace20_lnl/adsp_memory.h | 175 ----------------- .../ace/include/{ace30_ptl => }/adsp_memory.h | 8 +- 6 files changed, 49 insertions(+), 356 deletions(-) delete mode 100644 soc/intel/intel_adsp/ace/include/ace15_mtpm/adsp_memory.h delete mode 100644 soc/intel/intel_adsp/ace/include/ace20_lnl/adsp_memory.h rename soc/intel/intel_adsp/ace/include/{ace30_ptl => }/adsp_memory.h (94%) diff --git a/dts/xtensa/intel/intel_adsp_ace15_mtpm.dtsi b/dts/xtensa/intel/intel_adsp_ace15_mtpm.dtsi index 15b7128aea5ed..7c2050b109fda 100644 --- a/dts/xtensa/intel/intel_adsp_ace15_mtpm.dtsi +++ b/dts/xtensa/intel/intel_adsp_ace15_mtpm.dtsi @@ -111,6 +111,21 @@ soc { + l1ccap: l1ccap@1fe80080 { + compatible = "intel,adsp-l1ccap"; + reg = <0x1fe80080 0x4>; + }; + + l1ccfg: l1ccfg@1fe80084 { + compatible = "intel,adsp-l1ccfg"; + reg = <0x1fe80084 0x4>; + }; + + l1pcfg: l1pcfg@1fe80088 { + compatible = "intel,adsp-l1pcfg"; + reg = <0x1fe80088 0x4>; + }; + lsbpm: lsbpm@71d80 { compatible = "intel,adsp-lsbpm"; reg = <0x71d80 0x0008>; diff --git a/dts/xtensa/intel/intel_adsp_ace20_lnl.dtsi b/dts/xtensa/intel/intel_adsp_ace20_lnl.dtsi index e3462c834d193..c26d2b815fe0a 100644 --- a/dts/xtensa/intel/intel_adsp_ace20_lnl.dtsi +++ b/dts/xtensa/intel/intel_adsp_ace20_lnl.dtsi @@ -130,6 +130,21 @@ soc { + l1ccap: l1ccap@1fe80080 { + compatible = "intel,adsp-l1ccap"; + reg = <0x1fe80080 0x4>; + }; + + l1ccfg: l1ccfg@1fe80084 { + compatible = "intel,adsp-l1ccfg"; + reg = <0x1fe80084 0x4>; + }; + + l1pcfg: l1pcfg@1fe80088 { + compatible = "intel,adsp-l1pcfg"; + reg = <0x1fe80088 0x4>; + }; + lsbpm: lsbpm@71d80 { compatible = "intel,adsp-lsbpm"; reg = <0x71d80 0x0008>; diff --git a/dts/xtensa/intel/intel_adsp_ace30_ptl.dtsi b/dts/xtensa/intel/intel_adsp_ace30_ptl.dtsi index 35825e6ea6a71..5923d385291f7 100644 --- a/dts/xtensa/intel/intel_adsp_ace30_ptl.dtsi +++ b/dts/xtensa/intel/intel_adsp_ace30_ptl.dtsi @@ -124,6 +124,21 @@ }; soc { + l1ccap: l1ccap@3fe80080 { + compatible = "intel,adsp-l1ccap"; + reg = <0x3fe80080 0x4>; + }; + + l1ccfg: l1ccfg@3fe80084 { + compatible = "intel,adsp-l1ccfg"; + reg = <0x3fe80084 0x4>; + }; + + l1pcfg: l1pcfg@3fe80088 { + compatible = "intel,adsp-l1pcfg"; + reg = <0x3fe80088 0x4>; + }; + lsbpm: lsbpm@71d80 { compatible = "intel,adsp-lsbpm"; reg = <0x71d80 0x0008>; diff --git a/soc/intel/intel_adsp/ace/include/ace15_mtpm/adsp_memory.h b/soc/intel/intel_adsp/ace/include/ace15_mtpm/adsp_memory.h deleted file mode 100644 index e0a7175aad0ce..0000000000000 --- a/soc/intel/intel_adsp/ace/include/ace15_mtpm/adsp_memory.h +++ /dev/null @@ -1,177 +0,0 @@ -/* - * Copyright (c) 2022 Intel Corporation - * SPDX-License-Identifier: Apache-2.0 - */ - -#ifndef ZEPHYR_SOC_INTEL_ADSP_MEMORY_H_ -#define ZEPHYR_SOC_INTEL_ADSP_MEMORY_H_ - - -#include -#include -#include -#include - -#define L2_SRAM_BASE (DT_REG_ADDR(DT_NODELABEL(sram0))) -#define L2_SRAM_SIZE (DT_REG_SIZE(DT_NODELABEL(sram0))) - -#define L2_VIRTUAL_SRAM_BASE (DT_REG_ADDR(DT_NODELABEL(sram0virtual))) -#define L2_VIRTUAL_SRAM_SIZE (DT_REG_SIZE(DT_NODELABEL(sram0virtual))) - -#define LP_SRAM_BASE (DT_REG_ADDR(DT_NODELABEL(sram1))) -#define LP_SRAM_SIZE (DT_REG_SIZE(DT_NODELABEL(sram1))) - -#define ROM_JUMP_ADDR (LP_SRAM_BASE + 0x10) - -/* Linker-usable RAM region */ -#define RAM_BASE (L2_SRAM_BASE + CONFIG_HP_SRAM_RESERVE + VECTOR_TBL_SIZE) -#define RAM_SIZE (L2_SRAM_SIZE - CONFIG_HP_SRAM_RESERVE - VECTOR_TBL_SIZE) - - -/* L3 region (IMR), located in host memory */ - -#define L3_MEM_BASE_ADDR (DT_REG_ADDR(DT_NODELABEL(imr1))) -#define L3_MEM_SIZE (DT_REG_SIZE(DT_NODELABEL(imr1))) -#define L3_MEM_PAGE_SIZE (DT_PROP(DT_NODELABEL(imr1), block_size)) - -/* The rimage tool produces two blob addresses we need to find: one is - * our bootloader code block which starts at its entry point, the - * other is the "manifest" containing the HP-SRAM data to unpack, - * which appears 24k earlier in the DMA'd file, and thus in IMR - * memory. There's no ability to change this offset, it's a magic - * number from rimage we simply need to honor. - */ -#define IMR_BOOT_LDR_MANIFEST_OFFSET 0x42000 -#define IMR_BOOT_LDR_MANIFEST_SIZE 0x6000 -#define IMR_BOOT_LDR_MANIFEST_BASE (L3_MEM_BASE_ADDR + IMR_BOOT_LDR_MANIFEST_OFFSET) - -#define IMR_BOOT_LDR_TEXT_ENTRY_SIZE 0x180 -#define IMR_BOOT_LDR_TEXT_ENTRY_BASE (IMR_BOOT_LDR_MANIFEST_BASE + IMR_BOOT_LDR_MANIFEST_SIZE) - -#define IMR_BOOT_LDR_LIT_SIZE 0x40 -#define IMR_BOOT_LDR_LIT_BASE (IMR_BOOT_LDR_TEXT_ENTRY_BASE + \ - IMR_BOOT_LDR_TEXT_ENTRY_SIZE) - -#define IMR_BOOT_LDR_TEXT_SIZE 0x1C00 -#define IMR_BOOT_LDR_TEXT_BASE (IMR_BOOT_LDR_LIT_BASE + IMR_BOOT_LDR_LIT_SIZE) - -#define IMR_BOOT_LDR_DATA_OFFSET 0x49000 -#define IMR_BOOT_LDR_DATA_BASE (L3_MEM_BASE_ADDR + IMR_BOOT_LDR_DATA_OFFSET) -#define IMR_BOOT_LDR_DATA_SIZE 0xA8000 - -#define IMR_BOOT_LDR_BSS_OFFSET 0x110000 -#define IMR_BOOT_LDR_BSS_BASE (L3_MEM_BASE_ADDR + IMR_BOOT_LDR_BSS_OFFSET) -#define IMR_BOOT_LDR_BSS_SIZE 0x10000 - -/* stack to be used at boot, when RAM is not yet powered up */ -#define IMR_BOOT_LDR_STACK_BASE (IMR_BOOT_LDR_BSS_BASE + IMR_BOOT_LDR_BSS_SIZE) -#define IMR_BOOT_LDR_STACK_SIZE 0x1000 - -/* position of L3 heap, size of L3 heap - till end of the L3 memory */ -#define IMR_L3_HEAP_BASE (IMR_BOOT_LDR_STACK_BASE + IMR_BOOT_LDR_STACK_SIZE) -#define IMR_L3_HEAP_SIZE (L3_MEM_SIZE - \ - (IMR_L3_HEAP_BASE - L3_MEM_BASE_ADDR)) - -#define ADSP_L1_CACHE_PREFCTL_VALUE 0x1038 - -/* L1 init */ -#define ADSP_L1CC_ADDR (0x1FE80080) -#define ADSP_CxL1CCAP_ADDR (ADSP_L1CC_ADDR + 0x0000) -#define ADSP_CxL1CCFG_ADDR (ADSP_L1CC_ADDR + 0x0004) -#define ADSP_CxL1PCFG_ADDR (ADSP_L1CC_ADDR + 0x0008) - -#if (!defined(_ASMLANGUAGE) && !defined(__ASSEMBLER__)) - -#define ADSP_CxL1CCAP_REG (*(volatile uint32_t *)(ADSP_CxL1CCAP_ADDR)) -#define ADSP_CxL1CCFG_REG (*(volatile uint32_t *)(ADSP_CxL1CCFG_ADDR)) -#define ADSP_CxL1PCFG_REG (*(volatile uint32_t *)(ADSP_CxL1PCFG_ADDR)) - -#endif /* (!defined(_ASMLANGUAGE) && !defined(__ASSEMBLER__)) */ - -/* The number of set associative cache way supported on L1 Data Cache */ -#define ADSP_CxL1CCAP_DCMWC ((ADSP_CxL1CCAP_REG >> 16) & 7) -/* The number of set associative cache way supported on L1 Instruction Cache */ -#define ADSP_CxL1CCAP_ICMWC ((ADSP_CxL1CCAP_REG >> 20) & 7) - -#ifndef _LINKER -/* L2 Local Memory Management */ - -/* These registers are for the L2 memory control and status. */ -#define DFL2MM_REG 0x71d00 - -struct ace_l2mm { - uint32_t l2mcap; - uint32_t l2mpat; - uint32_t l2mecap; - uint32_t l2mecs; - uint32_t l2hsbpmptr; - uint32_t l2usbpmptr; - uint32_t l2usbmrpptr; - uint32_t l2ucmrpptr; - uint32_t l2ucmrpdptr; -}; - -#define ACE_L2MM ((volatile struct ace_l2mm *)DFL2MM_REG) - -/* DfL2MCAP */ -struct ace_l2mcap { - uint32_t l2hss : 8; - uint32_t l2uss : 4; - uint32_t l2hsbs : 4; - uint32_t l2hs2s : 8; - uint32_t l2usbs : 5; - uint32_t l2se : 1; - uint32_t el2se : 1; - uint32_t rsvd32 : 1; -}; - -#define ACE_L2MCAP ((volatile struct ace_l2mcap *)DFL2MM_REG) - -static ALWAYS_INLINE uint32_t ace_hpsram_get_bank_count(void) -{ - return ACE_L2MCAP->l2hss; -} - -static ALWAYS_INLINE uint32_t ace_lpsram_get_bank_count(void) -{ - return ACE_L2MCAP->l2uss; -} - -struct ace_hpsram_regs { - /** @brief power gating control */ - uint8_t HSxPGCTL; - /** @brief retention mode control */ - uint8_t HSxRMCTL; - uint8_t reserved[2]; - /** @brief power gating status */ - uint8_t HSxPGISTS; - uint8_t reserved1[3]; -}; - -struct ace_lpsram_regs { - /** @brief power gating control */ - uint8_t USxPGCTL; - /** @brief retention mode control */ - uint8_t USxRMCTL; - uint8_t reserved[2]; - /** @brief power gating status */ - uint8_t USxPGISTS; - uint8_t reserved1[3]; -}; -#endif - -/* These registers are for the L2 HP SRAM bank power management control and status.*/ -#define L2_HSBPM_BASE (DT_REG_ADDR(DT_NODELABEL(hsbpm))) -#define L2_HSBPM_SIZE (DT_REG_SIZE(DT_NODELABEL(hsbpm))) - -#define HPSRAM_REGS(block_idx) ((volatile struct ace_hpsram_regs *const) \ - (L2_HSBPM_BASE + L2_HSBPM_SIZE * (block_idx))) - -/* These registers are for the L2 LP SRAM bank power management control and status.*/ -#define L2_LSBPM_BASE (DT_REG_ADDR(DT_NODELABEL(lsbpm))) -#define L2_LSBPM_SIZE (DT_REG_SIZE(DT_NODELABEL(lsbpm))) - -#define LPSRAM_REGS(block_idx) ((volatile struct ace_lpsram_regs *const) \ - (L2_LSBPM_BASE + L2_LSBPM_SIZE * (block_idx))) - -#endif /* ZEPHYR_SOC_INTEL_ADSP_MEMORY_H_ */ diff --git a/soc/intel/intel_adsp/ace/include/ace20_lnl/adsp_memory.h b/soc/intel/intel_adsp/ace/include/ace20_lnl/adsp_memory.h deleted file mode 100644 index d8d23f2cefcdc..0000000000000 --- a/soc/intel/intel_adsp/ace/include/ace20_lnl/adsp_memory.h +++ /dev/null @@ -1,175 +0,0 @@ -/* - * Copyright (c) 2022 Intel Corporation - * SPDX-License-Identifier: Apache-2.0 - */ - -#ifndef ZEPHYR_SOC_INTEL_ADSP_MEMORY_H_ -#define ZEPHYR_SOC_INTEL_ADSP_MEMORY_H_ - - -#include -#include -#include -#include - -#define L2_SRAM_BASE (DT_REG_ADDR(DT_NODELABEL(sram0))) -#define L2_SRAM_SIZE (DT_REG_SIZE(DT_NODELABEL(sram0))) - -#define L2_VIRTUAL_SRAM_BASE (DT_REG_ADDR(DT_NODELABEL(sram0virtual))) -#define L2_VIRTUAL_SRAM_SIZE (DT_REG_SIZE(DT_NODELABEL(sram0virtual))) - -#define LP_SRAM_BASE (DT_REG_ADDR(DT_NODELABEL(sram1))) -#define LP_SRAM_SIZE (DT_REG_SIZE(DT_NODELABEL(sram1))) - -#define ROM_JUMP_ADDR (LP_SRAM_BASE + 0x10) - -/* Linker-usable RAM region */ -#define RAM_BASE (L2_SRAM_BASE + CONFIG_HP_SRAM_RESERVE + VECTOR_TBL_SIZE) -#define RAM_SIZE (L2_SRAM_SIZE - CONFIG_HP_SRAM_RESERVE - VECTOR_TBL_SIZE) - -/* L3 region (IMR), located in host memory */ -#define L3_MEM_BASE_ADDR (DT_REG_ADDR(DT_NODELABEL(imr1))) -#define L3_MEM_SIZE (DT_REG_SIZE(DT_NODELABEL(imr1))) -#define L3_MEM_PAGE_SIZE (DT_PROP(DT_NODELABEL(imr1), block_size)) - -/* The rimage tool produces two blob addresses we need to find: one is - * our bootloader code block which starts at its entry point, the - * other is the "manifest" containing the HP-SRAM data to unpack, - * which appears 24k earlier in the DMA'd file, and thus in IMR - * memory. There's no ability to change this offset, it's a magic - * number from rimage we simply need to honor. - */ -#define IMR_BOOT_LDR_MANIFEST_OFFSET 0x42000 -#define IMR_BOOT_LDR_MANIFEST_SIZE 0x6000 -#define IMR_BOOT_LDR_MANIFEST_BASE (L3_MEM_BASE_ADDR + IMR_BOOT_LDR_MANIFEST_OFFSET) - -#define IMR_BOOT_LDR_TEXT_ENTRY_SIZE 0x180 -#define IMR_BOOT_LDR_TEXT_ENTRY_BASE (IMR_BOOT_LDR_MANIFEST_BASE + IMR_BOOT_LDR_MANIFEST_SIZE) - -#define IMR_BOOT_LDR_LIT_SIZE 0x40 -#define IMR_BOOT_LDR_LIT_BASE (IMR_BOOT_LDR_TEXT_ENTRY_BASE + \ - IMR_BOOT_LDR_TEXT_ENTRY_SIZE) - -#define IMR_BOOT_LDR_TEXT_SIZE 0x1C00 -#define IMR_BOOT_LDR_TEXT_BASE (IMR_BOOT_LDR_LIT_BASE + IMR_BOOT_LDR_LIT_SIZE) - -#define IMR_BOOT_LDR_DATA_OFFSET 0x49000 -#define IMR_BOOT_LDR_DATA_BASE (L3_MEM_BASE_ADDR + IMR_BOOT_LDR_DATA_OFFSET) -#define IMR_BOOT_LDR_DATA_SIZE 0xA8000 - -#define IMR_BOOT_LDR_BSS_OFFSET 0x110000 -#define IMR_BOOT_LDR_BSS_BASE (L3_MEM_BASE_ADDR + IMR_BOOT_LDR_BSS_OFFSET) -#define IMR_BOOT_LDR_BSS_SIZE 0x10000 - -/* stack to be used at boot, when RAM is not yet powered up */ -#define IMR_BOOT_LDR_STACK_BASE (IMR_BOOT_LDR_BSS_BASE + IMR_BOOT_LDR_BSS_SIZE) -#define IMR_BOOT_LDR_STACK_SIZE 0x1000 - -/* position of L3 heap, size of L3 heap - till end of the L3 memory */ -#define IMR_L3_HEAP_BASE (IMR_BOOT_LDR_STACK_BASE + IMR_BOOT_LDR_STACK_SIZE) -#define IMR_L3_HEAP_SIZE (L3_MEM_SIZE - \ - (IMR_L3_HEAP_BASE - L3_MEM_BASE_ADDR)) - -#define ADSP_L1_CACHE_PREFCTL_VALUE 0x1038 - -/* L1 init */ -#define ADSP_L1CC_ADDR (0x1FE80080) -#define ADSP_CxL1CCAP_ADDR (ADSP_L1CC_ADDR + 0x0000) -#define ADSP_CxL1CCFG_ADDR (ADSP_L1CC_ADDR + 0x0004) -#define ADSP_CxL1PCFG_ADDR (ADSP_L1CC_ADDR + 0x0008) - -#if (!defined(_ASMLANGUAGE) && !defined(__ASSEMBLER__)) - -#define ADSP_CxL1CCAP_REG (*(volatile uint32_t *)(ADSP_CxL1CCAP_ADDR)) -#define ADSP_CxL1CCFG_REG (*(volatile uint32_t *)(ADSP_CxL1CCFG_ADDR)) -#define ADSP_CxL1PCFG_REG (*(volatile uint32_t *)(ADSP_CxL1PCFG_ADDR)) - -#endif /* (!defined(_ASMLANGUAGE) && !defined(__ASSEMBLER__)) */ - -/* The number of set associative cache way supported on L1 Data Cache */ -#define ADSP_CxL1CCAP_DCMWC ((ADSP_CxL1CCAP_REG >> 16) & 7) -/* The number of set associative cache way supported on L1 Instruction Cache */ -#define ADSP_CxL1CCAP_ICMWC ((ADSP_CxL1CCAP_REG >> 20) & 7) - -#ifndef _LINKER -/* L2 Local Memory Management */ - -/* These registers are for the L2 memory control and status. */ -#define DFL2MM_REG 0x71d00 - -struct ace_l2mm { - uint32_t l2mcap; - uint32_t l2mpat; - uint32_t l2mecap; - uint32_t l2mecs; - uint32_t l2hsbpmptr; - uint32_t l2usbpmptr; - uint32_t l2usbmrpptr; - uint32_t l2ucmrpptr; - uint32_t l2ucmrpdptr; -}; - -#define ACE_L2MM ((volatile struct ace_l2mm *)DFL2MM_REG) - -/* DfL2MCAP */ -struct ace_l2mcap { - uint32_t l2hss : 8; - uint32_t l2uss : 4; - uint32_t l2hsbs : 4; - uint32_t l2hs2s : 8; - uint32_t l2usbs : 5; - uint32_t l2se : 1; - uint32_t el2se : 1; - uint32_t rsvd32 : 1; -}; - -#define ACE_L2MCAP ((volatile struct ace_l2mcap *)DFL2MM_REG) - -static ALWAYS_INLINE uint32_t ace_hpsram_get_bank_count(void) -{ - return ACE_L2MCAP->l2hss; -} - -static ALWAYS_INLINE uint32_t ace_lpsram_get_bank_count(void) -{ - return ACE_L2MCAP->l2uss; -} - -struct ace_hpsram_regs { - /** @brief power gating control */ - uint8_t HSxPGCTL; - /** @brief retention mode control */ - uint8_t HSxRMCTL; - uint8_t reserved[2]; - /** @brief power gating status */ - uint8_t HSxPGISTS; - uint8_t reserved1[3]; -}; - -struct ace_lpsram_regs { - /** @brief power gating control */ - uint8_t USxPGCTL; - /** @brief retention mode control */ - uint8_t USxRMCTL; - uint8_t reserved[2]; - /** @brief power gating status */ - uint8_t USxPGISTS; - uint8_t reserved1[3]; -}; -#endif - -/* These registers are for the L2 HP SRAM bank power management control and status.*/ -#define L2_HSBPM_BASE (DT_REG_ADDR(DT_NODELABEL(hsbpm))) -#define L2_HSBPM_SIZE (DT_REG_SIZE(DT_NODELABEL(hsbpm))) - -#define HPSRAM_REGS(block_idx) ((volatile struct ace_hpsram_regs *const) \ - (L2_HSBPM_BASE + L2_HSBPM_SIZE * (block_idx))) - -/* These registers are for the L2 LP SRAM bank power management control and status.*/ -#define L2_LSBPM_BASE (DT_REG_ADDR(DT_NODELABEL(lsbpm))) -#define L2_LSBPM_SIZE (DT_REG_SIZE(DT_NODELABEL(lsbpm))) - -#define LPSRAM_REGS(block_idx) ((volatile struct ace_lpsram_regs *const) \ - (L2_LSBPM_BASE + L2_LSBPM_SIZE * (block_idx))) - -#endif /* ZEPHYR_SOC_INTEL_ADSP_MEMORY_H_ */ diff --git a/soc/intel/intel_adsp/ace/include/ace30_ptl/adsp_memory.h b/soc/intel/intel_adsp/ace/include/adsp_memory.h similarity index 94% rename from soc/intel/intel_adsp/ace/include/ace30_ptl/adsp_memory.h rename to soc/intel/intel_adsp/ace/include/adsp_memory.h index 1596cb489d350..3cdf0a6a6e8ac 100644 --- a/soc/intel/intel_adsp/ace/include/ace30_ptl/adsp_memory.h +++ b/soc/intel/intel_adsp/ace/include/adsp_memory.h @@ -75,10 +75,10 @@ #define ADSP_L1_CACHE_PREFCTL_VALUE 0x1038 /* L1 init */ -#define ADSP_L1CC_ADDR (0x3FE80080) -#define ADSP_CxL1CCAP_ADDR (ADSP_L1CC_ADDR + 0x0000) -#define ADSP_CxL1CCFG_ADDR (ADSP_L1CC_ADDR + 0x0004) -#define ADSP_CxL1PCFG_ADDR (ADSP_L1CC_ADDR + 0x0008) +#define ADSP_L1CC_ADDR (DT_REG_ADDR(DT_NODELABEL(l1ccap))) +#define ADSP_CxL1CCAP_ADDR (DT_REG_ADDR(DT_NODELABEL(l1ccap))) +#define ADSP_CxL1CCFG_ADDR (DT_REG_ADDR(DT_NODELABEL(l1ccfg))) +#define ADSP_CxL1PCFG_ADDR (DT_REG_ADDR(DT_NODELABEL(l1pcfg))) #if (!defined(_ASMLANGUAGE) && !defined(__ASSEMBLER__)) From 8100871856ff7394f9004457ade321d7fc3bf240 Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Tue, 4 Jun 2024 22:38:49 -0700 Subject: [PATCH 1979/2849] soc: intel_adsp: Avoid duplicate adsp_memory_regions This header is the same for all ACE platforms. Move it a common folder. Signed-off-by: Flavio Ceolin --- .../include/ace15_mtpm/adsp_memory_regions.h | 27 ------------------- .../include/ace20_lnl/adsp_memory_regions.h | 27 ------------------- .../{ace30_ptl => }/adsp_memory_regions.h | 0 3 files changed, 54 deletions(-) delete mode 100644 soc/intel/intel_adsp/ace/include/ace15_mtpm/adsp_memory_regions.h delete mode 100644 soc/intel/intel_adsp/ace/include/ace20_lnl/adsp_memory_regions.h rename soc/intel/intel_adsp/ace/include/{ace30_ptl => }/adsp_memory_regions.h (100%) diff --git a/soc/intel/intel_adsp/ace/include/ace15_mtpm/adsp_memory_regions.h b/soc/intel/intel_adsp/ace/include/ace15_mtpm/adsp_memory_regions.h deleted file mode 100644 index e235014f76a6a..0000000000000 --- a/soc/intel/intel_adsp/ace/include/ace15_mtpm/adsp_memory_regions.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (c) 2022 Intel Corporation - * SPDX-License-Identifier: Apache-2.0 - */ - -#ifndef ZEPHYR_SOC_INTEL_ADSP_MEMORY_REGIONS_H_ -#define ZEPHYR_SOC_INTEL_ADSP_MEMORY_REGIONS_H_ - -/* Define amount of regions other than core heaps that virtual memory will be split to - * currently includes shared heap and oma region and one regions set to 0 as for table - * iterator end value. - */ -#define VIRTUAL_REGION_COUNT 3 - -#define CORE_HEAP_SIZE 0x100000 -#define SHARED_HEAP_SIZE 0x100000 -#define OPPORTUNISTIC_REGION_SIZE 0x100000 - -/* size of TLB table */ -#define TLB_SIZE DT_REG_SIZE_BY_IDX(DT_INST(0, intel_adsp_mtl_tlb), 0) - -/* Attribiutes for memory regions */ -#define MEM_REG_ATTR_CORE_HEAP 1U -#define MEM_REG_ATTR_SHARED_HEAP 2U -#define MEM_REG_ATTR_OPPORTUNISTIC_MEMORY 4U - -#endif /* ZEPHYR_SOC_INTEL_ADSP_MEMORY_REGIONS_H_ */ diff --git a/soc/intel/intel_adsp/ace/include/ace20_lnl/adsp_memory_regions.h b/soc/intel/intel_adsp/ace/include/ace20_lnl/adsp_memory_regions.h deleted file mode 100644 index e235014f76a6a..0000000000000 --- a/soc/intel/intel_adsp/ace/include/ace20_lnl/adsp_memory_regions.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (c) 2022 Intel Corporation - * SPDX-License-Identifier: Apache-2.0 - */ - -#ifndef ZEPHYR_SOC_INTEL_ADSP_MEMORY_REGIONS_H_ -#define ZEPHYR_SOC_INTEL_ADSP_MEMORY_REGIONS_H_ - -/* Define amount of regions other than core heaps that virtual memory will be split to - * currently includes shared heap and oma region and one regions set to 0 as for table - * iterator end value. - */ -#define VIRTUAL_REGION_COUNT 3 - -#define CORE_HEAP_SIZE 0x100000 -#define SHARED_HEAP_SIZE 0x100000 -#define OPPORTUNISTIC_REGION_SIZE 0x100000 - -/* size of TLB table */ -#define TLB_SIZE DT_REG_SIZE_BY_IDX(DT_INST(0, intel_adsp_mtl_tlb), 0) - -/* Attribiutes for memory regions */ -#define MEM_REG_ATTR_CORE_HEAP 1U -#define MEM_REG_ATTR_SHARED_HEAP 2U -#define MEM_REG_ATTR_OPPORTUNISTIC_MEMORY 4U - -#endif /* ZEPHYR_SOC_INTEL_ADSP_MEMORY_REGIONS_H_ */ diff --git a/soc/intel/intel_adsp/ace/include/ace30_ptl/adsp_memory_regions.h b/soc/intel/intel_adsp/ace/include/adsp_memory_regions.h similarity index 100% rename from soc/intel/intel_adsp/ace/include/ace30_ptl/adsp_memory_regions.h rename to soc/intel/intel_adsp/ace/include/adsp_memory_regions.h From 87ef371fec414b5def46e6e0a11923a783788a47 Mon Sep 17 00:00:00 2001 From: cyliang tw Date: Wed, 5 Jun 2024 11:29:55 +0800 Subject: [PATCH 1980/2849] dts: arm: nuvoton: add wdt node of numaker m2l31x Update m2l31x.dtsi, to add wdt node for wdt driver support. Signed-off-by: cyliang tw --- dts/arm/nuvoton/m2l31x.dtsi | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/dts/arm/nuvoton/m2l31x.dtsi b/dts/arm/nuvoton/m2l31x.dtsi index 2b4b57c987687..b3cbd6c997b5d 100644 --- a/dts/arm/nuvoton/m2l31x.dtsi +++ b/dts/arm/nuvoton/m2l31x.dtsi @@ -386,6 +386,14 @@ bosch,mram-cfg = <0x0 12 10 3 3 3 3 3>; status = "disabled"; }; + + wwdt: watchdog@40096000 { + compatible = "nuvoton,numaker-wwdt"; + reg = <0x40096000 0x10>; + interrupts = <9 0>; + clocks = <&pcc NUMAKER_WWDT_MODULE NUMAKER_CLK_CLKSEL1_WWDTSEL_LIRC 0>; + status = "disabled"; + }; }; }; From 6293daa43870147fa33bb264e43e7966d5c4fef6 Mon Sep 17 00:00:00 2001 From: cyliang tw Date: Wed, 5 Jun 2024 11:35:25 +0800 Subject: [PATCH 1981/2849] tests: drivers: watchdog: wdt_basic_api: support numaker_m2l31ki Add support for Nuvoton numaker board numaker_m2l31ki. Signed-off-by: cyliang tw --- .../watchdog/wdt_basic_api/boards/numaker_m2l31ki.overlay | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 tests/drivers/watchdog/wdt_basic_api/boards/numaker_m2l31ki.overlay diff --git a/tests/drivers/watchdog/wdt_basic_api/boards/numaker_m2l31ki.overlay b/tests/drivers/watchdog/wdt_basic_api/boards/numaker_m2l31ki.overlay new file mode 100644 index 0000000000000..78f321a84adaa --- /dev/null +++ b/tests/drivers/watchdog/wdt_basic_api/boards/numaker_m2l31ki.overlay @@ -0,0 +1,5 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +&wwdt { + status = "okay"; +}; From 06177833d841a91fe9aa188c75243c43559eba01 Mon Sep 17 00:00:00 2001 From: Pisit Sawangvonganan Date: Thu, 30 May 2024 16:32:42 +0700 Subject: [PATCH 1982/2849] fs: fcb: correct `FCB_MAX_LEN` boundary condition Correct the boundary condition in `fcb_put_len` function to properly include `FCB_MAX_LEN` and change the #define to address the potential flaw where `CHAR_MAX` might be treated as unsigned by the compiler flag `-funsigned-char`, which would yield `FCB_MAX_LEN` to 0x7fff instead of 0x3fff. Fixes #73868 Signed-off-by: Pisit Sawangvonganan --- include/zephyr/fs/fcb.h | 2 +- subsys/fs/fcb/fcb.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/zephyr/fs/fcb.h b/include/zephyr/fs/fcb.h index 959a60b328646..63d68ef0898bf 100644 --- a/include/zephyr/fs/fcb.h +++ b/include/zephyr/fs/fcb.h @@ -37,7 +37,7 @@ extern "C" { * @{ */ -#define FCB_MAX_LEN (CHAR_MAX | CHAR_MAX << 7) /**< Max length of element */ +#define FCB_MAX_LEN (0x3fffu) /**< Max length of element (16,383) */ /** * @brief FCB entry info structure. This data structure describes the element diff --git a/subsys/fs/fcb/fcb.c b/subsys/fs/fcb/fcb.c index 44358a8dbeac3..502156da83efc 100644 --- a/subsys/fs/fcb/fcb.c +++ b/subsys/fs/fcb/fcb.c @@ -223,7 +223,7 @@ fcb_put_len(const struct fcb *fcb, uint8_t *buf, uint16_t len) if (len < 0x80) { buf[0] = len ^ ~fcb->f_erase_value; return 1; - } else if (len < FCB_MAX_LEN) { + } else if (len <= FCB_MAX_LEN) { buf[0] = (len | 0x80) ^ ~fcb->f_erase_value; buf[1] = (len >> 7) ^ ~fcb->f_erase_value; return 2; From aca97a0bef8b579a47966a5eb839c94b3bc9c809 Mon Sep 17 00:00:00 2001 From: Pisit Sawangvonganan Date: Thu, 30 May 2024 17:55:23 +0700 Subject: [PATCH 1983/2849] fs: fcb: refactor `fcb_get_len()` for improved readability Introduced temporary variables `buf0_xor` and `buf1_xor` to store XOR results and added an explicit cast to `uint16_t` for the `*len` variable. Signed-off-by: Pisit Sawangvonganan --- subsys/fs/fcb/fcb.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/subsys/fs/fcb/fcb.c b/subsys/fs/fcb/fcb.c index 502156da83efc..7154caa5f15e2 100644 --- a/subsys/fs/fcb/fcb.c +++ b/subsys/fs/fcb/fcb.c @@ -236,16 +236,21 @@ int fcb_get_len(const struct fcb *fcb, uint8_t *buf, uint16_t *len) { int rc; - if ((buf[0] ^ ~fcb->f_erase_value) & 0x80) { + uint8_t buf0_xor; + uint8_t buf1_xor; + + buf0_xor = buf[0] ^ ~fcb->f_erase_value; + if (buf0_xor & 0x80) { if ((buf[0] == fcb->f_erase_value) && (buf[1] == fcb->f_erase_value)) { return -ENOTSUP; } - *len = ((buf[0] ^ ~fcb->f_erase_value) & 0x7f) | - ((uint8_t)(buf[1] ^ ~fcb->f_erase_value) << 7); + + buf1_xor = buf[1] ^ ~fcb->f_erase_value; + *len = (uint16_t)((buf0_xor & 0x7f) | ((uint16_t)buf1_xor << 7)); rc = 2; } else { - *len = (uint8_t)(buf[0] ^ ~fcb->f_erase_value); + *len = (uint16_t)(buf0_xor); rc = 1; } return rc; From b7fbd91d9e9f47a477fb52029b12c382903d9092 Mon Sep 17 00:00:00 2001 From: Ioannis Damigos Date: Mon, 27 May 2024 13:00:49 +0300 Subject: [PATCH 1984/2849] soc/da1469x: Fix CONFIG_SYS_CLOCK_*_PER_SEC defines The following configuration options: SYS_CLOCK_HW_CYCLES_PER_SEC SYS_CLOCK_TICKS_PER_SEC should get their values according to lp_clock node's clock-src property. Signed-off-by: Ioannis Damigos --- soc/renesas/smartbond/da1469x/Kconfig.defconfig | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/soc/renesas/smartbond/da1469x/Kconfig.defconfig b/soc/renesas/smartbond/da1469x/Kconfig.defconfig index 418c4ea126ce6..4d9c062039ef3 100644 --- a/soc/renesas/smartbond/da1469x/Kconfig.defconfig +++ b/soc/renesas/smartbond/da1469x/Kconfig.defconfig @@ -12,12 +12,15 @@ config CORTEX_M_SYSTICK config NUM_IRQS default 40 +DT_LPCLK_PATH := $(dt_nodelabel_path,lp_clk) +DT_CLOCK_SRC_PATH := $(dt_node_ph_prop_path,$(DT_LPCLK_PATH),clock-src) + config SYS_CLOCK_HW_CYCLES_PER_SEC default $(dt_node_int_prop_int,/cpus/cpu@0,clock-frequency) if CORTEX_M_SYSTICK - default 32768 if SMARTBOND_TIMER + default $(dt_node_int_prop_int,$(DT_CLOCK_SRC_PATH),clock-frequency) if SMARTBOND_TIMER config SYS_CLOCK_TICKS_PER_SEC - default 32768 if SMARTBOND_TIMER + default $(dt_node_int_prop_int,$(DT_CLOCK_SRC_PATH),clock-frequency) if SMARTBOND_TIMER config SRAM_VECTOR_TABLE default y From 4873de287ac9216d16d255b41efce7c50ba4ca9b Mon Sep 17 00:00:00 2001 From: Anke Xiao Date: Fri, 24 May 2024 18:57:19 +0800 Subject: [PATCH 1985/2849] soc: nxp: kinetis: add mke17z9 soc support Updated the soc.yml and kconfig.soc to support mke17z9 Signed-off-by: Anke Xiao --- soc/nxp/kinetis/ke1xz/Kconfig.soc | 13 +++++++++++++ soc/nxp/kinetis/soc.yml | 1 + 2 files changed, 14 insertions(+) diff --git a/soc/nxp/kinetis/ke1xz/Kconfig.soc b/soc/nxp/kinetis/ke1xz/Kconfig.soc index 199d787758766..962db64482cf8 100644 --- a/soc/nxp/kinetis/ke1xz/Kconfig.soc +++ b/soc/nxp/kinetis/ke1xz/Kconfig.soc @@ -19,9 +19,14 @@ config SOC_MKE17Z7 bool select SOC_SERIES_KE1XZ +config SOC_MKE17Z9 + bool + select SOC_SERIES_KE1XZ + config SOC default "mke15z7" if SOC_MKE15Z7 default "mke17z7" if SOC_MKE17Z7 + default "mke17z9" if SOC_MKE17Z9 config SOC_PART_NUMBER_MKE15Z128VLL7 bool @@ -53,6 +58,12 @@ config SOC_PART_NUMBER_MKE17Z256VLH7 config SOC_PART_NUMBER_MKE17Z256VLL7 bool +config SOC_PART_NUMBER_MKE17Z512VLH9 + bool + +config SOC_PART_NUMBER_MKE17Z512VLL9 + bool + config SOC_PART_NUMBER default "MKE15Z128VLL7" if SOC_PART_NUMBER_MKE15Z128VLL7 default "MKE15Z128VLH7" if SOC_PART_NUMBER_MKE15Z128VLH7 @@ -64,3 +75,5 @@ config SOC_PART_NUMBER default "MKE17Z256VLF7" if SOC_PART_NUMBER_MKE17Z256VLF7 default "MKE17Z256VLH7" if SOC_PART_NUMBER_MKE17Z256VLH7 default "MKE17Z256VLL7" if SOC_PART_NUMBER_MKE17Z256VLL7 + default "MKE17Z512VLH9" if SOC_PART_NUMBER_MKE17Z512VLH9 + default "MKE17Z512VLL9" if SOC_PART_NUMBER_MKE17Z512VLL9 diff --git a/soc/nxp/kinetis/soc.yml b/soc/nxp/kinetis/soc.yml index 82b78b2577560..572e9c3b9d89a 100644 --- a/soc/nxp/kinetis/soc.yml +++ b/soc/nxp/kinetis/soc.yml @@ -33,3 +33,4 @@ family: socs: - name: mke15z7 - name: mke17z7 + - name: mke17z9 From 37e8c47650bf878d637e3e51eec0d24bfceebfa3 Mon Sep 17 00:00:00 2001 From: Anke Xiao Date: Fri, 24 May 2024 19:04:34 +0800 Subject: [PATCH 1986/2849] drivers: clock_control: add a macro for mke17z9 to wrap flexbus clock The flexbus clock-related macro is not defined in mke17z9 clock. Signed-off-by: Anke Xiao --- drivers/clock_control/clock_control_mcux_scg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clock_control/clock_control_mcux_scg.c b/drivers/clock_control/clock_control_mcux_scg.c index 0a88fc9066697..2898766e452cd 100644 --- a/drivers/clock_control/clock_control_mcux_scg.c +++ b/drivers/clock_control/clock_control_mcux_scg.c @@ -46,7 +46,7 @@ static int mcux_scg_get_rate(const struct device *dev, case KINETIS_SCG_BUS_CLK: clock_name = kCLOCK_BusClk; break; -#if !defined(CONFIG_SOC_MKE17Z7) +#if !(defined(CONFIG_SOC_MKE17Z7) || defined(CONFIG_SOC_MKE17Z9)) case KINETIS_SCG_FLEXBUS_CLK: clock_name = kCLOCK_FlexBusClk; break; From 2b2791e2edbe5ca95e73442fcf9c8a912f1fe13d Mon Sep 17 00:00:00 2001 From: Anke Xiao Date: Fri, 24 May 2024 19:01:50 +0800 Subject: [PATCH 1987/2849] boards: nxp: frdm_ke17z512: add new board support Added basic support for frdm_ke17z512 board Signed-off-by: Anke Xiao --- .../nxp/frdm_ke17z512/Kconfig.frdm_ke17z512 | 6 + boards/nxp/frdm_ke17z512/board.cmake | 11 + boards/nxp/frdm_ke17z512/board.yml | 5 + .../nxp/frdm_ke17z512/doc/frdm_ke17z512.webp | Bin 0 -> 13564 bytes boards/nxp/frdm_ke17z512/doc/index.rst | 198 ++++++++++++++++++ .../frdm_ke17z512/frdm_ke17z512-pinctrl.dtsi | 21 ++ boards/nxp/frdm_ke17z512/frdm_ke17z512.dts | 76 +++++++ boards/nxp/frdm_ke17z512/frdm_ke17z512.yaml | 20 ++ .../nxp/frdm_ke17z512/frdm_ke17z512_defconfig | 12 ++ 9 files changed, 349 insertions(+) create mode 100644 boards/nxp/frdm_ke17z512/Kconfig.frdm_ke17z512 create mode 100644 boards/nxp/frdm_ke17z512/board.cmake create mode 100644 boards/nxp/frdm_ke17z512/board.yml create mode 100644 boards/nxp/frdm_ke17z512/doc/frdm_ke17z512.webp create mode 100644 boards/nxp/frdm_ke17z512/doc/index.rst create mode 100644 boards/nxp/frdm_ke17z512/frdm_ke17z512-pinctrl.dtsi create mode 100644 boards/nxp/frdm_ke17z512/frdm_ke17z512.dts create mode 100644 boards/nxp/frdm_ke17z512/frdm_ke17z512.yaml create mode 100644 boards/nxp/frdm_ke17z512/frdm_ke17z512_defconfig diff --git a/boards/nxp/frdm_ke17z512/Kconfig.frdm_ke17z512 b/boards/nxp/frdm_ke17z512/Kconfig.frdm_ke17z512 new file mode 100644 index 0000000000000..0ac331398d2df --- /dev/null +++ b/boards/nxp/frdm_ke17z512/Kconfig.frdm_ke17z512 @@ -0,0 +1,6 @@ +# Copyright 2024 NXP +# SPDX-License-Identifier: Apache-2.0 + +config BOARD_FRDM_KE17Z512 + select SOC_MKE17Z9 + select SOC_PART_NUMBER_MKE17Z512VLL9 diff --git a/boards/nxp/frdm_ke17z512/board.cmake b/boards/nxp/frdm_ke17z512/board.cmake new file mode 100644 index 0000000000000..4c09a06e95ed4 --- /dev/null +++ b/boards/nxp/frdm_ke17z512/board.cmake @@ -0,0 +1,11 @@ +# +# Copyright 2024 NXP +# +# SPDX-License-Identifier: Apache-2.0 +# + +board_runner_args(linkserver "--device=MKE17Z512xxx9:FRDM-KE17Z512") +board_runner_args(jlink "--device=MKE17Z512xxx9" "--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_ke17z512/board.yml b/boards/nxp/frdm_ke17z512/board.yml new file mode 100644 index 0000000000000..46839e065b1dd --- /dev/null +++ b/boards/nxp/frdm_ke17z512/board.yml @@ -0,0 +1,5 @@ +board: + name: frdm_ke17z512 + vendor: nxp + socs: + - name: mke17z9 diff --git a/boards/nxp/frdm_ke17z512/doc/frdm_ke17z512.webp b/boards/nxp/frdm_ke17z512/doc/frdm_ke17z512.webp new file mode 100644 index 0000000000000000000000000000000000000000..d068f9257636a08c85546967e1997189e5fe1f19 GIT binary patch literal 13564 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 Cfr~f* literal 0 HcmV?d00001 diff --git a/boards/nxp/frdm_ke17z512/doc/index.rst b/boards/nxp/frdm_ke17z512/doc/index.rst new file mode 100644 index 0000000000000..d9dc4385a7980 --- /dev/null +++ b/boards/nxp/frdm_ke17z512/doc/index.rst @@ -0,0 +1,198 @@ +.. _frdm_ke17z512: + +NXP FRDM-KE17Z512 +################## + +Overview +******** + +The FRDM-KE17Z512 is a development board for NXP Kinetis KE1xZ 32-bit +MCU-based platforms. The onboard OpenSDAv2 serial and debug adapter, +running an open source bootloader, offers options for serial +communication, flash programming, and run-control debugging. + +.. figure:: frdm_ke17z512.webp + :align: center + :alt: FRDM-KE17Z512 + + FRDM-KE17Z512 (Credit: NXP) + +Hardware +******** + +- MKE17Z512VLL9 MCU (up to 96 MHz, 512 KB flash memory, 96 KB RAM, + and 100 Low profile Quad Flat Package (LQFP)) +- 3.3 V or 5 V MCU operation +- 6-axis FXOS8700CQ digital accelerometer and magnetometer +- RGB LED +- Two user push-buttons +- Thermistor +- Arduino compatible I/O pin header +- OpenSDA on-board debugger +- Two Touch Electrodes + +For more information about the KE1xZ SoC and the FRDM-KE17Z512 board, see +these NXP reference documents: + +- `KE1xZ Website`_ +- `KE1xZ Fact Sheet`_ +- `KE1xZ Reference Manual`_ +- `FRDM-KE17Z512 Website`_ +- `FRDM-KE17Z512 Quick Start Guide`_ +- `FRDM-KE17Z512 Reference Manual`_ + +Supported Features +================== + +The frdm_ke17z512 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: +``boards/nxp/frdm_ke17z512/frdm_ke17z512_defconfig``. + +Other hardware features are not currently supported by the port. + +System Clock +============ + +The KE17Z9 SoC is configured to run at 48 MHz using the FIRC. + +Serial Port +=========== + +The KE17Z9 SoC has three LPUARTs. UART2 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 `Segger J-Link OpenSDA V2.1 Firmware`_. +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 J10. + +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_ke17z512 + :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-xxxx-gxxxxxxxxxxxx *** + Hello World! frdm_ke17z512/mke17z9 + +Debugging +========= + +Here is an example for the :ref:`hello_world` application. + +.. zephyr-app-commands:: + :zephyr-app: samples/hello_world + :board: frdm_ke17z512 + :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 build v3.6.0-xxxx-gxxxxxxxxxxxx *** + Hello World! frdm_ke17z512/mke17z9 + +.. _FRDM-KE17Z512 Website: + https://www.nxp.com/design/design-center/development-boards-and-designs/general-purpose-mcus/frdm-development-board-for-96-mhz-ke17z-ke13z-ke12z-with-512-kb-flash-mcus:FRDM-KE17Z512 + +.. _FRDM-KE17Z512 Quick Start Guide: + https://www.nxp.com/docs/en/quick-reference-guide/FRDMKE17Z512QSG.pdf + +.. _FRDM-KE17Z512 Reference Manual: + https://www.nxp.com/docs/en/reference-manual/KE1XZP100M96SF0RM.pdf + +.. _KE1xZ 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 + +.. _KE1xZ Fact Sheet: + https://www.nxp.com/docs/en/fact-sheet/KE1xZMCUFAMFS.pdf + +.. _KE1xZ Reference Manual: + https://www.nxp.com/webapp/Download?colCode=KE1XZP100M72SF0RM + +.. _linkserver-debug-host-tools: + https://www.nxp.com/lgfiles/updates/mcuxpresso/LinkServer_1.5.30.exe + +.. _Segger J-Link OpenSDA V2.1 Firmware: + https://www.segger.com/downloads/jlink/OpenSDA_V2_1.bin + +.. _DAPLink Bootloader Update: + https://os.mbed.com/blog/entry/DAPLink-bootloader-update/ + +.. _jlink-debug-host-tools: + https://www.segger.com/downloads/jlink/JLink_Windows_V794_x86_64.exe diff --git a/boards/nxp/frdm_ke17z512/frdm_ke17z512-pinctrl.dtsi b/boards/nxp/frdm_ke17z512/frdm_ke17z512-pinctrl.dtsi new file mode 100644 index 0000000000000..cea7e351c9eab --- /dev/null +++ b/boards/nxp/frdm_ke17z512/frdm_ke17z512-pinctrl.dtsi @@ -0,0 +1,21 @@ +/* + * Copyright 2024 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + + +#include + +&pinctrl { + + /* Configures pin routing and optionally pin electrical features. */ + lpuart2_default: lpuart2_default { + group0 { + pinmux = , + ; + drive-strength = "low"; + slew-rate = "slow"; + }; + }; +}; diff --git a/boards/nxp/frdm_ke17z512/frdm_ke17z512.dts b/boards/nxp/frdm_ke17z512/frdm_ke17z512.dts new file mode 100644 index 0000000000000..f1f759b9e3132 --- /dev/null +++ b/boards/nxp/frdm_ke17z512/frdm_ke17z512.dts @@ -0,0 +1,76 @@ +/* + * Copyright 2024 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; + +#include +#include "frdm_ke17z512-pinctrl.dtsi" +#include + +/ { + model = "NXP Freedom KE17Z512 board"; + compatible = "nxp,ke17z512", "nxp,mke17z9", "nxp,ke1xz"; + + chosen { + zephyr,sram = &sram_u; + zephyr,flash = &flash0; + zephyr,console = &lpuart2; + zephyr,shell-uart = &lpuart2; + }; + + aliases { + led0 = &red_led; + led1 = &green_led; + led2 = &blue_led; + sw0 = &user_button_2; + sw1 = &user_button_3; + }; + + leds { + compatible = "gpio-leds"; + red_led: led_0 { + gpios = <&gpiod 10 GPIO_ACTIVE_LOW>; + label = "Red LED"; + }; + green_led: led_1 { + gpios = <&gpiod 5 GPIO_ACTIVE_LOW>; + label = "Green LED"; + }; + blue_led: led_2 { + gpios = <&gpiod 12 GPIO_ACTIVE_LOW>; + label = "Blue LED"; + }; + }; + + gpio_keys { + compatible = "gpio-keys"; + user_button_2: button_0 { + label = "User SW2"; + gpios = <&gpioe 14 GPIO_ACTIVE_LOW>; + zephyr,code = ; + }; + user_button_3: button_1 { + label = "User SW3"; + gpios = <&gpiod 3 GPIO_ACTIVE_LOW>; + zephyr,code = ; + }; + }; +}; + +&lpuart2 { + status = "okay"; + pinctrl-0 = <&lpuart2_default>; + pinctrl-names = "default"; + current-speed = <115200>; +}; + +&gpiod { + status = "okay"; +}; + +&gpioe { + status = "okay"; +}; diff --git a/boards/nxp/frdm_ke17z512/frdm_ke17z512.yaml b/boards/nxp/frdm_ke17z512/frdm_ke17z512.yaml new file mode 100644 index 0000000000000..4fb3e6f1ad355 --- /dev/null +++ b/boards/nxp/frdm_ke17z512/frdm_ke17z512.yaml @@ -0,0 +1,20 @@ +# +# Copyright 2024 NXP +# +# SPDX-License-Identifier: Apache-2.0 +# + +identifier: frdm_ke17z512 +name: NXP FRDM-KE17Z512 +type: mcu +arch: arm +ram: 64 +flash: 512 +toolchain: + - zephyr + - gnuarmemb + - xtools +supported: + - gpio + - uart +vendor: nxp diff --git a/boards/nxp/frdm_ke17z512/frdm_ke17z512_defconfig b/boards/nxp/frdm_ke17z512/frdm_ke17z512_defconfig new file mode 100644 index 0000000000000..d1237a34ce714 --- /dev/null +++ b/boards/nxp/frdm_ke17z512/frdm_ke17z512_defconfig @@ -0,0 +1,12 @@ +# +# Copyright 2024 NXP +# +# SPDX-License-Identifier: Apache-2.0 +# + +CONFIG_CONSOLE=y +CONFIG_UART_CONSOLE=y +CONFIG_SERIAL=y +CONFIG_GPIO=y +CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC=48000000 +CONFIG_PINCTRL=y From 495b90eadc1fa60c7a7fa3e17338f49c632d8e8f Mon Sep 17 00:00:00 2001 From: Anke Xiao Date: Fri, 24 May 2024 19:28:10 +0800 Subject: [PATCH 1988/2849] tests: drivers: gpio: gpio_basic_api: add overlay for ke17z512 The gpio_basic_api sample for gpio driver was tested for frdm_ke17z512 Signed-off-by: Anke Xiao --- .../gpio_basic_api/boards/frdm_ke17z512.overlay | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 tests/drivers/gpio/gpio_basic_api/boards/frdm_ke17z512.overlay diff --git a/tests/drivers/gpio/gpio_basic_api/boards/frdm_ke17z512.overlay b/tests/drivers/gpio/gpio_basic_api/boards/frdm_ke17z512.overlay new file mode 100644 index 0000000000000..ad957a4ae0964 --- /dev/null +++ b/tests/drivers/gpio/gpio_basic_api/boards/frdm_ke17z512.overlay @@ -0,0 +1,13 @@ +/* + * Copyright NXP 2024 + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + resources { + compatible = "test-gpio-basic-api"; + out-gpios = <&gpioe 0 0>; /* Arduino D13 */ + in-gpios = <&gpioe 1 0>; /* Arduino D12 */ + }; +}; From 92b56e2d3fa6a9991e9575b2c6488b6a3407429d Mon Sep 17 00:00:00 2001 From: Magdalena Pastula Date: Tue, 4 Jun 2024 10:13:06 +0200 Subject: [PATCH 1989/2849] manifest: update hal_nordic with nrfx_gpiote fix Update hal_nordic with fix in nrfx_gpiote. Signed-off-by: Magdalena Pastula --- west.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/west.yml b/west.yml index 238e3a6316406..fc117a3792e21 100644 --- a/west.yml +++ b/west.yml @@ -188,7 +188,7 @@ manifest: groups: - hal - name: hal_nordic - revision: f311735c1a16169ef228f1c50fefb4c8632ae69c + revision: ab5cb2e2faeb1edfad7a25286dcb513929ae55da path: modules/hal/nordic groups: - hal From fd236ee991e704d4bb560a8d691b2f8b4da07ba6 Mon Sep 17 00:00:00 2001 From: Alberto Escolar Piedras Date: Thu, 6 Jun 2024 11:19:11 +0200 Subject: [PATCH 1990/2849] manifest: Update nRF hw models to latest Update the HW models module to: 6c389b9b5fa0a079cd4502e69d375da4c0c289b7 Including the following: * 6c389b9 PPI (52): Connect CCM TASK_RATEOVERRIDE * 2056253 CCM: Change TASK RATEOVERRIDE warning to info 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 fc117a3792e21..4b9a98bcbb615 100644 --- a/west.yml +++ b/west.yml @@ -300,7 +300,7 @@ manifest: groups: - tools - name: nrf_hw_models - revision: 4447a22aea5e791c9bd18e7d71cc092623ddd2bb + revision: 6c389b9b5fa0a079cd4502e69d375da4c0c289b7 path: modules/bsim_hw_models/nrf_hw_models - name: open-amp revision: da78aea63159771956fe0c9263f2e6985b66e9d5 From 0e7c25fee462a7249a4303471617e5416120d198 Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Fri, 7 Jun 2024 11:59:34 +0200 Subject: [PATCH 1991/2849] drivers: flash: flash_shell: Fix unused variables Fix unused variable compilation warnings. Signed-off-by: Vinayak Kariappa Chettimada --- drivers/flash/flash_shell.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/flash/flash_shell.c b/drivers/flash/flash_shell.c index c3825d49ba39e..a0d6a19a2332a 100644 --- a/drivers/flash/flash_shell.c +++ b/drivers/flash/flash_shell.c @@ -73,12 +73,13 @@ static int parse_helper(const struct shell *sh, size_t *argc, static int cmd_erase(const struct shell *sh, size_t argc, char *argv[]) { + int result = -ENOTSUP; + +#if defined(CONFIG_FLASH_HAS_EXPLICIT_ERASE) const struct device *flash_dev; uint32_t page_addr; - int result = -ENOTSUP; uint32_t size; -#if defined(CONFIG_FLASH_HAS_EXPLICIT_ERASE) result = parse_helper(sh, &argc, &argv, &flash_dev, &page_addr); if (result) { return result; From 4c2938a29590107e1838178b2d4000922379c460 Mon Sep 17 00:00:00 2001 From: frei tycho Date: Wed, 5 Jun 2024 09:44:36 +0000 Subject: [PATCH 1992/2849] kernel: added missing parenthesis - added missing parenthesis around macro argument expansion Signed-off-by: frei tycho --- include/zephyr/spinlock.h | 2 +- kernel/include/mmu.h | 10 +++++----- kernel/mmu.c | 8 ++++---- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/include/zephyr/spinlock.h b/include/zephyr/spinlock.h index 51c160b0f8599..7b0d3a7b61afc 100644 --- a/include/zephyr/spinlock.h +++ b/include/zephyr/spinlock.h @@ -437,7 +437,7 @@ static ALWAYS_INLINE void z_spin_onexit(__maybe_unused k_spinlock_key_t *k) */ #define K_SPINLOCK(lck) \ for (k_spinlock_key_t __i K_SPINLOCK_ONEXIT = {}, __key = k_spin_lock(lck); !__i.key; \ - k_spin_unlock(lck, __key), __i.key = 1) + k_spin_unlock((lck), __key), __i.key = 1) /** @} */ diff --git a/kernel/include/mmu.h b/kernel/include/mmu.h index ddfbdd2e16e1d..f39656b5453d3 100644 --- a/kernel/include/mmu.h +++ b/kernel/include/mmu.h @@ -47,8 +47,8 @@ * been remapped or paged out. Never use this unless you know exactly what you * are doing. */ -#define Z_BOOT_VIRT_TO_PHYS(virt) ((uintptr_t)(((uint8_t *)virt) - Z_VM_OFFSET)) -#define Z_BOOT_PHYS_TO_VIRT(phys) ((uint8_t *)(((uintptr_t)phys) + Z_VM_OFFSET)) +#define Z_BOOT_VIRT_TO_PHYS(virt) ((uintptr_t)(((uint8_t *)(virt)) - Z_VM_OFFSET)) +#define Z_BOOT_PHYS_TO_VIRT(phys) ((uint8_t *)(((uintptr_t)(phys)) + Z_VM_OFFSET)) #ifdef CONFIG_ARCH_MAPS_ALL_RAM #define Z_FREE_VM_START Z_BOOT_PHYS_TO_VIRT(Z_PHYS_RAM_END) @@ -253,9 +253,9 @@ void z_page_frames_dump(void); /* Convenience macro for iterating over all page frames */ #define Z_PAGE_FRAME_FOREACH(_phys, _pageframe) \ - for (_phys = Z_PHYS_RAM_START, _pageframe = z_page_frames; \ - _phys < Z_PHYS_RAM_END; \ - _phys += CONFIG_MMU_PAGE_SIZE, _pageframe++) + for ((_phys) = Z_PHYS_RAM_START, (_pageframe) = z_page_frames; \ + (_phys) < Z_PHYS_RAM_END; \ + (_phys) += CONFIG_MMU_PAGE_SIZE, (_pageframe)++) #ifdef CONFIG_DEMAND_PAGING /* We reserve a virtual page as a scratch area for page-ins/outs at the end diff --git a/kernel/mmu.c b/kernel/mmu.c index f74b8c7cf4454..0621a63d6bfc6 100644 --- a/kernel/mmu.c +++ b/kernel/mmu.c @@ -133,12 +133,12 @@ void z_page_frames_dump(void) /* LCOV_EXCL_STOP */ #define VIRT_FOREACH(_base, _size, _pos) \ - for (_pos = _base; \ - _pos < ((uint8_t *)_base + _size); _pos += CONFIG_MMU_PAGE_SIZE) + for ((_pos) = (_base); \ + (_pos) < ((uint8_t *)(_base) + (_size)); (_pos) += CONFIG_MMU_PAGE_SIZE) #define PHYS_FOREACH(_base, _size, _pos) \ - for (_pos = _base; \ - _pos < ((uintptr_t)_base + _size); _pos += CONFIG_MMU_PAGE_SIZE) + for ((_pos) = (_base); \ + (_pos) < ((uintptr_t)(_base) + (_size)); (_pos) += CONFIG_MMU_PAGE_SIZE) /* From f55391745b86ea56e15d16a8aa99cd5b4c94c223 Mon Sep 17 00:00:00 2001 From: Francois Ramu Date: Wed, 5 Jun 2024 10:32:49 +0200 Subject: [PATCH 1993/2849] drivers: ethernet: stm32 eth hal driver align PTP Config Status Align the name of the ETH PTP Config Status values depending on the stm32HAL serie to be the HAL_ETH_PTP_NOT_CONFIGURATED/HAL_ETH_PTP_CONFIGURATED or HAL_ETH_PTP_NOT_CONFIGURED/HAL_ETH_PTP_CONFIGURED Signed-off-by: Francois Ramu --- drivers/ethernet/eth_stm32_hal.c | 2 +- drivers/ethernet/eth_stm32_hal_priv.h | 9 +++++++++ samples/net/gptp/sample.yaml | 1 + 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/drivers/ethernet/eth_stm32_hal.c b/drivers/ethernet/eth_stm32_hal.c index 0da1411c3112a..77c0c753691b5 100644 --- a/drivers/ethernet/eth_stm32_hal.c +++ b/drivers/ethernet/eth_stm32_hal.c @@ -1823,7 +1823,7 @@ static int ptp_stm32_init(const struct device *port) #if defined(CONFIG_ETH_STM32_HAL_API_V2) /* Set PTP Configuration done */ - heth->IsPtpConfigured = HAL_ETH_PTP_CONFIGURATED; + heth->IsPtpConfigured = ETH_STM32_PTP_CONFIGURED; #endif return 0; diff --git a/drivers/ethernet/eth_stm32_hal_priv.h b/drivers/ethernet/eth_stm32_hal_priv.h index 55ae396c90dcc..6402a9a306969 100644 --- a/drivers/ethernet/eth_stm32_hal_priv.h +++ b/drivers/ethernet/eth_stm32_hal_priv.h @@ -9,6 +9,15 @@ #include #include +/* Naming of the ETH PTP Config Status changes depending on the stm32 serie */ +#if defined(CONFIG_SOC_SERIES_STM32F7X) || defined(CONFIG_SOC_SERIES_STM32F4X) +#define ETH_STM32_PTP_CONFIGURED HAL_ETH_PTP_CONFIGURATED +#define ETH_STM32_PTP_NOT_CONFIGURED HAL_ETH_PTP_NOT_CONFIGURATED +#else +#define ETH_STM32_PTP_CONFIGURED HAL_ETH_PTP_CONFIGURED +#define ETH_STM32_PTP_NOT_CONFIGURED HAL_ETH_PTP_NOT_CONFIGURED +#endif /* stm32F7x or sm32F4x */ + #define ST_OUI_B0 0x00 #define ST_OUI_B1 0x80 #define ST_OUI_B2 0xE1 diff --git a/samples/net/gptp/sample.yaml b/samples/net/gptp/sample.yaml index b0a49d2413910..44bf695d628da 100644 --- a/samples/net/gptp/sample.yaml +++ b/samples/net/gptp/sample.yaml @@ -17,6 +17,7 @@ tests: - native_sim/native/64 - nucleo_f767zi - nucleo_h743zi + - nucleo_h753zi - nucleo_h745zi_q/stm32h745xx/m7 depends_on: eth integration_platforms: From 620708b9e0984235ecd891051ca1ad0f88031477 Mon Sep 17 00:00:00 2001 From: Emil Gydesen Date: Wed, 5 Jun 2024 10:20:42 +0200 Subject: [PATCH 1994/2849] Bluetooth: Audio: Shell: Add additional test cases for CAP Add additional test cases for CAP where only a single CAP role is enabled. Signed-off-by: Emil Gydesen --- tests/bluetooth/shell/testcase.yaml | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/tests/bluetooth/shell/testcase.yaml b/tests/bluetooth/shell/testcase.yaml index 3ddde520a861f..8f89277f29e5d 100644 --- a/tests/bluetooth/shell/testcase.yaml +++ b/tests/bluetooth/shell/testcase.yaml @@ -333,11 +333,25 @@ tests: build_only: true extra_configs: - CONFIG_BT_CAP_ACCEPTOR_SET_MEMBER=n + bluetooth.audio_shell.only_cap_acceptor: + extra_args: CONF_FILE="audio.conf" + build_only: true + extra_configs: + - CONFIG_BT_BAP_UNICAST_CLIENT=n + - CONFIG_BT_CAP_INITIATOR=n + - CONFIG_BT_CAP_COMMANDER=n bluetooth.audio_shell.no_cap_initiator: extra_args: CONF_FILE="audio.conf" build_only: true extra_configs: - CONFIG_BT_CAP_INITIATOR=n + bluetooth.audio_shell.only_cap_initiator: + extra_args: CONF_FILE="audio.conf" + build_only: true + extra_configs: + - CONFIG_BT_BAP_UNICAST_SERVER=n + - CONFIG_BT_CAP_ACCEPTOR=n + - CONFIG_BT_CAP_COMMANDER=n bluetooth.audio_shell.no_gmap: extra_args: CONF_FILE="audio.conf" build_only: true @@ -350,6 +364,14 @@ tests: platform_allow: native_posix extra_configs: - CONFIG_BT_CAP_COMMANDER=n + bluetooth.audio_shell.only_cap_commander: + extra_args: CONF_FILE="audio.conf" + build_only: true + platform_allow: native_posix + extra_configs: + - CONFIG_BT_BAP_UNICAST_CLIENT=n + - CONFIG_BT_CAP_ACCEPTOR=n + - CONFIG_BT_CAP_INITIATOR=n bluetooth.audio_shell.no_lc3: extra_args: CONF_FILE="audio.conf" build_only: true From 5c9032019cff84032ecb6e6830e7d9be945e7e31 Mon Sep 17 00:00:00 2001 From: Emil Gydesen Date: Wed, 5 Jun 2024 10:21:09 +0200 Subject: [PATCH 1995/2849] Bluetooth: CAP: Fix linker issue in cap_stream.c for x86 The existing code in the cap_stream.c that handled the check before calling CAP initiator unicast functions seemingly did not work for x86 targets such as native_sim or native_posix. Modified the check so that IS_ENABLED is used directly. Signed-off-by: Emil Gydesen --- subsys/bluetooth/audio/cap_stream.c | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/subsys/bluetooth/audio/cap_stream.c b/subsys/bluetooth/audio/cap_stream.c index ebebeb2eb5fa2..bd5390b9fef12 100644 --- a/subsys/bluetooth/audio/cap_stream.c +++ b/subsys/bluetooth/audio/cap_stream.c @@ -6,6 +6,7 @@ #include #include +#include #include #include @@ -25,9 +26,9 @@ LOG_MODULE_REGISTER(bt_cap_stream, CONFIG_BT_CAP_STREAM_LOG_LEVEL); -static bool is_cap_initiator_unicast(struct bt_bap_stream *bap_stream) +static bool stream_is_central(struct bt_bap_stream *bap_stream) { - if (IS_ENABLED(CONFIG_BT_CAP_INITIATOR) && IS_ENABLED(CONFIG_BT_BAP_UNICAST_CLIENT)) { + if (IS_ENABLED(CONFIG_BT_CONN)) { struct bt_conn_info info; int err; @@ -55,7 +56,8 @@ static void cap_stream_configured_cb(struct bt_bap_stream *bap_stream, LOG_DBG("%p", cap_stream); - if (is_cap_initiator_unicast(bap_stream)) { + if (IS_ENABLED(CONFIG_BT_CAP_INITIATOR) && IS_ENABLED(CONFIG_BT_BAP_UNICAST_CLIENT) && + stream_is_central(bap_stream)) { bt_cap_initiator_codec_configured(cap_stream); } @@ -73,7 +75,8 @@ static void cap_stream_qos_set_cb(struct bt_bap_stream *bap_stream) LOG_DBG("%p", cap_stream); - if (is_cap_initiator_unicast(bap_stream)) { + if (IS_ENABLED(CONFIG_BT_CAP_INITIATOR) && IS_ENABLED(CONFIG_BT_BAP_UNICAST_CLIENT) && + stream_is_central(bap_stream)) { bt_cap_initiator_qos_configured(cap_stream); } @@ -91,7 +94,8 @@ static void cap_stream_enabled_cb(struct bt_bap_stream *bap_stream) LOG_DBG("%p", cap_stream); - if (is_cap_initiator_unicast(bap_stream)) { + if (IS_ENABLED(CONFIG_BT_CAP_INITIATOR) && IS_ENABLED(CONFIG_BT_BAP_UNICAST_CLIENT) && + stream_is_central(bap_stream)) { bt_cap_initiator_enabled(cap_stream); } @@ -109,7 +113,8 @@ static void cap_stream_metadata_updated_cb(struct bt_bap_stream *bap_stream) LOG_DBG("%p", cap_stream); - if (is_cap_initiator_unicast(bap_stream)) { + if (IS_ENABLED(CONFIG_BT_CAP_INITIATOR) && IS_ENABLED(CONFIG_BT_BAP_UNICAST_CLIENT) && + stream_is_central(bap_stream)) { bt_cap_initiator_metadata_updated(cap_stream); } @@ -141,7 +146,7 @@ static void cap_stream_released_cb(struct bt_bap_stream *bap_stream) LOG_DBG("%p", cap_stream); - /* Here we cannot use is_cap_initiator_unicast as bap_stream->conn is NULL, so fall back to + /* Here we cannot use stream_is_central as bap_stream->conn is NULL, so fall back to * a more generic, less accurate check */ if (IS_ENABLED(CONFIG_BT_CAP_INITIATOR) && IS_ENABLED(CONFIG_BT_BAP_UNICAST_CLIENT)) { @@ -164,7 +169,8 @@ static void cap_stream_started_cb(struct bt_bap_stream *bap_stream) LOG_DBG("%p", cap_stream); - if (is_cap_initiator_unicast(bap_stream)) { + if (IS_ENABLED(CONFIG_BT_CAP_INITIATOR) && IS_ENABLED(CONFIG_BT_BAP_UNICAST_CLIENT) && + stream_is_central(bap_stream)) { bt_cap_initiator_started(cap_stream); } @@ -222,7 +228,8 @@ static void cap_stream_connected_cb(struct bt_bap_stream *bap_stream) CONTAINER_OF(bap_stream, struct bt_cap_stream, bap_stream); struct bt_bap_stream_ops *ops = cap_stream->ops; - if (is_cap_initiator_unicast(bap_stream)) { + if (IS_ENABLED(CONFIG_BT_CAP_INITIATOR) && IS_ENABLED(CONFIG_BT_BAP_UNICAST_CLIENT) && + stream_is_central(bap_stream)) { bt_cap_initiator_connected(cap_stream); } From b9ad339a5bc681f3d4bf80d3963d01685c952d20 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20Cab=C3=A9?= Date: Wed, 5 Jun 2024 09:52:01 +0200 Subject: [PATCH 1996/2849] mqtt: doc: remove Unicode fullwidth left parenthesis MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix Doxygen comment for shell_mqtt_get_devid which contained a funky Unicode char (U+FF08) for a left parenthesis that can cause issues with some documentation tools. Signed-off-by: Benjamin Cabé --- include/zephyr/shell/shell_mqtt.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/zephyr/shell/shell_mqtt.h b/include/zephyr/shell/shell_mqtt.h index 03cd64fbdcdba..72e597e6d53b2 100644 --- a/include/zephyr/shell/shell_mqtt.h +++ b/include/zephyr/shell/shell_mqtt.h @@ -120,7 +120,7 @@ struct shell_mqtt { const struct shell *shell_backend_mqtt_get_ptr(void); /** - * @brief Function to define the device ID (devid) for which the shell mqtt backend uses as a + * @brief Function to define the device ID (devid) for which the shell mqtt backend uses as a * client ID when it connects to the broker. It will publish its output to devid_tx and subscribe * to devid_rx for input . * From 11a038518a8b3824b49c49fa111b0a8e2529609f Mon Sep 17 00:00:00 2001 From: Tahsin Mutlugun Date: Wed, 5 Jun 2024 09:22:32 +0300 Subject: [PATCH 1997/2849] dts: arm: adi: Add I2C nodes for MAX32 SoCs. Enable I2C nodes on MAX32 SoCs. Co-Authored-By: Sadik Ozer Co-Authored-By: Mert Vatansever Signed-off-by: Tahsin Mutlugun --- dts/arm/adi/max32/max32xxx.dtsi | 34 +++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/dts/arm/adi/max32/max32xxx.dtsi b/dts/arm/adi/max32/max32xxx.dtsi index 64db703296029..9db02fc449834 100644 --- a/dts/arm/adi/max32/max32xxx.dtsi +++ b/dts/arm/adi/max32/max32xxx.dtsi @@ -7,6 +7,7 @@ #include #include #include +#include #include @@ -101,6 +102,39 @@ status = "okay"; }; + i2c0: i2c0@4001d000 { + compatible = "adi,max32-i2c"; + reg = <0x4001d000 0x1000>; + #address-cells = <1>; + #size-cells = <0>; + clock-frequency = ; + clocks = <&gcr ADI_MAX32_CLOCK_BUS0 13>; + interrupts = <13 0>; + status = "disabled"; + }; + + i2c1: i2c1@4001e000 { + compatible = "adi,max32-i2c"; + reg = <0x4001e000 0x1000>; + #address-cells = <1>; + #size-cells = <0>; + clock-frequency = ; + clocks = <&gcr ADI_MAX32_CLOCK_BUS0 28>; + interrupts = <36 0>; + status = "disabled"; + }; + + i2c2: i2c2@4001f000 { + compatible = "adi,max32-i2c"; + reg = <0x4001f000 0x1000>; + #address-cells = <1>; + #size-cells = <0>; + clock-frequency = ; + clocks = <&gcr ADI_MAX32_CLOCK_BUS1 24>; + interrupts = <62 0>; + status = "disabled"; + }; + pinctrl: pin-controller@40008000 { compatible = "adi,max32-pinctrl"; #address-cells = <1>; From f037b95549fb59b6775b786991f34773f2d0d0f4 Mon Sep 17 00:00:00 2001 From: Tahsin Mutlugun Date: Wed, 5 Jun 2024 10:28:52 +0300 Subject: [PATCH 1998/2849] drivers: i2c: Add MAX32690 I2C driver Add I2C driver for Analog Devices MAX32690 MCU. Supports target mode. Co-Authored-By: Sadik Ozer Co-Authored-By: Mert Vatansever Signed-off-by: Tahsin Mutlugun --- drivers/i2c/CMakeLists.txt | 1 + drivers/i2c/Kconfig | 1 + drivers/i2c/Kconfig.max32 | 20 + drivers/i2c/i2c_max32.c | 732 ++++++++++++++++++++++++++++ dts/bindings/i2c/adi,max32-i2c.yaml | 18 + 5 files changed, 772 insertions(+) create mode 100644 drivers/i2c/Kconfig.max32 create mode 100644 drivers/i2c/i2c_max32.c create mode 100644 dts/bindings/i2c/adi,max32-i2c.yaml diff --git a/drivers/i2c/CMakeLists.txt b/drivers/i2c/CMakeLists.txt index 16fa2b450d1fd..aa46769ed850b 100644 --- a/drivers/i2c/CMakeLists.txt +++ b/drivers/i2c/CMakeLists.txt @@ -79,6 +79,7 @@ zephyr_library_sources_ifdef(CONFIG_I2C_AMBIQ i2c_ambiq.c) zephyr_library_sources_ifdef(CONFIG_I2C_ENE_KB1200 i2c_ene_kb1200.c) zephyr_library_sources_ifdef(CONFIG_GPIO_I2C_SWITCH gpio_i2c_switch.c) zephyr_library_sources_ifdef(CONFIG_I2C_NUMAKER i2c_numaker.c) +zephyr_library_sources_ifdef(CONFIG_I2C_MAX32 i2c_max32.c) zephyr_library_sources_ifdef(CONFIG_I2C_STM32_V1 i2c_ll_stm32_v1.c diff --git a/drivers/i2c/Kconfig b/drivers/i2c/Kconfig index f5dacfe8ea4ca..2002813da526a 100644 --- a/drivers/i2c/Kconfig +++ b/drivers/i2c/Kconfig @@ -128,6 +128,7 @@ source "drivers/i2c/Kconfig.ambiq" source "drivers/i2c/Kconfig.numaker" source "drivers/i2c/Kconfig.mcux" source "drivers/i2c/Kconfig.ene" +source "drivers/i2c/Kconfig.max32" config I2C_INIT_PRIORITY int "Init priority" diff --git a/drivers/i2c/Kconfig.max32 b/drivers/i2c/Kconfig.max32 new file mode 100644 index 0000000000000..b41f5ec862077 --- /dev/null +++ b/drivers/i2c/Kconfig.max32 @@ -0,0 +1,20 @@ +# Copyright (c) 2024 Analog Devices, Inc. +# SPDX-License-Identifier: Apache-2.0 + +menuconfig I2C_MAX32 + bool "Analog Devices MAX32 I2C driver" + default y + depends on DT_HAS_ADI_MAX32_I2C_ENABLED + help + i2c driver for max32 family. + +if I2C_MAX32 + +config I2C_MAX32_INTERRUPT + bool "Interrupt support for MAX32 I2C driver" + default y + help + Enable interrupt support for MAX32 I2C controller mode + transfers. + +endif # I2C_MAX32 diff --git a/drivers/i2c/i2c_max32.c b/drivers/i2c/i2c_max32.c new file mode 100644 index 0000000000000..8783e6d7e4863 --- /dev/null +++ b/drivers/i2c/i2c_max32.c @@ -0,0 +1,732 @@ +/* + * Copyright (c) 2024 Analog Devices, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT adi_max32_i2c + +#include +#include +#include +#include +#include + +#include + +#define ADI_MAX32_I2C_INT_FL0_MASK 0x00FFFFFF +#define ADI_MAX32_I2C_INT_FL1_MASK 0x7 + +#define ADI_MAX32_I2C_STATUS_MASTER_BUSY BIT(5) + +#define I2C_RECOVER_MAX_RETRIES 3 + +/* Driver config */ +struct max32_i2c_config { + mxc_i2c_regs_t *regs; + const struct pinctrl_dev_config *pctrl; + const struct device *clock; + struct max32_perclk perclk; + uint32_t bitrate; +#if defined(CONFIG_I2C_TARGET) || defined(CONFIG_I2C_MAX32_INTERRUPT) + uint8_t irqn; + void (*irq_config_func)(const struct device *dev); +#endif +}; + +struct max32_i2c_data { + mxc_i2c_req_t req; + const struct device *dev; + struct k_sem lock; + uint8_t target_mode; + uint8_t flags; +#ifdef CONFIG_I2C_TARGET + struct i2c_target_config *target_cfg; + bool first_write; +#endif /* CONFIG_I2C_TARGET */ + uint32_t readb; + uint32_t written; +#if defined(CONFIG_I2C_MAX32_INTERRUPT) + struct k_sem xfer; + int err; +#endif +}; + +static int api_configure(const struct device *dev, uint32_t dev_cfg) +{ + int ret = 0; + const struct max32_i2c_config *const cfg = dev->config; + mxc_i2c_regs_t *i2c = cfg->regs; + + switch (I2C_SPEED_GET(dev_cfg)) { + case I2C_SPEED_STANDARD: /** I2C Standard Speed: 100 kHz */ + ret = MXC_I2C_SetFrequency(i2c, MXC_I2C_STD_MODE); + break; + + case I2C_SPEED_FAST: /** I2C Fast Speed: 400 kHz */ + ret = MXC_I2C_SetFrequency(i2c, MXC_I2C_FAST_SPEED); + break; + +#if defined(MXC_I2C_FASTPLUS_SPEED) + case I2C_SPEED_FAST_PLUS: /** I2C Fast Plus Speed: 1 MHz */ + ret = MXC_I2C_SetFrequency(i2c, MXC_I2C_FASTPLUS_SPEED); + break; +#endif + +#if defined(MXC_I2C_HIGH_SPEED) + case I2C_SPEED_HIGH: /** I2C High Speed: 3.4 MHz */ + ret = MXC_I2C_SetFrequency(i2c, MXC_I2C_HIGH_SPEED); + break; +#endif + + default: + /* Speed not supported */ + return -ENOTSUP; + } + + return ret; +} + +#ifdef CONFIG_I2C_TARGET +static int api_target_register(const struct device *dev, struct i2c_target_config *cfg) +{ + const struct max32_i2c_config *config = dev->config; + struct max32_i2c_data *data = dev->data; + mxc_i2c_regs_t *i2c = config->regs; + int ret; + + data->target_cfg = cfg; + + ret = MXC_I2C_Init(i2c, 0, cfg->address); + if (ret == E_NO_ERROR) { + data->target_mode = 1; + irq_enable(config->irqn); + MXC_I2C_SlaveTransactionAsync(i2c, NULL); + } + + return ret == E_NO_ERROR ? 0 : E_FAIL; +} + +static int api_target_unregister(const struct device *dev, struct i2c_target_config *cfg) +{ + const struct max32_i2c_config *config = dev->config; + struct max32_i2c_data *data = dev->data; + mxc_i2c_regs_t *i2c = config->regs; + + data->target_cfg = NULL; + data->target_mode = 0; + +#ifndef CONFIG_I2C_MAX32_INTERRUPT + irq_disable(config->irqn); +#endif + + return MXC_I2C_Init(i2c, 1, 0); +} + +static int i2c_max32_target_callback(const struct device *dev, mxc_i2c_regs_t *i2c, + mxc_i2c_slave_event_t event) +{ + struct max32_i2c_data *data = dev->data; + const struct i2c_target_callbacks *target_cb = data->target_cfg->callbacks; + static uint8_t rxval, txval, rxcnt; + + switch (event) { + case MXC_I2C_EVT_MASTER_WR: + if (data->first_write && target_cb->write_requested) { + target_cb->write_requested(data->target_cfg); + data->first_write = false; + } + break; + case MXC_I2C_EVT_MASTER_RD: + break; + case MXC_I2C_EVT_RX_THRESH: + case MXC_I2C_EVT_OVERFLOW: + rxcnt = MXC_I2C_GetRXFIFOAvailable(i2c); + if (target_cb->write_received) { + while (rxcnt--) { + MXC_I2C_ReadRXFIFO(i2c, &rxval, 1); + target_cb->write_received(data->target_cfg, rxval); + } + } else { + MXC_I2C_ClearRXFIFO(i2c); + } + break; + case MXC_I2C_EVT_TX_THRESH: + case MXC_I2C_EVT_UNDERFLOW: + if (target_cb->read_requested) { + target_cb->read_requested(data->target_cfg, &txval); + MXC_I2C_WriteTXFIFO(i2c, &txval, 1); + } + if (target_cb->read_processed) { + target_cb->read_processed(data->target_cfg, &txval); + } + break; + case MXC_I2C_EVT_TRANS_COMP: + if (target_cb->stop) { + target_cb->stop(data->target_cfg); + } + data->first_write = true; + break; + } + + return 0; +} +#endif /* CONFIG_I2C_TARGET */ + +static int api_recover_bus(const struct device *dev) +{ + int ret; + const struct max32_i2c_config *const cfg = dev->config; + mxc_i2c_regs_t *i2c = cfg->regs; + + ret = MXC_I2C_Recover(i2c, I2C_RECOVER_MAX_RETRIES); + + return ret; +} + +#ifndef CONFIG_I2C_MAX32_INTERRUPT +static int i2c_max32_transfer_sync(mxc_i2c_regs_t *i2c, struct max32_i2c_data *data) +{ + uint32_t int_fl0, int_fl1; + uint32_t readb = 0; + mxc_i2c_req_t *req = &data->req; + + /* Wait for acknowledge */ + if (data->flags & (I2C_MSG_RESTART | I2C_MSG_READ)) { + do { + MXC_I2C_GetFlags(i2c, &int_fl0, &int_fl1); + } while (!(int_fl0 & ADI_MAX32_I2C_INT_FL0_ADDR_ACK) && + !(int_fl0 & ADI_MAX32_I2C_INT_FL0_ERR)); + } + + if (int_fl0 & ADI_MAX32_I2C_INT_FL0_ERR) { + return -EIO; + } + + while (req->tx_len > data->written) { + MXC_I2C_GetFlags(i2c, &int_fl0, &int_fl1); + if (int_fl0 & ADI_MAX32_I2C_INT_FL0_TX_THD) { + data->written += MXC_I2C_WriteTXFIFO(i2c, &req->tx_buf[data->written], + req->tx_len - data->written); + MXC_I2C_ClearFlags(i2c, ADI_MAX32_I2C_INT_FL0_TX_THD, 0); + } + + if (int_fl0 & ADI_MAX32_I2C_INT_FL0_ERR) { + return -EIO; + } + } + + MXC_I2C_ClearFlags(i2c, ADI_MAX32_I2C_INT_FL0_DONE, 0); + Wrap_MXC_I2C_SetRxCount(i2c, req->rx_len); + while (req->rx_len > readb) { + MXC_I2C_GetFlags(i2c, &int_fl0, &int_fl1); + if (int_fl0 & (ADI_MAX32_I2C_INT_FL0_RX_THD | ADI_MAX32_I2C_INT_FL0_DONE)) { + readb += MXC_I2C_ReadRXFIFO(i2c, &req->rx_buf[readb], req->rx_len - readb); + MXC_I2C_ClearFlags(i2c, ADI_MAX32_I2C_INT_FL0_RX_THD, 0); + } + + if (int_fl0 & ADI_MAX32_I2C_INT_FL0_ERR) { + return -EIO; + } + + MXC_I2C_GetFlags(i2c, &int_fl0, &int_fl1); + if ((int_fl0 & ADI_MAX32_I2C_INT_FL0_DONE) && (req->rx_len > readb) && + MXC_I2C_GetRXFIFOAvailable(i2c) == 0) { + Wrap_MXC_I2C_SetRxCount(i2c, req->rx_len - readb); + Wrap_MXC_I2C_Restart(i2c); + MXC_I2C_ClearFlags(i2c, ADI_MAX32_I2C_INT_FL0_DONE, 0); + i2c->fifo = (req->addr << 1) | 0x1; + } + } + + MXC_I2C_GetFlags(i2c, &int_fl0, &int_fl1); + if (int_fl0 & ADI_MAX32_I2C_INT_FL0_ERR) { + return -EIO; + } + + if (data->flags & I2C_MSG_STOP) { + MXC_I2C_Stop(i2c); + do { + MXC_I2C_GetFlags(i2c, &int_fl0, &int_fl1); + } while (!(int_fl0 & ADI_MAX32_I2C_INT_FL0_STOP)); + } + + if (req->rx_len) { + do { + MXC_I2C_GetFlags(i2c, &int_fl0, &int_fl1); + } while (!(int_fl0 & ADI_MAX32_I2C_INT_FL0_DONE)); + } else { + while (Wrap_MXC_I2C_GetTxFIFOLevel(i2c) > 0) { + MXC_I2C_GetFlags(i2c, &int_fl0, &int_fl1); + } + } + MXC_I2C_ClearFlags(i2c, ADI_MAX32_I2C_INT_FL0_MASK, ADI_MAX32_I2C_INT_FL1_MASK); + + return 0; +} +#endif /* CONFIG_I2C_MAX32_INTERRUPT */ + +#ifdef CONFIG_I2C_MAX32_INTERRUPT +static int i2c_max32_transfer(const struct device *dev, struct i2c_msg *msgs, uint8_t num_msgs, + uint16_t target_address) +{ + int ret = 0; + const struct max32_i2c_config *const cfg = dev->config; + struct max32_i2c_data *data = dev->data; + mxc_i2c_regs_t *i2c = cfg->regs; + mxc_i2c_req_t *req = &data->req; + uint8_t target_rw; + unsigned int i = 0; + + req->i2c = i2c; + req->addr = target_address; + + k_sem_take(&data->lock, K_FOREVER); + + MXC_I2C_ClearRXFIFO(i2c); + MXC_I2C_ClearTXFIFO(i2c); + MXC_I2C_SetRXThreshold(i2c, 1); + + /* First message should always begin with a START condition */ + msgs[0].flags |= I2C_MSG_RESTART; + + for (i = 0; i < num_msgs; i++) { + if (msgs[i].flags & I2C_MSG_READ) { + req->rx_buf = (unsigned char *)msgs[i].buf; + req->rx_len = msgs[i].len; + req->tx_buf = NULL; + req->tx_len = 0; + target_rw = (target_address << 1) | 0x1; + } else { + req->tx_buf = (unsigned char *)msgs[i].buf; + req->tx_len = msgs[i].len; + req->rx_buf = NULL; + req->rx_len = 0; + target_rw = (target_address << 1) & ~0x1; + } + + /* + * If previous message ends with a STOP condition, this message + * should begin with a START + */ + if (i > 0) { + if ((msgs[i - 1].flags & (I2C_MSG_STOP | I2C_MSG_READ))) { + msgs[i].flags |= I2C_MSG_RESTART; + } + } + + data->flags = msgs[i].flags; + data->readb = 0; + data->written = 0; + data->err = 0; + + MXC_I2C_ClearFlags(i2c, ADI_MAX32_I2C_INT_FL0_MASK, ADI_MAX32_I2C_INT_FL1_MASK); + MXC_I2C_EnableInt(i2c, ADI_MAX32_I2C_INT_EN0_ERR, 0); + Wrap_MXC_I2C_SetRxCount(i2c, req->rx_len); + if ((data->flags & I2C_MSG_RESTART)) { + MXC_I2C_EnableInt(i2c, ADI_MAX32_I2C_INT_EN0_ADDR_ACK, 0); + MXC_I2C_Start(i2c); + Wrap_MXC_I2C_WaitForRestart(i2c); + MXC_I2C_WriteTXFIFO(i2c, &target_rw, 1); + } else { + if (req->tx_len) { + data->written = MXC_I2C_WriteTXFIFO(i2c, req->tx_buf, 1); + MXC_I2C_EnableInt(i2c, ADI_MAX32_I2C_INT_EN0_TX_THD, 0); + } else { + MXC_I2C_EnableInt(i2c, ADI_MAX32_I2C_INT_EN0_RX_THD, 0); + } + } + + ret = k_sem_take(&data->xfer, K_FOREVER); + if (data->err) { + MXC_I2C_Stop(i2c); + ret = data->err; + } else { + if (data->flags & I2C_MSG_STOP) { + /* Wait for busy flag to be cleared */ + while (i2c->status & ADI_MAX32_I2C_STATUS_MASTER_BUSY) { + } + MXC_I2C_ClearFlags(i2c, ADI_MAX32_I2C_INT_FL0_MASK, + ADI_MAX32_I2C_INT_FL1_MASK); + } + } + if (ret) { + break; + } + } + + k_sem_give(&data->lock); + + return ret; +} +#else +static int i2c_max32_transfer(const struct device *dev, struct i2c_msg *msgs, uint8_t num_msgs, + uint16_t target_address) +{ + int ret = 0; + const struct max32_i2c_config *const cfg = dev->config; + struct max32_i2c_data *data = dev->data; + mxc_i2c_regs_t *i2c = cfg->regs; + mxc_i2c_req_t *req = &data->req; + uint8_t target_rw; + unsigned int i = 0; + + req->i2c = i2c; + req->addr = target_address; + + k_sem_take(&data->lock, K_FOREVER); + + MXC_I2C_ClearRXFIFO(i2c); + + /* First message should always begin with a START condition */ + msgs[0].flags |= I2C_MSG_RESTART; + + for (i = 0; i < num_msgs; i++) { + if (msgs[i].flags & I2C_MSG_READ) { + req->rx_buf = (unsigned char *)msgs[i].buf; + req->rx_len = msgs[i].len; + req->tx_buf = NULL; + req->tx_len = 0; + target_rw = (target_address << 1) | 0x1; + } else { + req->tx_buf = (unsigned char *)msgs[i].buf; + req->tx_len = msgs[i].len; + req->rx_buf = NULL; + req->rx_len = 0; + target_rw = (target_address << 1) & ~0x1; + } + + /* + * If previous message ends with a STOP condition, this message + * should begin with a START + */ + if (i > 0) { + if ((msgs[i - 1].flags & (I2C_MSG_STOP | I2C_MSG_READ))) { + msgs[i].flags |= I2C_MSG_RESTART; + } + } + + data->flags = msgs[i].flags; + data->readb = 0; + data->written = 0; + + MXC_I2C_ClearFlags(i2c, ADI_MAX32_I2C_INT_FL0_MASK, ADI_MAX32_I2C_INT_FL1_MASK); + + Wrap_MXC_I2C_SetIntEn(i2c, 0, 0); + if (data->flags & I2C_MSG_RESTART) { + MXC_I2C_Start(i2c); + Wrap_MXC_I2C_WaitForRestart(i2c); + MXC_I2C_WriteTXFIFO(i2c, &target_rw, 1); + } + ret = i2c_max32_transfer_sync(i2c, data); + if (ret) { + MXC_I2C_Stop(i2c); + break; + } + } + + k_sem_give(&data->lock); + + return ret; +} +#endif /* CONFIG_I2C_MAX32_INTERRUPT */ + +static int api_transfer(const struct device *dev, struct i2c_msg *msgs, uint8_t num_msgs, + uint16_t target_address) +{ + return i2c_max32_transfer(dev, msgs, num_msgs, target_address); +} + +#ifdef CONFIG_I2C_TARGET +static void i2c_max32_isr_target(const struct device *dev, mxc_i2c_regs_t *i2c) +{ + uint32_t ctrl; + uint32_t int_fl0; + uint32_t int_fl1; + uint32_t int_en0; + uint32_t int_en1; + + ctrl = i2c->ctrl; + Wrap_MXC_I2C_GetIntEn(i2c, &int_en0, &int_en1); + MXC_I2C_GetFlags(i2c, &int_fl0, &int_fl1); + MXC_I2C_ClearFlags(i2c, ADI_MAX32_I2C_INT_FL0_MASK, ADI_MAX32_I2C_INT_FL1_MASK); + + if (int_fl0 & ADI_MAX32_I2C_INT_FL0_ERR) { + /* Error occurred, notify callback function and end transaction */ + i2c_max32_target_callback(dev, i2c, MXC_I2C_EVT_TRANS_COMP); + + MXC_I2C_ClearFlags(i2c, ADI_MAX32_I2C_INT_FL0_MASK, ADI_MAX32_I2C_INT_FL1_MASK); + MXC_I2C_ClearTXFIFO(i2c); + MXC_I2C_ClearRXFIFO(i2c); + } + + /* Check whether data is available if we received an interrupt occurred while receiving */ + if (int_en0 & ADI_MAX32_I2C_INT_EN0_RX_THD || int_en1 & ADI_MAX32_I2C_INT_EN1_RX_OVERFLOW) { + if (int_fl0 & ADI_MAX32_I2C_INT_FL0_RX_THD) { + i2c_max32_target_callback(dev, i2c, MXC_I2C_EVT_RX_THRESH); + } + + if (int_fl1 & ADI_MAX32_I2C_INT_FL1_RX_OVERFLOW) { + i2c_max32_target_callback(dev, i2c, MXC_I2C_EVT_OVERFLOW); + } + } + + /* Check whether TX FIFO needs to be refilled if interrupt ocurred while transmitting */ + if (int_en0 & (ADI_MAX32_I2C_INT_EN0_TX_THD | ADI_MAX32_I2C_INT_EN0_TX_LOCK_OUT) || + int_en1 & ADI_MAX32_I2C_INT_EN1_TX_UNDERFLOW) { + if (int_fl0 & ADI_MAX32_I2C_INT_FL0_TX_THD) { + i2c_max32_target_callback(dev, i2c, MXC_I2C_EVT_TX_THRESH); + } + + if (int_fl1 & ADI_MAX32_I2C_INT_EN1_TX_UNDERFLOW) { + i2c_max32_target_callback(dev, i2c, MXC_I2C_EVT_UNDERFLOW); + } + + if (int_fl0 & ADI_MAX32_I2C_INT_FL0_TX_LOCK_OUT) { + int_en0 = ADI_MAX32_I2C_INT_EN0_ADDR_MATCH; + int_en1 = 0; + i2c_max32_target_callback(dev, i2c, MXC_I2C_EVT_TRANS_COMP); + } + } + + /* Check if transaction completed or restart occurred */ + if (int_en0 & ADI_MAX32_I2C_INT_EN0_DONE) { + if (int_fl0 & ADI_MAX32_I2C_INT_FL0_STOP) { + /* Stop/NACK condition occurred, transaction complete */ + i2c_max32_target_callback(dev, i2c, MXC_I2C_EVT_TRANS_COMP); + int_en0 = ADI_MAX32_I2C_INT_EN0_ADDR_MATCH; + } else if (int_fl0 & ADI_MAX32_I2C_INT_FL0_DONE) { + /* Restart detected, re-arm address match interrupt */ + int_en0 = ADI_MAX32_I2C_INT_EN0_ADDR_MATCH; + } + int_en1 = 0; + } + + /* Check for address match interrupt */ + if (int_en0 & ADI_MAX32_I2C_INT_EN0_ADDR_MATCH) { + if (int_fl0 & ADI_MAX32_I2C_INT_FL0_ADDR_MATCH) { + /* Address match occurred, prepare for transaction */ + if (i2c->ctrl & MXC_F_I2C_CTRL_READ) { + /* Read request received from the master */ + i2c_max32_target_callback(dev, i2c, MXC_I2C_EVT_MASTER_RD); + int_en0 = ADI_MAX32_I2C_INT_EN0_TX_THD | + ADI_MAX32_I2C_INT_EN0_TX_LOCK_OUT | + ADI_MAX32_I2C_INT_EN0_DONE | ADI_MAX32_I2C_INT_EN0_ERR; + int_en1 = ADI_MAX32_I2C_INT_EN1_TX_UNDERFLOW; + } else { + /* Write request received from the master */ + i2c_max32_target_callback(dev, i2c, MXC_I2C_EVT_MASTER_WR); + int_en0 = ADI_MAX32_I2C_INT_EN0_RX_THD | + ADI_MAX32_I2C_INT_EN0_DONE | ADI_MAX32_I2C_INT_EN0_ERR; + int_en1 = ADI_MAX32_I2C_INT_EN1_RX_OVERFLOW; + } + } + } + Wrap_MXC_I2C_SetIntEn(i2c, int_en0, int_en1); +} +#endif /* CONFIG_I2C_TARGET */ + +#ifdef CONFIG_I2C_MAX32_INTERRUPT +static void i2c_max32_isr_controller(const struct device *dev, mxc_i2c_regs_t *i2c) +{ + struct max32_i2c_data *data = dev->data; + mxc_i2c_req_t *req = &data->req; + uint32_t written, readb; + uint32_t txfifolevel; + uint32_t int_fl0, int_fl1; + uint32_t int_en0, int_en1; + + written = data->written; + readb = data->readb; + + Wrap_MXC_I2C_GetIntEn(i2c, &int_en0, &int_en1); + MXC_I2C_GetFlags(i2c, &int_fl0, &int_fl1); + MXC_I2C_ClearFlags(i2c, ADI_MAX32_I2C_INT_FL0_MASK, ADI_MAX32_I2C_INT_FL1_MASK); + txfifolevel = Wrap_MXC_I2C_GetTxFIFOLevel(i2c); + + if (int_fl0 & ADI_MAX32_I2C_INT_FL0_ERR) { + data->err = -EIO; + Wrap_MXC_I2C_SetIntEn(i2c, 0, 0); + k_sem_give(&data->xfer); + return; + } + + if (int_fl0 & ADI_MAX32_I2C_INT_FL0_ADDR_ACK) { + MXC_I2C_DisableInt(i2c, ADI_MAX32_I2C_INT_EN0_ADDR_ACK, 0); + if (written < req->tx_len) { + MXC_I2C_EnableInt(i2c, ADI_MAX32_I2C_INT_EN0_TX_THD, 0); + } else if (readb < req->rx_len) { + MXC_I2C_EnableInt( + i2c, ADI_MAX32_I2C_INT_EN0_RX_THD | ADI_MAX32_I2C_INT_EN0_DONE, 0); + } + } + + if (req->tx_len && + (int_fl0 & (ADI_MAX32_I2C_INT_FL0_TX_THD | ADI_MAX32_I2C_INT_FL0_DONE))) { + if (written < req->tx_len) { + written += MXC_I2C_WriteTXFIFO(i2c, &req->tx_buf[written], + req->tx_len - written); + } else { + if (!(int_en0 & ADI_MAX32_I2C_INT_EN0_DONE)) { + /* We are done, stop sending more data */ + MXC_I2C_DisableInt(i2c, ADI_MAX32_I2C_INT_EN0_TX_THD, 0); + if (data->flags & I2C_MSG_STOP) { + MXC_I2C_EnableInt(i2c, ADI_MAX32_I2C_INT_EN0_DONE, 0); + /* Done flag is not set if stop/restart is not set */ + Wrap_MXC_I2C_Stop(i2c); + } else { + k_sem_give(&data->xfer); + } + } + + if ((int_fl0 & ADI_MAX32_I2C_INT_FL0_DONE)) { + MXC_I2C_DisableInt(i2c, ADI_MAX32_I2C_INT_EN0_DONE, 0); + k_sem_give(&data->xfer); + } + } + } else if ((int_fl0 & (ADI_MAX32_I2C_INT_FL0_RX_THD | ADI_MAX32_I2C_INT_FL0_DONE))) { + readb += MXC_I2C_ReadRXFIFO(i2c, &req->rx_buf[readb], req->rx_len - readb); + if (readb == req->rx_len) { + MXC_I2C_DisableInt(i2c, ADI_MAX32_I2C_INT_EN0_RX_THD, 0); + if (data->flags & I2C_MSG_STOP) { + MXC_I2C_DisableInt(i2c, ADI_MAX32_I2C_INT_EN0_DONE, 0); + Wrap_MXC_I2C_Stop(i2c); + k_sem_give(&data->xfer); + } else { + if (int_fl0 & ADI_MAX32_I2C_INT_FL0_DONE) { + MXC_I2C_DisableInt(i2c, ADI_MAX32_I2C_INT_EN0_DONE, 0); + k_sem_give(&data->xfer); + } + } + } else if ((int_en0 & ADI_MAX32_I2C_INT_EN0_DONE) && + (int_fl0 & ADI_MAX32_I2C_INT_FL0_DONE)) { + MXC_I2C_DisableInt( + i2c, (ADI_MAX32_I2C_INT_EN0_RX_THD | ADI_MAX32_I2C_INT_EN0_DONE), + 0); + Wrap_MXC_I2C_SetRxCount(i2c, req->rx_len - readb); + MXC_I2C_EnableInt(i2c, ADI_MAX32_I2C_INT_EN0_ADDR_ACK, 0); + i2c->fifo = (req->addr << 1) | 0x1; + Wrap_MXC_I2C_Restart(i2c); + } + } + + data->written = written; + data->readb = readb; +} +#endif /* CONFIG_I2C_MAX32_INTERRUPT */ + +#if defined(CONFIG_I2C_TARGET) || defined(CONFIG_I2C_MAX32_INTERRUPT) +static void i2c_max32_isr(const struct device *dev) +{ + const struct max32_i2c_config *cfg = dev->config; + struct max32_i2c_data *data = dev->data; + mxc_i2c_regs_t *i2c = cfg->regs; + +#ifdef CONFIG_I2C_MAX32_INTERRUPT + if (data->target_mode == 0) { + i2c_max32_isr_controller(dev, i2c); + return; + } +#endif /* CONFIG_I2C_MAX32_INTERRUPT */ + +#ifdef CONFIG_I2C_TARGET + if (data->target_mode == 1) { + i2c_max32_isr_target(dev, i2c); + } +#endif +} +#endif /* CONFIG_I2C_TARGET || CONFIG_I2C_MAX32_INTERRUPT */ + +static const struct i2c_driver_api api = { + .configure = api_configure, + .transfer = api_transfer, +#ifdef CONFIG_I2C_TARGET + .target_register = api_target_register, + .target_unregister = api_target_unregister, +#endif + .recover_bus = api_recover_bus, +}; + +static int i2c_max32_init(const struct device *dev) +{ + const struct max32_i2c_config *const cfg = dev->config; + struct max32_i2c_data *data = dev->data; + mxc_i2c_regs_t *i2c = cfg->regs; + int ret = 0; + + if (!device_is_ready(cfg->clock)) { + return -ENODEV; + } + + MXC_I2C_Shutdown(i2c); /* Clear everything out */ + + ret = clock_control_on(cfg->clock, (clock_control_subsys_t)&cfg->perclk); + if (ret) { + return ret; + } + + ret = pinctrl_apply_state(cfg->pctrl, PINCTRL_STATE_DEFAULT); + if (ret) { + return ret; + } + + ret = MXC_I2C_Init(i2c, 1, 0); /* Configure as master */ + if (ret) { + return ret; + } + + MXC_I2C_SetFrequency(i2c, cfg->bitrate); + + k_sem_init(&data->lock, 1, 1); + +#if defined(CONFIG_I2C_TARGET) || defined(CONFIG_I2C_MAX32_INTERRUPT) + cfg->irq_config_func(dev); +#endif + +#ifdef CONFIG_I2C_MAX32_INTERRUPT + irq_enable(cfg->irqn); + + k_sem_init(&data->xfer, 0, 1); +#endif + +#if defined(CONFIG_I2C_TARGET) + data->first_write = true; + data->target_mode = 0; +#endif + data->dev = dev; + + return ret; +} + +#if defined(CONFIG_I2C_TARGET) || defined(CONFIG_I2C_MAX32_INTERRUPT) +#define I2C_MAX32_CONFIG_IRQ_FUNC(n) \ + .irq_config_func = i2c_max32_irq_config_func_##n, .irqn = DT_INST_IRQN(n), + +#define I2C_MAX32_IRQ_CONFIG_FUNC(n) \ + static void i2c_max32_irq_config_func_##n(const struct device *dev) \ + { \ + IRQ_CONNECT(DT_INST_IRQN(n), DT_INST_IRQ(n, priority), i2c_max32_isr, \ + DEVICE_DT_INST_GET(n), 0); \ + } +#else +#define I2C_MAX32_CONFIG_IRQ_FUNC(n) +#define I2C_MAX32_IRQ_CONFIG_FUNC(n) +#endif + +#define DEFINE_I2C_MAX32(_num) \ + PINCTRL_DT_INST_DEFINE(_num); \ + I2C_MAX32_IRQ_CONFIG_FUNC(_num) \ + static const struct max32_i2c_config max32_i2c_dev_cfg_##_num = { \ + .regs = (mxc_i2c_regs_t *)DT_INST_REG_ADDR(_num), \ + .pctrl = PINCTRL_DT_INST_DEV_CONFIG_GET(_num), \ + .clock = DEVICE_DT_GET(DT_INST_CLOCKS_CTLR(_num)), \ + .perclk.bus = DT_INST_CLOCKS_CELL(_num, offset), \ + .perclk.bit = DT_INST_CLOCKS_CELL(_num, bit), \ + .bitrate = DT_INST_PROP(_num, clock_frequency), \ + I2C_MAX32_CONFIG_IRQ_FUNC(_num)}; \ + static struct max32_i2c_data max32_i2c_data_##_num; \ + I2C_DEVICE_DT_INST_DEFINE(_num, i2c_max32_init, NULL, &max32_i2c_data_##_num, \ + &max32_i2c_dev_cfg_##_num, PRE_KERNEL_2, \ + CONFIG_I2C_INIT_PRIORITY, &api); + +DT_INST_FOREACH_STATUS_OKAY(DEFINE_I2C_MAX32) diff --git a/dts/bindings/i2c/adi,max32-i2c.yaml b/dts/bindings/i2c/adi,max32-i2c.yaml new file mode 100644 index 0000000000000..2b1c81de0c70b --- /dev/null +++ b/dts/bindings/i2c/adi,max32-i2c.yaml @@ -0,0 +1,18 @@ +# Copyright (c) 2024 Analog Devices, Inc. +# SPDX-License-Identifier: Apache-2.0 + +description: ADI MAX32 I2C + +compatible: "adi,max32-i2c" + +include: [i2c-controller.yaml, pinctrl-device.yaml] + +properties: + reg: + required: true + + clocks: + required: true + + interrupts: + required: true From f560336812216327365dfe09c4be765259e80a00 Mon Sep 17 00:00:00 2001 From: Furkan Akkiz Date: Wed, 5 Jun 2024 10:35:56 +0300 Subject: [PATCH 1999/2849] boards: adi: max32690evkit: Enable I2C driver Add I2C in list of supported peripherals. Signed-off-by: Furkan Akkiz --- boards/adi/max32690evkit/doc/index.rst | 2 ++ boards/adi/max32690evkit/max32690evkit_max32690_m4.yaml | 1 + 2 files changed, 3 insertions(+) diff --git a/boards/adi/max32690evkit/doc/index.rst b/boards/adi/max32690evkit/doc/index.rst index 5faf8d7ca36ae..7da8592ff4f15 100644 --- a/boards/adi/max32690evkit/doc/index.rst +++ b/boards/adi/max32690evkit/doc/index.rst @@ -111,6 +111,8 @@ Below interfaces are supported by Zephyr on MAX32690EVKIT. +-----------+------------+-------------------------------------+ | SPI | on-chip | spi | +--------------------------------------------------------------+ +| I2C | on-chip | i2c | ++-----------+------------+-------------------------------------+ Connections and IOs diff --git a/boards/adi/max32690evkit/max32690evkit_max32690_m4.yaml b/boards/adi/max32690evkit/max32690evkit_max32690_m4.yaml index 5d24c145e4b0e..38989aa05f724 100644 --- a/boards/adi/max32690evkit/max32690evkit_max32690_m4.yaml +++ b/boards/adi/max32690evkit/max32690evkit_max32690_m4.yaml @@ -10,5 +10,6 @@ supported: - gpio - serial - spi + - i2c ram: 1024 flash: 3072 From 2d44b48cec84e143c2f7772d7ce2b3e637149671 Mon Sep 17 00:00:00 2001 From: Furkan Akkiz Date: Wed, 5 Jun 2024 10:37:26 +0300 Subject: [PATCH 2000/2849] tests: drivers: i2c: i2c_target_api: Add MAX32690EVKIT Enable I2C target API test for MAX32690EVKIT board. Signed-off-by: Furkan Akkiz --- .../boards/max32690evkit_max32690_m4.conf | 4 +++ .../boards/max32690evkit_max32690_m4.overlay | 29 +++++++++++++++++++ 2 files changed, 33 insertions(+) create mode 100644 tests/drivers/i2c/i2c_target_api/boards/max32690evkit_max32690_m4.conf create mode 100644 tests/drivers/i2c/i2c_target_api/boards/max32690evkit_max32690_m4.overlay diff --git a/tests/drivers/i2c/i2c_target_api/boards/max32690evkit_max32690_m4.conf b/tests/drivers/i2c/i2c_target_api/boards/max32690evkit_max32690_m4.conf new file mode 100644 index 0000000000000..c25d2c5d47fb7 --- /dev/null +++ b/tests/drivers/i2c/i2c_target_api/boards/max32690evkit_max32690_m4.conf @@ -0,0 +1,4 @@ +# Copyright (c) 2024 Analog Devices, Inc. +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_I2C_VIRTUAL=n diff --git a/tests/drivers/i2c/i2c_target_api/boards/max32690evkit_max32690_m4.overlay b/tests/drivers/i2c/i2c_target_api/boards/max32690evkit_max32690_m4.overlay new file mode 100644 index 0000000000000..dc62f0be0d217 --- /dev/null +++ b/tests/drivers/i2c/i2c_target_api/boards/max32690evkit_max32690_m4.overlay @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2024 Analog Devices, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&i2c0 { + status = "okay"; + pinctrl-0 = <&i2c0a_scl_p2_8 &i2c0a_sda_p2_7>; + pinctrl-names = "default"; + + eeprom0: eeprom@54 { + compatible = "zephyr,i2c-target-eeprom"; + reg = <0x54>; + size = <1024>; + }; +}; + +&i2c2 { + status = "okay"; + pinctrl-0 = <&i2c2c_scl_p1_8 &i2c2c_sda_p1_7>; + pinctrl-names = "default"; + + eeprom1: eeprom@56 { + compatible = "zephyr,i2c-target-eeprom"; + reg = <0x56>; + size = <1024>; + }; +}; From 28ed877f534135a61e3c59f668ba31c7af2357e1 Mon Sep 17 00:00:00 2001 From: Gerard Marull-Paretas Date: Tue, 12 Mar 2024 12:03:16 +0100 Subject: [PATCH 2001/2849] boards: nordic: nrf54h20dk: add custom JLink reset scheme A custom reset scheme is required for the nRF54H20 SoC so that debug works out of the box. This magic will eventually be part of JLink. Signed-off-by: Gerard Marull-Paretas --- boards/nordic/nrf54h20dk/board.cmake | 11 ++-- .../support/nrf54h20_cpuapp.JLinkScript | 41 +++++++++++++++ .../support/nrf54h20_cpurad.JLinkScript | 50 +++++++++++++++++-- 3 files changed, 93 insertions(+), 9 deletions(-) create mode 100644 boards/nordic/nrf54h20dk/support/nrf54h20_cpuapp.JLinkScript diff --git a/boards/nordic/nrf54h20dk/board.cmake b/boards/nordic/nrf54h20dk/board.cmake index 6361f7fe7b4a0..0c8376c1714e1 100644 --- a/boards/nordic/nrf54h20dk/board.cmake +++ b/boards/nordic/nrf54h20dk/board.cmake @@ -3,13 +3,12 @@ include(${ZEPHYR_BASE}/boards/common/nrfutil.board.cmake) if(CONFIG_BOARD_NRF54H20DK_NRF54H20_CPUAPP OR CONFIG_BOARD_NRF54H20DK_NRF54H20_CPURAD) - if(CONFIG_BOARD_NRF54H20DK_NRF54H20_CPURAD) - set( - JLINK_TOOL_OPT - "-jlinkscriptfile ${CMAKE_CURRENT_LIST_DIR}/support/nrf54h20_cpurad.JLinkScript" - ) + if(CONFIG_BOARD_NRF54H20DK_NRF54H20_CPUAPP) + set(JLINKSCRIPTFILE ${CMAKE_CURRENT_LIST_DIR}/support/nrf54h20_cpuapp.JLinkScript) + else() + set(JLINKSCRIPTFILE ${CMAKE_CURRENT_LIST_DIR}/support/nrf54h20_cpurad.JLinkScript) endif() - board_runner_args(jlink "--device=CORTEX-M33" "--speed=4000" "--tool-opt=${JLINK_TOOL_OPT}") + board_runner_args(jlink "--device=CORTEX-M33" "--speed=4000" "--tool-opt=-jlinkscriptfile ${JLINKSCRIPTFILE}") include(${ZEPHYR_BASE}/boards/common/jlink.board.cmake) endif() diff --git a/boards/nordic/nrf54h20dk/support/nrf54h20_cpuapp.JLinkScript b/boards/nordic/nrf54h20dk/support/nrf54h20_cpuapp.JLinkScript new file mode 100644 index 0000000000000..ffa1beed1ed65 --- /dev/null +++ b/boards/nordic/nrf54h20dk/support/nrf54h20_cpuapp.JLinkScript @@ -0,0 +1,41 @@ +// Debug Halting Control and Status Register +__constant U32 _DHCSR_ADDR = 0xE000EDF0; +__constant U32 _DHCSR_DBGKEY = (0xA05F << 16); +__constant U32 _DHCSR_C_DEBUGEN = (1 << 0); +__constant U32 _DHCSR_C_HALT = (1 << 1); + +// Debug Exception and Monitor Control Register +__constant U32 _DEMCR_ADDR = 0xE000EDFC; +__constant U32 _DEMCR_VC_CORERESET = (1 << 0); +__constant U32 _DEMCR_TRCENA = (1 << 24); + +// CPU wait enable register +__constant U32 _CPUCONF_CPUWAIT_ADDR = 0x5201150C; + +int ResetTarget(void) { + // ADAC reset + JLINK_CORESIGHT_WriteDP(2, 0x04000010); + JLINK_CORESIGHT_WriteAP(0, 0xA3030000); + JLINK_CORESIGHT_WriteAP(0, 0x00000004); + JLINK_CORESIGHT_WriteAP(0, 0x01020000); + + JLINK_SYS_Sleep(100); + JLINK_CORESIGHT_ReadAP(2); + JLINK_CORESIGHT_ReadAP(2); + JLINK_CORESIGHT_ReadAP(2); + JLINK_CORESIGHT_ReadAP(2); + + // Halt the CPU + JLINK_MEM_WriteU32(_DHCSR_ADDR, (_DHCSR_DBGKEY | _DHCSR_C_HALT | _DHCSR_C_DEBUGEN)); + + // Set vector catch on reset (to halt the CPU immediately after reset) + JLINK_MEM_WriteU32(_DEMCR_ADDR, (_DEMCR_VC_CORERESET | _DEMCR_TRCENA)); + + // Disable CPU wait + JLINK_MEM_WriteU32(_CPUCONF_CPUWAIT_ADDR, 0); + + // Clear vector catch stuff + JLINK_MEM_WriteU32(_DEMCR_ADDR, _DEMCR_TRCENA); + + return 0; +} diff --git a/boards/nordic/nrf54h20dk/support/nrf54h20_cpurad.JLinkScript b/boards/nordic/nrf54h20dk/support/nrf54h20_cpurad.JLinkScript index 2fb7e32302e23..2f1802801c11c 100644 --- a/boards/nordic/nrf54h20dk/support/nrf54h20_cpurad.JLinkScript +++ b/boards/nordic/nrf54h20dk/support/nrf54h20_cpurad.JLinkScript @@ -1,4 +1,48 @@ -void ConfigTargetSettings(void) { - JLINK_ExecCommand("CORESIGHT_AddAP = Index=1 Type=AHB-AP"); - CORESIGHT_IndexAHBAPToUse = 1; +// Debug Halting Control and Status Register +__constant U32 _DHCSR_ADDR = 0xE000EDF0; +__constant U32 _DHCSR_DBGKEY = (0xA05F << 16); +__constant U32 _DHCSR_C_DEBUGEN = (1 << 0); +__constant U32 _DHCSR_C_HALT = (1 << 1); + +// Debug Exception and Monitor Control Register +__constant U32 _DEMCR_ADDR = 0xE000EDFC; +__constant U32 _DEMCR_VC_CORERESET = (1 << 0); +__constant U32 _DEMCR_TRCENA = (1 << 24); + +// CPU wait enable register +__constant U32 _CPUCONF_CPUWAIT_ADDR = 0x5301150C; + +int ConfigTargetSettings(void) { + JLINK_ExecCommand("CORESIGHT_AddAP = Index=1 Type=AHB-AP"); + CORESIGHT_IndexAHBAPToUse = 1; + + return 0; +} + +int ResetTarget(void) { + // ADAC reset + JLINK_CORESIGHT_WriteDP(2, 0x04000010); + JLINK_CORESIGHT_WriteAP(0, 0xA3030000); + JLINK_CORESIGHT_WriteAP(0, 0x00000004); + JLINK_CORESIGHT_WriteAP(0, 0x01030000); + + JLINK_SYS_Sleep(100); + JLINK_CORESIGHT_ReadAP(2); + JLINK_CORESIGHT_ReadAP(2); + JLINK_CORESIGHT_ReadAP(2); + JLINK_CORESIGHT_ReadAP(2); + + // Halt the CPU + JLINK_MEM_WriteU32(_DHCSR_ADDR, (_DHCSR_DBGKEY | _DHCSR_C_HALT | _DHCSR_C_DEBUGEN)); + + // Set vector catch on reset (to halt the CPU immediately after reset) + JLINK_MEM_WriteU32(_DEMCR_ADDR, (_DEMCR_VC_CORERESET | _DEMCR_TRCENA)); + + // Disable CPU wait + JLINK_MEM_WriteU32(_CPUCONF_CPUWAIT_ADDR, 0); + + // Clear vector catch stuff + JLINK_MEM_WriteU32(_DEMCR_ADDR, _DEMCR_TRCENA); + + return 0; } From 7a5f2ad46e75f751c8746da59303518d12eefc14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20G=C5=82=C4=85b?= Date: Thu, 6 Jun 2024 11:54:22 +0200 Subject: [PATCH 2002/2849] samples: drivers: adc: Add nrf54l15 to platform_allow MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Enable execution of ADC driver tests on nrf54l15. Overlay file for nrf54l15 already exists. Signed-off-by: Sebastian Głąb --- samples/drivers/adc/adc_dt/sample.yaml | 1 + samples/drivers/adc/adc_sequence/sample.yaml | 1 + 2 files changed, 2 insertions(+) diff --git a/samples/drivers/adc/adc_dt/sample.yaml b/samples/drivers/adc/adc_dt/sample.yaml index 2096ad78eb9b4..c758d27e3ad94 100644 --- a/samples/drivers/adc/adc_dt/sample.yaml +++ b/samples/drivers/adc/adc_dt/sample.yaml @@ -15,6 +15,7 @@ tests: - stm32h735g_disco - nrf51dk/nrf51822 - nrf52840dk/nrf52840 + - nrf54l15pdk/nrf54l15/cpuapp - mec172xevb_assy6906 - gd32f350r_eval - gd32f450i_eval diff --git a/samples/drivers/adc/adc_sequence/sample.yaml b/samples/drivers/adc/adc_sequence/sample.yaml index 5f6436c076d69..5afd54ead3a29 100644 --- a/samples/drivers/adc/adc_sequence/sample.yaml +++ b/samples/drivers/adc/adc_sequence/sample.yaml @@ -9,6 +9,7 @@ tests: - cy8cproto_063_ble - cy8cproto_062_4343w - nrf52840dk/nrf52840 + - nrf54l15pdk/nrf54l15/cpuapp integration_platforms: - nrf52840dk/nrf52840 harness: console From 9e2c7731377c99f5c2eb3b8889886e82e213963c Mon Sep 17 00:00:00 2001 From: Gustavo Silva Date: Sat, 13 Jan 2024 19:36:49 -0300 Subject: [PATCH 2003/2849] doc: improvements to Contribution Guidelines Restructure the Contribution Guidelines page in the documentation. Create the 'Pull Request Guidelines' section containing the best practices for creating Pull Requests. Improve commit message guidelines: instruct contributors to refer to GitHub issue in the PR message instead of commit message when submitting a fix; add a description of `Link:` tags for refering to other relevant information. Move 'clang-format' and 'twister' subsections to the new PR Guidelines section. Delete outdated/incorrect information about how to run tests locally with twister. Describe the `check_compliance.py` script as the recommended tool for checking compliance of changes and how to run the script locally. Remove 'gitlint' subsection. Add a list of recommended steps for getting a new PR accepted quickly. Signed-off-by: Gustavo Silva --- doc/contribute/guidelines.rst | 537 ++++++++++++++++++---------------- 1 file changed, 288 insertions(+), 249 deletions(-) diff --git a/doc/contribute/guidelines.rst b/doc/contribute/guidelines.rst index 564deb0741896..5f31f6422e166 100644 --- a/doc/contribute/guidelines.rst +++ b/doc/contribute/guidelines.rst @@ -148,6 +148,8 @@ For your commits, replace: You can automatically add the Signed-off-by: line to your commit body using ``git commit -s``. Use other commits in the zephyr git history as examples. +See :ref:`git_setup` for instructions on configuring user and email settings +in Git. Additional requirements: @@ -331,16 +333,10 @@ business days. You can find all `open pull requests`_ on GitHub and open `Zephyr Project Issues`_ in Github issues. - .. _Continuous Integration: +.. _git_setup: - -Tools and Git Setup -******************* - -.. _git-name-and-email: - -Name and email -============== +Git Setup +********* We need to know who you are, and how to contact you. To add this information to your Git installation, set the Git configuration @@ -355,93 +351,181 @@ address is ``z.developer@example.com``: git config --global user.name "Zephyr Developer" git config --global user.email "z.developer@example.com" -gitlint -========= -When you submit a pull request to the project, a series of checks are -performed to verify your commit messages meet the requirements. The same step -done during the CI process can be performed locally using the ``gitlint`` -command. +Pull Request Guidelines +*********************** +When opening a new Pull Request, adhere to the following guidelines to ensure +compliance with Zephyr standards and facilitate the review process. -Run ``gitlint`` locally in your tree and branch where your patches have been -committed: +If in doubt, it's advisible to explore existing Pull Requests within the Zephyr +repository. Use the search filters and labels to locate PRs related to changes +similar to the ones you are proposing. -.. code-block:: console +.. _commit-guidelines: - gitlint +Commit Message Guidelines +========================= -Note, gitlint only checks HEAD (the most recent commit), so you should run it -after each commit, or use the ``--commits`` option to specify a commit range -covering all the development patches to be submitted. +Changes are submitted as Git commits. Each commit has a *commit +message* describing the change. Acceptable commit messages look like +this: -twister -======= +.. code-block:: none -.. note:: - twister support on windows is limited and execution of tests is not - supported, only building. + [area]: [summary of change] -To verify that your changes did not break any tests or samples, please run the -``twister`` script locally before submitting your pull request to GitHub. + [Commit message body (must be non-empty)] -Twister allows limiting the scope of the tests built and run by pointing it to -the tests related to the code or the platform you have modified. For example, to -limit tests to a single platform and an area in the kernel:: + Signed-off-by: [Your Full Name] <[your.email@address]> - source zephyr-env.sh - west twister -p qemu_x86 -T tests/kernel/sched +You need to change text in square brackets (``[like this]``) above to +fit your commit. -Running tests on connected devices is also supported using the -``--device-testing`` options. Please consult with the :ref:`Twister -` documentation for more details. +Examples and more details follow. -To run the same tests the CI system runs, follow these steps from within your -local Zephyr source working directory: +Example +------- -.. code-block:: console +Here is an example of a good commit message. - source zephyr-env.sh - west twister --integration +.. code-block:: none -The above will execute the basic twister script, which will run various -tests using the QEMU emulator and other simulators supported in Zephyr. -It will also do some build tests on various samples with advanced features that -can't run in a simulator or QEMU. + drivers: sensor: abcd1234: fix bus I/O error handling -We highly recommend you run these tests locally to avoid any CI failures -However, note that building and executing tests using twister requires -significant computing resources. When running locally and to get results in a -reasonable time, limit the scope to the areas and platforms you have modified. -In case of major changes to the kernel, build or configuration infrastructures -of Zephyr, it is advised to use twister for verifying majority the changes -before handing over to the dedicated CI resources provided by the Zephyr -project. + The abcd1234 sensor driver is failing to check the flags field in + the response packet from the device which signals that an error + occurred. This can lead to reading invalid data from the response + buffer. Fix it by checking the flag and adding an error path. -clang-format -============ + Signed-off-by: Zephyr Developer -The `clang-format tool `_ can -be helpful to quickly reformat large amounts of new source code to our -`Coding Style`_ standards together with the ``.clang-format`` configuration file -provided in the repository. ``clang-format`` is well integrated into most -editors, but you can also run it manually like this: +[area]: [summary of change] +--------------------------- -.. code-block:: bash +This line is called the commit's *title*. Titles must be: - clang-format -i my_source_file.c +* one line +* less than 72 characters long +* followed by a completely blank line -``clang-format`` is part of LLVM, which can be downloaded from the project -`releases page `. Note that if -you are a Linux user, ``clang-format`` will likely be available as a package in -your distribution repositories. +[area] + The ``[area]`` prefix usually identifies the area of code + being changed. It can also identify the change's wider + context if multiple areas are affected. + + Here are some examples: + + * ``doc: ...`` for documentation changes + * ``drivers: foo:`` for ``foo`` driver changes + * ``Bluetooth: Shell:`` for changes to the Bluetooth shell + * ``net: ethernet:`` for Ethernet-related networking changes + * ``dts:`` for treewide devicetree changes + * ``style:`` for code style changes + + If you're not sure what to use, try running ``git log FILE``, where + ``FILE`` is a file you are changing, and using previous commits that + changed the same file as inspiration. + +[summary of change] + The ``[summary of change]`` part should be a quick description of + what you've done. Here are some examples: + + * ``doc: update wiki references to new site`` + * ``drivers: sensor: sensor_shell: fix channel name collision`` + +Commit Message Body +------------------- + +.. warning:: + + An empty commit message body is not permitted. Even for trivial + changes, please include a descriptive commit message body. Your + pull request will fail CI checks if you do not. + +This part of the commit should explain what your change does, and why +it's needed. Be specific. A body that says ``"Fixes stuff"`` will be +rejected. Be sure to include the following as relevant: + +* **what** the change does, +* **why** you chose that approach, +* **what** assumptions were made, and +* **how** you know it works -- for example, which tests you ran. + +Each line in your commit message should usually be 75 characters or +less. Use newlines to wrap longer lines. Exceptions include lines +with long URLs, email addresses, etc. + +For examples of accepted commit messages, you can refer to the Zephyr GitHub +`changelog `__. + + +Signed-off-by: ... +------------------ + +.. tip:: + + You should have set your :ref:`git_setup` + already. Create your commit with ``git commit -s`` to add the + Signed-off-by: line automatically using this information. + +For open source licensing reasons, your commit must include a +Signed-off-by: line that looks like this: + +.. code-block:: none + + Signed-off-by: [Your Full Name] <[your.email@address]> + +For example, if your full name is ``Zephyr Developer`` and your email +address is ``z.developer@example.com``: + +.. code-block:: none + + Signed-off-by: Zephyr Developer + +This means that you have personally made sure your change complies +with the :ref:`DCO`. For this reason, you must use your legal name. +Pseudonyms or "hacker aliases" are not permitted. + +Your name and the email address you use must match the name and email +in the Git commit's ``Author:`` field. + +See the :ref:`contributor-expectations` for a more complete discussion of +contributor and reviewer expectations. + +Adding links +------------ + +.. _GitHub references: + https://docs.github.com/en/get-started/writing-on-github/working-with-advanced-formatting/autolinked-references-and-urls + +Do not include `GitHub references`_ in the commit message directly, as it can +lose meaning in case the repository is forked, for example. Instead, if the +change addresses a specific GitHub issue, include in the Pull Request message a +line of the form: + +.. code-block:: none + + Fixes #[issue number] + +Where ``[issue number]`` is the relevant GitHub issue's number. For +example: + +.. code-block:: none + + Fixes: #1234 + +You can point to other relevant information that can be found on the web using +:code:`Link:` tags. This includes, for example: GitHub issues, datasheets, +reference manuals, etc. + +.. code-block:: none + + Link: https://github.com/zephyrproject-rtos/zephyr/issues/ .. _coding_style: Coding Style -************ - -Use these coding guidelines to ensure that your development complies with the -project's style and naming conventions. +============ .. _Linux kernel coding style: https://kernel.org/doc/html/latest/process/coding-style.html @@ -462,8 +546,8 @@ exceptions: * Avoid using non-ASCII symbols in code, unless it significantly improves clarity, avoid emojis in any case. -When there are differences between the guidelines above and the formatting -generated by code formatting tools, the guidelines above take precedence. +Use these coding guidelines to ensure that your development complies with the +project's style and naming conventions. The Linux kernel GPL-licensed tool ``checkpatch`` is used to check coding style conformity. @@ -506,8 +590,102 @@ before pushing on zephyr repo. To do this, make the file If you want to override checkpatch verdict and push you branch despite reported issues, you can add option --no-verify to the git push command. -A more complete alternative to this is using check_compliance.py script from -ci-tools repo. +A more complete alternative to this is using :ref:`check_compliance_py` script. + +clang-format +------------ + +The `clang-format tool `_ can +be helpful to quickly reformat large amounts of new source code to our +`Coding Style`_ standards together with the ``.clang-format`` configuration file +provided in the repository. ``clang-format`` is well integrated into most +editors, but you can also run it manually like this: + +.. code-block:: bash + + clang-format -i my_source_file.c + +``clang-format`` is part of LLVM, which can be downloaded from the project +`releases page `_. Note that if +you are a Linux user, ``clang-format`` will likely be available as a package in +your distribution repositories. + +When there are differences between the `Coding Style`_ guidelines and the +formatting generated by code formatting tools, the `Coding Style`_ guidelines +take precedence. If there is ambiguity between formatting tools and the +guidelines, maintainers may decide which style should be adopted. + +.. _Continuous Integration: + +Continuous Integration (CI) +=========================== + +The Zephyr Project operates a Continuous Integration (CI) system that runs on +every Pull Request (PR) in order to verify several aspects of the PR: + +* Git commit formatting +* Coding Style +* Twister builds for multiple architectures and boards +* Documentation build to verify any doc changes + +CI is run on Github Actions and it uses the same tools described in the +`CI Tests`_ section. The CI results must be green indicating "All +checks have passed" before the Pull Request can be merged. CI is run when the +PR is created, and again every time the PR is modified with a commit. + +The current status of the CI run can always be found at the bottom of the +GitHub PR page, below the review status. Depending on the success or failure +of the run you will see: + +* "All checks have passed" +* "All checks have failed" + +In case of failure you can click on the "Details" link presented below the +failure message in order to navigate to ``Github Actions`` and inspect the +results. +Once you click on the link you will be taken to the ``Github actions`` summary +results page where a table with all the different builds will be shown. To see +what build or test failed click on the row that contains the failed (i.e. +non-green) build. + +.. _CI Tests: + +Running CI Tests Locally +======================== + +.. _check_compliance_py: + +check_compliance.py +------------------- + +The ``check_compliance.py`` script serves as a valuable tool for assessing code +compliance with Zephyr's established guidelines and best practices. The script +acts as wrapper for a suite of tools that performs various checks, including +linters and formatters. + +Developers are encouraged to run the script locally to validate their changes +before opening a new Pull Request: + +.. code-block:: bash + + ./scripts/ci/check_compliance.py -c upstream/main.. + +twister +------- + +.. note:: + twister is only fully supported on Linux; on Windows and MacOS the execution + of tests is not supported, only building. + +If you think your change may break some test, you can submit your PR as a draft +and let the project CI automatically run the :ref:`twister_script` for you. + +If a test fails, you can check from the CI run logs how to rerun it locally, +for example: + +.. code-block:: bash + + west twister -p native_sim -s tests/drivers/build_all/sensor/sensors.generic_test .. _static_analysis: @@ -560,8 +738,6 @@ it after completing the steps above on scan service website. Any issues closed without a fix or without ignoring the entry in the scan service will be automatically reopened if the issue continues to be present in the code. -.. _Contribution Tools: - .. _Contribution workflow: Contribution Workflow @@ -687,13 +863,7 @@ workflow here: and use the same process described above to work on this new topic branch. #. If reviewers do request changes to your patch, you can interactively rebase - commit(s) to fix review issues. In your development repo:: - - git fetch --all - git rebase --ignore-whitespace upstream/main - - The ``--ignore-whitespace`` option stops ``git apply`` (called by rebase) - from changing any whitespace. Continuing:: + commit(s) to fix review issues. In your development repo:: git rebase -i ^ @@ -715,6 +885,17 @@ workflow here: By force pushing your update, your original pull request will be updated with your changes so you won't need to resubmit the pull request. +#. After pushing the requested change, check on the PR page if there is a + merge conflict. If so, rebase your local branch:: + + git fetch --all + git rebase --ignore-whitespace upstream/main + + The ``--ignore-whitespace`` option stops ``git apply`` (called by rebase) + from changing any whitespace. Resolve the conflicts and push again:: + + git push --force origin fix_comment_typo + .. note:: While amending commits and force pushing is a common review model outside GitHub, and the one recommended by Zephyr, it's not the main model supported by GitHub. Forced pushes can cause unexpected behavior, @@ -729,151 +910,41 @@ workflow here: Additional information about the CI system can be found in `Continuous Integration`_. -.. _commit-guidelines: - -Commit Message Guidelines -************************* - -Changes are submitted as Git commits. Each commit has a *commit -message* describing the change. Acceptable commit messages look like -this: - -.. code-block:: none - - [area]: [summary of change] - - [Commit message body (must be non-empty)] - - Signed-off-by: [Your Full Name] <[your.email@address]> - -You need to change text in square brackets (``[like this]``) above to -fit your commit. - -Examples and more details follow. - -Example -======= - -Here is an example of a good commit message. - -.. code-block:: none - - drivers: sensor: abcd1234: fix bus I/O error handling - - The abcd1234 sensor driver is failing to check the flags field in - the response packet from the device which signals that an error - occurred. This can lead to reading invalid data from the response - buffer. Fix it by checking the flag and adding an error path. +.. _contribution_tips: - Signed-off-by: Zephyr Developer +Contribution Tips +================= -[area]: [summary of change] -=========================== +The following is a list of tips to improve and accelerate the review process of +Pull Requests. If you follow them, chances are your pull request will get the +attention needed and it will be ready for merge sooner than later: -This line is called the commit's *title*. Titles must be: +.. _git-rebase: + https://git-scm.com/docs/git-rebase#Documentation/git-rebase.txt---keep-base -* one line -* less than 72 characters long -* followed by a completely blank line +#. When pushing follow-up changes, use the ``--keep-base`` option of + `git-rebase`_ -[area] - The ``[area]`` prefix usually identifies the area of code - being changed. It can also identify the change's wider - context if multiple areas are affected. +#. On the PR page, check if the change can still be merged with no merge + conflicts - Here are some examples: +#. Make sure title of PR explains what is being fixed or added - * ``doc: ...`` for documentation changes - * ``drivers: foo:`` for ``foo`` driver changes - * ``Bluetooth: Shell:`` for changes to the Bluetooth shell - * ``net: ethernet:`` for Ethernet-related networking changes - * ``dts:`` for treewide devicetree changes - * ``style:`` for code style changes +#. Make sure your PR has a body with more details about the content of your + submission - If you're not sure what to use, try running ``git log FILE``, where - ``FILE`` is a file you are changing, and using previous commits that - changed the same file as inspiration. +#. Make sure you reference the issue you are fixing in the body of the PR -[summary of change] - The ``[summary of change]`` part should be a quick description of - what you've done. Here are some examples: +#. Watch early CI results immediately after submissions and fix issues as they + are discovered - * ``doc: update wiki references to new site`` - * ``drivers: sensor: sensor_shell: fix channel name collision`` +#. Revisit PR after 1-2 hours to see the status of all CI checks, make sure all + is green -Commit Message Body -=================== +#. If you get request for changes and submit a change to address them, make + sure you click the "Re-request review" button on the GitHub UI to notify + those who asked for the changes -.. warning:: - - An empty commit message body is not permitted. Even for trivial - changes, please include a descriptive commit message body. Your - pull request will fail CI checks if you do not. - -This part of the commit should explain what your change does, and why -it's needed. Be specific. A body that says ``"Fixes stuff"`` will be -rejected. Be sure to include the following as relevant: - -* **what** the change does, -* **why** you chose that approach, -* **what** assumptions were made, and -* **how** you know it works -- for example, which tests you ran. - -Each line in your commit message should usually be 75 characters or -less. Use newlines to wrap longer lines. Exceptions include lines -with long URLs, email addresses, etc. - -For examples of accepted commit messages, you can refer to the Zephyr GitHub -`changelog `__. - -If the change addresses a GitHub issue, include a line of the form: - -.. code-block:: none - - Fixes #[issue number] - -Where ``[issue number]`` is the relevant GitHub issue's number. For -example: - -.. code-block:: none - - Fixes: #1234 - -Signed-off-by: ... -================== - -.. tip:: - - You should have set your :ref:`git-name-and-email` - already. Create your commit with ``git commit -s`` to add the - Signed-off-by: line automatically using this information. - -For open source licensing reasons, your commit must include a -Signed-off-by: line that looks like this: - -.. code-block:: none - - Signed-off-by: [Your Full Name] <[your.email@address]> - -For example, if your full name is ``Zephyr Developer`` and your email -address is ``z.developer@example.com``: - -.. code-block:: none - - Signed-off-by: Zephyr Developer - -This means that you have personally made sure your change complies -with the :ref:`DCO`. For this reason, you must use your legal name. -Pseudonyms or "hacker aliases" are not permitted. - -Your name and the email address you use must match the name and email -in the Git commit's ``Author:`` field. - -Other Commit Expectations -========================= - -See the :ref:`contributor-expectations` for a more complete discussion of -contributor and reviewer expectations. Submitting Proposals ==================== @@ -930,38 +1001,6 @@ For example, a copy of an externally maintained import in a module repository:: commit: 08ded7f21529c39e5133688ffb93a9d0c94e5c6e Purpose: Introduction of TinyCrypt - -Continuous Integration (CI) -*************************** - -The Zephyr Project operates a Continuous Integration (CI) system that runs on -every Pull Request (PR) in order to verify several aspects of the PR: - -* Git commit formatting -* Coding Style -* Twister builds for multiple architectures and boards -* Documentation build to verify any doc changes - -CI is run on Github Actions and it uses the same tools described in the -`Contribution Tools`_ section. The CI results must be green indicating "All -checks have passed" before the Pull Request can be merged. CI is run when the -PR is created, and again every time the PR is modified with a commit. - -The current status of the CI run can always be found at the bottom of the -GitHub PR page, below the review status. Depending on the success or failure -of the run you will see: - -* "All checks have passed" -* "All checks have failed" - -In case of failure you can click on the "Details" link presented below the -failure message in order to navigate to ``Github Actions`` and inspect the -results. -Once you click on the link you will be taken to the ``Github actions`` summary -results page where a table with all the different builds will be shown. To see -what build or test failed click on the row that contains the failed (i.e. -non-green) build. - Contributions to External Modules ********************************** From 0b327db0976737871167fb92363c1a9df25a8c4e Mon Sep 17 00:00:00 2001 From: Sean Madigan Date: Tue, 4 Jun 2024 10:33:43 +0100 Subject: [PATCH 2004/2849] Bluetooth: Add support for Path Loss Monitoring feature This commit adds host support for the Path Loss Monitoring feature see Bluetooth Core specification, Version 5.4, Vol 6, Part B, Section 4.6.32. Limited logic is required, just adding a wrapper around the HCI command and callback for HCI event. Add new zone - BT_CONN_LE_PATH_LOSS_ZONE_UNAVAILABLE, to convert 0xFF path loss to a useful zone. Add new Kconfigs and functionality to the bt shell. Signed-off-by: Sean Madigan --- include/zephyr/bluetooth/conn.h | 93 ++++++++++++++++++++++++ include/zephyr/bluetooth/hci_types.h | 32 +++++++++ subsys/bluetooth/Kconfig | 7 ++ subsys/bluetooth/controller/Kconfig | 12 ++++ subsys/bluetooth/host/conn.c | 59 +++++++++++++++ subsys/bluetooth/host/conn_internal.h | 3 + subsys/bluetooth/host/hci_core.c | 44 ++++++++++++ subsys/bluetooth/shell/bt.c | 100 ++++++++++++++++++++++++++ 8 files changed, 350 insertions(+) diff --git a/include/zephyr/bluetooth/conn.h b/include/zephyr/bluetooth/conn.h index ca8a7bb3fb941..402dc3019db5b 100644 --- a/include/zephyr/bluetooth/conn.h +++ b/include/zephyr/bluetooth/conn.h @@ -515,6 +515,57 @@ struct bt_conn_le_tx_power_report { int8_t delta; }; +/** @brief Path Loss zone that has been entered. + * + * The path loss zone that has been entered in the most recent LE Path Loss Monitoring + * Threshold Change event as documented in Core Spec. Version 5.4 Vol.4, Part E, 7.7.65.32. + * + * @note BT_CONN_LE_PATH_LOSS_ZONE_UNAVAILABLE has been added to notify when path loss becomes + * unavailable. + */ +enum bt_conn_le_path_loss_zone { + /** Low path loss zone entered. */ + BT_CONN_LE_PATH_LOSS_ZONE_ENTERED_LOW, + /** Middle path loss zone entered. */ + BT_CONN_LE_PATH_LOSS_ZONE_ENTERED_MIDDLE, + /** High path loss zone entered. */ + BT_CONN_LE_PATH_LOSS_ZONE_ENTERED_HIGH, + /** Path loss has become unavailable. */ + BT_CONN_LE_PATH_LOSS_ZONE_UNAVAILABLE, +}; + +BUILD_ASSERT(BT_CONN_LE_PATH_LOSS_ZONE_ENTERED_LOW == BT_HCI_LE_ZONE_ENTERED_LOW); +BUILD_ASSERT(BT_CONN_LE_PATH_LOSS_ZONE_ENTERED_MIDDLE == BT_HCI_LE_ZONE_ENTERED_MIDDLE); +BUILD_ASSERT(BT_CONN_LE_PATH_LOSS_ZONE_ENTERED_HIGH == BT_HCI_LE_ZONE_ENTERED_HIGH); + +/** @brief LE Path Loss Monitoring Threshold Change Report Structure. */ +struct bt_conn_le_path_loss_threshold_report { + + /** Path Loss zone as documented in Core Spec. Version 5.4 Vol.4, Part E, 7.7.65.32. */ + enum bt_conn_le_path_loss_zone zone; + + /** Current path loss (dB). */ + uint8_t path_loss; +}; + +/** @brief LE Path Loss Monitoring Parameters Structure as defined in Core Spec. Version 5.4 + * Vol.4, Part E, 7.8.119 LE Set Path Loss Reporting Parameters command. + */ +struct bt_conn_le_path_loss_reporting_param { + /** High threshold for the path loss (dB). */ + uint8_t high_threshold; + /** Hysteresis value for the high threshold (dB). */ + uint8_t high_hysteresis; + /** Low threshold for the path loss (dB). */ + uint8_t low_threshold; + /** Hysteresis value for the low threshold (dB). */ + uint8_t low_hysteresis; + /** Minimum time in number of connection events to be observed once the + * path loss crosses the threshold before an event is generated. + */ + uint16_t min_time_spent; +}; + /** @brief Passkey Keypress Notification type * * The numeric values are the same as in the Core specification for Pairing @@ -601,6 +652,34 @@ int bt_conn_le_set_tx_power_report_enable(struct bt_conn *conn, bool local_enable, bool remote_enable); +/** @brief Set Path Loss Monitoring Parameters. + * + * Change the configuration for path loss threshold change events for a given conn handle. + * + * @note To use this API @kconfig{CONFIG_BT_PATH_LOSS_MONITORING} must be set. + * + * @param conn Connection object. + * @param param Path Loss Monitoring parameters + * + * @return Zero on success or (negative) error code on failure. + */ +int bt_conn_le_set_path_loss_mon_param(struct bt_conn *conn, + const struct bt_conn_le_path_loss_reporting_param *param); + +/** @brief Enable or Disable Path Loss Monitoring. + * + * Enable or disable Path Loss Monitoring, which will decide whether Path Loss Threshold events + * are sent from the controller to the host. + * + * @note To use this API @kconfig{CONFIG_BT_PATH_LOSS_MONITORING} must be set. + * + * @param conn Connection Object. + * @param enable Enable/disable path loss reporting. + * + * @return Zero on success or (negative) error code on failure. + */ +int bt_conn_le_set_path_loss_mon_enable(struct bt_conn *conn, bool enable); + /** @brief Update the connection parameters. * * If the local device is in the peripheral role then updating the connection @@ -1154,6 +1233,20 @@ struct bt_conn_cb { const struct bt_conn_le_tx_power_report *report); #endif /* CONFIG_BT_TRANSMIT_POWER_CONTROL */ +#if defined(CONFIG_BT_PATH_LOSS_MONITORING) + /** @brief LE Path Loss Threshold event. + * + * This callback notifies the application that there has been a path loss threshold + * crossing or reporting the initial path loss threshold zone after using + * @ref bt_conn_le_set_path_loss_mon_enable. + * + * @param conn Connection object. + * @param report Path loss threshold report. + */ + void (*path_loss_threshold_report)(struct bt_conn *conn, + const struct bt_conn_le_path_loss_threshold_report *report); +#endif /* CONFIG_BT_PATH_LOSS_MONITORING */ + struct bt_conn_cb *_next; }; diff --git a/include/zephyr/bluetooth/hci_types.h b/include/zephyr/bluetooth/hci_types.h index 2e91eda5c13c8..980aba1c9ab74 100644 --- a/include/zephyr/bluetooth/hci_types.h +++ b/include/zephyr/bluetooth/hci_types.h @@ -675,6 +675,26 @@ struct bt_hci_cp_le_set_tx_power_report_enable { uint8_t remote_enable; } __packed; +struct bt_hci_cp_le_set_path_loss_reporting_parameters { + uint16_t handle; + uint8_t high_threshold; + uint8_t high_hysteresis; + uint8_t low_threshold; + uint8_t low_hysteresis; + uint16_t min_time_spent; +} __packed; + +struct bt_hci_cp_le_set_path_loss_reporting_enable { + uint16_t handle; + uint8_t enable; +} __packed; + +#define BT_HCI_OP_LE_SET_PATH_LOSS_REPORTING_PARAMETERS BT_OP(BT_OGF_LE, 0x0078) /* 0x2078 */ + +#define BT_HCI_LE_PATH_LOSS_REPORTING_DISABLE 0x00 +#define BT_HCI_LE_PATH_LOSS_REPORTING_ENABLE 0x01 +#define BT_HCI_OP_LE_SET_PATH_LOSS_REPORTING_ENABLE BT_OP(BT_OGF_LE, 0x0079) /* 0x2079 */ + #define BT_HCI_CTL_TO_HOST_FLOW_DISABLE 0x00 #define BT_HCI_CTL_TO_HOST_FLOW_ENABLE 0x01 #define BT_HCI_OP_SET_CTL_TO_HOST_FLOW BT_OP(BT_OGF_BASEBAND, 0x0031) /* 0x0c31 */ @@ -3020,6 +3040,18 @@ struct bt_hci_evt_le_req_peer_sca_complete { uint8_t sca; } __packed; +#define BT_HCI_LE_ZONE_ENTERED_LOW 0x0 +#define BT_HCI_LE_ZONE_ENTERED_MIDDLE 0x1 +#define BT_HCI_LE_ZONE_ENTERED_HIGH 0x2 +#define BT_HCI_LE_PATH_LOSS_UNAVAILABLE 0xFF + +#define BT_HCI_EVT_LE_PATH_LOSS_THRESHOLD 0x20 +struct bt_hci_evt_le_path_loss_threshold { + uint16_t handle; + uint8_t current_path_loss; + uint8_t zone_entered; +} __packed; + /** Reason for Transmit power reporting. */ /* Local Transmit power changed. */ diff --git a/subsys/bluetooth/Kconfig b/subsys/bluetooth/Kconfig index 43b8c654e8522..5e1de57db0802 100644 --- a/subsys/bluetooth/Kconfig +++ b/subsys/bluetooth/Kconfig @@ -174,6 +174,13 @@ config BT_TRANSMIT_POWER_CONTROL Enable support for LE Power Control Request feature that is defined in the Bluetooth Core specification, Version 5.4 | Vol 6, Part B, Section 4.6.31. +config BT_PATH_LOSS_MONITORING + bool "LE Path Loss Monitoring" + depends on !BT_CTLR || BT_CTLR_LE_PATH_LOSS_MONITORING_SUPPORT + help + Enable support for LE Path Loss Monitoring feature that is defined in the + Bluetooth Core specification, Version 5.4 | Vol 6, Part B, Section 4.6.32. + endif # BT_CONN rsource "Kconfig.iso" diff --git a/subsys/bluetooth/controller/Kconfig b/subsys/bluetooth/controller/Kconfig index 3d1a36445444d..8be7989d24261 100644 --- a/subsys/bluetooth/controller/Kconfig +++ b/subsys/bluetooth/controller/Kconfig @@ -104,6 +104,10 @@ config BT_CTLR_READ_ISO_LINK_QUALITY_SUPPORT config BT_CTLR_LE_POWER_CONTROL_SUPPORT bool +config BT_CTLR_LE_PATH_LOSS_MONITORING_SUPPORT + depends on BT_CTLR_LE_POWER_CONTROL_SUPPORT + bool + config BT_CTLR bool "Bluetooth Controller" help @@ -550,6 +554,14 @@ config BT_CTLR_LE_POWER_CONTROL Enable support for LE Power Control Request feature that is defined in the Bluetooth Core specification, Version 5.4 | Vol 6, Part B, Section 4.6.31. +config BT_CTLR_LE_PATH_LOSS_MONITORING + bool "LE Path Loss Monitoring Feature" + depends on BT_CTLR_LE_PATH_LOSS_MONITORING_SUPPORT + default y if BT_PATH_LOSS_MONITORING + help + Enable support for LE Path Loss Monitoring feature that is defined in the + Bluetooth Core specification, Version 5.4 | Vol 6, Part B, Section 4.6.32. + endif # BT_CONN config BT_CTLR_FILTER_ACCEPT_LIST diff --git a/subsys/bluetooth/host/conn.c b/subsys/bluetooth/host/conn.c index 244658e6c74f7..3581562bc963d 100644 --- a/subsys/bluetooth/host/conn.c +++ b/subsys/bluetooth/host/conn.c @@ -2884,6 +2884,65 @@ int bt_conn_le_get_tx_power_level(struct bt_conn *conn, return err; } +#if defined(CONFIG_BT_PATH_LOSS_MONITORING) +void notify_path_loss_threshold_report(struct bt_conn *conn, + struct bt_conn_le_path_loss_threshold_report report) +{ + for (struct bt_conn_cb *cb = callback_list; cb; cb = cb->_next) { + if (cb->path_loss_threshold_report) { + cb->path_loss_threshold_report(conn, &report); + } + } + + STRUCT_SECTION_FOREACH(bt_conn_cb, cb) + { + if (cb->path_loss_threshold_report) { + cb->path_loss_threshold_report(conn, &report); + } + } +} + +int bt_conn_le_set_path_loss_mon_param(struct bt_conn *conn, + const struct bt_conn_le_path_loss_reporting_param *params) +{ + struct bt_hci_cp_le_set_path_loss_reporting_parameters *cp; + struct net_buf *buf; + + buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_PATH_LOSS_REPORTING_PARAMETERS, sizeof(*cp)); + if (!buf) { + return -ENOBUFS; + } + + cp = net_buf_add(buf, sizeof(*cp)); + cp->handle = sys_cpu_to_le16(conn->handle); + cp->high_threshold = params->high_threshold; + cp->high_hysteresis = params->high_hysteresis; + cp->low_threshold = params->low_threshold; + cp->low_hysteresis = params->low_hysteresis; + cp->min_time_spent = sys_cpu_to_le16(params->min_time_spent); + + return bt_hci_cmd_send_sync(BT_HCI_OP_LE_SET_PATH_LOSS_REPORTING_PARAMETERS, buf, NULL); +} + +int bt_conn_le_set_path_loss_mon_enable(struct bt_conn *conn, bool reporting_enable) +{ + struct bt_hci_cp_le_set_path_loss_reporting_enable *cp; + struct net_buf *buf; + + buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_PATH_LOSS_REPORTING_ENABLE, sizeof(*cp)); + if (!buf) { + return -ENOBUFS; + } + + cp = net_buf_add(buf, sizeof(*cp)); + cp->handle = sys_cpu_to_le16(conn->handle); + cp->enable = reporting_enable ? BT_HCI_LE_PATH_LOSS_REPORTING_ENABLE : + BT_HCI_LE_PATH_LOSS_REPORTING_DISABLE; + + return bt_hci_cmd_send_sync(BT_HCI_OP_LE_SET_PATH_LOSS_REPORTING_ENABLE, buf, NULL); +} +#endif /* CONFIG_BT_PATH_LOSS_MONITORING */ + int bt_conn_le_param_update(struct bt_conn *conn, const struct bt_le_conn_param *param) { diff --git a/subsys/bluetooth/host/conn_internal.h b/subsys/bluetooth/host/conn_internal.h index 5bdbc947b64fc..f3cdeac265bea 100644 --- a/subsys/bluetooth/host/conn_internal.h +++ b/subsys/bluetooth/host/conn_internal.h @@ -408,6 +408,9 @@ bool le_param_req(struct bt_conn *conn, struct bt_le_conn_param *param); void notify_tx_power_report(struct bt_conn *conn, struct bt_conn_le_tx_power_report report); +void notify_path_loss_threshold_report(struct bt_conn *conn, + struct bt_conn_le_path_loss_threshold_report report); + #if defined(CONFIG_BT_SMP) /* If role specific LTK is present */ bool bt_conn_ltk_present(const struct bt_conn *conn); diff --git a/subsys/bluetooth/host/hci_core.c b/subsys/bluetooth/host/hci_core.c index c394c36cc8dab..fcdb69a75778f 100644 --- a/subsys/bluetooth/host/hci_core.c +++ b/subsys/bluetooth/host/hci_core.c @@ -2514,6 +2514,42 @@ void bt_hci_le_transmit_power_report(struct net_buf *buf) } #endif /* CONFIG_BT_TRANSMIT_POWER_CONTROL */ +#if defined(CONFIG_BT_PATH_LOSS_MONITORING) +void bt_hci_le_path_loss_threshold_event(struct net_buf *buf) +{ + struct bt_hci_evt_le_path_loss_threshold *evt; + struct bt_conn_le_path_loss_threshold_report report; + struct bt_conn *conn; + + evt = net_buf_pull_mem(buf, sizeof(*evt)); + + if (evt->zone_entered > BT_CONN_LE_PATH_LOSS_ZONE_ENTERED_HIGH) { + LOG_ERR("Invalid zone %u in bt_hci_evt_le_path_loss_threshold", + evt->zone_entered); + return; + } + + conn = bt_conn_lookup_handle(sys_le16_to_cpu(evt->handle), BT_CONN_TYPE_LE); + if (!conn) { + LOG_ERR("Unknown conn handle 0x%04X for path loss threshold report", + sys_le16_to_cpu(evt->handle)); + return; + } + + if (evt->current_path_loss == BT_HCI_LE_PATH_LOSS_UNAVAILABLE) { + report.zone = BT_CONN_LE_PATH_LOSS_ZONE_UNAVAILABLE; + report.path_loss = BT_HCI_LE_PATH_LOSS_UNAVAILABLE; + } else { + report.zone = evt->zone_entered; + report.path_loss = evt->current_path_loss; + } + + notify_path_loss_threshold_report(conn, report); + + bt_conn_unref(conn); +} +#endif /* CONFIG_BT_PATH_LOSS_MONITORING */ + static const struct event_handler vs_events[] = { #if defined(CONFIG_BT_DF_VS_CL_IQ_REPORT_16_BITS_IQ_SAMPLES) EVENT_HANDLER(BT_HCI_EVT_VS_LE_CONNECTIONLESS_IQ_REPORT, @@ -2663,6 +2699,10 @@ static const struct event_handler meta_events[] = { EVENT_HANDLER(BT_HCI_EVT_LE_TRANSMIT_POWER_REPORT, bt_hci_le_transmit_power_report, sizeof(struct bt_hci_evt_le_transmit_power_report)), #endif /* CONFIG_BT_TRANSMIT_POWER_CONTROL */ +#if defined(CONFIG_BT_PATH_LOSS_MONITORING) + EVENT_HANDLER(BT_HCI_EVT_LE_PATH_LOSS_THRESHOLD, bt_hci_le_path_loss_threshold_event, + sizeof(struct bt_hci_evt_le_path_loss_threshold)), +#endif /* CONFIG_BT_PATH_LOSS_MONITORING */ #if defined(CONFIG_BT_PER_ADV_SYNC_RSP) EVENT_HANDLER(BT_HCI_EVT_LE_PER_ADVERTISING_REPORT_V2, bt_hci_le_per_adv_report_v2, sizeof(struct bt_hci_evt_le_per_advertising_report_v2)), @@ -3256,6 +3296,10 @@ static int le_set_event_mask(void) if (IS_ENABLED(CONFIG_BT_TRANSMIT_POWER_CONTROL)) { mask |= BT_EVT_MASK_LE_TRANSMIT_POWER_REPORTING; } + + if (IS_ENABLED(CONFIG_BT_PATH_LOSS_MONITORING)) { + mask |= BT_EVT_MASK_LE_PATH_LOSS_THRESHOLD; + } } if (IS_ENABLED(CONFIG_BT_SMP) && diff --git a/subsys/bluetooth/shell/bt.c b/subsys/bluetooth/shell/bt.c index 16f02e7d504f5..95766335bee51 100644 --- a/subsys/bluetooth/shell/bt.c +++ b/subsys/bluetooth/shell/bt.c @@ -189,6 +189,24 @@ static const char *enabled2str(bool enabled) #endif /* CONFIG_BT_TRANSMIT_POWER_CONTROL */ +#if defined(CONFIG_BT_PATH_LOSS_MONITORING) +static const char *plm_report_zone_str(enum bt_conn_le_path_loss_zone zone) +{ + switch (zone) { + case BT_CONN_LE_PATH_LOSS_ZONE_ENTERED_LOW: + return "Entered low zone"; + case BT_CONN_LE_PATH_LOSS_ZONE_ENTERED_MIDDLE: + return "Entered middle zone"; + case BT_CONN_LE_PATH_LOSS_ZONE_ENTERED_HIGH: + return "Entered high zone"; + case BT_CONN_LE_PATH_LOSS_ZONE_UNAVAILABLE: + return "Path loss unavailable"; + default: + return "Unknown"; + } +} +#endif /* CONFIG_BT_PATH_LOSS_MONITORING */ + #if defined(CONFIG_BT_CENTRAL) static int cmd_scan_off(const struct shell *sh); static int cmd_connect_le(const struct shell *sh, size_t argc, char *argv[]); @@ -955,6 +973,14 @@ void tx_power_report(struct bt_conn *conn, } #endif +#if defined(CONFIG_BT_PATH_LOSS_MONITORING) +void path_loss_threshold_report(struct bt_conn *conn, + const struct bt_conn_le_path_loss_threshold_report *report) +{ + shell_print(ctx_shell, "Path Loss Threshold event: Zone: %s, Path loss dbm: %d", + plm_report_zone_str(report->zone), report->path_loss); +} +#endif static struct bt_conn_cb conn_callbacks = { .connected = connected, @@ -979,6 +1005,9 @@ static struct bt_conn_cb conn_callbacks = { #if defined(CONFIG_BT_TRANSMIT_POWER_CONTROL) .tx_power_report = tx_power_report, #endif +#if defined(CONFIG_BT_PATH_LOSS_MONITORING) + .path_loss_threshold_report = path_loss_threshold_report, +#endif }; #endif /* CONFIG_BT_CONN */ @@ -2929,6 +2958,70 @@ static int cmd_set_power_report_enable(const struct shell *sh, size_t argc, char #endif +#if defined(CONFIG_BT_PATH_LOSS_MONITORING) +static int cmd_set_path_loss_reporting_parameters(const struct shell *sh, size_t argc, char *argv[]) +{ + int err = 0; + + if (default_conn == NULL) { + shell_error(sh, "Conn handle error, at least one connection is required."); + return -ENOEXEC; + } + + for (size_t argn = 1; argn < argc; argn++) { + (void)shell_strtoul(argv[argn], 10, &err); + + if (err) { + shell_help(sh); + shell_error(sh, "Could not parse input number %d", argn); + return SHELL_CMD_HELP_PRINTED; + } + } + + const struct bt_conn_le_path_loss_reporting_param params = { + .high_threshold = shell_strtoul(argv[1], 10, &err), + .high_hysteresis = shell_strtoul(argv[2], 10, &err), + .low_threshold = shell_strtoul(argv[3], 10, &err), + .low_hysteresis = shell_strtoul(argv[4], 10, &err), + .min_time_spent = shell_strtoul(argv[5], 10, &err), + }; + + err = bt_conn_le_set_path_loss_mon_param(default_conn, ¶ms); + if (err) { + shell_error(sh, "bt_conn_le_set_path_loss_mon_param returned error %d", err); + return -ENOEXEC; + } + + return 0; +} + +static int cmd_set_path_loss_reporting_enable(const struct shell *sh, size_t argc, char *argv[]) +{ + bool enable; + int err = 0; + + if (default_conn == NULL) { + shell_error(sh, "Conn handle error, at least one connection is required."); + return -ENOEXEC; + } + + enable = shell_strtobool(argv[1], 10, &err); + if (err) { + shell_help(sh); + return SHELL_CMD_HELP_PRINTED; + } + + err = bt_conn_le_set_path_loss_mon_enable(default_conn, enable); + + if (err) { + shell_error(sh, "bt_conn_le_set_path_loss_mon_enable returned error %d", err); + return -ENOEXEC; + } + + return 0; +} +#endif + #if defined(CONFIG_BT_CONN) #if defined(CONFIG_BT_CENTRAL) @@ -4619,6 +4712,13 @@ SHELL_STATIC_SUBCMD_SET_CREATE(bt_cmds, SHELL_CMD_ARG(read-local-tx-power, NULL, HELP_NONE, cmd_read_local_tx_power, 2, 0), SHELL_CMD_ARG(set-power-report-enable, NULL, HELP_NONE, cmd_set_power_report_enable, 3, 0), #endif +#if defined(CONFIG_BT_PATH_LOSS_MONITORING) + SHELL_CMD_ARG(path-loss-monitoring-set-params, NULL, + " ", + cmd_set_path_loss_reporting_parameters, 6, 0), + SHELL_CMD_ARG(path-loss-monitoring-enable, NULL, "", + cmd_set_path_loss_reporting_enable, 2, 0), +#endif #if defined(CONFIG_BT_BROADCASTER) SHELL_CMD_ARG(advertise, NULL, " [mode: discov, non_discov] " From 2d7528dc93061dc878755e448e9526fd1051f36b Mon Sep 17 00:00:00 2001 From: Jens Rehhoff Thomsen Date: Mon, 3 Jun 2024 14:27:13 +0200 Subject: [PATCH 2005/2849] Bluetooth samples: Handle broadcast source gone When the broadcast source unexpectedly disappears then the broadcast sink does a remove source command and resets. Signed-off-by: Jens Rehhoff Thomsen --- .../bluetooth/bap_broadcast_sink/src/main.c | 28 +++++++++++++++++-- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/samples/bluetooth/bap_broadcast_sink/src/main.c b/samples/bluetooth/bap_broadcast_sink/src/main.c index b08c4f96c9afb..c5a9b5ccb1dfe 100644 --- a/samples/bluetooth/bap_broadcast_sink/src/main.c +++ b/samples/bluetooth/bap_broadcast_sink/src/main.c @@ -38,7 +38,7 @@ BUILD_ASSERT(IS_ENABLED(CONFIG_SCAN_SELF) || IS_ENABLED(CONFIG_SCAN_OFFLOAD), #endif /* CONFIG_SCAN_SELF */ #define INVALID_BROADCAST_ID (BT_AUDIO_BROADCAST_ID_MAX + 1) -#define PA_SYNC_INTERVAL_TO_TIMEOUT_RATIO 20 /* Set the timeout relative to interval */ +#define PA_SYNC_INTERVAL_TO_TIMEOUT_RATIO 5 /* Set the timeout relative to interval */ #define PA_SYNC_SKIP 5 #define NAME_LEN sizeof(CONFIG_TARGET_BROADCAST_NAME) + 1 #define BROADCAST_DATA_ELEMENT_SIZE sizeof(int16_t) @@ -1248,10 +1248,32 @@ static void bap_pa_sync_terminated_cb(struct bt_le_per_adv_sync *sync, const struct bt_le_per_adv_sync_term_info *info) { if (sync == pa_sync) { - printk("PA sync %p lost with reason %u\n", sync, info->reason); + printk("PA sync %p lost with reason 0x%02X\n", sync, info->reason); pa_sync = NULL; k_sem_give(&sem_pa_sync_lost); + + if (info->reason != BT_HCI_ERR_LOCALHOST_TERM_CONN && req_recv_state != NULL) { + int err; + + if (k_sem_count_get(&sem_stream_connected) > 0) { + err = bt_bap_broadcast_sink_stop(broadcast_sink); + if (err != 0) { + printk("Failed to stop Broadcast Sink: %d\n", err); + + return; + } + } + + err = bt_bap_scan_delegator_rem_src(req_recv_state->src_id); + if (err != 0) { + printk("Failed to remove source: %d\n", err); + + return; + } + + k_sem_give(&sem_broadcast_sink_stopped); + } } } @@ -1634,7 +1656,7 @@ int main(void) printk("Waiting for PA disconnected\n"); k_sem_take(&sem_pa_sync_lost, K_FOREVER); - printk("Wainting for sink to stop\n"); + printk("Waiting 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"); From 80385a1180177d5eacfd72399783a5174164122a Mon Sep 17 00:00:00 2001 From: Seppo Takalo Date: Thu, 23 May 2024 13:51:57 +0300 Subject: [PATCH 2006/2849] tests: lwm2m: Allow server address to be changed Allow changing the target server address on interoperability tests. This allows running same testcases against public Leshan instance. It is a first requirement to run same tests on a real HW. Signed-off-by: Seppo Takalo --- .../net/lib/lwm2m/interop/pytest/conftest.py | 40 +++++++++++++------ tests/net/lib/lwm2m/interop/testcase.yaml | 1 - 2 files changed, 27 insertions(+), 14 deletions(-) diff --git a/tests/net/lib/lwm2m/interop/pytest/conftest.py b/tests/net/lib/lwm2m/interop/pytest/conftest.py index 7d3ea4e7f8087..f5e901fcc7b74 100644 --- a/tests/net/lib/lwm2m/interop/pytest/conftest.py +++ b/tests/net/lib/lwm2m/interop/pytest/conftest.py @@ -27,6 +27,12 @@ logger = logging.getLogger(__name__) +def pytest_addoption(parser): + parser.addoption('--leshan_addr', action='store', default=LESHAN_IP) + parser.addoption('--leshan_rest_api', action='store', default='http://localhost:8080/api') + parser.addoption('--leshan_bootstrap_rest_api', action='store', default='http://localhost:8081/api') + parser.addoption('--passwd', action='store', default='') + class Endpoint: def __init__(self, name: str, shell: Shell, registered: bool = False, bootstrap: bool = False): self.name = name @@ -47,7 +53,7 @@ def __str__(self): @pytest.fixture(scope='session') -def leshan() -> Leshan: +def leshan(request) -> Leshan: """ Fixture that returns a Leshan object for interacting with the Leshan server. @@ -55,12 +61,12 @@ def leshan() -> Leshan: :rtype: Leshan """ try: - return Leshan("http://localhost:8080/api") + return Leshan(request.config.getoption('--leshan_rest_api')) except RuntimeError: pytest.skip('Leshan server not available') @pytest.fixture(scope='session') -def leshan_bootstrap() -> Leshan: +def leshan_bootstrap(request) -> Leshan: """ Fixture that returns a Leshan object for interacting with the Bootstrap Leshan server. @@ -68,12 +74,12 @@ def leshan_bootstrap() -> Leshan: :rtype: Leshan """ try: - return Leshan("http://localhost:8081/api") + return Leshan(request.config.getoption('--leshan_bootstrap_rest_api')) except RuntimeError: pytest.skip('Leshan Bootstrap server not available') @pytest.fixture(scope='module') -def helperclient() -> object: +def helperclient(request) -> object: """ Fixture that returns a helper client object for testing. @@ -84,11 +90,11 @@ def helperclient() -> object: from coapthon.client.helperclient import HelperClient except ModuleNotFoundError: pytest.skip('CoAPthon3 package not installed') - return HelperClient(server=('127.0.0.1', COAP_PORT)) + return HelperClient(server=(request.config.getoption('--leshan_addr'), COAP_PORT)) @pytest.fixture(scope='module') -def endpoint_nosec(shell: Shell, dut: DeviceAdapter, leshan: Leshan) -> str: +def endpoint_nosec(request, shell: Shell, dut: DeviceAdapter, leshan: Leshan) -> str: """Fixture that returns an endpoint that starts on no-secure mode""" # Allow engine to start & stop once. time.sleep(2) @@ -99,7 +105,8 @@ def endpoint_nosec(shell: Shell, dut: DeviceAdapter, leshan: Leshan) -> str: # # Registration Interface test cases (using Non-secure mode) # - shell.exec_command(f'lwm2m write 0/0/0 -s coap://{LESHAN_IP}:{COAP_PORT}') + addr = request.config.getoption('--leshan_addr') + shell.exec_command(f'lwm2m write 0/0/0 -s coap://{addr}:{COAP_PORT}') shell.exec_command('lwm2m write 0/0/1 -b 0') shell.exec_command('lwm2m write 0/0/2 -u8 3') shell.exec_command(f'lwm2m write 0/0/3 -s {ep}') @@ -109,6 +116,7 @@ def endpoint_nosec(shell: Shell, dut: DeviceAdapter, leshan: Leshan) -> str: shell.exec_command('lwm2m write 1/0/1 -u32 86400') shell.exec_command(f'lwm2m start {ep} -b 0') + dut.readlines_until(regex='.*Registration Done', timeout=5.0) yield Endpoint(ep, shell) # All done @@ -116,27 +124,33 @@ def endpoint_nosec(shell: Shell, dut: DeviceAdapter, leshan: Leshan) -> str: dut.readlines_until(regex=r'.*Deregistration success', timeout=10.0) @pytest.fixture(scope='module') -def endpoint_bootstrap(shell: Shell, dut: DeviceAdapter, leshan: Leshan, leshan_bootstrap: Leshan) -> str: +def endpoint_bootstrap(request, shell: Shell, dut: DeviceAdapter, leshan: Leshan, leshan_bootstrap: Leshan) -> str: """Fixture that returns an endpoint that starts the bootstrap.""" try: + static_passwd = request.config.getoption('--passwd') # Generate randon device id and password (PSK key) ep = 'client_' + binascii.b2a_hex(os.urandom(1)).decode() - bs_passwd = ''.join(random.choice(string.ascii_lowercase) for i in range(16)) - passwd = ''.join(random.choice(string.ascii_lowercase) for i in range(16)) + if static_passwd: + bs_passwd = static_passwd + passwd = static_passwd + else: + bs_passwd = ''.join(random.choice(string.ascii_lowercase) for i in range(16)) + passwd = ''.join(random.choice(string.ascii_lowercase) for i in range(16)) logger.debug('Endpoint: %s', ep) logger.debug('Boostrap PSK: %s', binascii.b2a_hex(bs_passwd.encode()).decode()) logger.debug('PSK: %s', binascii.b2a_hex(passwd.encode()).decode()) # Create device entries in Leshan and Bootstrap server - leshan_bootstrap.create_bs_device(ep, f'coaps://{LESHAN_IP}:{COAPS_PORT}', bs_passwd, passwd) + addr = request.config.getoption('--leshan_addr') + leshan_bootstrap.create_bs_device(ep, f'coaps://{addr}:{COAPS_PORT}', bs_passwd, passwd) leshan.create_psk_device(ep, passwd) # Allow engine to start & stop once. time.sleep(2) # Write bootsrap server information and PSK keys - shell.exec_command(f'lwm2m write 0/0/0 -s coaps://{LESHAN_IP}:{BOOTSTRAP_COAPS_PORT}') + shell.exec_command(f'lwm2m write 0/0/0 -s coaps://{addr}:{BOOTSTRAP_COAPS_PORT}') shell.exec_command('lwm2m write 0/0/1 -b 1') shell.exec_command('lwm2m write 0/0/2 -u8 0') shell.exec_command(f'lwm2m write 0/0/3 -s {ep}') diff --git a/tests/net/lib/lwm2m/interop/testcase.yaml b/tests/net/lib/lwm2m/interop/testcase.yaml index 0639047226943..46a7eee055b84 100644 --- a/tests/net/lib/lwm2m/interop/testcase.yaml +++ b/tests/net/lib/lwm2m/interop/testcase.yaml @@ -5,7 +5,6 @@ tests: slow: true harness_config: pytest_dut_scope: module - pytest_args: [] integration_platforms: - native_sim platform_allow: From 61ec745b49d923371a75194f26e397979a7e1bea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20Cab=C3=A9?= Date: Tue, 4 Jun 2024 18:17:22 +0200 Subject: [PATCH 2007/2849] irq: doc: fix misspelled reference to k_spinlock MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit k_spinlock_t might have actually never existed (?) Rename to k_spinlock. Signed-off-by: Benjamin Cabé --- include/zephyr/irq.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/zephyr/irq.h b/include/zephyr/irq.h index 1fa559edccd34..4810a27b3e0dd 100644 --- a/include/zephyr/irq.h +++ b/include/zephyr/irq.h @@ -215,7 +215,7 @@ irq_disconnect_dynamic(unsigned int irq, unsigned int priority, * * @note * This routine must also serve as a memory barrier to ensure the uniprocessor - * implementation of `k_spinlock_t` is correct. + * implementation of spinlocks is correct. * * This routine can be called recursively, as long as the caller keeps track * of each lock-out key that is generated. Interrupts are re-enabled by @@ -263,7 +263,7 @@ unsigned int z_smp_global_lock(void); * * @note * This routine must also serve as a memory barrier to ensure the uniprocessor - * implementation of `k_spinlock_t` is correct. + * implementation of spinlocks is correct. * * This routine can only be invoked from supervisor mode. Some architectures * (for example, ARM) will fail silently if invoked from user mode instead From 1a59033ea376e6e92a2ab79fc38ccec11c6fb15c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20Cab=C3=A9?= Date: Thu, 6 Jun 2024 10:39:41 +0200 Subject: [PATCH 2008/2849] doc: Bluetooth: Mesh: fix :c:enum: used in lieu of :c:enumerator: MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit While Breathe seems to not care and creates hyperlinks either way, the proper role to mention a C enumerator is :c:enumerator:. :c:enum: is to be used to refer to the enum itself. Signed-off-by: Benjamin Cabé --- doc/connectivity/bluetooth/api/mesh/dfu.rst | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/doc/connectivity/bluetooth/api/mesh/dfu.rst b/doc/connectivity/bluetooth/api/mesh/dfu.rst index c83377aef85ca..5140d2ae36d65 100644 --- a/doc/connectivity/bluetooth/api/mesh/dfu.rst +++ b/doc/connectivity/bluetooth/api/mesh/dfu.rst @@ -201,17 +201,17 @@ DFU. Depending on the availability of the Remote Provisioning Server model on th the device may either boot up unprovisioned after applying the new firmware or require to be re-provisioned. The complete list of available options is defined in :c:enum:`bt_mesh_dfu_effect`: -:c:enum:`BT_MESH_DFU_EFFECT_NONE` +:c:enumerator:`BT_MESH_DFU_EFFECT_NONE` The device stays provisioned after the new firmware is programmed. This effect is chosen if the composition data of the new firmware doesn't change. -:c:enum:`BT_MESH_DFU_EFFECT_COMP_CHANGE_NO_RPR` +:c:enumerator:`BT_MESH_DFU_EFFECT_COMP_CHANGE_NO_RPR` This effect is chosen when the composition data changes and the device doesn't support the remote provisioning. The new composition data takes place only after re-provisioning. -:c:enum:`BT_MESH_DFU_EFFECT_COMP_CHANGE` +:c:enumerator:`BT_MESH_DFU_EFFECT_COMP_CHANGE` This effect is chosen when the composition data changes and the device supports the remote provisioning. In this case, the device stays provisioned and the new composition data takes place after re-provisioning using the Remote Provisioning models. -:c:enum:`BT_MESH_DFU_EFFECT_UNPROV` +:c:enumerator:`BT_MESH_DFU_EFFECT_UNPROV` This effect is chosen if the composition data in the new firmware changes, the device doesn't support the remote provisioning, and the new composition data takes effect after applying the firmware. @@ -219,7 +219,7 @@ re-provisioned. The complete list of available options is defined in :c:enum:`bt When the Target node receives the Firmware Update Firmware Metadata Check message, the Firmware Update Server model calls the :c:member:`bt_mesh_dfu_srv_cb.check` callback, the application can then process the metadata and provide the effect value. If the effect is -:c:enum:`BT_MESH_DFU_EFFECT_COMP_CHANGE`, the application must call functions +:c:enumerator:`BT_MESH_DFU_EFFECT_COMP_CHANGE`, the application must call functions :c:func:`bt_mesh_comp_change_prepare` and :c:func:`bt_mesh_models_metadata_change_prepare` to prepare the Composition Data Page and Models Metadata Page contents before applying the new firmware image. See :ref:`bluetooth_mesh_dfu_srv_comp_data_and_models_metadata` for more From 57d62ca6a4bcccd894dac210dff6e90189faa0ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20Battrel?= Date: Thu, 6 Jun 2024 10:54:21 +0200 Subject: [PATCH 2009/2849] Samples: Bluetooth: Remove unnecessary signal MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The `sec_update_signal` was raised but never waited on. It could be confusing, remove it. Signed-off-by: Théo Battrel --- .../bluetooth/encrypted_advertising/central/src/central_ead.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/samples/bluetooth/encrypted_advertising/central/src/central_ead.c b/samples/bluetooth/encrypted_advertising/central/src/central_ead.c index a321592007172..ddfb98cad8aa7 100644 --- a/samples/bluetooth/encrypted_advertising/central/src/central_ead.c +++ b/samples/bluetooth/encrypted_advertising/central/src/central_ead.c @@ -38,7 +38,6 @@ static struct bt_conn_cb central_cb; static struct bt_conn_auth_cb central_auth_cb; static struct k_poll_signal conn_signal; -static struct k_poll_signal sec_update_signal; static struct k_poll_signal passkey_enter_signal; static struct k_poll_signal device_found_cb_completed; @@ -348,7 +347,6 @@ static void security_changed(struct bt_conn *conn, bt_security_t level, enum bt_ if (!err) { LOG_DBG("Security changed: %s level %u", addr, level); - k_poll_signal_raise(&sec_update_signal, 0); } else { LOG_DBG("Security failed: %s level %u err %d", addr, level, err); } @@ -411,7 +409,6 @@ static int init_bt(void) k_poll_signal_init(&conn_signal); k_poll_signal_init(&passkey_enter_signal); - k_poll_signal_init(&sec_update_signal); k_poll_signal_init(&gatt_disc_signal); k_poll_signal_init(&gatt_read_signal); k_poll_signal_init(&device_found_cb_completed); From 1906ab33da8970f4098bcacba11cd5f35e572754 Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Thu, 6 Jun 2024 13:05:16 +0100 Subject: [PATCH 2010/2849] doc: services: device_mgmt: mcumgr: Remove references to go tool The go tool documentation is very old, and the tool is not recommended for use, therefore remove all documentation relating to it to prevent people from using it Signed-off-by: Jamie McCrae --- doc/services/device_mgmt/mcumgr.rst | 534 ---------------------------- 1 file changed, 534 deletions(-) diff --git a/doc/services/device_mgmt/mcumgr.rst b/doc/services/device_mgmt/mcumgr.rst index 905307ab424ae..0f4f57e7954ee 100644 --- a/doc/services/device_mgmt/mcumgr.rst +++ b/doc/services/device_mgmt/mcumgr.rst @@ -113,203 +113,6 @@ project. Note that a tick for a particular group indicates basic support for that group in the code, it is possible that not all commands/features of a group are supported by the implementation. -.. _mcumgr_cli: - -Command-line Tool -***************** - -MCUmgr provides a command-line tool, :file:`mcumgr`, for managing remote devices. -The tool is written in the Go programming language. - -.. note:: - This tool is provided for evaluation use only and is not recommended for - use in a production environment. It has known issues and will not respect - the MCUmgr protocol properly e.g. when an error is received, instead of - aborting will, in some circumstances, sit in an endless loop of sending the - same command over and over again. A universal replacement for this tool is - currently in development and once released, support for the go tool will be - dropped entirely. It is recommended that usage of tools listed above in the - :ref:`mcumgr_tools_libraries` section are used instead of the go client. - -To install the tool: - -.. tabs:: - - .. group-tab:: go version < 1.18 - - .. code-block:: console - - go get github.com/apache/mynewt-mcumgr-cli/mcumgr - - .. group-tab:: go version >= 1.18 - - .. code-block:: console - - go install github.com/apache/mynewt-mcumgr-cli/mcumgr@latest - -Configuring the transport -************************* - -There are two command-line options that are responsible for setting and configuring -the transport layer to use when communicating with managed device: - -* ``--conntype`` is used to choose the transport used, and -* ``--connstring`` is used to pass a comma separated list of options in the - ``key=value`` format, where each valid ``key`` depends on the particular - ``conntype``. - -Valid transports for ``--conntype`` are ``serial``, ``ble`` and ``udp``. Each -transport expects a different set of key/value options: - -.. tabs:: - - .. group-tab:: serial - - ``--connstring`` accepts the following ``key`` values: - - .. list-table:: - :width: 100% - :widths: 10 60 - - * - ``dev`` - - the device name for the OS ``mcumgr`` is running on (eg, ``/dev/ttyUSB0``, ``/dev/tty.usbserial``, ``COM1``, etc). - * - ``baud`` - - the communication speed; must match the baudrate of the server. - * - ``mtu`` - - aka Maximum Transmission Unit, the maximum protocol packet size. - - .. group-tab:: ble - - ``--connstring`` accepts the following ``key`` values: - - .. list-table:: - :width: 100% - :widths: 10 60 - - * - ``ctlr_name`` - - an OS specific string for the controller name. - * - ``own_addr_type`` - - can be one of ``public``, ``random``, ``rpa_pub``, ``rpa_rnd``, where ``random`` is the default. - * - ``peer_name`` - - the name the peer BLE device advertises, this should match the configuration specified with :kconfig:option:`CONFIG_BT_DEVICE_NAME`. - * - ``peer_id`` - - the peer BLE device address or UUID. Only required when ``peer_name`` was not given. The format depends on the OS where ``mcumgr`` is run, it is a 6 bytes hexadecimal string separated by colons on Linux, or a 128-bit UUID on macOS. - * - ``conn_timeout`` - - a float number representing the connection timeout in seconds. - - .. group-tab:: udp - - ``--connstring`` takes the form ``[addr]:port`` where: - - .. list-table:: - :width: 100% - :widths: 10 60 - - * - ``addr`` - - can be a DNS name (if it can be resolved to the device IP), IPv4 addr (app must be - built with :kconfig:option:`CONFIG_MCUMGR_TRANSPORT_UDP_IPV4`), or IPv6 addr (app must be built with :kconfig:option:`CONFIG_MCUMGR_TRANSPORT_UDP_IPV6`) - * - ``port`` - - any valid UDP port. - -Saving the connection config -**************************** - -The transport configuration can be managed with the ``conn`` sub-command and -later used with ``--conn`` (or ``-c``) parameter to skip typing both ``--conntype`` -and ``--connstring``. For example a new config for a serial device that would -require typing ``mcumgr --conntype serial --connstring dev=/dev/ttyACM0,baud=115200,mtu=512`` -can be saved with:: - - mcumgr conn add acm0 type="serial" connstring="dev=/dev/ttyACM0,baud=115200,mtu=512" - -Accessing this port can now be done with:: - - mcumgr -c acm0 - -.. _general_options: - -General options -*************** - -Some options work for every ``mcumgr`` command and might be helpful to debug and fix -issues with the communication, among them the following deserve special mention: - -.. list-table:: - :width: 100% - :widths: 10 60 - - * - ``-l `` - - Configures the log level, which can be one of ``critical``, ``error``, - ``warn``, ``info`` or ``debug``, from less to most verbose. When there are - communication issues, ``-lDEBUG`` might be useful to dump the packets for - later inspection. - * - ``-t `` - - Changes the timeout waiting for a response from the default of 10s to a - given value. Some commands might take a long time of processing, eg, the - erase before an image upload, and might need incrementing the timeout to - a larger value. - * - ``-r `` - - Changes the number of retries on timeout from the default of 1 to a given - value. - -List of Commands -**************** - -Not all commands defined by ``mcumgr`` (and SMP protocol) are currently supported -on Zephyr. The ones that are supported are described in the following table: - -.. tip:: Running ``mcumgr`` with no parameters, or ``-h`` will display the list - of commands. - -.. list-table:: - :widths: 10 30 - :header-rows: 1 - - * - Command - - Description - * - ``echo`` - - Send data to a device and display the echoed back data. This command is - part of the ``OS`` group, which must be enabled by setting - :kconfig:option:`CONFIG_MCUMGR_GRP_OS`. The ``echo`` command itself can be - enabled by setting :kconfig:option:`CONFIG_MCUMGR_GRP_OS_ECHO`. - * - ``fs`` - - Access files on a device. More info in :ref:`fs_mgmt`. - * - ``image`` - - Manage images on a device. More info in :ref:`image_mgmt`. - * - ``reset`` - - Perform a soft reset of a device. This command is part of the ``OS`` - group, which must be enabled by setting :kconfig:option:`CONFIG_MCUMGR_GRP_OS`. - The ``reset`` command itself is always enabled and the time taken for a - reset to happen can be set with :kconfig:option:`CONFIG_MCUMGR_GRP_OS_RESET_MS` (in ms). - * - ``shell`` - - Execute a command in the remote shell. This option is disabled by default - and can be enabled with :kconfig:option:`CONFIG_MCUMGR_GRP_SHELL` = ``y``. - To know more about the shell in Zephyr check :ref:`shell_api`. - * - ``stat`` - - Read statistics from a device. More info in :ref:`stats_mgmt`. - * - ``taskstat`` - - Read task statistics from a device. This command is part of the ``OS`` - group, which must be enabled by setting :kconfig:option:`CONFIG_MCUMGR_GRP_OS`. - The ``taskstat`` command itself can be enabled by setting - :kconfig:option:`CONFIG_MCUMGR_GRP_OS_TASKSTAT`. :kconfig:option:`CONFIG_THREAD_MONITOR` also - needs to be enabled otherwise a ``-8`` (``MGMT_ERR_ENOTSUP``) will be - returned. - -.. tip:: - - ``taskstat`` has a few options that might require tweaking. The - :kconfig:option:`CONFIG_THREAD_NAME` must be set to display the task names, otherwise - the priority is displayed. Since the ``taskstat`` packets are large, they - might need increasing the :kconfig:option:`CONFIG_MCUMGR_TRANSPORT_NETBUF_SIZE` option. - -.. warning:: - - To display the correct stack size in the ``taskstat`` command, the - :kconfig:option:`CONFIG_THREAD_STACK_INFO` option must be set. - To display the correct stack usage in the ``taskstat`` command, both - :kconfig:option:`CONFIG_THREAD_STACK_INFO` and :kconfig:option:`CONFIG_INIT_STACKS` options - must be set. - .. _mcumgr_jlink_ob_virtual_msd: J-Link Virtual MSD Interaction Note @@ -325,343 +128,6 @@ management commands for updating firmware). This issue can be resolved by disabling MSD functionality on the J-Link device, follow the instructions on :ref:`nordic_segger_msd` to disable MSD support. -.. _image_mgmt: - -Image Management -**************** - -The image management provided by ``mcumgr`` is based on the image format defined -by MCUboot. For more details on the internals see `MCUboot design`_ and :ref:`west-sign`. - -To list available images in a device:: - - mcumgr image list - -This should result in an output similar to this:: - - $ mcumgr -c acm0 image list - Images: - image=0 slot=0 - version: 1.0.0 - bootable: true - flags: active confirmed - hash: 86dca73a3439112b310b5e033d811ec2df728d2264265f2046fced5a9ed00cc7 - Split status: N/A (0) - -Where ``image`` is the number of the image pair in a multi-image system, and slot -is the number of the slot where the image is stored, ``0`` for primary and ``1`` for -secondary. This image being ``active`` and ``confirmed`` means it will run again on -next reset. Also relevant is the ``hash``, which is used by other commands to -refer to this specific image when performing operations. - -An image can be manually erased using:: - - mcumgr image erase - -The behavior of ``erase`` is defined by the server (``MCUmgr`` in the device). -The current implementation is limited to erasing the image in the secondary -partition. - -To upload a new image:: - - mcumgr image upload [-n] [-e] [-u] [-w] - -* ``-n``: This option allows uploading a new image to a specific set of images - in a multi-image system, and is currently only supported by MCUboot when the - CONFIG\ _MCUBOOT_SERIAL option is enabled. - -* ``-e``: This option avoids performing a full erase of the partition before - starting a new upload. - -.. tip:: - - The ``-e`` option should always be passed in because the ``upload`` command - already checks if an erase is required, respecting the - :kconfig:option:`CONFIG_IMG_ERASE_PROGRESSIVELY` setting. - -.. tip:: - - If the ``upload`` command times out while waiting for a response from the - device, ``-t`` might be used to increase the wait time to something larger - than the default of 10s. See general_options_. - -.. warning:: - - ``mcumgr`` does not understand .hex files, when uploading a new image always - use the .bin file. - -* ``-u``: This option allows upgrading only to newer image version. - -* ``-w``: This option allows setting the maximum size for the window of outstanding chunks in transit. - It is set to 5 by default. - - .. tip:: - - If the option is set to a value lower than the default one, for example ``-w 1``, less chunks are transmitted on the window, - resulting in lower risk of errors. Conversely, setting a value higher than 5 increases risk of errors and may impact performance. - -After an image upload is finished, a new ``image list`` would now have an output -like this:: - - $ mcumgr -c acm0 image upload -e build/zephyr/zephyr.signed.bin - 35.69 KiB / 92.92 KiB [==========>---------------] 38.41% 2.97 KiB/s 00m19 - -Now listing the images again:: - - $ mcumgr -c acm0 image list - Images: - image=0 slot=0 - version: 1.0.0 - bootable: true - flags: active confirmed - hash: 86dca73a3439112b310b5e033d811ec2df728d2264265f2046fced5a9ed00cc7 - image=0 slot=1 - version: 1.1.0 - bootable: true - flags: - hash: e8cf0dcef3ec8addee07e8c4d5dc89e64ba3fae46a2c5267fc4efbea4ca0e9f4 - Split status: N/A (0) - -To test a new upgrade image the ``test`` command is used:: - - mcumgr image test - -This command should mark a ``test`` upgrade, which means that after the next -reboot the bootloader will execute the upgrade and jump into the new image. If no -other image operations are executed on the newly running image, it will ``revert`` -back to the image that was previously running on the device on the subsequent reset. -When a ``test`` is requested, ``flags`` will be updated with ``pending`` to inform -that a new image will be run after a reset:: - - $ mcumgr -c acm0 image test e8cf0dcef3ec8addee07e8c4d5dc89e64ba3fae46a2c5267fc4efbea4ca0e9f4 - Images: - image=0 slot=0 - version: 1.0.0 - bootable: true - flags: active confirmed - hash: 86dca73a3439112b310b5e033d811ec2df728d2264265f2046fced5a9ed00cc7 - image=0 slot=1 - version: 1.1.0 - bootable: true - flags: pending - hash: e8cf0dcef3ec8addee07e8c4d5dc89e64ba3fae46a2c5267fc4efbea4ca0e9f4 - Split status: N/A (0) - -After a reset the output with change to:: - - $ mcumgr -c acm0 image list - Images: - image=0 slot=0 - version: 1.1.0 - bootable: true - flags: active - hash: e8cf0dcef3ec8addee07e8c4d5dc89e64ba3fae46a2c5267fc4efbea4ca0e9f4 - image=0 slot=1 - version: 1.0.0 - bootable: true - flags: confirmed - hash: 86dca73a3439112b310b5e033d811ec2df728d2264265f2046fced5a9ed00cc7 - Split status: N/A (0) - -.. tip:: - - It's important to mention that an upgrade only ever happens if the image is - valid. The first thing MCUboot does when an upgrade is requested is to - validate the image, using the SHA-256 and/or the signature (depending on - the configuration). So before uploading an image, one way to be sure it is - valid is to run ``imgtool verify -k ``, - where ``-k image confirm "" - -The ``confirm`` command can also be run passing in a ``hash`` so that instead of -doing a ``test``/``revert`` procedure, the image in the secondary partition is -directly upgraded to, eg:: - - mcumgr image confirm - -.. tip:: - - The whole ``test``/``revert`` cycle does not need to be done using only the - ``mcumgr`` command-line tool. A better alternative is to perform a ``test`` - and allow the new running image to self-confirm after any checks by calling - :c:func:`boot_write_img_confirmed`. - -.. tip:: - - Building with :kconfig:option:`CONFIG_MCUMGR_GRP_IMG_VERBOSE_ERR` enables better error - messages when failures happen (but increases the application size). - -.. _stats_mgmt: - -Statistics Management -********************* - -Statistics are used for troubleshooting, maintenance, and usage monitoring; it -consists basically of user-defined counters which are tightly connected to -``mcumgr`` and can be used to track any information for easy retrieval. The -available sub-commands are:: - - mcumgr stat list - mcumgr stat - -Statistics are organized in sections (also called groups), and each section can -be individually queried. Defining new statistics sections is done by using macros -available under :file:`zephyr/stats/stats.h`. Each section consists of multiple -variables (or counters), all with the same size (16, 32 or 64 bits). - -To create a new section ``my_stats``:: - - STATS_SECT_START(my_stats) - STATS_SECT_ENTRY(my_stat_counter1) - STATS_SECT_ENTRY(my_stat_counter2) - STATS_SECT_ENTRY(my_stat_counter3) - STATS_SECT_END; - - STATS_SECT_DECL(my_stats) my_stats; - -Each entry can be declared with :c:macro:`STATS_SECT_ENTRY` (or the equivalent -:c:macro:`STATS_SECT_ENTRY32`), :c:macro:`STATS_SECT_ENTRY16` or -:c:macro:`STATS_SECT_ENTRY64`. -All statistics in a section must be declared with the same size. - -The statistics counters can either have names or not, depending on the setting -of the :kconfig:option:`CONFIG_STATS_NAMES` option. Using names requires an extra -declaration step:: - - STATS_NAME_START(my_stats) - STATS_NAME(my_stats, my_stat_counter1) - STATS_NAME(my_stats, my_stat_counter2) - STATS_NAME(my_stats, my_stat_counter3) - STATS_NAME_END(my_stats); - -.. tip:: - - Disabling :kconfig:option:`CONFIG_STATS_NAMES` will free resources. When this option - is disabled the ``STATS_NAME*`` macros output nothing, so adding them in the - code does not increase the binary size. - -.. tip:: - - :kconfig:option:`CONFIG_MCUMGR_GRP_STAT_MAX_NAME_LEN` sets the maximum length of a section - name that can can be accepted as parameter for showing the section data, and - might require tweaking for long section names. - -The final steps to use a statistics section is to initialize and register it:: - - rc = STATS_INIT_AND_REG(my_stats, STATS_SIZE_32, "my_stats"); - assert (rc == 0); - -In the running code a statistics counter can be incremented by 1 using -:c:macro:`STATS_INC`, by N using :c:macro:`STATS_INCN` or reset with -:c:macro:`STATS_CLEAR`. - -Let's suppose we want to increment those counters by ``1``, ``2`` and ``3`` -every second. To get a list of stats:: - - $ mcumgr --conn acm0 stat list - stat groups: - my_stats - -To get the current value of the counters in ``my_stats``:: - - $ mcumgr --conn acm0 stat my_stats - stat group: my_stats - 13 my_stat_counter1 - 26 my_stat_counter2 - 39 my_stat_counter3 - - $ mcumgr --conn acm0 stat my_stats - stat group: my_stats - 16 my_stat_counter1 - 32 my_stat_counter2 - 48 my_stat_counter3 - -When :kconfig:option:`CONFIG_STATS_NAMES` is disabled the output will look like this:: - - $ mcumgr --conn acm0 stat my_stats - stat group: my_stats - 8 s0 - 16 s1 - 24 s2 - -.. _fs_mgmt: - -Filesystem Management -********************* - -The filesystem module is disabled by default due to security concerns: -because of a lack of access control by default, every file in the FS will be -accessible, including secrets, etc. To enable it -:kconfig:option:`CONFIG_MCUMGR_GRP_FS` must be set (``y``). Once enabled the -following sub-commands can be used:: - - mcumgr fs download - mcumgr fs upload - -Using the ``fs`` command, requires :kconfig:option:`CONFIG_FILE_SYSTEM` to be enabled, -and that some particular filesystem is enabled and properly mounted by the running -application, eg for littlefs this would mean enabling -:kconfig:option:`CONFIG_FILE_SYSTEM_LITTLEFS`, defining a storage partition :ref:`flash_map_api` -and mounting the filesystem in the startup (:c:func:`fs_mount`). - -Uploading a new file to a littlefs storage, mounted under ``/lfs``, can be done with:: - - $ mcumgr -c acm0 fs upload foo.txt /lfs/foo.txt - 25 - Done - -Where ``25`` is the size of the file. - -For downloading a file, let's first use the ``fs`` command -(:kconfig:option:`CONFIG_FILE_SYSTEM_SHELL` must be enabled) in a remote shell to create -a new file:: - - uart:~$ fs write /lfs/bar.txt 41 42 43 44 31 32 33 34 0a - uart:~$ fs read /lfs/bar.txt - File size: 9 - 00000000 41 42 43 44 31 32 33 34 0A ABCD1234. - -Now it can be downloaded using:: - - $ mcumgr -c acm0 fs download /lfs/bar.txt bar.txt - 0 - 9 - Done - $ cat bar.txt - ABCD1234 - -Where ``0`` is the return code, and ``9`` is the size of the file. - -.. warning:: - - The commands might exhaust the system workqueue, if its size is not large - enough, so increasing :kconfig:option:`CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE` might be - required for correct behavior. - -The size of the stack allocated buffer used to store the blocks, while transferring -a file can be adjusted with :kconfig:option:`CONFIG_MCUMGR_GRP_FS_DL_CHUNK_SIZE`; this allows -saving RAM resources. - -.. tip:: - - :kconfig:option:`CONFIG_MCUMGR_GRP_FS_PATH_LEN` sets the maximum PATH accepted for a file - name. It might require tweaking for longer file names. - -.. note:: - To add security to the filesystem management group, callbacks for MCUmgr - hooks can be registered by a user application when the upload/download - functions are ran which allows the application to control if access to a - file is allowed or denied. See the :ref:`mcumgr_callbacks` section for - details. - Bootloader Integration ********************** From 7e912578054530a060462e70e3088ea1459e7560 Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Thu, 6 Jun 2024 13:13:39 +0100 Subject: [PATCH 2011/2849] samples: mgmt: mcumgr: smp_svr: Remove documentation for go tool Removes references to old tool documentation and refers users to the list of supported applications instead Signed-off-by: Jamie McCrae --- samples/subsys/mgmt/mcumgr/smp_svr/README.rst | 143 ++++-------------- 1 file changed, 27 insertions(+), 116 deletions(-) diff --git a/samples/subsys/mgmt/mcumgr/smp_svr/README.rst b/samples/subsys/mgmt/mcumgr/smp_svr/README.rst index ce5cd64561dbb..a9ddfcbf4a146 100644 --- a/samples/subsys/mgmt/mcumgr/smp_svr/README.rst +++ b/samples/subsys/mgmt/mcumgr/smp_svr/README.rst @@ -31,18 +31,14 @@ Caveats properly. More information about the Device Firmware Upgrade subsystem and MCUboot can be found in :ref:`mcuboot`. -* The :file:`mcumgr` command-line tool only works with Bluetooth Low Energy (BLE) - on Linux and macOS. On Windows there is no support for Device Firmware - Upgrade over BLE yet. - Prerequisites ************* -Installing the mcumgr cli -========================= +Use of a tool +============= -To interact remotely with the management subsystem on a device, we need to have the -:file:`mcumgr` installed. Follow the instructions in the :ref:`mcumgr_cli` section +To interact remotely with the management subsystem on a device, a tool is required to interact with +it. There are various tools available which are listed on the :ref:`mcumgr_tools_libraries` page of the Management subsystem documentation. Building a BLE Controller @@ -63,7 +59,7 @@ The below steps describe how to build and run the MCUboot bootloader. Detailed instructions can be found in the :ref:`mcuboot` documentation page. The Zephyr port of MCUboot is essentially a normal Zephyr application, which means that -we can build and flash it like normal using ``west``, like so: +it can be built and flashed like normal using ``west``, like so: .. code-block:: console @@ -156,7 +152,7 @@ Signing the sample image A key feature of MCUboot is that images must be signed before they can be successfully uploaded and run on a target. To sign images, the MCUboot tool :file:`imgtool` can be used. -To sign the sample image we built in a previous step: +To sign the sample image built in the previous step: .. code-block:: console @@ -174,65 +170,22 @@ Flashing the sample image Upload the :file:`zephyr.signed.bin` file from the previous to image slot-0 of your board. See :ref:`flash_map_api` for details on flash partitioning. -To upload the initial image file to an empty slot-0, we simply use ``west flash`` -like normal. ``west flash`` will automatically detect slot-0 address and confirm -the image. +To upload the initial image file to an empty slot-0, use ``west flash`` like normal. +``west flash`` will automatically detect slot-0 address and confirm the image. .. code-block:: console west flash --bin-file build/zephyr/zephyr.signed.bin -We need to explicitly specify the *signed* image file, otherwise the non-signed version +The *signed* image file needs to be used specifically, otherwise the non-signed version will be used and the image won't be runnable. Sample image: hello world! ========================== The ``smp_svr`` app is ready to run. Just reset your board and test the app -with the :file:`mcumgr` command-line tool's ``echo`` functionality, which will -send a string to the remote target device and have it echo it back: - -.. tabs:: - - .. group-tab:: Bluetooth - - .. code-block:: console - - sudo mcumgr --conntype ble --connstring ctlr_name=hci0,peer_name='Zephyr' echo hello - hello - - .. group-tab:: Shell - - .. code-block:: console - - mcumgr --conntype serial --connstring "/dev/ttyACM0,baud=115200" echo hello - hello - - .. group-tab:: UDP - - Using IPv4: - - .. code-block:: console - - mcumgr --conntype udp --connstring=[192.168.1.1]:1337 echo hello - hello - - And using IPv6 - - .. code-block:: console - - mcumgr --conntype udp --connstring=[2001:db8::1]:1337 echo hello - hello - -.. note:: - The :file:`mcumgr` command-line tool requires a connection string in order - to identify the remote target device. In the BT sample we use a BLE-based - connection string, and you might need to modify it depending on the - BLE controller you are using. - -.. note:: - In the following sections, examples will use ```` to represent - the ``--conntype `` and ``--connstring=`` :file:`mcumgr` parameters. +with your choice of tool's ``echo`` functionality, which will +send a string to the remote target device and have it echo it back. J-Link Virtual MSD Interaction Note *********************************** @@ -269,10 +222,6 @@ Direct image upload and Image mapping to MCUboot slot Currently the mcumgr supports, for direct upload, 4 target images, of which first two are mapped into MCUboot primary (slot-0) and secondary (slot-1) respectively. -The mcumgr ``image upload`` command may be provided optional ``-e -n `` parameter that will -select target image for upload; when parameter is no provided, 0 is assumed, which means "default -behaviour", and it performs upload to the "image-1", the MCUboot secondary slot. - For clarity, here is DTS label to slot to ```` translation table: +-----------+--------+------------+ @@ -287,80 +236,47 @@ For clarity, here is DTS label to slot to ```` translation table: | "image-3" | | 3 | +-----------+--------+------------+ -.. note:: - - The ``-e`` option actually means "no erase", and is provided to the mcumgr - to prevent it from sending erase command to target, before updating image. - The options is always needed when ``-n`` is used for image selection, - as the erase command is hardcoded to erase slot-1 ("image-1"), - regardless of which slot is uploaded at the time. - Upload the signed image ======================= -To upload the signed image, use the following command: - -.. code-block:: console - - sudo mcumgr image upload build/zephyr/zephyr.signed.bin +To upload the signed image, refer to the documentation for your chosen tool, select the new +firmware file to upload and begin the upload. .. note:: At the beginning of the upload process, the target might start erasing - the image slot, taking several dozen seconds for some targets. This might - cause an NMP timeout in the management protocol tool. Use the - ``-t image list - -This should print the status and hash values of each of the images present. +A list of images (slot-0 and slot-1) that are present can now be obtained on the remote target device using +the tool of your choice, which should print the status and hash values of each of the images +present. Test the image ============== -In order to instruct MCUboot to swap the images we need to test the image first, -making sure it boots: - -.. code-block:: console - - sudo mcumgr image test - -Now MCUBoot will swap the image on the next reset. +In order to instruct MCUboot to swap the images, the image needs to be tested first, making sure it +boots, see the instructions in the tool of your choice. Upon reboot, MCUBoot will swap to the new +image. .. note:: There is not yet any way of getting the image hash without actually uploading the - image and getting the hash by using the ``image list`` command of :file:`mcumgr`. + image and getting the hash. Reset remotely ============== -We can reset the device remotely to observe (use the console output) how -MCUboot swaps the images: - -.. code-block:: console - - sudo mcumgr reset - -Upon reset MCUboot will swap slot-0 and slot-1. +The device can be reset remotely to observe (use the console output) how MCUboot swaps the images, +check the documentation in the tool of your choice. Upon reset MCUboot will swap slot-0 and +slot-1. Confirm new image ================= -The new image is now loaded into slot-0, but it will be swapped back into slot-1 -on the next reset unless the image is confirmed. To confirm the new image: - -.. code-block:: console - - sudo mcumgr image confirm +The new image is now loaded into slot-0, but it will be swapped back into slot-1 on the next +reset unless the image is confirmed. Confirm the image using the tool of your choice. Note that if you try to send the very same image that is already flashed in slot-0 then the procedure will not complete successfully since the hash values @@ -372,9 +288,4 @@ Download file from File System SMP server supports downloading files from File System on device via :file:`mcumgr`. This is useful with FS log backend, when files are stored in non-volatile memory. Build and flash both MCUboot and smp_svr applications and -then use :file:`mcumgr` with :file:`download` command, e.g.: - -.. code-block:: console - - mcumgr --conntype serial --connstring='dev=/dev/ttyACM0,baud=115200' \ - fs download /lfs/log.0000 ~/log.txt +then use the tool of your choice to download files from the file system. From 1c4dbf7f875ef18da6daf6bd7cb89b11d1c239a0 Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Fri, 7 Jun 2024 10:31:16 +0100 Subject: [PATCH 2012/2849] doc: release: 3.7: Add note on MCUmgr go tool instruction removal Adds a note that these instructions have been removed and list the available replacement tools Signed-off-by: Jamie McCrae --- 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 e4a33ceef94d2..434293ce680fa 100644 --- a/doc/releases/release-notes-3.7.rst +++ b/doc/releases/release-notes-3.7.rst @@ -488,6 +488,11 @@ Libraries / Subsystems registered to set the device attributes that are sent to the hawkBit server. Use the :c:func:`hawkbit_set_custom_data_cb` function to register the callback. + * MCUmgr + + * Instructions for the deprecated mcumgr go tool have been removed, a list of alternative, + supported clients can be found on :ref:`mcumgr_tools_libraries`. + * Logging * By enabling :kconfig:option:`CONFIG_LOG_BACKEND_NET_USE_DHCPV4_OPTION`, the IP address of the From 17c3a23157c875baea12fdd3490a0e9c193c42a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Chru=C5=9Bci=C5=84ski?= Date: Tue, 4 Jun 2024 14:11:23 +0200 Subject: [PATCH 2013/2849] modules: hal_nordic: nrfx: nrfx_glue: Improve GPIOTE_CHANNELS_USED MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Channels owned by a child core shall also be included in the mask of used channels (channels that cannot be allocated by the GPIOTE channel allocator). Signed-off-by: Krzysztof Chruściński --- modules/hal_nordic/nrfx/nrfx_glue.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/modules/hal_nordic/nrfx/nrfx_glue.h b/modules/hal_nordic/nrfx/nrfx_glue.h index 0dd8b2bba9473..0f480a70f494a 100644 --- a/modules/hal_nordic/nrfx/nrfx_glue.h +++ b/modules/hal_nordic/nrfx/nrfx_glue.h @@ -335,7 +335,10 @@ void nrfx_busy_wait(uint32_t usec_to_wait); NRFX_PPI_GROUPS_USED_BY_MPSL) /** @brief Bitmask that defines GPIOTE130 channels reserved for use outside of the nrfx library. */ -#define NRFX_GPIOTE130_CHANNELS_USED ~NRFX_CONFIG_MASK_DT(DT_NODELABEL(gpiote130), owned_channels) +#define NRFX_GPIOTE130_CHANNELS_USED \ + (~NRFX_CONFIG_MASK_DT(DT_NODELABEL(gpiote130), owned_channels) | \ + NRFX_CONFIG_MASK_DT(DT_NODELABEL(gpiote130), child_owned_channels)) + #if defined(CONFIG_BT_CTLR) /* From 211221a1026a7322ab27b10574c437a424179728 Mon Sep 17 00:00:00 2001 From: Alberto Escolar Piedras Date: Fri, 7 Jun 2024 10:06:05 +0200 Subject: [PATCH 2014/2849] manifest: Update bsim to version v2.2.1 Includes just changes for the phy dump conversion scripts, to add support in the csv2pcap conversion for coded phy. Signed-off-by: Alberto Escolar Piedras --- west.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/west.yml b/west.yml index 4b9a98bcbb615..685b2133bbe93 100644 --- a/west.yml +++ b/west.yml @@ -34,7 +34,7 @@ manifest: path: modules/lib/acpica - name: bsim repo-path: babblesim-manifest - revision: 68f6282c6a7f54641b75f5f9fc953c85e272a983 + revision: 9351ae1ad44864a49c351f9704f65f43046abeb0 path: tools/bsim groups: - babblesim @@ -56,7 +56,7 @@ manifest: remote: babblesim repo-path: ext_2G4_phy_v1 path: tools/bsim/components/ext_2G4_phy_v1 - revision: d8302b8d51409b9e717a1a0ba6b443d3b5552a6c + revision: 04eeb3c3794444122fbeeb3715f4233b0b50cfbb groups: - babblesim - name: babblesim_ext_2G4_channel_NtNcable From 62893328293f8719f72b0a4e2edcb48fef3e125c Mon Sep 17 00:00:00 2001 From: Alberto Escolar Piedras Date: Fri, 7 Jun 2024 10:09:14 +0200 Subject: [PATCH 2015/2849] manifest: Update EDTT to latest Update the EDTT module to: 8d7b543d4d2f2be0f78481e4e1d8d73a88024803 Including the following: * 8d7b543 Fix some issues found during CIS Central testing * fb426f1 Fix crash due to race when creating simulation folder 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 685b2133bbe93..e148264fb1584 100644 --- a/west.yml +++ b/west.yml @@ -127,7 +127,7 @@ manifest: revision: 0c8669d81381ccf3b1a01d699f3b68b50134a99f path: modules/lib/cmsis-nn - name: edtt - revision: 64e5105ad82390164fb73fc654be3f73a608209a + revision: 8d7b543d4d2f2be0f78481e4e1d8d73a88024803 path: tools/edtt groups: - tools From 5a5fd7c96fbdf1a80191b39296625a6174cfdd42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20Cab=C3=A9?= Date: Wed, 5 Jun 2024 15:04:49 +0200 Subject: [PATCH 2016/2849] doc: mcumgr: fix mixed up occurrences of :c:enum: and :c:enumerator: MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit While Breathe seems to not care and creates hyperlinks either way, the proper role to mention a C enumerator is :c:enumerator:. :c:enum: is to be used to refer to the enum itself. Signed-off-by: Benjamin Cabé --- doc/services/device_mgmt/mcumgr_callbacks.rst | 3 +-- doc/services/device_mgmt/mcumgr_handlers.rst | 6 +++--- doc/services/device_mgmt/smp_groups/smp_group_0.rst | 2 +- doc/services/device_mgmt/smp_groups/smp_group_1.rst | 8 ++++---- doc/services/device_mgmt/smp_groups/smp_group_3.rst | 4 ++-- doc/services/device_mgmt/smp_groups/smp_group_8.rst | 4 ++-- 6 files changed, 13 insertions(+), 14 deletions(-) diff --git a/doc/services/device_mgmt/mcumgr_callbacks.rst b/doc/services/device_mgmt/mcumgr_callbacks.rst index 7333f273f2b0b..0ed8b580c757c 100644 --- a/doc/services/device_mgmt/mcumgr_callbacks.rst +++ b/doc/services/device_mgmt/mcumgr_callbacks.rst @@ -192,7 +192,7 @@ the file should be allowed or not, note that this requires that :kconfig:option:`CONFIG_MCUMGR_GRP_FS_FILE_ACCESS_HOOK` be enabled to receive this callback. Two types of errors can be returned, the ``rc`` parameter can be set to an -:c:enumerator:`mcumgr_err_t` error code and :c:enumerator:`MGMT_CB_ERROR_RC` +:c:enum:`mcumgr_err_t` error code and :c:enumerator:`MGMT_CB_ERROR_RC` can be returned, or a group error code (introduced with version 2 of the MCUmgr protocol) can be set by setting the ``group`` value to the group and ``rc`` value to the group error code and returning :c:enumerator:`MGMT_CB_ERROR_ERR`. @@ -330,4 +330,3 @@ API Reference ************* .. doxygengroup:: mcumgr_callback_api - :inner: diff --git a/doc/services/device_mgmt/mcumgr_handlers.rst b/doc/services/device_mgmt/mcumgr_handlers.rst index e189ea887d473..18fc5e65366cb 100644 --- a/doc/services/device_mgmt/mcumgr_handlers.rst +++ b/doc/services/device_mgmt/mcumgr_handlers.rst @@ -52,8 +52,8 @@ responses (which have unique error codes per group as opposed to the legacy SMP responses that return a :c:enum:`mcumgr_err_t` - there should always be an OK error code with the value 0 and an unknown error code with the value 1. The above example then adds an error code of ``not wanted`` with value 2. In addition, the group ID is set to be -:c:enum:`MGMT_GROUP_ID_PERUSER`, which is the start group ID for user-defined groups, note that -group IDs need to be unique so other custom groups should use different values, a central index +:c:enumerator:`MGMT_GROUP_ID_PERUSER`, which is the start group ID for user-defined groups, note +that group IDs need to be unique so other custom groups should use different values, a central index header file (as upstream Zephyr has) can be used to distribute group IDs more easily. Initial header _mgmt_callbacks.h @@ -70,7 +70,7 @@ file would look similar to: This sets up a single event which application (or module) code can register for to receive a callback when the function handler is executed, which allows the flow of the handler to be changed (i.e. to return an error instead of continuing). The event group ID is set to -:c:enum:`MGMT_EVT_GRP_USER_CUSTOM_START`, which is the start event ID for user-defined groups, +:c:enumerator:`MGMT_EVT_GRP_USER_CUSTOM_START`, which is the start event ID for user-defined groups, note that event IDs need to be unique so other custom groups should use different values, a central index header file (as upstream Zephyr has) can be used to distribute event IDs more easily. diff --git a/doc/services/device_mgmt/smp_groups/smp_group_0.rst b/doc/services/device_mgmt/smp_groups/smp_group_0.rst index 7fb91463e336f..eb3b90b3a1d7f 100644 --- a/doc/services/device_mgmt/smp_groups/smp_group_0.rst +++ b/doc/services/device_mgmt/smp_groups/smp_group_0.rst @@ -563,7 +563,7 @@ System reset request header fields: +--------+--------------+----------------+ Normally the command sends an empty CBOR map as data, but if a previous reset -attempt has responded with "rc" equal to :c:enum:`MGMT_ERR_EBUSY` then the +attempt has responded with "rc" equal to :c:enumerator:`MGMT_ERR_EBUSY` then the following map may be sent to force a reset: .. code-block:: none diff --git a/doc/services/device_mgmt/smp_groups/smp_group_1.rst b/doc/services/device_mgmt/smp_groups/smp_group_1.rst index 2a1d1f2708632..744835fad25b1 100644 --- a/doc/services/device_mgmt/smp_groups/smp_group_1.rst +++ b/doc/services/device_mgmt/smp_groups/smp_group_1.rst @@ -204,7 +204,7 @@ where: | | using SMP version 1 or for SMP errors when using SMP version 2. | +------------------+-------------------------------------------------------------------------+ | "rsn" | optional string that clarifies reason for an error; specifically useful | - | | when ``rc`` is :c:enum:`MGMT_ERR_EUNKNOWN`. | + | | when ``rc`` is :c:enumerator:`MGMT_ERR_EUNKNOWN`. | +------------------+-------------------------------------------------------------------------+ .. note:: @@ -407,7 +407,7 @@ where: | | using SMP version 1 or for SMP errors when using SMP version 2. | +------------------+-------------------------------------------------------------------------+ | "rsn" | optional string that clarifies reason for an error; specifically useful | - | | when ``rc`` is :c:enum:`MGMT_ERR_EUNKNOWN`. | + | | when ``rc`` is :c:enumerator:`MGMT_ERR_EUNKNOWN`. | +------------------+-------------------------------------------------------------------------+ The "off" field is only included in responses to successfully processed requests; @@ -509,10 +509,10 @@ where: | | using SMP version 1 or for SMP errors when using SMP version 2. | +------------------+-------------------------------------------------------------------------+ | "rsn" | optional string that clarifies reason for an error; specifically useful | - | | when ``rc`` is :c:enum:`MGMT_ERR_EUNKNOWN`. | + | | when ``rc`` is :c:enumerator:`MGMT_ERR_EUNKNOWN`. | +------------------+-------------------------------------------------------------------------+ .. note:: Response from Zephyr running device may have "rc" value of - :c:enum:`MGMT_ERR_EBADSTATE`, which means that the secondary + :c:enumerator:`MGMT_ERR_EBADSTATE`, which means that the secondary image has been marked for next boot already and may not be erased. diff --git a/doc/services/device_mgmt/smp_groups/smp_group_3.rst b/doc/services/device_mgmt/smp_groups/smp_group_3.rst index 0636e72e3f649..b5fd66d3d6033 100644 --- a/doc/services/device_mgmt/smp_groups/smp_group_3.rst +++ b/doc/services/device_mgmt/smp_groups/smp_group_3.rst @@ -542,5 +542,5 @@ There is a settings access MCUmgr callback available (see :ref:`mcumgr_callbacks callbacks) which allows for applications/modules to know when settings management commands are used and, optionally, block access (for example through the use of a security mechanism). This callback can be enabled with :kconfig:option:`CONFIG_MCUMGR_GRP_SETTINGS_ACCESS_HOOK`, registered -with the event :c:enum:`MGMT_EVT_OP_SETTINGS_MGMT_ACCESS`, whereby the supplied callback data is -:c:struct:`settings_mgmt_access`. +with the event :c:enumerator:`MGMT_EVT_OP_SETTINGS_MGMT_ACCESS`, whereby the supplied callback data +is :c:struct:`settings_mgmt_access`. diff --git a/doc/services/device_mgmt/smp_groups/smp_group_8.rst b/doc/services/device_mgmt/smp_groups/smp_group_8.rst index 502a575716904..7a50ebf3d7c89 100644 --- a/doc/services/device_mgmt/smp_groups/smp_group_8.rst +++ b/doc/services/device_mgmt/smp_groups/smp_group_8.rst @@ -47,7 +47,7 @@ requests or even be removed. However, if the Kconfig option :kconfig:option:`CONFIG_MCUMGR_GRP_FS_FILE_ACCESS_HOOK` is enabled, then an application can register a callback handler for - :c:enum:`MGMT_EVT_OP_FS_MGMT_FILE_ACCESS` (see + :c:enumerator:`MGMT_EVT_OP_FS_MGMT_FILE_ACCESS` (see :ref:`MCUmgr callbacks `), which allows for allowing or declining access to reading/writing a particular file, or for rewriting the path supplied by the client. @@ -185,7 +185,7 @@ change between requests or even be removed. However, if the Kconfig option :kconfig:option:`CONFIG_MCUMGR_GRP_FS_FILE_ACCESS_HOOK` is enabled, then an application can register a callback handler for - :c:enum:`MGMT_EVT_OP_FS_MGMT_FILE_ACCESS` (see + :c:enumerator:`MGMT_EVT_OP_FS_MGMT_FILE_ACCESS` (see :ref:`MCUmgr callbacks `), which allows for allowing or declining access to reading/writing a particular file, or for rewriting the path supplied by the client. From c26f1bef49f58ceb944530ad0e84d630607a8380 Mon Sep 17 00:00:00 2001 From: Robert Lubos Date: Wed, 5 Jun 2024 13:23:15 +0200 Subject: [PATCH 2017/2849] samples: net: sockets: Add netif dependency where missing A few samples were not limiting the CI execution scope in any reasonable way, they should at least limit the execution to platforms that support netif capability. Signed-off-by: Robert Lubos --- samples/net/sockets/big_http_download/sample.yaml | 1 + samples/net/sockets/dumb_http_server_mt/sample.yaml | 1 + samples/net/sockets/http_get/sample.yaml | 1 + samples/net/sockets/http_server/sample.yaml | 1 + 4 files changed, 4 insertions(+) diff --git a/samples/net/sockets/big_http_download/sample.yaml b/samples/net/sockets/big_http_download/sample.yaml index 683b8c5c52c0d..d27f131836da1 100644 --- a/samples/net/sockets/big_http_download/sample.yaml +++ b/samples/net/sockets/big_http_download/sample.yaml @@ -4,6 +4,7 @@ sample: common: filter: CONFIG_FULL_LIBC_SUPPORTED and not CONFIG_NATIVE_LIBC harness: net + depends_on: netif min_ram: 32 min_flash: 128 tags: diff --git a/samples/net/sockets/dumb_http_server_mt/sample.yaml b/samples/net/sockets/dumb_http_server_mt/sample.yaml index dc0c81822468e..4d278431c2241 100644 --- a/samples/net/sockets/dumb_http_server_mt/sample.yaml +++ b/samples/net/sockets/dumb_http_server_mt/sample.yaml @@ -3,6 +3,7 @@ sample: name: socket_dumb_http_server_mt common: harness: net + depends_on: netif min_ram: 128 min_flash: 128 tags: diff --git a/samples/net/sockets/http_get/sample.yaml b/samples/net/sockets/http_get/sample.yaml index 94f7cd6f8ddd9..2aba5c7d60d8c 100644 --- a/samples/net/sockets/http_get/sample.yaml +++ b/samples/net/sockets/http_get/sample.yaml @@ -3,6 +3,7 @@ sample: name: socket_http_get common: filter: CONFIG_FULL_LIBC_SUPPORTED + depends_on: netif min_ram: 32 min_flash: 80 tags: diff --git a/samples/net/sockets/http_server/sample.yaml b/samples/net/sockets/http_server/sample.yaml index eeaca47d386ed..8af05127cd4b4 100644 --- a/samples/net/sockets/http_server/sample.yaml +++ b/samples/net/sockets/http_server/sample.yaml @@ -3,6 +3,7 @@ sample: name: http_server_sample common: harness: net + depends_on: netif min_ram: 192 tags: - http From 0163ae53329733d3a4fde451706bfcb4e2259deb Mon Sep 17 00:00:00 2001 From: Robert Lubos Date: Thu, 6 Jun 2024 09:41:57 +0200 Subject: [PATCH 2018/2849] samples: net: sockets: http_server: Disable PSA crypto The sample won't build with PSA crypto enabled on non-secure platform, causing disturbances in the CI. Signed-off-by: Robert Lubos --- samples/net/sockets/http_server/prj.conf | 1 + 1 file changed, 1 insertion(+) diff --git a/samples/net/sockets/http_server/prj.conf b/samples/net/sockets/http_server/prj.conf index 51d898eb15c2d..c9c80be2429dd 100644 --- a/samples/net/sockets/http_server/prj.conf +++ b/samples/net/sockets/http_server/prj.conf @@ -61,6 +61,7 @@ CONFIG_MBEDTLS_BUILTIN=y CONFIG_MBEDTLS_ENABLE_HEAP=y CONFIG_MBEDTLS_HEAP_SIZE=60000 CONFIG_MBEDTLS_SSL_MAX_CONTENT_LEN=2048 +CONFIG_MBEDTLS_USE_PSA_CRYPTO=n CONFIG_NET_SOCKETS_SOCKOPT_TLS=y CONFIG_NET_SOCKETS_TLS_MAX_CONTEXTS=6 CONFIG_TLS_CREDENTIALS=y From b5c5e0e4b6abc106790ed75858049d23ddb389ed Mon Sep 17 00:00:00 2001 From: Francois Ramu Date: Tue, 4 Jun 2024 10:28:40 +0200 Subject: [PATCH 2019/2849] boards: st: higher sysclock for the stm32h743/h753 nucleo boards Configure the DTS to increase the sysclock to its max value 480MHz for the nucleo_h743zi and nucleo_h753zi boards Max Hclock is 240MHz The Pll source is HSE is 8MHz clock source from the STLink. Signed-off-by: Francois Ramu --- boards/st/nucleo_h743zi/nucleo_h743zi.dts | 18 +++++++++--------- boards/st/nucleo_h753zi/nucleo_h753zi.dts | 18 +++++++++--------- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/boards/st/nucleo_h743zi/nucleo_h743zi.dts b/boards/st/nucleo_h743zi/nucleo_h743zi.dts index f410d6f956e9d..6e5a80b459310 100644 --- a/boards/st/nucleo_h743zi/nucleo_h743zi.dts +++ b/boards/st/nucleo_h743zi/nucleo_h743zi.dts @@ -80,10 +80,10 @@ }; &pll { - div-m = <1>; - mul-n = <24>; + div-m = <2>; + mul-n = <240>; div-p = <2>; - div-q = <4>; + div-q = <2>; div-r = <2>; clocks = <&clk_hse>; status = "okay"; @@ -91,13 +91,13 @@ &rcc { clocks = <&pll>; - clock-frequency = ; + clock-frequency = ; d1cpre = <1>; - hpre = <1>; - d1ppre = <1>; - d2ppre1 = <1>; - d2ppre2 = <1>; - d3ppre = <1>; + hpre = <2>; + d1ppre = <2>; + d2ppre1 = <2>; + d2ppre2 = <2>; + d3ppre = <2>; }; &usart3 { diff --git a/boards/st/nucleo_h753zi/nucleo_h753zi.dts b/boards/st/nucleo_h753zi/nucleo_h753zi.dts index e3b52c2b50cfe..2a2d68b400156 100644 --- a/boards/st/nucleo_h753zi/nucleo_h753zi.dts +++ b/boards/st/nucleo_h753zi/nucleo_h753zi.dts @@ -77,10 +77,10 @@ }; &pll { - div-m = <1>; - mul-n = <24>; + div-m = <2>; + mul-n = <240>; div-p = <2>; - div-q = <4>; + div-q = <2>; div-r = <2>; clocks = <&clk_hse>; status = "okay"; @@ -88,13 +88,13 @@ &rcc { clocks = <&pll>; - clock-frequency = ; + clock-frequency = ; d1cpre = <1>; - hpre = <1>; - d1ppre = <1>; - d2ppre1 = <1>; - d2ppre2 = <1>; - d3ppre = <1>; + hpre = <2>; + d1ppre = <2>; + d2ppre1 = <2>; + d2ppre2 = <2>; + d3ppre = <2>; }; &usart3 { From 0a5e7f8589f6d6c78d52f8b759618a4987b27121 Mon Sep 17 00:00:00 2001 From: Yuxuan Cai Date: Tue, 28 May 2024 07:44:20 -0700 Subject: [PATCH 2020/2849] samples: Bluetooth: use correct periodic advertising intervals BT_GAP_ADV_SLOW_INT_MIN and BT_GAP_ADV_SLOW_INT_MAX represent 1s and 1.2s, respectively, in the extended advertising context, where the bit interval is 0.625 ms. Using them for periodic advertising will result in a range of [2s, 2.4s], as the bit interval for periodic advertising is 1.25ms. Instead, BT_GAP_PER_ADV_SLOW_INT_MIN and BT_GAP_PER_ADV_SLOW_INT_MAX should be used in this sample, and the range will become [1s, 1.2s]. Signed-off-by: Yuxuan Cai --- .../bluetooth/direction_finding_connectionless_tx/src/main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/samples/bluetooth/direction_finding_connectionless_tx/src/main.c b/samples/bluetooth/direction_finding_connectionless_tx/src/main.c index ef6a89b885239..f827e39a6573c 100644 --- a/samples/bluetooth/direction_finding_connectionless_tx/src/main.c +++ b/samples/bluetooth/direction_finding_connectionless_tx/src/main.c @@ -42,8 +42,8 @@ static struct bt_le_ext_adv_start_param ext_adv_start_param = { }; static struct bt_le_per_adv_param per_adv_param = { - .interval_min = BT_GAP_ADV_SLOW_INT_MIN, - .interval_max = BT_GAP_ADV_SLOW_INT_MAX, + .interval_min = BT_GAP_PER_ADV_SLOW_INT_MIN, + .interval_max = BT_GAP_PER_ADV_SLOW_INT_MAX, .options = BT_LE_ADV_OPT_USE_TX_POWER, }; From 8124d064e933c8bcd039bd0768cc3e278a290411 Mon Sep 17 00:00:00 2001 From: frei tycho Date: Tue, 30 Apr 2024 11:54:05 +0000 Subject: [PATCH 2021/2849] include: zephyr: coding guidelines: add explicit cast to void - added explicit cast to void when returned value is expectedly ignored Signed-off-by: frei tycho --- include/zephyr/spinlock.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/include/zephyr/spinlock.h b/include/zephyr/spinlock.h index 7b0d3a7b61afc..451e91cbd5475 100644 --- a/include/zephyr/spinlock.h +++ b/include/zephyr/spinlock.h @@ -316,7 +316,7 @@ static ALWAYS_INLINE void k_spin_unlock(struct k_spinlock *l, #ifdef CONFIG_SMP #ifdef CONFIG_TICKET_SPINLOCKS /* Give the spinlock to the next CPU in a FIFO */ - atomic_inc(&l->owner); + (void)atomic_inc(&l->owner); #else /* Strictly we don't need atomic_clear() here (which is an * exchange operation that returns the old value). We are always @@ -325,7 +325,7 @@ static ALWAYS_INLINE void k_spin_unlock(struct k_spinlock *l, * a memory barrier when used like this, and we don't have a * Zephyr framework for that. */ - atomic_clear(&l->locked); + (void)atomic_clear(&l->locked); #endif /* CONFIG_TICKET_SPINLOCKS */ #endif /* CONFIG_SMP */ arch_irq_unlock(key.key); @@ -364,9 +364,9 @@ static ALWAYS_INLINE void k_spin_release(struct k_spinlock *l) #endif #ifdef CONFIG_SMP #ifdef CONFIG_TICKET_SPINLOCKS - atomic_inc(&l->owner); + (void)atomic_inc(&l->owner); #else - atomic_clear(&l->locked); + (void)atomic_clear(&l->locked); #endif /* CONFIG_TICKET_SPINLOCKS */ #endif /* CONFIG_SMP */ } From b08dfe436d4abd881f798e3018189cab9152cfcf Mon Sep 17 00:00:00 2001 From: Maxin John Date: Sun, 28 Apr 2024 08:50:56 +0300 Subject: [PATCH 2022/2849] boards: sipeed: longan_nano: update SPI documentation Update SPI documentation for longan_nano. In longan_nano board, spi1 is connected to sdhc0. Verified the functionality using "samples/subsys/fs/fs_sample". Fixes: #64759 Signed-off-by: Maxin John --- boards/sipeed/longan_nano/doc/index.rst | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/boards/sipeed/longan_nano/doc/index.rst b/boards/sipeed/longan_nano/doc/index.rst index b62d91c313007..6150c2378cf81 100644 --- a/boards/sipeed/longan_nano/doc/index.rst +++ b/boards/sipeed/longan_nano/doc/index.rst @@ -74,6 +74,11 @@ The board configuration supports the following hardware features: * - ADC - :kconfig:option:`CONFIG_ADC` - :dtcompatible:`gd,gd32-adc` + * - SPI + - :kconfig:option:`CONFIG_SPI` + - :dtcompatible:`gd,gd32-spi` + +The microSD card reader in Longan Nano board is connected to SPI1. Serial Port =========== From 3b4c458815793e388508e82e91e21d4485ade145 Mon Sep 17 00:00:00 2001 From: Helmut Lord Date: Tue, 23 Apr 2024 11:41:21 -0400 Subject: [PATCH 2023/2849] shields: waveshare_epaper: add 2.13in epaper Adds support for WaveShare's 2.13in epaper display with the ssd1680 display driver. Good Display part number gdey0213b74 Signed-off-by: Helmut Lord --- .../waveshare_epaper/Kconfig.defconfig | 3 +- .../shields/waveshare_epaper/Kconfig.shield | 3 ++ boards/shields/waveshare_epaper/doc/index.rst | 3 ++ .../waveshare_epaper_gdey0213b74.overlay | 36 +++++++++++++++++++ 4 files changed, 43 insertions(+), 2 deletions(-) create mode 100644 boards/shields/waveshare_epaper/waveshare_epaper_gdey0213b74.overlay diff --git a/boards/shields/waveshare_epaper/Kconfig.defconfig b/boards/shields/waveshare_epaper/Kconfig.defconfig index 5f7f13a0b16e4..6087880f4f378 100644 --- a/boards/shields/waveshare_epaper/Kconfig.defconfig +++ b/boards/shields/waveshare_epaper/Kconfig.defconfig @@ -5,8 +5,7 @@ # SPDX-License-Identifier: Apache-2.0 # -if SHIELD_WAVESHARE_EPAPER_GDEH029A1 || SHIELD_WAVESHARE_EPAPER_GDEH0213B1 || SHIELD_WAVESHARE_EPAPER_GDEH0213B72 || SHIELD_WAVESHARE_EPAPER_GDEW075T7 || SHIELD_WAVESHARE_EPAPER_GDEH0154A07 || SHIELD_WAVESHARE_EPAPER_GDEW042T2 || SHIELD_WAVESHARE_EPAPER_GDEW042T2_P - +if SHIELD_WAVESHARE_EPAPER_GDEH029A1 || SHIELD_WAVESHARE_EPAPER_GDEH0213B1 || SHIELD_WAVESHARE_EPAPER_GDEH0213B72 || SHIELD_WAVESHARE_EPAPER_GDEW075T7 || SHIELD_WAVESHARE_EPAPER_GDEH0154A07 || SHIELD_WAVESHARE_EPAPER_GDEW042T2 || SHIELD_WAVESHARE_EPAPER_GDEW042T2_P || SHIELD_WAVESHARE_EPAPER_GDEY0213B74 if DISPLAY diff --git a/boards/shields/waveshare_epaper/Kconfig.shield b/boards/shields/waveshare_epaper/Kconfig.shield index 863059e57843c..b3fe949cb3ae3 100644 --- a/boards/shields/waveshare_epaper/Kconfig.shield +++ b/boards/shields/waveshare_epaper/Kconfig.shield @@ -21,3 +21,6 @@ config SHIELD_WAVESHARE_EPAPER_GDEW042T2 config SHIELD_WAVESHARE_EPAPER_GDEW042T2_P def_bool $(shields_list_contains,waveshare_epaper_gdew042t2-p) + +config SHIELD_WAVESHARE_EPAPER_GDEY0213B74 + def_bool $(shields_list_contains,waveshare_epaper_gdey0213b74) diff --git a/boards/shields/waveshare_epaper/doc/index.rst b/boards/shields/waveshare_epaper/doc/index.rst index 876ba1d107e8c..25c4ecd955e40 100644 --- a/boards/shields/waveshare_epaper/doc/index.rst +++ b/boards/shields/waveshare_epaper/doc/index.rst @@ -65,6 +65,9 @@ Current supported displays | Good Display | WFT0420CZ15 | UC8176 / | waveshare_epaper_gdew042t2 | | GDEW042T2 | | gd7965 | waveshare_epaper_gdew042t2-p | +--------------+-----------------+--------------+------------------------------+ +| Good Display | FPC-A002 | SSD1680 / | waveshare_epaper_gdey0213b74 | +| GDEY0213B74 | | ssd16xx | | ++--------------+-----------------+--------------+------------------------------+ Requirements diff --git a/boards/shields/waveshare_epaper/waveshare_epaper_gdey0213b74.overlay b/boards/shields/waveshare_epaper/waveshare_epaper_gdey0213b74.overlay new file mode 100644 index 0000000000000..bd77a1ede516a --- /dev/null +++ b/boards/shields/waveshare_epaper/waveshare_epaper_gdey0213b74.overlay @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2024, Kelly Helmut Lord + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "waveshare_epaper_common.dtsi" + +/ { + chosen { + zephyr,display = &ssd16xx_waveshare_epaper_gdey0213b74; + }; +}; + +&arduino_spi { + ssd16xx_waveshare_epaper_gdey0213b74: ssd16xxfb@0 { + compatible = "gooddisplay,gdey0213b74", "solomon,ssd1680"; + spi-max-frequency = <4000000>; + reg = <0>; + width = <250>; + height = <122>; + dc-gpios = <&arduino_header 15 GPIO_ACTIVE_LOW>; /* D9 */ + reset-gpios = <&arduino_header 14 GPIO_ACTIVE_LOW>; /* D8 */ + busy-gpios = <&arduino_header 13 GPIO_ACTIVE_HIGH>; /* D7 */ + + tssv = <0x80>; + + full { + border-waveform = <0x05>; + }; + + partial { + border-waveform = <0x3c>; + }; + }; +}; From 45085ba647cab9c95b162c86697d9e09daf661f3 Mon Sep 17 00:00:00 2001 From: Siddharth Chandrasekaran Date: Wed, 1 Nov 2023 23:43:02 +0100 Subject: [PATCH 2024/2849] mgmt/osdp: cp: disallow unexpected SC responses When CP has a secure channel active, it should never receive a REPLY_CCRYPT or REPLY_RMAC_I. Since these responses change the SC state, let's also make sure that they are accepted only when they are expected: in response to commands CMD_CHLNG and CMD_SCRYPT respectively. Reported-by: Eran Jacob Signed-off-by: Siddharth Chandrasekaran --- subsys/mgmt/osdp/src/osdp_cp.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/subsys/mgmt/osdp/src/osdp_cp.c b/subsys/mgmt/osdp/src/osdp_cp.c index cf475c5c4cb87..d2b2735a6195f 100644 --- a/subsys/mgmt/osdp/src/osdp_cp.c +++ b/subsys/mgmt/osdp/src/osdp_cp.c @@ -511,6 +511,10 @@ static int cp_decode_response(struct osdp_pd *pd, uint8_t *buf, int len) break; #ifdef CONFIG_OSDP_SC_ENABLED case REPLY_CCRYPT: + if (sc_is_active(pd) || pd->cmd_id != CMD_CHLNG) { + LOG_ERR("Out of order REPLY_CCRYPT; has PD gone rogue?"); + break; + } if (len != REPLY_CCRYPT_DATA_LEN) { break; } @@ -526,6 +530,10 @@ static int cp_decode_response(struct osdp_pd *pd, uint8_t *buf, int len) ret = OSDP_CP_ERR_NONE; break; case REPLY_RMAC_I: + if (sc_is_active(pd) || pd->cmd_id != CMD_SCRYPT) { + LOG_ERR("Out of order REPLY_RMAC_I; has PD gone rogue?"); + break; + } if (len != REPLY_RMAC_I_DATA_LEN) { break; } From 593dfe13856df4d2919874037cbb5691b9f00a15 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20Cab=C3=A9?= Date: Tue, 4 Jun 2024 17:49:19 +0200 Subject: [PATCH 2025/2849] doc: kernel: fix improper Sphinx C domain usage MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit fixed usage of wrong C roles (e.g. `:c:struct:` instead of `:c:type:`) which Breathe tolerates but can cause trouble when using other systems. Signed-off-by: Benjamin Cabé --- doc/kernel/data_structures/dlist.rst | 8 ++++---- doc/kernel/data_structures/ring_buffers.rst | 2 +- doc/kernel/data_structures/slist.rst | 16 ++++++++-------- .../memory_management/shared_multi_heap.rst | 4 ++-- doc/kernel/services/polling.rst | 9 +++++---- doc/kernel/services/threads/workqueue.rst | 12 ++++++------ doc/kernel/services/timing/clocks.rst | 10 +++++----- doc/kernel/services/timing/timers.rst | 4 ++-- 8 files changed, 33 insertions(+), 32 deletions(-) diff --git a/doc/kernel/data_structures/dlist.rst b/doc/kernel/data_structures/dlist.rst index f045c939193e2..7366d37f4f9b7 100644 --- a/doc/kernel/data_structures/dlist.rst +++ b/doc/kernel/data_structures/dlist.rst @@ -11,9 +11,9 @@ the head, tail or any internal node). To do this, the list stores two pointers per node, and thus has somewhat higher runtime code and memory space needs. -A :c:struct:`sys_dlist_t` struct may be instantiated by the user in any +A :c:type:`sys_dlist_t` struct may be instantiated by the user in any accessible memory. It must be initialized with :c:func:`sys_dlist_init` -or :c:macro:`SYS_DLIST_STATIC_INIT` before use. The :c:struct:`sys_dnode_t` struct +or :c:macro:`SYS_DLIST_STATIC_INIT` before use. The :c:type:`sys_dnode_t` struct is expected to be provided by the user for any nodes added to the list (typically embedded within the struct to be tracked, as described above). It must be initialized in zeroed/bss memory or with @@ -50,8 +50,8 @@ implementation that has zero overhead vs. the normal list processing). Double-linked List Internals ---------------------------- -Internally, the dlist implementation is minimal: the :c:struct:`sys_dlist_t` -struct contains "head" and "tail" pointer fields, the :c:struct:`sys_dnode_t` +Internally, the dlist implementation is minimal: the :c:type:`sys_dlist_t` +struct contains "head" and "tail" pointer fields, the :c:type:`sys_dnode_t` contains "prev" and "next" pointers, and no other data is stored. But in practice the two structs are internally identical, and the list struct is inserted as a node into the list itself. This allows for a diff --git a/doc/kernel/data_structures/ring_buffers.rst b/doc/kernel/data_structures/ring_buffers.rst index d077cf1f21fb7..409b1c2bdc624 100644 --- a/doc/kernel/data_structures/ring_buffers.rst +++ b/doc/kernel/data_structures/ring_buffers.rst @@ -198,7 +198,7 @@ Implementation Defining a Ring Buffer ====================== -A ring buffer is defined using a variable of type :c:type:`ring_buf`. +A ring buffer is defined using a variable of type :c:struct:`ring_buf`. It must then be initialized by calling :c:func:`ring_buf_init` or :c:func:`ring_buf_item_init`. diff --git a/doc/kernel/data_structures/slist.rst b/doc/kernel/data_structures/slist.rst index c1eb062ff83df..cfffe802895ee 100644 --- a/doc/kernel/data_structures/slist.rst +++ b/doc/kernel/data_structures/slist.rst @@ -3,7 +3,7 @@ Single-linked List ================== -Zephyr provides a :c:struct:`sys_slist_t` type for storing simple +Zephyr provides a :c:type:`sys_slist_t` type for storing simple singly-linked list data (i.e. data where each list element stores a pointer to the next element, but not the previous one). This supports constant-time access to the first (head) and last (tail) elements of @@ -12,7 +12,7 @@ constant time removal of the head. Removal of subsequent nodes requires access to the "previous" pointer and thus can only be performed in linear time by searching the list. -The :c:struct:`sys_slist_t` struct may be instantiated by the user in any +The :c:type:`sys_slist_t` struct may be instantiated by the user in any accessible memory. It should be initialized with either :c:func:`sys_slist_init` or by static assignment from SYS_SLIST_STATIC_INIT before use. Its interior fields are opaque and should not be accessed @@ -21,15 +21,15 @@ by user code. The end nodes of a list may be retrieved with :c:func:`sys_slist_peek_head` and :c:func:`sys_slist_peek_tail`, which will return NULL if the list is empty, otherwise a pointer to a -:c:struct:`sys_snode_t` struct. +:c:type:`sys_snode_t` struct. -The :c:struct:`sys_snode_t` struct represents the data to be inserted. In +The :c:type:`sys_snode_t` struct represents the data to be inserted. In general, it is expected to be allocated/controlled by the user, usually embedded within a struct which is to be added to the list. The container struct pointer may be retrieved from a list node using :c:macro:`SYS_SLIST_CONTAINER`, passing it the struct name of the containing struct and the field name of the node. Internally, the -:c:struct:`sys_snode_t` struct contains only a next pointer, which may be +:c:type:`sys_snode_t` struct contains only a next pointer, which may be accessed with :c:func:`sys_slist_peek_next`. Lists may be modified by adding a single node at the head or tail with @@ -66,8 +66,8 @@ Single-linked List Internals ---------------------------- The slist code is designed to be minimal and conventional. -Internally, a :c:struct:`sys_slist_t` struct is nothing more than a pair of -"head" and "tail" pointer fields. And a :c:struct:`sys_snode_t` stores only a +Internally, a :c:type:`sys_slist_t` struct is nothing more than a pair of +"head" and "tail" pointer fields. And a :c:type:`sys_snode_t` stores only a single "next" pointer. .. figure:: slist.png @@ -101,7 +101,7 @@ Only one such variant, sflist, exists in Zephyr at the moment. Flagged List ------------ -The :c:struct:`sys_sflist_t` is implemented using the described genlist +The :c:type:`sys_sflist_t` is implemented using the described genlist template API. With the exception of symbol naming ("sflist" instead of "slist") and the additional API described next, it operates in all ways identically to the slist API. diff --git a/doc/kernel/memory_management/shared_multi_heap.rst b/doc/kernel/memory_management/shared_multi_heap.rst index 89458ecb927c6..cc5101ae1fbfe 100644 --- a/doc/kernel/memory_management/shared_multi_heap.rst +++ b/doc/kernel/memory_management/shared_multi_heap.rst @@ -18,7 +18,7 @@ This framework is commonly used as follow: the pool with :c:func:`shared_multi_heap_add()`, possibly gathering the needed information for the regions from the DT. -2. Each memory region encoded in a :c:type:`shared_multi_heap_region` +2. Each memory region encoded in a :c:struct:`shared_multi_heap_region` structure. This structure is also carrying an opaque and user-defined integer value that is used to define the region capabilities (for example: cacheability, cpu affinity, etc...) @@ -76,7 +76,7 @@ Adding new attributes ********************* The API does not enforce any attributes, but at least it defines the two most -common ones: :c:enum:`SMH_REG_ATTR_CACHEABLE` and :c:enum:`SMH_REG_ATTR_NON_CACHEABLE` +common ones: :c:enumerator:`SMH_REG_ATTR_CACHEABLE` and :c:enumerator:`SMH_REG_ATTR_NON_CACHEABLE`. .. doxygengroup:: shared_multi_heap :project: Zephyr diff --git a/doc/kernel/services/polling.rst b/doc/kernel/services/polling.rst index 46e586badb6e9..685a3023d5eb7 100644 --- a/doc/kernel/services/polling.rst +++ b/doc/kernel/services/polling.rst @@ -78,14 +78,15 @@ Poll events can be initialized using either the runtime initializers :c:macro:`K_POLL_EVENT_INITIALIZER()` or :c:func:`k_poll_event_init`, or the static initializer :c:macro:`K_POLL_EVENT_STATIC_INITIALIZER()`. An object that matches the **type** specified must be passed to the initializers. The -**mode** *must* be set to :c:macro:`K_POLL_MODE_NOTIFY_ONLY`. The state *must* -be set to :c:macro:`K_POLL_STATE_NOT_READY` (the initializers take care of -this). The user **tag** is optional and completely opaque to the API: it is +**mode** *must* be set to :c:enumerator:`K_POLL_MODE_NOTIFY_ONLY`. The state +*must* be set to :c:macro:`K_POLL_STATE_NOT_READY` (the initializers take care +of this). The user **tag** is optional and completely opaque to the API: it is there to help a user to group similar events together. Being optional, it is passed to the static initializer, but not the runtime ones for performance reasons. If using runtime initializers, the user must set it separately in the :c:struct:`k_poll_event` data structure. If an event in the array is to be -ignored, most likely temporarily, its type can be set to K_POLL_TYPE_IGNORE. +ignored, most likely temporarily, its type can be set to +:c:macro:`K_POLL_TYPE_IGNORE`. .. code-block:: c diff --git a/doc/kernel/services/threads/workqueue.rst b/doc/kernel/services/threads/workqueue.rst index b221e1163b7cd..18c1cf0e31a63 100644 --- a/doc/kernel/services/threads/workqueue.rst +++ b/doc/kernel/services/threads/workqueue.rst @@ -71,7 +71,7 @@ itself. The work item also maintains information about its status. A work item must be initialized before it can be used. This records the work item's handler function and marks it as not pending. -A work item may be **queued** (:c:macro:`K_WORK_QUEUED`) by submitting it to a +A work item may be **queued** (:c:enumerator:`K_WORK_QUEUED`) by submitting it to a workqueue by an ISR or a thread. Submitting a work item appends the work item to the workqueue's queue. Once the workqueue's thread has processed all of the preceding work items in its queue the thread will remove the next work @@ -80,11 +80,11 @@ the scheduling priority of the workqueue's thread, and the work required by other items in the queue, a queued work item may be processed quickly or it may remain in the queue for an extended period of time. -A delayable work item may be **scheduled** (:c:macro:`K_WORK_DELAYED`) to a +A delayable work item may be **scheduled** (:c:enumerator:`K_WORK_DELAYED`) to a workqueue; see `Delayable Work`_. -A work item will be **running** (:c:macro:`K_WORK_RUNNING`) when it is running -on a work queue, and may also be **canceling** (:c:macro:`K_WORK_CANCELING`) +A work item will be **running** (:c:enumerator:`K_WORK_RUNNING`) when it is running +on a work queue, and may also be **canceling** (:c:enumerator:`K_WORK_CANCELING`) if it started running before a thread has requested that it be cancelled. A work item can be in multiple states; for example it can be: @@ -248,7 +248,7 @@ The following code defines and initializes a workqueue: In addition the queue identity and certain behavior related to thread rescheduling can be controlled by the optional final parameter; see -:c:struct:`k_work_queue_start()` for details. +:c:func:`k_work_queue_start()` for details. The following API can be used to interact with a workqueue: @@ -416,7 +416,7 @@ be a flag indicating that work needs to be done, or a shared object that is filled by an ISR or thread and read by the work handler. For simple flags :ref:`atomic_v2` may be sufficient. In other cases spin -locks (:c:struct:`k_spinlock_t`) or thread-aware locks (:c:struct:`k_sem`, +locks (:c:struct:`k_spinlock`) or thread-aware locks (:c:struct:`k_sem`, :c:struct:`k_mutex` , ...) may be used to ensure data races don't occur. If the selected lock mechanism can :ref:`api_term_sleep` then allowing the diff --git a/doc/kernel/services/timing/clocks.rst b/doc/kernel/services/timing/clocks.rst index 0517d601f2767..4d88606938ee8 100644 --- a/doc/kernel/services/timing/clocks.rst +++ b/doc/kernel/services/timing/clocks.rst @@ -98,7 +98,7 @@ For example: * The kernel :c:struct:`k_work_delayable` API provides a timeout parameter indicating when a work queue item will be added to the system queue. -All these values are specified using a :c:struct:`k_timeout_t` value. This is +All these values are specified using a :c:type:`k_timeout_t` value. This is an opaque struct type that must be initialized using one of a family of kernel timeout macros. The most common, :c:macro:`K_MSEC`, defines a time in milliseconds after the current time. @@ -123,7 +123,7 @@ described above: :c:macro:`K_NSEC()`, :c:macro:`K_USEC`, :c:macro:`K_TICKS` and :c:macro:`K_CYC()` specify timeout values that will expire after specified numbers of nanoseconds, microseconds, ticks and cycles, respectively. -Precision of :c:struct:`k_timeout_t` values is configurable, with the default +Precision of :c:type:`k_timeout_t` values is configurable, with the default being 32 bits. Large uptime counts in non-tick units will experience complicated rollover semantics, so it is expected that timing-sensitive applications with long uptimes will be configured to @@ -141,16 +141,16 @@ Timing Internals Timeout Queue ------------- -All Zephyr :c:struct:`k_timeout_t` events specified using the API above are +All Zephyr :c:type:`k_timeout_t` events specified using the API above are managed in a single, global queue of events. Each event is stored in a double-linked list, with an attendant delta count in ticks from the previous event. The action to take on an event is specified as a callback function pointer provided by the subsystem requesting the event, along with a :c:struct:`_timeout` tracking struct that is expected to be embedded within subsystem-defined data structures (for -example: a :c:struct:`wait_q` struct, or a :c:struct:`k_tid_t` thread struct). +example: a :c:struct:`wait_q` struct, or a :c:type:`k_tid_t` thread struct). -Note that all variant units passed via a :c:struct:`k_timeout_t` are converted +Note that all variant units passed via a :c:type:`k_timeout_t` are converted to ticks once on insertion into the list. There no multiple-conversion steps internal to the kernel, so precision is guaranteed at the tick level no matter how many events exist or how diff --git a/doc/kernel/services/timing/timers.rst b/doc/kernel/services/timing/timers.rst index 9b1e424921de4..7fd3e2e46010d 100644 --- a/doc/kernel/services/timing/timers.rst +++ b/doc/kernel/services/timing/timers.rst @@ -22,11 +22,11 @@ is referenced by its memory address. A timer has the following key properties: * A **duration** specifying the time interval before the timer - expires for the first time. This is a ``k_timeout_t`` value that + expires for the first time. This is a :c:type:`k_timeout_t` value that may be initialized via different units. * A **period** specifying the time interval between all timer - expirations after the first one, also a ``k_timeout_t``. It must be + expirations after the first one, also a :c:type:`k_timeout_t`. It must be non-negative. A period of ``K_NO_WAIT`` (i.e. zero) or ``K_FOREVER`` means that the timer is a one-shot timer that stops after a single expiration. (For example then, if a timer is started From f30b414bbc028caed191d70dfa77a9fa69cbbe4a Mon Sep 17 00:00:00 2001 From: Fabio Baltieri Date: Thu, 6 Jun 2024 15:31:14 +0100 Subject: [PATCH 2026/2849] build: drop the CONFIG_LEGACY_GENERATED_INCLUDE_PATH message Does not make much sense to ship the project with a config that by default print a warning for a not-yet-deprecated feature. Let's drop it for now, we can reintroduce it once the default is changed. Signed-off-by: Fabio Baltieri --- CMakeLists.txt | 5 ----- 1 file changed, 5 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 05c50b119bc41..0afc945667b1a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -111,11 +111,6 @@ zephyr_library_named(zephyr) if(CONFIG_LEGACY_GENERATED_INCLUDE_PATH) zephyr_include_directories(${PROJECT_BINARY_DIR}/include/generated/zephyr) - message(WARNING " - Warning: CONFIG_LEGACY_GENERATED_INCLUDE_PATH is currently enabled by default - so that user applications can continue to use the legacy include paths for the - generated headers. This Kconfig will be deprecated and eventually removed in - the future releases.") endif() zephyr_include_directories( From bb4c92af7c5d3b06db60d955b21d4c3ffb317969 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Karol=20Laso=C5=84czyk?= Date: Fri, 26 Apr 2024 16:32:56 +0200 Subject: [PATCH 2027/2849] boards: nordic: Add PWM support for LEDs on nRF54 DKs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds support for first possible LED to be connected with HW PWM. Signed-off-by: Karol Lasończyk --- .../nrf54h20dk_nrf54h20-pinctrl.dtsi | 13 ++++++++++++ .../nrf54h20dk/nrf54h20dk_nrf54h20_cpuapp.dts | 21 +++++++++++++++++++ .../nrf54l15pdk_nrf54l15-common.dtsi | 21 +++++++++++++++++++ .../nrf54l15pdk_nrf54l15-pinctrl.dtsi | 13 ++++++++++++ .../nrf54l15pdk_nrf54l15_common_0_2_1.dtsi | 15 +++++++++++++ 5 files changed, 83 insertions(+) diff --git a/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20-pinctrl.dtsi b/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20-pinctrl.dtsi index efa58b2ffb59b..da3effb5af8fe 100644 --- a/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20-pinctrl.dtsi +++ b/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20-pinctrl.dtsi @@ -66,4 +66,17 @@ ; }; }; + + /omit-if-no-ref/ pwm130_default: pwm130_default { + group1 { + psels = ; + }; + }; + + /omit-if-no-ref/ pwm130_sleep: pwm130_sleep { + group1 { + psels = ; + low-power-enable; + }; + }; }; diff --git a/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpuapp.dts b/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpuapp.dts index 241539554e868..1d9e5dd4a545e 100644 --- a/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpuapp.dts +++ b/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpuapp.dts @@ -36,6 +36,7 @@ led2 = &led2; led3 = &led3; resetinfo = &cpuapp_resetinfo; + pwm-led0 = &pwm_led2; sw0 = &button0; sw1 = &button1; sw2 = &button2; @@ -95,6 +96,18 @@ label = "Green LED 3"; }; }; + + pwmleds { + compatible = "pwm-leds"; + /* + * LEDs are connected to GPIO Port 9 - pins 0-3. There is no valid hardware + * configuration to pass PWM signal on pis 0 and 1. First valid config is P9.2. + * Signal on PWM130's channel 0 can be passed directly on GPIO Port 9 pin 2. + */ + pwm_led2: pwm_led_2 { + pwms = <&pwm130 0 PWM_MSEC(20) PWM_POLARITY_NORMAL>; + }; + }; }; &cpuapp_ram0x_region { @@ -261,3 +274,11 @@ zephyr_udc0: &usbhs { pinctrl-0 = <&can120_default>; pinctrl-names = "default"; }; + +&pwm130 { + status = "okay"; + pinctrl-0 = <&pwm130_default>; + pinctrl-1 = <&pwm130_sleep>; + pinctrl-names = "default", "sleep"; + memory-regions = <&cpuapp_dma_region>; +}; diff --git a/boards/nordic/nrf54l15pdk/nrf54l15pdk_nrf54l15-common.dtsi b/boards/nordic/nrf54l15pdk/nrf54l15pdk_nrf54l15-common.dtsi index 75dbe78409793..9668cbe5bbf20 100644 --- a/boards/nordic/nrf54l15pdk/nrf54l15pdk_nrf54l15-common.dtsi +++ b/boards/nordic/nrf54l15pdk/nrf54l15pdk_nrf54l15-common.dtsi @@ -27,6 +27,19 @@ }; }; + pwmleds { + compatible = "pwm-leds"; + /* + * PWM signal can be exposed on GPIO pin only within same domain. + * There is only one domain which contains both PWM and GPIO: + * PWM20/21/22 and GPIO Port P1. + * Only LEDs connected to P1 can work with PWM, for example LED1. + */ + pwm_led1: pwm_led_1 { + pwms = <&pwm20 0 PWM_MSEC(20) PWM_POLARITY_NORMAL>; + }; + }; + buttons { compatible = "gpio-keys"; button0: button_0 { @@ -56,6 +69,7 @@ led1 = &led1; led2 = &led2; led3 = &led3; + pwm-led0 = &pwm_led1; sw0 = &button0; sw1 = &button1; sw2 = &button2; @@ -77,3 +91,10 @@ pinctrl-1 = <&uart30_sleep>; pinctrl-names = "default", "sleep"; }; + +&pwm20 { + status = "okay"; + pinctrl-0 = <&pwm20_default>; + pinctrl-1 = <&pwm20_sleep>; + pinctrl-names = "default", "sleep"; +}; diff --git a/boards/nordic/nrf54l15pdk/nrf54l15pdk_nrf54l15-pinctrl.dtsi b/boards/nordic/nrf54l15pdk/nrf54l15pdk_nrf54l15-pinctrl.dtsi index 043d35adcf41e..0b6e2056a82e1 100644 --- a/boards/nordic/nrf54l15pdk/nrf54l15pdk_nrf54l15-pinctrl.dtsi +++ b/boards/nordic/nrf54l15pdk/nrf54l15pdk_nrf54l15-pinctrl.dtsi @@ -64,4 +64,17 @@ low-power-enable; }; }; + + /omit-if-no-ref/ pwm20_default: pwm20_default { + group1 { + psels = ; + }; + }; + + /omit-if-no-ref/ pwm20_sleep: pwm20_sleep { + group1 { + psels = ; + low-power-enable; + }; + }; }; diff --git a/boards/nordic/nrf54l15pdk/nrf54l15pdk_nrf54l15_common_0_2_1.dtsi b/boards/nordic/nrf54l15pdk/nrf54l15pdk_nrf54l15_common_0_2_1.dtsi index bfe673ec966e5..a37cf23096670 100644 --- a/boards/nordic/nrf54l15pdk/nrf54l15pdk_nrf54l15_common_0_2_1.dtsi +++ b/boards/nordic/nrf54l15pdk/nrf54l15pdk_nrf54l15_common_0_2_1.dtsi @@ -35,3 +35,18 @@ &button3 { gpios = <&gpio2 10 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>; }; + +&pinctrl { + /omit-if-no-ref/ pwm20_default: pwm20_default { + group1 { + psels = ; + }; + }; + + /omit-if-no-ref/ pwm20_sleep: pwm20_sleep { + group1 { + psels = ; + low-power-enable; + }; + }; +}; From e1246ccb65632ed1841e7a1a6be9492e5e2e90c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fin=20Maa=C3=9F?= Date: Fri, 3 May 2024 08:22:42 +0200 Subject: [PATCH 2028/2849] mgmt: hawkbit: some Kconfig improvements MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit some hawkbit Kconfig improvements. Signed-off-by: Fin Maaß --- subsys/mgmt/hawkbit/Kconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/subsys/mgmt/hawkbit/Kconfig b/subsys/mgmt/hawkbit/Kconfig index 6b806f28a8091..64d18b0c60b26 100644 --- a/subsys/mgmt/hawkbit/Kconfig +++ b/subsys/mgmt/hawkbit/Kconfig @@ -30,7 +30,8 @@ config HAWKBIT_POLL_INTERVAL range 1 43200 help Set the interval that the hawkbit update server will be polled. - This time interval is zero and 43200 minutes(30 days). + This time interval is zero and 43200 minutes(30 days). This will be overridden + by the value configured in the settings of the hawkBit server. config HAWKBIT_SHELL bool "hawkBit shell utilities" @@ -40,7 +41,6 @@ config HAWKBIT_SHELL config HAWKBIT_SERVER string "User address for the hawkbit server" - default "" help Configure the hawkbit server address. From 073e627e3bbe5f536d46653fd5bcb6599b93cb35 Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Mon, 20 May 2024 18:08:52 +0200 Subject: [PATCH 2029/2849] Bluetooth: Controller: Fix ENTROPY_NRF5_RNG conditional compile Fix ENTROPY_NRF5_RNG conditional compile when not enabled. Signed-off-by: Vinayak Kariappa Chettimada --- subsys/bluetooth/controller/Kconfig | 1 - .../bluetooth/controller/Kconfig.ll_sw_split | 4 +-- .../controller/ll_sw/nordic/lll/lll.c | 36 +++++++++++++++++++ 3 files changed, 38 insertions(+), 3 deletions(-) diff --git a/subsys/bluetooth/controller/Kconfig b/subsys/bluetooth/controller/Kconfig index 8be7989d24261..fa48c86c6c15d 100644 --- a/subsys/bluetooth/controller/Kconfig +++ b/subsys/bluetooth/controller/Kconfig @@ -122,7 +122,6 @@ choice BT_LL_CHOICE config BT_LL_SW_SPLIT bool "Software-based BLE Link Layer" - select ENTROPY_GENERATOR help Use Zephyr software BLE Link Layer ULL LLL split implementation. diff --git a/subsys/bluetooth/controller/Kconfig.ll_sw_split b/subsys/bluetooth/controller/Kconfig.ll_sw_split index e4428929e3585..25f7e7a7574e3 100644 --- a/subsys/bluetooth/controller/Kconfig.ll_sw_split +++ b/subsys/bluetooth/controller/Kconfig.ll_sw_split @@ -11,8 +11,8 @@ config BT_LLL_VENDOR_NORDIC depends on !$(dt_nodelabel_enabled,timer0) depends on !$(dt_nodelabel_enabled,rtc0) - select ENTROPY_NRF5_RNG - select ENTROPY_NRF5_BIAS_CORRECTION + select ENTROPY_NRF5_RNG if BT_CTLR_CRYPTO + select ENTROPY_NRF5_BIAS_CORRECTION if ENTROPY_NRF5_RNG select BT_HAS_HCI_VS select BT_CTLR_LE_ENC_SUPPORT if !BT_CTLR_DATA_LENGTH_CLEAR && \ diff --git a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll.c b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll.c index 5ed02f4051ff0..ce47ec56226c4 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll.c +++ b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll.c @@ -59,7 +59,9 @@ static struct { } event; /* Entropy device */ +#if defined(CONFIG_ENTROPY_NRF5_RNG) static const struct device *const dev_entropy = DEVICE_DT_GET(DT_NODELABEL(rng)); +#endif /* CONFIG_ENTROPY_NRF5_RNG */ static int init_reset(void); #if defined(CONFIG_BT_CTLR_LOW_LAT_ULL_DONE) @@ -173,10 +175,12 @@ int lll_init(void) { int err; +#if defined(CONFIG_ENTROPY_NRF5_RNG) /* Get reference to entropy device */ if (!device_is_ready(dev_entropy)) { return -ENODEV; } +#endif /* CONFIG_ENTROPY_NRF5_RNG */ /* Initialise LLL internals */ event.curr.abort_cb = NULL; @@ -319,22 +323,54 @@ int lll_deinit(void) int lll_csrand_get(void *buf, size_t len) { +#if defined(CONFIG_ENTROPY_NRF5_RNG) return entropy_get_entropy(dev_entropy, buf, len); +#else + /* FIXME: No suitable entropy device available yet. + * It is required by Controller to use random numbers. + * Hence, return uninitialized buf contents, for now. + */ + return 0; +#endif } int lll_csrand_isr_get(void *buf, size_t len) { +#if defined(CONFIG_ENTROPY_NRF5_RNG) return entropy_get_entropy_isr(dev_entropy, buf, len, 0); +#else + /* FIXME: No suitable entropy device available yet. + * It is required by Controller to use random numbers. + * Hence, return uninitialized buf contents, for now. + */ + return 0; +#endif } int lll_rand_get(void *buf, size_t len) { +#if defined(CONFIG_ENTROPY_NRF5_RNG) return entropy_get_entropy(dev_entropy, buf, len); +#else + /* FIXME: No suitable entropy device available yet. + * It is required by Controller to use random numbers. + * Hence, return uninitialized buf contents, for now. + */ + return 0; +#endif } int lll_rand_isr_get(void *buf, size_t len) { +#if defined(CONFIG_ENTROPY_NRF5_RNG) return entropy_get_entropy_isr(dev_entropy, buf, len, 0); +#else + /* FIXME: No suitable entropy device available yet. + * It is required by Controller to use random numbers. + * Hence, return uninitialized buf contents, for now. + */ + return 0; +#endif } int lll_reset(void) From a66baa1101ad82cb708e27e465c25180e81adaae Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Mon, 20 May 2024 09:32:52 +0200 Subject: [PATCH 2030/2849] Bluetooth: Controller: Introduce BT_CTLR_CRYPTO_SUPPORT Introduce BT_CTLR_CRYPTO_SUPPORT so that preliminary port to support nRF54L15 SoC can be upstreamed without encryption support. ENTROPY_GENERATOR now selected when BT_CTLR_CRYPTO enabled. Signed-off-by: Vinayak Kariappa Chettimada --- subsys/bluetooth/common/rpa.c | 17 ++++++++--------- subsys/bluetooth/controller/Kconfig | 6 +++++- subsys/bluetooth/controller/Kconfig.ll_sw_split | 15 ++++++++++----- subsys/bluetooth/controller/hci/hci.c | 4 ++++ .../controller/ll_sw/nordic/CMakeLists.txt | 7 ++++++- 5 files changed, 33 insertions(+), 16 deletions(-) diff --git a/subsys/bluetooth/common/rpa.c b/subsys/bluetooth/common/rpa.c index b4650d5fba2a7..c4386fd8c478f 100644 --- a/subsys/bluetooth/common/rpa.c +++ b/subsys/bluetooth/common/rpa.c @@ -23,20 +23,20 @@ #include LOG_MODULE_REGISTER(bt_rpa); -#if defined(CONFIG_BT_CTLR) && defined(CONFIG_BT_HOST_CRYPTO) +#if defined(CONFIG_BT_CTLR_CRYPTO) && defined(CONFIG_BT_HOST_CRYPTO) #include "../controller/util/util.h" #include "../controller/hal/ecb.h" -#endif /* defined(CONFIG_BT_CTLR) && defined(CONFIG_BT_HOST_CRYPTO) */ +#endif /* CONFIG_BT_CTLR_CRYPTO && CONFIG_BT_HOST_CRYPTO */ #if defined(CONFIG_BT_PRIVACY) || defined(CONFIG_BT_CTLR_PRIVACY) static int internal_rand(void *buf, size_t len) { /* Force using controller rand function. */ -#if defined(CONFIG_BT_CTLR) && defined(CONFIG_BT_HOST_CRYPTO) +#if defined(CONFIG_BT_CTLR_CRYPTO) && defined(CONFIG_BT_HOST_CRYPTO) return lll_csrand_get(buf, len); -#else +#else /* !CONFIG_BT_CTLR_CRYPTO || !CONFIG_BT_HOST_CRYPTO */ return bt_rand(buf, len); -#endif +#endif /* !CONFIG_BT_CTLR_CRYPTO || !CONFIG_BT_HOST_CRYPTO */ } #endif /* defined(CONFIG_BT_PRIVACY) || defined(CONFIG_BT_CTLR_PRIVACY) */ @@ -44,13 +44,12 @@ static int internal_encrypt_le(const uint8_t key[16], const uint8_t plaintext[16 uint8_t enc_data[16]) { /* Force using controller encrypt function if supported. */ -#if defined(CONFIG_BT_CTLR) && defined(CONFIG_BT_HOST_CRYPTO) && \ - defined(CONFIG_BT_CTLR_LE_ENC) +#if defined(CONFIG_BT_CTLR_CRYPTO) && defined(CONFIG_BT_HOST_CRYPTO) ecb_encrypt(key, plaintext, enc_data, NULL); return 0; -#else +#else /* !CONFIG_BT_CTLR_CRYPTO || !CONFIG_BT_HOST_CRYPTO */ return bt_encrypt_le(key, plaintext, enc_data); -#endif +#endif /* !CONFIG_BT_CTLR_CRYPTO || !CONFIG_BT_HOST_CRYPTO */ } static int ah(const uint8_t irk[16], const uint8_t r[3], uint8_t out[3]) diff --git a/subsys/bluetooth/controller/Kconfig b/subsys/bluetooth/controller/Kconfig index fa48c86c6c15d..46d027b4e2f1e 100644 --- a/subsys/bluetooth/controller/Kconfig +++ b/subsys/bluetooth/controller/Kconfig @@ -6,6 +6,9 @@ # The following symbols are enabled depending if the controller actually # supports the respective features. +config BT_CTLR_CRYPTO_SUPPORT + bool + config BT_CTLR_LE_ENC_SUPPORT bool @@ -139,8 +142,9 @@ comment "BLE Controller configuration" config BT_CTLR_CRYPTO bool "Crypto functions in Controller" - default y + depends on BT_CTLR_CRYPTO_SUPPORT select ENTROPY_GENERATOR + default y help Use random number generation and AES encryption support functions provided by the controller. diff --git a/subsys/bluetooth/controller/Kconfig.ll_sw_split b/subsys/bluetooth/controller/Kconfig.ll_sw_split index 25f7e7a7574e3..2b1ad6fb906c9 100644 --- a/subsys/bluetooth/controller/Kconfig.ll_sw_split +++ b/subsys/bluetooth/controller/Kconfig.ll_sw_split @@ -15,14 +15,17 @@ config BT_LLL_VENDOR_NORDIC select ENTROPY_NRF5_BIAS_CORRECTION if ENTROPY_NRF5_RNG select BT_HAS_HCI_VS - select BT_CTLR_LE_ENC_SUPPORT if !BT_CTLR_DATA_LENGTH_CLEAR && \ + select BT_CTLR_CRYPTO_SUPPORT + select BT_CTLR_LE_ENC_SUPPORT if BT_CTLR_CRYPTO_SUPPORT && \ + !BT_CTLR_DATA_LENGTH_CLEAR && \ !BT_CTLR_PHY_2M_NRF + select BT_CTLR_PRIVACY_SUPPORT if BT_CTLR_CRYPTO_SUPPORT && \ + !SOC_SERIES_NRF51X select BT_CTLR_CONN_PARAM_REQ_SUPPORT select BT_CTLR_EXT_REJ_IND_SUPPORT select BT_CTLR_PER_INIT_FEAT_XCHG_SUPPORT select BT_CTLR_DATA_LEN_UPDATE_SUPPORT if HAS_HW_NRF_CCM_LFLEN_8BIT || \ BT_CTLR_DATA_LENGTH_CLEAR - select BT_CTLR_PRIVACY_SUPPORT if !SOC_SERIES_NRF51X select BT_CTLR_EXT_SCAN_FP_SUPPORT select BT_CTLR_PHY_2M_SUPPORT if HAS_HW_NRF_RADIO_BLE_2M || \ BT_CTLR_PHY_2M_NRF @@ -64,11 +67,13 @@ config BT_LLL_VENDOR_NORDIC config BT_LLL_VENDOR_OPENISA bool "Use OpenISA LLL" depends on SOC_OPENISA_RV32M1 + select BT_HAS_HCI_VS + select BT_CTLR_CRYPTO_SUPPORT + select BT_CTLR_LE_ENC_SUPPORT if BT_CTLR_CRYPTO_SUPPORT && \ + !BT_CTLR_DATA_LENGTH_CLEAR + select BT_CTLR_PRIVACY_SUPPORT if BT_CTLR_CRYPTO_SUPPORT select BT_CTLR_PHY_UPDATE_SUPPORT select BT_CTLR_EXT_REJ_IND_SUPPORT - select BT_HAS_HCI_VS - select BT_CTLR_LE_ENC_SUPPORT if !BT_CTLR_DATA_LENGTH_CLEAR - select BT_CTLR_PRIVACY_SUPPORT select BT_TICKER_UPDATE if BT_BROADCASTER || BT_CONN diff --git a/subsys/bluetooth/controller/hci/hci.c b/subsys/bluetooth/controller/hci/hci.c index ac7c55613ad1f..0cf0d9f7d6e1f 100644 --- a/subsys/bluetooth/controller/hci/hci.c +++ b/subsys/bluetooth/controller/hci/hci.c @@ -1466,6 +1466,7 @@ static void le_rem_dev_from_fal(struct net_buf *buf, struct net_buf **evt) } #endif /* CONFIG_BT_CTLR_FILTER_ACCEPT_LIST */ +#if defined(CONFIG_BT_CTLR_CRYPTO) static void le_encrypt(struct net_buf *buf, struct net_buf **evt) { struct bt_hci_cp_le_encrypt *cmd = (void *)buf->data; @@ -1479,6 +1480,7 @@ static void le_encrypt(struct net_buf *buf, struct net_buf **evt) rp->status = 0x00; memcpy(rp->enc_data, enc_data, 16); } +#endif /* CONFIG_BT_CTLR_CRYPTO */ static void le_rand(struct net_buf *buf, struct net_buf **evt) { @@ -4338,9 +4340,11 @@ static int controller_cmd_handle(uint16_t ocf, struct net_buf *cmd, break; #endif /* CONFIG_BT_CTLR_FILTER_ACCEPT_LIST */ +#if defined(CONFIG_BT_CTLR_CRYPTO) case BT_OCF(BT_HCI_OP_LE_ENCRYPT): le_encrypt(cmd, evt); break; +#endif /* CONFIG_BT_CTLR_CRYPTO */ case BT_OCF(BT_HCI_OP_LE_RAND): le_rand(cmd, evt); diff --git a/subsys/bluetooth/controller/ll_sw/nordic/CMakeLists.txt b/subsys/bluetooth/controller/ll_sw/nordic/CMakeLists.txt index 06904eb00940f..6d09e295e6968 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/CMakeLists.txt +++ b/subsys/bluetooth/controller/ll_sw/nordic/CMakeLists.txt @@ -91,11 +91,16 @@ zephyr_library_sources( zephyr_library_sources( hal/nrf5/cntr.c - hal/nrf5/ecb.c hal/nrf5/radio/radio.c hal/nrf5/mayfly.c hal/nrf5/ticker.c ) + +zephyr_library_sources_ifdef( + CONFIG_BT_CTLR_CRYPTO + hal/nrf5/ecb.c + ) + if(CONFIG_BT_CTLR_DF AND NOT CONFIG_SOC_SERIES_BSIM_NRFXX) zephyr_library_sources( hal/nrf5/radio/radio_df.c From 2d49080cb8ec072c6ae1f1bc6463d558c77f06d0 Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Mon, 20 May 2024 09:46:28 +0200 Subject: [PATCH 2031/2849] Bluetooth: Controller: Fix BT_CTLR_LE_ENC conditional compilation Fix BT_CTLR_LE_ENC conditional compilation when feature is disabled. Signed-off-by: Vinayak Kariappa Chettimada --- subsys/bluetooth/controller/CMakeLists.txt | 4 -- subsys/bluetooth/controller/Kconfig | 7 ++- .../ll_sw/nordic/hal/nrf5/radio/radio.c | 27 ++++++++++-- .../ll_sw/nordic/hal/nrf5/radio/radio_nrf5.h | 15 +++++-- .../nordic/hal/nrf5/radio/radio_nrf5_dppi.h | 44 ++++++++++--------- .../controller/ll_sw/nordic/lll/lll_adv_iso.c | 6 ++- .../ll_sw/nordic/lll/lll_sync_iso.c | 9 ++-- .../bluetooth/controller/ll_sw/ull_adv_iso.c | 8 +++- .../bluetooth/controller/ll_sw/ull_sync_iso.c | 9 +++- 9 files changed, 89 insertions(+), 40 deletions(-) diff --git a/subsys/bluetooth/controller/CMakeLists.txt b/subsys/bluetooth/controller/CMakeLists.txt index a9761dc217d0e..6906ed1061af6 100644 --- a/subsys/bluetooth/controller/CMakeLists.txt +++ b/subsys/bluetooth/controller/CMakeLists.txt @@ -173,10 +173,6 @@ zephyr_library_sources_ifdef( zephyr_library_include_directories( . include - ) - -zephyr_library_include_directories_ifdef( - CONFIG_BT_CTLR_CRYPTO ../crypto ) diff --git a/subsys/bluetooth/controller/Kconfig b/subsys/bluetooth/controller/Kconfig index 46d027b4e2f1e..a401502dbfe57 100644 --- a/subsys/bluetooth/controller/Kconfig +++ b/subsys/bluetooth/controller/Kconfig @@ -813,9 +813,14 @@ config BT_CTLR_SYNC_ISO config BT_CTLR_BROADCAST_ISO bool - select BT_CRYPTO if BT_LL_SW_SPLIT default BT_CTLR_ADV_ISO || BT_CTLR_SYNC_ISO +config BT_CTLR_BROADCAST_ISO_ENC + bool + depends on BT_CTLR_CRYPTO_SUPPORT && BT_CTLR_BROADCAST_ISO + select BT_CRYPTO if BT_LL_SW_SPLIT + default y + config BT_CTLR_ADV_ISO_SET int "LE Isochronous Channel advertising sets" depends on BT_CTLR_ADV_ISO 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 4988276ffc91d..14dc1e40763b3 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 @@ -1136,7 +1136,9 @@ void radio_tmr_status_reset(void) { nrf_rtc_event_disable(NRF_RTC0, RTC_EVTENCLR_COMPARE2_Msk); +#if defined(CONFIG_BT_CTLR_LE_ENC) || defined(CONFIG_BT_CTLR_BROADCAST_ISO_ENC) hal_trigger_crypt_ppi_disable(); +#endif /* CONFIG_BT_CTLR_LE_ENC || CONFIG_BT_CTLR_BROADCAST_ISO_ENC */ hal_radio_nrf_ppi_channels_disable( BIT(HAL_RADIO_ENABLE_TX_ON_TICK_PPI) | @@ -1163,14 +1165,19 @@ void radio_tmr_status_reset(void) #if defined(CONFIG_BT_CTLR_DF_CONN_CTE_RX) BIT(HAL_TRIGGER_CRYPT_DELAY_PPI) | #endif /* CONFIG_BT_CTLR_DF_CONN_CTE_RX */ - BIT(HAL_TRIGGER_CRYPT_PPI)); +#if defined(CONFIG_BT_CTLR_LE_ENC) || defined(CONFIG_BT_CTLR_BROADCAST_ISO_ENC) + BIT(HAL_TRIGGER_CRYPT_PPI) | +#endif /* CONFIG_BT_CTLR_LE_ENC || CONFIG_BT_CTLR_BROADCAST_ISO_ENC */ + 0); } void radio_tmr_tx_status_reset(void) { nrf_rtc_event_disable(NRF_RTC0, RTC_EVTENCLR_COMPARE2_Msk); +#if defined(CONFIG_BT_CTLR_LE_ENC) || defined(CONFIG_BT_CTLR_BROADCAST_ISO_ENC) hal_trigger_crypt_ppi_disable(); +#endif /* CONFIG_BT_CTLR_LE_ENC || CONFIG_BT_CTLR_BROADCAST_ISO_ENC */ hal_radio_nrf_ppi_channels_disable( #if (HAL_RADIO_ENABLE_TX_ON_TICK_PPI != HAL_RADIO_ENABLE_RX_ON_TICK_PPI) && \ @@ -1201,14 +1208,19 @@ void radio_tmr_tx_status_reset(void) #if defined(CONFIG_BT_CTLR_DF_CONN_CTE_RX) BIT(HAL_TRIGGER_CRYPT_DELAY_PPI) | #endif /* CONFIG_BT_CTLR_DF_CONN_CTE_RX */ - BIT(HAL_TRIGGER_CRYPT_PPI)); +#if defined(CONFIG_BT_CTLR_LE_ENC) || defined(CONFIG_BT_CTLR_BROADCAST_ISO_ENC) + BIT(HAL_TRIGGER_CRYPT_PPI) | +#endif /* CONFIG_BT_CTLR_LE_ENC || CONFIG_BT_CTLR_BROADCAST_ISO_ENC */ + 0); } void radio_tmr_rx_status_reset(void) { nrf_rtc_event_disable(NRF_RTC0, RTC_EVTENCLR_COMPARE2_Msk); +#if defined(CONFIG_BT_CTLR_LE_ENC) || defined(CONFIG_BT_CTLR_BROADCAST_ISO_ENC) hal_trigger_crypt_ppi_disable(); +#endif /* CONFIG_BT_CTLR_LE_ENC || CONFIG_BT_CTLR_BROADCAST_ISO_ENC */ hal_radio_nrf_ppi_channels_disable( #if (HAL_RADIO_ENABLE_TX_ON_TICK_PPI != HAL_RADIO_ENABLE_RX_ON_TICK_PPI) && \ @@ -1239,7 +1251,10 @@ void radio_tmr_rx_status_reset(void) #if defined(CONFIG_BT_CTLR_DF_CONN_CTE_RX) BIT(HAL_TRIGGER_CRYPT_DELAY_PPI) | #endif /* CONFIG_BT_CTLR_DF_CONN_CTE_RX */ - BIT(HAL_TRIGGER_CRYPT_PPI)); +#if defined(CONFIG_BT_CTLR_LE_ENC) || defined(CONFIG_BT_CTLR_BROADCAST_ISO_ENC) + BIT(HAL_TRIGGER_CRYPT_PPI) | +#endif /* CONFIG_BT_CTLR_LE_ENC || CONFIG_BT_CTLR_BROADCAST_ISO_ENC */ + 0); } void radio_tmr_tx_enable(void) @@ -1739,8 +1754,10 @@ void radio_gpio_pa_lna_disable(void) } #endif /* HAL_RADIO_GPIO_HAVE_PA_PIN || HAL_RADIO_GPIO_HAVE_LNA_PIN */ +#if defined(CONFIG_BT_CTLR_LE_ENC) || defined(CONFIG_BT_CTLR_BROADCAST_ISO_ENC) static uint8_t MALIGN(4) _ccm_scratch[(HAL_RADIO_PDU_LEN_MAX - 4) + 16]; +#if defined(CONFIG_BT_CTLR_LE_ENC) || defined(CONFIG_BT_CTLR_SYNC_ISO) static void *radio_ccm_ext_rx_pkt_set(struct ccm *cnf, uint8_t phy, uint8_t pdu_type, void *pkt) { uint32_t mode; @@ -1868,7 +1885,9 @@ void *radio_ccm_iso_rx_pkt_set(struct ccm *cnf, uint8_t phy, uint8_t pdu_type, v { return radio_ccm_ext_rx_pkt_set(cnf, phy, pdu_type, pkt); } +#endif /* CONFIG_BT_CTLR_LE_ENC || CONFIG_BT_CTLR_SYNC_ISO */ +#if defined(CONFIG_BT_CTLR_LE_ENC) || defined(CONFIG_BT_CTLR_ADV_ISO) static void *radio_ccm_ext_tx_pkt_set(struct ccm *cnf, uint8_t pdu_type, void *pkt) { uint32_t mode; @@ -1939,6 +1958,7 @@ void *radio_ccm_iso_tx_pkt_set(struct ccm *cnf, uint8_t pdu_type, void *pkt) { return radio_ccm_ext_tx_pkt_set(cnf, pdu_type, pkt); } +#endif /* CONFIG_BT_CTLR_LE_ENC || CONFIG_BT_CTLR_ADV_ISO */ uint32_t radio_ccm_is_done(void) { @@ -2086,6 +2106,7 @@ uint8_t radio_ar_resolve(const uint8_t *addr) } #endif /* CONFIG_BT_CTLR_PRIVACY */ +#endif /* CONFIG_BT_CTLR_LE_ENC || CONFIG_BT_CTLR_BROADCAST_ISO_ENC */ #if defined(CONFIG_BT_CTLR_DF_SUPPORT) && !defined(CONFIG_ZTEST) /* @brief Function configures CTE inline register to start sampling of CTE diff --git a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5.h b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5.h index b9401a5429247..bdfb3c8923888 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5.h +++ b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5.h @@ -5,6 +5,9 @@ * SPDX-License-Identifier: Apache-2.0 */ +/* HAL header files for nRF5x SoCs. + * These has to come before the radio_*.h include below. + */ #include /* Common radio resources */ @@ -44,6 +47,14 @@ #error "Unsupported SoC." #endif +#include +#include + +#if defined(CONFIG_BT_CTLR_LE_ENC) || defined(CONFIG_BT_CTLR_BROADCAST_ISO_ENC) +#include +#include +#endif /* CONFIG_BT_CTLR_LE_ENC || CONFIG_BT_CTLR_BROADCAST_ISO_ENC */ + /* Define to reset PPI registration. * This has to come before the ppi/dppi includes below. */ @@ -57,10 +68,6 @@ #include "radio_nrf5_ppi_resources.h" #include "radio_nrf5_ppi.h" #elif defined(DPPI_PRESENT) -#include -#include -#include -#include #include #include "radio_nrf5_dppi_resources.h" #include "radio_nrf5_dppi.h" 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 a09056ae2d3d3..6c975bccbc97f 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 @@ -113,6 +113,7 @@ static inline void hal_radio_ready_time_capture_ppi_config(void) NRF_TIMER_TASK_CAPTURE0, HAL_RADIO_READY_TIME_CAPTURE_PPI); } +#if defined(CONFIG_BT_CTLR_LE_ENC) || defined(CONFIG_BT_CTLR_BROADCAST_ISO_ENC) /******************************************************************************* * Trigger encryption task upon address reception: * wire the RADIO EVENTS_ADDRESS event to the CCM TASKS_CRYPT task. @@ -135,6 +136,28 @@ static inline void hal_trigger_crypt_ppi_disable(void) nrf_ccm_subscribe_clear(NRF_CCM, NRF_CCM_TASK_CRYPT); } +/******************************************************************************* + * Trigger automatic address resolution on Bit counter match: + * wire the RADIO EVENTS_BCMATCH event to the AAR TASKS_START task. + */ +static inline void hal_trigger_aar_ppi_config(void) +{ + nrf_radio_publish_set(NRF_RADIO, NRF_RADIO_EVENT_BCMATCH, HAL_TRIGGER_AAR_PPI); + nrf_aar_subscribe_set(NRF_AAR, NRF_AAR_TASK_START, HAL_TRIGGER_AAR_PPI); +} + +#if defined(CONFIG_BT_CTLR_PHY_CODED) && defined(CONFIG_HAS_HW_NRF_RADIO_BLE_CODED) +/******************************************************************************* + * Trigger Radio Rate override upon Rateboost event. + */ +static inline void hal_trigger_rateoverride_ppi_config(void) +{ + nrf_radio_publish_set(NRF_RADIO, NRF_RADIO_EVENT_RATEBOOST, HAL_TRIGGER_RATEOVERRIDE_PPI); + nrf_ccm_subscribe_set(NRF_CCM, NRF_CCM_TASK_RATEOVERRIDE, HAL_TRIGGER_RATEOVERRIDE_PPI); +} +#endif /* CONFIG_BT_CTLR_PHY_CODED && CONFIG_HAS_HW_NRF_RADIO_BLE_CODED */ +#endif /* CONFIG_BT_CTLR_LE_ENC || CONFIG_BT_CTLR_BROADCAST_ISO_ENC */ + #if defined(CONFIG_BT_CTLR_DF_CONN_CTE_RX) /******************************************************************************* * Trigger encryption task on Bit counter match: @@ -161,27 +184,6 @@ static inline void hal_trigger_crypt_by_bcmatch_ppi_config(void) } #endif /* CONFIG_BT_CTLR_DF_CONN_CTE_RX */ -/******************************************************************************* - * Trigger automatic address resolution on Bit counter match: - * wire the RADIO EVENTS_BCMATCH event to the AAR TASKS_START task. - */ -static inline void hal_trigger_aar_ppi_config(void) -{ - nrf_radio_publish_set(NRF_RADIO, NRF_RADIO_EVENT_BCMATCH, HAL_TRIGGER_AAR_PPI); - nrf_aar_subscribe_set(NRF_AAR, NRF_AAR_TASK_START, HAL_TRIGGER_AAR_PPI); -} - -#if defined(CONFIG_BT_CTLR_PHY_CODED) && defined(CONFIG_HAS_HW_NRF_RADIO_BLE_CODED) -/******************************************************************************* - * Trigger Radio Rate override upon Rateboost event. - */ -static inline void hal_trigger_rateoverride_ppi_config(void) -{ - nrf_radio_publish_set(NRF_RADIO, NRF_RADIO_EVENT_RATEBOOST, HAL_TRIGGER_RATEOVERRIDE_PPI); - nrf_ccm_subscribe_set(NRF_CCM, NRF_CCM_TASK_RATEOVERRIDE, HAL_TRIGGER_RATEOVERRIDE_PPI); -} -#endif /* CONFIG_BT_CTLR_PHY_CODED && CONFIG_HAS_HW_NRF_RADIO_BLE_CODED */ - /******************************************************************************/ #if !defined(CONFIG_BT_CTLR_TIFS_HW) diff --git a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_adv_iso.c b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_adv_iso.c index b3a86b7acb1ca..f11cd49c733ba 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_adv_iso.c +++ b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_adv_iso.c @@ -351,7 +351,8 @@ static int prepare_cb_common(struct lll_prepare_param *p) /* Radio packet configuration */ pkt_flags = RADIO_PKT_CONF_FLAGS(RADIO_PKT_CONF_PDU_TYPE_BIS, phy, RADIO_PKT_CONF_CTE_DISABLED); - if (pdu->len && lll->enc) { + if (IS_ENABLED(CONFIG_BT_CTLR_BROADCAST_ISO_ENC) && + pdu->len && lll->enc) { /* Encryption */ lll->ccm_tx.counter = payload_count; @@ -698,7 +699,8 @@ static void isr_tx_common(void *param, lll_chan_set(data_chan_use); /* Encryption */ - if (pdu->len && lll->enc) { + if (IS_ENABLED(CONFIG_BT_CTLR_BROADCAST_ISO_ENC) && + pdu->len && lll->enc) { lll->ccm_tx.counter = payload_count; (void)memcpy(lll->ccm_tx.iv, lll->giv, 4U); 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 96b932403aa14..ebd7ccbb595be 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 @@ -305,7 +305,8 @@ static int prepare_cb_common(struct lll_prepare_param *p) LL_ASSERT(node_rx); /* Encryption */ - if (lll->enc) { + if (IS_ENABLED(CONFIG_BT_CTLR_BROADCAST_ISO_ENC) && + lll->enc) { uint64_t payload_count; uint8_t pkt_flags; @@ -619,7 +620,8 @@ static void isr_rx(void *param) !lll->payload[bis_idx][payload_index]) { uint16_t handle; - if (lll->enc) { + if (IS_ENABLED(CONFIG_BT_CTLR_BROADCAST_ISO_ENC) && + lll->enc) { uint32_t mic_failure; uint32_t done; @@ -922,7 +924,8 @@ static void isr_rx(void *param) lll_chan_set(data_chan_use); /* Encryption */ - if (lll->enc) { + if (IS_ENABLED(CONFIG_BT_CTLR_BROADCAST_ISO_ENC) && + lll->enc) { uint64_t payload_count; struct pdu_bis *pdu; diff --git a/subsys/bluetooth/controller/ll_sw/ull_adv_iso.c b/subsys/bluetooth/controller/ll_sw/ull_adv_iso.c index 4c5265b799cff..54e7795158949 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_adv_iso.c +++ b/subsys/bluetooth/controller/ll_sw/ull_adv_iso.c @@ -144,6 +144,12 @@ static uint8_t big_create(uint8_t big_handle, uint8_t adv_handle, uint8_t num_bi return BT_HCI_ERR_UNKNOWN_ADV_IDENTIFIER; } + /* Check if encryption supported */ + if (!IS_ENABLED(CONFIG_BT_CTLR_BROADCAST_ISO_ENC) && + encryption) { + return BT_HCI_ERR_CMD_DISALLOWED; + }; + if (IS_ENABLED(CONFIG_BT_CTLR_PARAM_CHECK)) { if (num_bis == 0U || num_bis > 0x1F) { return BT_HCI_ERR_INVALID_PARAM; @@ -566,7 +572,7 @@ static uint8_t big_create(uint8_t big_handle, uint8_t adv_handle, uint8_t num_bi big_info->payload_count_framing[4] &= ~BIT(7); big_info->payload_count_framing[4] |= ((framing & 0x01) << 7); - if (encryption) { + if (IS_ENABLED(CONFIG_BT_CTLR_BROADCAST_ISO_ENC) && encryption) { const uint8_t BIG1[16] = {0x31, 0x47, 0x49, 0x42, }; const uint8_t BIG2[4] = {0x32, 0x47, 0x49, 0x42}; const uint8_t BIG3[4] = {0x33, 0x47, 0x49, 0x42}; diff --git a/subsys/bluetooth/controller/ll_sw/ull_sync_iso.c b/subsys/bluetooth/controller/ll_sw/ull_sync_iso.c index 41a6d0a303704..9ad0a9cc3f8ee 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_sync_iso.c +++ b/subsys/bluetooth/controller/ll_sw/ull_sync_iso.c @@ -125,6 +125,12 @@ uint8_t ll_big_sync_create(uint8_t big_handle, uint16_t sync_handle, last_index = bis[i]; } + /* Check if encryption supported */ + if (!IS_ENABLED(CONFIG_BT_CTLR_BROADCAST_ISO_ENC) && + encryption) { + return BT_HCI_ERR_CMD_DISALLOWED; + }; + /* Check if requested encryption matches */ if (encryption != sync->enc) { return BT_HCI_ERR_ENC_MODE_NOT_ACCEPTABLE; @@ -470,7 +476,8 @@ void ull_sync_iso_setup(struct ll_sync_iso_set *sync_iso, /* Set establishment event countdown */ lll->establish_events = CONN_ESTAB_COUNTDOWN; - if (lll->enc && (bi_size == PDU_BIG_INFO_ENCRYPTED_SIZE)) { + if (IS_ENABLED(CONFIG_BT_CTLR_BROADCAST_ISO_ENC) && + lll->enc && (bi_size == PDU_BIG_INFO_ENCRYPTED_SIZE)) { const uint8_t BIG3[4] = {0x33, 0x47, 0x49, 0x42}; struct ccm *ccm_rx; uint8_t gsk[16]; From fe205a598e38549bd16620eecaef0431cfcc1b84 Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Mon, 20 May 2024 09:46:28 +0200 Subject: [PATCH 2032/2849] Bluetooth: Controller: Refactor BT_CTLR_LE_ENC implementation Refactor reused function in BT_CTLR_LE_ENC feature. Signed-off-by: Vinayak Kariappa Chettimada --- subsys/bluetooth/controller/hci/hci.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/subsys/bluetooth/controller/hci/hci.c b/subsys/bluetooth/controller/hci/hci.c index 0cf0d9f7d6e1f..68a1021d0e59e 100644 --- a/subsys/bluetooth/controller/hci/hci.c +++ b/subsys/bluetooth/controller/hci/hci.c @@ -8621,7 +8621,7 @@ static void le_ltk_request(struct pdu_data *pdu_data, uint16_t handle, } static void encrypt_change(uint8_t err, uint16_t handle, - struct net_buf *buf) + struct net_buf *buf, bool encryption_on) { struct bt_hci_evt_encrypt_change *ep; @@ -8634,7 +8634,7 @@ static void encrypt_change(uint8_t err, uint16_t handle, ep->status = err; ep->handle = sys_cpu_to_le16(handle); - ep->encrypt = !err ? 1 : 0; + ep->encrypt = encryption_on ? 1 : 0; } #endif /* CONFIG_BT_CTLR_LE_ENC */ @@ -8776,7 +8776,7 @@ static void encode_data_ctrl(struct node_rx_pdu *node_rx, break; case PDU_DATA_LLCTRL_TYPE_START_ENC_RSP: - encrypt_change(0x00, handle, buf); + encrypt_change(0x00, handle, buf, true); break; #endif /* CONFIG_BT_CTLR_LE_ENC */ @@ -8793,7 +8793,7 @@ static void encode_data_ctrl(struct node_rx_pdu *node_rx, #if defined(CONFIG_BT_CTLR_LE_ENC) case PDU_DATA_LLCTRL_TYPE_REJECT_IND: encrypt_change(pdu_data->llctrl.reject_ind.error_code, handle, - buf); + buf, false); break; #endif /* CONFIG_BT_CTLR_LE_ENC */ From 78466c8f52c77d54c12641a83d61c4db1cb5dd8d Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Wed, 5 Jun 2024 12:47:12 +0200 Subject: [PATCH 2033/2849] Bluetooth: Controller: Use BT_HCI_ERR_UNSPECIFIED as needed A Host shall consider any error code that it does not explicitly understand equivalent to the error code Unspecified Error (0x1F). Signed-off-by: Vinayak Kariappa Chettimada --- 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 68a1021d0e59e..04760a0a4014a 100644 --- a/subsys/bluetooth/controller/hci/hci.c +++ b/subsys/bluetooth/controller/hci/hci.c @@ -8632,7 +8632,7 @@ static void encrypt_change(uint8_t err, uint16_t handle, hci_evt_create(buf, BT_HCI_EVT_ENCRYPT_CHANGE, sizeof(*ep)); ep = net_buf_add(buf, sizeof(*ep)); - ep->status = err; + ep->status = err ? err : (encryption_on ? err : BT_HCI_ERR_UNSPECIFIED); ep->handle = sys_cpu_to_le16(handle); ep->encrypt = encryption_on ? 1 : 0; } From d6f2bc96690f5c89e1dc5974024e07dae04a9d77 Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Wed, 5 Jun 2024 13:56:08 +0200 Subject: [PATCH 2034/2849] Bluetooth: Controller: Add explicit LLCP error code check Add unit tests to cover explicit LLCP error code check and cover the same in the Controller implementation. Signed-off-by: Vinayak Kariappa Chettimada --- .../bluetooth/controller/ll_sw/ull_llcp_enc.c | 16 +- .../controller/ctrl_encrypt/src/main.c | 421 +++++++++++++++++- 2 files changed, 433 insertions(+), 4 deletions(-) diff --git a/subsys/bluetooth/controller/ll_sw/ull_llcp_enc.c b/subsys/bluetooth/controller/ll_sw/ull_llcp_enc.c index cc112b11d3ab8..392f37963ae01 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_llcp_enc.c +++ b/subsys/bluetooth/controller/ll_sw/ull_llcp_enc.c @@ -369,19 +369,29 @@ static void lp_enc_store_s(struct ll_conn *conn, struct proc_ctx *ctx, struct pd static inline uint8_t reject_error_code(struct pdu_data *pdu) { + uint8_t error; + if (pdu->llctrl.opcode == PDU_DATA_LLCTRL_TYPE_REJECT_IND) { - return pdu->llctrl.reject_ind.error_code; + error = pdu->llctrl.reject_ind.error_code; #if defined(CONFIG_BT_CTLR_EXT_REJ_IND) } else if (pdu->llctrl.opcode == PDU_DATA_LLCTRL_TYPE_REJECT_EXT_IND) { - return pdu->llctrl.reject_ext_ind.error_code; + error = pdu->llctrl.reject_ext_ind.error_code; #endif /* CONFIG_BT_CTLR_EXT_REJ_IND */ } else { /* Called with an invalid PDU */ LL_ASSERT(0); /* Keep compiler happy */ - return BT_HCI_ERR_UNSPECIFIED; + error = BT_HCI_ERR_UNSPECIFIED; + } + + /* Check expected error code from the peer */ + if (error != BT_HCI_ERR_PIN_OR_KEY_MISSING && + error != BT_HCI_ERR_UNSUPP_REMOTE_FEATURE) { + error = BT_HCI_ERR_UNSPECIFIED; } + + return error; } static void lp_enc_st_wait_rx_enc_rsp(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t evt, diff --git a/tests/bluetooth/controller/ctrl_encrypt/src/main.c b/tests/bluetooth/controller/ctrl_encrypt/src/main.c index 7d968cba76ac3..66fe7e7b93950 100644 --- a/tests/bluetooth/controller/ctrl_encrypt/src/main.c +++ b/tests/bluetooth/controller/ctrl_encrypt/src/main.c @@ -962,6 +962,426 @@ ZTEST(encryption_start, test_encryption_start_central_loc_no_ltk_2) "Free CTX buffers %d", llcp_ctx_buffers_free()); } +/* +-----+ +-------+ +-----+ + * | UT | | LL_A | | LT | + * +-----+ +-------+ +-----+ + * | | | + * | Initiate | | + * | Encryption Start Proc. | | + * |--------------------------->| | + * | -----------------\ | | + * | | Empty Tx queue |-| | + * | |----------------| | | + * | | | + * | | LL_ENC_REQ | + * | |-------------------->| + * | | | + * | | LL_REJECT_EXT_IND | + * | |<--------------------| + * | | | + * | Encryption Start Proc. | | + * | Complete | | + * |<---------------------------| | + * | | | + */ +ZTEST(encryption_start, test_encryption_start_central_loc_reject_ext_success) +{ + uint8_t err; + struct node_tx *tx; + struct node_rx_pdu *ntf; + + const uint8_t rand[] = { RAND }; + const uint8_t ediv[] = { EDIV }; + const uint8_t ltk[] = { LTK }; + + /* Prepare expected LL_ENC_REQ */ + struct pdu_data_llctrl_enc_req exp_enc_req = { + .rand = { RAND }, + .ediv = { EDIV }, + .skdm = { SKDM }, + .ivm = { IVM }, + }; + + /* Prepare mocked call to lll_csrand_get */ + lll_csrand_get_fake.return_val = sizeof(exp_enc_req.skdm) + sizeof(exp_enc_req.ivm); + lll_csrand_get_custom_fake_context.buf = exp_enc_req.skdm; + lll_csrand_get_custom_fake_context.len = sizeof(exp_enc_req.skdm) + sizeof(exp_enc_req.ivm); + + struct pdu_data_llctrl_reject_ext_ind reject_ext_ind = { + .reject_opcode = PDU_DATA_LLCTRL_TYPE_ENC_REQ, + .error_code = BT_HCI_ERR_SUCCESS + }; + + /* Role */ + test_set_role(&conn, BT_HCI_ROLE_CENTRAL); + + /* Connect */ + ull_cp_state_set(&conn, ULL_CP_CONNECTED); + + /* Check state */ + CHECK_RX_PE_STATE(conn, RESUMED, UNENCRYPTED); /* Rx unenc. */ + CHECK_TX_PE_STATE(conn, RESUMED, UNENCRYPTED); /* Tx unenc. */ + + /* Initiate an Encryption Start Procedure */ + err = ull_cp_encryption_start(&conn, rand, ediv, ltk); + zassert_equal(err, BT_HCI_ERR_SUCCESS); + + /* Prepare */ + event_prepare(&conn); + + /* Tx Queue should have one LL Control PDU */ + lt_rx(LL_ENC_REQ, &conn, &tx, &exp_enc_req); + lt_rx_q_is_empty(&conn); + + /* Check state */ + CHECK_RX_PE_STATE(conn, RESUMED, UNENCRYPTED); /* Rx unenc. */ + CHECK_TX_PE_STATE(conn, PAUSED, UNENCRYPTED); /* Tx paused & unenc. */ + + /* Release Tx */ + ull_cp_release_tx(&conn, tx); + + /* Rx */ + lt_tx(LL_REJECT_EXT_IND, &conn, &reject_ext_ind); + + /* Done */ + event_done(&conn); + + /* Check state */ + CHECK_RX_PE_STATE(conn, RESUMED, UNENCRYPTED); /* Rx unenc. */ + CHECK_TX_PE_STATE(conn, RESUMED, UNENCRYPTED); /* Tx unenc. */ + + struct pdu_data_llctrl_reject_ind reject_ind_expected = { + .error_code = BT_HCI_ERR_UNSPECIFIED }; + + /* There should be one host notification */ + ut_rx_pdu(LL_REJECT_IND, &ntf, &reject_ind_expected); + ut_rx_q_is_empty(); + + /* Release Ntf */ + release_ntf(ntf); + + zassert_equal(llcp_ctx_buffers_free(), test_ctx_buffers_cnt(), + "Free CTX buffers %d", llcp_ctx_buffers_free()); +} + +/* +-----+ +-------+ +-----+ + * | UT | | LL_A | | LT | + * +-----+ +-------+ +-----+ + * | | | + * | Initiate | | + * | Encryption Start Proc. | | + * |--------------------------->| | + * | -----------------\ | | + * | | Empty Tx queue |-| | + * | |----------------| | | + * | | | + * | | LL_ENC_REQ | + * | |-------------------->| + * | | | + * | | LL_REJECT_IND | + * | |<--------------------| + * | | | + * | Encryption Start Proc. | | + * | Complete | | + * |<---------------------------| | + * | | | + */ +ZTEST(encryption_start, test_encryption_start_central_loc_reject_success) +{ + uint8_t err; + struct node_tx *tx; + struct node_rx_pdu *ntf; + + const uint8_t rand[] = { RAND }; + const uint8_t ediv[] = { EDIV }; + const uint8_t ltk[] = { LTK }; + + /* Prepare expected LL_ENC_REQ */ + struct pdu_data_llctrl_enc_req exp_enc_req = { + .rand = { RAND }, + .ediv = { EDIV }, + .skdm = { SKDM }, + .ivm = { IVM }, + }; + + /* Prepare mocked call to lll_csrand_get */ + lll_csrand_get_fake.return_val = sizeof(exp_enc_req.skdm) + sizeof(exp_enc_req.ivm); + lll_csrand_get_custom_fake_context.buf = exp_enc_req.skdm; + lll_csrand_get_custom_fake_context.len = sizeof(exp_enc_req.skdm) + sizeof(exp_enc_req.ivm); + + struct pdu_data_llctrl_reject_ind reject_ind = { .error_code = BT_HCI_ERR_SUCCESS }; + + /* Role */ + test_set_role(&conn, BT_HCI_ROLE_CENTRAL); + + /* Connect */ + ull_cp_state_set(&conn, ULL_CP_CONNECTED); + + /* Check state */ + CHECK_RX_PE_STATE(conn, RESUMED, UNENCRYPTED); /* Rx unenc. */ + CHECK_TX_PE_STATE(conn, RESUMED, UNENCRYPTED); /* Tx unenc. */ + + /* Initiate an Encryption Start Procedure */ + err = ull_cp_encryption_start(&conn, rand, ediv, ltk); + zassert_equal(err, BT_HCI_ERR_SUCCESS); + + /* Prepare */ + event_prepare(&conn); + + /* Tx Queue should have one LL Control PDU */ + lt_rx(LL_ENC_REQ, &conn, &tx, &exp_enc_req); + lt_rx_q_is_empty(&conn); + + /* Check state */ + CHECK_RX_PE_STATE(conn, RESUMED, UNENCRYPTED); /* Rx unenc. */ + CHECK_TX_PE_STATE(conn, PAUSED, UNENCRYPTED); /* Tx paused & unenc. */ + + /* Release Tx */ + ull_cp_release_tx(&conn, tx); + + /* Rx */ + lt_tx(LL_REJECT_IND, &conn, &reject_ind); + + /* Done */ + event_done(&conn); + + /* Check state */ + CHECK_RX_PE_STATE(conn, RESUMED, UNENCRYPTED); /* Rx unenc. */ + CHECK_TX_PE_STATE(conn, RESUMED, UNENCRYPTED); /* Tx unenc. */ + + struct pdu_data_llctrl_reject_ind reject_ind_expected = { + .error_code = BT_HCI_ERR_UNSPECIFIED }; + + /* There should be one host notification */ + ut_rx_pdu(LL_REJECT_IND, &ntf, &reject_ind_expected); + ut_rx_q_is_empty(); + + /* Release Ntf */ + release_ntf(ntf); + + zassert_equal(llcp_ctx_buffers_free(), test_ctx_buffers_cnt(), + "Free CTX buffers %d", llcp_ctx_buffers_free()); +} + +/* +-----+ +-------+ +-----+ + * | UT | | LL_A | | LT | + * +-----+ +-------+ +-----+ + * | | | + * | Initiate | | + * | Encryption Start Proc. | | + * |--------------------------->| | + * | -----------------\ | | + * | | Empty Tx queue |-| | + * | |----------------| | | + * | | | + * | | LL_ENC_REQ | + * | |-------------------->| + * | | | + * | | LL_ENC_RSP | + * | |<--------------------| + * | | | + * | | LL_REJECT_EXT_IND | + * | |<--------------------| + * | | | + * | Encryption Start Proc. | | + * | Complete | | + * |<---------------------------| | + * | | | + */ +ZTEST(encryption_start, test_encryption_start_central_loc_no_ltk_reject_ext_success) +{ + uint8_t err; + struct node_tx *tx; + struct node_rx_pdu *ntf; + + const uint8_t rand[] = { RAND }; + const uint8_t ediv[] = { EDIV }; + const uint8_t ltk[] = { LTK }; + + /* Prepare expected LL_ENC_REQ */ + struct pdu_data_llctrl_enc_req exp_enc_req = { + .rand = { RAND }, + .ediv = { EDIV }, + .skdm = { SKDM }, + .ivm = { IVM }, + }; + + /* Prepare LL_ENC_RSP */ + struct pdu_data_llctrl_enc_rsp enc_rsp = { .skds = { SKDS }, .ivs = { IVS } }; + + /* Prepare mocked call to lll_csrand_get */ + lll_csrand_get_fake.return_val = sizeof(exp_enc_req.skdm) + sizeof(exp_enc_req.ivm); + lll_csrand_get_custom_fake_context.buf = exp_enc_req.skdm; + lll_csrand_get_custom_fake_context.len = sizeof(exp_enc_req.skdm) + sizeof(exp_enc_req.ivm); + + struct pdu_data_llctrl_reject_ext_ind reject_ext_ind = { + .reject_opcode = PDU_DATA_LLCTRL_TYPE_ENC_REQ, + .error_code = BT_HCI_ERR_SUCCESS + }; + + /* Role */ + test_set_role(&conn, BT_HCI_ROLE_CENTRAL); + + /* Connect */ + ull_cp_state_set(&conn, ULL_CP_CONNECTED); + + /* Check state */ + CHECK_RX_PE_STATE(conn, RESUMED, UNENCRYPTED); /* Rx unenc. */ + CHECK_TX_PE_STATE(conn, RESUMED, UNENCRYPTED); /* Tx unenc. */ + + /* Initiate an Encryption Start Procedure */ + err = ull_cp_encryption_start(&conn, rand, ediv, ltk); + zassert_equal(err, BT_HCI_ERR_SUCCESS); + + /* Prepare */ + event_prepare(&conn); + + /* Tx Queue should have one LL Control PDU */ + lt_rx(LL_ENC_REQ, &conn, &tx, &exp_enc_req); + lt_rx_q_is_empty(&conn); + + /* Check state */ + CHECK_RX_PE_STATE(conn, RESUMED, UNENCRYPTED); /* Rx unenc. */ + CHECK_TX_PE_STATE(conn, PAUSED, UNENCRYPTED); /* Tx paused & unenc. */ + + /* Release Tx */ + ull_cp_release_tx(&conn, tx); + + /* Rx */ + lt_tx(LL_ENC_RSP, &conn, &enc_rsp); + + /* Rx */ + lt_tx(LL_REJECT_EXT_IND, &conn, &reject_ext_ind); + + /* Done */ + event_done(&conn); + + /* Check state */ + CHECK_RX_PE_STATE(conn, RESUMED, UNENCRYPTED); /* Rx unenc. */ + CHECK_TX_PE_STATE(conn, RESUMED, UNENCRYPTED); /* Tx unenc. */ + + struct pdu_data_llctrl_reject_ind reject_ind_expected = { + .error_code = BT_HCI_ERR_UNSPECIFIED }; + + /* There should be one host notification */ + ut_rx_pdu(LL_REJECT_IND, &ntf, &reject_ind_expected); + ut_rx_q_is_empty(); + + /* Release Ntf */ + release_ntf(ntf); + + zassert_equal(llcp_ctx_buffers_free(), test_ctx_buffers_cnt(), + "Free CTX buffers %d", llcp_ctx_buffers_free()); +} + +/* +-----+ +-------+ +-----+ + * | UT | | LL_A | | LT | + * +-----+ +-------+ +-----+ + * | | | + * | Initiate | | + * | Encryption Start Proc. | | + * |--------------------------->| | + * | -----------------\ | | + * | | Empty Tx queue |-| | + * | |----------------| | | + * | | | + * | | LL_ENC_REQ | + * | |-------------------->| + * | | | + * | | LL_ENC_RSP | + * | |<--------------------| + * | | | + * | | LL_REJECT_IND | + * | |<--------------------| + * | | | + * | Encryption Start Proc. | | + * | Complete | | + * |<---------------------------| | + * | | | + */ +ZTEST(encryption_start, test_encryption_start_central_loc_no_ltk_2_reject_success) +{ + uint8_t err; + struct node_tx *tx; + struct node_rx_pdu *ntf; + + const uint8_t rand[] = { RAND }; + const uint8_t ediv[] = { EDIV }; + const uint8_t ltk[] = { LTK }; + + /* Prepare expected LL_ENC_REQ */ + struct pdu_data_llctrl_enc_req exp_enc_req = { + .rand = { RAND }, + .ediv = { EDIV }, + .skdm = { SKDM }, + .ivm = { IVM }, + }; + + /* Prepare LL_ENC_RSP */ + struct pdu_data_llctrl_enc_rsp enc_rsp = { .skds = { SKDS }, .ivs = { IVS } }; + + /* Prepare mocked call to lll_csrand_get */ + lll_csrand_get_fake.return_val = sizeof(exp_enc_req.skdm) + sizeof(exp_enc_req.ivm); + lll_csrand_get_custom_fake_context.buf = exp_enc_req.skdm; + lll_csrand_get_custom_fake_context.len = sizeof(exp_enc_req.skdm) + sizeof(exp_enc_req.ivm); + + struct pdu_data_llctrl_reject_ind reject_ind = { .error_code = BT_HCI_ERR_SUCCESS }; + + /* Role */ + test_set_role(&conn, BT_HCI_ROLE_CENTRAL); + + /* Connect */ + ull_cp_state_set(&conn, ULL_CP_CONNECTED); + + /* Check state */ + CHECK_RX_PE_STATE(conn, RESUMED, UNENCRYPTED); /* Rx unenc. */ + CHECK_TX_PE_STATE(conn, RESUMED, UNENCRYPTED); /* Tx unenc. */ + + /* Initiate an Encryption Start Procedure */ + err = ull_cp_encryption_start(&conn, rand, ediv, ltk); + zassert_equal(err, BT_HCI_ERR_SUCCESS); + + /* Prepare */ + event_prepare(&conn); + + /* Tx Queue should have one LL Control PDU */ + lt_rx(LL_ENC_REQ, &conn, &tx, &exp_enc_req); + lt_rx_q_is_empty(&conn); + + /* Check state */ + CHECK_RX_PE_STATE(conn, RESUMED, UNENCRYPTED); /* Rx unenc. */ + CHECK_TX_PE_STATE(conn, PAUSED, UNENCRYPTED); /* Tx paused & unenc. */ + + /* Release Tx */ + ull_cp_release_tx(&conn, tx); + + /* Rx */ + lt_tx(LL_ENC_RSP, &conn, &enc_rsp); + + /* Rx */ + lt_tx(LL_REJECT_IND, &conn, &reject_ind); + + /* Done */ + event_done(&conn); + + /* Check state */ + CHECK_RX_PE_STATE(conn, RESUMED, UNENCRYPTED); /* Rx unenc. */ + CHECK_TX_PE_STATE(conn, RESUMED, UNENCRYPTED); /* Tx unenc. */ + + struct pdu_data_llctrl_reject_ind reject_ind_expected = { + .error_code = BT_HCI_ERR_UNSPECIFIED }; + + /* There should be one host notification */ + ut_rx_pdu(LL_REJECT_IND, &ntf, &reject_ind_expected); + ut_rx_q_is_empty(); + + /* Release Ntf */ + release_ntf(ntf); + + zassert_equal(llcp_ctx_buffers_free(), test_ctx_buffers_cnt(), + "Free CTX buffers %d", llcp_ctx_buffers_free()); +} + /* +-----+ +-------+ +-----+ * | UT | | LL_A | | LT | * +-----+ +-------+ +-----+ @@ -2216,7 +2636,6 @@ ZTEST(encryption_pause, test_encryption_pause_periph_rem_invalid) uint8_t err; struct node_tx *tx; - struct node_rx_pdu *ntf; struct ll_conn_iso_stream cis = { 0 }; const uint8_t rand[] = { RAND }; From 0bbbef3a8cee747bee4991051a9ec7eb97a4c058 Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Mon, 20 May 2024 09:53:02 +0200 Subject: [PATCH 2035/2849] Bluetooth: Controller: Use NRF_RTC and RADIO_SHORTS_TRX_END_DISABLE_Msk Use NRF_RTC and NRF_RADIO_SHORTS_TRX_END_DISABLE_Msk instead to prepare towards using configurable use of RTC and Radio hardware defines. Signed-off-by: Vinayak Kariappa Chettimada --- .../ll_sw/nordic/hal/nrf5/radio/radio.c | 81 ++++++++----------- .../ll_sw/nordic/hal/nrf5/radio/radio_df.c | 2 +- .../ll_sw/nordic/hal/nrf5/radio/radio_nrf51.h | 14 ++++ .../nordic/hal/nrf5/radio/radio_nrf52805.h | 14 ++++ .../nordic/hal/nrf5/radio/radio_nrf52810.h | 14 ++++ .../nordic/hal/nrf5/radio/radio_nrf52811.h | 14 ++++ .../nordic/hal/nrf5/radio/radio_nrf52820.h | 14 ++++ .../nordic/hal/nrf5/radio/radio_nrf52832.h | 14 ++++ .../nordic/hal/nrf5/radio/radio_nrf52833.h | 14 ++++ .../nordic/hal/nrf5/radio/radio_nrf52840.h | 14 ++++ .../nordic/hal/nrf5/radio/radio_nrf5340.h | 14 ++++ .../nordic/hal/nrf5/radio/radio_nrf5_dppi.h | 2 +- .../nordic/hal/nrf5/radio/radio_nrf5_ppi.h | 6 +- .../hal/nrf5/radio/radio_nrf5_resources.h | 24 +++--- .../nordic/hal/nrf5/radio/radio_sim_nrf52.h | 14 ++++ .../nordic/hal/nrf5/radio/radio_sim_nrf5340.h | 28 +++++-- .../controller/ll_sw/nordic/hal/nrf5/swi.h | 7 +- .../controller/ll_sw/nordic/lll/lll.c | 32 ++++---- 18 files changed, 235 insertions(+), 87 deletions(-) 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 14dc1e40763b3..9a79aca931d84 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 @@ -9,11 +9,6 @@ #include #include -#include -#include -#include -#include -#include #include #include "util/mem.h" @@ -175,25 +170,15 @@ void isr_radio(void) void radio_isr_set(radio_isr_cb_t cb, void *param) { - irq_disable(RADIO_IRQn); + irq_disable(HAL_RADIO_IRQn); isr_cb_param = param; isr_cb = cb; - nrf_radio_int_enable(NRF_RADIO, - 0 | - /* RADIO_INTENSET_READY_Msk | - * RADIO_INTENSET_ADDRESS_Msk | - * RADIO_INTENSET_PAYLOAD_Msk | - * RADIO_INTENSET_END_Msk | - */ - RADIO_INTENSET_DISABLED_Msk - /* | RADIO_INTENSET_RSSIEND_Msk | - */ - ); + nrf_radio_int_enable(NRF_RADIO, HAL_RADIO_INTENSET_DISABLED_Msk); - NVIC_ClearPendingIRQ(RADIO_IRQn); - irq_enable(RADIO_IRQn); + NVIC_ClearPendingIRQ(HAL_RADIO_IRQn); + irq_enable(HAL_RADIO_IRQn); } void radio_setup(void) @@ -236,7 +221,7 @@ void radio_setup(void) void radio_reset(void) { - irq_disable(RADIO_IRQn); + irq_disable(HAL_RADIO_IRQn); /* nRF SoC generic radio reset/initializations * Note: Only registers whose bits are partially modified across @@ -622,7 +607,7 @@ static uint32_t last_pdu_end_us; uint32_t radio_is_done(void) { - if (NRF_RADIO->NRF_RADIO_TXRX_END_EVENT != 0) { + if (NRF_RADIO->NRF_RADIO_TRX_END_EVENT != 0) { /* On packet END event increment last packet end time value. * Note: this depends on the function being called exactly once * in the ISR function. @@ -637,7 +622,7 @@ uint32_t radio_is_done(void) #else /* !CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER */ uint32_t radio_is_done(void) { - return (NRF_RADIO->NRF_RADIO_TXRX_END_EVENT != 0); + return (NRF_RADIO->NRF_RADIO_TRX_END_EVENT != 0); } #endif /* !CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER */ @@ -941,10 +926,10 @@ void radio_switch_complete_and_rx(uint8_t phy_rx) { #if defined(CONFIG_BT_CTLR_TIFS_HW) NRF_RADIO->SHORTS = RADIO_SHORTS_READY_START_Msk | - RADIO_SHORTS_END_DISABLE_Msk | + NRF_RADIO_SHORTS_TRX_END_DISABLE_Msk | RADIO_SHORTS_DISABLED_RXEN_Msk; #else /* !CONFIG_BT_CTLR_TIFS_HW */ - NRF_RADIO->SHORTS = RADIO_SHORTS_READY_START_Msk | NRF_RADIO_SHORTS_PDU_END_DISABLE; + NRF_RADIO->SHORTS = RADIO_SHORTS_READY_START_Msk | NRF_RADIO_SHORTS_TRX_END_DISABLE_Msk; /* NOTE: As Tx chain delays are negligible constant values (~1 us) * across nRF5x radios, sw_switch assumes the 1M chain delay for @@ -960,10 +945,10 @@ void radio_switch_complete_and_tx(uint8_t phy_rx, uint8_t flags_rx, { #if defined(CONFIG_BT_CTLR_TIFS_HW) NRF_RADIO->SHORTS = RADIO_SHORTS_READY_START_Msk | - RADIO_SHORTS_END_DISABLE_Msk | + NRF_RADIO_SHORTS_TRX_END_DISABLE_Msk | RADIO_SHORTS_DISABLED_TXEN_Msk; #else /* !CONFIG_BT_CTLR_TIFS_HW */ - NRF_RADIO->SHORTS = RADIO_SHORTS_READY_START_Msk | NRF_RADIO_SHORTS_PDU_END_DISABLE; + NRF_RADIO->SHORTS = RADIO_SHORTS_READY_START_Msk | NRF_RADIO_SHORTS_TRX_END_DISABLE_Msk; sw_switch(SW_SWITCH_RX, SW_SWITCH_TX, phy_rx, flags_rx, phy_tx, flags_tx, END_EVT_DELAY_DISABLED); @@ -975,10 +960,10 @@ void radio_switch_complete_with_delay_compensation_and_tx( enum radio_end_evt_delay_state end_delay_en) { #if defined(CONFIG_BT_CTLR_TIFS_HW) - NRF_RADIO->SHORTS = RADIO_SHORTS_READY_START_Msk | RADIO_SHORTS_END_DISABLE_Msk | + NRF_RADIO->SHORTS = RADIO_SHORTS_READY_START_Msk | NRF_RADIO_SHORTS_TRX_END_DISABLE_Msk | RADIO_SHORTS_DISABLED_TXEN_Msk; #else /* !CONFIG_BT_CTLR_TIFS_HW */ - NRF_RADIO->SHORTS = RADIO_SHORTS_READY_START_Msk | NRF_RADIO_SHORTS_PDU_END_DISABLE; + NRF_RADIO->SHORTS = RADIO_SHORTS_READY_START_Msk | NRF_RADIO_SHORTS_TRX_END_DISABLE_Msk; sw_switch(SW_SWITCH_RX, SW_SWITCH_TX, phy_rx, flags_rx, phy_tx, flags_tx, end_delay_en); #endif /* !CONFIG_BT_CTLR_TIFS_HW */ @@ -989,10 +974,10 @@ void radio_switch_complete_and_b2b_tx(uint8_t phy_curr, uint8_t flags_curr, { #if defined(CONFIG_BT_CTLR_TIFS_HW) NRF_RADIO->SHORTS = RADIO_SHORTS_READY_START_Msk | - RADIO_SHORTS_END_DISABLE_Msk | + NRF_RADIO_SHORTS_TRX_END_DISABLE_Msk | RADIO_SHORTS_DISABLED_TXEN_Msk; #else /* !CONFIG_BT_CTLR_TIFS_HW */ - NRF_RADIO->SHORTS = RADIO_SHORTS_READY_START_Msk | NRF_RADIO_SHORTS_PDU_END_DISABLE; + NRF_RADIO->SHORTS = RADIO_SHORTS_READY_START_Msk | NRF_RADIO_SHORTS_TRX_END_DISABLE_Msk; sw_switch(SW_SWITCH_TX, SW_SWITCH_TX, phy_curr, flags_curr, phy_next, flags_next, END_EVT_DELAY_DISABLED); @@ -1004,10 +989,10 @@ void radio_switch_complete_and_b2b_rx(uint8_t phy_curr, uint8_t flags_curr, { #if defined(CONFIG_BT_CTLR_TIFS_HW) NRF_RADIO->SHORTS = RADIO_SHORTS_READY_START_Msk | - RADIO_SHORTS_END_DISABLE_Msk | + NRF_RADIO_SHORTS_TRX_END_DISABLE_Msk | RADIO_SHORTS_DISABLED_RXEN_Msk; #else /* !CONFIG_BT_CTLR_TIFS_HW */ - NRF_RADIO->SHORTS = RADIO_SHORTS_READY_START_Msk | NRF_RADIO_SHORTS_PDU_END_DISABLE; + NRF_RADIO->SHORTS = RADIO_SHORTS_READY_START_Msk | NRF_RADIO_SHORTS_TRX_END_DISABLE_Msk; sw_switch(SW_SWITCH_RX, SW_SWITCH_RX, phy_curr, flags_curr, phy_next, flags_next, END_EVT_DELAY_DISABLED); @@ -1017,9 +1002,9 @@ void radio_switch_complete_and_b2b_rx(uint8_t phy_curr, uint8_t flags_curr, void radio_switch_complete_and_b2b_tx_disable(void) { #if defined(CONFIG_BT_CTLR_TIFS_HW) - NRF_RADIO->SHORTS = (RADIO_SHORTS_READY_START_Msk | RADIO_SHORTS_END_DISABLE_Msk); + NRF_RADIO->SHORTS = (RADIO_SHORTS_READY_START_Msk | NRF_RADIO_SHORTS_TRX_END_DISABLE_Msk); #else /* CONFIG_BT_CTLR_TIFS_HW */ - NRF_RADIO->SHORTS = (RADIO_SHORTS_READY_START_Msk | NRF_RADIO_SHORTS_PDU_END_DISABLE); + NRF_RADIO->SHORTS = (RADIO_SHORTS_READY_START_Msk | NRF_RADIO_SHORTS_TRX_END_DISABLE_Msk); hal_radio_sw_switch_b2b_tx_disable(sw_tifs_toggle); #endif /* !CONFIG_BT_CTLR_TIFS_HW */ } @@ -1027,9 +1012,9 @@ void radio_switch_complete_and_b2b_tx_disable(void) void radio_switch_complete_and_b2b_rx_disable(void) { #if defined(CONFIG_BT_CTLR_TIFS_HW) - NRF_RADIO->SHORTS = (RADIO_SHORTS_READY_START_Msk | RADIO_SHORTS_END_DISABLE_Msk); + NRF_RADIO->SHORTS = (RADIO_SHORTS_READY_START_Msk | NRF_RADIO_SHORTS_TRX_END_DISABLE_Msk); #else /* CONFIG_BT_CTLR_TIFS_HW */ - NRF_RADIO->SHORTS = (RADIO_SHORTS_READY_START_Msk | NRF_RADIO_SHORTS_PDU_END_DISABLE); + NRF_RADIO->SHORTS = (RADIO_SHORTS_READY_START_Msk | NRF_RADIO_SHORTS_TRX_END_DISABLE_Msk); hal_radio_sw_switch_b2b_rx_disable(sw_tifs_toggle); #endif /* !CONFIG_BT_CTLR_TIFS_HW */ } @@ -1037,9 +1022,9 @@ void radio_switch_complete_and_b2b_rx_disable(void) void radio_switch_complete_and_disable(void) { #if defined(CONFIG_BT_CTLR_TIFS_HW) - NRF_RADIO->SHORTS = (RADIO_SHORTS_READY_START_Msk | RADIO_SHORTS_END_DISABLE_Msk); + NRF_RADIO->SHORTS = (RADIO_SHORTS_READY_START_Msk | NRF_RADIO_SHORTS_TRX_END_DISABLE_Msk); #else /* CONFIG_BT_CTLR_TIFS_HW */ - NRF_RADIO->SHORTS = (RADIO_SHORTS_READY_START_Msk | NRF_RADIO_SHORTS_PDU_END_DISABLE); + NRF_RADIO->SHORTS = (RADIO_SHORTS_READY_START_Msk | NRF_RADIO_SHORTS_TRX_END_DISABLE_Msk); hal_radio_sw_switch_disable(); #endif /* !CONFIG_BT_CTLR_TIFS_HW */ } @@ -1134,7 +1119,7 @@ uint32_t radio_bc_has_match(void) void radio_tmr_status_reset(void) { - nrf_rtc_event_disable(NRF_RTC0, RTC_EVTENCLR_COMPARE2_Msk); + nrf_rtc_event_disable(NRF_RTC, RTC_EVTENCLR_COMPARE2_Msk); #if defined(CONFIG_BT_CTLR_LE_ENC) || defined(CONFIG_BT_CTLR_BROADCAST_ISO_ENC) hal_trigger_crypt_ppi_disable(); @@ -1173,7 +1158,7 @@ void radio_tmr_status_reset(void) void radio_tmr_tx_status_reset(void) { - nrf_rtc_event_disable(NRF_RTC0, RTC_EVTENCLR_COMPARE2_Msk); + nrf_rtc_event_disable(NRF_RTC, RTC_EVTENCLR_COMPARE2_Msk); #if defined(CONFIG_BT_CTLR_LE_ENC) || defined(CONFIG_BT_CTLR_BROADCAST_ISO_ENC) hal_trigger_crypt_ppi_disable(); @@ -1216,7 +1201,7 @@ void radio_tmr_tx_status_reset(void) void radio_tmr_rx_status_reset(void) { - nrf_rtc_event_disable(NRF_RTC0, RTC_EVTENCLR_COMPARE2_Msk); + nrf_rtc_event_disable(NRF_RTC, RTC_EVTENCLR_COMPARE2_Msk); #if defined(CONFIG_BT_CTLR_LE_ENC) || defined(CONFIG_BT_CTLR_BROADCAST_ISO_ENC) hal_trigger_crypt_ppi_disable(); @@ -1309,13 +1294,13 @@ uint32_t radio_tmr_start(uint8_t trx, uint32_t ticks_start, uint32_t remainder) nrf_timer_task_trigger(EVENT_TIMER, NRF_TIMER_TASK_CLEAR); EVENT_TIMER->MODE = 0; - EVENT_TIMER->PRESCALER = 4; + EVENT_TIMER->PRESCALER = HAL_EVENT_TIMER_PRESCALER_VALUE; EVENT_TIMER->BITMODE = 2; /* 24 - bit */ nrf_timer_cc_set(EVENT_TIMER, 0, remainder); - nrf_rtc_cc_set(NRF_RTC0, 2, ticks_start); - nrf_rtc_event_enable(NRF_RTC0, RTC_EVTENSET_COMPARE2_Msk); + nrf_rtc_cc_set(NRF_RTC, 2, ticks_start); + nrf_rtc_event_enable(NRF_RTC, RTC_EVTENSET_COMPARE2_Msk); hal_event_timer_start_ppi_config(); hal_radio_nrf_ppi_channels_enable(BIT(HAL_EVENT_TIMER_START_PPI)); @@ -1329,7 +1314,7 @@ uint32_t radio_tmr_start(uint8_t trx, uint32_t ticks_start, uint32_t remainder) #else /* !CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER */ nrf_timer_task_trigger(SW_SWITCH_TIMER, NRF_TIMER_TASK_CLEAR); SW_SWITCH_TIMER->MODE = 0; - SW_SWITCH_TIMER->PRESCALER = 4; + SW_SWITCH_TIMER->PRESCALER = HAL_EVENT_TIMER_PRESCALER_VALUE; SW_SWITCH_TIMER->BITMODE = 0; /* 16 bit */ /* FIXME: start along with EVENT_TIMER, to save power */ nrf_timer_task_trigger(SW_SWITCH_TIMER, NRF_TIMER_TASK_START); @@ -1365,8 +1350,8 @@ uint32_t radio_tmr_start_tick(uint8_t trx, uint32_t tick) remainder_us = 1; nrf_timer_cc_set(EVENT_TIMER, 0, remainder_us); - nrf_rtc_cc_set(NRF_RTC0, 2, tick); - nrf_rtc_event_enable(NRF_RTC0, RTC_EVTENSET_COMPARE2_Msk); + nrf_rtc_cc_set(NRF_RTC, 2, tick); + nrf_rtc_event_enable(NRF_RTC, RTC_EVTENSET_COMPARE2_Msk); hal_event_timer_start_ppi_config(); hal_radio_nrf_ppi_channels_enable(BIT(HAL_EVENT_TIMER_START_PPI)); @@ -1460,7 +1445,7 @@ uint32_t radio_tmr_start_now(uint8_t trx) uint32_t radio_tmr_start_get(void) { - return nrf_rtc_cc_get(NRF_RTC0, 2); + return nrf_rtc_cc_get(NRF_RTC, 2); } void radio_tmr_stop(void) diff --git a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_df.c b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_df.c index 1ca5438af3fd5..7935007baeb59 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_df.c +++ b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_df.c @@ -400,7 +400,7 @@ void radio_switch_complete_and_phy_end_b2b_tx(uint8_t phy_curr, uint8_t flags_cu NRF_RADIO->SHORTS = RADIO_SHORTS_READY_START_Msk | RADIO_SHORTS_END_DISABLE_Msk | RADIO_SHORTS_DISABLED_TXEN_Msk; #else /* !CONFIG_BT_CTLR_TIFS_HW */ - NRF_RADIO->SHORTS = RADIO_SHORTS_READY_START_Msk | NRF_RADIO_SHORTS_PDU_END_DISABLE; + NRF_RADIO->SHORTS = RADIO_SHORTS_READY_START_Msk | NRF_RADIO_SHORTS_TRX_END_DISABLE_Msk; sw_switch(SW_SWITCH_TX, SW_SWITCH_TX, phy_curr, flags_curr, phy_next, flags_next, END_EVT_DELAY_DISABLED); #endif /* !CONFIG_BT_CTLR_TIFS_HW */ diff --git a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf51.h b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf51.h index c1e27087150aa..4ccb6f2e30990 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf51.h +++ b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf51.h @@ -5,6 +5,12 @@ * SPDX-License-Identifier: Apache-2.0 */ +/* Use the NRF_RTC instance for coarse radio event scheduling */ +#define NRF_RTC NRF_RTC0 + +/* HAL abstraction of event timer prescaler value */ +#define HAL_EVENT_TIMER_PRESCALER_VALUE 4U + /* TXEN->TXIDLE + TXIDLE->TX in microseconds. */ #define HAL_RADIO_NRF51_TXEN_TXIDLE_TX_US 140 #define HAL_RADIO_NRF51_TXEN_TXIDLE_TX_NS 140000 @@ -17,6 +23,14 @@ #define HAL_RADIO_NRF51_RX_CHAIN_DELAY_US 3 /* ceil(3.0) */ #define HAL_RADIO_NRF51_RX_CHAIN_DELAY_NS 3000 /* 3.0 */ +/* HAL abstraction of Radio bitfields */ +#define HAL_RADIO_INTENSET_DISABLED_Msk RADIO_INTENSET_DISABLED_Msk +#define HAL_RADIO_SHORTS_TRX_END_DISABLE_Msk RADIO_SHORTS_END_DISABLE_Msk +#define HAL_RADIO_SHORTS_TRX_PHYEND_DISABLE_Msk RADIO_SHORTS_PHYEND_DISABLE_Msk + +/* HAL abstraction of Radio IRQ number */ +#define HAL_RADIO_IRQn RADIO_IRQn + static inline void hal_radio_reset(void) { /* TODO: Add any required setup for each radio event diff --git a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf52805.h b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf52805.h index 93d2215e9542b..ad4e1377d39c6 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf52805.h +++ b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf52805.h @@ -4,6 +4,12 @@ * SPDX-License-Identifier: Apache-2.0 */ +/* Use the NRF_RTC instance for coarse radio event scheduling */ +#define NRF_RTC NRF_RTC0 + +/* HAL abstraction of event timer prescaler value */ +#define HAL_EVENT_TIMER_PRESCALER_VALUE 4U + /* NRF Radio HW timing constants * - provided in US and NS (for higher granularity) * - based on empirical measurements and sniffer logs @@ -179,6 +185,14 @@ #endif /* !CONFIG_BT_CTLR_TIFS_HW */ #endif /* !CONFIG_BT_CTLR_RADIO_ENABLE_FAST */ +/* HAL abstraction of Radio bitfields */ +#define HAL_RADIO_INTENSET_DISABLED_Msk RADIO_INTENSET_DISABLED_Msk +#define HAL_RADIO_SHORTS_TRX_END_DISABLE_Msk RADIO_SHORTS_END_DISABLE_Msk +#define HAL_RADIO_SHORTS_TRX_PHYEND_DISABLE_Msk RADIO_SHORTS_PHYEND_DISABLE_Msk + +/* HAL abstraction of Radio IRQ number */ +#define HAL_RADIO_IRQn RADIO_IRQn + static inline void hal_radio_reset(void) { /* TODO: Add any required setup for each radio event diff --git a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf52810.h b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf52810.h index 9e03963ae6c6b..b672f74cf9ae0 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf52810.h +++ b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf52810.h @@ -6,6 +6,12 @@ #include +/* Use the NRF_RTC instance for coarse radio event scheduling */ +#define NRF_RTC NRF_RTC0 + +/* HAL abstraction of event timer prescaler value */ +#define HAL_EVENT_TIMER_PRESCALER_VALUE 4U + /* NRF Radio HW timing constants * - provided in US and NS (for higher granularity) * - based on empirical measurements and sniffer logs @@ -181,6 +187,14 @@ #endif /* !CONFIG_BT_CTLR_TIFS_HW */ #endif /* !CONFIG_BT_CTLR_RADIO_ENABLE_FAST */ +/* HAL abstraction of Radio bitfields */ +#define HAL_RADIO_INTENSET_DISABLED_Msk RADIO_INTENSET_DISABLED_Msk +#define HAL_RADIO_SHORTS_TRX_END_DISABLE_Msk RADIO_SHORTS_END_DISABLE_Msk +#define HAL_RADIO_SHORTS_TRX_PHYEND_DISABLE_Msk RADIO_SHORTS_PHYEND_DISABLE_Msk + +/* HAL abstraction of Radio IRQ number */ +#define HAL_RADIO_IRQn RADIO_IRQn + static inline void hal_radio_reset(void) { /* nRF52810 itself is not affected with these anomalies but it might be diff --git a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf52811.h b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf52811.h index 1247f6e69c087..4c057a3daf877 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf52811.h +++ b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf52811.h @@ -4,6 +4,12 @@ * SPDX-License-Identifier: Apache-2.0 */ +/* Use the NRF_RTC instance for coarse radio event scheduling */ +#define NRF_RTC NRF_RTC0 + +/* HAL abstraction of event timer prescaler value */ +#define HAL_EVENT_TIMER_PRESCALER_VALUE 4U + /* NRF Radio HW timing constants * - provided in US and NS (for higher granularity) * - based on empirical measurements and sniffer logs @@ -336,6 +342,14 @@ #endif /* !CONFIG_BT_CTLR_TIFS_HW */ #endif /* !CONFIG_BT_CTLR_RADIO_ENABLE_FAST */ +/* HAL abstraction of Radio bitfields */ +#define HAL_RADIO_INTENSET_DISABLED_Msk RADIO_INTENSET_DISABLED_Msk +#define HAL_RADIO_SHORTS_TRX_END_DISABLE_Msk RADIO_SHORTS_END_DISABLE_Msk +#define HAL_RADIO_SHORTS_TRX_PHYEND_DISABLE_Msk RADIO_SHORTS_PHYEND_DISABLE_Msk + +/* HAL abstraction of Radio IRQ number */ +#define HAL_RADIO_IRQn RADIO_IRQn + /* SoC specific NRF_RADIO power-on reset value. Refer to Product Specification, * RADIO Registers section for the documented reset values. * diff --git a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf52820.h b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf52820.h index 33ba6fa165414..4439550608fcf 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf52820.h +++ b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf52820.h @@ -4,6 +4,12 @@ * SPDX-License-Identifier: Apache-2.0 */ +/* Use the NRF_RTC instance for coarse radio event scheduling */ +#define NRF_RTC NRF_RTC0 + +/* HAL abstraction of event timer prescaler value */ +#define HAL_EVENT_TIMER_PRESCALER_VALUE 4U + /* NRF Radio HW timing constants * - provided in US and NS (for higher granularity) * - based on empirical measurements and sniffer logs @@ -336,6 +342,14 @@ #endif /* !CONFIG_BT_CTLR_TIFS_HW */ #endif /* !CONFIG_BT_CTLR_RADIO_ENABLE_FAST */ +/* HAL abstraction of Radio bitfields */ +#define HAL_RADIO_INTENSET_DISABLED_Msk RADIO_INTENSET_DISABLED_Msk +#define HAL_RADIO_SHORTS_TRX_END_DISABLE_Msk RADIO_SHORTS_END_DISABLE_Msk +#define HAL_RADIO_SHORTS_TRX_PHYEND_DISABLE_Msk RADIO_SHORTS_PHYEND_DISABLE_Msk + +/* HAL abstraction of Radio IRQ number */ +#define HAL_RADIO_IRQn RADIO_IRQn + /* SoC specific NRF_RADIO power-on reset value. Refer to Product Specification, * RADIO Registers section for the documented reset values. * diff --git a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf52832.h b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf52832.h index a5df5fe1ccea2..398c92b5064de 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf52832.h +++ b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf52832.h @@ -7,6 +7,12 @@ #include +/* Use the NRF_RTC instance for coarse radio event scheduling */ +#define NRF_RTC NRF_RTC0 + +/* HAL abstraction of event timer prescaler value */ +#define HAL_EVENT_TIMER_PRESCALER_VALUE 4U + /* NRF Radio HW timing constants * - provided in US and NS (for higher granularity) * - based on empirical measurements and sniffer logs @@ -182,6 +188,14 @@ #endif /* !CONFIG_BT_CTLR_TIFS_HW */ #endif /* !CONFIG_BT_CTLR_RADIO_ENABLE_FAST */ +/* HAL abstraction of Radio bitfields */ +#define HAL_RADIO_INTENSET_DISABLED_Msk RADIO_INTENSET_DISABLED_Msk +#define HAL_RADIO_SHORTS_TRX_END_DISABLE_Msk RADIO_SHORTS_END_DISABLE_Msk +#define HAL_RADIO_SHORTS_TRX_PHYEND_DISABLE_Msk RADIO_SHORTS_PHYEND_DISABLE_Msk + +/* HAL abstraction of Radio IRQ number */ +#define HAL_RADIO_IRQn RADIO_IRQn + static inline void hal_radio_reset(void) { if (nrf52_errata_102() || nrf52_errata_106() || nrf52_errata_107()) { diff --git a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf52833.h b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf52833.h index 18b53976d97d9..a0f424a897153 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf52833.h +++ b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf52833.h @@ -4,6 +4,12 @@ * SPDX-License-Identifier: Apache-2.0 */ +/* Use the NRF_RTC instance for coarse radio event scheduling */ +#define NRF_RTC NRF_RTC0 + +/* HAL abstraction of event timer prescaler value */ +#define HAL_EVENT_TIMER_PRESCALER_VALUE 4U + /* NRF Radio HW timing constants * - provided in US and NS (for higher granularity) * - based on empirical measurements and sniffer logs @@ -336,6 +342,14 @@ #endif /* !CONFIG_BT_CTLR_TIFS_HW */ #endif /* !CONFIG_BT_CTLR_RADIO_ENABLE_FAST */ +/* HAL abstraction of Radio bitfields */ +#define HAL_RADIO_INTENSET_DISABLED_Msk RADIO_INTENSET_DISABLED_Msk +#define HAL_RADIO_SHORTS_TRX_END_DISABLE_Msk RADIO_SHORTS_END_DISABLE_Msk +#define HAL_RADIO_SHORTS_TRX_PHYEND_DISABLE_Msk RADIO_SHORTS_PHYEND_DISABLE_Msk + +/* HAL abstraction of Radio IRQ number */ +#define HAL_RADIO_IRQn RADIO_IRQn + /* SoC specific NRF_RADIO power-on reset value. Refer to Product Specification, * RADIO Registers section for the documented reset values. * diff --git a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf52840.h b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf52840.h index 98fe83ebea79c..07c9a7d6130b7 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf52840.h +++ b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf52840.h @@ -7,6 +7,12 @@ #include +/* Use the NRF_RTC instance for coarse radio event scheduling */ +#define NRF_RTC NRF_RTC0 + +/* HAL abstraction of event timer prescaler value */ +#define HAL_EVENT_TIMER_PRESCALER_VALUE 4U + /* NRF Radio HW timing constants * - provided in US and NS (for higher granularity) * - based on empirical measurements and sniffer logs @@ -339,6 +345,14 @@ #endif /* !CONFIG_BT_CTLR_TIFS_HW */ #endif /* !CONFIG_BT_CTLR_RADIO_ENABLE_FAST */ +/* HAL abstraction of Radio bitfields */ +#define HAL_RADIO_INTENSET_DISABLED_Msk RADIO_INTENSET_DISABLED_Msk +#define HAL_RADIO_SHORTS_TRX_END_DISABLE_Msk RADIO_SHORTS_END_DISABLE_Msk +#define HAL_RADIO_SHORTS_TRX_PHYEND_DISABLE_Msk RADIO_SHORTS_PHYEND_DISABLE_Msk + +/* HAL abstraction of Radio IRQ number */ +#define HAL_RADIO_IRQn RADIO_IRQn + static inline void hal_radio_reset(void) { /* TODO: Add any required setup for each radio event diff --git a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5340.h b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5340.h index 68267490129ce..d3c1dbe0687c9 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5340.h +++ b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5340.h @@ -5,6 +5,9 @@ * SPDX-License-Identifier: Apache-2.0 */ +/* Use the NRF_RTC instance for coarse radio event scheduling */ +#define NRF_RTC NRF_RTC0 + /* Override EVENT_TIMER_ID from 4 to 0, as nRF5340 does not have 4 timer * instances. */ @@ -19,6 +22,9 @@ #define SW_SWITCH_TIMER EVENT_TIMER #endif /* CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER */ +/* HAL abstraction of event timer prescaler value */ +#define HAL_EVENT_TIMER_PRESCALER_VALUE 4U + /* NRF Radio HW timing constants * - provided in US and NS (for higher granularity) * - based on empirical measurements and sniffer logs @@ -358,6 +364,14 @@ #define RADIO_TXPOWER_TXPOWER_Pos3dBm (0x03UL) #endif +/* HAL abstraction of Radio bitfields */ +#define HAL_RADIO_INTENSET_DISABLED_Msk RADIO_INTENSET_DISABLED_Msk +#define HAL_RADIO_SHORTS_TRX_END_DISABLE_Msk RADIO_SHORTS_END_DISABLE_Msk +#define HAL_RADIO_SHORTS_TRX_PHYEND_DISABLE_Msk RADIO_SHORTS_PHYEND_DISABLE_Msk + +/* HAL abstraction of Radio IRQ number */ +#define HAL_RADIO_IRQn RADIO_IRQn + /* SoC specific NRF_RADIO power-on reset value. Refer to Product Specification, * RADIO Registers section for the documented reset values. * 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 6c975bccbc97f..be0844015682e 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 @@ -96,7 +96,7 @@ static inline void hal_radio_end_time_capture_ppi_config(void) */ static inline void hal_event_timer_start_ppi_config(void) { - nrf_rtc_publish_set(NRF_RTC0, NRF_RTC_EVENT_COMPARE_2, HAL_EVENT_TIMER_START_PPI); + nrf_rtc_publish_set(NRF_RTC, NRF_RTC_EVENT_COMPARE_2, HAL_EVENT_TIMER_START_PPI); nrf_timer_subscribe_set(EVENT_TIMER, NRF_TIMER_TASK_START, HAL_EVENT_TIMER_START_PPI); } 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 1976df32233c7..2aee25e2d850d 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 @@ -159,7 +159,7 @@ static inline void hal_radio_end_time_capture_ppi_config(void) nrf_ppi_channel_endpoint_setup( NRF_PPI, HAL_RADIO_END_TIME_CAPTURE_PPI, - (uint32_t)&(NRF_RADIO->NRF_RADIO_TXRX_END_EVENT), + (uint32_t)&(NRF_RADIO->NRF_RADIO_TRX_END_EVENT), (uint32_t)&(EVENT_TIMER->TASKS_CAPTURE[2])); } @@ -285,7 +285,7 @@ static inline void hal_sw_switch_timer_clear_ppi_config(void) nrf_ppi_channel_endpoint_setup( NRF_PPI, HAL_SW_SWITCH_TIMER_CLEAR_PPI, - (uint32_t)&(NRF_RADIO->NRF_RADIO_TXRX_END_EVENT), + (uint32_t)&(NRF_RADIO->NRF_RADIO_TRX_END_EVENT), (uint32_t)&(SW_SWITCH_TIMER->TASKS_CLEAR)); } @@ -346,7 +346,7 @@ static inline void hal_sw_switch_timer_clear_ppi_config(void) * 'index' must be 0 or 1. */ #define HAL_SW_SWITCH_GROUP_TASK_ENABLE_PPI_EVT \ - ((uint32_t)&(NRF_RADIO->NRF_RADIO_TXRX_END_EVENT)) + ((uint32_t)&(NRF_RADIO->NRF_RADIO_TRX_END_EVENT)) #define HAL_SW_SWITCH_GROUP_TASK_ENABLE_PPI_TASK(index) \ ((uint32_t)&(NRF_PPI->TASKS_CHG[SW_SWITCH_TIMER_TASK_GROUP(index)].EN)) diff --git a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5_resources.h b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5_resources.h index 87acc1896ee1b..259649f86549e 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5_resources.h +++ b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5_resources.h @@ -15,11 +15,12 @@ * or reception of a PDU on air. In case of regular PDU it is generated when last bit of CRC is * received or transmitted. */ -#define NRF_RADIO_TXRX_END_EVENT EVENTS_END +#define NRF_RADIO_TRX_END_EVENT EVENTS_END + /* Wrapper for RADIO_SHORTS mask connecting EVENTS_END to EVENTS_DISABLE. * This is a default shortcut used to automatically disable Radio after end of PDU. */ -#define NRF_RADIO_SHORTS_PDU_END_DISABLE RADIO_SHORTS_END_DISABLE_Msk +#define NRF_RADIO_SHORTS_TRX_END_DISABLE_Msk HAL_RADIO_SHORTS_TRX_END_DISABLE_Msk #define HAL_EVENT_TIMER_SAMPLE_CC_OFFSET 3 #define HAL_EVENT_TIMER_SAMPLE_TASK NRF_TIMER_TASK_CAPTURE3 @@ -39,11 +40,12 @@ * or reception of a PDU on air. In case of regular PDU it is generated when last bit of CRC is * received or transmitted. */ -#define NRF_RADIO_TXRX_END_EVENT EVENTS_END +#define NRF_RADIO_TRX_END_EVENT EVENTS_END + /* Wrapper for RADIO_SHORTS mask connecting EVENTS_END to EVENTS_DISABLE. * This is a default shortcut used to automatically disable Radio after end of PDU. */ -#define NRF_RADIO_SHORTS_PDU_END_DISABLE RADIO_SHORTS_END_DISABLE_Msk +#define NRF_RADIO_SHORTS_TRX_END_DISABLE_Msk HAL_RADIO_SHORTS_TRX_END_DISABLE_Msk #define HAL_EVENT_TIMER_SAMPLE_CC_OFFSET 2 #define HAL_EVENT_TIMER_SAMPLE_TASK NRF_TIMER_TASK_CAPTURE2 @@ -55,11 +57,12 @@ * or reception of a PDU on air. In case of regular PDU it is generated when last bit of CRC is * received or transmitted. */ -#define NRF_RADIO_TXRX_END_EVENT EVENTS_END +#define NRF_RADIO_TRX_END_EVENT EVENTS_END + /* Wrapper for RADIO_SHORTS mask connecting EVENTS_END to EVENTS_DISABLE. * This is a default shortcut used to automatically disable Radio after end of PDU. */ -#define NRF_RADIO_SHORTS_PDU_END_DISABLE RADIO_SHORTS_END_DISABLE_Msk +#define NRF_RADIO_SHORTS_TRX_END_DISABLE_Msk HAL_RADIO_SHORTS_TRX_END_DISABLE_Msk #define HAL_EVENT_TIMER_SAMPLE_CC_OFFSET 3 #define HAL_EVENT_TIMER_SAMPLE_TASK NRF_TIMER_TASK_CAPTURE3 @@ -95,7 +98,7 @@ * including CTE EVENTS_PHYEND event is generated at very end of a PDU. In case there is no CTE in * a PDU the EVENTS_PHYEND event is generated in the same instant as EVENTS_END event. */ -#define NRF_RADIO_TXRX_END_EVENT EVENTS_PHYEND +#define NRF_RADIO_TRX_END_EVENT EVENTS_PHYEND /* Wrapper for RADIO_SHORTS mask connecting EVENTS_PHYEND to EVENTS_DISABLE. * This is a mask for SOC that has Direction Finding Extension in a Radio peripheral. @@ -103,7 +106,7 @@ * In case there is a CTE in a PDU then EVENTS_PHYEND event is generated after the CTE. * If there is no CTE, it is generated in the same instant as EVENTS_END. */ -#define NRF_RADIO_SHORTS_PDU_END_DISABLE RADIO_SHORTS_PHYEND_DISABLE_Msk +#define NRF_RADIO_SHORTS_TRX_END_DISABLE_Msk HAL_RADIO_SHORTS_TRX_PHYEND_DISABLE_Msk /* Delay of EVENTS_PHYEND event on receive PDU without CTE inclded when CTEINLINE is enabled */ #define RADIO_EVENTS_PHYEND_DELAY_US 16 @@ -116,11 +119,12 @@ * or reception of a PDU on air. In case of regular PDU it is generated when last bit of CRC is * received or transmitted. */ -#define NRF_RADIO_TXRX_END_EVENT EVENTS_END +#define NRF_RADIO_TRX_END_EVENT EVENTS_END + /* Wrapper for RADIO_SHORTS mask connecting EVENTS_END to EVENTS_DISABLE. * This is a default shortcut used to automatically disable Radio after end of PDU. */ -#define NRF_RADIO_SHORTS_PDU_END_DISABLE RADIO_SHORTS_END_DISABLE_Msk +#define NRF_RADIO_SHORTS_TRX_END_DISABLE_Msk HAL_RADIO_SHORTS_TRX_END_DISABLE_Msk #endif /* !CONFIG_BT_CTLR_DF */ #define HAL_EVENT_TIMER_SAMPLE_CC_OFFSET 3 diff --git a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_sim_nrf52.h b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_sim_nrf52.h index 9f78ae78b2717..8e4838ef10ede 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_sim_nrf52.h +++ b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_sim_nrf52.h @@ -12,6 +12,12 @@ */ #include +/* Use the NRF_RTC instance for coarse radio event scheduling */ +#define NRF_RTC NRF_RTC0 + +/* HAL abstraction of event timer prescaler value */ +#define HAL_EVENT_TIMER_PRESCALER_VALUE 4U + /* NRF Radio HW timing constants * - provided in US and NS (for higher granularity) * - based on the timings configured in the HW models, which are based @@ -345,6 +351,14 @@ #endif /* !CONFIG_BT_CTLR_TIFS_HW */ #endif /* !CONFIG_BT_CTLR_RADIO_ENABLE_FAST */ +/* HAL abstraction of Radio bitfields */ +#define HAL_RADIO_INTENSET_DISABLED_Msk RADIO_INTENSET_DISABLED_Msk +#define HAL_RADIO_SHORTS_TRX_END_DISABLE_Msk RADIO_SHORTS_END_DISABLE_Msk +#define HAL_RADIO_SHORTS_TRX_PHYEND_DISABLE_Msk RADIO_SHORTS_PHYEND_DISABLE_Msk + +/* HAL abstraction of Radio IRQ number */ +#define HAL_RADIO_IRQn RADIO_IRQn + static inline void hal_radio_reset(void) { } diff --git a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_sim_nrf5340.h b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_sim_nrf5340.h index 101ace5d9e115..6e115926c41cb 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_sim_nrf5340.h +++ b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_sim_nrf5340.h @@ -8,13 +8,8 @@ #include #include -/* NRF Radio HW timing constants - * - provided in US and NS (for higher granularity) - * - based on the timings configured in the HW models, which are based - * on the product specification - * - Note that this timings are approx. the same as in the real HW, - * but tend to be rounded to the nearest microsecond - */ +/* Use the NRF_RTC instance for coarse radio event scheduling */ +#define NRF_RTC NRF_RTC0 /* Override EVENT_TIMER_ID from 4 to 0, as nRF5340 does not have 4 timer * instances. @@ -30,6 +25,17 @@ #define SW_SWITCH_TIMER EVENT_TIMER #endif /* CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER */ +/* HAL abstraction of event timer prescaler value */ +#define HAL_EVENT_TIMER_PRESCALER_VALUE 4U + +/* NRF Radio HW timing constants + * - provided in US and NS (for higher granularity) + * - based on the timings configured in the HW models, which are based + * on the product specification + * - Note that this timings are approx. the same as in the real HW, + * but tend to be rounded to the nearest microsecond + */ + /* TXEN->TXIDLE + TXIDLE->TX (with fast Radio ramp-up mode) * in microseconds for LE 1M PHY. */ @@ -359,6 +365,14 @@ #define RADIO_TXPOWER_TXPOWER_Pos3dBm (0x03UL) #endif +/* HAL abstraction of Radio bitfields */ +#define HAL_RADIO_INTENSET_DISABLED_Msk RADIO_INTENSET_DISABLED_Msk +#define HAL_RADIO_SHORTS_TRX_END_DISABLE_Msk RADIO_SHORTS_END_DISABLE_Msk +#define HAL_RADIO_SHORTS_TRX_PHYEND_DISABLE_Msk RADIO_SHORTS_PHYEND_DISABLE_Msk + +/* HAL abstraction of Radio IRQ number */ +#define HAL_RADIO_IRQn RADIO_IRQn + /* SoC specific NRF_RADIO power-on reset value. Refer to Product Specification, * RADIO Registers section for the documented reset values. * diff --git a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/swi.h b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/swi.h index 6b364fd349ae9..8f831e4554802 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/swi.h +++ b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/swi.h @@ -17,6 +17,8 @@ #define HAL_SWI_JOB_IRQ SWI5_IRQn #endif +#define HAL_RTC_IRQn RTC0_IRQn + /* nRF53 Series IRQ mapping */ #elif defined(CONFIG_SOC_COMPATIBLE_NRF53X) @@ -33,8 +35,11 @@ #define HAL_SWI_JOB_IRQ SWI3_IRQn #endif -#endif /* CONFIG_SOC_COMPATIBLE_NRF5340_CPUNET */ +#define HAL_RTC_IRQn RTC0_IRQn +#elif /* !CONFIG_SOC_COMPATIBLE_NRF5340_CPUNET */ +#error Unknown NRF5340 CPU. +#endif /* !CONFIG_SOC_COMPATIBLE_NRF5340_CPUNET */ #endif /* CONFIG_SOC_COMPATIBLE_NRF53X */ static inline void hal_swi_init(void) diff --git a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll.c b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll.c index ce47ec56226c4..8e3af92ea2434 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll.c +++ b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll.c @@ -120,8 +120,8 @@ static void rtc0_nrf5_isr(const void *arg) lll_prof_enter_ull_high(); /* On compare0 run ticker worker instance0 */ - if (NRF_RTC0->EVENTS_COMPARE[0]) { - nrf_rtc_event_clear(NRF_RTC0, NRF_RTC_EVENT_COMPARE_0); + if (NRF_RTC->EVENTS_COMPARE[0]) { + nrf_rtc_event_clear(NRF_RTC, NRF_RTC_EVENT_COMPARE_0); ticker_trigger(0); } @@ -210,15 +210,15 @@ int lll_init(void) /* Connect ISRs */ #if defined(CONFIG_BT_CTLR_DYNAMIC_INTERRUPTS) #if defined(CONFIG_DYNAMIC_DIRECT_INTERRUPTS) - ARM_IRQ_DIRECT_DYNAMIC_CONNECT(RADIO_IRQn, CONFIG_BT_CTLR_LLL_PRIO, + ARM_IRQ_DIRECT_DYNAMIC_CONNECT(HAL_RADIO_IRQn, CONFIG_BT_CTLR_LLL_PRIO, IRQ_CONNECT_FLAGS, no_reschedule); - irq_connect_dynamic(RADIO_IRQn, CONFIG_BT_CTLR_LLL_PRIO, + irq_connect_dynamic(HAL_RADIO_IRQn, CONFIG_BT_CTLR_LLL_PRIO, radio_nrf5_isr, NULL, IRQ_CONNECT_FLAGS); #else /* !CONFIG_DYNAMIC_DIRECT_INTERRUPTS */ - IRQ_DIRECT_CONNECT(RADIO_IRQn, CONFIG_BT_CTLR_LLL_PRIO, + IRQ_DIRECT_CONNECT(HAL_RADIO_IRQn, CONFIG_BT_CTLR_LLL_PRIO, radio_nrf5_isr, IRQ_CONNECT_FLAGS); #endif /* !CONFIG_DYNAMIC_DIRECT_INTERRUPTS */ - irq_connect_dynamic(RTC0_IRQn, CONFIG_BT_CTLR_ULL_HIGH_PRIO, + irq_connect_dynamic(HAL_RTC_IRQn, CONFIG_BT_CTLR_ULL_HIGH_PRIO, rtc0_nrf5_isr, NULL, 0U); irq_connect_dynamic(HAL_SWI_RADIO_IRQ, CONFIG_BT_CTLR_LLL_PRIO, swi_lll_nrf5_isr, NULL, IRQ_CONNECT_FLAGS); @@ -229,9 +229,9 @@ int lll_init(void) #endif #else /* !CONFIG_BT_CTLR_DYNAMIC_INTERRUPTS */ - IRQ_DIRECT_CONNECT(RADIO_IRQn, CONFIG_BT_CTLR_LLL_PRIO, + IRQ_DIRECT_CONNECT(HAL_RADIO_IRQn, CONFIG_BT_CTLR_LLL_PRIO, radio_nrf5_isr, IRQ_CONNECT_FLAGS); - IRQ_CONNECT(RTC0_IRQn, CONFIG_BT_CTLR_ULL_HIGH_PRIO, + IRQ_CONNECT(HAL_RTC_IRQn, CONFIG_BT_CTLR_ULL_HIGH_PRIO, rtc0_nrf5_isr, NULL, 0); #if defined(CONFIG_BT_CTLR_ZLI) IRQ_DIRECT_CONNECT(HAL_SWI_RADIO_IRQ, CONFIG_BT_CTLR_LLL_PRIO, @@ -248,8 +248,8 @@ int lll_init(void) #endif /* !CONFIG_BT_CTLR_DYNAMIC_INTERRUPTS */ /* Enable IRQs */ - irq_enable(RADIO_IRQn); - irq_enable(RTC0_IRQn); + irq_enable(HAL_RADIO_IRQn); + irq_enable(HAL_RTC_IRQn); irq_enable(HAL_SWI_RADIO_IRQ); if (IS_ENABLED(CONFIG_BT_CTLR_LOW_LAT) || (CONFIG_BT_CTLR_ULL_HIGH_PRIO != CONFIG_BT_CTLR_ULL_LOW_PRIO)) { @@ -277,8 +277,8 @@ int lll_deinit(void) } /* Disable IRQs */ - irq_disable(RADIO_IRQn); - irq_disable(RTC0_IRQn); + irq_disable(HAL_RADIO_IRQn); + irq_disable(HAL_RTC_IRQn); irq_disable(HAL_SWI_RADIO_IRQ); if (IS_ENABLED(CONFIG_BT_CTLR_LOW_LAT) || (CONFIG_BT_CTLR_ULL_HIGH_PRIO != CONFIG_BT_CTLR_ULL_LOW_PRIO)) { @@ -289,10 +289,10 @@ int lll_deinit(void) #if defined(CONFIG_BT_CTLR_DYNAMIC_INTERRUPTS) #if defined(CONFIG_SHARED_INTERRUPTS) #if defined(CONFIG_DYNAMIC_DIRECT_INTERRUPTS) - irq_disconnect_dynamic(RADIO_IRQn, CONFIG_BT_CTLR_LLL_PRIO, + irq_disconnect_dynamic(HAL_RADIO_IRQn, CONFIG_BT_CTLR_LLL_PRIO, radio_nrf5_isr, NULL, IRQ_CONNECT_FLAGS); #endif /* CONFIG_DYNAMIC_DIRECT_INTERRUPTS */ - irq_disconnect_dynamic(RTC0_IRQn, CONFIG_BT_CTLR_ULL_HIGH_PRIO, + irq_disconnect_dynamic(HAL_RTC_IRQn, CONFIG_BT_CTLR_ULL_HIGH_PRIO, rtc0_nrf5_isr, NULL, 0U); irq_disconnect_dynamic(HAL_SWI_RADIO_IRQ, CONFIG_BT_CTLR_LLL_PRIO, swi_lll_nrf5_isr, NULL, IRQ_CONNECT_FLAGS); @@ -303,10 +303,10 @@ int lll_deinit(void) #endif #else /* !CONFIG_SHARED_INTERRUPTS */ #if defined(CONFIG_DYNAMIC_DIRECT_INTERRUPTS) - irq_connect_dynamic(RADIO_IRQn, CONFIG_BT_CTLR_LLL_PRIO, NULL, NULL, + irq_connect_dynamic(HAL_RADIO_IRQn, CONFIG_BT_CTLR_LLL_PRIO, NULL, NULL, IRQ_CONNECT_FLAGS); #endif /* CONFIG_DYNAMIC_DIRECT_INTERRUPTS */ - irq_connect_dynamic(RTC0_IRQn, CONFIG_BT_CTLR_ULL_HIGH_PRIO, NULL, NULL, + irq_connect_dynamic(HAL_RTC_IRQn, CONFIG_BT_CTLR_ULL_HIGH_PRIO, NULL, NULL, 0U); irq_connect_dynamic(HAL_SWI_RADIO_IRQ, CONFIG_BT_CTLR_LLL_PRIO, NULL, NULL, IRQ_CONNECT_FLAGS); From f59c3fafe85c25826020d0152d8840121dc4e09e Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Mon, 20 May 2024 17:45:33 +0200 Subject: [PATCH 2036/2849] Bluetooth: Controller: Preliminary support for nRF54L15 SoC Add preliminary support for nRF54L15 SoC. This commit does not support Controller Random Number Generation and Controller Cryptography (AES-128 encryption) commands, nor does it support encrypted connections. Signed-off-by: Vinayak Kariappa Chettimada --- samples/bluetooth/beacon/sample.yaml | 11 +- samples/bluetooth/peripheral_hr/sample.yaml | 14 + .../bluetooth/controller/Kconfig.ll_sw_split | 2 +- .../controller/ll_sw/nordic/hal/nrf5/cntr.c | 6 +- .../ll_sw/nordic/hal/nrf5/radio/radio.c | 91 +- .../ll_sw/nordic/hal/nrf5/radio/radio_nrf5.h | 4 +- .../nordic/hal/nrf5/radio/radio_nrf54lx.h | 795 ++++++++++++++++++ .../nordic/hal/nrf5/radio/radio_nrf5_dppi.h | 4 + .../controller/ll_sw/nordic/hal/nrf5/swi.h | 18 +- 9 files changed, 911 insertions(+), 34 deletions(-) create mode 100644 subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf54lx.h diff --git a/samples/bluetooth/beacon/sample.yaml b/samples/bluetooth/beacon/sample.yaml index 9073de8c1fc0f..d76a16eb566f0 100644 --- a/samples/bluetooth/beacon/sample.yaml +++ b/samples/bluetooth/beacon/sample.yaml @@ -6,13 +6,20 @@ tests: platform_allow: - qemu_cortex_m3 - qemu_x86 + - nrf51dk/nrf51822 - nrf52dk/nrf52832 + - nrf54l15pdk/nrf54l15/cpuapp tags: bluetooth integration_platforms: - qemu_cortex_m3 - + - nrf51dk/nrf51822 + - nrf52dk/nrf52832 + - nrf54l15pdk/nrf54l15/cpuapp sample.bluetooth.beacon-coex: extra_args: CONF_FILE="prj-coex.conf" harness: bluetooth - platform_allow: nrf52840dk/nrf52840 + platform_allow: + - nrf52840dk/nrf52840 + integration_platforms: + - nrf52840dk/nrf52840 tags: bluetooth diff --git a/samples/bluetooth/peripheral_hr/sample.yaml b/samples/bluetooth/peripheral_hr/sample.yaml index 87442dd3e5978..6a4f2edead029 100644 --- a/samples/bluetooth/peripheral_hr/sample.yaml +++ b/samples/bluetooth/peripheral_hr/sample.yaml @@ -7,8 +7,22 @@ tests: platform_allow: - qemu_cortex_m3 - qemu_x86 + - nrf52_bsim + - nrf5340bsim/nrf5340/cpuapp + - nrf51dk/nrf51822 + - nrf52dk/nrf52832 + - nrf52840dk/nrf52840 + - nrf5340dk/nrf5340/cpuapp + - nrf54l15pdk/nrf54l15/cpuapp integration_platforms: - qemu_cortex_m3 + - nrf52_bsim + - nrf5340bsim/nrf5340/cpuapp + - nrf51dk/nrf51822 + - nrf52dk/nrf52832 + - nrf52840dk/nrf52840 + - nrf5340dk/nrf5340/cpuapp + - nrf54l15pdk/nrf54l15/cpuapp tags: bluetooth sample.bluetooth.peripheral_hr.minimal: harness: bluetooth diff --git a/subsys/bluetooth/controller/Kconfig.ll_sw_split b/subsys/bluetooth/controller/Kconfig.ll_sw_split index 2b1ad6fb906c9..09833a64fbd9f 100644 --- a/subsys/bluetooth/controller/Kconfig.ll_sw_split +++ b/subsys/bluetooth/controller/Kconfig.ll_sw_split @@ -15,7 +15,7 @@ config BT_LLL_VENDOR_NORDIC select ENTROPY_NRF5_BIAS_CORRECTION if ENTROPY_NRF5_RNG select BT_HAS_HCI_VS - select BT_CTLR_CRYPTO_SUPPORT + select BT_CTLR_CRYPTO_SUPPORT if !SOC_SERIES_NRF54LX select BT_CTLR_LE_ENC_SUPPORT if BT_CTLR_CRYPTO_SUPPORT && \ !BT_CTLR_DATA_LENGTH_CLEAR && \ !BT_CTLR_PHY_2M_NRF diff --git a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/cntr.c b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/cntr.c index 01adf92467d7d..b8cff57df3417 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/cntr.c +++ b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/cntr.c @@ -12,8 +12,12 @@ #include "hal/debug.h" #ifndef NRF_RTC +#if defined(CONFIG_SOC_SERIES_NRF54LX) +#define NRF_RTC NRF_RTC10 +#else /* !CONFIG_SOC_SERIES_NRF54LX */ #define NRF_RTC NRF_RTC0 -#endif +#endif /* !CONFIG_SOC_SERIES_NRF54LX */ +#endif /* !NRF_RTC */ static uint8_t _refcount; 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 9a79aca931d84..67df20c4b2361 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 @@ -242,6 +242,13 @@ void radio_reset(void) hal_radio_sw_switch_ppi_group_setup(); #endif +#if defined(CONFIG_SOC_SERIES_NRF54LX) + NRF_RADIO->TIMING = (0U << RADIO_TIMING_RU_Pos) & + RADIO_TIMING_RU_Msk; + + NRF_POWER->TASKS_CONSTLAT = 1U; +#endif /* CONFIG_SOC_SERIES_NRF54LX */ + #if defined(HAL_RADIO_GPIO_HAVE_PA_PIN) || defined(HAL_RADIO_GPIO_HAVE_LNA_PIN) hal_palna_ppi_setup(); #endif @@ -306,6 +313,7 @@ void radio_phy_set(uint8_t phy, uint8_t flags) NRF_RADIO->MODE = (mode << RADIO_MODE_MODE_Pos) & RADIO_MODE_MODE_Msk; +#if !defined(CONFIG_SOC_SERIES_NRF51X) && !defined(CONFIG_SOC_SERIES_NRF54LX) #if defined(CONFIG_BT_CTLR_RADIO_ENABLE_FAST) NRF_RADIO->MODECNF0 = ((RADIO_MODECNF0_DTX_Center << RADIO_MODECNF0_DTX_Pos) & @@ -314,17 +322,22 @@ void radio_phy_set(uint8_t phy, uint8_t flags) RADIO_MODECNF0_RU_Pos) & RADIO_MODECNF0_RU_Msk); #else /* !CONFIG_BT_CTLR_RADIO_ENABLE_FAST */ -#if !defined(CONFIG_SOC_SERIES_NRF51X) NRF_RADIO->MODECNF0 = (RADIO_MODECNF0_DTX_Center << RADIO_MODECNF0_DTX_Pos) & RADIO_MODECNF0_DTX_Msk; -#endif /* !CONFIG_SOC_SERIES_NRF51X */ #endif /* !CONFIG_BT_CTLR_RADIO_ENABLE_FAST */ +#endif /* !CONFIG_SOC_SERIES_NRF51X && !CONFIG_SOC_SERIES_NRF54LX */ } void radio_tx_power_set(int8_t power) { -#if defined(CONFIG_SOC_COMPATIBLE_NRF53X) +#if defined(CONFIG_SOC_COMPATIBLE_NRF54LX) + uint32_t value; + + value = hal_radio_tx_power_value(power); + NRF_RADIO->TXPOWER = value; + +#elif defined(CONFIG_SOC_COMPATIBLE_NRF53X) uint32_t value; /* NOTE: TXPOWER register only accepts upto 0dBm, hence use the HAL @@ -335,12 +348,12 @@ void radio_tx_power_set(int8_t power) NRF_RADIO->TXPOWER = value; hal_radio_tx_power_high_voltage_set(power); -#else /* !CONFIG_SOC_COMPATIBLE_NRF53X */ +#else /* !CONFIG_SOC_COMPATIBLE_NRF53X && !CONFIG_SOC_COMPATIBLE_NRF54LX */ /* NOTE: valid value range is passed by Kconfig define. */ NRF_RADIO->TXPOWER = (uint32_t)power; -#endif /* !CONFIG_SOC_COMPATIBLE_NRF53X */ +#endif /* !CONFIG_SOC_COMPATIBLE_NRF53X && !CONFIG_SOC_COMPATIBLE_NRF54LX */ } void radio_tx_power_max_set(void) @@ -426,7 +439,8 @@ void radio_pkt_configure(uint8_t bits_len, uint8_t max_len, uint8_t flags) bits_s1 = RADIO_PKT_CONF_LENGTH_8BIT - bits_len; #elif defined(CONFIG_SOC_COMPATIBLE_NRF52X) || \ - defined(CONFIG_SOC_COMPATIBLE_NRF53X) + defined(CONFIG_SOC_COMPATIBLE_NRF53X) || \ + defined(CONFIG_SOC_SERIES_NRF54LX) extra = 0U; phy = RADIO_PKT_CONF_PHY_GET(flags); @@ -523,7 +537,7 @@ uint32_t radio_rx_chain_delay_get(uint8_t phy, uint8_t flags) void radio_rx_enable(void) { #if !defined(CONFIG_BT_CTLR_TIFS_HW) -#if defined(CONFIG_SOC_COMPATIBLE_NRF53X) +#if defined(CONFIG_SOC_COMPATIBLE_NRF53X) || defined(CONFIG_SOC_SERIES_NRF54LX) /* NOTE: Timer clear DPPI configuration is needed only for nRF53 * because of calls to radio_disable() and * radio_switch_complete_and_disable() inside a radio event call @@ -536,7 +550,7 @@ void radio_rx_enable(void) * radio event but when the radio event is done. */ hal_sw_switch_timer_clear_ppi_config(); -#endif /* CONFIG_SOC_COMPATIBLE_NRF53X */ +#endif /* CONFIG_SOC_COMPATIBLE_NRF53X || CONFIG_SOC_SERIES_NRF54LX */ #endif /* !CONFIG_BT_CTLR_TIFS_HW */ nrf_radio_task_trigger(NRF_RADIO, NRF_RADIO_TASK_RXEN); @@ -545,7 +559,7 @@ void radio_rx_enable(void) void radio_tx_enable(void) { #if !defined(CONFIG_BT_CTLR_TIFS_HW) -#if defined(CONFIG_SOC_COMPATIBLE_NRF53X) +#if defined(CONFIG_SOC_COMPATIBLE_NRF53X) || defined(CONFIG_SOC_SERIES_NRF54LX) /* NOTE: Timer clear DPPI configuration is needed only for nRF53 * because of calls to radio_disable() and * radio_switch_complete_and_disable() inside a radio event call @@ -558,7 +572,7 @@ void radio_tx_enable(void) * radio event but when the radio event is done. */ hal_sw_switch_timer_clear_ppi_config(); -#endif /* CONFIG_SOC_COMPATIBLE_NRF53X */ +#endif /* CONFIG_SOC_COMPATIBLE_NRF53X || CONFIG_SOC_SERIES_NRF54LX */ #endif /* !CONFIG_BT_CTLR_TIFS_HW */ nrf_radio_task_trigger(NRF_RADIO, NRF_RADIO_TASK_TXEN); @@ -1046,7 +1060,12 @@ void radio_rssi_measure(void) { NRF_RADIO->SHORTS |= (RADIO_SHORTS_ADDRESS_RSSISTART_Msk | - RADIO_SHORTS_DISABLED_RSSISTOP_Msk); +#if defined(CONFIG_SOC_SERIES_NRF51X) || \ + defined(CONFIG_SOC_COMPATIBLE_NRF52X) || \ + defined(CONFIG_SOC_COMPATIBLE_NRF5340_CPUNET) + RADIO_SHORTS_DISABLED_RSSISTOP_Msk | +#endif + 0); } uint32_t radio_rssi_get(void) @@ -1056,12 +1075,22 @@ uint32_t radio_rssi_get(void) void radio_rssi_status_reset(void) { +#if defined(CONFIG_SOC_SERIES_NRF51X) || \ + defined(CONFIG_SOC_COMPATIBLE_NRF52X) || \ + defined(CONFIG_SOC_COMPATIBLE_NRF5340_CPUNET) nrf_radio_event_clear(NRF_RADIO, NRF_RADIO_EVENT_RSSIEND); +#endif } uint32_t radio_rssi_is_ready(void) { +#if defined(CONFIG_SOC_SERIES_NRF51X) || \ + defined(CONFIG_SOC_COMPATIBLE_NRF52X) || \ + defined(CONFIG_SOC_COMPATIBLE_NRF5340_CPUNET) return (NRF_RADIO->EVENTS_RSSIEND != 0); +#else + return 1U; +#endif } void radio_filter_configure(uint8_t bitmask_enable, uint8_t bitmask_addr_type, @@ -1244,38 +1273,38 @@ void radio_tmr_rx_status_reset(void) void radio_tmr_tx_enable(void) { -#if defined(CONFIG_SOC_COMPATIBLE_NRF53X) -#else /* !CONFIG_SOC_COMPATIBLE_NRF53X */ +#if defined(CONFIG_SOC_COMPATIBLE_NRF53X) || defined(CONFIG_SOC_SERIES_NRF54LX) +#else /* !CONFIG_SOC_COMPATIBLE_NRF53X && !CONFIG_SOC_SERIES_NRF54LX */ #if (HAL_RADIO_ENABLE_TX_ON_TICK_PPI == HAL_RADIO_ENABLE_RX_ON_TICK_PPI) hal_radio_enable_on_tick_ppi_config_and_enable(1U); #endif /* HAL_RADIO_ENABLE_TX_ON_TICK_PPI == HAL_RADIO_ENABLE_RX_ON_TICK_PPI */ -#endif /* !CONFIG_SOC_COMPATIBLE_NRF53X */ +#endif /* !CONFIG_SOC_COMPATIBLE_NRF53X && !CONFIG_SOC_SERIES_NRF54LX */ } void radio_tmr_rx_enable(void) { -#if defined(CONFIG_SOC_COMPATIBLE_NRF53X) -#else /* !CONFIG_SOC_COMPATIBLE_NRF53X */ +#if defined(CONFIG_SOC_COMPATIBLE_NRF53X) || defined(CONFIG_SOC_SERIES_NRF54LX) +#else /* !CONFIG_SOC_COMPATIBLE_NRF53X && !CONFIG_SOC_SERIES_NRF54LX */ #if (HAL_RADIO_ENABLE_TX_ON_TICK_PPI == HAL_RADIO_ENABLE_RX_ON_TICK_PPI) hal_radio_enable_on_tick_ppi_config_and_enable(0U); #endif /* HAL_RADIO_ENABLE_TX_ON_TICK_PPI == HAL_RADIO_ENABLE_RX_ON_TICK_PPI */ -#endif /* !CONFIG_SOC_COMPATIBLE_NRF53X */ +#endif /* !CONFIG_SOC_COMPATIBLE_NRF53X && !CONFIG_SOC_SERIES_NRF54LX */ } void radio_tmr_tx_disable(void) { -#if defined(CONFIG_SOC_COMPATIBLE_NRF53X) +#if defined(CONFIG_SOC_COMPATIBLE_NRF53X) || defined(CONFIG_SOC_SERIES_NRF54LX) nrf_radio_subscribe_clear(NRF_RADIO, NRF_RADIO_TASK_TXEN); -#else /* !CONFIG_SOC_COMPATIBLE_NRF53X */ -#endif /* !CONFIG_SOC_COMPATIBLE_NRF53X */ +#else /* !CONFIG_SOC_COMPATIBLE_NRF53X && !CONFIG_SOC_SERIES_NRF54LX */ +#endif /* !CONFIG_SOC_COMPATIBLE_NRF53X && !CONFIG_SOC_SERIES_NRF54LX */ } void radio_tmr_rx_disable(void) { -#if defined(CONFIG_SOC_COMPATIBLE_NRF53X) +#if defined(CONFIG_SOC_COMPATIBLE_NRF53X) || defined(CONFIG_SOC_SERIES_NRF54LX) nrf_radio_subscribe_clear(NRF_RADIO, NRF_RADIO_TASK_RXEN); -#else /* !CONFIG_SOC_COMPATIBLE_NRF53X */ -#endif /* !CONFIG_SOC_COMPATIBLE_NRF53X */ +#else /* !CONFIG_SOC_COMPATIBLE_NRF53X && !CONFIG_SOC_SERIES_NRF54LX */ +#endif /* !CONFIG_SOC_COMPATIBLE_NRF53X && !CONFIG_SOC_SERIES_NRF54LX */ } void radio_tmr_tifs_set(uint32_t tifs) @@ -1362,7 +1391,7 @@ uint32_t radio_tmr_start_tick(uint8_t trx, uint32_t tick) #if defined(CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER) last_pdu_end_us = 0U; #endif /* CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER */ -#if defined(CONFIG_SOC_COMPATIBLE_NRF53X) +#if defined(CONFIG_SOC_COMPATIBLE_NRF53X) || defined(CONFIG_SOC_SERIES_NRF54LX) /* NOTE: Timer clear DPPI configuration is needed only for nRF53 * because of calls to radio_disable() and * radio_switch_complete_and_disable() inside a radio event call @@ -1375,7 +1404,7 @@ uint32_t radio_tmr_start_tick(uint8_t trx, uint32_t tick) * radio event but when the radio event is done. */ hal_sw_switch_timer_clear_ppi_config(); -#endif /* CONFIG_SOC_COMPATIBLE_NRF53X */ +#endif /* CONFIG_SOC_COMPATIBLE_NRF53X || CONFIG_SOC_SERIES_NRF54LX */ #endif /* !CONFIG_BT_CTLR_TIFS_HW */ return remainder_us; @@ -1389,7 +1418,7 @@ uint32_t radio_tmr_start_us(uint8_t trx, uint32_t start_us) #if defined(CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER) last_pdu_end_us = 0U; #endif /* CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER */ -#if defined(CONFIG_SOC_COMPATIBLE_NRF53X) +#if defined(CONFIG_SOC_COMPATIBLE_NRF53X) || defined(CONFIG_SOC_SERIES_NRF54LX) /* NOTE: Timer clear DPPI configuration is needed only for nRF53 * because of calls to radio_disable() and * radio_switch_complete_and_disable() inside a radio event call @@ -1402,7 +1431,7 @@ uint32_t radio_tmr_start_us(uint8_t trx, uint32_t start_us) * radio event but when the radio event is done. */ hal_sw_switch_timer_clear_ppi_config(); -#endif /* CONFIG_SOC_COMPATIBLE_NRF53X */ +#endif /* CONFIG_SOC_COMPATIBLE_NRF53X || CONFIG_SOC_SERIES_NRF54LX */ #endif /* !CONFIG_BT_CTLR_TIFS_HW */ /* start_us could be the current count in the timer */ @@ -1457,6 +1486,10 @@ void radio_tmr_stop(void) nrf_timer_task_trigger(SW_SWITCH_TIMER, NRF_TIMER_TASK_STOP); nrf_timer_task_trigger(SW_SWITCH_TIMER, NRF_TIMER_TASK_SHUTDOWN); #endif /* !CONFIG_BT_CTLR_TIFS_HW */ + +#if defined(CONFIG_SOC_SERIES_NRF54LX) + NRF_POWER->TASKS_LOWPWR = 1U; +#endif /* CONFIG_SOC_SERIES_NRF54LX */ } void radio_tmr_hcto_configure(uint32_t hcto) @@ -1881,7 +1914,9 @@ static void *radio_ccm_ext_tx_pkt_set(struct ccm *cnf, uint8_t pdu_type, void *p NRF_CCM->ENABLE = CCM_ENABLE_ENABLE_Enabled; mode = (CCM_MODE_MODE_Encryption << CCM_MODE_MODE_Pos) & CCM_MODE_MODE_Msk; -#if defined(CONFIG_SOC_COMPATIBLE_NRF52X) || defined(CONFIG_SOC_COMPATIBLE_NRF53X) +#if defined(CONFIG_SOC_COMPATIBLE_NRF52X) || \ + defined(CONFIG_SOC_COMPATIBLE_NRF53X) || \ + defined(CONFIG_SOC_SERIES_NRF54LX) /* Enable CCM support for 8-bit length field PDUs. */ mode |= (CCM_MODE_LENGTH_Extended << CCM_MODE_LENGTH_Pos) & CCM_MODE_LENGTH_Msk; diff --git a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5.h b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5.h index bdfb3c8923888..add2117923fbf 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5.h +++ b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5.h @@ -43,7 +43,9 @@ #elif defined(CONFIG_SOC_NRF5340_CPUNET) #include #include "radio_nrf5340.h" -#elif +#elif defined(CONFIG_SOC_SERIES_NRF54LX) +#include "radio_nrf54lx.h" +#else /* !CONFIG_SOC_SERIES_NRF54LX */ #error "Unsupported SoC." #endif diff --git a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf54lx.h b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf54lx.h new file mode 100644 index 0000000000000..3e08842214f33 --- /dev/null +++ b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf54lx.h @@ -0,0 +1,795 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* Use the NRF_RTC instance for coarse radio event scheduling */ +#define NRF_RTC NRF_RTC10 + +#if defined(CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER) +#error "Single Timer feature not supported yet" +#endif + +#undef EVENT_TIMER_ID +#define EVENT_TIMER_ID 10 + +#undef EVENT_TIMER +#define EVENT_TIMER _CONCAT(NRF_TIMER, EVENT_TIMER_ID) + +/* HAL abstraction of event timer prescaler value */ +#define HAL_EVENT_TIMER_PRESCALER_VALUE 5U + +/* NRF Radio HW timing constants + * - provided in US and NS (for higher granularity) + * - based on empirical measurements and sniffer logs + */ + +/* TXEN->TXIDLE + TXIDLE->TX (with fast Radio ramp-up mode) + * in microseconds for LE 1M PHY. + */ +#define HAL_RADIO_NRF54LX_TXEN_TXIDLE_TX_1M_FAST_NS 40900 /*40.1 + 0.8*/ +#define HAL_RADIO_NRF54LX_TXEN_TXIDLE_TX_1M_FAST_US \ + HAL_RADIO_NS2US_ROUND(HAL_RADIO_NRF54LX_TXEN_TXIDLE_TX_1M_FAST_NS) + +/* TXEN->TXIDLE + TXIDLE->TX (with default Radio ramp-up mode) + * in microseconds for LE 1M PHY. + */ +#define HAL_RADIO_NRF54LX_TXEN_TXIDLE_TX_1M_DEFAULT_NS 140900 /*140.1 + 0.8*/ +#define HAL_RADIO_NRF54LX_TXEN_TXIDLE_TX_1M_DEFAULT_US \ + HAL_RADIO_NS2US_ROUND(HAL_RADIO_NRF54LX_TXEN_TXIDLE_TX_1M_DEFAULT_NS) + +/* TXEN->TXIDLE + TXIDLE->TX (with default Radio ramp-up mode + * and no HW TIFS auto-switch) in microseconds for LE 1M PHY. + */ + /* 129.5 + 0.8 */ +#define HAL_RADIO_NRF54LX_TXEN_TXIDLE_TX_1M_DEFAULT_NO_HW_TIFS_NS 130300 +#define HAL_RADIO_NRF54LX_TXEN_TXIDLE_TX_1M_DEFAULT_NO_HW_TIFS_US \ + HAL_RADIO_NS2US_ROUND( \ + HAL_RADIO_NRF54LX_TXEN_TXIDLE_TX_1M_DEFAULT_NO_HW_TIFS_NS) + +/* TXEN->TXIDLE + TXIDLE->TX (with fast Radio ramp-up mode) + * in microseconds for LE 2M PHY. + */ +#define HAL_RADIO_NRF54LX_TXEN_TXIDLE_TX_2M_FAST_NS 40000 /* 40.1 - 0.1 */ +#define HAL_RADIO_NRF54LX_TXEN_TXIDLE_TX_2M_FAST_US \ + HAL_RADIO_NS2US_ROUND(HAL_RADIO_NRF54LX_TXEN_TXIDLE_TX_2M_FAST_NS) + +/* TXEN->TXIDLE + TXIDLE->TX (with default Radio ramp-up mode) + * in microseconds for LE 2M PHY. + */ +#define HAL_RADIO_NRF54LX_TXEN_TXIDLE_TX_2M_DEFAULT_NS 144900 /* 145 - 0.1 */ +#define HAL_RADIO_NRF54LX_TXEN_TXIDLE_TX_2M_DEFAULT_US \ + HAL_RADIO_NS2US_ROUND(HAL_RADIO_NRF54LX_TXEN_TXIDLE_TX_2M_DEFAULT_NS) + +/* TXEN->TXIDLE + TXIDLE->TX (with default Radio ramp-up mode and + * no HW TIFS auto-switch) in microseconds for LE 2M PHY. + */ +/* 129.5 - 0.1 */ +#define HAL_RADIO_NRF54LX_TXEN_TXIDLE_TX_2M_DEFAULT_NO_HW_TIFS_NS 129400 +#define HAL_RADIO_NRF54LX_TXEN_TXIDLE_TX_2M_DEFAULT_NO_HW_TIFS_US \ + HAL_RADIO_NS2US_ROUND( \ + HAL_RADIO_NRF54LX_TXEN_TXIDLE_TX_2M_DEFAULT_NO_HW_TIFS_NS) + +/* TXEN->TXIDLE + TXIDLE->TX (with fast Radio ramp-up mode) + * in microseconds for LE CODED PHY [S2]. + */ +#define HAL_RADIO_NRF54LX_TXEN_TXIDLE_TX_S2_FAST_NS 42300 /* 40.1 + 2.2 */ +#define HAL_RADIO_NRF54LX_TXEN_TXIDLE_TX_S2_FAST_US \ + HAL_RADIO_NS2US_ROUND(HAL_RADIO_NRF54LX_TXEN_TXIDLE_TX_S2_FAST_NS) + +/* TXEN->TXIDLE + TXIDLE->TX (with default Radio ramp-up mode) + * in microseconds for LE 2M PHY [S2]. + */ +#define HAL_RADIO_NRF54LX_TXEN_TXIDLE_TX_S2_DEFAULT_NS 132200 /* 130 + 2.2 */ +#define HAL_RADIO_NRF54LX_TXEN_TXIDLE_TX_S2_DEFAULT_US \ + HAL_RADIO_NS2US_ROUND(HAL_RADIO_NRF54LX_TXEN_TXIDLE_TX_S2_DEFAULT_NS) + +/* TXEN->TXIDLE + TXIDLE->TX (with default Radio ramp-up mode and + * no HW TIFS auto-switch) in microseconds for LE 2M PHY [S2]. + */ +/* 129.5 + 2.2 */ +#define HAL_RADIO_NRF54LX_TXEN_TXIDLE_TX_S2_DEFAULT_NO_HW_TIFS_NS 131700 +#define HAL_RADIO_NRF54LX_TXEN_TXIDLE_TX_S2_DEFAULT_NO_HW_TIFS_US \ + HAL_RADIO_NS2US_ROUND( \ + HAL_RADIO_NRF54LX_TXEN_TXIDLE_TX_S2_DEFAULT_NO_HW_TIFS_NS) + +/* TXEN->TXIDLE + TXIDLE->TX (with fast Radio ramp-up mode) + * in microseconds for LE CODED PHY [S8]. + */ +#define HAL_RADIO_NRF54LX_TXEN_TXIDLE_TX_S8_FAST_NS 42300 /* 40.1 + 2.2 */ +#define HAL_RADIO_NRF54LX_TXEN_TXIDLE_TX_S8_FAST_US \ + HAL_RADIO_NS2US_ROUND(HAL_RADIO_NRF54LX_TXEN_TXIDLE_TX_S8_FAST_NS) +/* TXEN->TXIDLE + TXIDLE->TX (with default Radio ramp-up mode) + * in microseconds for LE 2M PHY [S8]. + */ +#define HAL_RADIO_NRF54LX_TXEN_TXIDLE_TX_S8_DEFAULT_NS 121800 /*119.6 + 2.2*/ +#define HAL_RADIO_NRF54LX_TXEN_TXIDLE_TX_S8_DEFAULT_US \ + HAL_RADIO_NS2US_ROUND(HAL_RADIO_NRF54LX_TXEN_TXIDLE_TX_S8_DEFAULT_NS) + +/* TXEN->TXIDLE + TXIDLE->TX (with default Radio ramp-up mode and + * no HW TIFS auto-switch) in microseconds for LE 2M PHY [S8]. + */ + /* 129.5 + 2.2 */ +#define HAL_RADIO_NRF54LX_TXEN_TXIDLE_TX_S8_DEFAULT_NO_HW_TIFS_NS 131700 +#define HAL_RADIO_NRF54LX_TXEN_TXIDLE_TX_S8_DEFAULT_NO_HW_TIFS_US \ + HAL_RADIO_NS2US_ROUND( \ + HAL_RADIO_NRF54LX_TXEN_TXIDLE_TX_S8_DEFAULT_NO_HW_TIFS_NS) + +/* RXEN->RXIDLE + RXIDLE->RX (with fast Radio ramp-up mode) + * in microseconds for LE 1M PHY. + */ +#define HAL_RADIO_NRF54LX_RXEN_RXIDLE_RX_1M_FAST_NS 40300 /* 40.1 + 0.2 */ +#define HAL_RADIO_NRF54LX_RXEN_RXIDLE_RX_1M_FAST_US \ + HAL_RADIO_NS2US_CEIL(HAL_RADIO_NRF54LX_RXEN_RXIDLE_RX_1M_FAST_NS) + +/* RXEN->RXIDLE + RXIDLE->RX (with default Radio ramp-up mode) + * in microseconds for LE 1M PHY. + */ +#define HAL_RADIO_NRF54LX_RXEN_RXIDLE_RX_1M_DEFAULT_NS 140300 /*140.1 + 0.2*/ +#define HAL_RADIO_NRF54LX_RXEN_RXIDLE_RX_1M_DEFAULT_US \ + HAL_RADIO_NS2US_CEIL(HAL_RADIO_NRF54LX_RXEN_RXIDLE_RX_1M_DEFAULT_NS) + +/* RXEN->RXIDLE + RXIDLE->RX (with default Radio ramp-up mode and + * no HW TIFS auto-switch) in microseconds for LE 1M PHY. + */ +/* 129.5 + 0.2 */ +#define HAL_RADIO_NRF54LX_RXEN_RXIDLE_RX_1M_DEFAULT_NO_HW_TIFS_NS 129700 +#define HAL_RADIO_NRF54LX_RXEN_RXIDLE_RX_1M_DEFAULT_NO_HW_TIFS_US \ + HAL_RADIO_NS2US_CEIL( \ + HAL_RADIO_NRF54LX_RXEN_RXIDLE_RX_1M_DEFAULT_NO_HW_TIFS_NS) + +/* RXEN->RXIDLE + RXIDLE->RX (with fast Radio ramp-up mode) + * in microseconds for LE 2M PHY. + */ +#define HAL_RADIO_NRF54LX_RXEN_RXIDLE_RX_2M_FAST_NS 40300 /* 40.1 + 0.2 */ +#define HAL_RADIO_NRF54LX_RXEN_RXIDLE_RX_2M_FAST_US \ + HAL_RADIO_NS2US_CEIL(HAL_RADIO_NRF54LX_RXEN_RXIDLE_RX_2M_FAST_NS) + +/* RXEN->RXIDLE + RXIDLE->RX (with default Radio ramp-up mode) + * in microseconds for LE 2M PHY. + */ +#define HAL_RADIO_NRF54LX_RXEN_RXIDLE_RX_2M_DEFAULT_NS 144800 /*144.6 + 0.2*/ +#define HAL_RADIO_NRF54LX_RXEN_RXIDLE_RX_2M_DEFAULT_US \ + HAL_RADIO_NS2US_CEIL(HAL_RADIO_NRF54LX_RXEN_RXIDLE_RX_2M_DEFAULT_NS) + +/* RXEN->RXIDLE + RXIDLE->RX (with default Radio ramp-up mode and + * no HW TIFS auto-switch) in microseconds for LE 2M PHY. + */ +/* 129.5 + 0.2 */ +#define HAL_RADIO_NRF54LX_RXEN_RXIDLE_RX_2M_DEFAULT_NO_HW_TIFS_NS 129700 +#define HAL_RADIO_NRF54LX_RXEN_RXIDLE_RX_2M_DEFAULT_NO_HW_TIFS_US \ + HAL_RADIO_NS2US_CEIL( \ + HAL_RADIO_NRF54LX_RXEN_RXIDLE_RX_2M_DEFAULT_NO_HW_TIFS_NS) + +/* RXEN->RXIDLE + RXIDLE->RX (with fast Radio ramp-up mode) + * in microseconds for LE Coded PHY [S2]. + */ +#define HAL_RADIO_NRF54LX_RXEN_RXIDLE_RX_S2_FAST_NS 40300 /* 40.1 + 0.2 */ +#define HAL_RADIO_NRF54LX_RXEN_RXIDLE_RX_S2_FAST_US \ + HAL_RADIO_NS2US_CEIL(HAL_RADIO_NRF54LX_RXEN_RXIDLE_RX_S2_FAST_NS) + +/* RXEN->RXIDLE + RXIDLE->RX (with default Radio ramp-up mode) + * in microseconds for LE Coded PHY [S2]. + */ +#define HAL_RADIO_NRF54LX_RXEN_RXIDLE_RX_S2_DEFAULT_NS 130200 /* 130 + 0.2 */ +#define HAL_RADIO_NRF54LX_RXEN_RXIDLE_RX_S2_DEFAULT_US \ + HAL_RADIO_NS2US_CEIL(HAL_RADIO_NRF54LX_RXEN_RXIDLE_RX_S2_DEFAULT_NS) + +/* RXEN->RXIDLE + RXIDLE->RX (with default Radio ramp-up mode + * and no HW TIFS auto-switch) in microseconds for LE Coded PHY [S2]. + */ +/* 129.5 + 0.2 */ +#define HAL_RADIO_NRF54LX_RXEN_RXIDLE_RX_S2_DEFAULT_NO_HW_TIFS_NS 129700 +#define HAL_RADIO_NRF54LX_RXEN_RXIDLE_RX_S2_DEFAULT_NO_HW_TIFS_US \ + HAL_RADIO_NS2US_CEIL( \ + HAL_RADIO_NRF54LX_RXEN_RXIDLE_RX_S2_DEFAULT_NO_HW_TIFS_NS) + +/* RXEN->RXIDLE + RXIDLE->RX (with fast Radio ramp-up mode) + * in microseconds for LE Coded PHY [S8]. + */ +#define HAL_RADIO_NRF54LX_RXEN_RXIDLE_RX_S8_FAST_NS 40300 /* 40.1 + 0.2 */ +#define HAL_RADIO_NRF54LX_RXEN_RXIDLE_RX_S8_FAST_US \ + HAL_RADIO_NS2US_CEIL(HAL_RADIO_NRF54LX_RXEN_RXIDLE_RX_S8_FAST_NS) + +/* RXEN->RXIDLE + RXIDLE->RX (with default Radio ramp-up mode) + * in microseconds for LE Coded PHY [S8]. + */ +#define HAL_RADIO_NRF54LX_RXEN_RXIDLE_RX_S8_DEFAULT_NS 120200 /* 120.0 + 0.2 */ +#define HAL_RADIO_NRF54LX_RXEN_RXIDLE_RX_S8_DEFAULT_US \ + HAL_RADIO_NS2US_CEIL(HAL_RADIO_NRF54LX_RXEN_RXIDLE_RX_S8_DEFAULT_NS) + +/* RXEN->RXIDLE + RXIDLE->RX (with default Radio ramp-up mode and + * no HW TIFS auto-switch) in microseconds for LE Coded PHY [S8]. + */ +/* 129.5 + 0.2 */ +#define HAL_RADIO_NRF54LX_RXEN_RXIDLE_RX_S8_DEFAULT_NO_HW_TIFS_NS 129700 +#define HAL_RADIO_NRF54LX_RXEN_RXIDLE_RX_S8_DEFAULT_NO_HW_TIFS_US \ + HAL_RADIO_NS2US_CEIL( \ + HAL_RADIO_NRF54LX_RXEN_RXIDLE_RX_S8_DEFAULT_NO_HW_TIFS_NS) + +#define HAL_RADIO_NRF54LX_TX_CHAIN_DELAY_1M_US 1 /* ceil(0.6) */ +#define HAL_RADIO_NRF54LX_TX_CHAIN_DELAY_1M_NS 600 /* 0.6 */ +#define HAL_RADIO_NRF54LX_TX_CHAIN_DELAY_2M_US 1 /* ceil(0.6) */ +#define HAL_RADIO_NRF54LX_TX_CHAIN_DELAY_2M_NS 600 /* 0.6 */ +#define HAL_RADIO_NRF54LX_TX_CHAIN_DELAY_S2_US 1 /* ceil(0.6) */ +#define HAL_RADIO_NRF54LX_TX_CHAIN_DELAY_S2_NS 600 /* 0.6 */ +#define HAL_RADIO_NRF54LX_TX_CHAIN_DELAY_S8_US 1 /* ceil(0.6) */ +#define HAL_RADIO_NRF54LX_TX_CHAIN_DELAY_S8_NS 600 /* 0.6 */ + +#define HAL_RADIO_NRF54LX_RX_CHAIN_DELAY_1M_US 10 /* ceil(9.4) */ +#define HAL_RADIO_NRF54LX_RX_CHAIN_DELAY_1M_NS 9400 /* 9.4 */ +#define HAL_RADIO_NRF54LX_RX_CHAIN_DELAY_2M_US 5 /* ceil(5.0) */ +#define HAL_RADIO_NRF54LX_RX_CHAIN_DELAY_2M_NS 5000 /* 5.0 */ +#define HAL_RADIO_NRF54LX_RX_CHAIN_DELAY_S2_US 25 /* ceil(19.6) */ +#define HAL_RADIO_NRF54LX_RX_CHAIN_DELAY_S2_NS 24600 /* 19.6 */ +#define HAL_RADIO_NRF54LX_RX_CHAIN_DELAY_S8_US 30 /* ceil(29.6) */ +#define HAL_RADIO_NRF54LX_RX_CHAIN_DELAY_S8_NS 29600 /* 29.6 */ + +#if defined(CONFIG_BT_CTLR_RADIO_ENABLE_FAST) +#define HAL_RADIO_NRF54LX_TXEN_TXIDLE_TX_1M_US \ + HAL_RADIO_NRF54LX_TXEN_TXIDLE_TX_1M_FAST_US +#define HAL_RADIO_NRF54LX_TXEN_TXIDLE_TX_1M_NS \ + HAL_RADIO_NRF54LX_TXEN_TXIDLE_TX_1M_FAST_NS + +#define HAL_RADIO_NRF54LX_TXEN_TXIDLE_TX_2M_US \ + HAL_RADIO_NRF54LX_TXEN_TXIDLE_TX_2M_FAST_US +#define HAL_RADIO_NRF54LX_TXEN_TXIDLE_TX_2M_NS \ + HAL_RADIO_NRF54LX_TXEN_TXIDLE_TX_2M_FAST_NS + +#define HAL_RADIO_NRF54LX_TXEN_TXIDLE_TX_S2_US \ + HAL_RADIO_NRF54LX_TXEN_TXIDLE_TX_S2_FAST_US +#define HAL_RADIO_NRF54LX_TXEN_TXIDLE_TX_S2_NS \ + HAL_RADIO_NRF54LX_TXEN_TXIDLE_TX_S2_FAST_NS + +#define HAL_RADIO_NRF54LX_TXEN_TXIDLE_TX_S8_US \ + HAL_RADIO_NRF54LX_TXEN_TXIDLE_TX_S8_FAST_US +#define HAL_RADIO_NRF54LX_TXEN_TXIDLE_TX_S8_NS \ + HAL_RADIO_NRF54LX_TXEN_TXIDLE_TX_S8_FAST_NS + +#define HAL_RADIO_NRF54LX_RXEN_RXIDLE_RX_1M_US \ + HAL_RADIO_NRF54LX_RXEN_RXIDLE_RX_1M_FAST_US +#define HAL_RADIO_NRF54LX_RXEN_RXIDLE_RX_1M_NS \ + HAL_RADIO_NRF54LX_RXEN_RXIDLE_RX_1M_FAST_NS + +#define HAL_RADIO_NRF54LX_RXEN_RXIDLE_RX_2M_US \ + HAL_RADIO_NRF54LX_RXEN_RXIDLE_RX_2M_FAST_US +#define HAL_RADIO_NRF54LX_RXEN_RXIDLE_RX_2M_NS \ + HAL_RADIO_NRF54LX_RXEN_RXIDLE_RX_2M_FAST_NS + +#define HAL_RADIO_NRF54LX_RXEN_RXIDLE_RX_S2_US \ + HAL_RADIO_NRF54LX_RXEN_RXIDLE_RX_S2_FAST_US +#define HAL_RADIO_NRF54LX_RXEN_RXIDLE_RX_S2_NS \ + HAL_RADIO_NRF54LX_RXEN_RXIDLE_RX_S2_FAST_NS + +#define HAL_RADIO_NRF54LX_RXEN_RXIDLE_RX_S8_US \ + HAL_RADIO_NRF54LX_RXEN_RXIDLE_RX_S8_FAST_US +#define HAL_RADIO_NRF54LX_RXEN_RXIDLE_RX_S8_NS \ + HAL_RADIO_NRF54LX_RXEN_RXIDLE_RX_S8_FAST_NS + +#else /* !CONFIG_BT_CTLR_RADIO_ENABLE_FAST */ +#if defined(CONFIG_BT_CTLR_TIFS_HW) +#define HAL_RADIO_NRF54LX_TXEN_TXIDLE_TX_1M_US \ + HAL_RADIO_NRF54LX_TXEN_TXIDLE_TX_1M_DEFAULT_US +#define HAL_RADIO_NRF54LX_TXEN_TXIDLE_TX_1M_NS \ + HAL_RADIO_NRF54LX_TXEN_TXIDLE_TX_1M_DEFAULT_NS + +#define HAL_RADIO_NRF54LX_TXEN_TXIDLE_TX_2M_US \ + HAL_RADIO_NRF54LX_TXEN_TXIDLE_TX_2M_DEFAULT_US +#define HAL_RADIO_NRF54LX_TXEN_TXIDLE_TX_2M_NS \ + HAL_RADIO_NRF54LX_TXEN_TXIDLE_TX_2M_DEFAULT_NS + +#define HAL_RADIO_NRF54LX_TXEN_TXIDLE_TX_S2_US \ + HAL_RADIO_NRF54LX_TXEN_TXIDLE_TX_S2_DEFAULT_US +#define HAL_RADIO_NRF54LX_TXEN_TXIDLE_TX_S2_NS \ + HAL_RADIO_NRF54LX_TXEN_TXIDLE_TX_S2_DEFAULT_NS + +#define HAL_RADIO_NRF54LX_TXEN_TXIDLE_TX_S8_US \ + HAL_RADIO_NRF54LX_TXEN_TXIDLE_TX_S8_DEFAULT_US +#define HAL_RADIO_NRF54LX_TXEN_TXIDLE_TX_S8_NS \ + HAL_RADIO_NRF54LX_TXEN_TXIDLE_TX_S8_DEFAULT_NS + +#define HAL_RADIO_NRF54LX_RXEN_RXIDLE_RX_1M_US \ + HAL_RADIO_NRF54LX_RXEN_RXIDLE_RX_1M_DEFAULT_US +#define HAL_RADIO_NRF54LX_RXEN_RXIDLE_RX_1M_NS \ + HAL_RADIO_NRF54LX_RXEN_RXIDLE_RX_1M_DEFAULT_NS + +#define HAL_RADIO_NRF54LX_RXEN_RXIDLE_RX_2M_US \ + HAL_RADIO_NRF54LX_RXEN_RXIDLE_RX_2M_DEFAULT_US +#define HAL_RADIO_NRF54LX_RXEN_RXIDLE_RX_2M_NS \ + HAL_RADIO_NRF54LX_RXEN_RXIDLE_RX_2M_DEFAULT_NS + +#define HAL_RADIO_NRF54LX_RXEN_RXIDLE_RX_S2_US \ + HAL_RADIO_NRF54LX_RXEN_RXIDLE_RX_S2_DEFAULT_US +#define HAL_RADIO_NRF54LX_RXEN_RXIDLE_RX_S2_NS \ + HAL_RADIO_NRF54LX_RXEN_RXIDLE_RX_S2_DEFAULT_NS + +#define HAL_RADIO_NRF54LX_RXEN_RXIDLE_RX_S8_US \ + HAL_RADIO_NRF54LX_RXEN_RXIDLE_RX_S8_DEFAULT_US +#define HAL_RADIO_NRF54LX_RXEN_RXIDLE_RX_S8_NS \ + HAL_RADIO_NRF54LX_RXEN_RXIDLE_RX_S8_DEFAULT_NS + +#else /* !CONFIG_BT_CTLR_TIFS_HW */ +#define HAL_RADIO_NRF54LX_TXEN_TXIDLE_TX_1M_US \ + HAL_RADIO_NRF54LX_TXEN_TXIDLE_TX_1M_DEFAULT_NO_HW_TIFS_US +#define HAL_RADIO_NRF54LX_TXEN_TXIDLE_TX_1M_NS \ + HAL_RADIO_NRF54LX_TXEN_TXIDLE_TX_1M_DEFAULT_NO_HW_TIFS_NS + +#define HAL_RADIO_NRF54LX_TXEN_TXIDLE_TX_2M_US \ + HAL_RADIO_NRF54LX_TXEN_TXIDLE_TX_2M_DEFAULT_NO_HW_TIFS_US +#define HAL_RADIO_NRF54LX_TXEN_TXIDLE_TX_2M_NS \ + HAL_RADIO_NRF54LX_TXEN_TXIDLE_TX_2M_DEFAULT_NO_HW_TIFS_NS + +#define HAL_RADIO_NRF54LX_TXEN_TXIDLE_TX_S2_US \ + HAL_RADIO_NRF54LX_TXEN_TXIDLE_TX_S2_DEFAULT_NO_HW_TIFS_US +#define HAL_RADIO_NRF54LX_TXEN_TXIDLE_TX_S2_NS \ + HAL_RADIO_NRF54LX_TXEN_TXIDLE_TX_S2_DEFAULT_NO_HW_TIFS_NS + +#define HAL_RADIO_NRF54LX_TXEN_TXIDLE_TX_S8_US \ + HAL_RADIO_NRF54LX_TXEN_TXIDLE_TX_S8_DEFAULT_NO_HW_TIFS_US +#define HAL_RADIO_NRF54LX_TXEN_TXIDLE_TX_S8_NS \ + HAL_RADIO_NRF54LX_TXEN_TXIDLE_TX_S8_DEFAULT_NO_HW_TIFS_NS + +#define HAL_RADIO_NRF54LX_RXEN_RXIDLE_RX_1M_US \ + HAL_RADIO_NRF54LX_RXEN_RXIDLE_RX_1M_DEFAULT_NO_HW_TIFS_US +#define HAL_RADIO_NRF54LX_RXEN_RXIDLE_RX_1M_NS \ + HAL_RADIO_NRF54LX_RXEN_RXIDLE_RX_1M_DEFAULT_NO_HW_TIFS_NS + +#define HAL_RADIO_NRF54LX_RXEN_RXIDLE_RX_2M_US \ + HAL_RADIO_NRF54LX_RXEN_RXIDLE_RX_2M_DEFAULT_NO_HW_TIFS_US +#define HAL_RADIO_NRF54LX_RXEN_RXIDLE_RX_2M_NS \ + HAL_RADIO_NRF54LX_RXEN_RXIDLE_RX_2M_DEFAULT_NO_HW_TIFS_NS + +#define HAL_RADIO_NRF54LX_RXEN_RXIDLE_RX_S2_US \ + HAL_RADIO_NRF54LX_RXEN_RXIDLE_RX_S2_DEFAULT_NO_HW_TIFS_US +#define HAL_RADIO_NRF54LX_RXEN_RXIDLE_RX_S2_NS \ + HAL_RADIO_NRF54LX_RXEN_RXIDLE_RX_S2_DEFAULT_NO_HW_TIFS_NS + +#define HAL_RADIO_NRF54LX_RXEN_RXIDLE_RX_S8_US \ + HAL_RADIO_NRF54LX_RXEN_RXIDLE_RX_S8_DEFAULT_NO_HW_TIFS_US +#define HAL_RADIO_NRF54LX_RXEN_RXIDLE_RX_S8_NS \ + HAL_RADIO_NRF54LX_RXEN_RXIDLE_RX_S8_DEFAULT_NO_HW_TIFS_NS +#endif /* !CONFIG_BT_CTLR_TIFS_HW */ +#endif /* !CONFIG_BT_CTLR_RADIO_ENABLE_FAST */ + +/* HAL abstraction of Radio bitfields */ +#define HAL_RADIO_INTENSET_DISABLED_Msk RADIO_INTENSET00_DISABLED_Msk +#define HAL_RADIO_SHORTS_TRX_END_DISABLE_Msk RADIO_SHORTS_PHYEND_DISABLE_Msk +#define HAL_RADIO_SHORTS_TRX_PHYEND_DISABLE_Msk RADIO_SHORTS_PHYEND_DISABLE_Msk + +/* HAL abstraction of Radio IRQ number */ +#define HAL_RADIO_IRQn RADIO_0_IRQn + +/* SoC specific NRF_RADIO power-on reset value. Refer to Product Specification, + * RADIO Registers section for the documented reset values. + * + * NOTE: Only implementation used values defined here. + * In the future if MDK or nRFx header include these, use them instead. + */ +#define HAL_RADIO_RESET_VALUE_DFEMODE 0x00000000UL +#define HAL_RADIO_RESET_VALUE_CTEINLINECONF 0x00002800UL + +static inline void hal_radio_reset(void) +{ + /* TODO: Add any required setup for each radio event + */ +} + +static inline void hal_radio_stop(void) +{ + /* TODO: Add any required cleanup of actions taken in hal_radio_reset() + */ +} + +static inline void hal_radio_ram_prio_setup(void) +{ + /* TODO */ +} + +static inline uint32_t hal_radio_phy_mode_get(uint8_t phy, uint8_t flags) +{ + uint32_t mode; + + switch (phy) { + case BIT(0): + default: + mode = RADIO_MODE_MODE_Ble_1Mbit; + break; + + case BIT(1): + mode = RADIO_MODE_MODE_Ble_2Mbit; + break; + +#if defined(CONFIG_BT_CTLR_PHY_CODED) + case BIT(2): + if (flags & 0x01) { + mode = RADIO_MODE_MODE_Ble_LR125Kbit; + } else { + mode = RADIO_MODE_MODE_Ble_LR500Kbit; + } + break; +#endif /* CONFIG_BT_CTLR_PHY_CODED */ + } + + return mode; +} + +static inline int8_t hal_radio_tx_power_max_get(void) +{ + return 8; /* +8 dBm */ +} + +static inline int8_t hal_radio_tx_power_min_get(void) +{ + return -46; /* -46 dBm */ +} + +static inline int8_t hal_radio_tx_power_floor(int8_t tx_power_lvl) +{ + if (tx_power_lvl >= 8) { + return 8; + } + + if (tx_power_lvl >= 7) { + return 7; + } + + if (tx_power_lvl >= 6) { + return 6; + } + + if (tx_power_lvl >= 5) { + return 5; + } + + if (tx_power_lvl >= 4) { + return 4; + } + + if (tx_power_lvl >= 3) { + return 3; + } + + if (tx_power_lvl >= 2) { + return 2; + } + + if (tx_power_lvl >= 1) { + return 1; + } + + if (tx_power_lvl >= 0) { + return 0; + } + + if (tx_power_lvl >= -1) { + return -1; + } + + if (tx_power_lvl >= -2) { + return -2; + } + + if (tx_power_lvl >= -3) { + return -3; + } + + if (tx_power_lvl >= -4) { + return -4; + } + + if (tx_power_lvl >= -5) { + return -5; + } + + if (tx_power_lvl >= -6) { + return -6; + } + + if (tx_power_lvl >= -7) { + return -7; + } + + if (tx_power_lvl >= -8) { + return -8; + } + + if (tx_power_lvl >= -9) { + return -9; + } + + if (tx_power_lvl >= -10) { + return -10; + } + + if (tx_power_lvl >= -12) { + return -12; + } + + if (tx_power_lvl >= -14) { + return -14; + } + + if (tx_power_lvl >= -16) { + return -16; + } + + if (tx_power_lvl >= -20) { + return -20; + } + + if (tx_power_lvl >= -26) { + return -26; + } + + if (tx_power_lvl >= -40) { + return -40; + } + + return -46; +} + +static inline uint32_t hal_radio_tx_power_value(int8_t tx_power_lvl) +{ + if (tx_power_lvl >= 8) { + return RADIO_TXPOWER_TXPOWER_Pos8dBm; + } + + if (tx_power_lvl >= 7) { + return RADIO_TXPOWER_TXPOWER_Pos7dBm; + } + + if (tx_power_lvl >= 6) { + return RADIO_TXPOWER_TXPOWER_Pos6dBm; + } + + if (tx_power_lvl >= 5) { + return RADIO_TXPOWER_TXPOWER_Pos5dBm; + } + + if (tx_power_lvl >= 4) { + return RADIO_TXPOWER_TXPOWER_Pos4dBm; + } + + if (tx_power_lvl >= 3) { + return RADIO_TXPOWER_TXPOWER_Pos3dBm; + } + + if (tx_power_lvl >= 2) { + return RADIO_TXPOWER_TXPOWER_Pos2dBm; + } + + if (tx_power_lvl >= 1) { + return RADIO_TXPOWER_TXPOWER_Pos1dBm; + } + + if (tx_power_lvl >= 0) { + return RADIO_TXPOWER_TXPOWER_0dBm; + } + + if (tx_power_lvl >= -1) { + return RADIO_TXPOWER_TXPOWER_Neg1dBm; + } + + if (tx_power_lvl >= -2) { + return RADIO_TXPOWER_TXPOWER_Neg2dBm; + } + + if (tx_power_lvl >= -3) { + return RADIO_TXPOWER_TXPOWER_Neg3dBm; + } + + if (tx_power_lvl >= -4) { + return RADIO_TXPOWER_TXPOWER_Neg4dBm; + } + + if (tx_power_lvl >= -5) { + return RADIO_TXPOWER_TXPOWER_Neg5dBm; + } + + if (tx_power_lvl >= -6) { + return RADIO_TXPOWER_TXPOWER_Neg6dBm; + } + + if (tx_power_lvl >= -7) { + return RADIO_TXPOWER_TXPOWER_Neg7dBm; + } + + if (tx_power_lvl >= -8) { + return RADIO_TXPOWER_TXPOWER_Neg8dBm; + } + + if (tx_power_lvl >= -9) { + return RADIO_TXPOWER_TXPOWER_Neg9dBm; + } + + if (tx_power_lvl >= -10) { + return RADIO_TXPOWER_TXPOWER_Neg10dBm; + } + + if (tx_power_lvl >= -12) { + return RADIO_TXPOWER_TXPOWER_Neg12dBm; + } + + if (tx_power_lvl >= -14) { + return RADIO_TXPOWER_TXPOWER_Neg14dBm; + } + + if (tx_power_lvl >= -16) { + return RADIO_TXPOWER_TXPOWER_Neg16dBm; + } + + if (tx_power_lvl >= -20) { + return RADIO_TXPOWER_TXPOWER_Neg20dBm; + } + + if (tx_power_lvl >= -26) { + return RADIO_TXPOWER_TXPOWER_Neg26dBm; + } + + if (tx_power_lvl >= -40) { + return RADIO_TXPOWER_TXPOWER_Neg40dBm; + } + + return RADIO_TXPOWER_TXPOWER_Neg46dBm; +} + +static inline uint32_t hal_radio_tx_ready_delay_us_get(uint8_t phy, uint8_t flags) +{ + switch (phy) { + default: + case BIT(0): + return HAL_RADIO_NRF54LX_TXEN_TXIDLE_TX_1M_US; + case BIT(1): + return HAL_RADIO_NRF54LX_TXEN_TXIDLE_TX_2M_US; + +#if defined(CONFIG_BT_CTLR_PHY_CODED) + case BIT(2): + if (flags & 0x01) { + return HAL_RADIO_NRF54LX_TXEN_TXIDLE_TX_S8_US; + } else { + return HAL_RADIO_NRF54LX_TXEN_TXIDLE_TX_S2_US; + } +#endif /* CONFIG_BT_CTLR_PHY_CODED */ + } +} + +static inline uint32_t hal_radio_rx_ready_delay_us_get(uint8_t phy, uint8_t flags) +{ + switch (phy) { + default: + case BIT(0): + return HAL_RADIO_NRF54LX_RXEN_RXIDLE_RX_1M_US; + case BIT(1): + return HAL_RADIO_NRF54LX_RXEN_RXIDLE_RX_2M_US; + +#if defined(CONFIG_BT_CTLR_PHY_CODED) + case BIT(2): + if (flags & 0x01) { + return HAL_RADIO_NRF54LX_RXEN_RXIDLE_RX_S8_US; + } else { + return HAL_RADIO_NRF54LX_RXEN_RXIDLE_RX_S2_US; + } +#endif /* CONFIG_BT_CTLR_PHY_CODED */ + } +} + +static inline uint32_t hal_radio_tx_chain_delay_us_get(uint8_t phy, uint8_t flags) +{ + switch (phy) { + default: + case BIT(0): + return HAL_RADIO_NRF54LX_TX_CHAIN_DELAY_1M_US; + case BIT(1): + return HAL_RADIO_NRF54LX_TX_CHAIN_DELAY_2M_US; + +#if defined(CONFIG_BT_CTLR_PHY_CODED) + case BIT(2): + if (flags & 0x01) { + return HAL_RADIO_NRF54LX_TX_CHAIN_DELAY_S8_US; + } else { + return HAL_RADIO_NRF54LX_TX_CHAIN_DELAY_S2_US; + } +#endif /* CONFIG_BT_CTLR_PHY_CODED */ + } +} + +static inline uint32_t hal_radio_rx_chain_delay_us_get(uint8_t phy, uint8_t flags) +{ + switch (phy) { + default: + case BIT(0): + return HAL_RADIO_NRF54LX_RX_CHAIN_DELAY_1M_US; + case BIT(1): + return HAL_RADIO_NRF54LX_RX_CHAIN_DELAY_2M_US; + +#if defined(CONFIG_BT_CTLR_PHY_CODED) + case BIT(2): + if (flags & 0x01) { + return HAL_RADIO_NRF54LX_RX_CHAIN_DELAY_S8_US; + } else { + return HAL_RADIO_NRF54LX_RX_CHAIN_DELAY_S2_US; + } +#endif /* CONFIG_BT_CTLR_PHY_CODED */ + } +} + +static inline uint32_t hal_radio_tx_ready_delay_ns_get(uint8_t phy, uint8_t flags) +{ + switch (phy) { + default: + case BIT(0): + return HAL_RADIO_NRF54LX_TXEN_TXIDLE_TX_1M_NS; + case BIT(1): + return HAL_RADIO_NRF54LX_TXEN_TXIDLE_TX_2M_NS; + +#if defined(CONFIG_BT_CTLR_PHY_CODED) + case BIT(2): + if (flags & 0x01) { + return HAL_RADIO_NRF54LX_TXEN_TXIDLE_TX_S8_NS; + } else { + return HAL_RADIO_NRF54LX_TXEN_TXIDLE_TX_S2_NS; + } +#endif /* CONFIG_BT_CTLR_PHY_CODED */ + } +} + +static inline uint32_t hal_radio_rx_ready_delay_ns_get(uint8_t phy, uint8_t flags) +{ + switch (phy) { + default: + case BIT(0): + return HAL_RADIO_NRF54LX_RXEN_RXIDLE_RX_1M_NS; + case BIT(1): + return HAL_RADIO_NRF54LX_RXEN_RXIDLE_RX_2M_NS; + +#if defined(CONFIG_BT_CTLR_PHY_CODED) + case BIT(2): + if (flags & 0x01) { + return HAL_RADIO_NRF54LX_RXEN_RXIDLE_RX_S8_NS; + } else { + return HAL_RADIO_NRF54LX_RXEN_RXIDLE_RX_S2_NS; + } +#endif /* CONFIG_BT_CTLR_PHY_CODED */ + } +} + +static inline uint32_t hal_radio_tx_chain_delay_ns_get(uint8_t phy, uint8_t flags) +{ + switch (phy) { + default: + case BIT(0): + return HAL_RADIO_NRF54LX_TX_CHAIN_DELAY_1M_NS; + case BIT(1): + return HAL_RADIO_NRF54LX_TX_CHAIN_DELAY_2M_NS; + +#if defined(CONFIG_BT_CTLR_PHY_CODED) + case BIT(2): + if (flags & 0x01) { + return HAL_RADIO_NRF54LX_TX_CHAIN_DELAY_S8_NS; + } else { + return HAL_RADIO_NRF54LX_TX_CHAIN_DELAY_S2_NS; + } +#endif /* CONFIG_BT_CTLR_PHY_CODED */ + } +} + +static inline uint32_t hal_radio_rx_chain_delay_ns_get(uint8_t phy, uint8_t flags) +{ + switch (phy) { + default: + case BIT(0): + return HAL_RADIO_NRF54LX_RX_CHAIN_DELAY_1M_NS; + case BIT(1): + return HAL_RADIO_NRF54LX_RX_CHAIN_DELAY_2M_NS; + +#if defined(CONFIG_BT_CTLR_PHY_CODED) + case BIT(2): + if (flags & 0x01) { + return HAL_RADIO_NRF54LX_RX_CHAIN_DELAY_S8_NS; + } else { + return HAL_RADIO_NRF54LX_RX_CHAIN_DELAY_S2_NS; + } +#endif /* CONFIG_BT_CTLR_PHY_CODED */ + } +} 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 be0844015682e..3b3fc681c9c1b 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 @@ -5,6 +5,10 @@ * SPDX-License-Identifier: Apache-2.0 */ +#if defined(CONFIG_SOC_SERIES_NRF54LX) +#define NRF_DPPIC NRF_DPPIC10 +#endif /* CONFIG_SOC_SERIES_NRF54LX */ + static inline void hal_radio_nrf_ppi_channels_enable(uint32_t mask) { nrf_dppi_channels_enable(NRF_DPPIC, mask); diff --git a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/swi.h b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/swi.h index 8f831e4554802..1759df921c751 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/swi.h +++ b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/swi.h @@ -40,7 +40,23 @@ #elif /* !CONFIG_SOC_COMPATIBLE_NRF5340_CPUNET */ #error Unknown NRF5340 CPU. #endif /* !CONFIG_SOC_COMPATIBLE_NRF5340_CPUNET */ -#endif /* CONFIG_SOC_COMPATIBLE_NRF53X */ + +/* nRF54 Series IRQ mapping */ +#elif defined(CONFIG_SOC_SERIES_NRF54LX) + +#define HAL_SWI_RADIO_IRQ SWI02_IRQn +#define HAL_SWI_WORKER_IRQ RTC10_IRQn + +#if !defined(CONFIG_BT_CTLR_LOW_LAT) && \ + (CONFIG_BT_CTLR_ULL_HIGH_PRIO == CONFIG_BT_CTLR_ULL_LOW_PRIO) +#define HAL_SWI_JOB_IRQ HAL_SWI_WORKER_IRQ +#else +#define HAL_SWI_JOB_IRQ SWI03_IRQn +#endif + +#define HAL_RTC_IRQn RTC10_IRQn + +#endif static inline void hal_swi_init(void) { From 04f2e1171ec74c7c8df75ab53b08b3ce09b81615 Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Wed, 29 May 2024 06:08:05 +0200 Subject: [PATCH 2037/2849] boards: nordic: nrf54l15pdk: Bind Bluetooth C2H and monitor uart Bind Bluetooth Controller to Host and Monitor UART. Signed-off-by: Vinayak Kariappa Chettimada --- boards/nordic/nrf54l15pdk/nrf54l15_cpuapp_common.dtsi | 2 ++ 1 file changed, 2 insertions(+) diff --git a/boards/nordic/nrf54l15pdk/nrf54l15_cpuapp_common.dtsi b/boards/nordic/nrf54l15pdk/nrf54l15_cpuapp_common.dtsi index eb93c1fee9636..2938f33f22610 100644 --- a/boards/nordic/nrf54l15pdk/nrf54l15_cpuapp_common.dtsi +++ b/boards/nordic/nrf54l15pdk/nrf54l15_cpuapp_common.dtsi @@ -14,6 +14,8 @@ zephyr,console = &uart20; zephyr,shell-uart = &uart20; zephyr,uart-mcumgr = &uart20; + zephyr,bt-mon-uart = &uart20; + zephyr,bt-c2h-uart = &uart20; zephyr,flash-controller = &rram_controller; zephyr,flash = &cpuapp_rram; zephyr,ieee802154 = &ieee802154; From 3d24a3ca8e11b5b6d042fe852b7e9e85d7526c50 Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Wed, 29 May 2024 06:25:30 +0200 Subject: [PATCH 2038/2849] samples: Bluetooth: hci_uart: Add preliminary support for nrf54l15pdk Add preliminary support for building hci_uart sample for nrf54l15pdk. Signed-off-by: Vinayak Kariappa Chettimada --- .../boards/nrf54l15pdk_nrf54l15_cpuapp.overlay | 12 ++++++++++++ samples/bluetooth/hci_uart/sample.yaml | 10 ++++++++++ 2 files changed, 22 insertions(+) create mode 100644 samples/bluetooth/hci_uart/boards/nrf54l15pdk_nrf54l15_cpuapp.overlay diff --git a/samples/bluetooth/hci_uart/boards/nrf54l15pdk_nrf54l15_cpuapp.overlay b/samples/bluetooth/hci_uart/boards/nrf54l15pdk_nrf54l15_cpuapp.overlay new file mode 100644 index 0000000000000..7ba5755c68133 --- /dev/null +++ b/samples/bluetooth/hci_uart/boards/nrf54l15pdk_nrf54l15_cpuapp.overlay @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + + &uart20 { + compatible = "nordic,nrf-uarte"; + current-speed = <1000000>; + status = "okay"; + hw-flow-control; +}; diff --git a/samples/bluetooth/hci_uart/sample.yaml b/samples/bluetooth/hci_uart/sample.yaml index 033a16c0cb143..7aa49e1eba592 100644 --- a/samples/bluetooth/hci_uart/sample.yaml +++ b/samples/bluetooth/hci_uart/sample.yaml @@ -58,3 +58,13 @@ tests: tags: - uart - bluetooth + sample.bluetooth.hci_uart.nrf54l15.all: + harness: bluetooth + platform_allow: nrf54l15pdk/nrf54l15/cpuapp + integration_platforms: + - nrf54l15pdk/nrf54l15/cpuapp + extra_args: + - OVERLAY_CONFIG=overlay-all-bt_ll_sw_split.conf + tags: + - uart + - bluetooth From 35773882c2bafc6bc699203ecafc2fcf2bf1afda Mon Sep 17 00:00:00 2001 From: Alberto Escolar Piedras Date: Wed, 29 May 2024 13:57:36 +0200 Subject: [PATCH 2039/2849] Bluetooth: Controller: Use HAL to modify renamed registers in nRF54 In some nRF54 devices, DATAWHITEIV was renamed to DATAWHITE, and the CRCCNF SKIADDR field was renamed OFFSET. The nrf HAL hid this change internally, so let's use it so we don't need to ifdef these in the Bluetooth Controller HAL code. Signed-off-by: Alberto Escolar Piedras --- .../controller/ll_sw/nordic/hal/nrf5/radio/radio.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) 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 67df20c4b2361..5878e0c6756a9 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 @@ -401,7 +401,7 @@ void radio_freq_chan_set(uint32_t chan) void radio_whiten_iv_set(uint32_t iv) { - NRF_RADIO->DATAWHITEIV = iv; + nrf_radio_datawhiteiv_set(NRF_RADIO, iv); NRF_RADIO->PCNF1 &= ~RADIO_PCNF1_WHITEEN_Msk; NRF_RADIO->PCNF1 |= ((1UL) << RADIO_PCNF1_WHITEEN_Pos) & @@ -652,12 +652,10 @@ uint32_t radio_is_idle(void) void radio_crc_configure(uint32_t polynomial, uint32_t iv) { - NRF_RADIO->CRCCNF = - (((RADIO_CRCCNF_SKIPADDR_Skip) << RADIO_CRCCNF_SKIPADDR_Pos) & - RADIO_CRCCNF_SKIPADDR_Msk) | - (((RADIO_CRCCNF_LEN_Three) << RADIO_CRCCNF_LEN_Pos) & - RADIO_CRCCNF_LEN_Msk); - NRF_RADIO->CRCPOLY = polynomial; + nrf_radio_crc_configure(NRF_RADIO, + RADIO_CRCCNF_LEN_Three, + NRF_RADIO_CRC_ADDR_SKIP, + polynomial); NRF_RADIO->CRCINIT = iv; } From a3218b0de5e8a0dab27cefc27abaca1779026910 Mon Sep 17 00:00:00 2001 From: Alberto Escolar Piedras Date: Fri, 31 May 2024 16:33:25 +0200 Subject: [PATCH 2040/2849] Bluetooth: Controller: Fix BT_CTLR_DATA_LEN_UPDATE_SUPPORT selection For the Nordic HW, the BT_CTLR_DATA_LEN_UPDATE_SUPPORT does not require CCM HW enabled, hence support Data Length Update if Encryption Support is disabled. Signed-off-by: Alberto Escolar Piedras Signed-off-by: Vinayak Kariappa Chettimada --- subsys/bluetooth/controller/Kconfig.ll_sw_split | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/subsys/bluetooth/controller/Kconfig.ll_sw_split b/subsys/bluetooth/controller/Kconfig.ll_sw_split index 09833a64fbd9f..729238a4a5e7e 100644 --- a/subsys/bluetooth/controller/Kconfig.ll_sw_split +++ b/subsys/bluetooth/controller/Kconfig.ll_sw_split @@ -24,7 +24,8 @@ config BT_LLL_VENDOR_NORDIC select BT_CTLR_CONN_PARAM_REQ_SUPPORT select BT_CTLR_EXT_REJ_IND_SUPPORT select BT_CTLR_PER_INIT_FEAT_XCHG_SUPPORT - select BT_CTLR_DATA_LEN_UPDATE_SUPPORT if HAS_HW_NRF_CCM_LFLEN_8BIT || \ + select BT_CTLR_DATA_LEN_UPDATE_SUPPORT if !BT_CTLR_LE_ENC_SUPPORT || \ + HAS_HW_NRF_CCM_LFLEN_8BIT || \ BT_CTLR_DATA_LENGTH_CLEAR select BT_CTLR_EXT_SCAN_FP_SUPPORT select BT_CTLR_PHY_2M_SUPPORT if HAS_HW_NRF_RADIO_BLE_2M || \ From 510e1ba6af989fa9b2610ed5308d11e17f393aed Mon Sep 17 00:00:00 2001 From: Alberto Escolar Piedras Date: Wed, 29 May 2024 10:26:38 +0200 Subject: [PATCH 2041/2849] Bluetooth: Controller: Treat nrf54l15bsim like a real platform Use the compatible kconfig option so that for the simulated nRF54L15 we build the same code as for the real platform. Signed-off-by: Alberto Escolar Piedras --- .../bluetooth/controller/Kconfig.ll_sw_split | 2 +- .../controller/ll_sw/nordic/hal/nrf5/cntr.c | 6 +- .../ll_sw/nordic/hal/nrf5/radio/radio.c | 56 +++++++++---------- .../ll_sw/nordic/hal/nrf5/radio/radio_nrf5.h | 4 +- .../nordic/hal/nrf5/radio/radio_nrf5_dppi.h | 4 +- .../controller/ll_sw/nordic/hal/nrf5/swi.h | 2 +- .../controller/ll_sw/nordic/hci/hci_vendor.h | 2 +- 7 files changed, 38 insertions(+), 38 deletions(-) diff --git a/subsys/bluetooth/controller/Kconfig.ll_sw_split b/subsys/bluetooth/controller/Kconfig.ll_sw_split index 729238a4a5e7e..2051e038bfeb7 100644 --- a/subsys/bluetooth/controller/Kconfig.ll_sw_split +++ b/subsys/bluetooth/controller/Kconfig.ll_sw_split @@ -15,7 +15,7 @@ config BT_LLL_VENDOR_NORDIC select ENTROPY_NRF5_BIAS_CORRECTION if ENTROPY_NRF5_RNG select BT_HAS_HCI_VS - select BT_CTLR_CRYPTO_SUPPORT if !SOC_SERIES_NRF54LX + select BT_CTLR_CRYPTO_SUPPORT if !SOC_COMPATIBLE_NRF54LX select BT_CTLR_LE_ENC_SUPPORT if BT_CTLR_CRYPTO_SUPPORT && \ !BT_CTLR_DATA_LENGTH_CLEAR && \ !BT_CTLR_PHY_2M_NRF diff --git a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/cntr.c b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/cntr.c index b8cff57df3417..1dccf4ed2f96a 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/cntr.c +++ b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/cntr.c @@ -12,11 +12,11 @@ #include "hal/debug.h" #ifndef NRF_RTC -#if defined(CONFIG_SOC_SERIES_NRF54LX) +#if defined(CONFIG_SOC_COMPATIBLE_NRF54LX) #define NRF_RTC NRF_RTC10 -#else /* !CONFIG_SOC_SERIES_NRF54LX */ +#else /* !CONFIG_SOC_COMPATIBLE_NRF54LX */ #define NRF_RTC NRF_RTC0 -#endif /* !CONFIG_SOC_SERIES_NRF54LX */ +#endif /* !CONFIG_SOC_COMPATIBLE_NRF54LX */ #endif /* !NRF_RTC */ static uint8_t _refcount; 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 5878e0c6756a9..f5ecc263cb1c4 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 @@ -242,12 +242,12 @@ void radio_reset(void) hal_radio_sw_switch_ppi_group_setup(); #endif -#if defined(CONFIG_SOC_SERIES_NRF54LX) +#if defined(CONFIG_SOC_COMPATIBLE_NRF54LX) NRF_RADIO->TIMING = (0U << RADIO_TIMING_RU_Pos) & RADIO_TIMING_RU_Msk; NRF_POWER->TASKS_CONSTLAT = 1U; -#endif /* CONFIG_SOC_SERIES_NRF54LX */ +#endif /* CONFIG_SOC_COMPATIBLE_NRF54LX */ #if defined(HAL_RADIO_GPIO_HAVE_PA_PIN) || defined(HAL_RADIO_GPIO_HAVE_LNA_PIN) hal_palna_ppi_setup(); @@ -313,7 +313,7 @@ void radio_phy_set(uint8_t phy, uint8_t flags) NRF_RADIO->MODE = (mode << RADIO_MODE_MODE_Pos) & RADIO_MODE_MODE_Msk; -#if !defined(CONFIG_SOC_SERIES_NRF51X) && !defined(CONFIG_SOC_SERIES_NRF54LX) +#if !defined(CONFIG_SOC_SERIES_NRF51X) && !defined(CONFIG_SOC_COMPATIBLE_NRF54LX) #if defined(CONFIG_BT_CTLR_RADIO_ENABLE_FAST) NRF_RADIO->MODECNF0 = ((RADIO_MODECNF0_DTX_Center << RADIO_MODECNF0_DTX_Pos) & @@ -326,7 +326,7 @@ void radio_phy_set(uint8_t phy, uint8_t flags) RADIO_MODECNF0_DTX_Pos) & RADIO_MODECNF0_DTX_Msk; #endif /* !CONFIG_BT_CTLR_RADIO_ENABLE_FAST */ -#endif /* !CONFIG_SOC_SERIES_NRF51X && !CONFIG_SOC_SERIES_NRF54LX */ +#endif /* !CONFIG_SOC_SERIES_NRF51X && !CONFIG_SOC_COMPATIBLE_NRF54LX */ } void radio_tx_power_set(int8_t power) @@ -440,7 +440,7 @@ void radio_pkt_configure(uint8_t bits_len, uint8_t max_len, uint8_t flags) #elif defined(CONFIG_SOC_COMPATIBLE_NRF52X) || \ defined(CONFIG_SOC_COMPATIBLE_NRF53X) || \ - defined(CONFIG_SOC_SERIES_NRF54LX) + defined(CONFIG_SOC_COMPATIBLE_NRF54LX) extra = 0U; phy = RADIO_PKT_CONF_PHY_GET(flags); @@ -537,7 +537,7 @@ uint32_t radio_rx_chain_delay_get(uint8_t phy, uint8_t flags) void radio_rx_enable(void) { #if !defined(CONFIG_BT_CTLR_TIFS_HW) -#if defined(CONFIG_SOC_COMPATIBLE_NRF53X) || defined(CONFIG_SOC_SERIES_NRF54LX) +#if defined(CONFIG_SOC_COMPATIBLE_NRF53X) || defined(CONFIG_SOC_COMPATIBLE_NRF54LX) /* NOTE: Timer clear DPPI configuration is needed only for nRF53 * because of calls to radio_disable() and * radio_switch_complete_and_disable() inside a radio event call @@ -550,7 +550,7 @@ void radio_rx_enable(void) * radio event but when the radio event is done. */ hal_sw_switch_timer_clear_ppi_config(); -#endif /* CONFIG_SOC_COMPATIBLE_NRF53X || CONFIG_SOC_SERIES_NRF54LX */ +#endif /* CONFIG_SOC_COMPATIBLE_NRF53X || CONFIG_SOC_COMPATIBLE_NRF54LX */ #endif /* !CONFIG_BT_CTLR_TIFS_HW */ nrf_radio_task_trigger(NRF_RADIO, NRF_RADIO_TASK_RXEN); @@ -559,7 +559,7 @@ void radio_rx_enable(void) void radio_tx_enable(void) { #if !defined(CONFIG_BT_CTLR_TIFS_HW) -#if defined(CONFIG_SOC_COMPATIBLE_NRF53X) || defined(CONFIG_SOC_SERIES_NRF54LX) +#if defined(CONFIG_SOC_COMPATIBLE_NRF53X) || defined(CONFIG_SOC_COMPATIBLE_NRF54LX) /* NOTE: Timer clear DPPI configuration is needed only for nRF53 * because of calls to radio_disable() and * radio_switch_complete_and_disable() inside a radio event call @@ -572,7 +572,7 @@ void radio_tx_enable(void) * radio event but when the radio event is done. */ hal_sw_switch_timer_clear_ppi_config(); -#endif /* CONFIG_SOC_COMPATIBLE_NRF53X || CONFIG_SOC_SERIES_NRF54LX */ +#endif /* CONFIG_SOC_COMPATIBLE_NRF53X || CONFIG_SOC_COMPATIBLE_NRF54LX */ #endif /* !CONFIG_BT_CTLR_TIFS_HW */ nrf_radio_task_trigger(NRF_RADIO, NRF_RADIO_TASK_TXEN); @@ -1271,38 +1271,38 @@ void radio_tmr_rx_status_reset(void) void radio_tmr_tx_enable(void) { -#if defined(CONFIG_SOC_COMPATIBLE_NRF53X) || defined(CONFIG_SOC_SERIES_NRF54LX) -#else /* !CONFIG_SOC_COMPATIBLE_NRF53X && !CONFIG_SOC_SERIES_NRF54LX */ +#if defined(CONFIG_SOC_COMPATIBLE_NRF53X) || defined(CONFIG_SOC_COMPATIBLE_NRF54LX) +#else /* !CONFIG_SOC_COMPATIBLE_NRF53X && !CONFIG_SOC_COMPATIBLE_NRF54LX */ #if (HAL_RADIO_ENABLE_TX_ON_TICK_PPI == HAL_RADIO_ENABLE_RX_ON_TICK_PPI) hal_radio_enable_on_tick_ppi_config_and_enable(1U); #endif /* HAL_RADIO_ENABLE_TX_ON_TICK_PPI == HAL_RADIO_ENABLE_RX_ON_TICK_PPI */ -#endif /* !CONFIG_SOC_COMPATIBLE_NRF53X && !CONFIG_SOC_SERIES_NRF54LX */ +#endif /* !CONFIG_SOC_COMPATIBLE_NRF53X && !CONFIG_SOC_COMPATIBLE_NRF54LX */ } void radio_tmr_rx_enable(void) { -#if defined(CONFIG_SOC_COMPATIBLE_NRF53X) || defined(CONFIG_SOC_SERIES_NRF54LX) -#else /* !CONFIG_SOC_COMPATIBLE_NRF53X && !CONFIG_SOC_SERIES_NRF54LX */ +#if defined(CONFIG_SOC_COMPATIBLE_NRF53X) || defined(CONFIG_SOC_COMPATIBLE_NRF54LX) +#else /* !CONFIG_SOC_COMPATIBLE_NRF53X && !CONFIG_SOC_COMPATIBLE_NRF54LX */ #if (HAL_RADIO_ENABLE_TX_ON_TICK_PPI == HAL_RADIO_ENABLE_RX_ON_TICK_PPI) hal_radio_enable_on_tick_ppi_config_and_enable(0U); #endif /* HAL_RADIO_ENABLE_TX_ON_TICK_PPI == HAL_RADIO_ENABLE_RX_ON_TICK_PPI */ -#endif /* !CONFIG_SOC_COMPATIBLE_NRF53X && !CONFIG_SOC_SERIES_NRF54LX */ +#endif /* !CONFIG_SOC_COMPATIBLE_NRF53X && !CONFIG_SOC_COMPATIBLE_NRF54LX */ } void radio_tmr_tx_disable(void) { -#if defined(CONFIG_SOC_COMPATIBLE_NRF53X) || defined(CONFIG_SOC_SERIES_NRF54LX) +#if defined(CONFIG_SOC_COMPATIBLE_NRF53X) || defined(CONFIG_SOC_COMPATIBLE_NRF54LX) nrf_radio_subscribe_clear(NRF_RADIO, NRF_RADIO_TASK_TXEN); -#else /* !CONFIG_SOC_COMPATIBLE_NRF53X && !CONFIG_SOC_SERIES_NRF54LX */ -#endif /* !CONFIG_SOC_COMPATIBLE_NRF53X && !CONFIG_SOC_SERIES_NRF54LX */ +#else /* !CONFIG_SOC_COMPATIBLE_NRF53X && !CONFIG_SOC_COMPATIBLE_NRF54LX */ +#endif /* !CONFIG_SOC_COMPATIBLE_NRF53X && !CONFIG_SOC_COMPATIBLE_NRF54LX */ } void radio_tmr_rx_disable(void) { -#if defined(CONFIG_SOC_COMPATIBLE_NRF53X) || defined(CONFIG_SOC_SERIES_NRF54LX) +#if defined(CONFIG_SOC_COMPATIBLE_NRF53X) || defined(CONFIG_SOC_COMPATIBLE_NRF54LX) nrf_radio_subscribe_clear(NRF_RADIO, NRF_RADIO_TASK_RXEN); -#else /* !CONFIG_SOC_COMPATIBLE_NRF53X && !CONFIG_SOC_SERIES_NRF54LX */ -#endif /* !CONFIG_SOC_COMPATIBLE_NRF53X && !CONFIG_SOC_SERIES_NRF54LX */ +#else /* !CONFIG_SOC_COMPATIBLE_NRF53X && !CONFIG_SOC_COMPATIBLE_NRF54LX */ +#endif /* !CONFIG_SOC_COMPATIBLE_NRF53X && !CONFIG_SOC_COMPATIBLE_NRF54LX */ } void radio_tmr_tifs_set(uint32_t tifs) @@ -1389,7 +1389,7 @@ uint32_t radio_tmr_start_tick(uint8_t trx, uint32_t tick) #if defined(CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER) last_pdu_end_us = 0U; #endif /* CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER */ -#if defined(CONFIG_SOC_COMPATIBLE_NRF53X) || defined(CONFIG_SOC_SERIES_NRF54LX) +#if defined(CONFIG_SOC_COMPATIBLE_NRF53X) || defined(CONFIG_SOC_COMPATIBLE_NRF54LX) /* NOTE: Timer clear DPPI configuration is needed only for nRF53 * because of calls to radio_disable() and * radio_switch_complete_and_disable() inside a radio event call @@ -1402,7 +1402,7 @@ uint32_t radio_tmr_start_tick(uint8_t trx, uint32_t tick) * radio event but when the radio event is done. */ hal_sw_switch_timer_clear_ppi_config(); -#endif /* CONFIG_SOC_COMPATIBLE_NRF53X || CONFIG_SOC_SERIES_NRF54LX */ +#endif /* CONFIG_SOC_COMPATIBLE_NRF53X || CONFIG_SOC_COMPATIBLE_NRF54LX */ #endif /* !CONFIG_BT_CTLR_TIFS_HW */ return remainder_us; @@ -1416,7 +1416,7 @@ uint32_t radio_tmr_start_us(uint8_t trx, uint32_t start_us) #if defined(CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER) last_pdu_end_us = 0U; #endif /* CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER */ -#if defined(CONFIG_SOC_COMPATIBLE_NRF53X) || defined(CONFIG_SOC_SERIES_NRF54LX) +#if defined(CONFIG_SOC_COMPATIBLE_NRF53X) || defined(CONFIG_SOC_COMPATIBLE_NRF54LX) /* NOTE: Timer clear DPPI configuration is needed only for nRF53 * because of calls to radio_disable() and * radio_switch_complete_and_disable() inside a radio event call @@ -1429,7 +1429,7 @@ uint32_t radio_tmr_start_us(uint8_t trx, uint32_t start_us) * radio event but when the radio event is done. */ hal_sw_switch_timer_clear_ppi_config(); -#endif /* CONFIG_SOC_COMPATIBLE_NRF53X || CONFIG_SOC_SERIES_NRF54LX */ +#endif /* CONFIG_SOC_COMPATIBLE_NRF53X || CONFIG_SOC_COMPATIBLE_NRF54LX */ #endif /* !CONFIG_BT_CTLR_TIFS_HW */ /* start_us could be the current count in the timer */ @@ -1485,9 +1485,9 @@ void radio_tmr_stop(void) nrf_timer_task_trigger(SW_SWITCH_TIMER, NRF_TIMER_TASK_SHUTDOWN); #endif /* !CONFIG_BT_CTLR_TIFS_HW */ -#if defined(CONFIG_SOC_SERIES_NRF54LX) +#if defined(CONFIG_SOC_COMPATIBLE_NRF54LX) NRF_POWER->TASKS_LOWPWR = 1U; -#endif /* CONFIG_SOC_SERIES_NRF54LX */ +#endif /* CONFIG_SOC_COMPATIBLE_NRF54LX */ } void radio_tmr_hcto_configure(uint32_t hcto) @@ -1914,7 +1914,7 @@ static void *radio_ccm_ext_tx_pkt_set(struct ccm *cnf, uint8_t pdu_type, void *p CCM_MODE_MODE_Msk; #if defined(CONFIG_SOC_COMPATIBLE_NRF52X) || \ defined(CONFIG_SOC_COMPATIBLE_NRF53X) || \ - defined(CONFIG_SOC_SERIES_NRF54LX) + defined(CONFIG_SOC_COMPATIBLE_NRF54LX) /* Enable CCM support for 8-bit length field PDUs. */ mode |= (CCM_MODE_LENGTH_Extended << CCM_MODE_LENGTH_Pos) & CCM_MODE_LENGTH_Msk; diff --git a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5.h b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5.h index add2117923fbf..ac771b37af893 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5.h +++ b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5.h @@ -43,9 +43,9 @@ #elif defined(CONFIG_SOC_NRF5340_CPUNET) #include #include "radio_nrf5340.h" -#elif defined(CONFIG_SOC_SERIES_NRF54LX) +#elif defined(CONFIG_SOC_COMPATIBLE_NRF54LX) #include "radio_nrf54lx.h" -#else /* !CONFIG_SOC_SERIES_NRF54LX */ +#else /* !CONFIG_SOC_COMPATIBLE_NRF54LX */ #error "Unsupported SoC." #endif 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 3b3fc681c9c1b..01f537c10d0da 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 @@ -5,9 +5,9 @@ * SPDX-License-Identifier: Apache-2.0 */ -#if defined(CONFIG_SOC_SERIES_NRF54LX) +#if defined(CONFIG_SOC_COMPATIBLE_NRF54LX) #define NRF_DPPIC NRF_DPPIC10 -#endif /* CONFIG_SOC_SERIES_NRF54LX */ +#endif /* CONFIG_SOC_COMPATIBLE_NRF54LX */ static inline void hal_radio_nrf_ppi_channels_enable(uint32_t mask) { diff --git a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/swi.h b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/swi.h index 1759df921c751..1cd17defbb970 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/swi.h +++ b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/swi.h @@ -42,7 +42,7 @@ #endif /* !CONFIG_SOC_COMPATIBLE_NRF5340_CPUNET */ /* nRF54 Series IRQ mapping */ -#elif defined(CONFIG_SOC_SERIES_NRF54LX) +#elif defined(CONFIG_SOC_COMPATIBLE_NRF54LX) #define HAL_SWI_RADIO_IRQ SWI02_IRQn #define HAL_SWI_WORKER_IRQ RTC10_IRQn diff --git a/subsys/bluetooth/controller/ll_sw/nordic/hci/hci_vendor.h b/subsys/bluetooth/controller/ll_sw/nordic/hci/hci_vendor.h index ecbe896847616..93abbd5ae5d2c 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/hci/hci_vendor.h +++ b/subsys/bluetooth/controller/ll_sw/nordic/hci/hci_vendor.h @@ -14,7 +14,7 @@ #define BT_HCI_VS_HW_VAR BT_HCI_VS_HW_VAR_NORDIC_NRF53X #elif defined(CONFIG_SOC_SERIES_NRF54HX) #define BT_HCI_VS_HW_VAR BT_HCI_VS_HW_VAR_NORDIC_NRF54HX -#elif defined(CONFIG_SOC_SERIES_NRF54LX) +#elif defined(CONFIG_SOC_COMPATIBLE_NRF54LX) #define BT_HCI_VS_HW_VAR BT_HCI_VS_HW_VAR_NORDIC_NRF54LX #endif #else From cdab35a118e4fcebbd52a3e1a58e7f369bd846b4 Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Thu, 30 May 2024 13:12:00 +0200 Subject: [PATCH 2042/2849] samples: Bluetooth: hci_uart: Use lower IRQ priority SoC peripherals Use lower IRQ proirities for SoC peripherals, example UART, to reduce ISR latencies on the IRQs processed by the Controller. Signed-off-by: Vinayak Kariappa Chettimada --- samples/bluetooth/hci_uart/dts/arm/nordic/override.dtsi | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 samples/bluetooth/hci_uart/dts/arm/nordic/override.dtsi diff --git a/samples/bluetooth/hci_uart/dts/arm/nordic/override.dtsi b/samples/bluetooth/hci_uart/dts/arm/nordic/override.dtsi new file mode 100644 index 0000000000000..882f70755d59d --- /dev/null +++ b/samples/bluetooth/hci_uart/dts/arm/nordic/override.dtsi @@ -0,0 +1,7 @@ +/* Keep default IRQ priority low for peripherals to reduce Radio ISR latency. + * ARM Cortex-M4 lowest priority value of 5, i.e. considering Zephyr reserved 2 + * levels for Exceptions and ZLI (if enabled). + * ARM Cortex-M0 lowest priority value of 3, i.e. we use it as Zephyr has no + * support for ZLI on Cortex-M0. + */ +#define NRF_DEFAULT_IRQ_PRIORITY 3 From cefeae0048b4f22e0360e497f7aba83124be0465 Mon Sep 17 00:00:00 2001 From: Luca Burelli Date: Tue, 21 May 2024 11:25:07 +0200 Subject: [PATCH 2043/2849] llext: add llext heap management functions Add llext_alloc(), llext_aligned_alloc() and llext_free() wrapper functions to manage memory allocation and deallocation from the llext heap. Also add a helper to free all memory regions allocated by an extension. Signed-off-by: Luca Burelli --- subsys/llext/llext.c | 69 +++++++++++++++++++++++++------------------- 1 file changed, 40 insertions(+), 29 deletions(-) diff --git a/subsys/llext/llext.c b/subsys/llext/llext.c index ca5513b741f6b..512cf949cb3f3 100644 --- a/subsys/llext/llext.c +++ b/subsys/llext/llext.c @@ -32,6 +32,32 @@ LOG_MODULE_REGISTER(llext, CONFIG_LLEXT_LOG_LEVEL); K_HEAP_DEFINE(llext_heap, CONFIG_LLEXT_HEAP_SIZE * 1024); +void *llext_alloc(size_t bytes) +{ + return k_heap_alloc(&llext_heap, bytes, K_NO_WAIT); +} + +void *llext_aligned_alloc(size_t align, size_t bytes) +{ + return k_heap_aligned_alloc(&llext_heap, align, bytes, K_NO_WAIT); +} + +void llext_free(void *ptr) +{ + k_heap_free(&llext_heap, ptr); +} + +void llext_free_sections(struct llext *ext) +{ + for (int i = 0; i < LLEXT_MEM_COUNT; i++) { + if (ext->mem_on_heap[i]) { + LOG_DBG("freeing memory region %d", i); + llext_free(ext->mem[i]); + ext->mem[i] = NULL; + } + } +} + static const char ELF_MAGIC[] = {0x7f, 'E', 'L', 'F'}; static sys_slist_t _llext_list = SYS_SLIST_STATIC_INIT(&_llext_list); @@ -475,10 +501,7 @@ static int llext_copy_section(struct llext_loader *ldr, struct llext *ext, uintptr_t sect_align = sect_alloc; #endif - ext->mem[mem_idx] = k_heap_aligned_alloc(&llext_heap, sect_align, - sect_alloc, - K_NO_WAIT); - + ext->mem[mem_idx] = llext_aligned_alloc(sect_align, sect_alloc); if (!ext->mem[mem_idx]) { return -ENOMEM; } @@ -507,7 +530,7 @@ static int llext_copy_section(struct llext_loader *ldr, struct llext *ext, return 0; err: - k_heap_free(&llext_heap, ext->mem[mem_idx]); + llext_free(ext->mem[mem_idx]); return ret; } @@ -594,7 +617,7 @@ static int llext_allocate_symtab(struct llext_loader *ldr, struct llext *ext) struct llext_symtable *sym_tab = &ext->sym_tab; size_t syms_size = sym_tab->sym_cnt * sizeof(struct llext_symbol); - sym_tab->syms = k_heap_alloc(&llext_heap, syms_size, K_NO_WAIT); + sym_tab->syms = llext_alloc(syms_size); if (!sym_tab->syms) { return -ENOMEM; } @@ -618,8 +641,7 @@ static int llext_export_symbols(struct llext_loader *ldr, struct llext *ext) struct llext_symtable *exp_tab = &ext->exp_tab; exp_tab->sym_cnt = shdr->sh_size / sizeof(struct llext_symbol); - exp_tab->syms = k_heap_alloc(&llext_heap, exp_tab->sym_cnt * sizeof(struct llext_symbol), - K_NO_WAIT); + exp_tab->syms = llext_alloc(exp_tab->sym_cnt * sizeof(struct llext_symbol)); if (!exp_tab->syms) { return -ENOMEM; } @@ -1056,7 +1078,7 @@ static int do_llext_load(struct llext_loader *ldr, struct llext *ext, size_t sect_map_sz = ldr->hdr.e_shnum * sizeof(ldr->sect_map[0]); - ldr->sect_map = k_heap_alloc(&llext_heap, sect_map_sz, K_NO_WAIT); + ldr->sect_map = llext_alloc(sect_map_sz); if (!ldr->sect_map) { LOG_ERR("Failed to allocate memory for section map, size %zu", sect_map_sz); ret = -ENOMEM; @@ -1138,23 +1160,19 @@ static int do_llext_load(struct llext_loader *ldr, struct llext *ext, } out: - k_heap_free(&llext_heap, ldr->sect_map); + llext_free(ldr->sect_map); if (ret != 0) { LOG_DBG("Failed to load extension, freeing memory..."); - for (enum llext_mem mem_idx = 0; mem_idx < LLEXT_MEM_COUNT; mem_idx++) { - if (ext->mem_on_heap[mem_idx]) { - k_heap_free(&llext_heap, ext->mem[mem_idx]); - } - } - k_heap_free(&llext_heap, ext->exp_tab.syms); + llext_free_sections(ext); + llext_free(ext->exp_tab.syms); } else { LOG_DBG("loaded module, .text at %p, .rodata at %p", ext->mem[LLEXT_MEM_TEXT], ext->mem[LLEXT_MEM_RODATA]); } ext->sym_tab.sym_cnt = 0; - k_heap_free(&llext_heap, ext->sym_tab.syms); + llext_free(ext->sym_tab.syms); ext->sym_tab.syms = NULL; return ret; @@ -1199,7 +1217,7 @@ int llext_load(struct llext_loader *ldr, const char *name, struct llext **ext, case ET_REL: case ET_DYN: LOG_DBG("Loading relocatable or shared elf"); - *ext = k_heap_alloc(&llext_heap, sizeof(struct llext), K_NO_WAIT); + *ext = llext_alloc(sizeof(struct llext)); if (*ext == NULL) { LOG_ERR("Not enough memory for extension metadata"); ret = -ENOMEM; @@ -1210,7 +1228,7 @@ int llext_load(struct llext_loader *ldr, const char *name, struct llext **ext, ldr->hdr = ehdr; ret = do_llext_load(ldr, *ext, ldr_parm); if (ret < 0) { - k_heap_free(&llext_heap, *ext); + llext_free(*ext); *ext = NULL; goto out; } @@ -1254,16 +1272,9 @@ int llext_unload(struct llext **ext) *ext = NULL; k_mutex_unlock(&llext_lock); - for (int i = 0; i < LLEXT_MEM_COUNT; i++) { - if (tmp->mem_on_heap[i]) { - LOG_DBG("freeing memory region %d", i); - k_heap_free(&llext_heap, tmp->mem[i]); - tmp->mem[i] = NULL; - } - } - - k_heap_free(&llext_heap, tmp->exp_tab.syms); - k_heap_free(&llext_heap, tmp); + llext_free_sections(tmp); + llext_free(tmp->exp_tab.syms); + llext_free(tmp); return 0; } From 35ef089cb14f30c2b7e53cdd69534b27dc3eb2f6 Mon Sep 17 00:00:00 2001 From: Luca Burelli Date: Tue, 21 May 2024 12:23:38 +0200 Subject: [PATCH 2044/2849] llext: move basic ELF checks to llext_load_elf_data() This patch moves the initial checks performed on the ELF file, that were split between llext_load() and do_llext_load(), to the newly defined llext_load_elf_data() function. This way: - only one function deals with ELF internal data checks; - do_llext_load() is reduced to a list of tasks; - llext_load() only focuses on the extension management. One totally misplaced line initializing the number of symbols has been moved to llext_count_export_syms(). No functional change except that the `struct llext` allocation may be performed unnecessarily if the ELF file is not valid. Signed-off-by: Luca Burelli --- subsys/llext/llext.c | 140 ++++++++++++++++++++++++------------------- 1 file changed, 80 insertions(+), 60 deletions(-) diff --git a/subsys/llext/llext.c b/subsys/llext/llext.c index 512cf949cb3f3..dba30885375ed 100644 --- a/subsys/llext/llext.c +++ b/subsys/llext/llext.c @@ -183,6 +183,66 @@ const void *llext_find_sym(const struct llext_symtable *sym_table, const char *s return NULL; } +/* + * Load basic ELF file data + */ + +static int llext_load_elf_data(struct llext_loader *ldr, struct llext *ext) +{ + int ret; + + /* read ELF header */ + + ret = llext_seek(ldr, 0); + if (ret != 0) { + LOG_ERR("Failed to seek for ELF header"); + return ret; + } + + ret = llext_read(ldr, &ldr->hdr, sizeof(ldr->hdr)); + if (ret != 0) { + LOG_ERR("Failed to read ELF header"); + return ret; + } + + /* check whether this is a valid ELF file */ + if (memcmp(ldr->hdr.e_ident, ELF_MAGIC, sizeof(ELF_MAGIC)) != 0) { + LOG_HEXDUMP_ERR(ldr->hdr.e_ident, 16, "Invalid ELF, magic does not match"); + return -EINVAL; + } + + switch (ldr->hdr.e_type) { + case ET_REL: + LOG_DBG("Loading relocatable ELF"); + break; + + case ET_DYN: + LOG_DBG("Loading shared ELF"); + break; + + default: + LOG_ERR("Unsupported ELF file type %x", ldr->hdr.e_type); + return -EINVAL; + } + + ldr->sect_cnt = ldr->hdr.e_shnum; + + memset(ldr->sects, 0, sizeof(ldr->sects)); + + size_t sect_map_sz = ldr->sect_cnt * sizeof(ldr->sect_map[0]); + + ldr->sect_map = llext_alloc(sect_map_sz); + if (!ldr->sect_map) { + LOG_ERR("Failed to allocate memory for section map, size %zu", sect_map_sz); + return -ENOMEM; + } + + memset(ldr->sect_map, 0, sect_map_sz); + ext->alloc_size += sect_map_sz; + + return 0; +} + /* * Find all relevant string and symbol tables */ @@ -575,6 +635,7 @@ static int llext_count_export_syms(struct llext_loader *ldr, struct llext *ext) LOG_DBG("symbol count %u", sym_cnt); + ext->sym_tab.sym_cnt = 0; for (i = 0, pos = ldr->sects[LLEXT_MEM_SYMTAB].sh_offset; i < sym_cnt; i++, pos += ent_size) { @@ -1070,24 +1131,14 @@ static int llext_link(struct llext_loader *ldr, struct llext *ext, bool do_local static int do_llext_load(struct llext_loader *ldr, struct llext *ext, struct llext_load_param *ldr_parm) { - int ret = 0; - - memset(ldr->sects, 0, sizeof(ldr->sects)); - ldr->sect_cnt = 0; - ext->sym_tab.sym_cnt = 0; - - size_t sect_map_sz = ldr->hdr.e_shnum * sizeof(ldr->sect_map[0]); + int ret; - ldr->sect_map = llext_alloc(sect_map_sz); - if (!ldr->sect_map) { - LOG_ERR("Failed to allocate memory for section map, size %zu", sect_map_sz); - ret = -ENOMEM; + LOG_DBG("Loading ELF data..."); + ret = llext_load_elf_data(ldr, ext); + if (ret != 0) { + LOG_ERR("Failed to load basic ELF data, ret %d", ret); goto out; } - memset(ldr->sect_map, 0, sect_map_sz); - - ldr->sect_cnt = ldr->hdr.e_shnum; - ext->alloc_size += sect_map_sz; #ifdef CONFIG_USERSPACE ret = k_mem_domain_init(&ext->mem_domain, 0, NULL); @@ -1182,7 +1233,6 @@ int llext_load(struct llext_loader *ldr, const char *name, struct llext **ext, struct llext_load_param *ldr_parm) { int ret; - elf_ehdr_t ehdr; *ext = llext_by_name(name); @@ -1194,57 +1244,27 @@ int llext_load(struct llext_loader *ldr, const char *name, struct llext **ext, goto out; } - ret = llext_seek(ldr, 0); - if (ret != 0) { - LOG_ERR("Failed to seek for ELF header"); + *ext = llext_alloc(sizeof(struct llext)); + if (*ext == NULL) { + LOG_ERR("Not enough memory for extension metadata"); + ret = -ENOMEM; goto out; } + memset(*ext, 0, sizeof(struct llext)); - ret = llext_read(ldr, &ehdr, sizeof(ehdr)); - if (ret != 0) { - LOG_ERR("Failed to read ELF header"); + ret = do_llext_load(ldr, *ext, ldr_parm); + if (ret < 0) { + llext_free(*ext); + *ext = NULL; goto out; } - /* check whether this is an valid elf file */ - if (memcmp(ehdr.e_ident, ELF_MAGIC, sizeof(ELF_MAGIC)) != 0) { - LOG_HEXDUMP_ERR(ehdr.e_ident, 16, "Invalid ELF, magic does not match"); - ret = -EINVAL; - goto out; - } + strncpy((*ext)->name, name, sizeof((*ext)->name)); + (*ext)->name[sizeof((*ext)->name) - 1] = '\0'; + (*ext)->use_count++; - switch (ehdr.e_type) { - case ET_REL: - case ET_DYN: - LOG_DBG("Loading relocatable or shared elf"); - *ext = llext_alloc(sizeof(struct llext)); - if (*ext == NULL) { - LOG_ERR("Not enough memory for extension metadata"); - ret = -ENOMEM; - goto out; - } - memset(*ext, 0, sizeof(struct llext)); - - ldr->hdr = ehdr; - ret = do_llext_load(ldr, *ext, ldr_parm); - if (ret < 0) { - llext_free(*ext); - *ext = NULL; - goto out; - } - - strncpy((*ext)->name, name, sizeof((*ext)->name)); - (*ext)->name[sizeof((*ext)->name) - 1] = '\0'; - (*ext)->use_count++; - - sys_slist_append(&_llext_list, &(*ext)->_llext_list); - LOG_INF("Loaded extension %s", (*ext)->name); - - break; - default: - LOG_ERR("Unsupported elf file type %x", ehdr.e_type); - ret = -EINVAL; - } + sys_slist_append(&_llext_list, &(*ext)->_llext_list); + LOG_INF("Loaded extension %s", (*ext)->name); out: k_mutex_unlock(&llext_lock); From 9c5412f79e37a03f45cbfaa30cabad01fa8f6a24 Mon Sep 17 00:00:00 2001 From: Luca Burelli Date: Tue, 4 Jun 2024 10:32:36 +0200 Subject: [PATCH 2045/2849] llext: refact: move memory code to llext_mem.c Move all memory management code to a separate file, llext_mem.c, to allow for better separation of concerns and to make the code more readable. No functional changes are introduced by this commit. Signed-off-by: Luca Burelli --- subsys/llext/CMakeLists.txt | 9 +- subsys/llext/llext.c | 191 +---------------------------------- subsys/llext/llext_mem.c | 196 ++++++++++++++++++++++++++++++++++++ subsys/llext/llext_priv.h | 42 ++++++++ 4 files changed, 247 insertions(+), 191 deletions(-) create mode 100644 subsys/llext/llext_mem.c create mode 100644 subsys/llext/llext_priv.h diff --git a/subsys/llext/CMakeLists.txt b/subsys/llext/CMakeLists.txt index d08e1c8aee0e3..b895480ecd55b 100644 --- a/subsys/llext/CMakeLists.txt +++ b/subsys/llext/CMakeLists.txt @@ -1,7 +1,14 @@ if(CONFIG_LLEXT) zephyr_library() + # For strnlen() zephyr_library_compile_definitions(-D_POSIX_C_SOURCE=200809L) - zephyr_library_sources(llext.c llext_export.c buf_loader.c) + + zephyr_library_sources( + llext.c + llext_mem.c + llext_export.c + buf_loader.c + ) zephyr_library_sources_ifdef(CONFIG_LLEXT_SHELL shell.c) endif() diff --git a/subsys/llext/llext.c b/subsys/llext/llext.c index dba30885375ed..a58cd6d4088ae 100644 --- a/subsys/llext/llext.c +++ b/subsys/llext/llext.c @@ -17,12 +17,7 @@ LOG_MODULE_REGISTER(llext, CONFIG_LLEXT_LOG_LEVEL); #include -#ifdef CONFIG_MMU_PAGE_SIZE -#define LLEXT_PAGE_SIZE CONFIG_MMU_PAGE_SIZE -#else -/* Arm's MPU wants a 32 byte minimum mpu region */ -#define LLEXT_PAGE_SIZE 32 -#endif +#include "llext_priv.h" #ifdef CONFIG_LLEXT_EXPORT_BUILTINS_BY_SLID #define SYM_NAME_OR_SLID(name, slid) ((const char *)slid) @@ -30,34 +25,6 @@ LOG_MODULE_REGISTER(llext, CONFIG_LLEXT_LOG_LEVEL); #define SYM_NAME_OR_SLID(name, slid) name #endif -K_HEAP_DEFINE(llext_heap, CONFIG_LLEXT_HEAP_SIZE * 1024); - -void *llext_alloc(size_t bytes) -{ - return k_heap_alloc(&llext_heap, bytes, K_NO_WAIT); -} - -void *llext_aligned_alloc(size_t align, size_t bytes) -{ - return k_heap_aligned_alloc(&llext_heap, align, bytes, K_NO_WAIT); -} - -void llext_free(void *ptr) -{ - k_heap_free(&llext_heap, ptr); -} - -void llext_free_sections(struct llext *ext) -{ - for (int i = 0; i < LLEXT_MEM_COUNT; i++) { - if (ext->mem_on_heap[i]) { - LOG_DBG("freeing memory region %d", i); - llext_free(ext->mem[i]); - ext->mem[i] = NULL; - } - } -} - static const char ELF_MAGIC[] = {0x7f, 'E', 'L', 'F'}; static sys_slist_t _llext_list = SYS_SLIST_STATIC_INIT(&_llext_list); @@ -490,139 +457,6 @@ static int llext_map_sections(struct llext_loader *ldr, struct llext *ext) return 0; } -/* - * Initialize the memory partition associated with the extension memory - */ -static void llext_init_mem_part(struct llext *ext, enum llext_mem mem_idx, - uintptr_t start, size_t len) -{ -#ifdef CONFIG_USERSPACE - if (mem_idx < LLEXT_MEM_PARTITIONS) { - ext->mem_parts[mem_idx].start = start; - ext->mem_parts[mem_idx].size = len; - - switch (mem_idx) { - case LLEXT_MEM_TEXT: - ext->mem_parts[mem_idx].attr = K_MEM_PARTITION_P_RX_U_RX; - break; - case LLEXT_MEM_DATA: - case LLEXT_MEM_BSS: - ext->mem_parts[mem_idx].attr = K_MEM_PARTITION_P_RW_U_RW; - break; - case LLEXT_MEM_RODATA: - ext->mem_parts[mem_idx].attr = K_MEM_PARTITION_P_RO_U_RO; - break; - default: - break; - } - LOG_DBG("mem partition %d start 0x%lx, size %d", mem_idx, - ext->mem_parts[mem_idx].start, - ext->mem_parts[mem_idx].size); - } -#endif - - LOG_DBG("mem idx %d: start 0x%zx, size %zd", mem_idx, (size_t)start, len); -} - -static int llext_copy_section(struct llext_loader *ldr, struct llext *ext, - enum llext_mem mem_idx) -{ - int ret; - - if (!ldr->sects[mem_idx].sh_size) { - return 0; - } - ext->mem_size[mem_idx] = ldr->sects[mem_idx].sh_size; - - if (ldr->sects[mem_idx].sh_type != SHT_NOBITS && - IS_ENABLED(CONFIG_LLEXT_STORAGE_WRITABLE)) { - ext->mem[mem_idx] = llext_peek(ldr, ldr->sects[mem_idx].sh_offset); - if (ext->mem[mem_idx]) { - llext_init_mem_part(ext, mem_idx, (uintptr_t)ext->mem[mem_idx], - ldr->sects[mem_idx].sh_size); - ext->mem_on_heap[mem_idx] = false; - return 0; - } - } - - /* On ARM with an MPU a pow(2, N)*32 sized and aligned region is needed, - * otherwise its typically an mmu page (sized and aligned memory region) - * we are after that we can assign memory permission bits on. - */ -#ifndef CONFIG_ARM_MPU - const uintptr_t sect_alloc = ROUND_UP(ldr->sects[mem_idx].sh_size, LLEXT_PAGE_SIZE); - const uintptr_t sect_align = LLEXT_PAGE_SIZE; -#else - uintptr_t sect_alloc = LLEXT_PAGE_SIZE; - - while (sect_alloc < ldr->sects[mem_idx].sh_size) { - sect_alloc *= 2; - } - uintptr_t sect_align = sect_alloc; -#endif - - ext->mem[mem_idx] = llext_aligned_alloc(sect_align, sect_alloc); - if (!ext->mem[mem_idx]) { - return -ENOMEM; - } - - ext->alloc_size += sect_alloc; - - llext_init_mem_part(ext, mem_idx, (uintptr_t)ext->mem[mem_idx], - sect_alloc); - - if (ldr->sects[mem_idx].sh_type == SHT_NOBITS) { - memset(ext->mem[mem_idx], 0, ldr->sects[mem_idx].sh_size); - } else { - ret = llext_seek(ldr, ldr->sects[mem_idx].sh_offset); - if (ret != 0) { - goto err; - } - - ret = llext_read(ldr, ext->mem[mem_idx], ldr->sects[mem_idx].sh_size); - if (ret != 0) { - goto err; - } - } - - ext->mem_on_heap[mem_idx] = true; - - return 0; - -err: - llext_free(ext->mem[mem_idx]); - return ret; -} - -static int llext_copy_strings(struct llext_loader *ldr, struct llext *ext) -{ - int ret = llext_copy_section(ldr, ext, LLEXT_MEM_SHSTRTAB); - - if (!ret) { - ret = llext_copy_section(ldr, ext, LLEXT_MEM_STRTAB); - } - - return ret; -} - -static int llext_copy_sections(struct llext_loader *ldr, struct llext *ext) -{ - for (enum llext_mem mem_idx = 0; mem_idx < LLEXT_MEM_COUNT; mem_idx++) { - /* strings have already been copied */ - if (ext->mem[mem_idx]) { - continue; - } - - int ret = llext_copy_section(ldr, ext, mem_idx); - - if (ret < 0) { - return ret; - } - } - - return 0; -} - static int llext_count_export_syms(struct llext_loader *ldr, struct llext *ext) { size_t ent_size = ldr->sects[LLEXT_MEM_SYMTAB].sh_entsize; @@ -1311,26 +1145,3 @@ int llext_call_fn(struct llext *ext, const char *sym_name) return 0; } - -int llext_add_domain(struct llext *ext, struct k_mem_domain *domain) -{ -#ifdef CONFIG_USERSPACE - int ret = 0; - - for (int i = 0; i < LLEXT_MEM_PARTITIONS; i++) { - if (ext->mem_size[i] == 0) { - continue; - } - ret = k_mem_domain_add_partition(domain, &ext->mem_parts[i]); - if (ret != 0) { - LOG_ERR("Failed adding memory partition %d to domain %p", - i, domain); - return ret; - } - } - - return ret; -#else - return -ENOSYS; -#endif -} diff --git a/subsys/llext/llext_mem.c b/subsys/llext/llext_mem.c new file mode 100644 index 0000000000000..d4a96da5e67e1 --- /dev/null +++ b/subsys/llext/llext_mem.c @@ -0,0 +1,196 @@ +/* + * Copyright (c) 2023 Intel Corporation + * Copyright (c) 2024 Arduino SA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include + +#include +LOG_MODULE_DECLARE(llext, CONFIG_LLEXT_LOG_LEVEL); + +#include + +#include "llext_priv.h" + +#ifdef CONFIG_MMU_PAGE_SIZE +#define LLEXT_PAGE_SIZE CONFIG_MMU_PAGE_SIZE +#else +/* Arm's MPU wants a 32 byte minimum mpu region */ +#define LLEXT_PAGE_SIZE 32 +#endif + +K_HEAP_DEFINE(llext_heap, CONFIG_LLEXT_HEAP_SIZE * 1024); + +/* + * Initialize the memory partition associated with the extension memory + */ +static void llext_init_mem_part(struct llext *ext, enum llext_mem mem_idx, + uintptr_t start, size_t len) +{ +#ifdef CONFIG_USERSPACE + if (mem_idx < LLEXT_MEM_PARTITIONS) { + ext->mem_parts[mem_idx].start = start; + ext->mem_parts[mem_idx].size = len; + + switch (mem_idx) { + case LLEXT_MEM_TEXT: + ext->mem_parts[mem_idx].attr = K_MEM_PARTITION_P_RX_U_RX; + break; + case LLEXT_MEM_DATA: + case LLEXT_MEM_BSS: + ext->mem_parts[mem_idx].attr = K_MEM_PARTITION_P_RW_U_RW; + break; + case LLEXT_MEM_RODATA: + ext->mem_parts[mem_idx].attr = K_MEM_PARTITION_P_RO_U_RO; + break; + default: + break; + } + LOG_DBG("mem partition %d start 0x%lx, size %d", mem_idx, + ext->mem_parts[mem_idx].start, + ext->mem_parts[mem_idx].size); + } +#endif + + LOG_DBG("mem idx %d: start 0x%zx, size %zd", mem_idx, (size_t)start, len); +} + +static int llext_copy_section(struct llext_loader *ldr, struct llext *ext, + enum llext_mem mem_idx) +{ + int ret; + + if (!ldr->sects[mem_idx].sh_size) { + return 0; + } + ext->mem_size[mem_idx] = ldr->sects[mem_idx].sh_size; + + if (ldr->sects[mem_idx].sh_type != SHT_NOBITS && + IS_ENABLED(CONFIG_LLEXT_STORAGE_WRITABLE)) { + ext->mem[mem_idx] = llext_peek(ldr, ldr->sects[mem_idx].sh_offset); + if (ext->mem[mem_idx]) { + llext_init_mem_part(ext, mem_idx, (uintptr_t)ext->mem[mem_idx], + ldr->sects[mem_idx].sh_size); + ext->mem_on_heap[mem_idx] = false; + return 0; + } + } + + /* On ARM with an MPU a pow(2, N)*32 sized and aligned region is needed, + * otherwise its typically an mmu page (sized and aligned memory region) + * we are after that we can assign memory permission bits on. + */ +#ifndef CONFIG_ARM_MPU + const uintptr_t sect_alloc = ROUND_UP(ldr->sects[mem_idx].sh_size, LLEXT_PAGE_SIZE); + const uintptr_t sect_align = LLEXT_PAGE_SIZE; +#else + uintptr_t sect_alloc = LLEXT_PAGE_SIZE; + + while (sect_alloc < ldr->sects[mem_idx].sh_size) { + sect_alloc *= 2; + } + uintptr_t sect_align = sect_alloc; +#endif + + ext->mem[mem_idx] = llext_aligned_alloc(sect_align, sect_alloc); + if (!ext->mem[mem_idx]) { + return -ENOMEM; + } + + ext->alloc_size += sect_alloc; + + llext_init_mem_part(ext, mem_idx, (uintptr_t)ext->mem[mem_idx], + sect_alloc); + + if (ldr->sects[mem_idx].sh_type == SHT_NOBITS) { + memset(ext->mem[mem_idx], 0, ldr->sects[mem_idx].sh_size); + } else { + ret = llext_seek(ldr, ldr->sects[mem_idx].sh_offset); + if (ret != 0) { + goto err; + } + + ret = llext_read(ldr, ext->mem[mem_idx], ldr->sects[mem_idx].sh_size); + if (ret != 0) { + goto err; + } + } + + ext->mem_on_heap[mem_idx] = true; + + return 0; + +err: + llext_free(ext->mem[mem_idx]); + ext->mem[mem_idx] = NULL; + return ret; +} + +int llext_copy_strings(struct llext_loader *ldr, struct llext *ext) +{ + int ret = llext_copy_section(ldr, ext, LLEXT_MEM_SHSTRTAB); + + if (!ret) { + ret = llext_copy_section(ldr, ext, LLEXT_MEM_STRTAB); + } + + return ret; +} + +int llext_copy_sections(struct llext_loader *ldr, struct llext *ext) +{ + for (enum llext_mem mem_idx = 0; mem_idx < LLEXT_MEM_COUNT; mem_idx++) { + /* strings have already been copied */ + if (ext->mem[mem_idx]) { + continue; + } + + int ret = llext_copy_section(ldr, ext, mem_idx); + + if (ret < 0) { + return ret; + } + } + + return 0; +} + +void llext_free_sections(struct llext *ext) +{ + for (int i = 0; i < LLEXT_MEM_COUNT; i++) { + if (ext->mem_on_heap[i]) { + LOG_DBG("freeing memory region %d", i); + llext_free(ext->mem[i]); + ext->mem[i] = NULL; + } + } +} + +int llext_add_domain(struct llext *ext, struct k_mem_domain *domain) +{ +#ifdef CONFIG_USERSPACE + int ret = 0; + + for (int i = 0; i < LLEXT_MEM_PARTITIONS; i++) { + if (ext->mem_size[i] == 0) { + continue; + } + ret = k_mem_domain_add_partition(domain, &ext->mem_parts[i]); + if (ret != 0) { + LOG_ERR("Failed adding memory partition %d to domain %p", + i, domain); + return ret; + } + } + + return ret; +#else + return -ENOSYS; +#endif +} diff --git a/subsys/llext/llext_priv.h b/subsys/llext/llext_priv.h new file mode 100644 index 0000000000000..d699e6318498b --- /dev/null +++ b/subsys/llext/llext_priv.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2024 Arduino SA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_SUBSYS_LLEXT_PRIV_H_ +#define ZEPHYR_SUBSYS_LLEXT_PRIV_H_ + +#include +#include + +/* + * Memory management (llext_mem.c) + */ + +int llext_copy_strings(struct llext_loader *ldr, struct llext *ext); +int llext_copy_sections(struct llext_loader *ldr, struct llext *ext); +void llext_free_sections(struct llext *ext); + +static inline void *llext_alloc(size_t bytes) +{ + extern struct k_heap llext_heap; + + return k_heap_alloc(&llext_heap, bytes, K_NO_WAIT); +} + +static inline void *llext_aligned_alloc(size_t align, size_t bytes) +{ + extern struct k_heap llext_heap; + + return k_heap_aligned_alloc(&llext_heap, align, bytes, K_NO_WAIT); +} + +static inline void llext_free(void *ptr) +{ + extern struct k_heap llext_heap; + + k_heap_free(&llext_heap, ptr); +} + +#endif /* ZEPHYR_SUBSYS_LLEXT_PRIV_H_ */ From 1a2f6ae381421cf3fdd079187d8d60dfec7f41fe Mon Sep 17 00:00:00 2001 From: Luca Burelli Date: Wed, 5 Jun 2024 11:02:46 +0200 Subject: [PATCH 2046/2849] llext: refact: move ELF loading and linking to separate files This commit moves ELF loading and linking code to separate files. This is done to make the code more manageable and to make it easier to add new features in the future. No functional changes are introduced by this commit, except for a few static functions now made public to allow this file split to occur. Signed-off-by: Luca Burelli --- subsys/llext/CMakeLists.txt | 2 + subsys/llext/llext.c | 948 ------------------------------------ subsys/llext/llext_link.c | 337 +++++++++++++ subsys/llext/llext_load.c | 644 ++++++++++++++++++++++++ subsys/llext/llext_priv.h | 21 + 5 files changed, 1004 insertions(+), 948 deletions(-) create mode 100644 subsys/llext/llext_link.c create mode 100644 subsys/llext/llext_load.c diff --git a/subsys/llext/CMakeLists.txt b/subsys/llext/CMakeLists.txt index b895480ecd55b..415e012a3d2f7 100644 --- a/subsys/llext/CMakeLists.txt +++ b/subsys/llext/CMakeLists.txt @@ -7,6 +7,8 @@ if(CONFIG_LLEXT) zephyr_library_sources( llext.c llext_mem.c + llext_load.c + llext_link.c llext_export.c buf_loader.c ) diff --git a/subsys/llext/llext.c b/subsys/llext/llext.c index a58cd6d4088ae..d00d952b76e33 100644 --- a/subsys/llext/llext.c +++ b/subsys/llext/llext.c @@ -19,45 +19,10 @@ LOG_MODULE_REGISTER(llext, CONFIG_LLEXT_LOG_LEVEL); #include "llext_priv.h" -#ifdef CONFIG_LLEXT_EXPORT_BUILTINS_BY_SLID -#define SYM_NAME_OR_SLID(name, slid) ((const char *)slid) -#else -#define SYM_NAME_OR_SLID(name, slid) name -#endif - -static const char ELF_MAGIC[] = {0x7f, 'E', 'L', 'F'}; - static sys_slist_t _llext_list = SYS_SLIST_STATIC_INIT(&_llext_list); static struct k_mutex llext_lock = Z_MUTEX_INITIALIZER(llext_lock); -static elf_shdr_t *llext_section_by_name(struct llext_loader *ldr, const char *search_name) -{ - elf_shdr_t *shdr; - unsigned int i; - size_t pos; - - for (i = 0, pos = ldr->hdr.e_shoff; - i < ldr->hdr.e_shnum; - i++, pos += ldr->hdr.e_shentsize) { - shdr = llext_peek(ldr, pos); - if (!shdr) { - /* The peek() method isn't supported */ - return NULL; - } - - const char *name = llext_peek(ldr, - ldr->sects[LLEXT_MEM_SHSTRTAB].sh_offset + - shdr->sh_name); - - if (!strcmp(name, search_name)) { - return shdr; - } - } - - return NULL; -} - ssize_t llext_find_section(struct llext_loader *ldr, const char *search_name) { elf_shdr_t *shdr = llext_section_by_name(ldr, search_name); @@ -150,919 +115,6 @@ const void *llext_find_sym(const struct llext_symtable *sym_table, const char *s return NULL; } -/* - * Load basic ELF file data - */ - -static int llext_load_elf_data(struct llext_loader *ldr, struct llext *ext) -{ - int ret; - - /* read ELF header */ - - ret = llext_seek(ldr, 0); - if (ret != 0) { - LOG_ERR("Failed to seek for ELF header"); - return ret; - } - - ret = llext_read(ldr, &ldr->hdr, sizeof(ldr->hdr)); - if (ret != 0) { - LOG_ERR("Failed to read ELF header"); - return ret; - } - - /* check whether this is a valid ELF file */ - if (memcmp(ldr->hdr.e_ident, ELF_MAGIC, sizeof(ELF_MAGIC)) != 0) { - LOG_HEXDUMP_ERR(ldr->hdr.e_ident, 16, "Invalid ELF, magic does not match"); - return -EINVAL; - } - - switch (ldr->hdr.e_type) { - case ET_REL: - LOG_DBG("Loading relocatable ELF"); - break; - - case ET_DYN: - LOG_DBG("Loading shared ELF"); - break; - - default: - LOG_ERR("Unsupported ELF file type %x", ldr->hdr.e_type); - return -EINVAL; - } - - ldr->sect_cnt = ldr->hdr.e_shnum; - - memset(ldr->sects, 0, sizeof(ldr->sects)); - - size_t sect_map_sz = ldr->sect_cnt * sizeof(ldr->sect_map[0]); - - ldr->sect_map = llext_alloc(sect_map_sz); - if (!ldr->sect_map) { - LOG_ERR("Failed to allocate memory for section map, size %zu", sect_map_sz); - return -ENOMEM; - } - - memset(ldr->sect_map, 0, sect_map_sz); - ext->alloc_size += sect_map_sz; - - return 0; -} - -/* - * Find all relevant string and symbol tables - */ -static int llext_find_tables(struct llext_loader *ldr) -{ - int sect_cnt, i, ret; - size_t pos; - elf_shdr_t shdr; - - ldr->sects[LLEXT_MEM_SHSTRTAB] = - ldr->sects[LLEXT_MEM_STRTAB] = - ldr->sects[LLEXT_MEM_SYMTAB] = (elf_shdr_t){0}; - - /* Find symbol and string tables */ - for (i = 0, sect_cnt = 0, pos = ldr->hdr.e_shoff; - i < ldr->hdr.e_shnum && sect_cnt < 3; - i++, pos += ldr->hdr.e_shentsize) { - ret = llext_seek(ldr, pos); - if (ret != 0) { - LOG_ERR("failed seeking to position %zu\n", pos); - return ret; - } - - ret = llext_read(ldr, &shdr, sizeof(elf_shdr_t)); - if (ret != 0) { - LOG_ERR("failed reading section header at position %zu\n", pos); - return ret; - } - - LOG_DBG("section %d at %zx: name %d, type %d, flags %zx, " - "ofs %zx, addr %zx, size %zd", - i, pos, - shdr.sh_name, - shdr.sh_type, - (size_t)shdr.sh_flags, - (size_t)shdr.sh_offset, - (size_t)shdr.sh_addr, - (size_t)shdr.sh_size); - - switch (shdr.sh_type) { - case SHT_SYMTAB: - case SHT_DYNSYM: - LOG_DBG("symtab at %d", i); - ldr->sects[LLEXT_MEM_SYMTAB] = shdr; - ldr->sect_map[i] = LLEXT_MEM_SYMTAB; - sect_cnt++; - break; - case SHT_STRTAB: - if (ldr->hdr.e_shstrndx == i) { - LOG_DBG("shstrtab at %d", i); - ldr->sects[LLEXT_MEM_SHSTRTAB] = shdr; - ldr->sect_map[i] = LLEXT_MEM_SHSTRTAB; - } else { - LOG_DBG("strtab at %d", i); - ldr->sects[LLEXT_MEM_STRTAB] = shdr; - ldr->sect_map[i] = LLEXT_MEM_STRTAB; - } - sect_cnt++; - break; - default: - break; - } - } - - if (!ldr->sects[LLEXT_MEM_SHSTRTAB].sh_type || - !ldr->sects[LLEXT_MEM_STRTAB].sh_type || - !ldr->sects[LLEXT_MEM_SYMTAB].sh_type) { - LOG_ERR("Some sections are missing or present multiple times!"); - return -ENOENT; - } - - return 0; -} - -static const char *llext_string(struct llext_loader *ldr, struct llext *ext, - enum llext_mem mem_idx, unsigned int idx) -{ - return (char *)ext->mem[mem_idx] + idx; -} - -/* - * Maps the section indexes and copies special section headers for easier use - */ -static int llext_map_sections(struct llext_loader *ldr, struct llext *ext) -{ - int i, j, ret; - size_t pos; - elf_shdr_t shdr; - const char *name; - - for (i = 0, pos = ldr->hdr.e_shoff; - i < ldr->hdr.e_shnum; - i++, pos += ldr->hdr.e_shentsize) { - ret = llext_seek(ldr, pos); - if (ret != 0) { - return ret; - } - - ret = llext_read(ldr, &shdr, sizeof(elf_shdr_t)); - if (ret != 0) { - return ret; - } - - if ((shdr.sh_type != SHT_PROGBITS && shdr.sh_type != SHT_NOBITS) || - !(shdr.sh_flags & SHF_ALLOC) || - shdr.sh_size == 0) { - continue; - } - - name = llext_string(ldr, ext, LLEXT_MEM_SHSTRTAB, shdr.sh_name); - - /* Identify the section type by its flags */ - enum llext_mem mem_idx; - - switch (shdr.sh_type) { - case SHT_NOBITS: - mem_idx = LLEXT_MEM_BSS; - break; - case SHT_PROGBITS: - if (shdr.sh_flags & SHF_EXECINSTR) { - mem_idx = LLEXT_MEM_TEXT; - } else if (shdr.sh_flags & SHF_WRITE) { - mem_idx = LLEXT_MEM_DATA; - } else { - mem_idx = LLEXT_MEM_RODATA; - } - break; - default: - LOG_DBG("Not copied section %s", name); - continue; - } - - /* Special exception for .exported_sym */ - if (strcmp(name, ".exported_sym") == 0) { - mem_idx = LLEXT_MEM_EXPORT; - } - - LOG_DBG("section %d name %s maps to idx %d", i, name, mem_idx); - - ldr->sect_map[i] = mem_idx; - elf_shdr_t *sect = ldr->sects + mem_idx; - - if (sect->sh_type == SHT_NULL) { - /* First section of this type, copy all info */ - *sect = shdr; - } else { - /* Make sure the sections are compatible before merging */ - if (shdr.sh_flags != sect->sh_flags) { - LOG_ERR("Unsupported section flags for %s (mem %d)", - name, mem_idx); - return -ENOEXEC; - } - - if (mem_idx == LLEXT_MEM_BSS) { - /* SHT_NOBITS sections cannot be merged properly: - * as they use no space in the file, the logic - * below does not work; they must be treated as - * independent entities. - */ - LOG_ERR("Multiple SHT_NOBITS sections are not supported"); - return -ENOEXEC; - } - - if (ldr->hdr.e_type == ET_DYN) { - /* In shared objects, sh_addr is the VMA. Before - * merging these sections, make sure the delta - * in VMAs matches that of file offsets. - */ - if (shdr.sh_addr - sect->sh_addr != - shdr.sh_offset - sect->sh_offset) { - LOG_ERR("Incompatible section addresses " - "for %s (mem %d)", name, mem_idx); - return -ENOEXEC; - } - } - - /* - * Extend the current section to include the new one - * (overlaps are detected later) - */ - size_t address = MIN(sect->sh_addr, shdr.sh_addr); - size_t bot_ofs = MIN(sect->sh_offset, shdr.sh_offset); - size_t top_ofs = MAX(sect->sh_offset + sect->sh_size, - shdr.sh_offset + shdr.sh_size); - - sect->sh_addr = address; - sect->sh_offset = bot_ofs; - sect->sh_size = top_ofs - bot_ofs; - } - } - - /* - * Test that no computed range overlaps. This can happen if sections of - * different llext_mem type are interleaved in the ELF file or in VMAs. - */ - for (i = 0; i < LLEXT_MEM_COUNT; i++) { - for (j = i+1; j < LLEXT_MEM_COUNT; j++) { - elf_shdr_t *x = ldr->sects + i; - elf_shdr_t *y = ldr->sects + j; - - if (x->sh_type == SHT_NULL || x->sh_size == 0 || - y->sh_type == SHT_NULL || y->sh_size == 0) { - /* Skip empty sections */ - continue; - } - - if (ldr->hdr.e_type == ET_DYN) { - /* - * Test all merged VMA ranges for overlaps - */ - if ((x->sh_addr <= y->sh_addr && - x->sh_addr + x->sh_size > y->sh_addr) || - (y->sh_addr <= x->sh_addr && - y->sh_addr + y->sh_size > x->sh_addr)) { - LOG_ERR("VMA range %d (0x%zx +%zd) " - "overlaps with %d (0x%zx +%zd)", - i, (size_t)x->sh_addr, (size_t)x->sh_size, - j, (size_t)y->sh_addr, (size_t)y->sh_size); - return -ENOEXEC; - } - } - - /* - * Test file offsets. BSS sections store no - * data in the file and must not be included - * in checks to avoid false positives. - */ - if (i == LLEXT_MEM_BSS || j == LLEXT_MEM_BSS) { - continue; - } - - if ((x->sh_offset <= y->sh_offset && - x->sh_offset + x->sh_size > y->sh_offset) || - (y->sh_offset <= x->sh_offset && - y->sh_offset + y->sh_size > x->sh_offset)) { - LOG_ERR("ELF file range %d (0x%zx +%zd) " - "overlaps with %d (0x%zx +%zd)", - i, (size_t)x->sh_offset, (size_t)x->sh_size, - j, (size_t)y->sh_offset, (size_t)y->sh_size); - return -ENOEXEC; - } - } - } - - return 0; -} - -static int llext_count_export_syms(struct llext_loader *ldr, struct llext *ext) -{ - size_t ent_size = ldr->sects[LLEXT_MEM_SYMTAB].sh_entsize; - size_t syms_size = ldr->sects[LLEXT_MEM_SYMTAB].sh_size; - int sym_cnt = syms_size / sizeof(elf_sym_t); - const char *name; - elf_sym_t sym; - int i, ret; - size_t pos; - - LOG_DBG("symbol count %u", sym_cnt); - - ext->sym_tab.sym_cnt = 0; - for (i = 0, pos = ldr->sects[LLEXT_MEM_SYMTAB].sh_offset; - i < sym_cnt; - i++, pos += ent_size) { - if (!i) { - /* A dummy entry */ - continue; - } - - ret = llext_seek(ldr, pos); - if (ret != 0) { - return ret; - } - - ret = llext_read(ldr, &sym, ent_size); - if (ret != 0) { - return ret; - } - - uint32_t stt = ELF_ST_TYPE(sym.st_info); - uint32_t stb = ELF_ST_BIND(sym.st_info); - uint32_t sect = sym.st_shndx; - - name = llext_string(ldr, ext, LLEXT_MEM_STRTAB, sym.st_name); - - 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++; - } else { - LOG_DBG("unhandled symbol %d, name %s, type tag %d, bind %d, sect %d", - i, name, stt, stb, sect); - } - } - - return 0; -} - -static int llext_allocate_symtab(struct llext_loader *ldr, struct llext *ext) -{ - struct llext_symtable *sym_tab = &ext->sym_tab; - size_t syms_size = sym_tab->sym_cnt * sizeof(struct llext_symbol); - - sym_tab->syms = llext_alloc(syms_size); - if (!sym_tab->syms) { - return -ENOMEM; - } - memset(sym_tab->syms, 0, syms_size); - ext->alloc_size += syms_size; - - return 0; -} - -static int llext_export_symbols(struct llext_loader *ldr, struct llext *ext) -{ - elf_shdr_t *shdr = ldr->sects + LLEXT_MEM_EXPORT; - struct llext_symbol *sym; - unsigned int i; - - if (shdr->sh_size < sizeof(struct llext_symbol)) { - /* Not found, no symbols exported */ - return 0; - } - - struct llext_symtable *exp_tab = &ext->exp_tab; - - exp_tab->sym_cnt = shdr->sh_size / sizeof(struct llext_symbol); - exp_tab->syms = llext_alloc(exp_tab->sym_cnt * sizeof(struct llext_symbol)); - if (!exp_tab->syms) { - return -ENOMEM; - } - - for (i = 0, sym = ext->mem[LLEXT_MEM_EXPORT]; - i < exp_tab->sym_cnt; - i++, sym++) { - exp_tab->syms[i].name = sym->name; - exp_tab->syms[i].addr = sym->addr; - LOG_DBG("sym %p name %s in %p", sym->addr, sym->name, exp_tab->syms + i); - } - - return 0; -} - -static int llext_copy_symbols(struct llext_loader *ldr, struct llext *ext, - bool pre_located) -{ - size_t ent_size = ldr->sects[LLEXT_MEM_SYMTAB].sh_entsize; - size_t syms_size = ldr->sects[LLEXT_MEM_SYMTAB].sh_size; - int sym_cnt = syms_size / sizeof(elf_sym_t); - struct llext_symtable *sym_tab = &ext->sym_tab; - elf_sym_t sym; - int i, j, ret; - size_t pos; - - for (i = 0, pos = ldr->sects[LLEXT_MEM_SYMTAB].sh_offset, j = 0; - i < sym_cnt; - i++, pos += ent_size) { - if (!i) { - /* A dummy entry */ - continue; - } - - ret = llext_seek(ldr, pos); - if (ret != 0) { - return ret; - } - - ret = llext_read(ldr, &sym, ent_size); - if (ret != 0) { - return ret; - } - - uint32_t stt = ELF_ST_TYPE(sym.st_info); - uint32_t stb = ELF_ST_BIND(sym.st_info); - unsigned int sect = sym.st_shndx; - - if ((stt == STT_FUNC || stt == STT_OBJECT) && - stb == STB_GLOBAL && sect != SHN_UNDEF) { - const char *name = llext_string(ldr, ext, LLEXT_MEM_STRTAB, sym.st_name); - - __ASSERT(j <= sym_tab->sym_cnt, "Miscalculated symbol number %u\n", j); - - sym_tab->syms[j].name = name; - - uintptr_t section_addr; - void *base; - - if (sect < LLEXT_MEM_BSS) { - /* - * This is just a slight optimisation for cached - * sections, we could use the generic path below - * for all of them - */ - base = ext->mem[ldr->sect_map[sect]]; - section_addr = ldr->sects[ldr->sect_map[sect]].sh_addr; - } else { - /* Section header isn't stored, have to read it */ - size_t shdr_pos = ldr->hdr.e_shoff + sect * ldr->hdr.e_shentsize; - elf_shdr_t shdr; - - ret = llext_seek(ldr, shdr_pos); - if (ret != 0) { - LOG_ERR("failed seeking to position %zu\n", shdr_pos); - return ret; - } - - ret = llext_read(ldr, &shdr, sizeof(elf_shdr_t)); - if (ret != 0) { - LOG_ERR("failed reading section header at position %zu\n", - shdr_pos); - return ret; - } - - base = llext_peek(ldr, shdr.sh_offset); - if (!base) { - LOG_ERR("cannot handle arbitrary sections without .peek\n"); - return -EOPNOTSUPP; - } - - section_addr = shdr.sh_addr; - } - - if (pre_located) { - sym_tab->syms[j].addr = (uint8_t *)sym.st_value + - (ldr->hdr.e_type == ET_REL ? section_addr : 0); - } else { - sym_tab->syms[j].addr = (uint8_t *)base + sym.st_value - - (ldr->hdr.e_type == ET_REL ? 0 : section_addr); - } - - LOG_DBG("function symbol %d name %s addr %p", - j, name, sym_tab->syms[j].addr); - j++; - } - } - - return 0; -} - -/* - * Find the section, containing the supplied offset and return file offset for - * that value - */ -static size_t llext_file_offset(struct llext_loader *ldr, size_t offset) -{ - unsigned int i; - - for (i = 0; i < LLEXT_MEM_COUNT; i++) - if (ldr->sects[i].sh_addr <= offset && - ldr->sects[i].sh_addr + ldr->sects[i].sh_size > offset) - return offset - ldr->sects[i].sh_addr + ldr->sects[i].sh_offset; - - return offset; -} - -__weak void arch_elf_relocate_local(struct llext_loader *ldr, struct llext *ext, - const elf_rela_t *rel, const elf_sym_t *sym, size_t got_offset) -{ -} - -static void llext_link_plt(struct llext_loader *ldr, struct llext *ext, - elf_shdr_t *shdr, bool do_local, elf_shdr_t *tgt) -{ - unsigned int sh_cnt = shdr->sh_size / shdr->sh_entsize; - /* - * CPU address where the .text section is stored, we use .text just as a - * reference point - */ - uint8_t *text = ext->mem[LLEXT_MEM_TEXT]; - - LOG_DBG("Found %p in PLT %u size %zu cnt %u text %p", - (void *)llext_string(ldr, ext, LLEXT_MEM_SHSTRTAB, shdr->sh_name), - shdr->sh_type, (size_t)shdr->sh_entsize, sh_cnt, (void *)text); - - const elf_shdr_t *sym_shdr = ldr->sects + LLEXT_MEM_SYMTAB; - unsigned int sym_cnt = sym_shdr->sh_size / sym_shdr->sh_entsize; - - for (unsigned int i = 0; i < sh_cnt; i++) { - elf_rela_t rela; - - int ret = llext_seek(ldr, shdr->sh_offset + i * shdr->sh_entsize); - - if (!ret) { - ret = llext_read(ldr, &rela, sizeof(rela)); - } - - if (ret < 0) { - LOG_ERR("PLT: failed to read RELA #%u, trying to continue", i); - continue; - } - - /* Index in the symbol table */ - unsigned int j = ELF32_R_SYM(rela.r_info); - - if (j >= sym_cnt) { - LOG_WRN("PLT: idx %u >= %u", j, sym_cnt); - continue; - } - - elf_sym_t sym_tbl; - - ret = llext_seek(ldr, sym_shdr->sh_offset + j * sizeof(elf_sym_t)); - if (!ret) { - ret = llext_read(ldr, &sym_tbl, sizeof(sym_tbl)); - } - - if (ret < 0) { - LOG_ERR("PLT: failed to read symbol table #%u RELA #%u, trying to continue", - j, i); - continue; - } - - uint32_t stt = ELF_ST_TYPE(sym_tbl.st_info); - - if (stt != STT_FUNC && - stt != STT_SECTION && - stt != STT_OBJECT && - (stt != STT_NOTYPE || sym_tbl.st_shndx != SHN_UNDEF)) { - continue; - } - - const char *name = llext_string(ldr, ext, LLEXT_MEM_STRTAB, sym_tbl.st_name); - - /* - * Both r_offset and sh_addr are addresses for which the extension - * has been built. - */ - size_t got_offset; - - if (tgt) { - got_offset = rela.r_offset + tgt->sh_offset - - ldr->sects[LLEXT_MEM_TEXT].sh_offset; - } else { - got_offset = llext_file_offset(ldr, rela.r_offset) - - ldr->sects[LLEXT_MEM_TEXT].sh_offset; - } - - uint32_t stb = ELF_ST_BIND(sym_tbl.st_info); - const void *link_addr; - - switch (stb) { - case STB_GLOBAL: - link_addr = llext_find_sym(NULL, - SYM_NAME_OR_SLID(name, sym_tbl.st_value)); - - if (!link_addr) - link_addr = llext_find_sym(&ext->sym_tab, name); - - if (!link_addr) { - LOG_WRN("PLT: cannot find idx %u name %s", j, name); - continue; - } - - /* Resolve the symbol */ - *(const void **)(text + got_offset) = link_addr; - break; - case STB_LOCAL: - if (do_local) { - arch_elf_relocate_local(ldr, ext, &rela, &sym_tbl, got_offset); - } - } - - LOG_DBG("symbol %s offset %#zx r-offset %#zx .text offset %#zx stb %u", - name, got_offset, - (size_t)rela.r_offset, (size_t)ldr->sects[LLEXT_MEM_TEXT].sh_offset, stb); - } -} - -__weak int arch_elf_relocate(elf_rela_t *rel, uintptr_t loc, - uintptr_t sym_base_addr, const char *sym_name, uintptr_t load_bias) -{ - return -EOPNOTSUPP; -} - -static int llext_link(struct llext_loader *ldr, struct llext *ext, bool do_local) -{ - uintptr_t loc = 0; - elf_shdr_t shdr; - elf_rela_t rel; - elf_sym_t sym; - elf_word rel_cnt = 0; - const char *name; - int i, ret; - size_t pos; - - for (i = 0, pos = ldr->hdr.e_shoff; - i < ldr->hdr.e_shnum - 1; - i++, pos += ldr->hdr.e_shentsize) { - ret = llext_seek(ldr, pos); - if (ret != 0) { - return ret; - } - - ret = llext_read(ldr, &shdr, sizeof(elf_shdr_t)); - if (ret != 0) { - return ret; - } - - /* find relocation sections */ - if (shdr.sh_type != SHT_REL && shdr.sh_type != SHT_RELA) { - continue; - } - - rel_cnt = shdr.sh_size / shdr.sh_entsize; - - name = llext_string(ldr, ext, LLEXT_MEM_SHSTRTAB, shdr.sh_name); - - if (strcmp(name, ".rel.text") == 0) { - loc = (uintptr_t)ext->mem[LLEXT_MEM_TEXT]; - } else if (strcmp(name, ".rel.bss") == 0 || - strcmp(name, ".rela.bss") == 0) { - loc = (uintptr_t)ext->mem[LLEXT_MEM_BSS]; - } else if (strcmp(name, ".rel.rodata") == 0 || - strcmp(name, ".rela.rodata") == 0) { - loc = (uintptr_t)ext->mem[LLEXT_MEM_RODATA]; - } else if (strcmp(name, ".rel.data") == 0) { - loc = (uintptr_t)ext->mem[LLEXT_MEM_DATA]; - } else if (strcmp(name, ".rel.exported_sym") == 0) { - loc = (uintptr_t)ext->mem[LLEXT_MEM_EXPORT]; - } else if (strcmp(name, ".rela.plt") == 0 || - strcmp(name, ".rela.dyn") == 0) { - llext_link_plt(ldr, ext, &shdr, do_local, NULL); - continue; - } else if (strncmp(name, ".rela", 5) == 0 && strlen(name) > 5) { - elf_shdr_t *tgt = llext_section_by_name(ldr, name + 5); - - if (tgt) - llext_link_plt(ldr, ext, &shdr, do_local, tgt); - continue; - } else if (strcmp(name, ".rel.dyn") == 0) { - /* we assume that first load segment starts at MEM_TEXT */ - loc = (uintptr_t)ext->mem[LLEXT_MEM_TEXT]; - } - - LOG_DBG("relocation section %s (%d) linked to section %d has %zd relocations", - name, i, shdr.sh_link, (size_t)rel_cnt); - - for (int j = 0; j < rel_cnt; j++) { - /* get each relocation entry */ - ret = llext_seek(ldr, shdr.sh_offset + j * shdr.sh_entsize); - if (ret != 0) { - return ret; - } - - ret = llext_read(ldr, &rel, shdr.sh_entsize); - if (ret != 0) { - return ret; - } - - /* get corresponding symbol */ - ret = llext_seek(ldr, ldr->sects[LLEXT_MEM_SYMTAB].sh_offset - + ELF_R_SYM(rel.r_info) * sizeof(elf_sym_t)); - if (ret != 0) { - return ret; - } - - ret = llext_read(ldr, &sym, sizeof(elf_sym_t)); - if (ret != 0) { - return ret; - } - - name = llext_string(ldr, ext, LLEXT_MEM_STRTAB, sym.st_name); - - LOG_DBG("relocation %d:%d info %zx (type %zd, sym %zd) offset %zd sym_name " - "%s sym_type %d sym_bind %d sym_ndx %d", - i, j, (size_t)rel.r_info, (size_t)ELF_R_TYPE(rel.r_info), - (size_t)ELF_R_SYM(rel.r_info), - (size_t)rel.r_offset, name, ELF_ST_TYPE(sym.st_info), - ELF_ST_BIND(sym.st_info), sym.st_shndx); - - uintptr_t link_addr, op_loc; - - op_loc = loc + rel.r_offset; - - if (ELF_R_SYM(rel.r_info) == 0) { - /* no symbol ex: R_ARM_V4BX relocation, R_ARM_RELATIVE */ - link_addr = 0; - } else if (sym.st_shndx == SHN_UNDEF) { - /* If symbol is undefined, then we need to look it up */ - link_addr = (uintptr_t)llext_find_sym(NULL, - SYM_NAME_OR_SLID(name, sym.st_value)); - - if (link_addr == 0) { - LOG_ERR("Undefined symbol with no entry in " - "symbol table %s, offset %zd, link section %d", - name, (size_t)rel.r_offset, shdr.sh_link); - return -ENODATA; - } else { - LOG_INF("found symbol %s at 0x%lx", name, link_addr); - } - } else if (sym.st_shndx == SHN_ABS) { - /* Absolute symbol */ - link_addr = sym.st_value; - } else if ((sym.st_shndx < ldr->hdr.e_shnum) && - !IN_RANGE(sym.st_shndx, SHN_LORESERVE, SHN_HIRESERVE)) { - /* This check rejects all relocations whose target symbol - * has a section index higher than the maximum possible - * in this ELF file, or belongs in the reserved range: - * they will be caught by the `else` below and cause an - * error to be returned. This aborts the LLEXT's loading - * and prevents execution of improperly relocated code, - * which is dangerous. - * - * Note that the unsupported SHN_COMMON section is rejected - * as part of this check. Also note that SHN_ABS would be - * rejected as well, but we want to handle it properly: - * for this reason, this check must come AFTER handling - * the case where the symbol's section index is SHN_ABS! - * - * - * For regular symbols, the link address is obtained by - * adding st_value to the start address of the section - * in which the target symbol resides. - */ - link_addr = (uintptr_t)ext->mem[ldr->sect_map[sym.st_shndx]] - + sym.st_value; - } else { - LOG_ERR("rela section %d, entry %d: cannot apply relocation: " - "target symbol has unexpected section index %d (0x%X)", - i, j, sym.st_shndx, sym.st_shndx); - return -ENOEXEC; - } - - LOG_INF("writing relocation symbol %s type %zd sym %zd at addr 0x%lx " - "addr 0x%lx", - name, (size_t)ELF_R_TYPE(rel.r_info), (size_t)ELF_R_SYM(rel.r_info), - op_loc, link_addr); - - /* relocation */ - ret = arch_elf_relocate(&rel, op_loc, link_addr, name, - (uintptr_t)ext->mem[LLEXT_MEM_TEXT]); - if (ret != 0) { - return ret; - } - } - } - -#ifdef CONFIG_CACHE_MANAGEMENT - /* Make sure changes to ext sections are flushed to RAM */ - for (i = 0; i < LLEXT_MEM_COUNT; ++i) { - if (ext->mem[i]) { - sys_cache_data_flush_range(ext->mem[i], ext->mem_size[i]); - sys_cache_instr_invd_range(ext->mem[i], ext->mem_size[i]); - } - } -#endif - - return 0; -} - -/* - * Load a valid ELF as an extension - */ -static int do_llext_load(struct llext_loader *ldr, struct llext *ext, - struct llext_load_param *ldr_parm) -{ - int ret; - - LOG_DBG("Loading ELF data..."); - ret = llext_load_elf_data(ldr, ext); - if (ret != 0) { - LOG_ERR("Failed to load basic ELF data, ret %d", ret); - goto out; - } - -#ifdef CONFIG_USERSPACE - ret = k_mem_domain_init(&ext->mem_domain, 0, NULL); - if (ret != 0) { - LOG_ERR("Failed to initialize extenion memory domain %d", ret); - goto out; - } -#endif - - LOG_DBG("Finding ELF tables..."); - ret = llext_find_tables(ldr); - if (ret != 0) { - LOG_ERR("Failed to find important ELF tables, ret %d", ret); - goto out; - } - - LOG_DBG("Allocate and copy strings..."); - ret = llext_copy_strings(ldr, ext); - if (ret != 0) { - LOG_ERR("Failed to copy ELF string sections, ret %d", ret); - goto out; - } - - LOG_DBG("Mapping ELF sections..."); - ret = llext_map_sections(ldr, ext); - if (ret != 0) { - LOG_ERR("Failed to map ELF sections, ret %d", ret); - goto out; - } - - LOG_DBG("Allocate and copy sections..."); - ret = llext_copy_sections(ldr, ext); - if (ret != 0) { - LOG_ERR("Failed to copy ELF sections, ret %d", ret); - goto out; - } - - LOG_DBG("Counting exported symbols..."); - ret = llext_count_export_syms(ldr, ext); - if (ret != 0) { - LOG_ERR("Failed to count exported ELF symbols, ret %d", ret); - goto out; - } - - LOG_DBG("Allocating memory for symbol table..."); - ret = llext_allocate_symtab(ldr, ext); - if (ret != 0) { - LOG_ERR("Failed to allocate extension symbol table, ret %d", ret); - goto out; - } - - LOG_DBG("Copying symbols..."); - ret = llext_copy_symbols(ldr, ext, ldr_parm ? ldr_parm->pre_located : false); - if (ret != 0) { - LOG_ERR("Failed to copy symbols, ret %d", ret); - goto out; - } - - LOG_DBG("Linking ELF..."); - ret = llext_link(ldr, ext, ldr_parm ? ldr_parm->relocate_local : true); - if (ret != 0) { - LOG_ERR("Failed to link, ret %d", ret); - goto out; - } - - ret = llext_export_symbols(ldr, ext); - if (ret != 0) { - LOG_ERR("Failed to export, ret %d", ret); - goto out; - } - -out: - llext_free(ldr->sect_map); - - if (ret != 0) { - LOG_DBG("Failed to load extension, freeing memory..."); - llext_free_sections(ext); - llext_free(ext->exp_tab.syms); - } else { - LOG_DBG("loaded module, .text at %p, .rodata at %p", ext->mem[LLEXT_MEM_TEXT], - ext->mem[LLEXT_MEM_RODATA]); - } - - ext->sym_tab.sym_cnt = 0; - llext_free(ext->sym_tab.syms); - ext->sym_tab.syms = NULL; - - return ret; -} - int llext_load(struct llext_loader *ldr, const char *name, struct llext **ext, struct llext_load_param *ldr_parm) { diff --git a/subsys/llext/llext_link.c b/subsys/llext/llext_link.c new file mode 100644 index 0000000000000..9fb484f8ddee0 --- /dev/null +++ b/subsys/llext/llext_link.c @@ -0,0 +1,337 @@ +/* + * Copyright (c) 2023 Intel Corporation + * Copyright (c) 2024 Arduino SA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include + +#include +LOG_MODULE_DECLARE(llext, CONFIG_LLEXT_LOG_LEVEL); + +#include + +#include "llext_priv.h" + +#ifdef CONFIG_LLEXT_EXPORT_BUILTINS_BY_SLID +#define SYM_NAME_OR_SLID(name, slid) ((const char *) slid) +#else +#define SYM_NAME_OR_SLID(name, slid) name +#endif + +__weak int arch_elf_relocate(elf_rela_t *rel, uintptr_t loc, + uintptr_t sym_base_addr, const char *sym_name, uintptr_t load_bias) +{ + return -EOPNOTSUPP; +} + +__weak void arch_elf_relocate_local(struct llext_loader *ldr, struct llext *ext, + const elf_rela_t *rel, const elf_sym_t *sym, size_t got_offset) +{ +} + +/* + * Find the section containing the supplied offset and return file offset for + * that value + */ +static size_t llext_file_offset(struct llext_loader *ldr, size_t offset) +{ + unsigned int i; + + for (i = 0; i < LLEXT_MEM_COUNT; i++) + if (ldr->sects[i].sh_addr <= offset && + ldr->sects[i].sh_addr + ldr->sects[i].sh_size > offset) + return offset - ldr->sects[i].sh_addr + ldr->sects[i].sh_offset; + + return offset; +} + +static void llext_link_plt(struct llext_loader *ldr, struct llext *ext, + elf_shdr_t *shdr, bool do_local, elf_shdr_t *tgt) +{ + unsigned int sh_cnt = shdr->sh_size / shdr->sh_entsize; + /* + * CPU address where the .text section is stored, we use .text just as a + * reference point + */ + uint8_t *text = ext->mem[LLEXT_MEM_TEXT]; + + LOG_DBG("Found %p in PLT %u size %zu cnt %u text %p", + (void *)llext_string(ldr, ext, LLEXT_MEM_SHSTRTAB, shdr->sh_name), + shdr->sh_type, (size_t)shdr->sh_entsize, sh_cnt, (void *)text); + + const elf_shdr_t *sym_shdr = ldr->sects + LLEXT_MEM_SYMTAB; + unsigned int sym_cnt = sym_shdr->sh_size / sym_shdr->sh_entsize; + + for (unsigned int i = 0; i < sh_cnt; i++) { + elf_rela_t rela; + + int ret = llext_seek(ldr, shdr->sh_offset + i * shdr->sh_entsize); + + if (!ret) { + ret = llext_read(ldr, &rela, sizeof(rela)); + } + + if (ret < 0) { + LOG_ERR("PLT: failed to read RELA #%u, trying to continue", i); + continue; + } + + /* Index in the symbol table */ + unsigned int j = ELF32_R_SYM(rela.r_info); + + if (j >= sym_cnt) { + LOG_WRN("PLT: idx %u >= %u", j, sym_cnt); + continue; + } + + elf_sym_t sym_tbl; + + ret = llext_seek(ldr, sym_shdr->sh_offset + j * sizeof(elf_sym_t)); + if (!ret) { + ret = llext_read(ldr, &sym_tbl, sizeof(sym_tbl)); + } + + if (ret < 0) { + LOG_ERR("PLT: failed to read symbol table #%u RELA #%u, trying to continue", + j, i); + continue; + } + + uint32_t stt = ELF_ST_TYPE(sym_tbl.st_info); + + if (stt != STT_FUNC && + stt != STT_SECTION && + stt != STT_OBJECT && + (stt != STT_NOTYPE || sym_tbl.st_shndx != SHN_UNDEF)) { + continue; + } + + const char *name = llext_string(ldr, ext, LLEXT_MEM_STRTAB, sym_tbl.st_name); + + /* + * Both r_offset and sh_addr are addresses for which the extension + * has been built. + */ + size_t got_offset; + + if (tgt) { + got_offset = rela.r_offset + tgt->sh_offset - + ldr->sects[LLEXT_MEM_TEXT].sh_offset; + } else { + got_offset = llext_file_offset(ldr, rela.r_offset) - + ldr->sects[LLEXT_MEM_TEXT].sh_offset; + } + + uint32_t stb = ELF_ST_BIND(sym_tbl.st_info); + const void *link_addr; + + switch (stb) { + case STB_GLOBAL: + link_addr = llext_find_sym(NULL, + SYM_NAME_OR_SLID(name, sym_tbl.st_value)); + + if (!link_addr) + link_addr = llext_find_sym(&ext->sym_tab, name); + + if (!link_addr) { + LOG_WRN("PLT: cannot find idx %u name %s", j, name); + continue; + } + + /* Resolve the symbol */ + *(const void **)(text + got_offset) = link_addr; + break; + case STB_LOCAL: + if (do_local) { + arch_elf_relocate_local(ldr, ext, &rela, &sym_tbl, got_offset); + } + } + + LOG_DBG("symbol %s offset %#zx r-offset %#zx .text offset %#zx stb %u", + name, got_offset, + (size_t)rela.r_offset, (size_t)ldr->sects[LLEXT_MEM_TEXT].sh_offset, stb); + } +} + +int llext_link(struct llext_loader *ldr, struct llext *ext, bool do_local) +{ + uintptr_t loc = 0; + elf_shdr_t shdr; + elf_rela_t rel; + elf_sym_t sym; + elf_word rel_cnt = 0; + const char *name; + int i, ret; + size_t pos; + + for (i = 0, pos = ldr->hdr.e_shoff; + i < ldr->hdr.e_shnum - 1; + i++, pos += ldr->hdr.e_shentsize) { + ret = llext_seek(ldr, pos); + if (ret != 0) { + return ret; + } + + ret = llext_read(ldr, &shdr, sizeof(elf_shdr_t)); + if (ret != 0) { + return ret; + } + + /* find relocation sections */ + if (shdr.sh_type != SHT_REL && shdr.sh_type != SHT_RELA) { + continue; + } + + rel_cnt = shdr.sh_size / shdr.sh_entsize; + + name = llext_string(ldr, ext, LLEXT_MEM_SHSTRTAB, shdr.sh_name); + + if (strcmp(name, ".rel.text") == 0) { + loc = (uintptr_t)ext->mem[LLEXT_MEM_TEXT]; + } else if (strcmp(name, ".rel.bss") == 0 || + strcmp(name, ".rela.bss") == 0) { + loc = (uintptr_t)ext->mem[LLEXT_MEM_BSS]; + } else if (strcmp(name, ".rel.rodata") == 0 || + strcmp(name, ".rela.rodata") == 0) { + loc = (uintptr_t)ext->mem[LLEXT_MEM_RODATA]; + } else if (strcmp(name, ".rel.data") == 0) { + loc = (uintptr_t)ext->mem[LLEXT_MEM_DATA]; + } else if (strcmp(name, ".rel.exported_sym") == 0) { + loc = (uintptr_t)ext->mem[LLEXT_MEM_EXPORT]; + } else if (strcmp(name, ".rela.plt") == 0 || + strcmp(name, ".rela.dyn") == 0) { + llext_link_plt(ldr, ext, &shdr, do_local, NULL); + continue; + } else if (strncmp(name, ".rela", 5) == 0 && strlen(name) > 5) { + elf_shdr_t *tgt = llext_section_by_name(ldr, name + 5); + + if (tgt) + llext_link_plt(ldr, ext, &shdr, do_local, tgt); + continue; + } else if (strcmp(name, ".rel.dyn") == 0) { + /* we assume that first load segment starts at MEM_TEXT */ + loc = (uintptr_t)ext->mem[LLEXT_MEM_TEXT]; + } + + LOG_DBG("relocation section %s (%d) linked to section %d has %zd relocations", + name, i, shdr.sh_link, (size_t)rel_cnt); + + for (int j = 0; j < rel_cnt; j++) { + /* get each relocation entry */ + ret = llext_seek(ldr, shdr.sh_offset + j * shdr.sh_entsize); + if (ret != 0) { + return ret; + } + + ret = llext_read(ldr, &rel, shdr.sh_entsize); + if (ret != 0) { + return ret; + } + + /* get corresponding symbol */ + ret = llext_seek(ldr, ldr->sects[LLEXT_MEM_SYMTAB].sh_offset + + ELF_R_SYM(rel.r_info) * sizeof(elf_sym_t)); + if (ret != 0) { + return ret; + } + + ret = llext_read(ldr, &sym, sizeof(elf_sym_t)); + if (ret != 0) { + return ret; + } + + name = llext_string(ldr, ext, LLEXT_MEM_STRTAB, sym.st_name); + + LOG_DBG("relocation %d:%d info %zx (type %zd, sym %zd) offset %zd sym_name " + "%s sym_type %d sym_bind %d sym_ndx %d", + i, j, (size_t)rel.r_info, (size_t)ELF_R_TYPE(rel.r_info), + (size_t)ELF_R_SYM(rel.r_info), + (size_t)rel.r_offset, name, ELF_ST_TYPE(sym.st_info), + ELF_ST_BIND(sym.st_info), sym.st_shndx); + + uintptr_t link_addr, op_loc; + + op_loc = loc + rel.r_offset; + + if (ELF_R_SYM(rel.r_info) == 0) { + /* no symbol ex: R_ARM_V4BX relocation, R_ARM_RELATIVE */ + link_addr = 0; + } else if (sym.st_shndx == SHN_UNDEF) { + /* If symbol is undefined, then we need to look it up */ + link_addr = (uintptr_t)llext_find_sym(NULL, + SYM_NAME_OR_SLID(name, sym.st_value)); + + if (link_addr == 0) { + LOG_ERR("Undefined symbol with no entry in " + "symbol table %s, offset %zd, link section %d", + name, (size_t)rel.r_offset, shdr.sh_link); + return -ENODATA; + } + + LOG_INF("found symbol %s at 0x%lx", name, link_addr); + } else if (sym.st_shndx == SHN_ABS) { + /* Absolute symbol */ + link_addr = sym.st_value; + } else if ((sym.st_shndx < ldr->hdr.e_shnum) && + !IN_RANGE(sym.st_shndx, SHN_LORESERVE, SHN_HIRESERVE)) { + /* This check rejects all relocations whose target symbol + * has a section index higher than the maximum possible + * in this ELF file, or belongs in the reserved range: + * they will be caught by the `else` below and cause an + * error to be returned. This aborts the LLEXT's loading + * and prevents execution of improperly relocated code, + * which is dangerous. + * + * Note that the unsupported SHN_COMMON section is rejected + * as part of this check. Also note that SHN_ABS would be + * rejected as well, but we want to handle it properly: + * for this reason, this check must come AFTER handling + * the case where the symbol's section index is SHN_ABS! + * + * + * For regular symbols, the link address is obtained by + * adding st_value to the start address of the section + * in which the target symbol resides. + */ + link_addr = (uintptr_t)ext->mem[ldr->sect_map[sym.st_shndx]] + + sym.st_value; + } else { + LOG_ERR("rela section %d, entry %d: cannot apply relocation: " + "target symbol has unexpected section index %d (0x%X)", + i, j, sym.st_shndx, sym.st_shndx); + return -ENOEXEC; + } + + LOG_INF("writing relocation symbol %s type %zd sym %zd at addr 0x%lx " + "addr 0x%lx", + name, (size_t)ELF_R_TYPE(rel.r_info), (size_t)ELF_R_SYM(rel.r_info), + op_loc, link_addr); + + /* relocation */ + ret = arch_elf_relocate(&rel, op_loc, link_addr, name, + (uintptr_t)ext->mem[LLEXT_MEM_TEXT]); + if (ret != 0) { + return ret; + } + } + } + +#ifdef CONFIG_CACHE_MANAGEMENT + /* Make sure changes to ext sections are flushed to RAM */ + for (i = 0; i < LLEXT_MEM_COUNT; ++i) { + if (ext->mem[i]) { + sys_cache_data_flush_range(ext->mem[i], ext->mem_size[i]); + sys_cache_instr_invd_range(ext->mem[i], ext->mem_size[i]); + } + } +#endif + + return 0; +} diff --git a/subsys/llext/llext_load.c b/subsys/llext/llext_load.c new file mode 100644 index 0000000000000..287e6ff8edc9a --- /dev/null +++ b/subsys/llext/llext_load.c @@ -0,0 +1,644 @@ +/* + * Copyright (c) 2023 Intel Corporation + * Copyright (c) 2024 Arduino SA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include + +#include +LOG_MODULE_DECLARE(llext, CONFIG_LLEXT_LOG_LEVEL); + +#include + +#include "llext_priv.h" + +static const char ELF_MAGIC[] = {0x7f, 'E', 'L', 'F'}; + +elf_shdr_t *llext_section_by_name(struct llext_loader *ldr, const char *search_name) +{ + elf_shdr_t *shdr; + unsigned int i; + size_t pos; + + for (i = 0, pos = ldr->hdr.e_shoff; + i < ldr->hdr.e_shnum; + i++, pos += ldr->hdr.e_shentsize) { + shdr = llext_peek(ldr, pos); + if (!shdr) { + /* The peek() method isn't supported */ + return NULL; + } + + const char *name = llext_peek(ldr, + ldr->sects[LLEXT_MEM_SHSTRTAB].sh_offset + + shdr->sh_name); + + if (!strcmp(name, search_name)) { + return shdr; + } + } + + return NULL; +} + +/* + * Load basic ELF file data + */ + +static int llext_load_elf_data(struct llext_loader *ldr, struct llext *ext) +{ + int ret; + + /* read ELF header */ + + ret = llext_seek(ldr, 0); + if (ret != 0) { + LOG_ERR("Failed to seek for ELF header"); + return ret; + } + + ret = llext_read(ldr, &ldr->hdr, sizeof(ldr->hdr)); + if (ret != 0) { + LOG_ERR("Failed to read ELF header"); + return ret; + } + + /* check whether this is a valid ELF file */ + if (memcmp(ldr->hdr.e_ident, ELF_MAGIC, sizeof(ELF_MAGIC)) != 0) { + LOG_HEXDUMP_ERR(ldr->hdr.e_ident, 16, "Invalid ELF, magic does not match"); + return -EINVAL; + } + + switch (ldr->hdr.e_type) { + case ET_REL: + LOG_DBG("Loading relocatable ELF"); + break; + + case ET_DYN: + LOG_DBG("Loading shared ELF"); + break; + + default: + LOG_ERR("Unsupported ELF file type %x", ldr->hdr.e_type); + return -EINVAL; + } + + ldr->sect_cnt = ldr->hdr.e_shnum; + + memset(ldr->sects, 0, sizeof(ldr->sects)); + + size_t sect_map_sz = ldr->sect_cnt * sizeof(ldr->sect_map[0]); + + ldr->sect_map = llext_alloc(sect_map_sz); + if (!ldr->sect_map) { + LOG_ERR("Failed to allocate memory for section map, size %zu", sect_map_sz); + return -ENOMEM; + } + + memset(ldr->sect_map, 0, sect_map_sz); + ext->alloc_size += sect_map_sz; + + return 0; +} + +/* + * Find all relevant string and symbol tables + */ +static int llext_find_tables(struct llext_loader *ldr) +{ + int sect_cnt, i, ret; + size_t pos; + elf_shdr_t shdr; + + ldr->sects[LLEXT_MEM_SHSTRTAB] = + ldr->sects[LLEXT_MEM_STRTAB] = + ldr->sects[LLEXT_MEM_SYMTAB] = (elf_shdr_t){0}; + + /* Find symbol and string tables */ + for (i = 0, sect_cnt = 0, pos = ldr->hdr.e_shoff; + i < ldr->hdr.e_shnum && sect_cnt < 3; + i++, pos += ldr->hdr.e_shentsize) { + ret = llext_seek(ldr, pos); + if (ret != 0) { + LOG_ERR("failed seeking to position %zu\n", pos); + return ret; + } + + ret = llext_read(ldr, &shdr, sizeof(elf_shdr_t)); + if (ret != 0) { + LOG_ERR("failed reading section header at position %zu\n", pos); + return ret; + } + + LOG_DBG("section %d at %zx: name %d, type %d, flags %zx, " + "ofs %zx, addr %zx, size %zd", + i, pos, + shdr.sh_name, + shdr.sh_type, + (size_t)shdr.sh_flags, + (size_t)shdr.sh_offset, + (size_t)shdr.sh_addr, + (size_t)shdr.sh_size); + + switch (shdr.sh_type) { + case SHT_SYMTAB: + case SHT_DYNSYM: + LOG_DBG("symtab at %d", i); + ldr->sects[LLEXT_MEM_SYMTAB] = shdr; + ldr->sect_map[i] = LLEXT_MEM_SYMTAB; + sect_cnt++; + break; + case SHT_STRTAB: + if (ldr->hdr.e_shstrndx == i) { + LOG_DBG("shstrtab at %d", i); + ldr->sects[LLEXT_MEM_SHSTRTAB] = shdr; + ldr->sect_map[i] = LLEXT_MEM_SHSTRTAB; + } else { + LOG_DBG("strtab at %d", i); + ldr->sects[LLEXT_MEM_STRTAB] = shdr; + ldr->sect_map[i] = LLEXT_MEM_STRTAB; + } + sect_cnt++; + break; + default: + break; + } + } + + if (!ldr->sects[LLEXT_MEM_SHSTRTAB].sh_type || + !ldr->sects[LLEXT_MEM_STRTAB].sh_type || + !ldr->sects[LLEXT_MEM_SYMTAB].sh_type) { + LOG_ERR("Some sections are missing or present multiple times!"); + return -ENOENT; + } + + return 0; +} + +/* + * Maps the section indexes and copies special section headers for easier use + */ +static int llext_map_sections(struct llext_loader *ldr, struct llext *ext) +{ + int i, j, ret; + size_t pos; + elf_shdr_t shdr; + const char *name; + + for (i = 0, pos = ldr->hdr.e_shoff; + i < ldr->hdr.e_shnum; + i++, pos += ldr->hdr.e_shentsize) { + ret = llext_seek(ldr, pos); + if (ret != 0) { + return ret; + } + + ret = llext_read(ldr, &shdr, sizeof(elf_shdr_t)); + if (ret != 0) { + return ret; + } + + if ((shdr.sh_type != SHT_PROGBITS && shdr.sh_type != SHT_NOBITS) || + !(shdr.sh_flags & SHF_ALLOC) || + shdr.sh_size == 0) { + continue; + } + + name = llext_string(ldr, ext, LLEXT_MEM_SHSTRTAB, shdr.sh_name); + + /* Identify the section type by its flags */ + enum llext_mem mem_idx; + + switch (shdr.sh_type) { + case SHT_NOBITS: + mem_idx = LLEXT_MEM_BSS; + break; + case SHT_PROGBITS: + if (shdr.sh_flags & SHF_EXECINSTR) { + mem_idx = LLEXT_MEM_TEXT; + } else if (shdr.sh_flags & SHF_WRITE) { + mem_idx = LLEXT_MEM_DATA; + } else { + mem_idx = LLEXT_MEM_RODATA; + } + break; + default: + LOG_DBG("Not copied section %s", name); + continue; + } + + /* Special exception for .exported_sym */ + if (strcmp(name, ".exported_sym") == 0) { + mem_idx = LLEXT_MEM_EXPORT; + } + + LOG_DBG("section %d name %s maps to idx %d", i, name, mem_idx); + + ldr->sect_map[i] = mem_idx; + elf_shdr_t *sect = ldr->sects + mem_idx; + + if (sect->sh_type == SHT_NULL) { + /* First section of this type, copy all info */ + *sect = shdr; + } else { + /* Make sure the sections are compatible before merging */ + if (shdr.sh_flags != sect->sh_flags) { + LOG_ERR("Unsupported section flags for %s (mem %d)", + name, mem_idx); + return -ENOEXEC; + } + + if (mem_idx == LLEXT_MEM_BSS) { + /* SHT_NOBITS sections cannot be merged properly: + * as they use no space in the file, the logic + * below does not work; they must be treated as + * independent entities. + */ + LOG_ERR("Multiple SHT_NOBITS sections are not supported"); + return -ENOEXEC; + } + + if (ldr->hdr.e_type == ET_DYN) { + /* In shared objects, sh_addr is the VMA. Before + * merging these sections, make sure the delta + * in VMAs matches that of file offsets. + */ + if (shdr.sh_addr - sect->sh_addr != + shdr.sh_offset - sect->sh_offset) { + LOG_ERR("Incompatible section addresses " + "for %s (mem %d)", name, mem_idx); + return -ENOEXEC; + } + } + + /* + * Extend the current section to include the new one + * (overlaps are detected later) + */ + size_t address = MIN(sect->sh_addr, shdr.sh_addr); + size_t bot_ofs = MIN(sect->sh_offset, shdr.sh_offset); + size_t top_ofs = MAX(sect->sh_offset + sect->sh_size, + shdr.sh_offset + shdr.sh_size); + + sect->sh_addr = address; + sect->sh_offset = bot_ofs; + sect->sh_size = top_ofs - bot_ofs; + } + } + + /* + * Test that no computed range overlaps. This can happen if sections of + * different llext_mem type are interleaved in the ELF file or in VMAs. + */ + for (i = 0; i < LLEXT_MEM_COUNT; i++) { + for (j = i+1; j < LLEXT_MEM_COUNT; j++) { + elf_shdr_t *x = ldr->sects + i; + elf_shdr_t *y = ldr->sects + j; + + if (x->sh_type == SHT_NULL || x->sh_size == 0 || + y->sh_type == SHT_NULL || y->sh_size == 0) { + /* Skip empty sections */ + continue; + } + + if (ldr->hdr.e_type == ET_DYN) { + /* + * Test all merged VMA ranges for overlaps + */ + if ((x->sh_addr <= y->sh_addr && + x->sh_addr + x->sh_size > y->sh_addr) || + (y->sh_addr <= x->sh_addr && + y->sh_addr + y->sh_size > x->sh_addr)) { + LOG_ERR("VMA range %d (0x%zx +%zd) " + "overlaps with %d (0x%zx +%zd)", + i, (size_t)x->sh_addr, (size_t)x->sh_size, + j, (size_t)y->sh_addr, (size_t)y->sh_size); + return -ENOEXEC; + } + } + + /* + * Test file offsets. BSS sections store no + * data in the file and must not be included + * in checks to avoid false positives. + */ + if (i == LLEXT_MEM_BSS || j == LLEXT_MEM_BSS) { + continue; + } + + if ((x->sh_offset <= y->sh_offset && + x->sh_offset + x->sh_size > y->sh_offset) || + (y->sh_offset <= x->sh_offset && + y->sh_offset + y->sh_size > x->sh_offset)) { + LOG_ERR("ELF file range %d (0x%zx +%zd) " + "overlaps with %d (0x%zx +%zd)", + i, (size_t)x->sh_offset, (size_t)x->sh_size, + j, (size_t)y->sh_offset, (size_t)y->sh_size); + return -ENOEXEC; + } + } + } + + return 0; +} + +static int llext_count_export_syms(struct llext_loader *ldr, struct llext *ext) +{ + size_t ent_size = ldr->sects[LLEXT_MEM_SYMTAB].sh_entsize; + size_t syms_size = ldr->sects[LLEXT_MEM_SYMTAB].sh_size; + int sym_cnt = syms_size / sizeof(elf_sym_t); + const char *name; + elf_sym_t sym; + int i, ret; + size_t pos; + + LOG_DBG("symbol count %u", sym_cnt); + + ext->sym_tab.sym_cnt = 0; + for (i = 0, pos = ldr->sects[LLEXT_MEM_SYMTAB].sh_offset; + i < sym_cnt; + i++, pos += ent_size) { + if (!i) { + /* A dummy entry */ + continue; + } + + ret = llext_seek(ldr, pos); + if (ret != 0) { + return ret; + } + + ret = llext_read(ldr, &sym, ent_size); + if (ret != 0) { + return ret; + } + + uint32_t stt = ELF_ST_TYPE(sym.st_info); + uint32_t stb = ELF_ST_BIND(sym.st_info); + uint32_t sect = sym.st_shndx; + + name = llext_string(ldr, ext, LLEXT_MEM_STRTAB, sym.st_name); + + 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++; + } else { + LOG_DBG("unhandled symbol %d, name %s, type tag %d, bind %d, sect %d", + i, name, stt, stb, sect); + } + } + + return 0; +} + +static int llext_allocate_symtab(struct llext_loader *ldr, struct llext *ext) +{ + struct llext_symtable *sym_tab = &ext->sym_tab; + size_t syms_size = sym_tab->sym_cnt * sizeof(struct llext_symbol); + + sym_tab->syms = llext_alloc(syms_size); + if (!sym_tab->syms) { + return -ENOMEM; + } + memset(sym_tab->syms, 0, syms_size); + ext->alloc_size += syms_size; + + return 0; +} + +static int llext_export_symbols(struct llext_loader *ldr, struct llext *ext) +{ + elf_shdr_t *shdr = ldr->sects + LLEXT_MEM_EXPORT; + struct llext_symbol *sym; + unsigned int i; + + if (shdr->sh_size < sizeof(struct llext_symbol)) { + /* Not found, no symbols exported */ + return 0; + } + + struct llext_symtable *exp_tab = &ext->exp_tab; + + exp_tab->sym_cnt = shdr->sh_size / sizeof(struct llext_symbol); + exp_tab->syms = llext_alloc(exp_tab->sym_cnt * sizeof(struct llext_symbol)); + if (!exp_tab->syms) { + return -ENOMEM; + } + + for (i = 0, sym = ext->mem[LLEXT_MEM_EXPORT]; + i < exp_tab->sym_cnt; + i++, sym++) { + exp_tab->syms[i].name = sym->name; + exp_tab->syms[i].addr = sym->addr; + LOG_DBG("sym %p name %s in %p", sym->addr, sym->name, exp_tab->syms + i); + } + + return 0; +} + +static int llext_copy_symbols(struct llext_loader *ldr, struct llext *ext, + bool pre_located) +{ + size_t ent_size = ldr->sects[LLEXT_MEM_SYMTAB].sh_entsize; + size_t syms_size = ldr->sects[LLEXT_MEM_SYMTAB].sh_size; + int sym_cnt = syms_size / sizeof(elf_sym_t); + struct llext_symtable *sym_tab = &ext->sym_tab; + elf_sym_t sym; + int i, j, ret; + size_t pos; + + for (i = 0, pos = ldr->sects[LLEXT_MEM_SYMTAB].sh_offset, j = 0; + i < sym_cnt; + i++, pos += ent_size) { + if (!i) { + /* A dummy entry */ + continue; + } + + ret = llext_seek(ldr, pos); + if (ret != 0) { + return ret; + } + + ret = llext_read(ldr, &sym, ent_size); + if (ret != 0) { + return ret; + } + + uint32_t stt = ELF_ST_TYPE(sym.st_info); + uint32_t stb = ELF_ST_BIND(sym.st_info); + unsigned int sect = sym.st_shndx; + + if ((stt == STT_FUNC || stt == STT_OBJECT) && + stb == STB_GLOBAL && sect != SHN_UNDEF) { + const char *name = llext_string(ldr, ext, LLEXT_MEM_STRTAB, sym.st_name); + + __ASSERT(j <= sym_tab->sym_cnt, "Miscalculated symbol number %u\n", j); + + sym_tab->syms[j].name = name; + + uintptr_t section_addr; + void *base; + + if (sect < LLEXT_MEM_BSS) { + /* + * This is just a slight optimisation for cached + * sections, we could use the generic path below + * for all of them + */ + base = ext->mem[ldr->sect_map[sect]]; + section_addr = ldr->sects[ldr->sect_map[sect]].sh_addr; + } else { + /* Section header isn't stored, have to read it */ + size_t shdr_pos = ldr->hdr.e_shoff + sect * ldr->hdr.e_shentsize; + elf_shdr_t shdr; + + ret = llext_seek(ldr, shdr_pos); + if (ret != 0) { + LOG_ERR("failed seeking to position %zu\n", shdr_pos); + return ret; + } + + ret = llext_read(ldr, &shdr, sizeof(elf_shdr_t)); + if (ret != 0) { + LOG_ERR("failed reading section header at position %zu\n", + shdr_pos); + return ret; + } + + base = llext_peek(ldr, shdr.sh_offset); + if (!base) { + LOG_ERR("cannot handle arbitrary sections without .peek\n"); + return -EOPNOTSUPP; + } + + section_addr = shdr.sh_addr; + } + + if (pre_located) { + sym_tab->syms[j].addr = (uint8_t *)sym.st_value + + (ldr->hdr.e_type == ET_REL ? section_addr : 0); + } else { + sym_tab->syms[j].addr = (uint8_t *)base + sym.st_value - + (ldr->hdr.e_type == ET_REL ? 0 : section_addr); + } + + LOG_DBG("function symbol %d name %s addr %p", + j, name, sym_tab->syms[j].addr); + j++; + } + } + + return 0; +} + +/* + * Load a valid ELF as an extension + */ +int do_llext_load(struct llext_loader *ldr, struct llext *ext, + struct llext_load_param *ldr_parm) +{ + int ret; + + LOG_DBG("Loading ELF data..."); + ret = llext_load_elf_data(ldr, ext); + if (ret != 0) { + LOG_ERR("Failed to load basic ELF data, ret %d", ret); + goto out; + } + +#ifdef CONFIG_USERSPACE + ret = k_mem_domain_init(&ext->mem_domain, 0, NULL); + if (ret != 0) { + LOG_ERR("Failed to initialize extenion memory domain %d", ret); + goto out; + } +#endif + + LOG_DBG("Finding ELF tables..."); + ret = llext_find_tables(ldr); + if (ret != 0) { + LOG_ERR("Failed to find important ELF tables, ret %d", ret); + goto out; + } + + LOG_DBG("Allocate and copy strings..."); + ret = llext_copy_strings(ldr, ext); + if (ret != 0) { + LOG_ERR("Failed to copy ELF string sections, ret %d", ret); + goto out; + } + + LOG_DBG("Mapping ELF sections..."); + ret = llext_map_sections(ldr, ext); + if (ret != 0) { + LOG_ERR("Failed to map ELF sections, ret %d", ret); + goto out; + } + + LOG_DBG("Allocate and copy sections..."); + ret = llext_copy_sections(ldr, ext); + if (ret != 0) { + LOG_ERR("Failed to copy ELF sections, ret %d", ret); + goto out; + } + + LOG_DBG("Counting exported symbols..."); + ret = llext_count_export_syms(ldr, ext); + if (ret != 0) { + LOG_ERR("Failed to count exported ELF symbols, ret %d", ret); + goto out; + } + + LOG_DBG("Allocating memory for symbol table..."); + ret = llext_allocate_symtab(ldr, ext); + if (ret != 0) { + LOG_ERR("Failed to allocate extension symbol table, ret %d", ret); + goto out; + } + + LOG_DBG("Copying symbols..."); + ret = llext_copy_symbols(ldr, ext, ldr_parm ? ldr_parm->pre_located : false); + if (ret != 0) { + LOG_ERR("Failed to copy symbols, ret %d", ret); + goto out; + } + + LOG_DBG("Linking ELF..."); + ret = llext_link(ldr, ext, ldr_parm ? ldr_parm->relocate_local : true); + if (ret != 0) { + LOG_ERR("Failed to link, ret %d", ret); + goto out; + } + + ret = llext_export_symbols(ldr, ext); + if (ret != 0) { + LOG_ERR("Failed to export, ret %d", ret); + goto out; + } + +out: + llext_free(ldr->sect_map); + + if (ret != 0) { + LOG_DBG("Failed to load extension, freeing memory..."); + llext_free_sections(ext); + llext_free(ext->exp_tab.syms); + } else { + LOG_DBG("loaded module, .text at %p, .rodata at %p", ext->mem[LLEXT_MEM_TEXT], + ext->mem[LLEXT_MEM_RODATA]); + } + + ext->sym_tab.sym_cnt = 0; + llext_free(ext->sym_tab.syms); + ext->sym_tab.syms = NULL; + + return ret; +} diff --git a/subsys/llext/llext_priv.h b/subsys/llext/llext_priv.h index d699e6318498b..4098659c84f55 100644 --- a/subsys/llext/llext_priv.h +++ b/subsys/llext/llext_priv.h @@ -39,4 +39,25 @@ static inline void llext_free(void *ptr) k_heap_free(&llext_heap, ptr); } +/* + * ELF parsing (llext_load.c) + */ + +int do_llext_load(struct llext_loader *ldr, struct llext *ext, + struct llext_load_param *ldr_parm); + +elf_shdr_t *llext_section_by_name(struct llext_loader *ldr, const char *search_name); + +static inline const char *llext_string(struct llext_loader *ldr, struct llext *ext, + enum llext_mem mem_idx, unsigned int idx) +{ + return (char *)ext->mem[mem_idx] + idx; +} + +/* + * Relocation (llext_link.c) + */ + +int llext_link(struct llext_loader *ldr, struct llext *ext, bool do_local); + #endif /* ZEPHYR_SUBSYS_LLEXT_PRIV_H_ */ From 3ceed632f9c4f30a8993295645cc3f159af08a95 Mon Sep 17 00:00:00 2001 From: Reto Schneider Date: Fri, 10 May 2024 20:06:53 +0200 Subject: [PATCH 2047/2849] drivers: hwinfo: Prevent conflicts By sorting the lines alphabetically, conflicts can be reduced. Signed-off-by: Reto Schneider --- drivers/hwinfo/CMakeLists.txt | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/hwinfo/CMakeLists.txt b/drivers/hwinfo/CMakeLists.txt index 60707d59a6199..6730e60491f0a 100644 --- a/drivers/hwinfo/CMakeLists.txt +++ b/drivers/hwinfo/CMakeLists.txt @@ -8,6 +8,9 @@ zephyr_library_sources_ifdef(CONFIG_USERSPACE hwinfo_handlers.c) zephyr_library_sources_ifdef(CONFIG_HWINFO hwinfo_weak_impl.c) zephyr_library_sources_ifdef(CONFIG_HWINFO_SHELL hwinfo_shell.c) +# zephyr-keep-sorted-start +zephyr_library_sources_ifdef(CONFIG_HWINFO_AMBIQ hwinfo_ambiq.c) +zephyr_library_sources_ifdef(CONFIG_HWINFO_ANDES hwinfo_andes.c) zephyr_library_sources_ifdef(CONFIG_HWINFO_CC13XX_CC26XX hwinfo_cc13xx_cc26xx.c) zephyr_library_sources_ifdef(CONFIG_HWINFO_ESP32 hwinfo_esp32.c) zephyr_library_sources_ifdef(CONFIG_HWINFO_GECKO hwinfo_gecko.c) @@ -21,12 +24,11 @@ zephyr_library_sources_ifdef(CONFIG_HWINFO_MCUX_SYSCON hwinfo_mcux_syscon.c) zephyr_library_sources_ifdef(CONFIG_HWINFO_NRF hwinfo_nrf.c) zephyr_library_sources_ifdef(CONFIG_HWINFO_PSOC6 hwinfo_psoc6.c) zephyr_library_sources_ifdef(CONFIG_HWINFO_RPI_PICO hwinfo_rpi_pico.c) -zephyr_library_sources_ifdef(CONFIG_HWINFO_SAM_RSTC hwinfo_sam_rstc.c) +zephyr_library_sources_ifdef(CONFIG_HWINFO_RW61X hwinfo_rw61x.c) zephyr_library_sources_ifdef(CONFIG_HWINFO_SAM hwinfo_sam.c) zephyr_library_sources_ifdef(CONFIG_HWINFO_SAM0 hwinfo_sam0.c) zephyr_library_sources_ifdef(CONFIG_HWINFO_SAM4L hwinfo_sam4l.c) +zephyr_library_sources_ifdef(CONFIG_HWINFO_SAM_RSTC hwinfo_sam_rstc.c) 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) +# zephyr-keep-sorted-stop From 8f3989412f67ac847e62e6de46e88bbe667b33e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Chru=C5=9Bci=C5=84ski?= Date: Thu, 23 May 2024 11:03:40 +0200 Subject: [PATCH 2048/2849] testsuite: ztest: ztress: Add missing static keywords MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add static to local timers definition. Signed-off-by: Krzysztof Chruściński --- subsys/testsuite/ztest/src/ztress.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/subsys/testsuite/ztest/src/ztress.c b/subsys/testsuite/ztest/src/ztress.c index ce8b31a5a2d7c..eb7dbd22b6b7f 100644 --- a/subsys/testsuite/ztest/src/ztress.c +++ b/subsys/testsuite/ztest/src/ztress.c @@ -18,20 +18,20 @@ static bool cpu_sys_clock_ok; /* Timer used for adjusting contexts backoff time to get optimal CPU load. */ static void ctrl_timeout(struct k_timer *timer); -K_TIMER_DEFINE(ctrl_timer, ctrl_timeout, NULL); +static K_TIMER_DEFINE(ctrl_timer, ctrl_timeout, NULL); /* Timer used for reporting test progress. */ static void progress_timeout(struct k_timer *timer); -K_TIMER_DEFINE(progress_timer, progress_timeout, NULL); +static K_TIMER_DEFINE(progress_timer, progress_timeout, NULL); /* Timer used for higher priority context. */ static void ztress_timeout(struct k_timer *timer); -K_TIMER_DEFINE(ztress_timer, ztress_timeout, NULL); +static K_TIMER_DEFINE(ztress_timer, ztress_timeout, NULL); /* Timer handling test timeout which ends test prematurely. */ static k_timeout_t timeout; static void test_timeout(struct k_timer *timer); -K_TIMER_DEFINE(test_timer, test_timeout, NULL); +static K_TIMER_DEFINE(test_timer, test_timeout, NULL); static atomic_t active_cnt; static struct k_thread threads[CONFIG_ZTRESS_MAX_THREADS]; From 2c112ce5196dc7d18fafb03a0fb10dae5e7d7fb2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20Cab=C3=A9?= Date: Tue, 4 Jun 2024 18:09:27 +0200 Subject: [PATCH 2049/2849] doc: bluetooth: fix Sphinx C domain roles usage MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit use the proper types for referencing C elements from Bluetooth docs Signed-off-by: Benjamin Cabé --- doc/connectivity/bluetooth/api/mesh/blob_cli.rst | 2 +- doc/connectivity/bluetooth/api/mesh/dfu_srv.rst | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/connectivity/bluetooth/api/mesh/blob_cli.rst b/doc/connectivity/bluetooth/api/mesh/blob_cli.rst index b4193d5033472..0d533109830ad 100644 --- a/doc/connectivity/bluetooth/api/mesh/blob_cli.rst +++ b/doc/connectivity/bluetooth/api/mesh/blob_cli.rst @@ -33,7 +33,7 @@ Transfer context ================ Both the transfer capabilities retrieval procedure and the BLOB transfer uses an instance of a -:c:type:`bt_mesh_blob_cli_inputs` to determine how to perform the transfer. The BLOB Transfer Client +:c:struct:`bt_mesh_blob_cli_inputs` to determine how to perform the transfer. The BLOB Transfer Client Inputs structure must at least be initialized with a list of targets, an application key and a time to live (TTL) value before it is used in a procedure: diff --git a/doc/connectivity/bluetooth/api/mesh/dfu_srv.rst b/doc/connectivity/bluetooth/api/mesh/dfu_srv.rst index 105bdecb86cce..fdccbba639cce 100644 --- a/doc/connectivity/bluetooth/api/mesh/dfu_srv.rst +++ b/doc/connectivity/bluetooth/api/mesh/dfu_srv.rst @@ -45,7 +45,7 @@ firmware image metadata. The Firmware Update Server performs the transfer check :c:member:`check ` callback. The result of the transfer check is a pass/fail status return and the expected -:c:type:`bt_mesh_dfu_effect`. The DFU effect return parameter will be communicated back to the +:c:enum:`bt_mesh_dfu_effect`. The DFU effect return parameter will be communicated back to the Distributor, and should indicate what effect the firmware update will have on the mesh state of the device. From 3e349bf475e9213cff5b04656d6620385f7d50fe Mon Sep 17 00:00:00 2001 From: Ayush Singh Date: Wed, 5 Jun 2024 20:54:56 +0530 Subject: [PATCH 2050/2849] samples: blinky_pwm: fix overlay for beagleconnect_freedom - Add missing flags - Fixes https://github.com/zephyrproject-rtos/zephyr/pull/73628 Signed-off-by: Ayush Singh --- samples/basic/blinky_pwm/boards/beagleconnect_freedom.overlay | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/basic/blinky_pwm/boards/beagleconnect_freedom.overlay b/samples/basic/blinky_pwm/boards/beagleconnect_freedom.overlay index 1d8f708c712bf..a2aeeeefee29f 100644 --- a/samples/basic/blinky_pwm/boards/beagleconnect_freedom.overlay +++ b/samples/basic/blinky_pwm/boards/beagleconnect_freedom.overlay @@ -12,7 +12,7 @@ pwmleds { compatible = "pwm-leds"; pwm_led0: pwm_led_0 { - pwms = <&pwm0 0 255>; + pwms = <&pwm0 0 255 PWM_POLARITY_NORMAL>; label = "PWM MB1"; }; }; From 87379793f5c9576a61cb9ec093388e7942972e5d Mon Sep 17 00:00:00 2001 From: Fabio Baltieri Date: Thu, 6 Jun 2024 15:18:46 +0100 Subject: [PATCH 2051/2849] posix: add a missing include prefix Add the missing prefix so this builds with CONFIG_LEGACY_GENERATED_INCLUDE_PATH=n Signed-off-by: Fabio Baltieri --- include/zephyr/posix/posix_features.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/zephyr/posix/posix_features.h b/include/zephyr/posix/posix_features.h index ed948158e7f91..4c7a3d98e30c5 100644 --- a/include/zephyr/posix/posix_features.h +++ b/include/zephyr/posix/posix_features.h @@ -8,7 +8,7 @@ #ifndef INCLUDE_ZEPHYR_POSIX_POSIX_FEATURES_H_ #define INCLUDE_ZEPHYR_POSIX_POSIX_FEATURES_H_ -#include /* CONFIG_* */ +#include /* CONFIG_* */ #include /* COND_CODE_1() */ /* From 3c41820d065c70c88e978141ec7e555e4fd248c9 Mon Sep 17 00:00:00 2001 From: cyliang tw Date: Fri, 7 Jun 2024 20:40:04 +0800 Subject: [PATCH 2052/2849] manifest: update hal_nuvoton revision To fix redefined warnings of TRUE/FALSE. Signed-off-by: cyliang tw --- west.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/west.yml b/west.yml index e148264fb1584..0252d081fd4e2 100644 --- a/west.yml +++ b/west.yml @@ -193,7 +193,7 @@ manifest: groups: - hal - name: hal_nuvoton - revision: ab342e6915bf7bff2203a20985754f6dbdb5343d + revision: 466c3eed9c98453fb23953bf0e0427fea01924be path: modules/hal/nuvoton groups: - hal From 3386a43a516e32592246ae6ecd9575ca20f33d5d Mon Sep 17 00:00:00 2001 From: Daniel DeGrasse Date: Fri, 31 May 2024 19:16:52 +0000 Subject: [PATCH 2053/2849] disk_access: reference count initialization calls for disks Reference count initialization calls for disks. This changes the behavior of the disk_access_init() function, such that disks will no longer be initialized again if the first disk access init call succeeds. Disk access is reference counted in preparation for supporting disk de-initialization, where a balanced number of disk de-initialization calls with disk initialization calls will de-initialize the disk. Also, remove code in disk drivers that was already checking against duplicate disk_access_init() calls. Signed-off-by: Daniel DeGrasse --- drivers/disk/mmc_subsys.c | 5 ----- drivers/disk/sdmmc_stm32.c | 4 ---- drivers/disk/sdmmc_subsys.c | 5 ----- include/zephyr/drivers/disk.h | 2 ++ include/zephyr/storage/disk_access.h | 3 +++ subsys/disk/disk_access.c | 20 +++++++++++++++++--- 6 files changed, 22 insertions(+), 17 deletions(-) diff --git a/drivers/disk/mmc_subsys.c b/drivers/disk/mmc_subsys.c index 455d56818d3c1..74276502d8347 100644 --- a/drivers/disk/mmc_subsys.c +++ b/drivers/disk/mmc_subsys.c @@ -38,11 +38,6 @@ static int disk_mmc_access_init(struct disk_info *disk) struct mmc_data *data = dev->data; int ret; - if (data->status == SD_OK) { - /* Called twice, don't reinit */ - return 0; - } - ret = sd_init(cfg->host_controller, &data->card); if (ret) { data->status = SD_ERROR; diff --git a/drivers/disk/sdmmc_stm32.c b/drivers/disk/sdmmc_stm32.c index a9cda286e3af6..6f301d8afae0e 100644 --- a/drivers/disk/sdmmc_stm32.c +++ b/drivers/disk/sdmmc_stm32.c @@ -265,10 +265,6 @@ static int stm32_sdmmc_access_init(struct disk_info *disk) struct stm32_sdmmc_priv *priv = dev->data; int err; - if (priv->status == DISK_STATUS_OK) { - return 0; - } - if (priv->status == DISK_STATUS_NOMEDIA) { return -ENODEV; } diff --git a/drivers/disk/sdmmc_subsys.c b/drivers/disk/sdmmc_subsys.c index 863755841dad3..2d6d17c3e8ebb 100644 --- a/drivers/disk/sdmmc_subsys.c +++ b/drivers/disk/sdmmc_subsys.c @@ -37,11 +37,6 @@ static int disk_sdmmc_access_init(struct disk_info *disk) struct sdmmc_data *data = dev->data; int ret; - if (data->status == SD_OK) { - /* Called twice, don't reinit */ - return 0; - } - if (!sd_is_card_present(cfg->host_controller)) { return DISK_STATUS_NOMEDIA; } diff --git a/include/zephyr/drivers/disk.h b/include/zephyr/drivers/disk.h index 623b65118b3be..27b7b5c41619c 100644 --- a/include/zephyr/drivers/disk.h +++ b/include/zephyr/drivers/disk.h @@ -77,6 +77,8 @@ struct disk_info { const struct disk_operations *ops; /** Device associated to this disk */ const struct device *dev; + /** Internally used disk reference count */ + uint16_t refcnt; }; /** diff --git a/include/zephyr/storage/disk_access.h b/include/zephyr/storage/disk_access.h index 53774e7666edc..9b86b4146e86e 100644 --- a/include/zephyr/storage/disk_access.h +++ b/include/zephyr/storage/disk_access.h @@ -41,6 +41,9 @@ extern "C" { * This call is made by the consumer before doing any IO calls so that the * disk or the backing device can do any initialization. * + * Disk initialization is reference counted, so only the first successful call + * to initialize a uninitialized disk will actually initialize the disk + * * @param[in] pdrv Disk name * * @return 0 on success, negative errno code on fail diff --git a/subsys/disk/disk_access.c b/subsys/disk/disk_access.c index e69bc4946076e..c9909dbea9cef 100644 --- a/subsys/disk/disk_access.c +++ b/subsys/disk/disk_access.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2018 Intel Corporation. + * Copyright 2024 NXP * * SPDX-License-Identifier: Apache-2.0 */ @@ -58,9 +59,19 @@ int disk_access_init(const char *pdrv) struct disk_info *disk = disk_access_get_di(pdrv); int rc = -EINVAL; - if ((disk != NULL) && (disk->ops != NULL) && - (disk->ops->init != NULL)) { - rc = disk->ops->init(disk); + if ((disk != NULL) && (disk->refcnt == 0U)) { + /* Disk has not been initialized, start it */ + if ((disk->ops != NULL) && (disk->ops->init != NULL)) { + rc = disk->ops->init(disk); + if (rc == 0) { + /* Increment reference count */ + disk->refcnt++; + } + } + } else if ((disk != NULL) && (disk->refcnt < UINT16_MAX)) { + /* Disk reference count is nonzero, simply increment it */ + disk->refcnt++; + rc = 0; } return rc; @@ -137,6 +148,9 @@ int disk_access_register(struct disk_info *disk) goto reg_err; } + /* Initialize reference count to zero */ + disk->refcnt = 0U; + /* append to the disk list */ sys_dlist_append(&disk_access_list, &disk->node); LOG_DBG("disk interface(%s) registered", disk->name); From fb2d5c338b0ba513d39f541b50fc1f22ca30b5f9 Mon Sep 17 00:00:00 2001 From: Daniel DeGrasse Date: Fri, 31 May 2024 19:34:09 +0000 Subject: [PATCH 2054/2849] drivers: disk: add DISK_IOCTL_CTRL_INIT macro to initialize a disk Add DISK_IOCTL_CTRL_INIT IOCTL to initialize a disk. This IOCTL is intended to replace disk_access_init() for new applications, but disk_access_init() is kept for legacy compatibility. The INIT IOCTL is added to better match the path that will be used for disk de-initialization. Like the disk_access_init() calls, DISK_IOCTL_CTRL_INIT calls are reference counted Signed-off-by: Daniel DeGrasse --- drivers/disk/flashdisk.c | 2 ++ drivers/disk/loopback_disk.c | 10 ++++++---- drivers/disk/mmc_subsys.c | 9 ++++++++- drivers/disk/nvme/nvme_disk.c | 13 ++++++++----- drivers/disk/ramdisk.c | 12 +++++++----- drivers/disk/sdmmc_stm32.c | 2 ++ drivers/disk/sdmmc_subsys.c | 8 +++++++- include/zephyr/drivers/disk.h | 6 ++++++ include/zephyr/storage/disk_access.h | 4 +++- subsys/disk/disk_access.c | 18 +++++++++++++++++- 10 files changed, 66 insertions(+), 18 deletions(-) diff --git a/drivers/disk/flashdisk.c b/drivers/disk/flashdisk.c index 4c9d65ee7a634..79c788f2a5c73 100644 --- a/drivers/disk/flashdisk.c +++ b/drivers/disk/flashdisk.c @@ -451,6 +451,8 @@ static int disk_flash_access_ioctl(struct disk_info *disk, uint8_t cmd, void *bu *(uint32_t *)buff = ctx->page_size / ctx->sector_size; k_mutex_unlock(&ctx->lock); return 0; + case DISK_IOCTL_CTRL_INIT: + return disk_flash_access_init(disk); default: break; } diff --git a/drivers/disk/loopback_disk.c b/drivers/disk/loopback_disk.c index 50b7beeaabc40..69c5dbe7ed6ee 100644 --- a/drivers/disk/loopback_disk.c +++ b/drivers/disk/loopback_disk.c @@ -22,10 +22,6 @@ static inline struct loopback_disk_access *get_ctx(struct disk_info *info) return CONTAINER_OF(info, struct loopback_disk_access, info); } -static int loopback_disk_access_init(struct disk_info *disk) -{ - return 0; -} static int loopback_disk_access_status(struct disk_info *disk) { return DISK_STATUS_OK; @@ -113,10 +109,16 @@ static int loopback_disk_access_ioctl(struct disk_info *disk, uint8_t cmd, void } case DISK_IOCTL_CTRL_SYNC: return fs_sync(&ctx->file); + case DISK_IOCTL_CTRL_INIT: + return 0; default: return -ENOTSUP; } } +static int loopback_disk_access_init(struct disk_info *disk) +{ + return loopback_disk_access_ioctl(disk, DISK_IOCTL_CTRL_INIT, NULL); +} static const struct disk_operations loopback_disk_operations = { .init = loopback_disk_access_init, diff --git a/drivers/disk/mmc_subsys.c b/drivers/disk/mmc_subsys.c index 74276502d8347..d131736e4095c 100644 --- a/drivers/disk/mmc_subsys.c +++ b/drivers/disk/mmc_subsys.c @@ -82,7 +82,14 @@ static int disk_mmc_access_ioctl(struct disk_info *disk, uint8_t cmd, void *buf) const struct device *dev = disk->dev; struct mmc_data *data = dev->data; - return mmc_ioctl(&data->card, cmd, buf); + switch (cmd) { + case DISK_IOCTL_CTRL_INIT: + return disk_mmc_access_init(disk); + default: + return mmc_ioctl(&data->card, cmd, buf); + } + + return 0; } static const struct disk_operations mmc_disk_ops = { diff --git a/drivers/disk/nvme/nvme_disk.c b/drivers/disk/nvme/nvme_disk.c index 9b46e0270d7ac..bbc2ca75ceb4d 100644 --- a/drivers/disk/nvme/nvme_disk.c +++ b/drivers/disk/nvme/nvme_disk.c @@ -11,11 +11,6 @@ LOG_MODULE_DECLARE(nvme, CONFIG_NVME_LOG_LEVEL); #include "nvme.h" -static int nvme_disk_init(struct disk_info *disk) -{ - return 0; -} - static int nvme_disk_status(struct disk_info *disk) { return 0; @@ -186,6 +181,9 @@ static int nvme_disk_ioctl(struct disk_info *disk, uint8_t cmd, void *buff) case DISK_IOCTL_CTRL_SYNC: ret = nvme_disk_flush(ns); break; + case DISK_IOCTL_CTRL_INIT: + ret = 0; + break; default: ret = -EINVAL; } @@ -194,6 +192,11 @@ static int nvme_disk_ioctl(struct disk_info *disk, uint8_t cmd, void *buff) return ret; } +static int nvme_disk_init(struct disk_info *disk) +{ + return nvme_disk_ioctl(disk, DISK_IOCTL_CTRL_INIT, NULL); +} + static const struct disk_operations nvme_disk_ops = { .init = nvme_disk_init, .status = nvme_disk_status, diff --git a/drivers/disk/ramdisk.c b/drivers/disk/ramdisk.c index 1d1fcc46a0d2f..c076ab3256d24 100644 --- a/drivers/disk/ramdisk.c +++ b/drivers/disk/ramdisk.c @@ -41,11 +41,6 @@ static int disk_ram_access_status(struct disk_info *disk) return DISK_STATUS_OK; } -static int disk_ram_access_init(struct disk_info *disk) -{ - return 0; -} - static int disk_ram_access_read(struct disk_info *disk, uint8_t *buff, uint32_t sector, uint32_t count) { @@ -98,6 +93,8 @@ static int disk_ram_access_ioctl(struct disk_info *disk, uint8_t cmd, void *buff case DISK_IOCTL_GET_ERASE_BLOCK_SZ: *(uint32_t *)buff = 1U; break; + case DISK_IOCTL_CTRL_INIT: + break; default: return -EINVAL; } @@ -105,6 +102,11 @@ static int disk_ram_access_ioctl(struct disk_info *disk, uint8_t cmd, void *buff return 0; } +static int disk_ram_access_init(struct disk_info *disk) +{ + return disk_ram_access_ioctl(disk, DISK_IOCTL_CTRL_INIT, NULL); +} + static int disk_ram_init(const struct device *dev) { struct disk_info *info = dev->data; diff --git a/drivers/disk/sdmmc_stm32.c b/drivers/disk/sdmmc_stm32.c index 6f301d8afae0e..05f67e621eec9 100644 --- a/drivers/disk/sdmmc_stm32.c +++ b/drivers/disk/sdmmc_stm32.c @@ -481,6 +481,8 @@ static int stm32_sdmmc_access_ioctl(struct disk_info *disk, uint8_t cmd, case DISK_IOCTL_CTRL_SYNC: /* we use a blocking API, so nothing to do for sync */ break; + case DISK_IOCTL_CTRL_INIT: + return stm32_sdmmc_access_init(disk); default: return -EINVAL; } diff --git a/drivers/disk/sdmmc_subsys.c b/drivers/disk/sdmmc_subsys.c index 2d6d17c3e8ebb..0640f0f9f64ad 100644 --- a/drivers/disk/sdmmc_subsys.c +++ b/drivers/disk/sdmmc_subsys.c @@ -89,7 +89,13 @@ static int disk_sdmmc_access_ioctl(struct disk_info *disk, uint8_t cmd, void *bu const struct device *dev = disk->dev; struct sdmmc_data *data = dev->data; - return sdmmc_ioctl(&data->card, cmd, buf); + case DISK_IOCTL_CTRL_INIT: + return disk_sdmmc_access_init(disk); + default: + return sdmmc_ioctl(&data->card, cmd, buf); + } + + return 0; } static const struct disk_operations sdmmc_disk_ops = { diff --git a/include/zephyr/drivers/disk.h b/include/zephyr/drivers/disk.h index 27b7b5c41619c..59be2d13dce47 100644 --- a/include/zephyr/drivers/disk.h +++ b/include/zephyr/drivers/disk.h @@ -49,6 +49,12 @@ extern "C" { #define DISK_IOCTL_GET_ERASE_BLOCK_SZ 4 /** Commit any cached read/writes to disk */ #define DISK_IOCTL_CTRL_SYNC 5 +/** Initialize the disk. This IOCTL must be issued before the disk can be + * used for I/O. It is reference counted, so only the first successful + * invocation of this macro on an uninitialized disk will initialize the IO + * device + */ +#define DISK_IOCTL_CTRL_INIT 6 /** * @brief Possible return bitmasks for disk_status() diff --git a/include/zephyr/storage/disk_access.h b/include/zephyr/storage/disk_access.h index 9b86b4146e86e..e96ffc9b192e1 100644 --- a/include/zephyr/storage/disk_access.h +++ b/include/zephyr/storage/disk_access.h @@ -39,7 +39,9 @@ extern "C" { * @brief perform any initialization * * This call is made by the consumer before doing any IO calls so that the - * disk or the backing device can do any initialization. + * disk or the backing device can do any initialization. Although still + * supported for legacy compatibility, users should instead call + * @ref disk_access_ioctl with the IOCTL @ref DISK_IOCTL_CTRL_INIT. * * Disk initialization is reference counted, so only the first successful call * to initialize a uninitialized disk will actually initialize the disk diff --git a/subsys/disk/disk_access.c b/subsys/disk/disk_access.c index c9909dbea9cef..1aa1fecf2f131 100644 --- a/subsys/disk/disk_access.c +++ b/subsys/disk/disk_access.c @@ -125,7 +125,23 @@ int disk_access_ioctl(const char *pdrv, uint8_t cmd, void *buf) if ((disk != NULL) && (disk->ops != NULL) && (disk->ops->ioctl != NULL)) { - rc = disk->ops->ioctl(disk, cmd, buf); + switch (cmd) { + case DISK_IOCTL_CTRL_INIT: + if (disk->refcnt == 0U) { + rc = disk->ops->ioctl(disk, cmd, buf); + if (rc == 0) { + disk->refcnt++; + } + } else if (disk->refcnt < UINT16_MAX) { + disk->refcnt++; + rc = 0; + } else { + LOG_ERR("Disk reference count at max value"); + } + break; + default: + rc = disk->ops->ioctl(disk, cmd, buf); + } } return rc; From d18cbb60b2bff15e5fe318eac64d77c60f7baa22 Mon Sep 17 00:00:00 2001 From: Daniel DeGrasse Date: Tue, 14 May 2024 14:33:49 -0500 Subject: [PATCH 2055/2849] drivers: disk: add DISK_IOCTL_CTRL_DEINIT command to supported IOCTLs Add DISK_IOCTL_CTRL_DEINIT ioctl command to disk subsystem. When disk_access_ioctl() is called with this command, the disk will be de-initialized. After this IOCTL completes, the disk can safely be reinitialized. Fixes #60628 Signed-off-by: Daniel DeGrasse --- drivers/disk/flashdisk.c | 1 + drivers/disk/loopback_disk.c | 1 + drivers/disk/mmc_subsys.c | 7 +++++++ drivers/disk/nvme/nvme_disk.c | 1 + drivers/disk/ramdisk.c | 1 + drivers/disk/sdmmc_stm32.c | 12 +++++++++--- drivers/disk/sdmmc_subsys.c | 8 ++++++++ include/zephyr/drivers/disk.h | 12 ++++++++++++ include/zephyr/storage/disk_access.h | 3 ++- subsys/disk/disk_access.c | 18 ++++++++++++++++++ 10 files changed, 60 insertions(+), 4 deletions(-) diff --git a/drivers/disk/flashdisk.c b/drivers/disk/flashdisk.c index 79c788f2a5c73..6b71ea993c21e 100644 --- a/drivers/disk/flashdisk.c +++ b/drivers/disk/flashdisk.c @@ -435,6 +435,7 @@ static int disk_flash_access_ioctl(struct disk_info *disk, uint8_t cmd, void *bu ctx = CONTAINER_OF(disk, struct flashdisk_data, info); switch (cmd) { + case DISK_IOCTL_CTRL_DEINIT: case DISK_IOCTL_CTRL_SYNC: k_mutex_lock(&ctx->lock, K_FOREVER); rc = flashdisk_cache_commit(ctx); diff --git a/drivers/disk/loopback_disk.c b/drivers/disk/loopback_disk.c index 69c5dbe7ed6ee..c7f587b0c1955 100644 --- a/drivers/disk/loopback_disk.c +++ b/drivers/disk/loopback_disk.c @@ -107,6 +107,7 @@ static int loopback_disk_access_ioctl(struct disk_info *disk, uint8_t cmd, void *(uint32_t *)buff = LOOPBACK_SECTOR_SIZE; return 0; } + case DISK_IOCTL_CTRL_DEINIT: case DISK_IOCTL_CTRL_SYNC: return fs_sync(&ctx->file); case DISK_IOCTL_CTRL_INIT: diff --git a/drivers/disk/mmc_subsys.c b/drivers/disk/mmc_subsys.c index d131736e4095c..c595c0edb8a7e 100644 --- a/drivers/disk/mmc_subsys.c +++ b/drivers/disk/mmc_subsys.c @@ -85,6 +85,13 @@ static int disk_mmc_access_ioctl(struct disk_info *disk, uint8_t cmd, void *buf) switch (cmd) { case DISK_IOCTL_CTRL_INIT: return disk_mmc_access_init(disk); + case DISK_IOCTL_CTRL_DEINIT: + mmc_ioctl(&data->card, DISK_IOCTL_CTRL_SYNC, NULL); + /* sd_init() will toggle power to MMC, so we can just mark + * disk as uninitialized + */ + data->status = SD_UNINIT; + return 0; default: return mmc_ioctl(&data->card, cmd, buf); } diff --git a/drivers/disk/nvme/nvme_disk.c b/drivers/disk/nvme/nvme_disk.c index bbc2ca75ceb4d..5d1e18f6b7264 100644 --- a/drivers/disk/nvme/nvme_disk.c +++ b/drivers/disk/nvme/nvme_disk.c @@ -178,6 +178,7 @@ static int nvme_disk_ioctl(struct disk_info *disk, uint8_t cmd, void *buff) *(uint32_t *)buff = nvme_namespace_get_sector_size(ns); break; + case DISK_IOCTL_CTRL_DEINIT: case DISK_IOCTL_CTRL_SYNC: ret = nvme_disk_flush(ns); break; diff --git a/drivers/disk/ramdisk.c b/drivers/disk/ramdisk.c index c076ab3256d24..d4da37ea9d9d4 100644 --- a/drivers/disk/ramdisk.c +++ b/drivers/disk/ramdisk.c @@ -94,6 +94,7 @@ static int disk_ram_access_ioctl(struct disk_info *disk, uint8_t cmd, void *buff *(uint32_t *)buff = 1U; break; case DISK_IOCTL_CTRL_INIT: + case DISK_IOCTL_CTRL_DEINIT: break; default: return -EINVAL; diff --git a/drivers/disk/sdmmc_stm32.c b/drivers/disk/sdmmc_stm32.c index 05f67e621eec9..a344bb9d19235 100644 --- a/drivers/disk/sdmmc_stm32.c +++ b/drivers/disk/sdmmc_stm32.c @@ -307,14 +307,18 @@ static int stm32_sdmmc_access_init(struct disk_info *disk) return 0; } -#if !defined(CONFIG_SDMMC_STM32_EMMC) -static void stm32_sdmmc_access_deinit(struct stm32_sdmmc_priv *priv) +static int stm32_sdmmc_access_deinit(struct stm32_sdmmc_priv *priv) { +#if defined(CONFIG_SDMMC_STM32_EMMC) + HAL_MMC_DeInit(&priv->hsd); +#else HAL_SD_DeInit(&priv->hsd); stm32_sdmmc_clock_disable(priv); -} #endif + priv->status = DISK_STATUS_UNINIT; + return 0; +} static int stm32_sdmmc_access_status(struct disk_info *disk) { @@ -483,6 +487,8 @@ static int stm32_sdmmc_access_ioctl(struct disk_info *disk, uint8_t cmd, break; case DISK_IOCTL_CTRL_INIT: return stm32_sdmmc_access_init(disk); + case DISK_IOCTL_CTRL_DEINIT: + return stm32_sdmmc_access_deinit(priv); default: return -EINVAL; } diff --git a/drivers/disk/sdmmc_subsys.c b/drivers/disk/sdmmc_subsys.c index 0640f0f9f64ad..e2511d1b1007a 100644 --- a/drivers/disk/sdmmc_subsys.c +++ b/drivers/disk/sdmmc_subsys.c @@ -89,8 +89,16 @@ static int disk_sdmmc_access_ioctl(struct disk_info *disk, uint8_t cmd, void *bu const struct device *dev = disk->dev; struct sdmmc_data *data = dev->data; + switch (cmd) { case DISK_IOCTL_CTRL_INIT: return disk_sdmmc_access_init(disk); + case DISK_IOCTL_CTRL_DEINIT: + sdmmc_ioctl(&data->card, DISK_IOCTL_CTRL_SYNC, NULL); + /* sd_init() will toggle power to SDMMC, so we can just mark + * disk as uninitialized + */ + data->status = SD_UNINIT; + return 0; default: return sdmmc_ioctl(&data->card, cmd, buf); } diff --git a/include/zephyr/drivers/disk.h b/include/zephyr/drivers/disk.h index 59be2d13dce47..c248ccd93db3c 100644 --- a/include/zephyr/drivers/disk.h +++ b/include/zephyr/drivers/disk.h @@ -55,6 +55,18 @@ extern "C" { * device */ #define DISK_IOCTL_CTRL_INIT 6 +/** Deinitialize the disk. This IOCTL can be used to de-initialize the disk, + * enabling it to be removed from the system if the disk is hot-pluggable. + * Disk usage is reference counted, so for a given disk the + * `DISK_IOCTL_CTRL_DEINIT` IOCTL must be issued as many times as the + * `DISK_IOCTL_CTRL_INIT` IOCTL was issued in order to de-initialize it. + * + * This macro optionally accepts a pointer to a boolean as the `buf` parameter, + * which if true indicates the disk should be forcibly stopped, ignoring all + * reference counts. The disk driver must report success if a forced stop is + * requested, but this operation is inherently unsafe. + */ +#define DISK_IOCTL_CTRL_DEINIT 7 /** * @brief Possible return bitmasks for disk_status() diff --git a/include/zephyr/storage/disk_access.h b/include/zephyr/storage/disk_access.h index e96ffc9b192e1..a5ce72dd5bfb3 100644 --- a/include/zephyr/storage/disk_access.h +++ b/include/zephyr/storage/disk_access.h @@ -44,7 +44,8 @@ extern "C" { * @ref disk_access_ioctl with the IOCTL @ref DISK_IOCTL_CTRL_INIT. * * Disk initialization is reference counted, so only the first successful call - * to initialize a uninitialized disk will actually initialize the disk + * to initialize a uninitialized (or previously de-initialized) disk will + * actually initialize the disk * * @param[in] pdrv Disk name * diff --git a/subsys/disk/disk_access.c b/subsys/disk/disk_access.c index 1aa1fecf2f131..4f1169e702203 100644 --- a/subsys/disk/disk_access.c +++ b/subsys/disk/disk_access.c @@ -139,6 +139,24 @@ int disk_access_ioctl(const char *pdrv, uint8_t cmd, void *buf) LOG_ERR("Disk reference count at max value"); } break; + case DISK_IOCTL_CTRL_DEINIT: + if ((buf != NULL) && (*((bool *)buf))) { + /* Force deinit disk */ + disk->refcnt = 0U; + disk->ops->ioctl(disk, cmd, buf); + rc = 0; + } else if (disk->refcnt == 1U) { + rc = disk->ops->ioctl(disk, cmd, buf); + if (rc == 0) { + disk->refcnt--; + } + } else if (disk->refcnt > 0) { + disk->refcnt--; + rc = 0; + } else { + LOG_WRN("Disk is already deinitialized"); + } + break; default: rc = disk->ops->ioctl(disk, cmd, buf); } From 93ebf1c48f842f89d75cd2844d6ca2a58dd21dfb Mon Sep 17 00:00:00 2001 From: Daniel DeGrasse Date: Fri, 24 May 2024 12:33:10 -0500 Subject: [PATCH 2056/2849] doc: services: disk_access: add documentation for INIT/DEINIT IOCTLs Add documentation for disk INIT/DEINIT IOCTLs to the disk access API. Signed-off-by: Daniel DeGrasse --- doc/services/storage/disk/access.rst | 38 +++++++++++++++++++++++----- 1 file changed, 32 insertions(+), 6 deletions(-) diff --git a/doc/services/storage/disk/access.rst b/doc/services/storage/disk/access.rst index db06e87e5c07e..7cc5fe12f5419 100644 --- a/doc/services/storage/disk/access.rst +++ b/doc/services/storage/disk/access.rst @@ -8,6 +8,35 @@ Overview The disk access API provides access to storage devices. +Initializing Disks +****************** + +Since many disk devices (such as SD cards) are hotpluggable, the disk access +API provides IOCTLs to initialize and de-initialize the disk. They are +as follows: + +* :c:macro:`DISK_IOCTL_CTRL_INIT`: Initialize the disk. Must be called before + additional I/O operations can be run on the disk device. Equivalent to + calling the legacy function :c:func:`disk_access_init`. + +* :c:macro:`DISK_IOCTL_CTRL_DEINIT`: De-initialize the disk. Once this IOCTL + is issued, the :c:macro:`DISK_IOCTL_CTRL_INIT` must be issued before + the disk can be used for addition I/O operations. + +Init/deinit IOCTL calls are balanced, so a disk will not de-initialize until +an equal number of deinit IOCTLs have been issued as init IOCTLs. + +It is also possible to force a disk de-initialization by passing a +pointer to a boolean set to ``true`` as a parameter to the +:c:macro:`DISK_IOCTL_CTRL_DEINIT` IOCTL. This is an unsafe operation which +each disk driver may handle differently, but it will always return +a value indicating success. + +Note that de-initializing a disk is a low level operation- typically the +de-initialization and initialization calls should be left to the filesystem +implementation, and the user application should not need to manually +de-initialize the disk and can instead call :c:func:`fs_unmount` + SD Card support *************** @@ -16,12 +45,9 @@ SD cards via SPI. These drivers use disk driver interface and a file system can access the SD cards via disk access API. Both standard and high-capacity SD cards are supported. -.. note:: The system does not support inserting or removing cards while the - system is running. The cards must be present at boot and must not be - removed. This may be fixed in future releases. - - FAT filesystems are not power safe so the filesystem may become - corrupted if power is lost or if the card is removed. +.. note:: FAT filesystems are not power safe so the filesystem may become + corrupted if power is lost or if the card is removed without unmounting + the filesystem SD Memory Card subsystem ======================== From 7981ea0056a6b34c7ccbeab2dab01818b1d93c9b Mon Sep 17 00:00:00 2001 From: Daniel DeGrasse Date: Tue, 14 May 2024 14:46:20 -0500 Subject: [PATCH 2057/2849] fs: fat_fs: make IOCTL call to de-initialize disk in fatfs_unmount() Make call to de-initialize disk in fatfs_unmount(). This will permit the disk to be reinitialized when it is mounted with fatfs_mount(). Signed-off-by: Daniel DeGrasse --- modules/fatfs/zfs_diskio.c | 31 +++++++++++++++++++++++++------ modules/fatfs/zfs_diskio.h | 22 ++++++++++++++++++++++ subsys/fs/fat_fs.c | 37 ++++++++++++++++++++++++++++++++++++- 3 files changed, 83 insertions(+), 7 deletions(-) create mode 100644 modules/fatfs/zfs_diskio.h diff --git a/modules/fatfs/zfs_diskio.c b/modules/fatfs/zfs_diskio.c index 7a5061f15b6e4..2b0fa742e711e 100644 --- a/modules/fatfs/zfs_diskio.c +++ b/modules/fatfs/zfs_diskio.c @@ -1,6 +1,7 @@ /* * Copyright (c) 2018-2021 Zephyr contributors * Copyright (c) 2022 Nordic Semiconductor ASA + * Copyright 2024 NXP * * SPDX-License-Identifier: Apache-2.0 */ @@ -12,6 +13,7 @@ */ #include #include /* FatFs lower layer API */ +#include /* Zephyr specific FatFS API */ #include static const char * const pdrv_str[] = {FF_VOLUME_STRS}; @@ -31,13 +33,9 @@ DSTATUS disk_status(BYTE pdrv) /* Initialize a Drive */ DSTATUS disk_initialize(BYTE pdrv) { - __ASSERT(pdrv < ARRAY_SIZE(pdrv_str), "pdrv out-of-range\n"); + uint8_t param = DISK_IOCTL_POWER_ON; - if (disk_access_init(pdrv_str[pdrv]) != 0) { - return STA_NOINIT; - } else { - return RES_OK; - } + return disk_ioctl(pdrv, CTRL_POWER, ¶m); } /* Read Sector(s) */ @@ -109,6 +107,27 @@ DRESULT disk_ioctl(BYTE pdrv, BYTE cmd, void *buff) } break; + /* Optional IOCTL command used by Zephyr fs_unmount implementation, + * not called by FATFS + */ + case CTRL_POWER: + if (((*(uint8_t *)buff)) == DISK_IOCTL_POWER_OFF) { + /* Power disk off */ + if (disk_access_ioctl(pdrv_str[pdrv], + DISK_IOCTL_CTRL_DEINIT, + NULL) != 0) { + ret = RES_ERROR; + } + } else { + /* Power disk on */ + if (disk_access_ioctl(pdrv_str[pdrv], + DISK_IOCTL_CTRL_INIT, + NULL) != 0) { + ret = STA_NOINIT; + } + } + break; + default: ret = RES_PARERR; break; diff --git a/modules/fatfs/zfs_diskio.h b/modules/fatfs/zfs_diskio.h new file mode 100644 index 0000000000000..b22c75586be71 --- /dev/null +++ b/modules/fatfs/zfs_diskio.h @@ -0,0 +1,22 @@ +/* + * Copyright 2024 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_MODULES_FATFS_ZFS_DISKIO_H_ +#define ZEPHYR_MODULES_FATFS_ZFS_DISKIO_H_ +/* + * Header file for Zephyr specific portions of the FatFS disk interface. + * These APIs are internal to Zephyr's FatFS VFS implementation + */ + +/* + * Values that can be passed to buffer pointer used by disk_ioctl() when + * sending CTRL_POWER IOCTL + */ +#define DISK_IOCTL_POWER_OFF 0x0 +#define DISK_IOCTL_POWER_ON 0x1 + + +#endif /* ZEPHYR_MODULES_FATFS_ZFS_DISKIO_H_ */ diff --git a/subsys/fs/fat_fs.c b/subsys/fs/fat_fs.c index a9e5c7f93cd74..2a0b7b7d486ac 100644 --- a/subsys/fs/fat_fs.c +++ b/subsys/fs/fat_fs.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2016 Intel Corporation. + * Copyright 2024 NXP * * SPDX-License-Identifier: Apache-2.0 */ @@ -14,6 +15,10 @@ #include #include #include +#include +#include /* Zephyr specific FatFS API */ +#include +LOG_MODULE_DECLARE(fs, CONFIG_FS_LOG_LEVEL); #define FATFS_MAX_FILE_NAME 12 /* Uses 8.3 SFN */ @@ -64,6 +69,23 @@ static int translate_error(int error) return -EIO; } +static int translate_disk_error(int error) +{ + switch (error) { + case RES_OK: + return 0; + case RES_WRPRT: + return -EPERM; + case RES_PARERR: + return -EINVAL; + case RES_NOTRDY: + case RES_ERROR: + return -EIO; + } + + return -EIO; +} + /* Converts a zephyr path like /SD:/foo into a path digestible by FATFS by stripping the * leading slash, i.e. SD:/foo. */ @@ -463,10 +485,23 @@ static int fatfs_mount(struct fs_mount_t *mountp) static int fatfs_unmount(struct fs_mount_t *mountp) { FRESULT res; + DRESULT disk_res; + uint8_t param = DISK_IOCTL_POWER_OFF; res = f_mount(NULL, translate_path(mountp->mnt_point), 0); + if (res != FR_OK) { + LOG_ERR("Unmount failed (%d)", res); + return translate_error(res); + } - return translate_error(res); + /* Make direct disk IOCTL call to deinit disk */ + disk_res = disk_ioctl(((FATFS *)mountp->fs_data)->pdrv, CTRL_POWER, ¶m); + if (disk_res != RES_OK) { + LOG_ERR("Could not power off disk (%d)", disk_res); + return translate_disk_error(disk_res); + } + + return 0; } #if defined(CONFIG_FILE_SYSTEM_MKFS) && defined(CONFIG_FS_FATFS_MKFS) From f414400b8fd8427fc713ed46853cda4d270614b2 Mon Sep 17 00:00:00 2001 From: Daniel DeGrasse Date: Tue, 14 May 2024 14:48:33 -0500 Subject: [PATCH 2058/2849] samples: fs: unmount and remount filesystem during init Unmount and remount filesystem during init, to verify that filesystem remount works as expected. Signed-off-by: Daniel DeGrasse --- samples/subsys/fs/fs_sample/src/main.c | 33 +++++++++++++++++++++----- 1 file changed, 27 insertions(+), 6 deletions(-) diff --git a/samples/subsys/fs/fs_sample/src/main.c b/samples/subsys/fs/fs_sample/src/main.c index 52c74cc74b1d8..01d935d7e1b50 100644 --- a/samples/subsys/fs/fs_sample/src/main.c +++ b/samples/subsys/fs/fs_sample/src/main.c @@ -48,6 +48,12 @@ static struct fs_mount_t mp = { #endif +#if defined(CONFIG_FAT_FILESYSTEM_ELM) +#define FS_RET_OK FR_OK +#else +#define FS_RET_OK 0 +#endif + LOG_MODULE_REGISTER(main); #define MAX_PATH 128 @@ -107,7 +113,8 @@ int main(void) uint32_t block_count; uint32_t block_size; - if (disk_access_init(disk_pdrv) != 0) { + if (disk_access_ioctl(disk_pdrv, + DISK_IOCTL_CTRL_INIT, NULL) != 0) { LOG_ERR("Storage init ERROR!"); break; } @@ -128,18 +135,32 @@ int main(void) memory_size_mb = (uint64_t)block_count * block_size; printk("Memory Size(MB) %u\n", (uint32_t)(memory_size_mb >> 20)); + + if (disk_access_ioctl(disk_pdrv, + DISK_IOCTL_CTRL_DEINIT, NULL) != 0) { + LOG_ERR("Storage deinit ERROR!"); + break; + } } while (0); mp.mnt_point = disk_mount_pt; int res = fs_mount(&mp); -#if defined(CONFIG_FAT_FILESYSTEM_ELM) - if (res == FR_OK) { -#else - if (res == 0) { -#endif + if (res == FS_RET_OK) { printk("Disk mounted.\n"); + /* Try to unmount and remount the disk */ + res = fs_unmount(&mp); + if (res != FS_RET_OK) { + printk("Error unmounting disk\n"); + return res; + } + res = fs_mount(&mp); + if (res != FS_RET_OK) { + printk("Error remounting disk\n"); + return res; + } + if (lsdir(disk_mount_pt) == 0) { #ifdef CONFIG_FS_SAMPLE_CREATE_SOME_ENTRIES if (create_some_entries(disk_mount_pt)) { From 35e04ef6f3a59ea41b3a2b3bd07858f3725ae01a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20Cab=C3=A9?= Date: Tue, 4 Jun 2024 18:03:02 +0200 Subject: [PATCH 2059/2849] doc: ztest: fix reference to kconfig options MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use proper identifiers and sphinx roles to reference Kconfigs. Signed-off-by: Benjamin Cabé --- doc/develop/test/ztest.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/develop/test/ztest.rst b/doc/develop/test/ztest.rst index e589bc907f8bf..e8bf8f43f0715 100644 --- a/doc/develop/test/ztest.rst +++ b/doc/develop/test/ztest.rst @@ -457,9 +457,9 @@ Configuration Static configuration of Ztress contains: - - :c:macro:`ZTRESS_MAX_THREADS` - number of supported threads. - - :c:macro:`ZTRESS_STACK_SIZE` - Stack size of created threads. - - :c:macro:`ZTRESS_REPORT_PROGRESS_MS` - Test progress report interval. + - :kconfig:option:`CONFIG_ZTRESS_MAX_THREADS` - number of supported threads. + - :kconfig:option:`CONFIG_ZTRESS_STACK_SIZE` - Stack size of created threads. + - :kconfig:option:`CONFIG_ZTRESS_REPORT_PROGRESS_MS` - Test progress report interval. API reference ************* From 34f4a0f6bcaa6a4b4c8108fa60ffede3a0edbaa6 Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Thu, 6 Jun 2024 22:18:20 +0200 Subject: [PATCH 2060/2849] drivers: rtc: rtc_shell: Add devices as sub commands This commit adds support for entry tab completion and device lookup if enabled. Signed-off-by: Aurelien Jarno --- drivers/rtc/rtc_shell.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/drivers/rtc/rtc_shell.c b/drivers/rtc/rtc_shell.c index 714d63c6759b5..a87056c6ed707 100644 --- a/drivers/rtc/rtc_shell.c +++ b/drivers/rtc/rtc_shell.c @@ -217,6 +217,16 @@ static int cmd_get(const struct shell *sh, size_t argc, char **argv) return 0; } +static void device_name_get(size_t idx, struct shell_static_entry *entry) +{ + const struct device *dev = shell_device_lookup(idx, NULL); + + entry->syntax = (dev != NULL) ? dev->name : NULL; + entry->handler = NULL; + entry->help = NULL; + entry->subcmd = NULL; +} + #define RTC_GET_HELP \ ("Get current time (UTC)\n" \ "Usage: rtc get ") @@ -225,10 +235,12 @@ static int cmd_get(const struct shell *sh, size_t argc, char **argv) ("Set UTC time\n" \ "Usage: rtc set | | ") +SHELL_DYNAMIC_CMD_CREATE(dsub_device_name, device_name_get); + SHELL_STATIC_SUBCMD_SET_CREATE(sub_rtc, /* Alphabetically sorted */ - SHELL_CMD_ARG(set, NULL, RTC_SET_HELP, cmd_set, 3, 0), - SHELL_CMD_ARG(get, NULL, RTC_GET_HELP, cmd_get, 2, 0), + SHELL_CMD_ARG(set, &dsub_device_name, RTC_SET_HELP, cmd_set, 3, 0), + SHELL_CMD_ARG(get, &dsub_device_name, RTC_GET_HELP, cmd_get, 2, 0), SHELL_SUBCMD_SET_END); SHELL_CMD_REGISTER(rtc, &sub_rtc, "RTC commands", NULL); From bf8b1d67d60d0eb01af0cfe87e2595d4fa525715 Mon Sep 17 00:00:00 2001 From: Adrien Ricciardi Date: Wed, 15 May 2024 11:28:34 +0200 Subject: [PATCH 2061/2849] sys: util: Add SIZEOF_FIELD() macro This macro allows to know the size of a struct member at compile time. Several parts of the Zephyr code are currently using directly the macro code. Also added a unit test. Signed-off-by: Adrien Ricciardi --- include/zephyr/sys/util.h | 10 ++++++++++ tests/unit/util/main.c | 15 +++++++++++++++ 2 files changed, 25 insertions(+) diff --git a/include/zephyr/sys/util.h b/include/zephyr/sys/util.h index b457862bb9770..fe04c058b1e4a 100644 --- a/include/zephyr/sys/util.h +++ b/include/zephyr/sys/util.h @@ -271,6 +271,16 @@ extern "C" { ((type *)(((char *)(ptr)) - offsetof(type, field))); \ }) +/** + * @brief Report the size of a struct field in bytes. + * + * @param type The structure containing the field of interest. + * @param member The field to return the size of. + * + * @return The field size. + */ +#define SIZEOF_FIELD(type, member) sizeof((((type *)0)->member)) + /** * @brief Concatenate input arguments * diff --git a/tests/unit/util/main.c b/tests/unit/util/main.c index 1e0bb67346a0a..f386ba0f7894e 100644 --- a/tests/unit/util/main.c +++ b/tests/unit/util/main.c @@ -803,4 +803,19 @@ ZTEST(util, test_CONCAT) zassert_equal(CONCAT(CAT_PART1, CONCAT(CAT_PART2, CAT_PART3)), 123); } +ZTEST(util, test_SIZEOF_FIELD) +{ + struct test_t { + uint32_t a; + uint8_t b; + uint8_t c[17]; + int16_t d; + }; + + BUILD_ASSERT(SIZEOF_FIELD(struct test_t, a) == 4, "The a member is 4-byte wide."); + BUILD_ASSERT(SIZEOF_FIELD(struct test_t, b) == 1, "The b member is 1-byte wide."); + BUILD_ASSERT(SIZEOF_FIELD(struct test_t, c) == 17, "The c member is 17-byte wide."); + BUILD_ASSERT(SIZEOF_FIELD(struct test_t, d) == 2, "The d member is 2-byte wide."); +} + ZTEST_SUITE(util, NULL, NULL, NULL, NULL, NULL); From 9f6451d0862372ef1e060bcf613e83931419d30d Mon Sep 17 00:00:00 2001 From: Adrien Ricciardi Date: Thu, 16 May 2024 14:05:43 +0200 Subject: [PATCH 2062/2849] drivers: gpio: gecko: Use SIZEOF_FIELD() macro Use the utility macro instead of bare code. Signed-off-by: Adrien Ricciardi --- drivers/gpio/gpio_gecko.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpio/gpio_gecko.c b/drivers/gpio/gpio_gecko.c index dc3e5317d4d62..1025f1eaa7ab0 100644 --- a/drivers/gpio/gpio_gecko.c +++ b/drivers/gpio/gpio_gecko.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #ifdef CONFIG_SOC_GECKO_DEV_INIT @@ -63,9 +64,8 @@ #define GECKO_GPIO_MODEH(pin, mode) (mode << ((pin - 8) * 4)) -#define member_size(type, member) sizeof(((type *)0)->member) -#define NUMBER_OF_PORTS (member_size(GPIO_TypeDef, P) / \ - member_size(GPIO_TypeDef, P[0])) +#define NUMBER_OF_PORTS (SIZEOF_FIELD(GPIO_TypeDef, P) / \ + SIZEOF_FIELD(GPIO_TypeDef, P[0])) struct gpio_gecko_common_config { }; From 67706a1802547a279b46318ab0974c43339115e8 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Wed, 29 May 2024 14:30:43 -0400 Subject: [PATCH 2063/2849] kernel: mem_slab: reverse free list initialization As it is, blocks are allocated going backward within the buffer. There is nothing fundamentally wrong with that, but it makes debugging unnatural with the successively descending addresses. Create the free list so pointers are oriented forward, at least initially. Signed-off-by: Nicolas Pitre --- kernel/mem_slab.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/kernel/mem_slab.c b/kernel/mem_slab.c index 9482f0e88c50a..65b2456a2bfbe 100644 --- a/kernel/mem_slab.c +++ b/kernel/mem_slab.c @@ -103,7 +103,6 @@ static struct k_obj_core_stats_desc mem_slab_stats_desc = { */ static int create_free_list(struct k_mem_slab *slab) { - uint32_t j; char *p; /* blocks must be word aligned */ @@ -113,12 +112,12 @@ static int create_free_list(struct k_mem_slab *slab) } slab->free_list = NULL; - p = slab->buffer; + p = slab->buffer + slab->info.block_size * (slab->info.num_blocks - 1); - for (j = 0U; j < slab->info.num_blocks; j++) { + while (p >= slab->buffer) { *(char **)p = slab->free_list; slab->free_list = p; - p += slab->info.block_size; + p -= slab->info.block_size; } return 0; } From 5f2620fece42815c04629dcb9baa044e7c2f3c44 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Wed, 29 May 2024 15:18:25 -0400 Subject: [PATCH 2064/2849] kernel: mem_slab: extend slab pointer validation Abstract slab pointer validation and apply it to block dequeue during allocation in addition to the existing block freeing. This should help catching some buffer overflow induced corruptions. Signed-off-by: Nicolas Pitre --- kernel/mem_slab.c | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/kernel/mem_slab.c b/kernel/mem_slab.c index 65b2456a2bfbe..f79c5b01d4f99 100644 --- a/kernel/mem_slab.c +++ b/kernel/mem_slab.c @@ -204,6 +204,16 @@ int k_mem_slab_init(struct k_mem_slab *slab, void *buffer, return rc; } +static inline bool slab_ptr_is_good(struct k_mem_slab *slab, const void *ptr) +{ + const char *p = ptr; + ptrdiff_t offset = p - slab->buffer; + + return (offset >= 0) && + (offset < (slab->info.block_size * slab->info.num_blocks)) && + ((offset % slab->info.block_size) == 0); +} + int k_mem_slab_alloc(struct k_mem_slab *slab, void **mem, k_timeout_t timeout) { k_spinlock_key_t key = k_spin_lock(&slab->lock); @@ -216,6 +226,10 @@ int k_mem_slab_alloc(struct k_mem_slab *slab, void **mem, k_timeout_t timeout) *mem = slab->free_list; slab->free_list = *(char **)(slab->free_list); slab->info.num_used++; + __ASSERT((slab->free_list == NULL && + slab->info.num_used == slab->info.num_blocks) || + slab_ptr_is_good(slab, slab->free_list), + "slab corruption detected"); #ifdef CONFIG_MEM_SLAB_TRACE_MAX_UTILIZATION slab->info.max_used = MAX(slab->info.num_used, @@ -253,11 +267,7 @@ void k_mem_slab_free(struct k_mem_slab *slab, void *mem) { k_spinlock_key_t key = k_spin_lock(&slab->lock); - __ASSERT(((char *)mem >= slab->buffer) && - ((((char *)mem - slab->buffer) % slab->info.block_size) == 0) && - ((char *)mem <= (slab->buffer + (slab->info.block_size * - (slab->info.num_blocks - 1)))), - "Invalid memory pointer provided"); + __ASSERT(slab_ptr_is_good(slab, 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)) { From 0c0475ff629cb5783b03ed9c4811cd3c105aca51 Mon Sep 17 00:00:00 2001 From: Anas Nashif Date: Fri, 7 Jun 2024 12:26:03 -0400 Subject: [PATCH 2065/2849] soc: xlnx: remove duplicate soc entry xc7z010 is duplicated. Signed-off-by: Anas Nashif --- soc/xlnx/zynq7000/soc.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/soc/xlnx/zynq7000/soc.yml b/soc/xlnx/zynq7000/soc.yml index 25c5d0f227fca..8bf83bc527b9f 100644 --- a/soc/xlnx/zynq7000/soc.yml +++ b/soc/xlnx/zynq7000/soc.yml @@ -4,7 +4,6 @@ family: - name: xc7zxxx socs: - name: xc7z010 - - name: xc7z010 - name: xc7z015 - name: xc7z020 - name: xc7z030 From 45ba038aac2083e662c1ee7595a5839752be0a51 Mon Sep 17 00:00:00 2001 From: Grzegorz Swiderski Date: Fri, 7 Jun 2024 11:55:30 +0200 Subject: [PATCH 2066/2849] devicetree: Remove DT_INST_NODE_HAS_PROP_AND_OR This undocumented helper macro is unused as of: 4c8ed7dd9a108b505d646e3077d735bc807f6863 Signed-off-by: Grzegorz Swiderski --- include/zephyr/devicetree.h | 4 ---- 1 file changed, 4 deletions(-) diff --git a/include/zephyr/devicetree.h b/include/zephyr/devicetree.h index c1c90220a1aa8..7bdcc671b4d89 100644 --- a/include/zephyr/devicetree.h +++ b/include/zephyr/devicetree.h @@ -4557,10 +4557,6 @@ #define DT_NODE_HAS_STATUS_INTERNAL(node_id, status) \ IS_ENABLED(DT_CAT3(node_id, _STATUS_, status)) -/** @brief Helper macro to OR multiple has property checks in a loop macro */ -#define DT_INST_NODE_HAS_PROP_AND_OR(inst, prop) \ - DT_INST_NODE_HAS_PROP(inst, prop) || - /** * @def DT_U64_C * @brief Macro to add ULL postfix to the devicetree address constants From 76c623806d791502b716cede85d618d7e8c69f22 Mon Sep 17 00:00:00 2001 From: Grzegorz Swiderski Date: Fri, 7 Jun 2024 11:55:30 +0200 Subject: [PATCH 2067/2849] devicetree: Use UTIL_AND in DT_NODE_HAS_COMPAT_STATUS Replace the leftover `&&` operator with UTIL_AND(), so that this DT API can be evaluated at C preprocessor time. Signed-off-by: Grzegorz Swiderski --- include/zephyr/devicetree.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/zephyr/devicetree.h b/include/zephyr/devicetree.h index 7bdcc671b4d89..58f924e266d82 100644 --- a/include/zephyr/devicetree.h +++ b/include/zephyr/devicetree.h @@ -3289,7 +3289,7 @@ * @param status okay or disabled as a token, not a string */ #define DT_NODE_HAS_COMPAT_STATUS(node_id, compat, status) \ - DT_NODE_HAS_COMPAT(node_id, compat) && DT_NODE_HAS_STATUS(node_id, status) + UTIL_AND(DT_NODE_HAS_COMPAT(node_id, compat), DT_NODE_HAS_STATUS(node_id, status)) /** * @brief Does a devicetree node have a property? From bb3eb967c8a1c6f167207dfc93e849ca900a8890 Mon Sep 17 00:00:00 2001 From: Daniel DeGrasse Date: Thu, 6 Jun 2024 17:16:46 -0500 Subject: [PATCH 2068/2849] boards: nuvoton: numaker_m2l31ki: reenable userspace In commit a30c5731aed (tests: drivers: can: api: support numaker_m2l31ki, 2024-05-31), CONFIG_USERSPACE was disabled for the numaker_m2l31ki. This fix is valid to support running the CAN API testsuite, but Zephyr's infrastructure does not properly support disabling userspace at the board level. As a temporary workaround, reenable userspace to fix failing CI tests on this board. Signed-off-by: Daniel DeGrasse --- boards/nuvoton/numaker_m2l31ki/numaker_m2l31ki_defconfig | 3 --- 1 file changed, 3 deletions(-) diff --git a/boards/nuvoton/numaker_m2l31ki/numaker_m2l31ki_defconfig b/boards/nuvoton/numaker_m2l31ki/numaker_m2l31ki_defconfig index 4e555333a7eae..e59234cb73c74 100644 --- a/boards/nuvoton/numaker_m2l31ki/numaker_m2l31ki_defconfig +++ b/boards/nuvoton/numaker_m2l31ki/numaker_m2l31ki_defconfig @@ -21,6 +21,3 @@ CONFIG_UART_CONSOLE=y # Enable RMC CONFIG_FLASH=y - -# m2l31x has 4 MPU regions and can't afford to enable CONFIG_USERSPACE -CONFIG_USERSPACE=n From 6cdb9a0c9e12cd5303b183dd65cf8b15f1f8d040 Mon Sep 17 00:00:00 2001 From: Daniel DeGrasse Date: Mon, 3 Jun 2024 16:02:37 -0500 Subject: [PATCH 2069/2849] samples: ipc: openamp: remove pre HWMV2 overlays for RT11xx boards Remove pre hardware model v2 overlays present for RT11xx boards, that were missed in the HWMv2 migration Signed-off-by: Daniel DeGrasse --- .../openamp/boards/mimxrt1170_evkb_cm7.conf | 7 --- .../remote/boards/mimxrt1160_evk_cm4.conf | 3 -- .../remote/boards/mimxrt1170_evk_cm4.conf | 3 -- .../remote/boards/mimxrt1170_evk_cm4.overlay | 51 ------------------- .../remote/boards/mimxrt1170_evkb_cm4.conf | 8 --- .../remote/boards/mimxrt1170_evkb_cm4.overlay | 49 ------------------ 6 files changed, 121 deletions(-) delete mode 100644 samples/subsys/ipc/openamp/boards/mimxrt1170_evkb_cm7.conf delete mode 100644 samples/subsys/ipc/openamp/remote/boards/mimxrt1160_evk_cm4.conf delete mode 100644 samples/subsys/ipc/openamp/remote/boards/mimxrt1170_evk_cm4.conf delete mode 100644 samples/subsys/ipc/openamp/remote/boards/mimxrt1170_evk_cm4.overlay delete mode 100644 samples/subsys/ipc/openamp/remote/boards/mimxrt1170_evkb_cm4.conf delete mode 100644 samples/subsys/ipc/openamp/remote/boards/mimxrt1170_evkb_cm4.overlay diff --git a/samples/subsys/ipc/openamp/boards/mimxrt1170_evkb_cm7.conf b/samples/subsys/ipc/openamp/boards/mimxrt1170_evkb_cm7.conf deleted file mode 100644 index ae8dba8cc217f..0000000000000 --- a/samples/subsys/ipc/openamp/boards/mimxrt1170_evkb_cm7.conf +++ /dev/null @@ -1,7 +0,0 @@ -# -# Copyright 2023, NXP -# -# SPDX-License-Identifier: Apache-2.0 -# -CONFIG_INCLUDE_REMOTE_DIR=y -CONFIG_SECOND_CORE_MCUX=y diff --git a/samples/subsys/ipc/openamp/remote/boards/mimxrt1160_evk_cm4.conf b/samples/subsys/ipc/openamp/remote/boards/mimxrt1160_evk_cm4.conf deleted file mode 100644 index 4dfc4a60b76ac..0000000000000 --- a/samples/subsys/ipc/openamp/remote/boards/mimxrt1160_evk_cm4.conf +++ /dev/null @@ -1,3 +0,0 @@ -CONFIG_BUILD_OUTPUT_INFO_HEADER=y -CONFIG_BUILD_OUTPUT_HEX=y -CONFIG_SECOND_CORE_MCUX=y diff --git a/samples/subsys/ipc/openamp/remote/boards/mimxrt1170_evk_cm4.conf b/samples/subsys/ipc/openamp/remote/boards/mimxrt1170_evk_cm4.conf deleted file mode 100644 index 4dfc4a60b76ac..0000000000000 --- a/samples/subsys/ipc/openamp/remote/boards/mimxrt1170_evk_cm4.conf +++ /dev/null @@ -1,3 +0,0 @@ -CONFIG_BUILD_OUTPUT_INFO_HEADER=y -CONFIG_BUILD_OUTPUT_HEX=y -CONFIG_SECOND_CORE_MCUX=y diff --git a/samples/subsys/ipc/openamp/remote/boards/mimxrt1170_evk_cm4.overlay b/samples/subsys/ipc/openamp/remote/boards/mimxrt1170_evk_cm4.overlay deleted file mode 100644 index 87159192cf249..0000000000000 --- a/samples/subsys/ipc/openamp/remote/boards/mimxrt1170_evk_cm4.overlay +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright 2022-2023 NXP - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include - -/ { - /* Switch to lpuart2, since primary core uses lpuart1 */ - chosen { - zephyr,flash = &ocram; - zephyr,console = &lpuart2; - zephyr,shell-uart = &lpuart2; - zephyr,ipc_shm = &ocram2_overlay; - }; - - soc { - /delete-node/ gpt@400f0000; - - /* Replace GPT2 with another GPT kernel timer */ - gpt2_hw_timer:gpt@400f0000 { - compatible = "nxp,gpt-hw-timer"; - reg = <0x400f0000 0x4000>; - interrupts = <120 0>; - status = "okay"; - }; - }; - - /* OpenAMP fails with full 512K OCRAM2 memory region as shared memory. - * Define a subset of the OCRAM2 region for demo to use - * Note that shared memory must have specific MPU attributes set - */ - ocram2_overlay: memory@202c0000 { - compatible = "zephyr,memory-region", "mmio-sram"; - reg = <0x202c0000 DT_SIZE_K(16)>; - zephyr,memory-region="OCRAM2_OVERLAY"; - zephyr,memory-attr = <( DT_MEM_ARM(ATTR_MPU_IO) )>; - }; -}; - -/* Enable secondary LPUART */ -&lpuart2 { - status = "okay"; - current-speed = <115200>; -}; - -/* Disable primary GPT timer */ -&gpt_hw_timer { - status = "disabled"; -}; diff --git a/samples/subsys/ipc/openamp/remote/boards/mimxrt1170_evkb_cm4.conf b/samples/subsys/ipc/openamp/remote/boards/mimxrt1170_evkb_cm4.conf deleted file mode 100644 index 7b43b448c72c2..0000000000000 --- a/samples/subsys/ipc/openamp/remote/boards/mimxrt1170_evkb_cm4.conf +++ /dev/null @@ -1,8 +0,0 @@ -# -# Copyright 2023, NXP -# -# SPDX-License-Identifier: Apache-2.0 -# -CONFIG_BUILD_OUTPUT_INFO_HEADER=y -CONFIG_BUILD_OUTPUT_HEX=y -CONFIG_SECOND_CORE_MCUX=y diff --git a/samples/subsys/ipc/openamp/remote/boards/mimxrt1170_evkb_cm4.overlay b/samples/subsys/ipc/openamp/remote/boards/mimxrt1170_evkb_cm4.overlay deleted file mode 100644 index 72510d261664a..0000000000000 --- a/samples/subsys/ipc/openamp/remote/boards/mimxrt1170_evkb_cm4.overlay +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright 2023 NXP - * - * SPDX-License-Identifier: Apache-2.0 - */ - -/ { - /* Switch to lpuart2, since primary core uses lpuart1 */ - chosen { - zephyr,flash = &ocram; - zephyr,console = &lpuart2; - zephyr,shell-uart = &lpuart2; - zephyr,ipc_shm = &ocram2_overlay; - }; - - soc { - /delete-node/ gpt@400f0000; - - /* Replace GPT2 with another GPT kernel timer */ - gpt2_hw_timer:gpt@400f0000 { - compatible = "nxp,gpt-hw-timer"; - reg = <0x400f0000 0x4000>; - interrupts = <120 0>; - status = "okay"; - }; - }; - - /* OpenAMP fails with full 512K OCRAM2 memory region as shared memory. - * Define a subset of the OCRAM2 region for demo to use - * Note that shared memory must have specific MPU attributes set - */ - ocram2_overlay: memory@202c0000 { - compatible = "zephyr,memory-region", "mmio-sram"; - reg = <0x202c0000 DT_SIZE_K(16)>; - zephyr,memory-region="OCRAM2_OVERLAY"; - zephyr,memory-attr = <( DT_MEM_ARM(ATTR_MPU_IO) )>; - }; -}; - -/* Enable secondary LPUART */ -&lpuart2 { - status = "okay"; - current-speed = <115200>; -}; - -/* Disable primary GPT timer */ -&gpt_hw_timer { - status = "disabled"; -}; From b48aeedf7759ed527e5c90ca24e755e45834c00a Mon Sep 17 00:00:00 2001 From: Lars-Ove Karlsson Date: Tue, 28 May 2024 22:02:48 +0200 Subject: [PATCH 2070/2849] arch: common: Removed unnecessary cast Removed an unnecessary cast to void * from a function that already had the correct signature. This makes for more portable code as casting between code and data pointers are frowned upon by the C standard. Signed-off-by: Lars-Ove Karlsson --- arch/common/isr_tables.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/common/isr_tables.c b/arch/common/isr_tables.c index 050597b7b1d82..b3bdd136e0c20 100644 --- a/arch/common/isr_tables.c +++ b/arch/common/isr_tables.c @@ -90,7 +90,7 @@ uintptr_t __irq_vector_table _irq_vector_table[IRQ_TABLE_SIZE] = { #ifdef CONFIG_GEN_SW_ISR_TABLE struct _isr_table_entry __sw_isr_table _sw_isr_table[IRQ_TABLE_SIZE] = { [0 ...(IRQ_TABLE_SIZE - 1)] = {(const void *)0x42, - (void *)&z_irq_spurious}, + &z_irq_spurious}, }; #endif From 161c56fa31d37c7aadee0003764c006f6977c732 Mon Sep 17 00:00:00 2001 From: nagendra modadugu Date: Tue, 12 Mar 2024 10:03:55 -0700 Subject: [PATCH 2071/2849] soc: opentitan: update manifest format Fix calculation of the app entry point. Signed-off-by: nagendra modadugu --- soc/lowrisc/opentitan/rom_header.S | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/soc/lowrisc/opentitan/rom_header.S b/soc/lowrisc/opentitan/rom_header.S index 6bfedafa906bf..e7b41235dab73 100644 --- a/soc/lowrisc/opentitan/rom_header.S +++ b/soc/lowrisc/opentitan/rom_header.S @@ -6,16 +6,24 @@ #include -/* imports */ -GTEXT(__start) +/* exports */ +GTEXT(__rom_header) -/* OpenTitan manifest consists of 896 bytes (224 words) containing signature, - * device ID, version info, etc. The test ROM ignores all of these fields - * except for entry point (final word in manifest). +/* OpenTitan manifest consists of 1024 bytes (256 words) of manifest + * containing signature, device ID, version info, etc. The test ROM + * ignores all of these fields except for entry point. + * + * The layout below conforms to manifest version: 0x71c3 (major), + * 0x6c47 (minor). The manifest format is documented here: + * https://github.com/lowRISC/opentitan/blob/689a163294e1791bd30cfe096decf7f9233abad4/sw/host/opentitanlib/src/image/manifest.rs#L205 */ SECTION_FUNC(rom_header, __rom_header) - .rept(223) + .rept(225) .word 0 .endr /* Entry point is relative to the beginning of manifest. */ .word(__start - __rom_header) + /* Extensions entry table goes here. */ + .rept(30) + .word 0 + .endr From 02a14d75fc7fc0c1894f7832ce20fc48edf5ac66 Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Sun, 10 Mar 2024 20:32:43 -0700 Subject: [PATCH 2072/2849] pm: Declare pm state constraints for a device Declare power state constraints for a device in devicetree. It allows a map between device instances and power states that disable their power. This information is used by a new API (pm_policy_device_power_lock_put/get) that automically set/release pm state constraints. Signed-off-by: Flavio Ceolin --- dts/bindings/base/pm.yaml | 5 ++ include/zephyr/device.h | 105 +++++++++++++++++++++++++++++-------- include/zephyr/pm/policy.h | 38 ++++++++++++++ include/zephyr/pm/state.h | 18 +++++++ subsys/pm/policy.c | 20 +++++++ 5 files changed, 165 insertions(+), 21 deletions(-) diff --git a/dts/bindings/base/pm.yaml b/dts/bindings/base/pm.yaml index 0776170d8f205..50c016d07bd12 100644 --- a/dts/bindings/base/pm.yaml +++ b/dts/bindings/base/pm.yaml @@ -30,3 +30,8 @@ properties: description: | Automatically configure the device for runtime power management after the init function runs. + + zephyr,disabling-power-states: + type: phandles + description: | + List of power states that will disable this device power. diff --git a/include/zephyr/device.h b/include/zephyr/device.h index 5d891c1e9ef5e..e15f426f952c8 100644 --- a/include/zephyr/device.h +++ b/include/zephyr/device.h @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -418,6 +419,10 @@ struct device { */ Z_DEVICE_DEPS_CONST device_handle_t *deps; #endif /* CONFIG_DEVICE_DEPS */ +#if defined(CONFIG_PM) || defined(__DOXYGEN__) + struct pm_state_constraint const *pm_constraints; + size_t pm_constraints_size; +#endif /* CONFIG_PM */ #if defined(CONFIG_PM_DEVICE) || defined(__DOXYGEN__) /** * Reference to the device PM resources (only available if @@ -866,6 +871,58 @@ __syscall int device_init(const struct device *dev); #endif /* CONFIG_DEVICE_DEPS */ +#if defined(CONFIG_PM) || defined(__DOXYGEN__) + +/** + * @brief Synthesize the name of the object that holds a device pm constraint. + * + * @param dev_id Device identifier. + */ +#define Z_DEVICE_PM_CONSTRAINTS_NAME(dev_id) _CONCAT(__devicepmconstraints_, dev_id) + +/** + * @brief initialize a device pm constraint with information from devicetree. + * + * @param node_id Node identifier. + */ +#define Z_PM_STATE_CONSTRAINT_DT_INIT(node_id) \ + { \ + .state = PM_STATE_DT_INIT(node_id), \ + .substate_id = DT_PROP_OR(node_id, substate_id, 0), \ + } + +#define Z_PM_STATE_FROM_DT_DEVICE(i, node_id) \ + COND_CODE_1(DT_NODE_HAS_STATUS(DT_PHANDLE_BY_IDX(node_id, \ + zephyr_disabling_power_states, i), okay), \ + (Z_PM_STATE_CONSTRAINT_DT_INIT(DT_PHANDLE_BY_IDX(node_id, \ + zephyr_disabling_power_states, i)),), ()) + +/** + * @brief Helper macro to generate a list of device pm constraints. + */ +#define Z_PM_STATE_CONSTRAINTS_FROM_DT_DEVICE(node_id) \ + { \ + LISTIFY(DT_PROP_LEN_OR(node_id, zephyr_disabling_power_states, 0), \ + Z_PM_STATE_FROM_DT_DEVICE, (), node_id) \ + } + +/** + * @brief Define device pm constraints. + * + * Defines a list of `pm_state_constraint` for a specific device from its + * devicetree definition. + * + * This information tell us which power states would cause power loss + * and intended to be used by a device to set power state constraints when + * it is in the middle of an operation. + */ +#define Z_DEVICE_PM_CONSTRAINTS_DEFINE(node_id, dev_id, ...) \ + Z_DECL_ALIGN(struct pm_state_constraint) \ + Z_DEVICE_PM_CONSTRAINTS_NAME(dev_id)[] = \ + Z_PM_STATE_CONSTRAINTS_FROM_DT_DEVICE(node_id); + +#endif /* CONFIG_PM */ + /** * @brief Init sub-priority of the device * @@ -905,15 +962,18 @@ __syscall int device_init(const struct device *dev); * @param state_ Reference to device state. * @param deps_ Reference to device dependencies. */ -#define Z_DEVICE_INIT(name_, pm_, data_, config_, api_, state_, deps_) \ - { \ - .name = name_, \ - .config = (config_), \ - .api = (api_), \ - .state = (state_), \ - .data = (data_), \ - IF_ENABLED(CONFIG_DEVICE_DEPS, (.deps = (deps_),)) /**/ \ - IF_ENABLED(CONFIG_PM_DEVICE, ({ .pm_base = (pm_),})) /**/ \ +#define Z_DEVICE_INIT(name_, pm_, data_, config_, api_, state_, deps_, \ + constraints_size_, constraints_) \ + { \ + .name = name_, \ + .config = (config_), \ + .api = (api_), \ + .state = (state_), \ + .data = (data_), \ + IF_ENABLED(CONFIG_DEVICE_DEPS, (.deps = (deps_),)) /**/ \ + IF_ENABLED(CONFIG_PM, (.pm_constraints = (constraints_),)) \ + IF_ENABLED(CONFIG_PM, (.pm_constraints_size = (constraints_size_),)) \ + IF_ENABLED(CONFIG_PM_DEVICE, ({ .pm_base = (pm_),})) /**/ \ } /** @@ -942,13 +1002,14 @@ __syscall int device_init(const struct device *dev); * @param ... Optional dependencies, manually specified. */ #define Z_DEVICE_BASE_DEFINE(node_id, dev_id, name, pm, data, config, level, prio, api, state, \ - deps) \ + deps, constraints) \ COND_CODE_1(DT_NODE_EXISTS(node_id), (), (static)) \ COND_CODE_1(Z_DEVICE_IS_MUTABLE(node_id), (), (const)) \ STRUCT_SECTION_ITERABLE_NAMED_ALTERNATE( \ device, COND_CODE_1(Z_DEVICE_IS_MUTABLE(node_id), (device_mutable), (device)), \ Z_DEVICE_SECTION_NAME(level, prio), DEVICE_NAME_GET(dev_id)) = \ - Z_DEVICE_INIT(name, pm, data, config, api, state, deps) + Z_DEVICE_INIT(name, pm, data, config, api, state, deps, \ + DT_PROP_LEN_OR(node_id, zephyr_disabling_power_states, 0), constraints) /* deprecated device initialization levels */ #define Z_DEVICE_LEVEL_DEPRECATED_EARLY \ @@ -1026,16 +1087,18 @@ __syscall int device_init(const struct device *dev); * @param state Reference to device state. * @param ... Optional dependencies, manually specified. */ -#define Z_DEVICE_DEFINE(node_id, dev_id, name, init_fn, pm, data, config, \ - level, prio, api, state, ...) \ - Z_DEVICE_NAME_CHECK(name); \ - \ - IF_ENABLED(CONFIG_DEVICE_DEPS, \ - (Z_DEVICE_DEPS_DEFINE(node_id, dev_id, __VA_ARGS__);)) \ - \ - Z_DEVICE_BASE_DEFINE(node_id, dev_id, name, pm, data, config, level, \ - prio, api, state, Z_DEVICE_DEPS_NAME(dev_id)); \ - \ +#define Z_DEVICE_DEFINE(node_id, dev_id, name, init_fn, pm, data, config, \ + level, prio, api, state, ...) \ + Z_DEVICE_NAME_CHECK(name); \ + \ + IF_ENABLED(CONFIG_DEVICE_DEPS, \ + (Z_DEVICE_DEPS_DEFINE(node_id, dev_id, __VA_ARGS__);)) \ + \ + IF_ENABLED(CONFIG_PM, \ + (Z_DEVICE_PM_CONSTRAINTS_DEFINE(node_id, dev_id, __VA_ARGS__);))\ + Z_DEVICE_BASE_DEFINE(node_id, dev_id, name, pm, data, config, level, \ + prio, api, state, Z_DEVICE_DEPS_NAME(dev_id), \ + Z_DEVICE_PM_CONSTRAINTS_NAME(dev_id)); \ COND_CODE_1(DEVICE_DT_DEFER(node_id), \ (Z_DEFER_DEVICE_INIT_ENTRY_DEFINE(node_id, dev_id, \ init_fn)), \ diff --git a/include/zephyr/pm/policy.h b/include/zephyr/pm/policy.h index e77004bbbe8fd..6fe91663bb6c7 100644 --- a/include/zephyr/pm/policy.h +++ b/include/zephyr/pm/policy.h @@ -10,6 +10,7 @@ #include #include +#include #include #include #include @@ -219,6 +220,32 @@ void pm_policy_event_update(struct pm_policy_event *evt, uint32_t time_us); */ void pm_policy_event_unregister(struct pm_policy_event *evt); +/** + * @brief Increase power state locks. + * + * Set power state locks in all power states that disable power in the given + * device. + * + * @param dev Device reference. + * + * @see pm_policy_device_power_lock_put() + * @see pm_policy_state_lock_get() + */ +void pm_policy_device_power_lock_get(const struct device *dev); + +/** + * @brief Decrease power state locks. + * + * Remove power state locks in all power states that disable power in the given + * device. + * + * @param dev Device reference. + * + * @see pm_policy_device_power_lock_get() + * @see pm_policy_state_lock_put() + */ +void pm_policy_device_power_lock_put(const struct device *dev); + #else static inline void pm_policy_state_lock_get(enum pm_state state, uint8_t substate_id) { @@ -278,6 +305,17 @@ static inline void pm_policy_event_unregister(struct pm_policy_event *evt) { ARG_UNUSED(evt); } + +static inline void pm_policy_device_power_lock_get(const struct device *dev) +{ + ARG_UNUSED(dev); +} + +static inline void pm_policy_device_power_lock_put(const struct device *dev) +{ + ARG_UNUSED(dev); +} + #endif /* CONFIG_PM */ /** diff --git a/include/zephyr/pm/state.h b/include/zephyr/pm/state.h index e5866953f379a..87363ea27d2e9 100644 --- a/include/zephyr/pm/state.h +++ b/include/zephyr/pm/state.h @@ -166,6 +166,24 @@ struct pm_state_info { uint32_t exit_latency_us; }; +/** + * Power state information needed to lock a power state. + */ +struct pm_state_constraint { + /** + * Power management state + * + * @see pm_state + **/ + enum pm_state state; + /** + * Power management sub-state + * + * @see pm_state + **/ + uint8_t substate_id; +}; + /** @cond INTERNAL_HIDDEN */ /** diff --git a/subsys/pm/policy.c b/subsys/pm/policy.c index 9b5570136bcdc..0d9922ffd6662 100644 --- a/subsys/pm/policy.c +++ b/subsys/pm/policy.c @@ -329,3 +329,23 @@ void pm_policy_event_unregister(struct pm_policy_event *evt) k_spin_unlock(&events_lock, key); } + +void pm_policy_device_power_lock_get(const struct device *dev) +{ +#if DT_HAS_COMPAT_STATUS_OKAY(zephyr_power_state) + for (size_t i = 0; i < dev->pm_constraints_size; i++) { + pm_policy_state_lock_get(dev->pm_constraints[i].state, + dev->pm_constraints[i].substate_id); + } +#endif +} + +void pm_policy_device_power_lock_put(const struct device *dev) +{ +#if DT_HAS_COMPAT_STATUS_OKAY(zephyr_power_state) + for (size_t i = 0; i < dev->pm_constraints_size; i++) { + pm_policy_state_lock_put(dev->pm_constraints[i].state, + dev->pm_constraints[i].substate_id); + } +#endif +} From 39544299fc5454de7c8461bd6c047ab43791d33a Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Sun, 10 Mar 2024 20:38:59 -0700 Subject: [PATCH 2073/2849] tests: pm/power_states_api: Test device constraints Test that device pm state constraints work as expected. It declares a device in DT that specify that two pm states cause power loss and use this information when the device is in the middle of an action. Signed-off-by: Flavio Ceolin --- .../subsys/pm/power_states_api/CMakeLists.txt | 2 +- .../boards/native_sim.overlay | 18 +++-- .../dts/bindings/test-device-pm.yaml | 10 +++ tests/subsys/pm/power_states_api/prj.conf | 1 + tests/subsys/pm/power_states_api/src/main.c | 50 ++++++++++--- .../pm/power_states_api/src/test_driver.c | 70 +++++++++++++++++++ .../pm/power_states_api/src/test_driver.h | 24 +++++++ 7 files changed, 161 insertions(+), 14 deletions(-) create mode 100644 tests/subsys/pm/power_states_api/dts/bindings/test-device-pm.yaml create mode 100644 tests/subsys/pm/power_states_api/src/test_driver.c create mode 100644 tests/subsys/pm/power_states_api/src/test_driver.h diff --git a/tests/subsys/pm/power_states_api/CMakeLists.txt b/tests/subsys/pm/power_states_api/CMakeLists.txt index 4e8711798fa6b..7f506a835a638 100644 --- a/tests/subsys/pm/power_states_api/CMakeLists.txt +++ b/tests/subsys/pm/power_states_api/CMakeLists.txt @@ -6,4 +6,4 @@ cmake_minimum_required(VERSION 3.20.0) find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) project(pm-states-test) -target_sources(app PRIVATE src/main.c) +target_sources(app PRIVATE src/main.c src/test_driver.c) diff --git a/tests/subsys/pm/power_states_api/boards/native_sim.overlay b/tests/subsys/pm/power_states_api/boards/native_sim.overlay index e7222630000ba..1b4b740761975 100644 --- a/tests/subsys/pm/power_states_api/boards/native_sim.overlay +++ b/tests/subsys/pm/power_states_api/boards/native_sim.overlay @@ -20,21 +20,29 @@ state1: state1 { compatible = "zephyr,power-state"; - power-state-name = "suspend-to-ram"; - min-residency-us = <50000>; - exit-latency-us = <500>; + power-state-name = "standby"; + min-residency-us = <20000>; + exit-latency-us = <200>; }; state2: state2 { compatible = "zephyr,power-state"; - power-state-name = "standby"; + power-state-name = "suspend-to-ram"; + min-residency-us = <50000>; + exit-latency-us = <500>; }; state3: state3 { compatible = "zephyr,power-state"; - power-state-name = "suspend-to-ram"; + power-state-name = "suspend-to-disk"; status = "disabled"; }; }; }; + + test_dev: test_dev { + compatible = "test-device-pm"; + status = "okay"; + zephyr,disabling-power-states = <&state1 &state2>; + }; }; diff --git a/tests/subsys/pm/power_states_api/dts/bindings/test-device-pm.yaml b/tests/subsys/pm/power_states_api/dts/bindings/test-device-pm.yaml new file mode 100644 index 0000000000000..ddd6a29a0a71c --- /dev/null +++ b/tests/subsys/pm/power_states_api/dts/bindings/test-device-pm.yaml @@ -0,0 +1,10 @@ +# Copyright (c) 2024 Intel Corporation. +# SPDX-License-Identifier: Apache-2.0 + +include: [base.yaml, pm.yaml] + +description: | + This binding provides resources required to build and run the + tests/subsys/pm/power_states_api test in Zephyr. + +compatible: "test-device-pm" diff --git a/tests/subsys/pm/power_states_api/prj.conf b/tests/subsys/pm/power_states_api/prj.conf index e623494111a97..ae15587934f4f 100644 --- a/tests/subsys/pm/power_states_api/prj.conf +++ b/tests/subsys/pm/power_states_api/prj.conf @@ -1,2 +1,3 @@ CONFIG_PM=y +CONFIG_PM_DEVICE=y CONFIG_ZTEST=y diff --git a/tests/subsys/pm/power_states_api/src/main.c b/tests/subsys/pm/power_states_api/src/main.c index dac96e9e2993c..ae53ab1b7de4b 100644 --- a/tests/subsys/pm/power_states_api/src/main.c +++ b/tests/subsys/pm/power_states_api/src/main.c @@ -4,6 +4,9 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include "test_driver.h" + +#include #include #include #include @@ -11,17 +14,24 @@ /* Last state has not declared a minimum residency, so it should be * set the default 0 value */ -static struct pm_state_info infos[] = {{PM_STATE_SUSPEND_TO_IDLE, 0, false, 10000, 100}, - {PM_STATE_SUSPEND_TO_RAM, 0, false, 50000, 500}, {PM_STATE_STANDBY, 0, false, 0}}; +static struct pm_state_info infos[] = {{PM_STATE_SUSPEND_TO_IDLE, 0, 10000, 100}, + {PM_STATE_STANDBY, 0, 20000, 200}, {PM_STATE_SUSPEND_TO_RAM, 0, 50000, 500}}; static enum pm_state states[] = {PM_STATE_SUSPEND_TO_IDLE, - PM_STATE_SUSPEND_TO_RAM, PM_STATE_STANDBY}; + PM_STATE_STANDBY, PM_STATE_SUSPEND_TO_RAM}; static enum pm_state wrong_states[] = {PM_STATE_SUSPEND_TO_DISK, PM_STATE_SUSPEND_TO_RAM, PM_STATE_SUSPEND_TO_RAM}; +static uint8_t suspend_to_ram_count; + void pm_state_set(enum pm_state state, uint8_t substate_id) { ARG_UNUSED(substate_id); - ARG_UNUSED(state); + + if (state == PM_STATE_SUSPEND_TO_RAM) { + suspend_to_ram_count++; + } + + k_cpu_idle(); } void pm_state_exit_post_ops(enum pm_state state, uint8_t substate_id) @@ -45,12 +55,12 @@ ZTEST(power_states_1cpu, test_power_states) zassert_true(ARRAY_SIZE(states) == dts_states_len, "Invalid number of pm states"); - zassert_true(memcmp(infos, dts_infos, sizeof(dts_infos)) == 0, + zassert_true(memcmp(infos, dts_infos, ARRAY_SIZE(dts_infos)) == 0, "Invalid pm_state_info array"); - zassert_true(memcmp(states, dts_states, sizeof(dts_states)) == 0, + zassert_true(memcmp(states, dts_states, ARRAY_SIZE(dts_states)) == 0, "Invalid pm-states array"); - zassert_false(memcmp(wrong_states, dts_states, sizeof(dts_states)) == 0, + zassert_false(memcmp(wrong_states, dts_states, ARRAY_SIZE(dts_states)) == 0, "Invalid pm-states array"); ret = pm_state_cpu_get_all(CONFIG_MP_MAX_NUM_CPUS + 1, &cpu_states); @@ -59,9 +69,33 @@ ZTEST(power_states_1cpu, test_power_states) ret = pm_state_cpu_get_all(0U, &cpu_states); zassert_true(ret == dts_states_len, "Invalid number of pm states"); - zassert_true(memcmp(cpu_states, dts_infos, sizeof(dts_infos)) == 0, + zassert_true(memcmp(cpu_states, dts_infos, ARRAY_SIZE(dts_infos)) == 0, "Invalid pm_state_info array"); } +ZTEST(power_states_1cpu, test_device_power_state_constraints) +{ + static const struct device *const dev = + DEVICE_DT_GET(DT_NODELABEL(test_dev)); + suspend_to_ram_count = 0; + + test_driver_async_operation(dev); + + /** Lets sleep long enough to suspend the CPU with `suspend to ram` + * power state. If everything works well the cpu should not use this + * state due the constraint set by `test_dev`. + */ + k_sleep(K_USEC(60000)); + + zassert_true(suspend_to_ram_count == 0, "Invalid suspend to ram count"); + + /** Now lets check ensure that if there is no ongoing work + * the cpu will suspend to ram. + */ + k_sleep(K_MSEC(600)); + + zassert(suspend_to_ram_count != 0, "Not suspended to ram"); +} + ZTEST_SUITE(power_states_1cpu, NULL, NULL, ztest_simple_1cpu_before, ztest_simple_1cpu_after, NULL); diff --git a/tests/subsys/pm/power_states_api/src/test_driver.c b/tests/subsys/pm/power_states_api/src/test_driver.c new file mode 100644 index 0000000000000..d5c90b5af279d --- /dev/null +++ b/tests/subsys/pm/power_states_api/src/test_driver.c @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2024 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "test_driver.h" + +#include +#include +#include +#include + +struct test_driver_data { + const struct device *self; + struct k_timer timer; + bool ongoing; +}; + +static int test_driver_action(const struct device *dev, + enum pm_device_action action) +{ + ARG_UNUSED(dev); + ARG_UNUSED(action); + + return 0; +} + +static void timer_expire_cb(struct k_timer *timer) +{ + struct test_driver_data *data = k_timer_user_data_get(timer); + + data->ongoing = false; + k_timer_stop(timer); + pm_policy_device_power_lock_put(data->self); +} + +void test_driver_async_operation(const struct device *dev) +{ + struct test_driver_data *data = dev->data; + + data->ongoing = true; + pm_policy_device_power_lock_get(dev); + + /** Lets set a timer big enough to ensure that any deep + * sleep state would be suitable but constraints will + * make only state0 (suspend-to-idle) will be used. + */ + k_timer_start(&data->timer, K_MSEC(500), K_NO_WAIT); +} + +int test_driver_init(const struct device *dev) +{ + struct test_driver_data *data = dev->data; + + data->self = dev; + + k_timer_init(&data->timer, timer_expire_cb, NULL); + k_timer_user_data_set(&data->timer, data); + + return 0; +} + +PM_DEVICE_DT_DEFINE(DT_NODELABEL(test_dev), test_driver_action); + +static struct test_driver_data data; + +DEVICE_DT_DEFINE(DT_NODELABEL(test_dev), test_driver_init, + PM_DEVICE_DT_GET(DT_NODELABEL(test_dev)), &data, NULL, POST_KERNEL, + CONFIG_KERNEL_INIT_PRIORITY_DEVICE, NULL); diff --git a/tests/subsys/pm/power_states_api/src/test_driver.h b/tests/subsys/pm/power_states_api/src/test_driver.h new file mode 100644 index 0000000000000..5e28759d86b29 --- /dev/null +++ b/tests/subsys/pm/power_states_api/src/test_driver.h @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2024 Intel Corporation. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef TESTS_SUBSYS_PM_POWER_STATES_API_TEST_DRIVER_H_ +#define TESTS_SUBSYS_PM_POWER_STATES_API_TEST_DRIVER_H_ + +#include + +/** + * @brief Async operation. + * + * The device simulates an async operation and shall + * not be suspended while is in progress. This included + * the SoC not transition to certain power states. + * + * @param dev Device instance. + */ +void test_driver_async_operation(const struct device *dev); + + +#endif /* TESTS_SUBSYS_PM_POWER_STATES_API_TEST_DRIVER_H_ */ From 73b755d817156fe92e2ae16d27af913035d66446 Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Wed, 24 Apr 2024 16:17:00 -0700 Subject: [PATCH 2074/2849] pm: Add a symbol for device power state constraints Add a symbol to enable device power state constraints this saves resources when this feature is not needed. Signed-off-by: Flavio Ceolin --- include/zephyr/device.h | 14 ++++++++------ subsys/pm/Kconfig | 8 ++++++++ subsys/pm/policy.c | 4 ++-- tests/subsys/pm/power_states_api/prj.conf | 1 + 4 files changed, 19 insertions(+), 8 deletions(-) diff --git a/include/zephyr/device.h b/include/zephyr/device.h index e15f426f952c8..90774ef16698c 100644 --- a/include/zephyr/device.h +++ b/include/zephyr/device.h @@ -419,7 +419,7 @@ struct device { */ Z_DEVICE_DEPS_CONST device_handle_t *deps; #endif /* CONFIG_DEVICE_DEPS */ -#if defined(CONFIG_PM) || defined(__DOXYGEN__) +#if defined(CONFIG_PM_POLICY_DEVICE_CONSTRAINTS) || defined(__DOXYGEN__) struct pm_state_constraint const *pm_constraints; size_t pm_constraints_size; #endif /* CONFIG_PM */ @@ -871,7 +871,7 @@ __syscall int device_init(const struct device *dev); #endif /* CONFIG_DEVICE_DEPS */ -#if defined(CONFIG_PM) || defined(__DOXYGEN__) +#if defined(CONFIG_PM_POLICY_DEVICE_CONSTRAINTS) || defined(__DOXYGEN__) /** * @brief Synthesize the name of the object that holds a device pm constraint. @@ -921,7 +921,7 @@ __syscall int device_init(const struct device *dev); Z_DEVICE_PM_CONSTRAINTS_NAME(dev_id)[] = \ Z_PM_STATE_CONSTRAINTS_FROM_DT_DEVICE(node_id); -#endif /* CONFIG_PM */ +#endif /* CONFIG_PM_POLICY_DEVICE_CONSTRAINTS */ /** * @brief Init sub-priority of the device @@ -971,8 +971,10 @@ __syscall int device_init(const struct device *dev); .state = (state_), \ .data = (data_), \ IF_ENABLED(CONFIG_DEVICE_DEPS, (.deps = (deps_),)) /**/ \ - IF_ENABLED(CONFIG_PM, (.pm_constraints = (constraints_),)) \ - IF_ENABLED(CONFIG_PM, (.pm_constraints_size = (constraints_size_),)) \ + IF_ENABLED(CONFIG_PM_POLICY_DEVICE_CONSTRAINTS, \ + (.pm_constraints = (constraints_),)) \ + IF_ENABLED(CONFIG_PM_POLICY_DEVICE_CONSTRAINTS, \ + (.pm_constraints_size = (constraints_size_),)) \ IF_ENABLED(CONFIG_PM_DEVICE, ({ .pm_base = (pm_),})) /**/ \ } @@ -1094,7 +1096,7 @@ __syscall int device_init(const struct device *dev); IF_ENABLED(CONFIG_DEVICE_DEPS, \ (Z_DEVICE_DEPS_DEFINE(node_id, dev_id, __VA_ARGS__);)) \ \ - IF_ENABLED(CONFIG_PM, \ + IF_ENABLED(CONFIG_PM_POLICY_DEVICE_CONSTRAINTS, \ (Z_DEVICE_PM_CONSTRAINTS_DEFINE(node_id, dev_id, __VA_ARGS__);))\ Z_DEVICE_BASE_DEFINE(node_id, dev_id, name, pm, data, config, level, \ prio, api, state, Z_DEVICE_DEPS_NAME(dev_id), \ diff --git a/subsys/pm/Kconfig b/subsys/pm/Kconfig index 2b7ef998415db..94d082c85b7a1 100644 --- a/subsys/pm/Kconfig +++ b/subsys/pm/Kconfig @@ -72,6 +72,14 @@ config PM_POLICY_CUSTOM endchoice +config PM_POLICY_DEVICE_CONSTRAINTS + bool "Power state constraints per device" + help + This option allows devices to have a list of power states + that when the system transition to them, cause power loss in the device. + This used to set and release power state constraints when + it is needed by the device. + endif # PM config PM_DEVICE diff --git a/subsys/pm/policy.c b/subsys/pm/policy.c index 0d9922ffd6662..942fb900bf953 100644 --- a/subsys/pm/policy.c +++ b/subsys/pm/policy.c @@ -332,7 +332,7 @@ void pm_policy_event_unregister(struct pm_policy_event *evt) void pm_policy_device_power_lock_get(const struct device *dev) { -#if DT_HAS_COMPAT_STATUS_OKAY(zephyr_power_state) +#if DT_HAS_COMPAT_STATUS_OKAY(zephyr_power_state) && defined(CONFIG_PM_POLICY_DEVICE_CONSTRAINTS) for (size_t i = 0; i < dev->pm_constraints_size; i++) { pm_policy_state_lock_get(dev->pm_constraints[i].state, dev->pm_constraints[i].substate_id); @@ -342,7 +342,7 @@ void pm_policy_device_power_lock_get(const struct device *dev) void pm_policy_device_power_lock_put(const struct device *dev) { -#if DT_HAS_COMPAT_STATUS_OKAY(zephyr_power_state) +#if DT_HAS_COMPAT_STATUS_OKAY(zephyr_power_state) && defined(CONFIG_PM_POLICY_DEVICE_CONSTRAINTS) for (size_t i = 0; i < dev->pm_constraints_size; i++) { pm_policy_state_lock_put(dev->pm_constraints[i].state, dev->pm_constraints[i].substate_id); diff --git a/tests/subsys/pm/power_states_api/prj.conf b/tests/subsys/pm/power_states_api/prj.conf index ae15587934f4f..d0b65f5a66340 100644 --- a/tests/subsys/pm/power_states_api/prj.conf +++ b/tests/subsys/pm/power_states_api/prj.conf @@ -1,3 +1,4 @@ CONFIG_PM=y CONFIG_PM_DEVICE=y +CONFIG_PM_POLICY_DEVICE_CONSTRAINTS=y CONFIG_ZTEST=y From 9ba65abcb3685f4971cd44ec480f1ea600f77d7b Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Thu, 30 May 2024 10:28:06 -0700 Subject: [PATCH 2075/2849] doc: pm: Add information about device and system constraint Add information about device power management and system power management constarints. Signed-off-by: Flavio Ceolin --- doc/services/pm/device.rst | 90 ++++++++++++++++++++++++++++++++++++++ doc/services/pm/system.rst | 2 + 2 files changed, 92 insertions(+) diff --git a/doc/services/pm/device.rst b/doc/services/pm/device.rst index e473fe3f4bfcf..379ebfbef74fb 100644 --- a/doc/services/pm/device.rst +++ b/doc/services/pm/device.rst @@ -307,6 +307,96 @@ the system will not do power management on it. After the device is no longer doing an operation and can be suspended, it should call :c:func:`pm_device_busy_clear`. +.. _pm-device-constraint: + +Device Power Management X System Power Management +************************************************* + +When managing power in embedded systems, it's crucial to understand +the interplay between device power state and the overall system power +state. Some devices may have dependencies on the system power +state. For example, certain low-power states of the SoC might not +supply power to peripheral devices, leading to problems if the device +is in the middle of an operation. Proper coordination is essential to +maintain system stability and data integrity. + +To avoid this sort of problem, devices must :ref:`get and release lock ` +power states that cause power loss during an operation. + +Zephyr provides a mechanism for devices to declare which power states cause power +loss and an API that automatically get and put lock on them. This feature is +enabled setting :kconfig:option:`CONFIG_PM_POLICY_DEVICE_CONSTRAINTS` to ``y``. + +Once this feature is enabled, devices must declare in devicetree which +states cause power loss. In the following example, device ``test_dev`` +says that power states ``state1`` and ``state2`` cause power loss. + +.. code-block:: devicetree + + power-states { + state0: state0 { + compatible = "zephyr,power-state"; + power-state-name = "suspend-to-idle"; + min-residency-us = <10000>; + exit-latency-us = <100>; + }; + + state1: state1 { + compatible = "zephyr,power-state"; + power-state-name = "standby"; + min-residency-us = <20000>; + exit-latency-us = <200>; + }; + + state2: state2 { + compatible = "zephyr,power-state"; + power-state-name = "suspend-to-ram"; + min-residency-us = <50000>; + exit-latency-us = <500>; + }; + + state3: state3 { + compatible = "zephyr,power-state"; + power-state-name = "suspend-to-ram"; + status = "disabled"; + }; + }; + + test_dev: test_dev { + compatible = "test-device-pm"; + status = "okay"; + zephyr,disabling-power-states = <&state1 &state2>; + }; + +After that devices can lock these state calling +:c:func:`pm_policy_device_power_lock_get` and release with +:c:func:`pm_policy_device_power_lock_put`. For example: + +.. code-block:: C + + static void timer_expire_cb(struct k_timer *timer) + { + struct test_driver_data *data = k_timer_user_data_get(timer); + + data->ongoing = false; + k_timer_stop(timer); + pm_policy_device_power_lock_put(data->self); + } + + void test_driver_async_operation(const struct device *dev) + { + struct test_driver_data *data = dev->data; + + data->ongoing = true; + pm_policy_device_power_lock_get(dev); + + /** Lets set a timer big enough to ensure that any deep + * sleep state would be suitable but constraints will + * make only state0 (suspend-to-idle) will be used. + */ + k_timer_start(&data->timer, K_MSEC(500), K_NO_WAIT); + } + Wakeup capability ***************** diff --git a/doc/services/pm/system.rst b/doc/services/pm/system.rst index d6ec306a20013..49ba81e935731 100644 --- a/doc/services/pm/system.rst +++ b/doc/services/pm/system.rst @@ -122,6 +122,8 @@ remaining time until the next scheduled timeout. An example of an application that defines its own policy can be found in :zephyr_file:`tests/subsys/pm/power_mgmt/`. +.. _pm-policy-power-states: + Policy and Power States ------------------------ From e21a021ed6263a2b8ae4451ca2be71488c13c028 Mon Sep 17 00:00:00 2001 From: Vincent Geneves Date: Mon, 5 Feb 2024 08:06:14 +0100 Subject: [PATCH 2076/2849] drivers: gpio: pcal64xxa: give semaphore in case of error In function pcal64xxa_process_input, lock was not released in case of error when calling inputs_read. This was causing an infinite wait in the following calls of functions using I2C bus. Signed-off-by: Vincent Geneves --- drivers/gpio/gpio_pcal64xxa.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpio/gpio_pcal64xxa.c b/drivers/gpio/gpio_pcal64xxa.c index 687cf53c1bf26..93cc4814993e5 100644 --- a/drivers/gpio/gpio_pcal64xxa.c +++ b/drivers/gpio/gpio_pcal64xxa.c @@ -204,6 +204,7 @@ static int pcal64xxa_process_input(const struct device *dev, gpio_port_value_t * if (rc != 0) { LOG_ERR("failed to read inputs from device %s", dev->name); + k_sem_give(&drv_data->lock); return rc; } From 79c93dd5ecfde7b6af6109672b856bbf230bbda1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Chru=C5=9Bci=C5=84ski?= Date: Mon, 22 Jan 2024 13:29:15 +0100 Subject: [PATCH 2077/2849] drivers: serial: Add gpio management to low power mode MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When low power mode is enabled then whenever UARTE is not active, driver attempts to put the peripheral into the lowest power state by stopping and disabling UARTE. However, it did not put pins into sleep state which could lead to increased current consumption. Adding pins state handling to the low power mode. Pins are put into sleep state only if CONFIG_PM_DEVICE=y. Signed-off-by: Krzysztof Chruściński --- drivers/serial/uart_nrfx_uarte.c | 61 ++++++++++++++++++++++++-------- 1 file changed, 46 insertions(+), 15 deletions(-) diff --git a/drivers/serial/uart_nrfx_uarte.c b/drivers/serial/uart_nrfx_uarte.c index d2b36017051b7..990f4f3fb2ac6 100644 --- a/drivers/serial/uart_nrfx_uarte.c +++ b/drivers/serial/uart_nrfx_uarte.c @@ -516,6 +516,20 @@ static int wait_tx_ready(const struct device *dev) return key; } +#if defined(UARTE_ANY_ASYNC) || defined(CONFIG_PM_DEVICE) +static int pins_state_change(const struct device *dev, bool on) +{ + const struct uarte_nrfx_config *config = dev->config; + + if (config->flags & UARTE_CFG_FLAG_GPIO_MGMT) { + return pinctrl_apply_state(config->pcfg, + on ? PINCTRL_STATE_DEFAULT : PINCTRL_STATE_SLEEP); + } + + return 0; +} +#endif + #ifdef UARTE_ANY_ASYNC /* Using Macro instead of static inline function to handle NO_OPTIMIZATIONS case @@ -526,7 +540,7 @@ static int wait_tx_ready(const struct device *dev) #endif /* UARTE_ANY_ASYNC */ -static void uarte_enable(const struct device *dev, uint32_t mask) +static int uarte_enable(const struct device *dev, uint32_t mask) { #ifdef UARTE_ANY_ASYNC const struct uarte_nrfx_config *config = dev->config; @@ -534,8 +548,14 @@ static void uarte_enable(const struct device *dev, uint32_t mask) if (data->async) { bool disabled = data->async->low_power_mask == 0; + int ret; data->async->low_power_mask |= mask; + ret = pins_state_change(dev, true); + if (ret < 0) { + return ret; + } + if (HW_RX_COUNTING_ENABLED(data) && disabled) { const nrfx_timer_t *timer = &config->timer; @@ -548,6 +568,8 @@ static void uarte_enable(const struct device *dev, uint32_t mask) } #endif nrf_uarte_enable(get_uarte_instance(dev)); + + return 0; } /* At this point we should have irq locked and any previous transfer completed. @@ -571,7 +593,7 @@ static void tx_start(const struct device *dev, const uint8_t *buf, size_t len) nrf_uarte_event_clear(uarte, NRF_UARTE_EVENT_TXSTOPPED); if (config->flags & UARTE_CFG_FLAG_LOW_POWER) { - uarte_enable(dev, UARTE_LOW_POWER_TX); + (void)uarte_enable(dev, UARTE_LOW_POWER_TX); nrf_uarte_int_enable(uarte, NRF_UARTE_INT_TXSTOPPED_MASK); } @@ -853,6 +875,7 @@ static int uarte_nrfx_rx_enable(const struct device *dev, uint8_t *buf, struct uarte_nrfx_data *data = dev->data; const struct uarte_nrfx_config *cfg = dev->config; NRF_UARTE_Type *uarte = get_uarte_instance(dev); + int ret = 0; if (cfg->disable_rx) { __ASSERT(false, "TX only UARTE instance"); @@ -906,7 +929,7 @@ static int uarte_nrfx_rx_enable(const struct device *dev, uint8_t *buf, if (cfg->flags & UARTE_CFG_FLAG_LOW_POWER) { unsigned int key = irq_lock(); - uarte_enable(dev, UARTE_LOW_POWER_RX); + ret = uarte_enable(dev, UARTE_LOW_POWER_RX); irq_unlock(key); } @@ -1279,6 +1302,10 @@ static void async_uart_release(const struct device *dev, uint32_t dir_mask) } uart_disable(dev); + int err = pins_state_change(dev, false); + + (void)err; + __ASSERT_NO_MSG(err == 0); } irq_unlock(key); @@ -1875,14 +1902,21 @@ static int uarte_nrfx_pm_action(const struct device *dev, const struct uarte_nrfx_config *cfg = dev->config; int ret; +#ifdef UARTE_ANY_ASYNC + /* If low power mode for asynchronous mode is used then there is nothing to do here. + * In low power mode UARTE is turned off whenever there is no activity. + */ + if (data->async && (cfg->flags & UARTE_CFG_FLAG_LOW_POWER)) { + return 0; + } +#endif + switch (action) { case PM_DEVICE_ACTION_RESUME: - if (cfg->flags & UARTE_CFG_FLAG_GPIO_MGMT) { - ret = pinctrl_apply_state(cfg->pcfg, - PINCTRL_STATE_DEFAULT); - if (ret < 0) { - return ret; - } + + ret = pins_state_change(dev, true); + if (ret < 0) { + return ret; } nrf_uarte_enable(uarte); @@ -1951,12 +1985,9 @@ static int uarte_nrfx_pm_action(const struct device *dev, wait_for_tx_stopped(dev); uart_disable(dev); - if (cfg->flags & UARTE_CFG_FLAG_GPIO_MGMT) { - ret = pinctrl_apply_state(cfg->pcfg, - PINCTRL_STATE_SLEEP); - if (ret < 0) { - return ret; - } + ret = pins_state_change(dev, false); + if (ret < 0) { + return ret; } break; From 8136f740df63878273625d41e46e9c1497598042 Mon Sep 17 00:00:00 2001 From: Emil Gydesen Date: Wed, 5 Jun 2024 23:07:20 +0200 Subject: [PATCH 2078/2849] tests: Bluetooth: Move audio related BTP files Move the audio related files to a new subdirectory called audio. The purpose of this is to clean up the file structure a bit, and also allow for better filtering of the files. Signed-off-by: Emil Gydesen --- MAINTAINERS.yml | 1 + tests/bluetooth/tester/CMakeLists.txt | 69 +------------------ .../bluetooth/tester/src/audio/CMakeLists.txt | 69 +++++++++++++++++++ .../tester/src/{ => audio}/btp/btp_aics.h | 0 .../tester/src/{ => audio}/btp/btp_ascs.h | 0 .../tester/src/{ => audio}/btp/btp_bap.h | 0 .../tester/src/{ => audio}/btp/btp_cap.h | 0 .../tester/src/{ => audio}/btp/btp_cas.h | 0 .../tester/src/{ => audio}/btp/btp_ccp.h | 0 .../tester/src/{ => audio}/btp/btp_csip.h | 0 .../tester/src/{ => audio}/btp/btp_csis.h | 0 .../tester/src/{ => audio}/btp/btp_hap.h | 0 .../tester/src/{ => audio}/btp/btp_has.h | 0 .../tester/src/{ => audio}/btp/btp_mcp.h | 0 .../tester/src/{ => audio}/btp/btp_mcs.h | 0 .../tester/src/{ => audio}/btp/btp_micp.h | 0 .../tester/src/{ => audio}/btp/btp_mics.h | 0 .../tester/src/{ => audio}/btp/btp_pacs.h | 0 .../tester/src/{ => audio}/btp/btp_tbs.h | 0 .../tester/src/{ => audio}/btp/btp_tmap.h | 0 .../tester/src/{ => audio}/btp/btp_vcp.h | 0 .../tester/src/{ => audio}/btp/btp_vcs.h | 0 .../tester/src/{ => audio}/btp/btp_vocs.h | 0 .../tester/src/{ => audio}/btp_aics.c | 0 .../tester/src/{ => audio}/btp_bap.c | 0 .../src/{ => audio}/btp_bap_audio_stream.c | 0 .../src/{ => audio}/btp_bap_audio_stream.h | 0 .../src/{ => audio}/btp_bap_broadcast.c | 0 .../src/{ => audio}/btp_bap_broadcast.h | 0 .../tester/src/{ => audio}/btp_bap_unicast.c | 0 .../tester/src/{ => audio}/btp_bap_unicast.h | 0 .../tester/src/{ => audio}/btp_cap.c | 0 .../tester/src/{ => audio}/btp_cas.c | 0 .../tester/src/{ => audio}/btp_ccp.c | 0 .../tester/src/{ => audio}/btp_csip.c | 0 .../tester/src/{ => audio}/btp_csis.c | 0 .../tester/src/{ => audio}/btp_hap.c | 0 .../tester/src/{ => audio}/btp_has.c | 0 .../tester/src/{ => audio}/btp_mcp.c | 0 .../tester/src/{ => audio}/btp_micp.c | 0 .../tester/src/{ => audio}/btp_tmap.c | 0 .../tester/src/{ => audio}/btp_vcp.c | 0 42 files changed, 73 insertions(+), 66 deletions(-) create mode 100644 tests/bluetooth/tester/src/audio/CMakeLists.txt rename tests/bluetooth/tester/src/{ => audio}/btp/btp_aics.h (100%) rename tests/bluetooth/tester/src/{ => audio}/btp/btp_ascs.h (100%) rename tests/bluetooth/tester/src/{ => audio}/btp/btp_bap.h (100%) rename tests/bluetooth/tester/src/{ => audio}/btp/btp_cap.h (100%) rename tests/bluetooth/tester/src/{ => audio}/btp/btp_cas.h (100%) rename tests/bluetooth/tester/src/{ => audio}/btp/btp_ccp.h (100%) rename tests/bluetooth/tester/src/{ => audio}/btp/btp_csip.h (100%) rename tests/bluetooth/tester/src/{ => audio}/btp/btp_csis.h (100%) rename tests/bluetooth/tester/src/{ => audio}/btp/btp_hap.h (100%) rename tests/bluetooth/tester/src/{ => audio}/btp/btp_has.h (100%) rename tests/bluetooth/tester/src/{ => audio}/btp/btp_mcp.h (100%) rename tests/bluetooth/tester/src/{ => audio}/btp/btp_mcs.h (100%) rename tests/bluetooth/tester/src/{ => audio}/btp/btp_micp.h (100%) rename tests/bluetooth/tester/src/{ => audio}/btp/btp_mics.h (100%) rename tests/bluetooth/tester/src/{ => audio}/btp/btp_pacs.h (100%) rename tests/bluetooth/tester/src/{ => audio}/btp/btp_tbs.h (100%) rename tests/bluetooth/tester/src/{ => audio}/btp/btp_tmap.h (100%) rename tests/bluetooth/tester/src/{ => audio}/btp/btp_vcp.h (100%) rename tests/bluetooth/tester/src/{ => audio}/btp/btp_vcs.h (100%) rename tests/bluetooth/tester/src/{ => audio}/btp/btp_vocs.h (100%) rename tests/bluetooth/tester/src/{ => audio}/btp_aics.c (100%) rename tests/bluetooth/tester/src/{ => audio}/btp_bap.c (100%) rename tests/bluetooth/tester/src/{ => audio}/btp_bap_audio_stream.c (100%) rename tests/bluetooth/tester/src/{ => audio}/btp_bap_audio_stream.h (100%) rename tests/bluetooth/tester/src/{ => audio}/btp_bap_broadcast.c (100%) rename tests/bluetooth/tester/src/{ => audio}/btp_bap_broadcast.h (100%) rename tests/bluetooth/tester/src/{ => audio}/btp_bap_unicast.c (100%) rename tests/bluetooth/tester/src/{ => audio}/btp_bap_unicast.h (100%) rename tests/bluetooth/tester/src/{ => audio}/btp_cap.c (100%) rename tests/bluetooth/tester/src/{ => audio}/btp_cas.c (100%) rename tests/bluetooth/tester/src/{ => audio}/btp_ccp.c (100%) rename tests/bluetooth/tester/src/{ => audio}/btp_csip.c (100%) rename tests/bluetooth/tester/src/{ => audio}/btp_csis.c (100%) rename tests/bluetooth/tester/src/{ => audio}/btp_hap.c (100%) rename tests/bluetooth/tester/src/{ => audio}/btp_has.c (100%) rename tests/bluetooth/tester/src/{ => audio}/btp_mcp.c (100%) rename tests/bluetooth/tester/src/{ => audio}/btp_micp.c (100%) rename tests/bluetooth/tester/src/{ => audio}/btp_tmap.c (100%) rename tests/bluetooth/tester/src/{ => audio}/btp_vcp.c (100%) diff --git a/MAINTAINERS.yml b/MAINTAINERS.yml index a22323b69fa80..52d7a305e1ec9 100644 --- a/MAINTAINERS.yml +++ b/MAINTAINERS.yml @@ -446,6 +446,7 @@ Bluetooth Audio: - tests/bsim/bluetooth/audio_samples/ - tests/bluetooth/shell/audio.conf - tests/bluetooth/tester/overlay-le-audio.conf + - tests/bluetooth/tester/src/audio/ - doc/connectivity/bluetooth/api/audio/ - samples/bluetooth/bap*/ - samples/bluetooth/hap*/ diff --git a/tests/bluetooth/tester/CMakeLists.txt b/tests/bluetooth/tester/CMakeLists.txt index eb3ad4bda2445..2493fd11f9991 100644 --- a/tests/bluetooth/tester/CMakeLists.txt +++ b/tests/bluetooth/tester/CMakeLists.txt @@ -9,7 +9,6 @@ project(tester) zephyr_library_include_directories(${ZEPHYR_BASE}/samples/bluetooth) zephyr_library_include_directories(${ZEPHYR_BASE}/subsys/bluetooth/mesh) -zephyr_library_include_directories(${ZEPHYR_BASE}/subsys/bluetooth/audio) zephyr_library_include_directories(${ZEPHYR_BASE}/subsys/bluetooth/host) target_sources(app PRIVATE src/main.c @@ -26,75 +25,13 @@ if(CONFIG_BT_MESH) target_sources(app PRIVATE src/btp_mesh.c) endif() -target_sources_ifdef(CONFIG_BT_VCP_VOL_REND app PRIVATE src/btp_vcp.c) - if(CONFIG_BT_IAS OR CONFIG_BT_IAS_CLIENT) target_sources(app PRIVATE src/btp_ias.c) endif() -if(CONFIG_BT_BAP_UNICAST OR BT_BAP_BROADCAST_SOURCE OR BT_BAP_BROADCAST_SINK) - target_sources(app PRIVATE - src/btp_bap_audio_stream.c - src/btp_bap.c - ) -endif() - -if(CONFIG_BT_BAP_UNICAST) - target_sources(app PRIVATE src/btp_bap_unicast.c) -endif() - -if(CONFIG_BT_BAP_BROADCAST_SOURCE OR CONFIG_BT_BAP_BROADCAST_SOURCE) - target_sources(app PRIVATE src/btp_bap_broadcast.c) -endif() - -if(CONFIG_BT_HAS) - target_sources(app PRIVATE src/btp_has.c) -endif() - -if (CONFIG_BT_CSIP_SET_MEMBER) - target_sources(app PRIVATE src/btp_csis.c) -endif() - -if (CONFIG_BT_CSIP_SET_COORDINATOR) - target_sources(app PRIVATE src/btp_csip.c) -endif() - -if(CONFIG_BT_MICP_MIC_DEV) - target_sources(app PRIVATE src/btp_micp.c) -endif() - -if(CONFIG_BT_AICS) - target_sources(app PRIVATE src/btp_aics.c) -endif() - -if (CONFIG_BT_TBS_CLIENT) - target_sources(app PRIVATE src/btp_ccp.c) -endif() - -if (CONFIG_BT_CAP_ACCEPTOR) - target_sources(app PRIVATE src/btp_cas.c) -endif() - -if(CONFIG_BT_MCC OR CONFIG_BT_MCS) - target_sources(app PRIVATE src/btp_mcp.c) -endif() - -if(CONFIG_BT_HAS) - target_sources(app PRIVATE src/btp_hap.c) -endif() - -if(CONFIG_BT_CAP_INITIATOR) - target_sources(app PRIVATE src/btp_cap.c) -endif() - -if(CONFIG_BT_TBS OR CONFIG_BT_GTBS) - target_sources(app PRIVATE src/btp_ccp.c) -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() + +zephyr_library_include_directories(src src/btp src/audio/btp) +add_subdirectory_ifdef(CONFIG_BT_AUDIO src/audio) diff --git a/tests/bluetooth/tester/src/audio/CMakeLists.txt b/tests/bluetooth/tester/src/audio/CMakeLists.txt new file mode 100644 index 0000000000000..38b4cac11cbe4 --- /dev/null +++ b/tests/bluetooth/tester/src/audio/CMakeLists.txt @@ -0,0 +1,69 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) + +zephyr_library_include_directories(${ZEPHYR_BASE}/subsys/bluetooth/audio) + +if(CONFIG_BT_VCP_VOL_REND) + target_sources(app PRIVATE btp_vcp.c) +endif() + +if(CONFIG_BT_BAP_UNICAST OR BT_BAP_BROADCAST_SOURCE OR BT_BAP_BROADCAST_SINK) + target_sources(app PRIVATE btp_bap_audio_stream.c btp_bap.c ) +endif() + +if(CONFIG_BT_BAP_UNICAST) + target_sources(app PRIVATE btp_bap_unicast.c) +endif() + +if(CONFIG_BT_BAP_BROADCAST_SOURCE OR CONFIG_BT_BAP_BROADCAST_SOURCE) + target_sources(app PRIVATE btp_bap_broadcast.c) +endif() + +if(CONFIG_BT_HAS) + target_sources(app PRIVATE btp_has.c) +endif() + +if (CONFIG_BT_CSIP_SET_MEMBER) + target_sources(app PRIVATE btp_csis.c) +endif() + +if (CONFIG_BT_CSIP_SET_COORDINATOR) + target_sources(app PRIVATE btp_csip.c) +endif() + +if(CONFIG_BT_MICP_MIC_DEV) + target_sources(app PRIVATE btp_micp.c) +endif() + +if(CONFIG_BT_AICS) + target_sources(app PRIVATE btp_aics.c) +endif() + +if (CONFIG_BT_TBS_CLIENT) + target_sources(app PRIVATE btp_ccp.c) +endif() + +if (CONFIG_BT_CAP_ACCEPTOR) + target_sources(app PRIVATE btp_cas.c) +endif() + +if(CONFIG_BT_MCC OR CONFIG_BT_MCS) + target_sources(app PRIVATE btp_mcp.c) +endif() + +if(CONFIG_BT_HAS) + target_sources(app PRIVATE btp_hap.c) +endif() + +if(CONFIG_BT_CAP_INITIATOR) + target_sources(app PRIVATE btp_cap.c) +endif() + +if(CONFIG_BT_TBS OR CONFIG_BT_GTBS) + target_sources(app PRIVATE btp_ccp.c) +endif() + +if(CONFIG_BT_TMAP) + target_sources(app PRIVATE btp_tmap.c) +endif() diff --git a/tests/bluetooth/tester/src/btp/btp_aics.h b/tests/bluetooth/tester/src/audio/btp/btp_aics.h similarity index 100% rename from tests/bluetooth/tester/src/btp/btp_aics.h rename to tests/bluetooth/tester/src/audio/btp/btp_aics.h diff --git a/tests/bluetooth/tester/src/btp/btp_ascs.h b/tests/bluetooth/tester/src/audio/btp/btp_ascs.h similarity index 100% rename from tests/bluetooth/tester/src/btp/btp_ascs.h rename to tests/bluetooth/tester/src/audio/btp/btp_ascs.h diff --git a/tests/bluetooth/tester/src/btp/btp_bap.h b/tests/bluetooth/tester/src/audio/btp/btp_bap.h similarity index 100% rename from tests/bluetooth/tester/src/btp/btp_bap.h rename to tests/bluetooth/tester/src/audio/btp/btp_bap.h diff --git a/tests/bluetooth/tester/src/btp/btp_cap.h b/tests/bluetooth/tester/src/audio/btp/btp_cap.h similarity index 100% rename from tests/bluetooth/tester/src/btp/btp_cap.h rename to tests/bluetooth/tester/src/audio/btp/btp_cap.h diff --git a/tests/bluetooth/tester/src/btp/btp_cas.h b/tests/bluetooth/tester/src/audio/btp/btp_cas.h similarity index 100% rename from tests/bluetooth/tester/src/btp/btp_cas.h rename to tests/bluetooth/tester/src/audio/btp/btp_cas.h diff --git a/tests/bluetooth/tester/src/btp/btp_ccp.h b/tests/bluetooth/tester/src/audio/btp/btp_ccp.h similarity index 100% rename from tests/bluetooth/tester/src/btp/btp_ccp.h rename to tests/bluetooth/tester/src/audio/btp/btp_ccp.h diff --git a/tests/bluetooth/tester/src/btp/btp_csip.h b/tests/bluetooth/tester/src/audio/btp/btp_csip.h similarity index 100% rename from tests/bluetooth/tester/src/btp/btp_csip.h rename to tests/bluetooth/tester/src/audio/btp/btp_csip.h diff --git a/tests/bluetooth/tester/src/btp/btp_csis.h b/tests/bluetooth/tester/src/audio/btp/btp_csis.h similarity index 100% rename from tests/bluetooth/tester/src/btp/btp_csis.h rename to tests/bluetooth/tester/src/audio/btp/btp_csis.h diff --git a/tests/bluetooth/tester/src/btp/btp_hap.h b/tests/bluetooth/tester/src/audio/btp/btp_hap.h similarity index 100% rename from tests/bluetooth/tester/src/btp/btp_hap.h rename to tests/bluetooth/tester/src/audio/btp/btp_hap.h diff --git a/tests/bluetooth/tester/src/btp/btp_has.h b/tests/bluetooth/tester/src/audio/btp/btp_has.h similarity index 100% rename from tests/bluetooth/tester/src/btp/btp_has.h rename to tests/bluetooth/tester/src/audio/btp/btp_has.h diff --git a/tests/bluetooth/tester/src/btp/btp_mcp.h b/tests/bluetooth/tester/src/audio/btp/btp_mcp.h similarity index 100% rename from tests/bluetooth/tester/src/btp/btp_mcp.h rename to tests/bluetooth/tester/src/audio/btp/btp_mcp.h diff --git a/tests/bluetooth/tester/src/btp/btp_mcs.h b/tests/bluetooth/tester/src/audio/btp/btp_mcs.h similarity index 100% rename from tests/bluetooth/tester/src/btp/btp_mcs.h rename to tests/bluetooth/tester/src/audio/btp/btp_mcs.h diff --git a/tests/bluetooth/tester/src/btp/btp_micp.h b/tests/bluetooth/tester/src/audio/btp/btp_micp.h similarity index 100% rename from tests/bluetooth/tester/src/btp/btp_micp.h rename to tests/bluetooth/tester/src/audio/btp/btp_micp.h diff --git a/tests/bluetooth/tester/src/btp/btp_mics.h b/tests/bluetooth/tester/src/audio/btp/btp_mics.h similarity index 100% rename from tests/bluetooth/tester/src/btp/btp_mics.h rename to tests/bluetooth/tester/src/audio/btp/btp_mics.h diff --git a/tests/bluetooth/tester/src/btp/btp_pacs.h b/tests/bluetooth/tester/src/audio/btp/btp_pacs.h similarity index 100% rename from tests/bluetooth/tester/src/btp/btp_pacs.h rename to tests/bluetooth/tester/src/audio/btp/btp_pacs.h diff --git a/tests/bluetooth/tester/src/btp/btp_tbs.h b/tests/bluetooth/tester/src/audio/btp/btp_tbs.h similarity index 100% rename from tests/bluetooth/tester/src/btp/btp_tbs.h rename to tests/bluetooth/tester/src/audio/btp/btp_tbs.h diff --git a/tests/bluetooth/tester/src/btp/btp_tmap.h b/tests/bluetooth/tester/src/audio/btp/btp_tmap.h similarity index 100% rename from tests/bluetooth/tester/src/btp/btp_tmap.h rename to tests/bluetooth/tester/src/audio/btp/btp_tmap.h diff --git a/tests/bluetooth/tester/src/btp/btp_vcp.h b/tests/bluetooth/tester/src/audio/btp/btp_vcp.h similarity index 100% rename from tests/bluetooth/tester/src/btp/btp_vcp.h rename to tests/bluetooth/tester/src/audio/btp/btp_vcp.h diff --git a/tests/bluetooth/tester/src/btp/btp_vcs.h b/tests/bluetooth/tester/src/audio/btp/btp_vcs.h similarity index 100% rename from tests/bluetooth/tester/src/btp/btp_vcs.h rename to tests/bluetooth/tester/src/audio/btp/btp_vcs.h diff --git a/tests/bluetooth/tester/src/btp/btp_vocs.h b/tests/bluetooth/tester/src/audio/btp/btp_vocs.h similarity index 100% rename from tests/bluetooth/tester/src/btp/btp_vocs.h rename to tests/bluetooth/tester/src/audio/btp/btp_vocs.h diff --git a/tests/bluetooth/tester/src/btp_aics.c b/tests/bluetooth/tester/src/audio/btp_aics.c similarity index 100% rename from tests/bluetooth/tester/src/btp_aics.c rename to tests/bluetooth/tester/src/audio/btp_aics.c diff --git a/tests/bluetooth/tester/src/btp_bap.c b/tests/bluetooth/tester/src/audio/btp_bap.c similarity index 100% rename from tests/bluetooth/tester/src/btp_bap.c rename to tests/bluetooth/tester/src/audio/btp_bap.c diff --git a/tests/bluetooth/tester/src/btp_bap_audio_stream.c b/tests/bluetooth/tester/src/audio/btp_bap_audio_stream.c similarity index 100% rename from tests/bluetooth/tester/src/btp_bap_audio_stream.c rename to tests/bluetooth/tester/src/audio/btp_bap_audio_stream.c diff --git a/tests/bluetooth/tester/src/btp_bap_audio_stream.h b/tests/bluetooth/tester/src/audio/btp_bap_audio_stream.h similarity index 100% rename from tests/bluetooth/tester/src/btp_bap_audio_stream.h rename to tests/bluetooth/tester/src/audio/btp_bap_audio_stream.h diff --git a/tests/bluetooth/tester/src/btp_bap_broadcast.c b/tests/bluetooth/tester/src/audio/btp_bap_broadcast.c similarity index 100% rename from tests/bluetooth/tester/src/btp_bap_broadcast.c rename to tests/bluetooth/tester/src/audio/btp_bap_broadcast.c diff --git a/tests/bluetooth/tester/src/btp_bap_broadcast.h b/tests/bluetooth/tester/src/audio/btp_bap_broadcast.h similarity index 100% rename from tests/bluetooth/tester/src/btp_bap_broadcast.h rename to tests/bluetooth/tester/src/audio/btp_bap_broadcast.h diff --git a/tests/bluetooth/tester/src/btp_bap_unicast.c b/tests/bluetooth/tester/src/audio/btp_bap_unicast.c similarity index 100% rename from tests/bluetooth/tester/src/btp_bap_unicast.c rename to tests/bluetooth/tester/src/audio/btp_bap_unicast.c diff --git a/tests/bluetooth/tester/src/btp_bap_unicast.h b/tests/bluetooth/tester/src/audio/btp_bap_unicast.h similarity index 100% rename from tests/bluetooth/tester/src/btp_bap_unicast.h rename to tests/bluetooth/tester/src/audio/btp_bap_unicast.h diff --git a/tests/bluetooth/tester/src/btp_cap.c b/tests/bluetooth/tester/src/audio/btp_cap.c similarity index 100% rename from tests/bluetooth/tester/src/btp_cap.c rename to tests/bluetooth/tester/src/audio/btp_cap.c diff --git a/tests/bluetooth/tester/src/btp_cas.c b/tests/bluetooth/tester/src/audio/btp_cas.c similarity index 100% rename from tests/bluetooth/tester/src/btp_cas.c rename to tests/bluetooth/tester/src/audio/btp_cas.c diff --git a/tests/bluetooth/tester/src/btp_ccp.c b/tests/bluetooth/tester/src/audio/btp_ccp.c similarity index 100% rename from tests/bluetooth/tester/src/btp_ccp.c rename to tests/bluetooth/tester/src/audio/btp_ccp.c diff --git a/tests/bluetooth/tester/src/btp_csip.c b/tests/bluetooth/tester/src/audio/btp_csip.c similarity index 100% rename from tests/bluetooth/tester/src/btp_csip.c rename to tests/bluetooth/tester/src/audio/btp_csip.c diff --git a/tests/bluetooth/tester/src/btp_csis.c b/tests/bluetooth/tester/src/audio/btp_csis.c similarity index 100% rename from tests/bluetooth/tester/src/btp_csis.c rename to tests/bluetooth/tester/src/audio/btp_csis.c diff --git a/tests/bluetooth/tester/src/btp_hap.c b/tests/bluetooth/tester/src/audio/btp_hap.c similarity index 100% rename from tests/bluetooth/tester/src/btp_hap.c rename to tests/bluetooth/tester/src/audio/btp_hap.c diff --git a/tests/bluetooth/tester/src/btp_has.c b/tests/bluetooth/tester/src/audio/btp_has.c similarity index 100% rename from tests/bluetooth/tester/src/btp_has.c rename to tests/bluetooth/tester/src/audio/btp_has.c diff --git a/tests/bluetooth/tester/src/btp_mcp.c b/tests/bluetooth/tester/src/audio/btp_mcp.c similarity index 100% rename from tests/bluetooth/tester/src/btp_mcp.c rename to tests/bluetooth/tester/src/audio/btp_mcp.c diff --git a/tests/bluetooth/tester/src/btp_micp.c b/tests/bluetooth/tester/src/audio/btp_micp.c similarity index 100% rename from tests/bluetooth/tester/src/btp_micp.c rename to tests/bluetooth/tester/src/audio/btp_micp.c diff --git a/tests/bluetooth/tester/src/btp_tmap.c b/tests/bluetooth/tester/src/audio/btp_tmap.c similarity index 100% rename from tests/bluetooth/tester/src/btp_tmap.c rename to tests/bluetooth/tester/src/audio/btp_tmap.c diff --git a/tests/bluetooth/tester/src/btp_vcp.c b/tests/bluetooth/tester/src/audio/btp_vcp.c similarity index 100% rename from tests/bluetooth/tester/src/btp_vcp.c rename to tests/bluetooth/tester/src/audio/btp_vcp.c From 453ab8a9a356acf475a965a777a370795effa255 Mon Sep 17 00:00:00 2001 From: Rodrigo Peixoto Date: Sun, 28 Apr 2024 14:38:15 -0300 Subject: [PATCH 2079/2849] zbus: vded: msg_sub: Improve channel ref copy The VDED was adding the channel information per clone. But it could be done in the original buffer. This commit fixes that by adding the channel information to the original buffer and not for each clone. As a result, we have a more straightforward VDED execution with fewer copies. Signed-off-by: Rodrigo Peixoto --- subsys/zbus/zbus.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/subsys/zbus/zbus.c b/subsys/zbus/zbus.c index d16cc27d965ca..c01002f5b2f9e 100644 --- a/subsys/zbus/zbus.c +++ b/subsys/zbus/zbus.c @@ -105,7 +105,6 @@ static inline int _zbus_notify_observer(const struct zbus_channel *chan, if (cloned_buf == NULL) { return -ENOMEM; } - memcpy(net_buf_user_data(cloned_buf), &chan, sizeof(struct zbus_channel *)); net_buf_put(obs->message_fifo, cloned_buf); @@ -136,6 +135,8 @@ static inline int _zbus_vded_exec(const struct zbus_channel *chan, k_timepoint_t _ZBUS_ASSERT(buf != NULL, "net_buf zbus_msg_subscribers_pool is " "unavailable or heap is full"); + memcpy(net_buf_user_data(buf), &chan, sizeof(struct zbus_channel *)); + net_buf_add_mem(buf, zbus_chan_msg(chan), zbus_chan_msg_size(chan)); #endif /* CONFIG_ZBUS_MSG_SUBSCRIBER */ From 87946a899684e7764958aacc24cbba2c398e1ed6 Mon Sep 17 00:00:00 2001 From: Krzysztof Sychla Date: Thu, 6 Jun 2024 08:45:40 +0200 Subject: [PATCH 2080/2849] kernel: banner: fix disabling boot banner When the CONFIG_BOOT_BANNER flag is set to "n", but CONFIG_BOOT_DELAY is enabled, there is a delay message printed at boot time. This allows for the whole boot banner to be disabled. Signed-off-by: Krzysztof Sychla --- kernel/banner.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/kernel/banner.c b/kernel/banner.c index d2a431edd9679..1d95f2b18350c 100644 --- a/kernel/banner.c +++ b/kernel/banner.c @@ -27,7 +27,9 @@ void boot_banner(void) { #if defined(CONFIG_BOOT_DELAY) && (CONFIG_BOOT_DELAY > 0) +#ifdef CONFIG_BOOT_BANNER printk("***** delaying boot " DELAY_STR "ms (per build configuration) *****\n"); +#endif /* CONFIG_BOOT_BANNER */ k_busy_wait(CONFIG_BOOT_DELAY * USEC_PER_MSEC); #endif /* defined(CONFIG_BOOT_DELAY) && (CONFIG_BOOT_DELAY > 0) */ From 0a95423421dad9b487bf59aa438484e915c65b2a Mon Sep 17 00:00:00 2001 From: Robert Lubos Date: Wed, 5 Jun 2024 13:53:11 +0200 Subject: [PATCH 2081/2849] net: ipv4: Implement IPv4 address conflict detection Add support for IPv4 conflict detection, as specified in RFC 5227. The new feature is optional and disabled by default. Address conflict detection was implemented as a part of the IPv4 autoconf feature can be generalized to be available for all address types. Signed-off-by: Robert Lubos --- include/zephyr/net/net_event.h | 18 ++ include/zephyr/net/net_if.h | 42 ++- include/zephyr/net/net_pkt.h | 28 +- subsys/net/ip/CMakeLists.txt | 1 + subsys/net/ip/Kconfig.ipv4 | 16 ++ subsys/net/ip/ipv4.c | 4 + subsys/net/ip/ipv4.h | 49 ++++ subsys/net/ip/ipv4_acd.c | 417 ++++++++++++++++++++++++++++++ subsys/net/ip/ipv4_autoconf.c | 2 +- subsys/net/ip/net_if.c | 138 +++++++++- subsys/net/l2/ethernet/arp.c | 6 +- subsys/net/l2/ethernet/ethernet.c | 8 +- 12 files changed, 700 insertions(+), 29 deletions(-) create mode 100644 subsys/net/ip/ipv4_acd.c diff --git a/include/zephyr/net/net_event.h b/include/zephyr/net/net_event.h index b149934f8bcac..a15d5f2078078 100644 --- a/include/zephyr/net/net_event.h +++ b/include/zephyr/net/net_event.h @@ -96,6 +96,9 @@ enum net_event_ipv4_cmd { NET_EVENT_IPV4_CMD_DHCP_STOP, NET_EVENT_IPV4_CMD_MCAST_JOIN, NET_EVENT_IPV4_CMD_MCAST_LEAVE, + NET_EVENT_IPV4_CMD_ACD_SUCCEED, + NET_EVENT_IPV4_CMD_ACD_FAILED, + NET_EVENT_IPV4_CMD_ACD_CONFLICT, }; /* L4 network events */ @@ -274,6 +277,21 @@ enum net_event_l4_cmd { #define NET_EVENT_IPV4_MCAST_LEAVE \ (_NET_EVENT_IPV4_BASE | NET_EVENT_IPV4_CMD_MCAST_LEAVE) +/** Event emitted when an IPv4 address conflict detection succeeds. */ +#define NET_EVENT_IPV4_ACD_SUCCEED \ + (_NET_EVENT_IPV4_BASE | NET_EVENT_IPV4_CMD_ACD_SUCCEED) + +/** Event emitted when an IPv4 address conflict detection fails. */ +#define NET_EVENT_IPV4_ACD_FAILED \ + (_NET_EVENT_IPV4_BASE | NET_EVENT_IPV4_CMD_ACD_FAILED) + +/** Event emitted when an IPv4 address conflict was detected after the address + * was confirmed as safe to use. It's up to the application to determine on + * how to act in such case. + */ +#define NET_EVENT_IPV4_ACD_CONFLICT \ + (_NET_EVENT_IPV4_BASE | NET_EVENT_IPV4_CMD_ACD_CONFLICT) + /** 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. diff --git a/include/zephyr/net/net_if.h b/include/zephyr/net/net_if.h index 0b69dde2fe70d..3944315dc064b 100644 --- a/include/zephyr/net/net_if.h +++ b/include/zephyr/net/net_if.h @@ -62,11 +62,6 @@ struct net_if_addr { struct net_timeout lifetime; #endif -#if defined(CONFIG_NET_IPV6_DAD) && defined(CONFIG_NET_NATIVE_IPV6) - /** Duplicate address detection (DAD) timer */ - sys_snode_t dad_node; - uint32_t dad_start; -#endif /** How the IP address was set */ enum net_addr_type addr_type; @@ -90,14 +85,38 @@ struct net_if_addr { */ int32_t addr_timeout; #endif +#endif /* CONFIG_NET_NATIVE_IPV6 */ + union { #if defined(CONFIG_NET_IPV6_DAD) - /** How many times we have done DAD */ - uint8_t dad_count; - /* What interface the DAD is running */ + struct { + /** Duplicate address detection (DAD) timer */ + sys_snode_t dad_node; + uint32_t dad_start; + + /** How many times we have done DAD */ + uint8_t dad_count; + }; +#endif /* CONFIG_NET_IPV6_DAD */ +#if defined(CONFIG_NET_IPV4_ACD) + struct { + /** Address conflict detection (ACD) timer. */ + sys_snode_t acd_node; + k_timepoint_t acd_timeout; + + /** ACD probe/announcement counter. */ + uint8_t acd_count; + + /** ACD status. */ + uint8_t acd_state; + }; +#endif /* CONFIG_NET_IPV4_ACD */ + }; + +#if defined(CONFIG_NET_IPV6_DAD) || defined(CONFIG_NET_IPV4_ACD) + /** What interface the conflict detection is running */ uint8_t ifindex; #endif -#endif /* CONFIG_NET_NATIVE_IPV6 */ /** Is the IP address valid forever */ uint8_t is_infinite : 1; @@ -438,6 +457,11 @@ struct net_if_ipv4 { /** IPv4 time-to-live for multicast packets */ uint8_t mcast_ttl; + +#if defined(CONFIG_NET_IPV4_ACD) + /** IPv4 conflict count. */ + uint8_t conflict_cnt; +#endif }; #if defined(CONFIG_NET_DHCPV4) && defined(CONFIG_NET_NATIVE_IPV4) diff --git a/include/zephyr/net/net_pkt.h b/include/zephyr/net/net_pkt.h index 4c5b592fde4ab..97709533df8e6 100644 --- a/include/zephyr/net/net_pkt.h +++ b/include/zephyr/net/net_pkt.h @@ -167,8 +167,8 @@ struct net_pkt { /* bitfield byte alignment boundary */ -#if defined(CONFIG_NET_IPV4_AUTO) - uint8_t ipv4_auto_arp_msg : 1; /* Is this pkt IPv4 autoconf ARP +#if defined(CONFIG_NET_IPV4_ACD) + uint8_t ipv4_acd_arp_msg : 1; /* Is this pkt IPv4 conflict detection ARP * message. * Note: family needs to be * AF_INET. @@ -1206,32 +1206,32 @@ static inline void net_pkt_set_ll_proto_type(struct net_pkt *pkt, uint16_t type) pkt->ll_proto_type = type; } -#if defined(CONFIG_NET_IPV4_AUTO) -static inline bool net_pkt_ipv4_auto(struct net_pkt *pkt) +#if defined(CONFIG_NET_IPV4_ACD) +static inline bool net_pkt_ipv4_acd(struct net_pkt *pkt) { - return !!(pkt->ipv4_auto_arp_msg); + return !!(pkt->ipv4_acd_arp_msg); } -static inline void net_pkt_set_ipv4_auto(struct net_pkt *pkt, - bool is_auto_arp_msg) +static inline void net_pkt_set_ipv4_acd(struct net_pkt *pkt, + bool is_acd_arp_msg) { - pkt->ipv4_auto_arp_msg = is_auto_arp_msg; + pkt->ipv4_acd_arp_msg = is_acd_arp_msg; } -#else /* CONFIG_NET_IPV4_AUTO */ -static inline bool net_pkt_ipv4_auto(struct net_pkt *pkt) +#else /* CONFIG_NET_IPV4_ACD */ +static inline bool net_pkt_ipv4_acd(struct net_pkt *pkt) { ARG_UNUSED(pkt); return false; } -static inline void net_pkt_set_ipv4_auto(struct net_pkt *pkt, - bool is_auto_arp_msg) +static inline void net_pkt_set_ipv4_acd(struct net_pkt *pkt, + bool is_acd_arp_msg) { ARG_UNUSED(pkt); - ARG_UNUSED(is_auto_arp_msg); + ARG_UNUSED(is_acd_arp_msg); } -#endif /* CONFIG_NET_IPV4_AUTO */ +#endif /* CONFIG_NET_IPV4_ACD */ #if defined(CONFIG_NET_LLDP) static inline bool net_pkt_is_lldp(struct net_pkt *pkt) diff --git a/subsys/net/ip/CMakeLists.txt b/subsys/net/ip/CMakeLists.txt index abb26e3dafe0c..11509d804d789 100644 --- a/subsys/net/ip/CMakeLists.txt +++ b/subsys/net/ip/CMakeLists.txt @@ -33,6 +33,7 @@ zephyr_library_sources_ifdef(CONFIG_NET_IP connection.c) zephyr_library_sources_ifdef(CONFIG_NET_6LO 6lo.c) zephyr_library_sources_ifdef(CONFIG_NET_IPV4_AUTO ipv4_autoconf.c) zephyr_library_sources_ifdef(CONFIG_NET_IPV4 icmpv4.c ipv4.c) +zephyr_library_sources_ifdef(CONFIG_NET_IPV4_ACD ipv4_acd.c) 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) diff --git a/subsys/net/ip/Kconfig.ipv4 b/subsys/net/ip/Kconfig.ipv4 index e2427d8857546..4dc1dcf94cde3 100644 --- a/subsys/net/ip/Kconfig.ipv4 +++ b/subsys/net/ip/Kconfig.ipv4 @@ -86,10 +86,18 @@ config NET_IPV4_IGMPV3 help Use IGMPv3 for managing the multicast groups. +config NET_IPV4_ACD + bool "Activate IPv4 address conflict detection (RFC 5227)" + depends on NET_ARP + help + Activate IPv4 address conflict detection specified in RFC 5227. + The conflict detection is based on ARP probes/announcements. + config NET_IPV4_AUTO bool "IPv4 autoconfiguration [EXPERIMENTAL]" depends on NET_ARP select EXPERIMENTAL + select NET_IPV4_ACD help Enables IPv4 auto IP address configuration (see RFC 3927) @@ -150,6 +158,14 @@ module-str = Log level for ICMPv4 module-help = Enables ICMPv4 code to output debug messages. source "subsys/net/Kconfig.template.log_config.net" +#if NET_IPV4_ACD +module = NET_IPV4_ACD +module-dep = NET_LOG +module-str = Log level for IPv4 address conflict detection +module-help = Enables IPv4 address conflict detection debug messages. +source "subsys/net/Kconfig.template.log_config.net" +#endif + if NET_IPV4_AUTO module = NET_IPV4_AUTO module-dep = NET_LOG diff --git a/subsys/net/ip/ipv4.c b/subsys/net/ip/ipv4.c index 36ac0c4787b1a..35872988edd76 100644 --- a/subsys/net/ip/ipv4.c +++ b/subsys/net/ip/ipv4.c @@ -449,4 +449,8 @@ void net_ipv4_init(void) if (IS_ENABLED(CONFIG_NET_IPV4_FRAGMENT)) { net_ipv4_setup_fragment_buffers(); } + + if (IS_ENABLED(CONFIG_NET_IPV4_ACD)) { + net_ipv4_acd_init(); + } } diff --git a/subsys/net/ip/ipv4.h b/subsys/net/ip/ipv4.h index 162faca24b5a8..8c063952e9fff 100644 --- a/subsys/net/ip/ipv4.h +++ b/subsys/net/ip/ipv4.h @@ -416,4 +416,53 @@ static inline void net_ipv4_setup_fragment_buffers(void) #define net_ipv4_init(...) #endif /* CONFIG_NET_NATIVE_IPV4 */ +/** + * @brief Starts address conflict detection for an IPv4 address. + * + * @param iface Network interface the address belongs to. + * @param ifaddr IPv4 address to probe. + * + * @return 0 on success, negative otherwise. + */ +int net_ipv4_acd_start(struct net_if *iface, struct net_if_addr *ifaddr); + +/** + * @brief Cancel address conflict detection for an IPv4 address. + * + * @param iface Network interface the address belongs to. + * @param ifaddr IPv4 address to probe. + */ +void net_ipv4_acd_cancel(struct net_if *iface, struct net_if_addr *ifaddr); + +/** + * @brief Notify no conflict was detected for an IPv4 address. + * + * @param iface Network interface the address belongs to. + * @param ifaddr IPv4 address. + */ +void net_if_ipv4_acd_succeeded(struct net_if *iface, struct net_if_addr *ifaddr); + +/** + * @brief Notify conflict for an IPv4 address. + * + * @param iface Network interface the address belongs to. + * @param ifaddr IPv4 address. + */ +void net_if_ipv4_acd_failed(struct net_if *iface, struct net_if_addr *ifaddr); + +/** + * @brief Initialize IPv4 address conflict detection module. + */ +void net_ipv4_acd_init(void); + +/** + * @brief Process ARP packet in terms of conflict detection. + * + * @param iface Network interface the packet was received on. + * @param pkt ARP packet to process. + * + * @return Return verdict about the packet. + */ +enum net_verdict net_ipv4_acd_input(struct net_if *iface, struct net_pkt *pkt); + #endif /* __IPV4_H */ diff --git a/subsys/net/ip/ipv4_acd.c b/subsys/net/ip/ipv4_acd.c new file mode 100644 index 0000000000000..c4f5bdccad2a3 --- /dev/null +++ b/subsys/net/ip/ipv4_acd.c @@ -0,0 +1,417 @@ +/* + * Copyright (c) 2017 Matthias Boesl + * Copyright (c) 2018 Intel Corporation + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** @file + * @brief IPv4 address conflict detection + */ + +#include +LOG_MODULE_REGISTER(net_ipv4_acd, CONFIG_NET_IPV4_ACD_LOG_LEVEL); + +#include +#include +#include +#include +#include +#include +#include + +#include "ipv4.h" +#include "net_private.h" +#include "../l2/ethernet/arp.h" + +static K_MUTEX_DEFINE(lock); + +/* Address conflict detection timer. */ +static struct k_work_delayable ipv4_acd_timer; + +/* List of IPv4 addresses under an active conflict detection. */ +static sys_slist_t active_acd_timers; + +#define BUF_ALLOC_TIMEOUT K_MSEC(100) + +/* Initial random delay*/ +#define IPV4_ACD_PROBE_WAIT 1 + +/* Number of probe packets */ +#define IPV4_ACD_PROBE_NUM 3 + +/* Minimum delay till repeated probe */ +#define IPV4_ACD_PROBE_MIN 1 + +/* Maximum delay till repeated probe */ +#define IPV4_ACD_PROBE_MAX 2 + +/* Delay before announcing */ +#define IPV4_ACD_ANNOUNCE_WAIT 2 + +/* Number of announcement packets */ +#define IPV4_ACD_ANNOUNCE_NUM 2 + +/* Time between announcement packets */ +#define IPV4_ACD_ANNOUNCE_INTERVAL 2 + +/* Max conflicts before rate limiting */ +#define IPV4_ACD_MAX_CONFLICTS 10 + +/* Delay between successive attempts */ +#define IPV4_ACD_RATE_LIMIT_INTERVAL 60 + +/* Minimum interval between defensive ARPs */ +#define IPV4_ACD_DEFEND_INTERVAL 10 + +enum ipv4_acd_state { + IPV4_ACD_PROBE, /* Probing state */ + IPV4_ACD_ANNOUNCE, /* Announce state */ +}; + +static struct net_pkt *ipv4_acd_prepare_arp(struct net_if *iface, + struct in_addr *sender_ip, + struct in_addr *target_ip) +{ + struct net_pkt *pkt; + + /* We provide AF_UNSPEC to the allocator: this packet does not + * need space for any IPv4 header. + */ + pkt = net_pkt_alloc_with_buffer(iface, sizeof(struct net_arp_hdr), + AF_UNSPEC, 0, BUF_ALLOC_TIMEOUT); + if (!pkt) { + return NULL; + } + + net_pkt_set_family(pkt, AF_INET); + net_pkt_set_ipv4_acd(pkt, true); + + return net_arp_prepare(pkt, target_ip, sender_ip); +} + +static void ipv4_acd_send_probe(struct net_if_addr *ifaddr) +{ + struct net_if *iface = net_if_get_by_index(ifaddr->ifindex); + struct in_addr unspecified = { 0 }; + struct net_pkt *pkt; + + pkt = ipv4_acd_prepare_arp(iface, &unspecified, &ifaddr->address.in_addr); + if (!pkt) { + NET_DBG("Failed to prepare probe %p", iface); + return; + } + + if (net_if_send_data(iface, pkt) == NET_DROP) { + net_pkt_unref(pkt); + } +} + +static void ipv4_acd_send_announcement(struct net_if_addr *ifaddr) +{ + struct net_if *iface = net_if_get_by_index(ifaddr->ifindex); + struct net_pkt *pkt; + + pkt = ipv4_acd_prepare_arp(iface, &ifaddr->address.in_addr, + &ifaddr->address.in_addr); + if (!pkt) { + NET_DBG("Failed to prepare announcement %p", iface); + return; + } + + if (net_if_send_data(iface, pkt) == NET_DROP) { + net_pkt_unref(pkt); + } +} + +static void acd_timer_reschedule(void) +{ + k_timepoint_t expiry = sys_timepoint_calc(K_FOREVER); + k_timeout_t timeout; + sys_snode_t *node; + + SYS_SLIST_FOR_EACH_NODE(&active_acd_timers, node) { + struct net_if_addr *ifaddr = + CONTAINER_OF(node, struct net_if_addr, acd_node); + + if (sys_timepoint_cmp(ifaddr->acd_timeout, expiry) < 0) { + expiry = ifaddr->acd_timeout; + } + } + + timeout = sys_timepoint_timeout(expiry); + if (K_TIMEOUT_EQ(timeout, K_FOREVER)) { + k_work_cancel_delayable(&ipv4_acd_timer); + return; + } + + k_work_reschedule(&ipv4_acd_timer, timeout); +} + +static void ipv4_acd_manage_timeout(struct net_if_addr *ifaddr) +{ + switch (ifaddr->acd_state) { + case IPV4_ACD_PROBE: + if (ifaddr->acd_count < IPV4_ACD_PROBE_NUM) { + uint32_t delay; + + NET_DBG("Sending probe for %s", + net_sprint_ipv4_addr(&ifaddr->address.in_addr)); + + ipv4_acd_send_probe(ifaddr); + + ifaddr->acd_count++; + if (ifaddr->acd_count < IPV4_ACD_PROBE_NUM) { + delay = sys_rand32_get(); + delay %= MSEC_PER_SEC * (IPV4_ACD_PROBE_MAX - IPV4_ACD_PROBE_MIN); + delay += MSEC_PER_SEC * IPV4_ACD_PROBE_MIN; + } else { + delay = MSEC_PER_SEC * IPV4_ACD_ANNOUNCE_WAIT; + + } + + ifaddr->acd_timeout = sys_timepoint_calc(K_MSEC(delay)); + + break; + } + + net_if_ipv4_acd_succeeded(net_if_get_by_index(ifaddr->ifindex), + ifaddr); + + ifaddr->acd_state = IPV4_ACD_ANNOUNCE; + ifaddr->acd_count = 0; + __fallthrough; + case IPV4_ACD_ANNOUNCE: + if (ifaddr->acd_count < IPV4_ACD_ANNOUNCE_NUM) { + NET_DBG("Sending announcement for %s", + net_sprint_ipv4_addr(&ifaddr->address.in_addr)); + + ipv4_acd_send_announcement(ifaddr); + + ifaddr->acd_count++; + ifaddr->acd_timeout = sys_timepoint_calc( + K_SECONDS(IPV4_ACD_ANNOUNCE_INTERVAL)); + + break; + } + + NET_DBG("IPv4 conflict detection done for %s", + net_sprint_ipv4_addr(&ifaddr->address.in_addr)); + + /* Timeout will be used to determine whether DEFEND_INTERVAL + * has expired in case of conflicts. + */ + ifaddr->acd_timeout = sys_timepoint_calc(K_NO_WAIT); + + sys_slist_find_and_remove(&active_acd_timers, &ifaddr->acd_node); + break; + default: + break; + } +} + +static void ipv4_acd_timeout(struct k_work *work) +{ + sys_snode_t *current, *next; + + ARG_UNUSED(work); + + k_mutex_lock(&lock, K_FOREVER); + + SYS_SLIST_FOR_EACH_NODE_SAFE(&active_acd_timers, current, next) { + struct net_if_addr *ifaddr = + CONTAINER_OF(current, struct net_if_addr, acd_node); + + if (sys_timepoint_expired(ifaddr->acd_timeout)) { + ipv4_acd_manage_timeout(ifaddr); + } + } + + acd_timer_reschedule(); + + k_mutex_unlock(&lock); +} + +static void acd_start_timer(struct net_if *iface, struct net_if_addr *ifaddr) +{ + uint32_t delay; + + sys_slist_find_and_remove(&active_acd_timers, &ifaddr->acd_node); + sys_slist_append(&active_acd_timers, &ifaddr->acd_node); + + if (iface->config.ip.ipv4->conflict_cnt >= IPV4_ACD_MAX_CONFLICTS) { + NET_DBG("Rate limiting"); + delay = MSEC_PER_SEC * IPV4_ACD_RATE_LIMIT_INTERVAL; + } else { + /* Initial probe should be delayed by a random time interval + * between 0 and PROBE_WAIT. + */ + delay = sys_rand32_get() % (MSEC_PER_SEC * IPV4_ACD_PROBE_WAIT); + } + + ifaddr->acd_timeout = sys_timepoint_calc(K_MSEC(delay)); + + acd_timer_reschedule(); +} + +enum net_verdict net_ipv4_acd_input(struct net_if *iface, struct net_pkt *pkt) +{ + sys_snode_t *current, *next; + struct net_arp_hdr *arp_hdr; + struct net_if_ipv4 *ipv4; + + if (net_pkt_get_len(pkt) < sizeof(struct net_arp_hdr)) { + NET_DBG("Invalid ARP header (len %zu, min %zu bytes)", + net_pkt_get_len(pkt), sizeof(struct net_arp_hdr)); + return NET_DROP; + } + + arp_hdr = NET_ARP_HDR(pkt); + + k_mutex_lock(&lock, K_FOREVER); + + SYS_SLIST_FOR_EACH_NODE_SAFE(&active_acd_timers, current, next) { + struct net_if_addr *ifaddr = + CONTAINER_OF(current, struct net_if_addr, acd_node); + struct net_if *addr_iface = net_if_get_by_index(ifaddr->ifindex); + struct net_linkaddr *ll_addr; + + if (iface != addr_iface) { + continue; + } + + if (ifaddr->acd_state != IPV4_ACD_PROBE) { + continue; + } + + ll_addr = net_if_get_link_addr(addr_iface); + + /* RFC 5227, ch. 2.1.1 Probe Details: + * - Sender IP address match OR, + * - Target IP address match with different sender HW address, + * indicate a conflict. + */ + if (net_ipv4_addr_cmp_raw(arp_hdr->src_ipaddr, + (uint8_t *)&ifaddr->address.in_addr) || + (net_ipv4_addr_cmp_raw(arp_hdr->dst_ipaddr, + (uint8_t *)&ifaddr->address.in_addr) && + memcmp(&arp_hdr->src_hwaddr, ll_addr->addr, ll_addr->len) != 0)) { + NET_DBG("Conflict detected from %s for %s", + net_sprint_ll_addr((uint8_t *)&arp_hdr->src_hwaddr, + arp_hdr->hwlen), + net_sprint_ipv4_addr(&ifaddr->address.in_addr)); + + iface->config.ip.ipv4->conflict_cnt++; + + net_if_ipv4_acd_failed(addr_iface, ifaddr); + + k_mutex_unlock(&lock); + + return NET_DROP; + } + } + + k_mutex_unlock(&lock); + + ipv4 = iface->config.ip.ipv4; + if (ipv4 == NULL) { + goto out; + } + + /* Passive conflict detection - try to defend already confirmed + * addresses. + */ + ARRAY_FOR_EACH(ipv4->unicast, i) { + struct net_if_addr *ifaddr = &ipv4->unicast[i].ipv4; + struct net_linkaddr *ll_addr = net_if_get_link_addr(iface); + + if (!ifaddr->is_used) { + continue; + } + + if (net_ipv4_addr_cmp_raw(arp_hdr->src_ipaddr, + (uint8_t *)&ifaddr->address.in_addr) && + memcmp(&arp_hdr->src_hwaddr, ll_addr->addr, ll_addr->len) != 0) { + NET_DBG("Conflict detected from %s for %s", + net_sprint_ll_addr((uint8_t *)&arp_hdr->src_hwaddr, + arp_hdr->hwlen), + net_sprint_ipv4_addr(&ifaddr->address.in_addr)); + + ipv4->conflict_cnt++; + + /* In case timer has expired, we're past DEFEND_INTERVAL + * and can try to defend again + */ + if (sys_timepoint_expired(ifaddr->acd_timeout)) { + NET_DBG("Defending address %s", + net_sprint_ipv4_addr(&ifaddr->address.in_addr)); + ipv4_acd_send_announcement(ifaddr); + ifaddr->acd_timeout = sys_timepoint_calc( + K_SECONDS(IPV4_ACD_DEFEND_INTERVAL)); + } else { + NET_DBG("Reporting conflict on %s", + net_sprint_ipv4_addr(&ifaddr->address.in_addr)); + /* Otherwise report the conflict and let the + * application decide. + */ + net_mgmt_event_notify_with_info( + NET_EVENT_IPV4_ACD_CONFLICT, iface, + &ifaddr->address.in_addr, + sizeof(struct in_addr)); + } + + break; + } + } + +out: + return NET_CONTINUE; +} + +void net_ipv4_acd_init(void) +{ + k_work_init_delayable(&ipv4_acd_timer, ipv4_acd_timeout); +} + +int net_ipv4_acd_start(struct net_if *iface, struct net_if_addr *ifaddr) +{ + /* Address conflict detection is based on ARP, so can only be done on + * supporting interfaces. + */ + if (!(net_if_l2(iface) == &NET_L2_GET_NAME(ETHERNET) || + net_eth_is_vlan_interface(iface))) { + net_if_ipv4_acd_succeeded(iface, ifaddr); + return 0; + } + + k_mutex_lock(&lock, K_FOREVER); + + ifaddr->ifindex = net_if_get_by_iface(iface); + ifaddr->acd_state = IPV4_ACD_PROBE; + ifaddr->acd_count = 0; + + acd_start_timer(iface, ifaddr); + + k_mutex_unlock(&lock); + + return 0; +} + +void net_ipv4_acd_cancel(struct net_if *iface, struct net_if_addr *ifaddr) +{ + /* Address conflict detection is based on ARP, so can only be done on + * supporting interfaces. + */ + if (!(net_if_l2(iface) == &NET_L2_GET_NAME(ETHERNET) || + net_eth_is_vlan_interface(iface))) { + return; + } + + k_mutex_lock(&lock, K_FOREVER); + + sys_slist_find_and_remove(&active_acd_timers, &ifaddr->acd_node); + acd_timer_reschedule(); + + k_mutex_unlock(&lock); +} diff --git a/subsys/net/ip/ipv4_autoconf.c b/subsys/net/ip/ipv4_autoconf.c index c9b21e79ac44b..7774b131fa902 100644 --- a/subsys/net/ip/ipv4_autoconf.c +++ b/subsys/net/ip/ipv4_autoconf.c @@ -45,7 +45,7 @@ static struct net_pkt *ipv4_autoconf_prepare_arp(struct net_if *iface) } net_pkt_set_family(pkt, AF_INET); - net_pkt_set_ipv4_auto(pkt, true); + net_pkt_set_ipv4_acd(pkt, true); return net_arp_prepare(pkt, &cfg->ipv4auto.requested_ip, &cfg->ipv4auto.current_ip); diff --git a/subsys/net/ip/net_if.c b/subsys/net/ip/net_if.c index 8a61d98cffd31..3cb112bc80f2d 100644 --- a/subsys/net/ip/net_if.c +++ b/subsys/net/ip/net_if.c @@ -4110,6 +4110,118 @@ static struct net_if_addr *ipv4_addr_find(struct net_if *iface, return NULL; } +#if defined(CONFIG_NET_IPV4_ACD) +void net_if_ipv4_acd_succeeded(struct net_if *iface, struct net_if_addr *ifaddr) +{ + net_if_lock(iface); + + NET_DBG("ACD succeeded for %s at interface %d", + net_sprint_ipv4_addr(&ifaddr->address.in_addr), + ifaddr->ifindex); + + ifaddr->addr_state = NET_ADDR_PREFERRED; + + net_mgmt_event_notify_with_info(NET_EVENT_IPV4_ACD_SUCCEED, iface, + &ifaddr->address.in_addr, + sizeof(struct in_addr)); + + net_if_unlock(iface); +} + +void net_if_ipv4_acd_failed(struct net_if *iface, struct net_if_addr *ifaddr) +{ + net_if_lock(iface); + + NET_DBG("ACD failed for %s at interface %d", + net_sprint_ipv4_addr(&ifaddr->address.in_addr), + ifaddr->ifindex); + + net_mgmt_event_notify_with_info(NET_EVENT_IPV4_ACD_FAILED, iface, + &ifaddr->address.in_addr, + sizeof(struct in_addr)); + + net_if_ipv4_addr_rm(iface, &ifaddr->address.in_addr); + + net_if_unlock(iface); +} + +void net_if_ipv4_start_acd(struct net_if *iface, struct net_if_addr *ifaddr) +{ + ifaddr->addr_state = NET_ADDR_TENTATIVE; + + if (net_if_is_up(iface)) { + NET_DBG("Interface %p ll addr %s tentative IPv4 addr %s", + iface, + net_sprint_ll_addr(net_if_get_link_addr(iface)->addr, + net_if_get_link_addr(iface)->len), + net_sprint_ipv4_addr(&ifaddr->address.in_addr)); + + if (net_ipv4_acd_start(iface, ifaddr) != 0) { + NET_DBG("Failed to start ACD for %s on iface %p.", + net_sprint_ipv4_addr(&ifaddr->address.in_addr), + iface); + + /* Just act as if no conflict was detected. */ + net_if_ipv4_acd_succeeded(iface, ifaddr); + } + } else { + NET_DBG("Interface %p is down, starting ACD for %s later.", + iface, net_sprint_ipv4_addr(&ifaddr->address.in_addr)); + } +} + +void net_if_start_acd(struct net_if *iface) +{ + struct net_if_ipv4 *ipv4; + int ret; + + net_if_lock(iface); + + NET_DBG("Starting ACD for iface %p", iface); + + ret = net_if_config_ipv4_get(iface, &ipv4); + if (ret < 0) { + if (ret != -ENOTSUP) { + NET_WARN("Cannot do ACD IPv4 config is not valid."); + } + + goto out; + } + + if (!ipv4) { + goto out; + } + + ipv4->conflict_cnt = 0; + + /* Start ACD for all the addresses that were added earlier when + * the interface was down. + */ + ARRAY_FOR_EACH(ipv4->unicast, i) { + if (!ipv4->unicast[i].ipv4.is_used || + ipv4->unicast[i].ipv4.address.family != AF_INET || + net_ipv4_is_addr_loopback( + &ipv4->unicast[i].ipv4.address.in_addr)) { + continue; + } + + net_if_ipv4_start_acd(iface, &ipv4->unicast[i].ipv4); + } + +out: + net_if_unlock(iface); +} +#else +void net_if_ipv4_start_acd(struct net_if *iface, struct net_if_addr *ifaddr) +{ + ARG_UNUSED(iface); + + ifaddr->addr_state = NET_ADDR_PREFERRED; +} + +#define net_if_start_acd(...) +#endif /* CONFIG_NET_IPV4_ACD */ + struct net_if_addr *net_if_ipv4_addr_add(struct net_if *iface, struct in_addr *addr, enum net_addr_type addr_type, @@ -4167,13 +4279,19 @@ struct net_if_addr *net_if_ipv4_addr_add(struct net_if *iface, * TODO: Handle properly PREFERRED/DEPRECATED state when * address in use, expired and renewal state. */ - ifaddr->addr_state = NET_ADDR_PREFERRED; NET_DBG("[%d] interface %d (%p) address %s type %s added", idx, net_if_get_by_iface(iface), iface, net_sprint_ipv4_addr(addr), net_addr_type2str(addr_type)); + if (!(l2_flags_get(iface) & NET_L2_POINT_TO_POINT) && + !net_ipv4_is_addr_loopback(addr)) { + net_if_ipv4_start_acd(iface, ifaddr); + } else { + ifaddr->addr_state = NET_ADDR_PREFERRED; + } + net_mgmt_event_notify_with_info(NET_EVENT_IPV4_ADDR_ADD, iface, &ifaddr->address.in_addr, sizeof(struct in_addr)); @@ -4524,9 +4642,22 @@ static void leave_ipv4_mcast_all(struct net_if *iface) } } +static void iface_ipv4_start(struct net_if *iface) +{ + if (!net_if_flag_is_set(iface, NET_IF_IPV4)) { + return; + } + + if (IS_ENABLED(CONFIG_NET_IPV4_ACD)) { + net_if_start_acd(iface); + } +} + + #else /* CONFIG_NET_NATIVE_IPV4 */ #define leave_ipv4_mcast_all(...) #define iface_ipv4_init(...) +#define iface_ipv4_start(...) struct net_if_mcast_addr *net_if_ipv4_maddr_lookup(const struct in_addr *addr, struct net_if **iface) @@ -4735,6 +4866,10 @@ static void remove_ipv4_ifaddr(struct net_if *iface, goto out; } +#if defined(CONFIG_NET_IPV4_ACD) + net_ipv4_acd_cancel(iface, ifaddr); +#endif + net_mgmt_event_notify_with_info(NET_EVENT_IPV4_ADDR_DEL, iface, &ifaddr->address.in_addr, @@ -5025,6 +5160,7 @@ static void notify_iface_up(struct net_if *iface) */ rejoin_multicast_groups(iface); iface_ipv6_start(iface); + iface_ipv4_start(iface); net_ipv4_autoconf_start(iface); } } diff --git a/subsys/net/l2/ethernet/arp.c b/subsys/net/l2/ethernet/arp.c index de5de8821e9f2..a166e304f4244 100644 --- a/subsys/net/l2/ethernet/arp.c +++ b/subsys/net/l2/ethernet/arp.c @@ -290,7 +290,7 @@ static inline struct net_pkt *arp_prepare(struct net_if *iface, * request and we want to send it again. */ if (entry) { - if (!net_pkt_ipv4_auto(pkt)) { + if (!net_pkt_ipv4_acd(pkt)) { k_fifo_put(&entry->pending_queue, net_pkt_ref(pending)); } @@ -325,7 +325,7 @@ static inline struct net_pkt *arp_prepare(struct net_if *iface, memcpy(hdr->src_hwaddr.addr, net_pkt_lladdr_src(pkt)->addr, sizeof(struct net_eth_addr)); - if (net_pkt_ipv4_auto(pkt)) { + if (net_pkt_ipv4_acd(pkt)) { my_addr = current_ip; } else if (!entry) { my_addr = (struct in_addr *)NET_IPV4_HDR(pending)->src; @@ -406,7 +406,7 @@ struct net_pkt *net_arp_prepare(struct net_pkt *pkt, * in the pending list and if so, resend the request, otherwise just * append the packet to the request fifo list. */ - if (!net_pkt_ipv4_auto(pkt) && + if (!net_pkt_ipv4_acd(pkt) && k_queue_unique_append(&entry->pending_queue._queue, net_pkt_ref(pkt))) { NET_DBG("Pending ARP request for %s, queuing pkt %p", diff --git a/subsys/net/l2/ethernet/ethernet.c b/subsys/net/l2/ethernet/ethernet.c index 76591856be890..403df565ca883 100644 --- a/subsys/net/l2/ethernet/ethernet.c +++ b/subsys/net/l2/ethernet/ethernet.c @@ -26,6 +26,7 @@ LOG_MODULE_REGISTER(net_ethernet, CONFIG_NET_L2_ETHERNET_LOG_LEVEL); #include "eth_stats.h" #include "net_private.h" #include "ipv6.h" +#include "ipv4.h" #include "ipv4_autoconf_internal.h" #include "bridge.h" @@ -395,6 +396,11 @@ static enum net_verdict ethernet_recv(struct net_if *iface, return NET_DROP; } + if (IS_ENABLED(CONFIG_NET_IPV4_ACD) && + net_ipv4_acd_input(iface, pkt) == NET_DROP) { + return NET_DROP; + } + return net_arp_input(pkt, hdr); } @@ -628,7 +634,7 @@ static int ethernet_send(struct net_if *iface, struct net_pkt *pkt) net_pkt_family(pkt) == AF_INET) { struct net_pkt *tmp; - if (net_pkt_ipv4_auto(pkt)) { + if (net_pkt_ipv4_acd(pkt)) { ptype = htons(NET_ETH_PTYPE_ARP); } else { tmp = ethernet_ll_prepare_on_ipv4(iface, pkt); From a89dd1a6f6c6d7b8b1cabf311068bf5bf92e88ba Mon Sep 17 00:00:00 2001 From: Robert Lubos Date: Tue, 4 Jun 2024 10:44:23 +0200 Subject: [PATCH 2082/2849] net: shell: Add ACD events to the event monitor Include new ACD events in the shell event monitor. Signed-off-by: Robert Lubos --- subsys/net/lib/shell/events.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/subsys/net/lib/shell/events.c b/subsys/net/lib/shell/events.c index f781498213020..e90ebce12e7a1 100644 --- a/subsys/net/lib/shell/events.c +++ b/subsys/net/lib/shell/events.c @@ -256,6 +256,18 @@ static char *get_l3_desc(struct event_msg *msg, *desc = "DHCPv4"; *desc2 = "stop"; break; + case NET_EVENT_IPV4_ACD_SUCCEED: + *desc = "IPv4 ACD"; + *desc2 = "ok"; + info = net_addr_ntop(AF_INET, msg->data, extra_info, + extra_info_len); + break; + case NET_EVENT_IPV4_ACD_FAILED: + *desc = "IPv4 ACD"; + *desc2 = "fail"; + info = net_addr_ntop(AF_INET, msg->data, extra_info, + extra_info_len); + break; } return info; From c281db0f7e5018caaa771b2f69b7d743d349f1f0 Mon Sep 17 00:00:00 2001 From: Robert Lubos Date: Tue, 4 Jun 2024 10:54:01 +0200 Subject: [PATCH 2083/2849] net: conn_mgr: Add support for ACD events Connection manager needs to monitor ACD events as well to determine whether a preferred IPv4 address is available. Signed-off-by: Robert Lubos --- subsys/net/conn_mgr/conn_mgr_private.h | 4 +++- subsys/net/conn_mgr/events_handler.c | 14 ++++++++++---- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/subsys/net/conn_mgr/conn_mgr_private.h b/subsys/net/conn_mgr/conn_mgr_private.h index 99aa98567a31b..5b03912f924f2 100644 --- a/subsys/net/conn_mgr/conn_mgr_private.h +++ b/subsys/net/conn_mgr/conn_mgr_private.h @@ -49,7 +49,9 @@ NET_EVENT_IPV6_DAD_FAILED) #define CONN_MGR_IPV4_EVENTS_MASK (NET_EVENT_IPV4_ADDR_ADD | \ - NET_EVENT_IPV4_ADDR_DEL) + NET_EVENT_IPV4_ADDR_DEL | \ + NET_EVENT_IPV4_ACD_SUCCEED | \ + NET_EVENT_IPV4_ACD_FAILED) extern struct k_sem conn_mgr_mon_updated; extern struct k_mutex conn_mgr_mon_lock; diff --git a/subsys/net/conn_mgr/events_handler.c b/subsys/net/conn_mgr/events_handler.c index 21677770ce3c6..7633aa7e96274 100644 --- a/subsys/net/conn_mgr/events_handler.c +++ b/subsys/net/conn_mgr/events_handler.c @@ -134,15 +134,21 @@ static void conn_mgr_ipv4_events_handler(struct net_mgmt_event_callback *cb, k_mutex_lock(&conn_mgr_mon_lock, K_FOREVER); switch (NET_MGMT_GET_COMMAND(mgmt_event)) { + case NET_EVENT_IPV4_CMD_ACD_SUCCEED: + __fallthrough; case NET_EVENT_IPV4_CMD_ADDR_ADD: - iface_states[idx] |= CONN_MGR_IF_IPV4_SET; + if (net_if_ipv4_get_global_addr(iface, NET_ADDR_PREFERRED)) { + iface_states[idx] |= CONN_MGR_IF_IPV4_SET; + } + break; + case NET_EVENT_IPV4_CMD_ACD_FAILED: + __fallthrough; case NET_EVENT_IPV4_CMD_ADDR_DEL: - if (net_if_ipv4_get_global_addr(iface, NET_ADDR_PREFERRED)) { - break; + if (!net_if_ipv4_get_global_addr(iface, NET_ADDR_PREFERRED)) { + iface_states[idx] &= ~CONN_MGR_IF_IPV4_SET; } - iface_states[idx] &= ~CONN_MGR_IF_IPV4_SET; break; default: goto done; From 7352aaa841206d66003d3c4f281d882b2b912a6e Mon Sep 17 00:00:00 2001 From: Robert Lubos Date: Tue, 4 Jun 2024 12:17:43 +0200 Subject: [PATCH 2084/2849] net: config: Add support for IPv4 ACD In case IPv4 conflict detection is enabled, monitor network events to determine whether IPv4 address is ready to use or not, so that the library returns only after the network setup is fully complete. Signed-off-by: Robert Lubos --- subsys/net/lib/config/init.c | 82 +++++++++++++++++++++--------------- 1 file changed, 49 insertions(+), 33 deletions(-) diff --git a/subsys/net/lib/config/init.c b/subsys/net/lib/config/init.c index 23ceeff5247e5..76d1fd7b191c7 100644 --- a/subsys/net/lib/config/init.c +++ b/subsys/net/lib/config/init.c @@ -51,34 +51,35 @@ static inline bool services_are_ready(int flags) return (atomic_get(&services_flags) & flags) == flags; } -#if defined(CONFIG_NET_DHCPV4) && defined(CONFIG_NET_NATIVE_IPV4) -static struct net_mgmt_event_callback mgmt4_cb; +#if defined(CONFIG_NET_NATIVE_IPV4) -static void ipv4_addr_add_handler(struct net_mgmt_event_callback *cb, - uint32_t mgmt_event, - struct net_if *iface) +#if defined(CONFIG_NET_DHCPV4) + +static void setup_dhcpv4(struct net_if *iface) +{ + NET_INFO("Running dhcpv4 client..."); + + net_dhcpv4_start(iface); +} + +static void print_dhcpv4_info(struct net_if *iface) { #if CONFIG_NET_CONFIG_LOG_LEVEL >= LOG_LEVEL_INF char hr_addr[NET_IPV4_ADDR_LEN]; #endif - - if (mgmt_event != NET_EVENT_IPV4_ADDR_ADD) { - return; - } - ARRAY_FOR_EACH(iface->config.ip.ipv4->unicast, i) { struct net_if_addr *if_addr = &iface->config.ip.ipv4->unicast[i].ipv4; - if (if_addr->addr_type != NET_ADDR_DHCP || !if_addr->is_used) { + if (if_addr->addr_type != NET_ADDR_DHCP || + !if_addr->is_used) { continue; } #if CONFIG_NET_CONFIG_LOG_LEVEL >= LOG_LEVEL_INF NET_INFO("IPv4 address: %s", - net_addr_ntop(AF_INET, - &if_addr->address.in_addr, - hr_addr, sizeof(hr_addr))); + net_addr_ntop(AF_INET, &if_addr->address.in_addr, + hr_addr, sizeof(hr_addr))); NET_INFO("Lease time: %u seconds", iface->config.dhcpv4.lease_time); NET_INFO("Subnet: %s", @@ -86,31 +87,37 @@ static void ipv4_addr_add_handler(struct net_mgmt_event_callback *cb, &iface->config.ip.ipv4->unicast[i].netmask, hr_addr, sizeof(hr_addr))); NET_INFO("Router: %s", - net_addr_ntop(AF_INET, - &iface->config.ip.ipv4->gw, - hr_addr, sizeof(hr_addr))); + net_addr_ntop(AF_INET, &iface->config.ip.ipv4->gw, + hr_addr, sizeof(hr_addr))); #endif break; } - - services_notify_ready(NET_CONFIG_NEED_IPV4); } -static void setup_dhcpv4(struct net_if *iface) +#else +#define setup_dhcpv4(...) +#define print_dhcpv4_info(...) +#endif /* CONFIG_NET_DHCPV4 */ + +static struct net_mgmt_event_callback mgmt4_cb; + +static void ipv4_addr_add_handler(struct net_mgmt_event_callback *cb, + uint32_t mgmt_event, + struct net_if *iface) { - NET_INFO("Running dhcpv4 client..."); + if (mgmt_event == NET_EVENT_IPV4_ADDR_ADD) { + print_dhcpv4_info(iface); - net_mgmt_init_event_callback(&mgmt4_cb, ipv4_addr_add_handler, - NET_EVENT_IPV4_ADDR_ADD); - net_mgmt_add_event_callback(&mgmt4_cb); + if (!IS_ENABLED(CONFIG_NET_IPV4_ACD)) { + services_notify_ready(NET_CONFIG_NEED_IPV4); + } + } - net_dhcpv4_start(iface); + if (mgmt_event == NET_EVENT_IPV4_ACD_SUCCEED) { + services_notify_ready(NET_CONFIG_NEED_IPV4); + } } -#else -#define setup_dhcpv4(...) -#endif /* CONFIG_NET_DHCPV4 */ - #if defined(CONFIG_NET_VLAN) && (CONFIG_NET_CONFIG_MY_VLAN_ID > 0) static void setup_vlan(struct net_if *iface) @@ -132,8 +139,6 @@ static void setup_vlan(struct net_if *iface) #error "You need to define an IPv4 address or enable DHCPv4!" #endif -#if defined(CONFIG_NET_NATIVE_IPV4) && defined(CONFIG_NET_CONFIG_MY_IPV4_ADDR) - static void setup_ipv4(struct net_if *iface) { #if CONFIG_NET_CONFIG_LOG_LEVEL >= LOG_LEVEL_INF @@ -141,6 +146,13 @@ static void setup_ipv4(struct net_if *iface) #endif struct in_addr addr, netmask; + if (IS_ENABLED(CONFIG_NET_IPV4_ACD) || IS_ENABLED(CONFIG_NET_DHCPV4)) { + net_mgmt_init_event_callback(&mgmt4_cb, ipv4_addr_add_handler, + NET_EVENT_IPV4_ADDR_ADD | + NET_EVENT_IPV4_ACD_SUCCEED); + net_mgmt_add_event_callback(&mgmt4_cb); + } + if (sizeof(CONFIG_NET_CONFIG_MY_IPV4_ADDR) == 1) { /* Empty address, skip setting ANY address in this case */ return; @@ -194,12 +206,16 @@ static void setup_ipv4(struct net_if *iface) } } - services_notify_ready(NET_CONFIG_NEED_IPV4); + if (!IS_ENABLED(CONFIG_NET_IPV4_ACD)) { + services_notify_ready(NET_CONFIG_NEED_IPV4); + } } #else #define setup_ipv4(...) -#endif /* CONFIG_NET_IPV4 && !CONFIG_NET_DHCPV4 */ +#define setup_dhcpv4(...) +#define setup_vlan(...) +#endif /* CONFIG_NET_NATIVE_IPV4*/ #if defined(CONFIG_NET_NATIVE_IPV6) From 80339ac4eea9dc387e486ec02ba03aafc28bb8c9 Mon Sep 17 00:00:00 2001 From: Robert Lubos Date: Tue, 4 Jun 2024 12:56:10 +0200 Subject: [PATCH 2085/2849] net: dhcpv4: Add support for conflict detection In case a conflict was detected on a DHCP-assigned address, send a Decline message to the server and start over. Signed-off-by: Robert Lubos --- include/zephyr/net/dhcpv4.h | 1 + subsys/net/lib/dhcpv4/Kconfig | 1 + subsys/net/lib/dhcpv4/dhcpv4.c | 112 +++++++++++++++++++++++++++++++-- 3 files changed, 109 insertions(+), 5 deletions(-) diff --git a/include/zephyr/net/dhcpv4.h b/include/zephyr/net/dhcpv4.h index c31d5f9141782..925c4e13568ac 100644 --- a/include/zephyr/net/dhcpv4.h +++ b/include/zephyr/net/dhcpv4.h @@ -40,6 +40,7 @@ enum net_dhcpv4_state { NET_DHCPV4_RENEWING, NET_DHCPV4_REBINDING, NET_DHCPV4_BOUND, + NET_DHCPV4_DECLINE, } __packed; /** @endcond */ diff --git a/subsys/net/lib/dhcpv4/Kconfig b/subsys/net/lib/dhcpv4/Kconfig index 34d40619c1d94..8c01cd3e1fa91 100644 --- a/subsys/net/lib/dhcpv4/Kconfig +++ b/subsys/net/lib/dhcpv4/Kconfig @@ -9,6 +9,7 @@ config NET_DHCPV4 bool "DHCPv4 client" select NET_MGMT select NET_MGMT_EVENT + select NET_MGMT_EVENT_INFO if NET_IPV4_ACD depends on NET_IPV4 && NET_UDP if NET_DHCPV4 diff --git a/subsys/net/lib/dhcpv4/dhcpv4.c b/subsys/net/lib/dhcpv4/dhcpv4.c index d0ea25edc4943..ffacf7ed587e4 100644 --- a/subsys/net/lib/dhcpv4/dhcpv4.c +++ b/subsys/net/lib/dhcpv4/dhcpv4.c @@ -46,7 +46,10 @@ static K_MUTEX_DEFINE(lock); static sys_slist_t dhcpv4_ifaces; static struct k_work_delayable timeout_work; -static struct net_mgmt_event_callback mgmt4_cb; +static struct net_mgmt_event_callback mgmt4_if_cb; +#if defined(CONFIG_NET_IPV4_ACD) +static struct net_mgmt_event_callback mgmt4_acd_cb; +#endif #if defined(CONFIG_NET_DHCPV4_OPTION_CALLBACKS) static sys_slist_t option_callbacks = SYS_SLIST_STATIC_INIT(&option_callbacks); @@ -437,6 +440,7 @@ static uint32_t dhcpv4_send_request(struct net_if *iface) case NET_DHCPV4_INIT: case NET_DHCPV4_SELECTING: case NET_DHCPV4_BOUND: + case NET_DHCPV4_DECLINE: /* Not possible */ NET_ASSERT(0, "Invalid state %s", net_dhcpv4_state_name(iface->config.dhcpv4.state)); @@ -543,6 +547,33 @@ static uint32_t dhcpv4_send_discover(struct net_if *iface) DHCPV4_INITIAL_DELAY_MIN; } +static void dhcpv4_send_decline(struct net_if *iface) +{ + struct net_pkt *pkt; + + iface->config.dhcpv4.xid++; + + pkt = dhcpv4_create_message(iface, NET_DHCPV4_MSG_TYPE_DECLINE, + NULL, NULL, net_ipv4_broadcast_address(), + false, true); + if (!pkt) { + goto fail; + } + + if (net_send_data(pkt) < 0) { + goto fail; + } + + net_stats_update_udp_sent(iface); + + return; + +fail: + if (pkt) { + net_pkt_unref(pkt); + } +} + static void dhcpv4_enter_selecting(struct net_if *iface) { iface->config.dhcpv4.attempts = 0U; @@ -681,6 +712,9 @@ static uint32_t dhcpv4_manage_timers(struct net_if *iface, int64_t now) switch (iface->config.dhcpv4.state) { case NET_DHCPV4_DISABLED: break; + case NET_DHCPV4_DECLINE: + dhcpv4_send_decline(iface); + __fallthrough; case NET_DHCPV4_INIT: dhcpv4_enter_selecting(iface); __fallthrough; @@ -1177,6 +1211,7 @@ static inline void dhcpv4_handle_msg_offer(struct net_if *iface, case NET_DHCPV4_RENEWING: case NET_DHCPV4_REBINDING: case NET_DHCPV4_BOUND: + case NET_DHCPV4_DECLINE: break; case NET_DHCPV4_SELECTING: dhcpv4_enter_requesting(iface, msg); @@ -1192,6 +1227,7 @@ static void dhcpv4_handle_msg_ack(struct net_if *iface) case NET_DHCPV4_INIT: case NET_DHCPV4_SELECTING: case NET_DHCPV4_BOUND: + case NET_DHCPV4_DECLINE: break; case NET_DHCPV4_REQUESTING: NET_INFO("Received: %s", @@ -1241,6 +1277,7 @@ static void dhcpv4_handle_msg_nak(struct net_if *iface) } break; case NET_DHCPV4_BOUND: + case NET_DHCPV4_DECLINE: break; case NET_DHCPV4_RENEWING: case NET_DHCPV4_REBINDING: @@ -1429,6 +1466,57 @@ static void dhcpv4_iface_event_handler(struct net_mgmt_event_callback *cb, k_mutex_unlock(&lock); } +#if defined(CONFIG_NET_IPV4_ACD) +static void dhcpv4_acd_event_handler(struct net_mgmt_event_callback *cb, + uint32_t mgmt_event, struct net_if *iface) +{ + sys_snode_t *node = NULL; + struct in_addr *addr; + + + k_mutex_lock(&lock, K_FOREVER); + + SYS_SLIST_FOR_EACH_NODE(&dhcpv4_ifaces, node) { + if (node == &iface->config.dhcpv4.node) { + break; + } + } + + if (node == NULL) { + goto out; + } + + if (mgmt_event != NET_EVENT_IPV4_ACD_FAILED && + mgmt_event != NET_EVENT_IPV4_ACD_CONFLICT) { + goto out; + } + + if (cb->info_length != sizeof(struct in_addr)) { + goto out; + } + + addr = (struct in_addr *)cb->info; + + if (!net_ipv4_addr_cmp(&iface->config.dhcpv4.requested_ip, addr)) { + goto out; + } + + if (mgmt_event == NET_EVENT_IPV4_ACD_CONFLICT) { + /* Need to remove address explicitly in this case. */ + (void)net_if_ipv4_addr_rm(iface, &iface->config.dhcpv4.requested_ip); + } + + NET_DBG("Conflict on DHCP assigned address %s, starting over", + net_sprint_ipv4_addr(addr)); + + iface->config.dhcpv4.state = NET_DHCPV4_DECLINE; + dhcpv4_immediate_timeout(&iface->config.dhcpv4); + +out: + k_mutex_unlock(&lock); +} +#endif /* CONFIG_NET_IPV4_ACD */ + const char *net_dhcpv4_state_name(enum net_dhcpv4_state state) { static const char * const name[] = { @@ -1439,6 +1527,7 @@ const char *net_dhcpv4_state_name(enum net_dhcpv4_state state) "renewing", "rebinding", "bound", + "decline," }; __ASSERT_NO_MSG(state >= 0 && state < sizeof(name)); @@ -1502,7 +1591,10 @@ static void dhcpv4_start_internal(struct net_if *iface, bool first_start) NET_DBG("wait timeout=%us", timeout); if (sys_slist_is_empty(&dhcpv4_ifaces)) { - net_mgmt_add_event_callback(&mgmt4_cb); + net_mgmt_add_event_callback(&mgmt4_if_cb); +#if defined(CONFIG_NET_IPV4_ACD) + net_mgmt_add_event_callback(&mgmt4_acd_cb); +#endif } sys_slist_append(&dhcpv4_ifaces, @@ -1517,6 +1609,7 @@ static void dhcpv4_start_internal(struct net_if *iface, bool first_start) case NET_DHCPV4_RENEWING: case NET_DHCPV4_REBINDING: case NET_DHCPV4_BOUND: + case NET_DHCPV4_DECLINE: break; } @@ -1614,6 +1707,7 @@ void net_dhcpv4_stop(struct net_if *iface) case NET_DHCPV4_SELECTING: case NET_DHCPV4_REQUESTING: case NET_DHCPV4_REBINDING: + case NET_DHCPV4_DECLINE: iface->config.dhcpv4.state = NET_DHCPV4_DISABLED; NET_DBG("state=%s", net_dhcpv4_state_name(iface->config.dhcpv4.state)); @@ -1626,7 +1720,10 @@ void net_dhcpv4_stop(struct net_if *iface) * cancellation is unsuccessful. */ (void)k_work_cancel_delayable(&timeout_work); - net_mgmt_del_event_callback(&mgmt4_cb); + net_mgmt_del_event_callback(&mgmt4_if_cb); +#if defined(CONFIG_NET_IPV4_ACD) + net_mgmt_del_event_callback(&mgmt4_acd_cb); +#endif } break; @@ -1672,8 +1769,13 @@ int net_dhcpv4_init(void) /* Catch network interface UP or DOWN events and renew the address * if interface is coming back up again. */ - net_mgmt_init_event_callback(&mgmt4_cb, dhcpv4_iface_event_handler, - NET_EVENT_IF_DOWN | NET_EVENT_IF_UP); + net_mgmt_init_event_callback(&mgmt4_if_cb, dhcpv4_iface_event_handler, + NET_EVENT_IF_DOWN | NET_EVENT_IF_UP); +#if defined(CONFIG_NET_IPV4_ACD) + net_mgmt_init_event_callback(&mgmt4_acd_cb, dhcpv4_acd_event_handler, + NET_EVENT_IPV4_ACD_FAILED | + NET_EVENT_IPV4_ACD_CONFLICT); +#endif return 0; } From cc53826cc9f41b3fa084e41f73e7eedc269bf081 Mon Sep 17 00:00:00 2001 From: Robert Lubos Date: Tue, 4 Jun 2024 17:55:05 +0200 Subject: [PATCH 2086/2849] net: ipv4: autoconf: Integrate with the ACD module The autoconf module can now reuse generic address conflict detection, which was added for all address types. Signed-off-by: Robert Lubos --- include/zephyr/net/ipv4_autoconf.h | 38 ++- include/zephyr/net/net_if.h | 21 -- subsys/net/ip/Kconfig.ipv4 | 3 + subsys/net/ip/ipv4_autoconf.c | 351 ++++--------------------- subsys/net/ip/ipv4_autoconf_internal.h | 93 ------- subsys/net/ip/net_core.c | 2 +- subsys/net/ip/net_if.c | 2 +- subsys/net/l2/ethernet/ethernet.c | 6 - 8 files changed, 95 insertions(+), 421 deletions(-) delete mode 100644 subsys/net/ip/ipv4_autoconf_internal.h diff --git a/include/zephyr/net/ipv4_autoconf.h b/include/zephyr/net/ipv4_autoconf.h index 3b686faffca5a..8d1873b439f9e 100644 --- a/include/zephyr/net/ipv4_autoconf.h +++ b/include/zephyr/net/ipv4_autoconf.h @@ -14,12 +14,44 @@ /** Current state of IPv4 Autoconfiguration */ enum net_ipv4_autoconf_state { 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 */ }; +struct net_if; + +/** + * @brief Start IPv4 autoconfiguration RFC 3927: IPv4 Link Local + * + * @details Start IPv4 IP autoconfiguration + * + * @param iface A valid pointer on an interface + */ +#if defined(CONFIG_NET_IPV4_AUTO) +void net_ipv4_autoconf_start(struct net_if *iface); +#else +static inline void net_ipv4_autoconf_start(struct net_if *iface) +{ + ARG_UNUSED(iface); +} +#endif + +/** + * @brief Reset autoconf process + * + * @details Reset IPv4 IP autoconfiguration + * + * @param iface A valid pointer on an interface + */ +#if defined(CONFIG_NET_IPV4_AUTO) +void net_ipv4_autoconf_reset(struct net_if *iface); +#else +static inline void net_ipv4_autoconf_reset(struct net_if *iface) +{ + ARG_UNUSED(iface); +} +#endif + /** @cond INTERNAL_HIDDEN */ /** @@ -28,7 +60,7 @@ enum net_ipv4_autoconf_state { #if defined(CONFIG_NET_IPV4_AUTO) void net_ipv4_autoconf_init(void); #else -#define net_ipv4_autoconf_init(...) +static inline void net_ipv4_autoconf_init(void) { } #endif /** @endcond */ diff --git a/include/zephyr/net/net_if.h b/include/zephyr/net/net_if.h index 3944315dc064b..05cdc7155f4a1 100644 --- a/include/zephyr/net/net_if.h +++ b/include/zephyr/net/net_if.h @@ -519,36 +519,15 @@ struct net_if_dhcpv4 { #if defined(CONFIG_NET_IPV4_AUTO) && defined(CONFIG_NET_NATIVE_IPV4) struct net_if_ipv4_autoconf { - /** Used for timer lists */ - sys_snode_t node; - /** Backpointer to correct network interface */ struct net_if *iface; - /** Timer start */ - int64_t timer_start; - - /** Time for INIT, DISCOVER, REQUESTING, RENEWAL */ - uint32_t timer_timeout; - - /** Current IP addr */ - struct in_addr current_ip; - /** Requested IP addr */ struct in_addr requested_ip; /** IPV4 Autoconf state in the process of network address allocation. */ enum net_ipv4_autoconf_state state; - - /** Number of sent probe requests */ - uint8_t probe_cnt; - - /** Number of sent announcements */ - uint8_t announce_cnt; - - /** Incoming conflict count */ - uint8_t conflict_cnt; }; #endif /* CONFIG_NET_IPV4_AUTO */ diff --git a/subsys/net/ip/Kconfig.ipv4 b/subsys/net/ip/Kconfig.ipv4 index 4dc1dcf94cde3..69279f7a44965 100644 --- a/subsys/net/ip/Kconfig.ipv4 +++ b/subsys/net/ip/Kconfig.ipv4 @@ -98,6 +98,9 @@ config NET_IPV4_AUTO depends on NET_ARP select EXPERIMENTAL select NET_IPV4_ACD + select NET_MGMT + select NET_MGMT_EVENT + select NET_MGMT_EVENT_INFO help Enables IPv4 auto IP address configuration (see RFC 3927) diff --git a/subsys/net/ip/ipv4_autoconf.c b/subsys/net/ip/ipv4_autoconf.c index 7774b131fa902..f08608f3b7e25 100644 --- a/subsys/net/ip/ipv4_autoconf.c +++ b/subsys/net/ip/ipv4_autoconf.c @@ -15,329 +15,91 @@ LOG_MODULE_REGISTER(net_ipv4_autoconf, CONFIG_NET_IPV4_AUTO_LOG_LEVEL); #include "net_private.h" #include #include "../l2/ethernet/arp.h" +#include #include #include #include #include -#include "ipv4_autoconf_internal.h" +static struct net_mgmt_event_callback mgmt4_acd_cb; -/* Have only one timer in order to save memory */ -static struct k_work_delayable ipv4auto_timer; - -/* Track currently active timers */ -static sys_slist_t ipv4auto_ifaces; - -#define BUF_ALLOC_TIMEOUT K_MSEC(100) - -static struct net_pkt *ipv4_autoconf_prepare_arp(struct net_if *iface) -{ - struct net_if_config *cfg = net_if_get_config(iface); - struct net_pkt *pkt; - - /* We provide AF_UNSPEC to the allocator: this packet does not - * need space for any IPv4 header. - */ - pkt = net_pkt_alloc_with_buffer(iface, sizeof(struct net_arp_hdr), - AF_UNSPEC, 0, BUF_ALLOC_TIMEOUT); - if (!pkt) { - return NULL; - } - - net_pkt_set_family(pkt, AF_INET); - net_pkt_set_ipv4_acd(pkt, true); - - return net_arp_prepare(pkt, &cfg->ipv4auto.requested_ip, - &cfg->ipv4auto.current_ip); -} - -static void ipv4_autoconf_send_probe(struct net_if_ipv4_autoconf *ipv4auto) +static inline void ipv4_autoconf_addr_set(struct net_if_ipv4_autoconf *ipv4auto) { - struct net_pkt *pkt; - - pkt = ipv4_autoconf_prepare_arp(ipv4auto->iface); - if (!pkt) { - NET_DBG("Failed to prepare probe %p", ipv4auto->iface); - return; - } - - NET_DBG("Probing pkt %p", pkt); + struct in_addr netmask = { { { 255, 255, 0, 0 } } }; - if (net_if_send_data(ipv4auto->iface, pkt) == NET_DROP) { - net_pkt_unref(pkt); - } else { - ipv4auto->probe_cnt++; - ipv4auto->state = NET_IPV4_AUTOCONF_PROBE; + if (ipv4auto->state == NET_IPV4_AUTOCONF_INIT) { + ipv4auto->requested_ip.s4_addr[0] = 169U; + ipv4auto->requested_ip.s4_addr[1] = 254U; + ipv4auto->requested_ip.s4_addr[2] = sys_rand8_get() % 254; + ipv4auto->requested_ip.s4_addr[3] = sys_rand8_get() % 254; } -} -static void ipv4_autoconf_send_announcement( - struct net_if_ipv4_autoconf *ipv4auto) -{ - struct net_pkt *pkt; + NET_DBG("%s: Starting probe for 169.254.%d.%d", + ipv4auto->state == NET_IPV4_AUTOCONF_INIT ? "Init" : "Renew", + ipv4auto->requested_ip.s4_addr[2], + ipv4auto->requested_ip.s4_addr[3]); - pkt = ipv4_autoconf_prepare_arp(ipv4auto->iface); - if (!pkt) { - NET_DBG("Failed to prepare announcement %p", ipv4auto->iface); + /* Add IPv4 address to the interface, this will trigger conflict detection. */ + if (!net_if_ipv4_addr_add(ipv4auto->iface, &ipv4auto->requested_ip, + NET_ADDR_AUTOCONF, 0)) { + NET_DBG("Failed to add IPv4 addr to iface %p", + ipv4auto->iface); return; } - NET_DBG("Announcing pkt %p", pkt); + net_if_ipv4_set_netmask_by_addr(ipv4auto->iface, + &ipv4auto->requested_ip, + &netmask); - if (net_if_send_data(ipv4auto->iface, pkt) == NET_DROP) { - net_pkt_unref(pkt); - } else { - ipv4auto->announce_cnt++; - ipv4auto->state = NET_IPV4_AUTOCONF_ANNOUNCE; - } + ipv4auto->state = NET_IPV4_AUTOCONF_ASSIGNED; } -enum net_verdict net_ipv4_autoconf_input(struct net_if *iface, - struct net_pkt *pkt) +static void acd_event_handler(struct net_mgmt_event_callback *cb, + uint32_t mgmt_event, struct net_if *iface) { struct net_if_config *cfg; - struct net_arp_hdr *arp_hdr; + struct in_addr *addr; cfg = net_if_get_config(iface); if (!cfg) { - NET_DBG("Interface %p configuration missing!", iface); - return NET_DROP; - } - - if (net_pkt_get_len(pkt) < sizeof(struct net_arp_hdr)) { - NET_DBG("Invalid ARP header (len %zu, min %zu bytes)", - net_pkt_get_len(pkt), sizeof(struct net_arp_hdr)); - return NET_DROP; - } - - arp_hdr = NET_ARP_HDR(pkt); - - if (!net_ipv4_addr_cmp_raw(arp_hdr->dst_ipaddr, - (uint8_t *)&cfg->ipv4auto.requested_ip)) { - /* No conflict */ - return NET_CONTINUE; - } - - if (!net_ipv4_addr_cmp_raw(arp_hdr->src_ipaddr, - (uint8_t *)&cfg->ipv4auto.requested_ip)) { - /* No need to defend */ - return NET_CONTINUE; + return; } - NET_DBG("Conflict detected from %s for %s, state %d", - net_sprint_ll_addr((uint8_t *)&arp_hdr->src_hwaddr, - arp_hdr->hwlen), - net_sprint_ipv4_addr(&arp_hdr->dst_ipaddr), - cfg->ipv4auto.state); - - cfg->ipv4auto.conflict_cnt++; - - switch (cfg->ipv4auto.state) { - case NET_IPV4_AUTOCONF_PROBE: - /* restart probing with renewed IP */ - net_ipv4_autoconf_start(iface); - break; - case NET_IPV4_AUTOCONF_ANNOUNCE: - case NET_IPV4_AUTOCONF_ASSIGNED: - if (cfg->ipv4auto.conflict_cnt == 1U) { - /* defend IP */ - ipv4_autoconf_send_announcement(&cfg->ipv4auto); - } else { - /* unset host ip */ - if (!net_if_ipv4_addr_rm(iface, - &cfg->ipv4auto.requested_ip)) { - NET_DBG("Failed to remove addr from iface"); - } - - /* restart probing after second conflict */ - net_ipv4_autoconf_start(iface); - } - - break; - default: - break; + if (cfg->ipv4auto.iface == NULL) { + return; } - return NET_DROP; -} - -static inline void ipv4_autoconf_addr_set(struct net_if_ipv4_autoconf *ipv4auto) -{ - struct in_addr netmask = { { { 255, 255, 0, 0 } } }; - - if (ipv4auto->announce_cnt <= - (IPV4_AUTOCONF_ANNOUNCE_NUM - 1)) { - net_ipaddr_copy(&ipv4auto->current_ip, - &ipv4auto->requested_ip); - ipv4_autoconf_send_announcement(ipv4auto); + if (mgmt_event != NET_EVENT_IPV4_ACD_SUCCEED && + mgmt_event != NET_EVENT_IPV4_ACD_FAILED && + mgmt_event != NET_EVENT_IPV4_ACD_CONFLICT) { return; } - /* Success, add new IPv4 address. */ - if (!net_if_ipv4_addr_add(ipv4auto->iface, - &ipv4auto->requested_ip, - NET_ADDR_AUTOCONF, 0)) { - NET_DBG("Failed to add IPv4 addr to iface %p", - ipv4auto->iface); + if (cb->info_length != sizeof(struct in_addr)) { return; } - net_if_ipv4_set_netmask_by_addr(ipv4auto->iface, - &ipv4auto->requested_ip, - &netmask); - - ipv4auto->state = NET_IPV4_AUTOCONF_ASSIGNED; -} + addr = (struct in_addr *)cb->info; -static void ipv4_autoconf_send(struct net_if_ipv4_autoconf *ipv4auto) -{ - switch (ipv4auto->state) { - case NET_IPV4_AUTOCONF_INIT: - ipv4auto->probe_cnt = 0U; - ipv4auto->announce_cnt = 0U; - ipv4auto->conflict_cnt = 0U; - (void)memset(&ipv4auto->current_ip, 0, sizeof(struct in_addr)); - ipv4auto->requested_ip.s4_addr[0] = 169U; - ipv4auto->requested_ip.s4_addr[1] = 254U; - ipv4auto->requested_ip.s4_addr[2] = sys_rand8_get() % 254; - ipv4auto->requested_ip.s4_addr[3] = sys_rand8_get() % 254; + if (!net_ipv4_addr_cmp(&cfg->ipv4auto.requested_ip, addr)) { + return; + } - NET_DBG("%s: Starting probe for 169.254.%d.%d", "Init", - ipv4auto->requested_ip.s4_addr[2], - ipv4auto->requested_ip.s4_addr[3]); - ipv4_autoconf_send_probe(ipv4auto); + switch (mgmt_event) { + case NET_EVENT_IPV4_ACD_SUCCEED: + cfg->ipv4auto.state = NET_IPV4_AUTOCONF_ASSIGNED; break; - case NET_IPV4_AUTOCONF_RENEW: - ipv4auto->probe_cnt = 0U; - ipv4auto->announce_cnt = 0U; - ipv4auto->conflict_cnt = 0U; - (void)memset(&ipv4auto->current_ip, 0, sizeof(struct in_addr)); - NET_DBG("%s: Starting probe for 169.254.%d.%d", "Renew", - ipv4auto->requested_ip.s4_addr[2], - ipv4auto->requested_ip.s4_addr[3]); - ipv4_autoconf_send_probe(ipv4auto); - break; - case NET_IPV4_AUTOCONF_PROBE: - /* schedule next probe */ - if (ipv4auto->probe_cnt <= (IPV4_AUTOCONF_PROBE_NUM - 1)) { - ipv4_autoconf_send_probe(ipv4auto); - break; - } + case NET_EVENT_IPV4_ACD_CONFLICT: + net_ipv4_autoconf_reset(iface); __fallthrough; - case NET_IPV4_AUTOCONF_ANNOUNCE: - ipv4_autoconf_addr_set(ipv4auto); - break; - - default: + case NET_EVENT_IPV4_ACD_FAILED: + /* Try new address. */ + cfg->ipv4auto.state = NET_IPV4_AUTOCONF_INIT; + ipv4_autoconf_addr_set(&cfg->ipv4auto); break; - } -} - -static uint32_t ipv4_autoconf_get_timeout(struct net_if_ipv4_autoconf *ipv4auto) -{ - switch (ipv4auto->state) { - case NET_IPV4_AUTOCONF_PROBE: - if (ipv4auto->conflict_cnt >= IPV4_AUTOCONF_MAX_CONFLICTS) { - NET_DBG("Rate limiting"); - return MSEC_PER_SEC * IPV4_AUTOCONF_RATE_LIMIT_INTERVAL; - - } else if (ipv4auto->probe_cnt == IPV4_AUTOCONF_PROBE_NUM) { - return MSEC_PER_SEC * IPV4_AUTOCONF_ANNOUNCE_INTERVAL; - } - - return IPV4_AUTOCONF_PROBE_WAIT * MSEC_PER_SEC + - (sys_rand32_get() % MSEC_PER_SEC); - - case NET_IPV4_AUTOCONF_ANNOUNCE: - return MSEC_PER_SEC * IPV4_AUTOCONF_ANNOUNCE_INTERVAL; - default: break; } - - return 0; -} - -static void ipv4_autoconf_submit_work(uint32_t timeout) -{ - k_work_cancel_delayable(&ipv4auto_timer); - k_work_reschedule(&ipv4auto_timer, K_MSEC(timeout)); - - NET_DBG("Next wakeup in %d ms", - k_ticks_to_ms_ceil32( - k_work_delayable_remaining_get(&ipv4auto_timer))); -} - -static bool ipv4_autoconf_check_timeout(int64_t start, uint32_t time, int64_t timeout) -{ - start += time; - if (start < 0) { - start = -start; - } - - if (start > timeout) { - return false; - } - - return true; -} - -static bool ipv4_autoconf_timedout(struct net_if_ipv4_autoconf *ipv4auto, - int64_t timeout) -{ - return ipv4_autoconf_check_timeout(ipv4auto->timer_start, - ipv4auto->timer_timeout, - timeout); -} - -static uint32_t ipv4_autoconf_manage_timeouts( - struct net_if_ipv4_autoconf *ipv4auto, - int64_t timeout) -{ - if (ipv4_autoconf_timedout(ipv4auto, timeout)) { - ipv4_autoconf_send(ipv4auto); - } - - ipv4auto->timer_timeout = ipv4_autoconf_get_timeout(ipv4auto); - - return ipv4auto->timer_timeout; -} - -static void ipv4_autoconf_timeout(struct k_work *work) -{ - uint32_t timeout_update = UINT32_MAX - 1; - int64_t timeout = k_uptime_get(); - struct net_if_ipv4_autoconf *current, *next; - - ARG_UNUSED(work); - - SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&ipv4auto_ifaces, current, next, - node) { - uint32_t next_timeout; - - next_timeout = ipv4_autoconf_manage_timeouts(current, timeout); - if (next_timeout < timeout_update) { - timeout_update = next_timeout; - } - } - - if (timeout_update != UINT32_MAX && timeout_update > 0) { - NET_DBG("Waiting for %u ms", timeout_update); - - k_work_reschedule(&ipv4auto_timer, K_MSEC(timeout_update)); - } -} - -static void ipv4_autoconf_start_timer(struct net_if *iface, - struct net_if_ipv4_autoconf *ipv4auto) -{ - sys_slist_append(&ipv4auto_ifaces, &ipv4auto->node); - - ipv4auto->timer_start = k_uptime_get(); - ipv4auto->timer_timeout = MSEC_PER_SEC * IPV4_AUTOCONF_START_DELAY; - ipv4auto->iface = iface; - - ipv4_autoconf_submit_work(ipv4auto->timer_timeout); } void net_ipv4_autoconf_start(struct net_if *iface) @@ -359,15 +121,18 @@ void net_ipv4_autoconf_start(struct net_if *iface) net_ipv4_autoconf_reset(iface); } + cfg->ipv4auto.iface = iface; + NET_DBG("Starting IPv4 autoconf for iface %p", iface); if (cfg->ipv4auto.state == NET_IPV4_AUTOCONF_ASSIGNED) { + /* Try to reuse previously used address. */ cfg->ipv4auto.state = NET_IPV4_AUTOCONF_RENEW; } else { cfg->ipv4auto.state = NET_IPV4_AUTOCONF_INIT; } - ipv4_autoconf_start_timer(iface, &cfg->ipv4auto); + ipv4_autoconf_addr_set(&cfg->ipv4auto); } void net_ipv4_autoconf_reset(struct net_if *iface) @@ -379,22 +144,16 @@ void net_ipv4_autoconf_reset(struct net_if *iface) return; } - /* Initialize interface and start probing */ - if (cfg->ipv4auto.state == NET_IPV4_AUTOCONF_ASSIGNED) { - net_if_ipv4_addr_rm(iface, &cfg->ipv4auto.current_ip); - } + net_if_ipv4_addr_rm(iface, &cfg->ipv4auto.requested_ip); NET_DBG("Autoconf reset for %p", iface); - - /* Cancel any ongoing probing/announcing attempt*/ - sys_slist_find_and_remove(&ipv4auto_ifaces, &cfg->ipv4auto.node); - - if (sys_slist_is_empty(&ipv4auto_ifaces)) { - k_work_cancel_delayable(&ipv4auto_timer); - } } void net_ipv4_autoconf_init(void) { - k_work_init_delayable(&ipv4auto_timer, ipv4_autoconf_timeout); + net_mgmt_init_event_callback(&mgmt4_acd_cb, acd_event_handler, + NET_EVENT_IPV4_ACD_SUCCEED | + NET_EVENT_IPV4_ACD_FAILED | + NET_EVENT_IPV4_ACD_CONFLICT); + net_mgmt_add_event_callback(&mgmt4_acd_cb); } diff --git a/subsys/net/ip/ipv4_autoconf_internal.h b/subsys/net/ip/ipv4_autoconf_internal.h deleted file mode 100644 index 0d78d51d98ed2..0000000000000 --- a/subsys/net/ip/ipv4_autoconf_internal.h +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright (c) 2017 Matthias Boesl - * - * SPDX-License-Identifier: Apache-2.0 - */ - -/** @file - * @brief IPv4 Autoconfiguration - * - * This is not to be included by the application. - */ - -#ifndef __IPV4_AUTOCONF_INTERNAL_H -#define __IPV4_AUTOCONF_INTERNAL_H - -#include - -#include - -/* Initial random delay*/ -#define IPV4_AUTOCONF_PROBE_WAIT 1 - -/* Number of probe packets */ -#define IPV4_AUTOCONF_PROBE_NUM 3 - -/* Minimum delay till repeated probe */ -#define IPV4_AUTOCONF_PROBE_MIN 1 - -/* Maximum delay till repeated probe */ -#define IPV4_AUTOCONF_PROBE_MAX 2 - -/* Number of announcement packets */ -#define IPV4_AUTOCONF_ANNOUNCE_NUM 2 - -/* Time between announcement packets */ -#define IPV4_AUTOCONF_ANNOUNCE_INTERVAL 2 - -/* Max conflicts before rate limiting */ -#define IPV4_AUTOCONF_MAX_CONFLICTS 10 - -/* Delay between successive attempts */ -#define IPV4_AUTOCONF_RATE_LIMIT_INTERVAL 60 - -/* Minimum interval between defensive ARPs */ -#define IPV4_AUTOCONF_DEFEND_INTERVAL 10 - -/* Time between carrier up and first probe */ -#define IPV4_AUTOCONF_START_DELAY 3 - -/** - * @brief Start IPv4 autoconfiguration RFC 3927: IPv4 Link Local - * - * @details Start IPv4 IP autoconfiguration - * - * @param iface A valid pointer on an interface - */ -#if defined(CONFIG_NET_IPV4_AUTO) -void net_ipv4_autoconf_start(struct net_if *iface); -#else -#define net_ipv4_autoconf_start(...) -#endif - -/** - * @brief Reset autoconf process - * - * @details Reset IPv4 IP autoconfiguration - * - * @param iface A valid pointer on an interface - */ -#if defined(CONFIG_NET_IPV4_AUTO) -void net_ipv4_autoconf_reset(struct net_if *iface); -#else -#define net_ipv4_autoconf_reset(...) -#endif - -/** - * @brief Autoconf ARP input message handler. - * - * @details Called when ARP message is received when auto is enabled. - * - * @param iface A valid pointer on an interface - * @param pkt Received network packet - * - * @return What should be done with packet (drop or accept) - */ -#if defined(CONFIG_NET_IPV4_AUTO) -enum net_verdict net_ipv4_autoconf_input(struct net_if *iface, - struct net_pkt *pkt); -#else -#define net_ipv4_autoconf_input(...) NET_CONTINUE -#endif - -#endif /* __IPV4_AUTOCONF_INTERNAL_H */ diff --git a/subsys/net/ip/net_core.c b/subsys/net/ip/net_core.c index fe37c75d97c48..6f05ea7e5f2ed 100644 --- a/subsys/net/ip/net_core.c +++ b/subsys/net/ip/net_core.c @@ -21,6 +21,7 @@ LOG_MODULE_REGISTER(net_core, CONFIG_NET_CORE_LOG_LEVEL); #include #include +#include #include #include #include @@ -55,7 +56,6 @@ LOG_MODULE_REGISTER(net_core, CONFIG_NET_CORE_LOG_LEVEL); #include "connection.h" #include "udp_internal.h" #include "tcp_internal.h" -#include "ipv4_autoconf_internal.h" #include "net_stats.h" diff --git a/subsys/net/ip/net_if.c b/subsys/net/ip/net_if.c index 3cb112bc80f2d..bfadd34596269 100644 --- a/subsys/net/ip/net_if.c +++ b/subsys/net/ip/net_if.c @@ -16,6 +16,7 @@ LOG_MODULE_REGISTER(net_if, CONFIG_NET_IF_LOG_LEVEL); #include #include #include +#include #include #include #include @@ -30,7 +31,6 @@ LOG_MODULE_REGISTER(net_if, CONFIG_NET_IF_LOG_LEVEL); #include "net_private.h" #include "ipv4.h" #include "ipv6.h" -#include "ipv4_autoconf_internal.h" #include "net_stats.h" diff --git a/subsys/net/l2/ethernet/ethernet.c b/subsys/net/l2/ethernet/ethernet.c index 403df565ca883..8db861aae57fd 100644 --- a/subsys/net/l2/ethernet/ethernet.c +++ b/subsys/net/l2/ethernet/ethernet.c @@ -27,7 +27,6 @@ LOG_MODULE_REGISTER(net_ethernet, CONFIG_NET_L2_ETHERNET_LOG_LEVEL); #include "net_private.h" #include "ipv6.h" #include "ipv4.h" -#include "ipv4_autoconf_internal.h" #include "bridge.h" #define NET_BUF_TIMEOUT K_MSEC(100) @@ -391,11 +390,6 @@ static enum net_verdict ethernet_recv(struct net_if *iface, net_sprint_ll_addr((uint8_t *)hdr->src.addr, sizeof(struct net_eth_addr))); - if (IS_ENABLED(CONFIG_NET_IPV4_AUTO) && - net_ipv4_autoconf_input(iface, pkt) == NET_DROP) { - return NET_DROP; - } - if (IS_ENABLED(CONFIG_NET_IPV4_ACD) && net_ipv4_acd_input(iface, pkt) == NET_DROP) { return NET_DROP; From c0161c8052ef3971cc529c9de95d8a6cc82033bf Mon Sep 17 00:00:00 2001 From: Robert Lubos Date: Wed, 5 Jun 2024 15:17:00 +0200 Subject: [PATCH 2087/2849] net: l2: ethernet: arp: Simplify ACD case In case of ACD Probe/Announcement, all we need is to generate ARP packet, we don't really want any cache entries to be created or searched for. There was a bug, that a cache entry was created for the Announcement sent, resulting in skipped ARP packet generation and malformed packet being sent by the ACD module. Therefore, simplify all this, by simply returning early in case of conflict detection packets. Signed-off-by: Robert Lubos --- subsys/net/l2/ethernet/arp.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/subsys/net/l2/ethernet/arp.c b/subsys/net/l2/ethernet/arp.c index a166e304f4244..07066472da964 100644 --- a/subsys/net/l2/ethernet/arp.c +++ b/subsys/net/l2/ethernet/arp.c @@ -355,6 +355,11 @@ struct net_pkt *net_arp_prepare(struct net_pkt *pkt, return NULL; } + if (net_pkt_ipv4_acd(pkt)) { + return arp_prepare(net_pkt_iface(pkt), request_ip, NULL, + pkt, current_ip); + } + if (IS_ENABLED(CONFIG_NET_IPV4_AUTO)) { is_ipv4_ll_used = net_ipv4_is_ll_addr((struct in_addr *) &NET_IPV4_HDR(pkt)->src) || @@ -406,8 +411,7 @@ struct net_pkt *net_arp_prepare(struct net_pkt *pkt, * in the pending list and if so, resend the request, otherwise just * append the packet to the request fifo list. */ - if (!net_pkt_ipv4_acd(pkt) && - k_queue_unique_append(&entry->pending_queue._queue, + if (k_queue_unique_append(&entry->pending_queue._queue, net_pkt_ref(pkt))) { NET_DBG("Pending ARP request for %s, queuing pkt %p", net_sprint_ipv4_addr(addr), pkt); From f3d6324bcaa40dfba7524c95cf21597de5c62a79 Mon Sep 17 00:00:00 2001 From: Robert Lubos Date: Tue, 4 Jun 2024 11:21:28 +0200 Subject: [PATCH 2088/2849] tests: net: all: Enable IPv4 ACD in the test suite Make sure ACD is enabled in the build-all configuration. 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 90d38919cdad8..7944be6a884d6 100644 --- a/tests/net/all/prj.conf +++ b/tests/net/all/prj.conf @@ -204,6 +204,7 @@ CONFIG_NET_MGMT_EVENT_MONITOR_AUTO_START=y # IPv4 CONFIG_NET_IPV4=y +CONFIG_NET_IPV4_ACD=y CONFIG_NET_INITIAL_TTL=42 CONFIG_NET_IF_UNICAST_IPV4_ADDR_COUNT=2 CONFIG_NET_IF_MCAST_IPV4_ADDR_COUNT=2 From 3501d6e6d4254237d709f8e1ece38e2821fe6eb8 Mon Sep 17 00:00:00 2001 From: Robert Lubos Date: Thu, 6 Jun 2024 09:38:30 +0200 Subject: [PATCH 2089/2849] net: shell: ipv4: Add information about ACD Print information in IPv4 shell whether address conflict detection is enabled or not. Signed-off-by: Robert Lubos --- subsys/net/lib/shell/ipv4.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/subsys/net/lib/shell/ipv4.c b/subsys/net/lib/shell/ipv4.c index 2e6d4ccf7d6fd..74afea9a54ac7 100644 --- a/subsys/net/lib/shell/ipv4.c +++ b/subsys/net/lib/shell/ipv4.c @@ -67,6 +67,9 @@ static int cmd_net_ipv4(const struct shell *sh, size_t argc, char *argv[]) PR("IPv4 fragmentation support : %s\n", IS_ENABLED(CONFIG_NET_IPV4_FRAGMENT) ? "enabled" : "disabled"); + PR("IPv4 conflict detection support : %s\n", + IS_ENABLED(CONFIG_NET_IPV4_ACD) ? "enabled" : + "disabled"); PR("Max number of IPv4 network interfaces " "in the system : %d\n", CONFIG_NET_IF_MAX_IPV4_COUNT); From 875755fbb23d1ab38f45e4fe7dcca088c595187f Mon Sep 17 00:00:00 2001 From: Georges Oates_Larsen Date: Mon, 6 May 2024 10:37:04 -0700 Subject: [PATCH 2090/2849] net: conn_mgr: Track ready count ephemerally Instead of incrementing and decrementing global counter, just recompute the ready-count from scratch every time conn_mgr_mon_handle_update is called. This will simplify the introduction of additional ready count types. This should have no externally observable impact on the behavior of conn_mgr. Signed-off-by: Georges Oates_Larsen --- subsys/net/conn_mgr/conn_mgr_monitor.c | 36 ++++++++++---------------- subsys/net/conn_mgr/conn_mgr_private.h | 2 -- subsys/net/conn_mgr/events_handler.c | 4 --- 3 files changed, 14 insertions(+), 28 deletions(-) diff --git a/subsys/net/conn_mgr/conn_mgr_monitor.c b/subsys/net/conn_mgr/conn_mgr_monitor.c index 0f8c9567b8ce7..8a87d2e89c1e8 100644 --- a/subsys/net/conn_mgr/conn_mgr_monitor.c +++ b/subsys/net/conn_mgr/conn_mgr_monitor.c @@ -34,8 +34,8 @@ static struct k_thread conn_mgr_mon_thread; */ uint16_t iface_states[CONN_MGR_IFACE_MAX]; -/* Tracks the total number of L4-ready ifaces */ -static uint16_t ready_count; +/* Tracks the most recent total quantity of L4-ready ifaces */ +static uint16_t last_ready_count; /* Tracks the last ifaces to change state in each respective direction */ static struct net_if *last_iface_down; @@ -82,11 +82,8 @@ static void conn_mgr_mon_set_ready(int idx, bool readiness) if (readiness) { iface_states[idx] |= CONN_MGR_IF_READY; - - ready_count += 1; last_iface_up = conn_mgr_mon_get_if_by_index(idx); } else { - ready_count -= 1; last_iface_down = conn_mgr_mon_get_if_by_index(idx); } } @@ -94,7 +91,7 @@ static void conn_mgr_mon_set_ready(int idx, bool readiness) static void conn_mgr_mon_handle_update(void) { int idx; - int original_ready_count; + int ready_count; bool is_ip_ready; bool is_ipv6_ready; bool is_ipv4_ready; @@ -105,21 +102,13 @@ static void conn_mgr_mon_handle_update(void) k_mutex_lock(&conn_mgr_mon_lock, K_FOREVER); - original_ready_count = ready_count; + ready_count = 0; for (idx = 0; idx < ARRAY_SIZE(iface_states); idx++) { if (iface_states[idx] == 0) { /* This interface is not used */ continue; } - if (!(iface_states[idx] & CONN_MGR_IF_CHANGED)) { - /* No changes on this iface */ - continue; - } - - /* Clear the state-change flag */ - iface_states[idx] &= ~CONN_MGR_IF_CHANGED; - /* Detect whether the iface is currently or was L4 ready */ was_l4_ready = iface_states[idx] & CONN_MGR_IF_READY; is_ipv6_ready = iface_states[idx] & CONN_MGR_IF_IPV6_SET; @@ -134,17 +123,24 @@ static void conn_mgr_mon_handle_update(void) /* Track the iface readiness change */ conn_mgr_mon_set_ready(idx, is_l4_ready); } + + /* Track ready iface count */ + if (is_l4_ready) { + ready_count += 1; + } + } /* If the total number of ready ifaces changed, possibly send an event */ - if (ready_count != original_ready_count) { + if (ready_count != last_ready_count) { if (ready_count == 0) { /* We just lost connectivity */ net_mgmt_event_notify(NET_EVENT_L4_DISCONNECTED, last_iface_down); - } else if (original_ready_count == 0) { + } else if (last_ready_count == 0) { /* We just gained connectivity */ net_mgmt_event_notify(NET_EVENT_L4_CONNECTED, last_iface_up); } + last_ready_count = ready_count; } k_mutex_unlock(&conn_mgr_mon_lock); @@ -181,8 +177,6 @@ static void conn_mgr_mon_initial_state(struct net_if *iface) } - iface_states[idx] |= CONN_MGR_IF_CHANGED; - k_mutex_unlock(&conn_mgr_mon_lock); } @@ -224,7 +218,7 @@ void conn_mgr_mon_resend_status(void) { k_mutex_lock(&conn_mgr_mon_lock, K_FOREVER); - if (ready_count == 0) { + if (last_ready_count == 0) { net_mgmt_event_notify(NET_EVENT_L4_DISCONNECTED, last_iface_down); } else { net_mgmt_event_notify(NET_EVENT_L4_CONNECTED, last_iface_up); @@ -242,7 +236,6 @@ void conn_mgr_ignore_iface(struct net_if *iface) if (!(iface_states[idx] & CONN_MGR_IF_IGNORED)) { /* Set ignored flag and mark state as changed */ iface_states[idx] |= CONN_MGR_IF_IGNORED; - iface_states[idx] |= CONN_MGR_IF_CHANGED; k_sem_give(&conn_mgr_mon_updated); } @@ -258,7 +251,6 @@ void conn_mgr_watch_iface(struct net_if *iface) if (iface_states[idx] & CONN_MGR_IF_IGNORED) { /* Clear ignored flag and mark state as changed */ iface_states[idx] &= ~CONN_MGR_IF_IGNORED; - iface_states[idx] |= CONN_MGR_IF_CHANGED; k_sem_give(&conn_mgr_mon_updated); } diff --git a/subsys/net/conn_mgr/conn_mgr_private.h b/subsys/net/conn_mgr/conn_mgr_private.h index 5b03912f924f2..1d5b5d8efec54 100644 --- a/subsys/net/conn_mgr/conn_mgr_private.h +++ b/subsys/net/conn_mgr/conn_mgr_private.h @@ -30,8 +30,6 @@ /* Internal state flags */ #define CONN_MGR_IF_READY BIT(14) -/* Event flags */ -#define CONN_MGR_IF_CHANGED BIT(15) /* NET_MGMT event masks */ #define CONN_MGR_IFACE_EVENTS_MASK (NET_EVENT_IF_DOWN | \ diff --git a/subsys/net/conn_mgr/events_handler.c b/subsys/net/conn_mgr/events_handler.c index 7633aa7e96274..8f15a8b6c6225 100644 --- a/subsys/net/conn_mgr/events_handler.c +++ b/subsys/net/conn_mgr/events_handler.c @@ -47,8 +47,6 @@ static void conn_mgr_iface_events_handler(struct net_mgmt_event_callback *cb, default: goto done; } - - iface_states[idx] |= CONN_MGR_IF_CHANGED; k_sem_give(&conn_mgr_mon_updated); done: @@ -95,7 +93,6 @@ static void conn_mgr_ipv6_events_handler(struct net_mgmt_event_callback *cb, goto done; } - iface_states[idx] |= CONN_MGR_IF_CHANGED; k_sem_give(&conn_mgr_mon_updated); done: @@ -154,7 +151,6 @@ static void conn_mgr_ipv4_events_handler(struct net_mgmt_event_callback *cb, goto done; } - iface_states[idx] |= CONN_MGR_IF_CHANGED; k_sem_give(&conn_mgr_mon_updated); done: From 32ae816d0beb1dd84198aff7b137b06a597644c8 Mon Sep 17 00:00:00 2001 From: Georges Oates_Larsen Date: Wed, 22 May 2024 10:23:09 -0700 Subject: [PATCH 2091/2849] net: conn_mgr: Simplify blame handling Don't track up/down blame separately. Instead, track a single last-blame iface. Don't track blame iface inside set_ready. Instead, track directly inside handle_update. These two changes will simplify the addition of blame for IPv4- and IPv6-specific events. Signed-off-by: Georges Oates_Larsen --- subsys/net/conn_mgr/conn_mgr_monitor.c | 35 +++++++++++++------------- 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/subsys/net/conn_mgr/conn_mgr_monitor.c b/subsys/net/conn_mgr/conn_mgr_monitor.c index 8a87d2e89c1e8..fea84b1e0fc33 100644 --- a/subsys/net/conn_mgr/conn_mgr_monitor.c +++ b/subsys/net/conn_mgr/conn_mgr_monitor.c @@ -37,9 +37,8 @@ uint16_t iface_states[CONN_MGR_IFACE_MAX]; /* Tracks the most recent total quantity of L4-ready ifaces */ static uint16_t last_ready_count; -/* Tracks the last ifaces to change state in each respective direction */ -static struct net_if *last_iface_down; -static struct net_if *last_iface_up; +/* Tracks the last iface to cause a major state change */ +static struct net_if *last_blame; /* Used to signal when modifications have been made that need to be responded to */ K_SEM_DEFINE(conn_mgr_mon_updated, 1, 1); @@ -70,7 +69,7 @@ static int conn_mgr_get_index_for_if(struct net_if *iface) } /** - * @brief Marks an iface as ready or unready and updates all associated state tracking. + * @brief Conveniently update iface readiness state * * @param idx - index (in iface_states) of the iface to mark ready or unready * @param readiness - true if the iface should be considered ready, otherwise false @@ -82,16 +81,12 @@ static void conn_mgr_mon_set_ready(int idx, bool readiness) if (readiness) { iface_states[idx] |= CONN_MGR_IF_READY; - last_iface_up = conn_mgr_mon_get_if_by_index(idx); - } else { - last_iface_down = conn_mgr_mon_get_if_by_index(idx); } } static void conn_mgr_mon_handle_update(void) { int idx; - int ready_count; bool is_ip_ready; bool is_ipv6_ready; bool is_ipv4_ready; @@ -99,6 +94,8 @@ static void conn_mgr_mon_handle_update(void) bool is_oper_up; bool was_l4_ready; bool is_ignored; + int ready_count = 0; + struct net_if *blame = NULL; k_mutex_lock(&conn_mgr_mon_lock, K_FOREVER); @@ -118,29 +115,31 @@ static void conn_mgr_mon_handle_update(void) is_ip_ready = is_ipv6_ready || is_ipv4_ready; is_l4_ready = is_oper_up && is_ip_ready && !is_ignored; - /* Respond to changes to iface readiness */ - if (was_l4_ready != is_l4_ready) { - /* Track the iface readiness change */ - conn_mgr_mon_set_ready(idx, is_l4_ready); - } - /* Track ready iface count */ if (is_l4_ready) { ready_count += 1; } + /* If readiness changed, track blame for possibly triggered events */ + if (was_l4_ready != is_l4_ready) { + blame = conn_mgr_mon_get_if_by_index(idx); + } + + /* Update readiness state flag with the (possibly) new value */ + conn_mgr_mon_set_ready(idx, is_l4_ready); } /* If the total number of ready ifaces changed, possibly send an event */ if (ready_count != last_ready_count) { if (ready_count == 0) { /* We just lost connectivity */ - net_mgmt_event_notify(NET_EVENT_L4_DISCONNECTED, last_iface_down); + net_mgmt_event_notify(NET_EVENT_L4_DISCONNECTED, blame); } else if (last_ready_count == 0) { /* We just gained connectivity */ - net_mgmt_event_notify(NET_EVENT_L4_CONNECTED, last_iface_up); + net_mgmt_event_notify(NET_EVENT_L4_CONNECTED, blame); } last_ready_count = ready_count; + last_blame = blame; } k_mutex_unlock(&conn_mgr_mon_lock); @@ -219,9 +218,9 @@ void conn_mgr_mon_resend_status(void) k_mutex_lock(&conn_mgr_mon_lock, K_FOREVER); if (last_ready_count == 0) { - net_mgmt_event_notify(NET_EVENT_L4_DISCONNECTED, last_iface_down); + net_mgmt_event_notify(NET_EVENT_L4_DISCONNECTED, last_blame); } else { - net_mgmt_event_notify(NET_EVENT_L4_CONNECTED, last_iface_up); + net_mgmt_event_notify(NET_EVENT_L4_CONNECTED, last_blame); } k_mutex_unlock(&conn_mgr_mon_lock); From 85c4cb9265529fc5efaa9aac0ecb98c8c309808a Mon Sep 17 00:00:00 2001 From: Georges Oates_Larsen Date: Mon, 6 May 2024 16:27:05 -0700 Subject: [PATCH 2092/2849] net: conn_mgr: Add IPv4 and IPv6 tracking conn_mgr now fires: - NET_EVENT_L4_IPV4_CONNECTED - NET_EVENT_L4_IPV4_DISCONNECTED - NET_EVENT_L4_IPV6_CONNECTED - NET_EVENT_L4_IPV6_DISCONNECTED These events track whether there are any ready ifaces offering specifically IPv4 or specifically IPv6 connectivity. Signed-off-by: Georges Oates_Larsen --- doc/connectivity/networking/conn_mgr/main.rst | 11 ++ include/zephyr/net/net_event.h | 21 ++++ subsys/net/conn_mgr/conn_mgr_monitor.c | 113 +++++++++++++++--- subsys/net/conn_mgr/conn_mgr_private.h | 5 +- 4 files changed, 132 insertions(+), 18 deletions(-) diff --git a/doc/connectivity/networking/conn_mgr/main.rst b/doc/connectivity/networking/conn_mgr/main.rst index fd7a8bf87eec5..8788da9ceb82b 100644 --- a/doc/connectivity/networking/conn_mgr/main.rst +++ b/doc/connectivity/networking/conn_mgr/main.rst @@ -73,6 +73,17 @@ Afterwards, ifaces can become ready or unready without firing additional events, When there are no longer any ready ifaces left, the :c:macro:`NET_EVENT_L4_DISCONNECTED` :ref:`network management ` event is triggered, and IP connectivity is said to be unready. +.. note:: + + Connection Manager also fires the following more specific ``CONNECTED`` / ``DISCONNECTED`` events: + + - :c:macro:`NET_EVENT_L4_IPV4_CONNECTED` + - :c:macro:`NET_EVENT_L4_IPV4_DISCONNECTED` + - :c:macro:`NET_EVENT_L4_IPV6_CONNECTED` + - :c:macro:`NET_EVENT_L4_IPV6_DISCONNECTED` + + These are similar to :c:macro:`NET_EVENT_L4_CONNECTED` and :c:macro:`NET_EVENT_L4_DISCONNECTED`, but specifically track whether IPv4- and IPv6-capable ifaces are ready. + .. _conn_mgr_monitoring_usage: Usage diff --git a/include/zephyr/net/net_event.h b/include/zephyr/net/net_event.h index a15d5f2078078..8e37638f7531b 100644 --- a/include/zephyr/net/net_event.h +++ b/include/zephyr/net/net_event.h @@ -112,6 +112,10 @@ enum net_event_ipv4_cmd { enum net_event_l4_cmd { NET_EVENT_L4_CMD_CONNECTED = 1, NET_EVENT_L4_CMD_DISCONNECTED, + NET_EVENT_L4_CMD_IPV4_CONNECTED, + NET_EVENT_L4_CMD_IPV4_DISCONNECTED, + NET_EVENT_L4_CMD_IPV6_CONNECTED, + NET_EVENT_L4_CMD_IPV6_DISCONNECTED, NET_EVENT_L4_CMD_DNS_SERVER_ADD, NET_EVENT_L4_CMD_DNS_SERVER_DEL, NET_EVENT_L4_CMD_HOSTNAME_CHANGED, @@ -307,6 +311,23 @@ enum net_event_l4_cmd { #define NET_EVENT_L4_DISCONNECTED \ (_NET_EVENT_L4_BASE | NET_EVENT_L4_CMD_DISCONNECTED) + +/** Event raised when IPv4 network connectivity becomes available. */ +#define NET_EVENT_L4_IPV4_CONNECTED \ + (_NET_EVENT_L4_BASE | NET_EVENT_L4_CMD_IPV4_CONNECTED) + +/** Event emitted when IPv4 network connectivity becomes lost. */ +#define NET_EVENT_L4_IPV4_DISCONNECTED \ + (_NET_EVENT_L4_BASE | NET_EVENT_L4_CMD_IPV4_DISCONNECTED) + +/** Event emitted when IPv6 network connectivity becomes available. */ +#define NET_EVENT_L4_IPV6_CONNECTED \ + (_NET_EVENT_L4_BASE | NET_EVENT_L4_CMD_IPV6_CONNECTED) + +/** Event emitted when IPv6 network connectivity becomes available. */ +#define NET_EVENT_L4_IPV6_DISCONNECTED \ + (_NET_EVENT_L4_BASE | NET_EVENT_L4_CMD_IPV6_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) diff --git a/subsys/net/conn_mgr/conn_mgr_monitor.c b/subsys/net/conn_mgr/conn_mgr_monitor.c index fea84b1e0fc33..09097f49b0040 100644 --- a/subsys/net/conn_mgr/conn_mgr_monitor.c +++ b/subsys/net/conn_mgr/conn_mgr_monitor.c @@ -34,11 +34,15 @@ static struct k_thread conn_mgr_mon_thread; */ uint16_t iface_states[CONN_MGR_IFACE_MAX]; -/* Tracks the most recent total quantity of L4-ready ifaces */ +/* Tracks the most recent total quantity of L4-ready ifaces (any, IPv4, IPv6) */ static uint16_t last_ready_count; +static uint16_t last_ready_count_ipv4; +static uint16_t last_ready_count_ipv6; -/* Tracks the last iface to cause a major state change */ +/* Tracks the last ifaces to cause a major state change (any, IPv4, IPv6) */ static struct net_if *last_blame; +static struct net_if *last_blame_ipv4; +static struct net_if *last_blame_ipv6; /* Used to signal when modifications have been made that need to be responded to */ K_SEM_DEFINE(conn_mgr_mon_updated, 1, 1); @@ -72,61 +76,100 @@ static int conn_mgr_get_index_for_if(struct net_if *iface) * @brief Conveniently update iface readiness state * * @param idx - index (in iface_states) of the iface to mark ready or unready - * @param readiness - true if the iface should be considered ready, otherwise false + * @param ready - true if the iface should be considered ready, otherwise false + * @param ready_ipv4 - true if the iface is ready with IPv4, otherwise false + * @param ready_ipv6 - true if the iface is ready with IPv6, otherwise false */ -static void conn_mgr_mon_set_ready(int idx, bool readiness) +static void conn_mgr_mon_set_ready(int idx, bool ready, bool ready_ipv4, bool ready_ipv6) { /* Clear and then update the L4-readiness bit */ iface_states[idx] &= ~CONN_MGR_IF_READY; + iface_states[idx] &= ~CONN_MGR_IF_READY_IPV4; + iface_states[idx] &= ~CONN_MGR_IF_READY_IPV6; - if (readiness) { + if (ready) { iface_states[idx] |= CONN_MGR_IF_READY; } + + if (ready_ipv4) { + iface_states[idx] |= CONN_MGR_IF_READY_IPV4; + } + + if (ready_ipv6) { + iface_states[idx] |= CONN_MGR_IF_READY_IPV6; + } } static void conn_mgr_mon_handle_update(void) { int idx; - bool is_ip_ready; + bool has_ip; + bool has_ipv6; + bool has_ipv4; + bool is_l4_ready; bool is_ipv6_ready; bool is_ipv4_ready; - bool is_l4_ready; bool is_oper_up; bool was_l4_ready; + bool was_ipv6_ready; + bool was_ipv4_ready; bool is_ignored; int ready_count = 0; + int ready_count_ipv4 = 0; + int ready_count_ipv6 = 0; struct net_if *blame = NULL; + struct net_if *blame_ipv4 = NULL; + struct net_if *blame_ipv6 = NULL; k_mutex_lock(&conn_mgr_mon_lock, K_FOREVER); - ready_count = 0; for (idx = 0; idx < ARRAY_SIZE(iface_states); idx++) { if (iface_states[idx] == 0) { /* This interface is not used */ continue; } - /* Detect whether the iface is currently or was L4 ready */ + /* Detect whether iface was previously considered ready */ was_l4_ready = iface_states[idx] & CONN_MGR_IF_READY; - is_ipv6_ready = iface_states[idx] & CONN_MGR_IF_IPV6_SET; - is_ipv4_ready = iface_states[idx] & CONN_MGR_IF_IPV4_SET; + was_ipv6_ready = iface_states[idx] & CONN_MGR_IF_READY_IPV6; + was_ipv4_ready = iface_states[idx] & CONN_MGR_IF_READY_IPV4; + + /* Collect iface readiness requirements */ + has_ipv6 = iface_states[idx] & CONN_MGR_IF_IPV6_SET; + has_ipv4 = iface_states[idx] & CONN_MGR_IF_IPV4_SET; + has_ip = has_ipv6 || has_ipv4; is_oper_up = iface_states[idx] & CONN_MGR_IF_UP; is_ignored = iface_states[idx] & CONN_MGR_IF_IGNORED; - is_ip_ready = is_ipv6_ready || is_ipv4_ready; - is_l4_ready = is_oper_up && is_ip_ready && !is_ignored; + + /* Determine whether iface is currently considered ready */ + is_l4_ready = is_oper_up && has_ip && !is_ignored; + is_ipv6_ready = is_oper_up && has_ipv6 && !is_ignored; + is_ipv4_ready = is_oper_up && has_ipv4 && !is_ignored; /* Track ready iface count */ if (is_l4_ready) { ready_count += 1; } + if (is_ipv6_ready) { + ready_count_ipv6 += 1; + } + if (is_ipv4_ready) { + ready_count_ipv4 += 1; + } - /* If readiness changed, track blame for possibly triggered events */ + /* If any states changed, track blame for possibly triggered events */ if (was_l4_ready != is_l4_ready) { blame = conn_mgr_mon_get_if_by_index(idx); } + if (was_ipv6_ready != is_ipv6_ready) { + blame_ipv6 = conn_mgr_mon_get_if_by_index(idx); + } + if (was_ipv4_ready != is_ipv4_ready) { + blame_ipv4 = conn_mgr_mon_get_if_by_index(idx); + } - /* Update readiness state flag with the (possibly) new value */ - conn_mgr_mon_set_ready(idx, is_l4_ready); + /* Update readiness state flags with the (possibly) new values */ + conn_mgr_mon_set_ready(idx, is_l4_ready, is_ipv4_ready, is_ipv6_ready); } /* If the total number of ready ifaces changed, possibly send an event */ @@ -142,6 +185,32 @@ static void conn_mgr_mon_handle_update(void) last_blame = blame; } + /* Same, but specifically for IPv4 */ + if (ready_count_ipv4 != last_ready_count_ipv4) { + if (ready_count_ipv4 == 0) { + /* We just lost IPv4 connectivity */ + net_mgmt_event_notify(NET_EVENT_L4_IPV4_DISCONNECTED, blame_ipv4); + } else if (last_ready_count_ipv4 == 0) { + /* We just gained IPv4 connectivity */ + net_mgmt_event_notify(NET_EVENT_L4_IPV4_CONNECTED, blame_ipv4); + } + last_ready_count_ipv4 = ready_count_ipv4; + last_blame_ipv4 = blame_ipv4; + } + + /* Same, but specifically for IPv6 */ + if (ready_count_ipv6 != last_ready_count_ipv6) { + if (ready_count_ipv6 == 0) { + /* We just lost IPv6 connectivity */ + net_mgmt_event_notify(NET_EVENT_L4_IPV6_DISCONNECTED, blame_ipv6); + } else if (last_ready_count_ipv6 == 0) { + /* We just gained IPv6 connectivity */ + net_mgmt_event_notify(NET_EVENT_L4_IPV6_CONNECTED, blame_ipv6); + } + last_ready_count_ipv6 = ready_count_ipv6; + last_blame_ipv6 = blame_ipv6; + } + k_mutex_unlock(&conn_mgr_mon_lock); } @@ -223,6 +292,18 @@ void conn_mgr_mon_resend_status(void) net_mgmt_event_notify(NET_EVENT_L4_CONNECTED, last_blame); } + if (last_ready_count_ipv6 == 0) { + net_mgmt_event_notify(NET_EVENT_L4_IPV6_DISCONNECTED, last_blame_ipv6); + } else { + net_mgmt_event_notify(NET_EVENT_L4_IPV6_CONNECTED, last_blame_ipv6); + } + + if (last_ready_count_ipv4 == 0) { + net_mgmt_event_notify(NET_EVENT_L4_IPV4_DISCONNECTED, last_blame_ipv4); + } else { + net_mgmt_event_notify(NET_EVENT_L4_IPV4_CONNECTED, last_blame_ipv4); + } + k_mutex_unlock(&conn_mgr_mon_lock); } diff --git a/subsys/net/conn_mgr/conn_mgr_private.h b/subsys/net/conn_mgr/conn_mgr_private.h index 1d5b5d8efec54..5aa08ed7b256b 100644 --- a/subsys/net/conn_mgr/conn_mgr_private.h +++ b/subsys/net/conn_mgr/conn_mgr_private.h @@ -28,8 +28,9 @@ #define CONN_MGR_IF_IGNORED BIT(7) /* Internal state flags */ -#define CONN_MGR_IF_READY BIT(14) - +#define CONN_MGR_IF_READY BIT(13) +#define CONN_MGR_IF_READY_IPV4 BIT(14) +#define CONN_MGR_IF_READY_IPV6 BIT(15) /* NET_MGMT event masks */ #define CONN_MGR_IFACE_EVENTS_MASK (NET_EVENT_IF_DOWN | \ From 976e0a49e44ac161e9e7645185d7075c3d86d52e Mon Sep 17 00:00:00 2001 From: Georges Oates_Larsen Date: Tue, 21 May 2024 17:45:22 -0700 Subject: [PATCH 2093/2849] test: net: conn_mgr: Add IPv4/IPv6 notif test coverage Modify the test cycle routines to verify recently added IPv4- and IPv6-specific events. Signed-off-by: Georges Oates_Larsen --- tests/net/conn_mgr_monitor/src/main.c | 500 +++++++++++++++++++++----- 1 file changed, 401 insertions(+), 99 deletions(-) diff --git a/tests/net/conn_mgr_monitor/src/main.c b/tests/net/conn_mgr_monitor/src/main.c index 425533d8aa974..d500ab58b8919 100644 --- a/tests/net/conn_mgr_monitor/src/main.c +++ b/tests/net/conn_mgr_monitor/src/main.c @@ -26,8 +26,15 @@ /* Time to wait for NET_MGMT events to finish firing */ #define EVENT_WAIT_TIME K_MSEC(1) -/* Time to wait for IPv6 DAD to finish */ + +/* Time to wait for IPv6 DAD-gated events to finish. + * Equivalent to EVENT_WAIT_TIME if DAD is dissabled. + */ +#if defined(CONFIG_NET_IPV6_DAD) #define DAD_WAIT_TIME K_MSEC(110) +#else +#define DAD_WAIT_TIME EVENT_WAIT_TIME +#endif /* IP addresses -- Two of each are needed because address sharing will cause address removal to * fail silently (Address is only removed from one iface). @@ -37,6 +44,10 @@ static struct in_addr test_ipv4_b = { { { 10, 0, 0, 2 } } }; static struct in6_addr test_ipv6_a = { { { 0x20, 0x01, 0x0d, 0xb8, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x1 } } }; +static struct in6_addr test_ipv6_b = { { { + 0x20, 0x01, 0x0d, 0xb8, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x2 +} } }; + /* Helpers */ static void reset_test_iface(struct net_if *iface) @@ -50,6 +61,7 @@ static void reset_test_iface(struct net_if *iface) net_if_ipv4_addr_rm(iface, &test_ipv4_a); net_if_ipv4_addr_rm(iface, &test_ipv4_b); net_if_ipv6_addr_rm(iface, &test_ipv6_a); + net_if_ipv6_addr_rm(iface, &test_ipv6_b); /* DAD adds the link-local address automatically. Check for it, and remove it if present. */ ll_ipv6 = net_if_ipv6_get_ll(iface, NET_ADDR_ANY_STATE); @@ -63,31 +75,54 @@ static void reset_test_iface(struct net_if *iface) /* Thread-safe test statistics */ K_MUTEX_DEFINE(stats_mutex); static struct test_stats { - /** The number of times conn_mgr_monitor has raised a connect event */ - int conn_count; + /** IPv4 connectivity event counters */ + int event_count_ipv4; /* any */ + int conn_count_ipv4; /* connect */ + int dconn_count_ipv4; /* disconnect */ - /** The number of times conn_mgr_monitor has raised a disconnect event */ - int dconn_count; + /** IPv6 connectivity event counters */ + int event_count_ipv6; /* any */ + int conn_count_ipv6; /* connect */ + int dconn_count_ipv6; /* disconnect */ - /** The total number of connectivity events fired by conn_mgr_monitor */ - int event_count; + /** General connectivity event counters */ + int event_count_gen; /* any */ + int conn_count_gen; /* connect */ + int dconn_count_gen; /* disconnect */ /** The iface blamed for the last disconnect event */ - struct net_if *dconn_iface; + struct net_if *dconn_iface_gen; + struct net_if *dconn_iface_ipv4; + struct net_if *dconn_iface_ipv6; /** The iface blamed for the last connect event */ - struct net_if *conn_iface; + struct net_if *conn_iface_gen; + struct net_if *conn_iface_ipv4; + struct net_if *conn_iface_ipv6; + } global_stats; static void reset_stats(void) { k_mutex_lock(&stats_mutex, K_FOREVER); - global_stats.conn_count = 0; - global_stats.dconn_count = 0; - global_stats.event_count = 0; - global_stats.dconn_iface = NULL; - global_stats.conn_iface = NULL; + global_stats.conn_count_gen = 0; + global_stats.dconn_count_gen = 0; + global_stats.event_count_gen = 0; + global_stats.dconn_iface_gen = NULL; + global_stats.conn_iface_gen = NULL; + + global_stats.conn_count_ipv4 = 0; + global_stats.dconn_count_ipv4 = 0; + global_stats.event_count_ipv4 = 0; + global_stats.dconn_iface_ipv4 = NULL; + global_stats.conn_iface_ipv4 = NULL; + + global_stats.conn_count_ipv6 = 0; + global_stats.dconn_count_ipv6 = 0; + global_stats.event_count_ipv6 = 0; + global_stats.dconn_iface_ipv6 = NULL; + global_stats.conn_iface_ipv6 = NULL; k_mutex_unlock(&stats_mutex); } @@ -115,19 +150,55 @@ void l4_handler(struct net_mgmt_event_callback *cb, uint32_t event, struct net_i { if (event == NET_EVENT_L4_CONNECTED) { k_mutex_lock(&stats_mutex, K_FOREVER); - global_stats.conn_count += 1; - global_stats.event_count += 1; - global_stats.conn_iface = iface; + printk("NET_EVENT_L4_CONNECTED\n"); + global_stats.conn_count_gen += 1; + global_stats.event_count_gen += 1; + global_stats.conn_iface_gen = iface; k_mutex_unlock(&stats_mutex); } else if (event == NET_EVENT_L4_DISCONNECTED) { k_mutex_lock(&stats_mutex, K_FOREVER); - global_stats.dconn_count += 1; - global_stats.event_count += 1; - global_stats.dconn_iface = iface; + printk("NET_EVENT_L4_DISCONNECTED\n"); + global_stats.dconn_count_gen += 1; + global_stats.event_count_gen += 1; + global_stats.dconn_iface_gen = iface; k_mutex_unlock(&stats_mutex); } } +struct net_mgmt_event_callback conn_callback; + +void conn_handler(struct net_mgmt_event_callback *cb, uint32_t event, struct net_if *iface) +{ + if (event == NET_EVENT_L4_IPV6_CONNECTED) { + k_mutex_lock(&stats_mutex, K_FOREVER); + printk("NET_EVENT_L4_IPV6_CONNECTED\n"); + global_stats.conn_count_ipv6 += 1; + global_stats.event_count_ipv6 += 1; + global_stats.conn_iface_ipv6 = iface; + k_mutex_unlock(&stats_mutex); + } else if (event == NET_EVENT_L4_IPV6_DISCONNECTED) { + k_mutex_lock(&stats_mutex, K_FOREVER); + printk("NET_EVENT_L4_IPV6_DISCONNECTED\n"); + global_stats.dconn_count_ipv6 += 1; + global_stats.event_count_ipv6 += 1; + global_stats.dconn_iface_ipv6 = iface; + k_mutex_unlock(&stats_mutex); + } else if (event == NET_EVENT_L4_IPV4_CONNECTED) { + k_mutex_lock(&stats_mutex, K_FOREVER); + printk("NET_EVENT_L4_IPV4_CONNECTED\n"); + global_stats.conn_count_ipv4 += 1; + global_stats.event_count_ipv4 += 1; + global_stats.conn_iface_ipv4 = iface; + k_mutex_unlock(&stats_mutex); + } else if (event == NET_EVENT_L4_IPV4_DISCONNECTED) { + k_mutex_lock(&stats_mutex, K_FOREVER); + printk("NET_EVENT_L4_IPV4_DISCONNECTED\n"); + global_stats.dconn_count_ipv4 += 1; + global_stats.event_count_ipv4 += 1; + global_stats.dconn_iface_ipv4 = iface; + k_mutex_unlock(&stats_mutex); + } +} /* Test suite shared functions & routines */ @@ -137,6 +208,13 @@ static void *conn_mgr_setup(void) &l4_callback, l4_handler, NET_EVENT_L4_CONNECTED | NET_EVENT_L4_DISCONNECTED ); net_mgmt_add_event_callback(&l4_callback); + + net_mgmt_init_event_callback( + &conn_callback, conn_handler, + NET_EVENT_L4_IPV6_CONNECTED | NET_EVENT_L4_IPV6_DISCONNECTED | + NET_EVENT_L4_IPV4_CONNECTED | NET_EVENT_L4_IPV4_DISCONNECTED + ); + net_mgmt_add_event_callback(&conn_callback); return NULL; } @@ -178,7 +256,7 @@ static void cycle_ready_ifaces(struct net_if *ifa, struct net_if *ifb) /* Expect no events */ k_sleep(EVENT_WAIT_TIME); stats = get_reset_stats(); - zassert_equal(stats.event_count, 0, + zassert_equal(stats.event_count_gen, 0, "No events should be fired if connectivity availability did not change."); /* Take A up */ @@ -187,11 +265,11 @@ static void cycle_ready_ifaces(struct net_if *ifa, struct net_if *ifb) /* Expect connectivity gained */ k_sleep(EVENT_WAIT_TIME); stats = get_reset_stats(); - zassert_equal(stats.conn_count, 1, + zassert_equal(stats.conn_count_gen, 1, "NET_EVENT_L4_CONNECTED should be fired when connectivity is gained."); - zassert_equal(stats.event_count, 1, + zassert_equal(stats.event_count_gen, 1, "Only NET_EVENT_L4_CONNECTED should be fired when connectivity is gained."); - zassert_equal(stats.conn_iface, ifa, "ifa should be blamed."); + zassert_equal(stats.conn_iface_gen, ifa, "ifa should be blamed."); /* Take B up */ zassert_equal(net_if_up(ifb), 0, "net_if_up should succeed for ifb."); @@ -199,7 +277,7 @@ static void cycle_ready_ifaces(struct net_if *ifa, struct net_if *ifb) /* Expect no events */ k_sleep(EVENT_WAIT_TIME); stats = get_reset_stats(); - zassert_equal(stats.event_count, 0, + zassert_equal(stats.event_count_gen, 0, "No events should be fired if connectivity availability did not change."); /* Take A down */ @@ -208,7 +286,7 @@ static void cycle_ready_ifaces(struct net_if *ifa, struct net_if *ifb) /* Expect no events */ k_sleep(EVENT_WAIT_TIME); stats = get_reset_stats(); - zassert_equal(stats.event_count, 0, + zassert_equal(stats.event_count_gen, 0, "No events should be fired if connectivity availability did not change."); /* Take B down */ @@ -217,11 +295,11 @@ static void cycle_ready_ifaces(struct net_if *ifa, struct net_if *ifb) /* Expect connectivity loss */ k_sleep(EVENT_WAIT_TIME); stats = get_reset_stats(); - zassert_equal(stats.dconn_count, 1, + zassert_equal(stats.dconn_count_gen, 1, "NET_EVENT_L4_DISCONNECTED should be fired when connectivity is lost."); - zassert_equal(stats.event_count, 1, + zassert_equal(stats.event_count_gen, 1, "Only NET_EVENT_L4_DISCONNECTED should be fired when connectivity is lost."); - zassert_equal(stats.dconn_iface, ifb, "ifb should be blamed."); + zassert_equal(stats.dconn_iface_gen, ifb, "ifb should be blamed."); } /** @@ -229,29 +307,42 @@ static void cycle_ready_ifaces(struct net_if *ifa, struct net_if *ifb) * * At several points, change the readiness state of ifa and ensure events are fired. * + * Steps which bring ifa or ifb online wait for the DAD delay to allow IPv6 events to finish. + * For test builds that have DAD disabled, this is equivalent to the usual event wait time. + * * @param ifa * @param ifb */ static void cycle_ignored_iface(struct net_if *ifa, struct net_if *ifb) { struct test_stats stats; + printk("cycle_ignored_iface\n"); /* Ignore B */ conn_mgr_ignore_iface(ifb); - /* Add IPv4 addresses */ + /* Add IPv4 and IPv6 addresses so that all possible event types are fired. */ net_if_ipv4_addr_add(ifa, &test_ipv4_a, NET_ADDR_MANUAL, 0); net_if_ipv4_addr_add(ifb, &test_ipv4_b, NET_ADDR_MANUAL, 0); + net_if_ipv6_addr_add(ifa, &test_ipv6_a, NET_ADDR_MANUAL, 0); + net_if_ipv6_addr_add(ifb, &test_ipv6_b, NET_ADDR_MANUAL, 0); /* Set one: Change A state between B state toggles */ /* Take B up */ zassert_equal(net_if_up(ifb), 0, "net_if_up should succeed for ifb."); - /* Expect no events */ - k_sleep(EVENT_WAIT_TIME); + /* Expect no events. + * Wait for the DAD delay since IPv6 connected events might be delayed by this amount. + */ + printk("Expect no events.\n"); + k_sleep(DAD_WAIT_TIME); stats = get_reset_stats(); - zassert_equal(stats.event_count, 0, + zassert_equal(stats.event_count_gen, 0, + "No events should be fired if connectivity availability did not change."); + zassert_equal(stats.event_count_ipv4, 0, + "No events should be fired if connectivity availability did not change."); + zassert_equal(stats.event_count_ipv6, 0, "No events should be fired if connectivity availability did not change."); /* Take B down */ @@ -260,28 +351,46 @@ static void cycle_ignored_iface(struct net_if *ifa, struct net_if *ifb) /* Expect no events */ k_sleep(EVENT_WAIT_TIME); stats = get_reset_stats(); - zassert_equal(stats.event_count, 0, + zassert_equal(stats.event_count_gen, 0, + "No events should be fired if connectivity availability did not change."); + zassert_equal(stats.event_count_ipv4, 0, + "No events should be fired if connectivity availability did not change."); + zassert_equal(stats.event_count_ipv6, 0, "No events should be fired if connectivity availability did not change."); /* Take A up */ zassert_equal(net_if_up(ifa), 0, "net_if_up should succeed for ifa."); /* Expect connectivity gained */ - k_sleep(EVENT_WAIT_TIME); + k_sleep(DAD_WAIT_TIME); stats = get_reset_stats(); - zassert_equal(stats.conn_count, 1, + zassert_equal(stats.conn_count_gen, 1, "NET_EVENT_L4_CONNECTED should be fired when connectivity is gained."); - zassert_equal(stats.event_count, 1, + zassert_equal(stats.event_count_gen, 1, "Only NET_EVENT_L4_CONNECTED should be fired when connectivity is gained."); - zassert_equal(stats.conn_iface, ifa, "ifa should be blamed."); + zassert_equal(stats.conn_count_ipv6, 1, + "NET_EVENT_L4_IPV6_CONNECTED should be fired when connectivity is gained."); + zassert_equal(stats.event_count_ipv6, 1, + "Only NET_EVENT_L4_IPV6_CONNECTED should be fired when connectivity is gained."); + zassert_equal(stats.conn_count_ipv4, 1, + "NET_EVENT_L4_IPV4_CONNECTED should be fired when connectivity is gained."); + zassert_equal(stats.event_count_ipv4, 1, + "Only NET_EVENT_L4_IPV4_CONNECTED should be fired when connectivity is gained."); + zassert_equal(stats.conn_iface_gen, ifa, "ifa should be blamed."); + zassert_equal(stats.conn_iface_ipv4, ifa, "ifa should be blamed."); + zassert_equal(stats.conn_iface_ipv6, ifa, "ifa should be blamed."); /* Take B up */ zassert_equal(net_if_up(ifb), 0, "net_if_up should succeed for ifb."); /* Expect no events */ - k_sleep(EVENT_WAIT_TIME); + k_sleep(DAD_WAIT_TIME); stats = get_reset_stats(); - zassert_equal(stats.event_count, 0, + zassert_equal(stats.event_count_gen, 0, + "No events should be fired if connectivity availability did not change."); + zassert_equal(stats.event_count_ipv4, 0, + "No events should be fired if connectivity availability did not change."); + zassert_equal(stats.event_count_ipv6, 0, "No events should be fired if connectivity availability did not change."); /* Take B down */ @@ -290,7 +399,11 @@ static void cycle_ignored_iface(struct net_if *ifa, struct net_if *ifb) /* Expect no events */ k_sleep(EVENT_WAIT_TIME); stats = get_reset_stats(); - zassert_equal(stats.event_count, 0, + zassert_equal(stats.event_count_gen, 0, + "No events should be fired if connectivity availability did not change."); + zassert_equal(stats.event_count_ipv4, 0, + "No events should be fired if connectivity availability did not change."); + zassert_equal(stats.event_count_ipv6, 0, "No events should be fired if connectivity availability did not change."); /* Take A down */ @@ -299,11 +412,21 @@ static void cycle_ignored_iface(struct net_if *ifa, struct net_if *ifb) /* Expect connectivity lost */ k_sleep(EVENT_WAIT_TIME); stats = get_reset_stats(); - zassert_equal(stats.dconn_count, 1, + zassert_equal(stats.dconn_count_gen, 1, "NET_EVENT_L4_DISCONNECTED should be fired when connectivity is lost."); - zassert_equal(stats.event_count, 1, + zassert_equal(stats.event_count_gen, 1, "Only NET_EVENT_L4_DISCONNECTED should be fired when connectivity is lost."); - zassert_equal(stats.dconn_iface, ifa, "ifa should be blamed."); + zassert_equal(stats.dconn_count_ipv6, 1, + "NET_EVENT_L4_IPV6_DISCONNECTED should be fired when connectivity is lost."); + zassert_equal(stats.event_count_ipv6, 1, + "Only NET_EVENT_L4_IPV6_DISCONNECTED should be fired when connectivity is lost."); + zassert_equal(stats.dconn_count_ipv4, 1, + "NET_EVENT_L4_IPV4_DISCONNECTED should be fired when connectivity is lost."); + zassert_equal(stats.event_count_ipv4, 1, + "Only NET_EVENT_L4_IPV4_DISCONNECTED should be fired when connectivity is lost."); + zassert_equal(stats.dconn_iface_gen, ifa, "ifa should be blamed."); + zassert_equal(stats.dconn_iface_ipv4, ifa, "ifa should be blamed."); + zassert_equal(stats.dconn_iface_ipv6, ifa, "ifa should be blamed."); /* Set two: Change A state during B state toggles */ @@ -312,22 +435,36 @@ static void cycle_ignored_iface(struct net_if *ifa, struct net_if *ifb) zassert_equal(net_if_up(ifb), 0, "net_if_up should succeed for ifb."); /* Expect no events */ - k_sleep(EVENT_WAIT_TIME); + k_sleep(DAD_WAIT_TIME); stats = get_reset_stats(); - zassert_equal(stats.event_count, 0, + zassert_equal(stats.event_count_gen, 0, + "No events should be fired if connectivity availability did not change."); + zassert_equal(stats.event_count_ipv4, 0, + "No events should be fired if connectivity availability did not change."); + zassert_equal(stats.event_count_ipv6, 0, "No events should be fired if connectivity availability did not change."); /* Take A up */ zassert_equal(net_if_up(ifa), 0, "net_if_up should succeed for ifa."); /* Expect connectivity gained */ - k_sleep(EVENT_WAIT_TIME); + k_sleep(DAD_WAIT_TIME); stats = get_reset_stats(); - zassert_equal(stats.conn_count, 1, + zassert_equal(stats.conn_count_gen, 1, "NET_EVENT_L4_CONNECTED should be fired when connectivity is gained."); - zassert_equal(stats.event_count, 1, + zassert_equal(stats.event_count_gen, 1, "Only NET_EVENT_L4_CONNECTED should be fired when connectivity is gained."); - zassert_equal(stats.conn_iface, ifa, "ifa should be blamed."); + zassert_equal(stats.conn_count_ipv6, 1, + "NET_EVENT_L4_IPV6_CONNECTED should be fired when connectivity is gained."); + zassert_equal(stats.event_count_ipv6, 1, + "Only NET_EVENT_L4_IPV6_CONNECTED should be fired when connectivity is gained."); + zassert_equal(stats.conn_count_ipv4, 1, + "NET_EVENT_L4_IPV4_CONNECTED should be fired when connectivity is gained."); + zassert_equal(stats.event_count_ipv4, 1, + "Only NET_EVENT_L4_IPV4_CONNECTED should be fired when connectivity is gained."); + zassert_equal(stats.conn_iface_gen, ifa, "ifa should be blamed."); + zassert_equal(stats.conn_iface_ipv4, ifa, "ifa should be blamed."); + zassert_equal(stats.conn_iface_ipv6, ifa, "ifa should be blamed."); /* Take B down */ zassert_equal(net_if_down(ifb), 0, "net_if_down should succeed for ifb."); @@ -335,7 +472,11 @@ static void cycle_ignored_iface(struct net_if *ifa, struct net_if *ifb) /* Expect no events */ k_sleep(EVENT_WAIT_TIME); stats = get_reset_stats(); - zassert_equal(stats.event_count, 0, + zassert_equal(stats.event_count_gen, 0, + "No events should be fired if connectivity availability did not change."); + zassert_equal(stats.event_count_ipv4, 0, + "No events should be fired if connectivity availability did not change."); + zassert_equal(stats.event_count_ipv6, 0, "No events should be fired if connectivity availability did not change."); @@ -343,9 +484,13 @@ static void cycle_ignored_iface(struct net_if *ifa, struct net_if *ifb) zassert_equal(net_if_up(ifb), 0, "net_if_up should succeed for ifb."); /* Expect no events */ - k_sleep(EVENT_WAIT_TIME); + k_sleep(DAD_WAIT_TIME); stats = get_reset_stats(); - zassert_equal(stats.event_count, 0, + zassert_equal(stats.event_count_gen, 0, + "No events should be fired if connectivity availability did not change."); + zassert_equal(stats.event_count_ipv4, 0, + "No events should be fired if connectivity availability did not change."); + zassert_equal(stats.event_count_ipv6, 0, "No events should be fired if connectivity availability did not change."); /* Take A down */ @@ -354,11 +499,21 @@ static void cycle_ignored_iface(struct net_if *ifa, struct net_if *ifb) /* Expect connectivity lost */ k_sleep(EVENT_WAIT_TIME); stats = get_reset_stats(); - zassert_equal(stats.dconn_count, 1, + zassert_equal(stats.dconn_count_gen, 1, "NET_EVENT_L4_DISCONNECTED should be fired when connectivity is lost."); - zassert_equal(stats.event_count, 1, + zassert_equal(stats.event_count_gen, 1, "Only NET_EVENT_L4_DISCONNECTED should be fired when connectivity is lost."); - zassert_equal(stats.dconn_iface, ifa, "ifa should be blamed."); + zassert_equal(stats.dconn_count_ipv6, 1, + "NET_EVENT_L4_IPV6_DISCONNECTED should be fired when connectivity is lost."); + zassert_equal(stats.event_count_ipv6, 1, + "Only NET_EVENT_L4_IPV6_DISCONNECTED should be fired when connectivity is lost."); + zassert_equal(stats.dconn_count_ipv4, 1, + "NET_EVENT_L4_IPV4_DISCONNECTED should be fired when connectivity is lost."); + zassert_equal(stats.event_count_ipv4, 1, + "Only NET_EVENT_L4_IPV4_DISCONNECTED should be fired when connectivity is lost."); + zassert_equal(stats.dconn_iface_gen, ifa, "ifa should be blamed."); + zassert_equal(stats.dconn_iface_ipv4, ifa, "ifa should be blamed."); + zassert_equal(stats.dconn_iface_ipv6, ifa, "ifa should be blamed."); /* Take B down */ zassert_equal(net_if_down(ifb), 0, "net_if_down should succeed for ifb."); @@ -366,7 +521,11 @@ static void cycle_ignored_iface(struct net_if *ifa, struct net_if *ifb) /* Expect no events */ k_sleep(EVENT_WAIT_TIME); stats = get_reset_stats(); - zassert_equal(stats.event_count, 0, + zassert_equal(stats.event_count_gen, 0, + "No events should be fired if connectivity availability did not change."); + zassert_equal(stats.event_count_ipv4, 0, + "No events should be fired if connectivity availability did not change."); + zassert_equal(stats.event_count_ipv6, 0, "No events should be fired if connectivity availability did not change."); } @@ -417,7 +576,7 @@ static void cycle_iface_states(struct net_if *iface, enum ip_order ifa_ipm) /* Verify that no events have been fired yet */ k_sleep(EVENT_WAIT_TIME); stats = get_reset_stats(); - zassert_equal(stats.event_count, 0, + zassert_equal(stats.event_count_gen, 0, "No events should be fired if connectivity availability did not change."); /* (10 -> 11): Gain IP from semi-ready state */ @@ -429,22 +588,40 @@ static void cycle_iface_states(struct net_if *iface, enum ip_order ifa_ipm) /* Verify correct events */ k_sleep(EVENT_WAIT_TIME); stats = get_reset_stats(); - zassert_equal(stats.conn_count, 1, + zassert_equal(stats.conn_count_gen, 1, "NET_EVENT_L4_CONNECTED should be fired when connectivity is gained."); - zassert_equal(stats.event_count, 1, + zassert_equal(stats.event_count_gen, 1, "Only NET_EVENT_L4_CONNECTED should be fired when connectivity is gained."); - zassert_equal(stats.conn_iface, iface, "The test iface should be blamed."); + zassert_equal(stats.conn_count_ipv4, 1, + "NET_EVENT_L4_IPV4_CONNECTED should be fired when IPv4 " + "connectivity is gained."); + zassert_equal(stats.event_count_ipv4, 1, + "Only NET_EVENT_L4_IPV4_CONNECTED should be fired when IPv4 " + "connectivity is gained."); + zassert_equal(stats.event_count_ipv6, 0, + "No IPv6 events should be fired when IPv4 connectivity is gained."); + zassert_equal(stats.conn_iface_gen, iface, "The test iface should be blamed."); + zassert_equal(stats.conn_iface_ipv4, iface, "The test iface should be blamed."); /* Add IPv6 */ net_if_ipv6_addr_add(iface, &test_ipv6_a, NET_ADDR_MANUAL, 0); k_sleep(DAD_WAIT_TIME); - /* Verify no events */ + /* Verify only IPv6 events */ k_sleep(EVENT_WAIT_TIME); stats = get_reset_stats(); - zassert_equal(stats.event_count, 0, + zassert_equal(stats.event_count_gen, 0, "No events should be fired if connectivity availability did not change."); + zassert_equal(stats.conn_count_ipv6, 1, + "NET_EVENT_L4_IPV6_CONNECTED should be fired when IPv6 " + "connectivity is gained."); + zassert_equal(stats.event_count_ipv6, 1, + "Only NET_EVENT_L4_IPV6_CONNECTED should be fired when IPv6 " + "connectivity is gained."); + zassert_equal(stats.event_count_ipv4, 0, + "No IPv4 events should be fired when IPv6 connectivity is gained."); + zassert_equal(stats.conn_iface_ipv6, iface, "The test iface should be blamed."); break; case IPV6_FIRST: @@ -455,20 +632,38 @@ static void cycle_iface_states(struct net_if *iface, enum ip_order ifa_ipm) /* Verify correct events */ k_sleep(EVENT_WAIT_TIME); stats = get_reset_stats(); - zassert_equal(stats.conn_count, 1, + zassert_equal(stats.conn_count_gen, 1, "NET_EVENT_L4_CONNECTED should be fired when connectivity is gained."); - zassert_equal(stats.event_count, 1, + zassert_equal(stats.event_count_gen, 1, "Only NET_EVENT_L4_CONNECTED should be fired when connectivity is gained."); - zassert_equal(stats.conn_iface, iface, "The test iface should be blamed."); + zassert_equal(stats.conn_count_ipv6, 1, + "NET_EVENT_L4_IPV6_CONNECTED should be fired when IPv6 " + "connectivity is gained."); + zassert_equal(stats.event_count_ipv6, 1, + "Only NET_EVENT_L4_IPV6_CONNECTED should be fired when IPv6 " + "connectivity is gained."); + zassert_equal(stats.event_count_ipv4, 0, + "No IPv4 events should be fired when IPv6 connectivity is gained."); + zassert_equal(stats.conn_iface_gen, iface, "The test iface should be blamed."); + zassert_equal(stats.conn_iface_ipv6, iface, "The test iface should be blamed."); /* Add IPv4 */ net_if_ipv4_addr_add(iface, &test_ipv4_a, NET_ADDR_MANUAL, 0); - /* Verify no events */ + /* Verify only IPv4 events */ k_sleep(EVENT_WAIT_TIME); stats = get_reset_stats(); - zassert_equal(stats.event_count, 0, + zassert_equal(stats.event_count_gen, 0, "No events should be fired if connectivity availability did not change."); + zassert_equal(stats.conn_count_ipv4, 1, + "NET_EVENT_L4_IPV4_CONNECTED should be fired when IPv4 " + "connectivity is gained."); + zassert_equal(stats.event_count_ipv4, 1, + "Only NET_EVENT_L4_IPV4_CONNECTED should be fired when IPv4 " + "connectivity is gained."); + zassert_equal(stats.event_count_ipv6, 0, + "No IPv6 events should be fired when IPv4 connectivity is gained."); + zassert_equal(stats.conn_iface_ipv4, iface, "The test iface should be blamed."); break; } @@ -479,11 +674,20 @@ static void cycle_iface_states(struct net_if *iface, enum ip_order ifa_ipm) zassert_true(net_if_ipv4_addr_rm(iface, &test_ipv4_a), "IPv4 removal should succeed."); - /* Verify no events (because IPv6 addr is still active) */ + /* Verify only IPv4 events */ k_sleep(EVENT_WAIT_TIME); stats = get_reset_stats(); - zassert_equal(stats.event_count, 0, + zassert_equal(stats.event_count_gen, 0, "No events should be fired if connectivity availability did not change."); + zassert_equal(stats.dconn_count_ipv4, 1, + "NET_EVENT_L4_IPV4_DISCONNECTED should be fired when IPv4 " + "connectivity is lost."); + zassert_equal(stats.event_count_ipv4, 1, + "Only NET_EVENT_L4_IPV4_DISCONNECTED should be fired when IPv4 " + "connectivity is lost."); + zassert_equal(stats.event_count_ipv6, 0, + "No IPv6 events should be fired when IPv4 connectivity is gained."); + zassert_equal(stats.dconn_iface_ipv4, iface, "The test iface should be blamed."); /* Remove IPv6 */ zassert_true(net_if_ipv6_addr_rm(iface, &test_ipv6_a), @@ -492,12 +696,22 @@ static void cycle_iface_states(struct net_if *iface, enum ip_order ifa_ipm) /* Verify correct events */ k_sleep(EVENT_WAIT_TIME); stats = get_reset_stats(); - zassert_equal(stats.dconn_count, 1, + zassert_equal(stats.dconn_count_gen, 1, "NET_EVENT_L4_DISCONNECTED should be fired when connectivity is lost."); - zassert_equal(stats.event_count, 1, + zassert_equal(stats.event_count_gen, 1, "Only NET_EVENT_L4_DISCONNECTED should be fired when connectivity " "is lost."); - zassert_equal(stats.dconn_iface, iface, "The test iface should be blamed."); + zassert_equal(stats.dconn_count_ipv6, 1, + "NET_EVENT_L4_IPV6_DISCONNECTED should be fired when IPv6 " + "connectivity is lost."); + zassert_equal(stats.event_count_ipv6, 1, + "Only NET_EVENT_L4_IPV6_DISCONNECTED should be fired when IPv6 " + "connectivity is lost."); + zassert_equal(stats.event_count_ipv4, 0, + "No IPv4 events should be fired when IPv6 connectivity is gained."); + + zassert_equal(stats.dconn_iface_gen, iface, "The test iface should be blamed."); + zassert_equal(stats.dconn_iface_ipv6, iface, "The test iface should be blamed."); break; case IPV6_FIRST: @@ -505,11 +719,20 @@ static void cycle_iface_states(struct net_if *iface, enum ip_order ifa_ipm) zassert_true(net_if_ipv6_addr_rm(iface, &test_ipv6_a), "IPv6 removal should succeed."); - /* Verify no events (because IPv4 addr is still active) */ + /* Verify only IPv6 events */ k_sleep(EVENT_WAIT_TIME); stats = get_reset_stats(); - zassert_equal(stats.event_count, 0, + zassert_equal(stats.event_count_gen, 0, "No events should be fired if connectivity availability did not change."); + zassert_equal(stats.dconn_count_ipv6, 1, + "NET_EVENT_L4_IPV6_DISCONNECTED should be fired when IPv6 " + "connectivity is lost."); + zassert_equal(stats.event_count_ipv6, 1, + "Only NET_EVENT_L4_IPV6_DISCONNECTED should be fired when IPv6 " + "connectivity is lost."); + zassert_equal(stats.event_count_ipv4, 0, + "No IPv4 events should be fired when IPv6 connectivity is gained."); + zassert_equal(stats.dconn_iface_ipv6, iface, "The test iface should be blamed."); /* Remove IPv4 */ zassert_true(net_if_ipv4_addr_rm(iface, &test_ipv4_a), @@ -518,12 +741,21 @@ static void cycle_iface_states(struct net_if *iface, enum ip_order ifa_ipm) /* Verify correct events */ k_sleep(EVENT_WAIT_TIME); stats = get_reset_stats(); - zassert_equal(stats.dconn_count, 1, + zassert_equal(stats.dconn_count_gen, 1, "NET_EVENT_L4_DISCONNECTED should be fired when connectivity is lost."); - zassert_equal(stats.event_count, 1, + zassert_equal(stats.event_count_gen, 1, "Only NET_EVENT_L4_DISCONNECTED should be fired when connectivity " "is lost."); - zassert_equal(stats.dconn_iface, iface, "The test iface should be blamed."); + zassert_equal(stats.dconn_count_ipv4, 1, + "NET_EVENT_L4_IPV4_DISCONNECTED should be fired when IPv4 " + "connectivity is lost."); + zassert_equal(stats.event_count_ipv4, 1, + "Only NET_EVENT_L4_IPV4_DISCONNECTED should be fired when IPv4 " + "connectivity is lost."); + zassert_equal(stats.event_count_ipv6, 0, + "No IPv6 events should be fired when IPv4 connectivity is gained."); + zassert_equal(stats.dconn_iface_gen, iface, "The test iface should be blamed."); + zassert_equal(stats.dconn_iface_ipv4, iface, "The test iface should be blamed."); break; } @@ -536,7 +768,11 @@ static void cycle_iface_states(struct net_if *iface, enum ip_order ifa_ipm) /* Verify there are no events fired */ k_sleep(EVENT_WAIT_TIME); stats = get_reset_stats(); - zassert_equal(stats.event_count, 0, + zassert_equal(stats.event_count_gen, 0, + "No events should be fired if connectivity availability did not change."); + zassert_equal(stats.event_count_ipv4, 0, + "No events should be fired if connectivity availability did not change."); + zassert_equal(stats.event_count_ipv6, 0, "No events should be fired if connectivity availability did not change."); /* (00 -> 01): Gain IP from unready state */ @@ -560,7 +796,11 @@ static void cycle_iface_states(struct net_if *iface, enum ip_order ifa_ipm) /* Verify that no events are fired */ k_sleep(EVENT_WAIT_TIME); stats = get_reset_stats(); - zassert_equal(stats.event_count, 0, + zassert_equal(stats.event_count_gen, 0, + "No events should be fired if connectivity availability did not change."); + zassert_equal(stats.event_count_ipv4, 0, + "No events should be fired if connectivity availability did not change."); + zassert_equal(stats.event_count_ipv6, 0, "No events should be fired if connectivity availability did not change."); /* (01 -> 11): Gain Oper-up from semi-ready state */ @@ -569,13 +809,27 @@ static void cycle_iface_states(struct net_if *iface, enum ip_order ifa_ipm) zassert_equal(net_if_up(iface), 0, "net_if_up should succeed."); /* Verify events are fired */ - k_sleep(EVENT_WAIT_TIME); + k_sleep(DAD_WAIT_TIME); stats = get_reset_stats(); - zassert_equal(stats.conn_count, 1, + zassert_equal(stats.conn_count_gen, 1, "NET_EVENT_L4_CONNECTED should be fired when connectivity is gained."); - zassert_equal(stats.event_count, 1, + zassert_equal(stats.event_count_gen, 1, "Only NET_EVENT_L4_CONNECTED should be fired when connectivity is gained."); - zassert_equal(stats.conn_iface, iface, "The test iface should be blamed."); + zassert_equal(stats.conn_count_ipv4, 1, + "NET_EVENT_L4_IPV4_CONNECTED should be fired when IPv4 " + "connectivity is gained."); + zassert_equal(stats.event_count_ipv4, 1, + "Only NET_EVENT_L4_IPV4_CONNECTED should be fired when IPv4 " + "connectivity is gained."); + zassert_equal(stats.conn_count_ipv6, 1, + "NET_EVENT_L4_IPV6_CONNECTED should be fired when IPv6 " + "connectivity is gained."); + zassert_equal(stats.event_count_ipv6, 1, + "Only NET_EVENT_L4_IPV6_CONNECTED should be fired when IPv6 " + "connectivity is gained."); + zassert_equal(stats.conn_iface_gen, iface, "The test iface should be blamed."); + zassert_equal(stats.conn_iface_ipv4, iface, "The test iface should be blamed."); + zassert_equal(stats.conn_iface_ipv6, iface, "The test iface should be blamed."); /* (11 -> 01): Lose oper-up from ready state */ @@ -585,11 +839,25 @@ static void cycle_iface_states(struct net_if *iface, enum ip_order ifa_ipm) /* Verify events are fired */ k_sleep(EVENT_WAIT_TIME); stats = get_reset_stats(); - zassert_equal(stats.dconn_count, 1, + zassert_equal(stats.dconn_count_gen, 1, "NET_EVENT_L4_DISCONNECTED should be fired when connectivity is lost."); - zassert_equal(stats.event_count, 1, + zassert_equal(stats.event_count_gen, 1, "Only NET_EVENT_L4_DISCONNECTED should be fired when connectivity is lost."); - zassert_equal(stats.dconn_iface, iface, "The test iface should be blamed."); + zassert_equal(stats.dconn_count_ipv4, 1, + "NET_EVENT_L4_IPV4_DISCONNECTED should be fired when IPv4 " + "connectivity is lost."); + zassert_equal(stats.event_count_ipv4, 1, + "Only NET_EVENT_L4_IPV4_DISCONNECTED should be fired when IPv4 " + "connectivity is lost."); + zassert_equal(stats.dconn_count_ipv6, 1, + "NET_EVENT_L4_IPV6_DISCONNECTED should be fired when IPv6 " + "connectivity is lost."); + zassert_equal(stats.event_count_ipv6, 1, + "Only NET_EVENT_L4_IPV6_DISCONNECTED should be fired when IPv6 " + "connectivity is lost."); + zassert_equal(stats.dconn_iface_gen, iface, "The test iface should be blamed."); + zassert_equal(stats.dconn_iface_ipv4, iface, "The test iface should be blamed."); + zassert_equal(stats.dconn_iface_ipv6, iface, "The test iface should be blamed."); /* (01 -> 00): Lose IP from semi-ready state */ @@ -614,7 +882,11 @@ static void cycle_iface_states(struct net_if *iface, enum ip_order ifa_ipm) /* Verify no events fired */ k_sleep(EVENT_WAIT_TIME); stats = get_reset_stats(); - zassert_equal(stats.event_count, 0, + zassert_equal(stats.event_count_gen, 0, + "No events should be fired if connectivity availability did not change."); + zassert_equal(stats.event_count_ipv4, 0, + "No events should be fired if connectivity availability did not change."); + zassert_equal(stats.event_count_ipv6, 0, "No events should be fired if connectivity availability did not change."); } @@ -700,13 +972,13 @@ ZTEST(conn_mgr_monitor, test_DAD) /* After a delay too short for DAD, ensure no events */ k_sleep(EVENT_WAIT_TIME); stats = get_reset_stats(); - zassert_equal(stats.event_count, 0, + zassert_equal(stats.event_count_gen, 0, "No events should be fired before DAD success."); /* After a delay long enough for DAD, ensure connectivity acquired */ k_sleep(DAD_WAIT_TIME); stats = get_reset_stats(); - zassert_equal(stats.conn_count, 1, + zassert_equal(stats.conn_count_gen, 1, "NET_EVENT_L4_CONNECTED should be fired after DAD success."); } @@ -720,12 +992,17 @@ ZTEST(conn_mgr_monitor, test_ignore_while_ready) /* Add IP and take iface up */ net_if_ipv4_addr_add(if_simp_a, &test_ipv4_a, NET_ADDR_MANUAL, 0); + net_if_ipv6_addr_add(if_simp_a, &test_ipv6_a, NET_ADDR_MANUAL, 0); zassert_equal(net_if_up(if_simp_a), 0, "net_if_up should succeed for if_simp_a."); /* Ensure no events */ - k_sleep(EVENT_WAIT_TIME); + k_sleep(DAD_WAIT_TIME); stats = get_reset_stats(); - zassert_equal(stats.event_count, 0, + zassert_equal(stats.event_count_gen, 0, + "No events should be fired if connecting iface is ignored."); + zassert_equal(stats.event_count_ipv4, 0, + "No events should be fired if connecting iface is ignored."); + zassert_equal(stats.event_count_ipv6, 0, "No events should be fired if connecting iface is ignored."); /* Watch iface */ @@ -734,11 +1011,22 @@ ZTEST(conn_mgr_monitor, test_ignore_while_ready) /* Ensure connectivity gained */ k_sleep(EVENT_WAIT_TIME); stats = get_reset_stats(); - zassert_equal(stats.conn_count, 1, + zassert_equal(stats.conn_count_gen, 1, "NET_EVENT_L4_CONNECTED should be fired when online iface is watched."); - zassert_equal(stats.event_count, 1, + zassert_equal(stats.event_count_gen, 1, "Only NET_EVENT_L4_CONNECTED should be fired."); - zassert_equal(stats.conn_iface, if_simp_a, "if_simp_a should be blamed."); + zassert_equal(stats.conn_count_ipv4, 1, + "NET_EVENT_L4_IPV4_CONNECTED should be fired when online iface is watched."); + zassert_equal(stats.event_count_ipv4, 1, + "Only NET_EVENT_L4_IPV4_CONNECTED should be fired."); + zassert_equal(stats.conn_count_ipv6, 1, + "NET_EVENT_L4_IPV6_CONNECTED should be fired when online iface is watched."); + zassert_equal(stats.event_count_ipv6, 1, + "Only NET_EVENT_L4_IPV6_CONNECTED should be fired."); + zassert_equal(stats.conn_iface_gen, if_simp_a, "if_simp_a should be blamed"); + zassert_equal(stats.conn_iface_ipv4, if_simp_a, "if_simp_a should be blamed"); + zassert_equal(stats.conn_iface_ipv6, if_simp_a, "if_simp_a should be blamed"); + /* Ignore iface */ conn_mgr_ignore_iface(if_simp_a); @@ -746,11 +1034,21 @@ ZTEST(conn_mgr_monitor, test_ignore_while_ready) /* Ensure connectivity lost */ k_sleep(EVENT_WAIT_TIME); stats = get_reset_stats(); - zassert_equal(stats.dconn_count, 1, + zassert_equal(stats.dconn_count_gen, 1, "NET_EVENT_L4_DISCONNECTED should be fired when online iface is ignored."); - zassert_equal(stats.event_count, 1, + zassert_equal(stats.event_count_gen, 1, "Only NET_EVENT_L4_DISCONNECTED should be fired."); - zassert_equal(stats.dconn_iface, if_simp_a, "if_simp_a should be blamed"); + zassert_equal(stats.dconn_count_ipv4, 1, + "NET_EVENT_L4_IPV4_DISCONNECTED should be fired when online iface is ignored."); + zassert_equal(stats.event_count_ipv4, 1, + "Only NET_EVENT_L4_IPV4_DISCONNECTED should be fired."); + zassert_equal(stats.dconn_count_ipv6, 1, + "NET_EVENT_L4_IPV6_DISCONNECTED should be fired when online iface is ignored."); + zassert_equal(stats.event_count_ipv6, 1, + "Only NET_EVENT_L4_IPV6_DISCONNECTED should be fired."); + zassert_equal(stats.dconn_iface_gen, if_simp_a, "if_simp_a should be blamed"); + zassert_equal(stats.dconn_iface_ipv4, if_simp_a, "if_simp_a should be blamed"); + zassert_equal(stats.dconn_iface_ipv6, if_simp_a, "if_simp_a should be blamed"); /* Take iface down*/ zassert_equal(net_if_down(if_simp_a), 0, "net_if_down should succeed for if_simp_a."); @@ -758,7 +1056,11 @@ ZTEST(conn_mgr_monitor, test_ignore_while_ready) /* Ensure no events */ k_sleep(EVENT_WAIT_TIME); stats = get_reset_stats(); - zassert_equal(stats.event_count, 0, + zassert_equal(stats.event_count_gen, 0, + "No events should be fired if disconnecting iface is ignored."); + zassert_equal(stats.event_count_ipv4, 0, + "No events should be fired if disconnecting iface is ignored."); + zassert_equal(stats.event_count_ipv6, 0, "No events should be fired if disconnecting iface is ignored."); } From 7fa6b53ac37c29c3510b5634aeaa12241bfcb851 Mon Sep 17 00:00:00 2001 From: Georges Oates_Larsen Date: Thu, 6 Jun 2024 18:50:07 -0700 Subject: [PATCH 2094/2849] net: shell: Add IPv4 and IPv6 connectivity events Add descriptions for recently introduced IPv4 and IPv6 connectivity events to the net event monitor. Signed-off-by: Georges Oates_Larsen --- include/zephyr/net/net_event.h | 8 ++++---- subsys/net/lib/shell/events.c | 12 ++++++++++++ 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/include/zephyr/net/net_event.h b/include/zephyr/net/net_event.h index 8e37638f7531b..9bcba06be76eb 100644 --- a/include/zephyr/net/net_event.h +++ b/include/zephyr/net/net_event.h @@ -312,19 +312,19 @@ enum net_event_l4_cmd { (_NET_EVENT_L4_BASE | NET_EVENT_L4_CMD_DISCONNECTED) -/** Event raised when IPv4 network connectivity becomes available. */ +/** Event raised when IPv4 network connectivity is available. */ #define NET_EVENT_L4_IPV4_CONNECTED \ (_NET_EVENT_L4_BASE | NET_EVENT_L4_CMD_IPV4_CONNECTED) -/** Event emitted when IPv4 network connectivity becomes lost. */ +/** Event emitted when IPv4 network connectivity is lost. */ #define NET_EVENT_L4_IPV4_DISCONNECTED \ (_NET_EVENT_L4_BASE | NET_EVENT_L4_CMD_IPV4_DISCONNECTED) -/** Event emitted when IPv6 network connectivity becomes available. */ +/** Event emitted when IPv6 network connectivity is available. */ #define NET_EVENT_L4_IPV6_CONNECTED \ (_NET_EVENT_L4_BASE | NET_EVENT_L4_CMD_IPV6_CONNECTED) -/** Event emitted when IPv6 network connectivity becomes available. */ +/** Event emitted when IPv6 network connectivity is lost. */ #define NET_EVENT_L4_IPV6_DISCONNECTED \ (_NET_EVENT_L4_BASE | NET_EVENT_L4_CMD_IPV6_DISCONNECTED) diff --git a/subsys/net/lib/shell/events.c b/subsys/net/lib/shell/events.c index e90ebce12e7a1..72044b5afa6fd 100644 --- a/subsys/net/lib/shell/events.c +++ b/subsys/net/lib/shell/events.c @@ -284,6 +284,18 @@ static const char *get_l4_desc(uint32_t event) case NET_EVENT_L4_DISCONNECTED: desc = "disconnected"; break; + case NET_EVENT_L4_IPV4_CONNECTED: + desc = "IPv4 connectivity available"; + break; + case NET_EVENT_L4_IPV4_DISCONNECTED: + desc = "IPv4 connectivity lost"; + break; + case NET_EVENT_L4_IPV6_CONNECTED: + desc = "IPv6 connectivity available"; + break; + case NET_EVENT_L4_IPV6_DISCONNECTED: + desc = "IPv6 connectivity lost"; + break; case NET_EVENT_DNS_SERVER_ADD: desc = "DNS server add"; break; From 65154e644be83588837961c6ea22bc932a1fd5af Mon Sep 17 00:00:00 2001 From: Eve Redero Date: Tue, 26 Mar 2024 20:24:57 +0100 Subject: [PATCH 2095/2849] doc: cmake: fix cmake config documentation In new hardware model, the arch subfolder is no more: updating cmake config documentation to reflect this change Signed-off-by: Eve Redero --- cmake/modules/boards.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/modules/boards.cmake b/cmake/modules/boards.cmake index ec9b6579146c0..d2c0666f2c576 100644 --- a/cmake/modules/boards.cmake +++ b/cmake/modules/boards.cmake @@ -136,7 +136,7 @@ foreach(root ${BOARD_ROOT}) message(WARNING "BOARD_ROOT element without a 'boards' subdirectory: ${root} Hints: - - if your board directory is '/foo/bar/boards//my_board' then add '/foo/bar' to BOARD_ROOT, not the entire board directory + - if your board directory is '/foo/bar/boards/my_board' then add '/foo/bar' to BOARD_ROOT, not the entire board directory - if in doubt, use absolute paths") endif() endforeach() From 9ba4aab76eaaee8de7d66a664aeb4da7a42e880e Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Thu, 6 Jun 2024 12:27:30 +0300 Subject: [PATCH 2096/2849] MAINTAINERS: Add a maintainer and collaborator for Silabs Platforms MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add Johan, Jérôme and Aksel to Silabs Platforms. Also update the subsystem and GitHub label name from "SiLabs" to "Silabs", since this is the more usual spelling. Signed-off-by: Aksel Mellbye Signed-off-by: Jérôme Pouiller Signed-off-by: Johan Hedberg --- MAINTAINERS.yml | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/MAINTAINERS.yml b/MAINTAINERS.yml index 52d7a305e1ec9..33df039be7ee8 100644 --- a/MAINTAINERS.yml +++ b/MAINTAINERS.yml @@ -3240,8 +3240,13 @@ Raspberry Pi Pico Platforms: labels: - "platform: Raspberry Pi Pico" -SiLabs Platforms: - status: odd fixes +Silabs Platforms: + status: maintained + maintainers: + - jhedberg + collaborators: + - jerome-pouiller + - asmellby files: - soc/silabs/ - boards/silabs/ @@ -3249,7 +3254,7 @@ SiLabs Platforms: - dts/bindings/*/silabs* - drivers/*/*_gecko* labels: - - "platform: SiLabs" + - "platform: Silabs" Intel Platforms (X86): status: maintained From b46fb464cbaaad8d094f75487a3502a11126d025 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Thu, 6 Jun 2024 18:04:14 +0300 Subject: [PATCH 2097/2849] MAINTAINERS: Add a maintainer and collaborators to hal_silabs Update the status to maintained, add a maintainer and collaborators, and also update the label to match the recent spelling change ("SiLabs" -> "Silabs"). Signed-off-by: Johan Hedberg --- MAINTAINERS.yml | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/MAINTAINERS.yml b/MAINTAINERS.yml index 33df039be7ee8..39bc7e0f8fb00 100644 --- a/MAINTAINERS.yml +++ b/MAINTAINERS.yml @@ -4450,15 +4450,19 @@ West: - "platform: Raspberry Pi Pico" "West project: hal_silabs": - status: odd fixes + status: maintained + maintainers: + - jhedberg collaborators: + - jerome-pouiller + - asmellby - sateeshkotapati - yonsch - mnkp files: - modules/Kconfig.silabs labels: - - "platform: SiLabs" + - "platform: Silabs" "West project: hal_st": status: maintained From 9ee3bf221d0288f123cd193d78984cac2d95e22e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20Cab=C3=A9?= Date: Wed, 5 Jun 2024 18:31:56 +0200 Subject: [PATCH 2098/2849] doc: pdf: add ImageMagick converter extension MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Our documentation uses image formats such as WebP that are not supported by LaTeX. This commit enables Sphinx's sphinx.ext.imageconverter extension, and updates the documentation to indicate ImageMagick is required to build docs. Signed-off-by: Benjamin Cabé --- .github/workflows/doc-build.yml | 2 +- doc/CMakeLists.txt | 2 +- doc/conf.py | 8 ++++++-- doc/contribute/documentation/generation.rst | 12 ++++++------ 4 files changed, 14 insertions(+), 10 deletions(-) diff --git a/.github/workflows/doc-build.yml b/.github/workflows/doc-build.yml index d7c1edd6a6591..c50625a1879ea 100644 --- a/.github/workflows/doc-build.yml +++ b/.github/workflows/doc-build.yml @@ -217,7 +217,7 @@ jobs: - name: install-pkgs run: | apt-get update - apt-get install -y python3-pip python3-venv ninja-build doxygen graphviz librsvg2-bin + apt-get install -y python3-pip python3-venv ninja-build doxygen graphviz librsvg2-bin imagemagick - name: cache-pip uses: actions/cache@v4 diff --git a/doc/CMakeLists.txt b/doc/CMakeLists.txt index 5cfce578a4a9e..e72b7ac229861 100644 --- a/doc/CMakeLists.txt +++ b/doc/CMakeLists.txt @@ -174,7 +174,7 @@ add_doc_target( -d ${DOCS_DOCTREE_DIR} -w ${DOCS_BUILD_DIR}/latex.log -t ${DOC_TAG} - -t svgconvert + -t convertimages ${SPHINXOPTS} ${SPHINXOPTS_EXTRA} ${DOCS_SRC_DIR} diff --git a/doc/conf.py b/doc/conf.py index ff54dd2cc490f..a86f09b054234 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -99,9 +99,13 @@ "zephyr.api_overview", ] -# Only use SVG converter when it is really needed, e.g. LaTeX. -if tags.has("svgconvert"): # pylint: disable=undefined-variable +# Only use image conversion when it is really needed, e.g. LaTeX build. +# Ensure "sphinxcontrib.rsvgconverter" is added before "sphinx.ext.imgconverter" +# as it's better at converting SVG with extended features (like the ones from +# draw.io) to PDF format). +if tags.has("convertimages"): # pylint: disable=undefined-variable extensions.append("sphinxcontrib.rsvgconverter") + extensions.append("sphinx.ext.imgconverter") templates_path = ["_templates"] diff --git a/doc/contribute/documentation/generation.rst b/doc/contribute/documentation/generation.rst index 3991b19c47d23..f51eb59e44e49 100644 --- a/doc/contribute/documentation/generation.rst +++ b/doc/contribute/documentation/generation.rst @@ -105,27 +105,27 @@ as described below: .. code-block:: console sudo apt-get install --no-install-recommends doxygen graphviz librsvg2-bin \ - texlive-latex-base texlive-latex-extra latexmk texlive-fonts-recommended + texlive-latex-base texlive-latex-extra latexmk texlive-fonts-recommended imagemagick On Fedora Linux: .. code-block:: console sudo dnf install doxygen graphviz texlive-latex latexmk \ - texlive-collection-fontsrecommended librsvg2-tools + texlive-collection-fontsrecommended librsvg2-tools ImageMagick On Clear Linux: .. code-block:: console - sudo swupd bundle-add texlive graphviz + sudo swupd bundle-add texlive graphviz ImageMagick On Arch Linux: .. code-block:: console sudo pacman -S graphviz doxygen librsvg texlive-core texlive-bin \ - texlive-latexextra texlive-fontsextra + texlive-latexextra texlive-fontsextra imagemagick .. group-tab:: macOS @@ -139,7 +139,7 @@ as described below: .. code-block:: console - brew install doxygen graphviz mactex librsvg + brew install doxygen graphviz mactex librsvg imagemagick tlmgr install latexmk tlmgr install collection-fontsrecommended @@ -155,7 +155,7 @@ as described below: .. code-block:: console - choco install doxygen.install graphviz strawberryperl miktex rsvg-convert + choco install doxygen.install graphviz strawberryperl miktex rsvg-convert imagemagick .. note:: On Windows, the Sphinx executable ``sphinx-build.exe`` is placed in From c61ccd9af014a0a0e733b6784f6595db0ad09870 Mon Sep 17 00:00:00 2001 From: Ioannis Karachalios Date: Thu, 6 Jun 2024 11:08:35 +0300 Subject: [PATCH 2099/2849] dts: renesas: smartbond: Add missing #dma-cells binding This commit should address the #73803 issue where the DMA node does not provide support for the #dma-cells binding. Peripherals should specify one or more DMA channels via the dmas and optionally dma-names DT properties. Signed-off-by: Ioannis Karachalios --- dts/arm/renesas/smartbond/da1469x.dtsi | 2 +- dts/bindings/dma/renesas,smartbond-dma.yaml | 11 +++++++ .../zephyr/dt-bindings/dma/dma_smartbond.h | 31 +++++++++++++++++++ 3 files changed, 43 insertions(+), 1 deletion(-) create mode 100644 include/zephyr/dt-bindings/dma/dma_smartbond.h diff --git a/dts/arm/renesas/smartbond/da1469x.dtsi b/dts/arm/renesas/smartbond/da1469x.dtsi index 1da9cc6cae0b5..3ab063af25cc7 100644 --- a/dts/arm/renesas/smartbond/da1469x.dtsi +++ b/dts/arm/renesas/smartbond/da1469x.dtsi @@ -386,7 +386,7 @@ status = "disabled"; dma-channels = <8>; block-count = <1>; - #dma-cells = <0>; + #dma-cells = <2>; }; memc: qspic2@34000000 { diff --git a/dts/bindings/dma/renesas,smartbond-dma.yaml b/dts/bindings/dma/renesas,smartbond-dma.yaml index 0845df7746324..388efb236ebf0 100644 --- a/dts/bindings/dma/renesas,smartbond-dma.yaml +++ b/dts/bindings/dma/renesas,smartbond-dma.yaml @@ -19,3 +19,14 @@ properties: type: int const: 1 description: Number of block counts supported + + "#dma-cells": + const: 2 + +# - #dma-cells : Must be <2>. +# channel: dma channel to be reserved +# config: peripheral's dma request line. Valid values are defined in dt-bindings/dma/dma_smartbond.h + +dma-cells: + - channel + - config diff --git a/include/zephyr/dt-bindings/dma/dma_smartbond.h b/include/zephyr/dt-bindings/dma/dma_smartbond.h new file mode 100644 index 0000000000000..4240801c9756a --- /dev/null +++ b/include/zephyr/dt-bindings/dma/dma_smartbond.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2023 Renesas Electronics Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef DMA_SMARTBOND_H_ +#define DMA_SMARTBOND_H_ + +/** + * @brief Vendror-specific DMA peripheral triggering sources. + * + * A valid triggering source should be provided when DMA + * is configured for peripheral to peripheral or memory to peripheral + * transactions. + */ +#define DMA_SMARTBOND_TRIG_MUX_SPI 0x0 +#define DMA_SMARTBOND_TRIG_MUX_SPI2 0x1 +#define DMA_SMARTBOND_TRIG_MUX_UART 0x2 +#define DMA_SMARTBOND_TRIG_MUX_UART2 0x3 +#define DMA_SMARTBOND_TRIG_MUX_I2C 0x4 +#define DMA_SMARTBOND_TRIG_MUX_I2C2 0x5 +#define DMA_SMARTBOND_TRIG_MUX_USB 0x6 +#define DMA_SMARTBOND_TRIG_MUX_UART3 0x7 +#define DMA_SMARTBOND_TRIG_MUX_PCM 0x8 +#define DMA_SMARTBOND_TRIG_MUX_SRC 0x9 +#define DMA_SMARTBOND_TRIG_MUX_GPADC 0xC +#define DMA_SMARTBOND_TRIG_MUX_SDADC 0xD +#define DMA_SMARTBOND_TRIG_MUX_NONE 0xF + +#endif /* DMA_SMARTBOND_H_ */ From c8b2f2e2b6d10e75acede5caf460b48e1686b730 Mon Sep 17 00:00:00 2001 From: Ioannis Karachalios Date: Thu, 6 Jun 2024 11:19:02 +0300 Subject: [PATCH 2100/2849] drivers: dma: smartbond: Add missing direction case This commit should deal with adding a missing direction case as memory-to-peripheral and peripheral-to-memory transfers should be considered the same. Signed-off-by: Ioannis Karachalios --- drivers/dma/dma_smartbond.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/dma/dma_smartbond.c b/drivers/dma/dma_smartbond.c index d3ded5ebc37bb..493ac222836de 100644 --- a/drivers/dma/dma_smartbond.c +++ b/drivers/dma/dma_smartbond.c @@ -343,6 +343,7 @@ static bool dma_channel_update_dreq_mode(enum dma_channel_direction direction, DMA_CTRL_REG_SET_FIELD(DREQ_MODE, *dma_ctrl_reg, DREQ_MODE_SW); break; case PERIPHERAL_TO_MEMORY: + case MEMORY_TO_PERIPHERAL: case PERIPHERAL_TO_PERIPHERAL: /* DMA channels starts by peripheral DMA req */ DMA_CTRL_REG_SET_FIELD(DREQ_MODE, *dma_ctrl_reg, DREQ_MODE_HW); From 6be31f5243fe1d54fdcde9e2a26f44d4d5897c8b Mon Sep 17 00:00:00 2001 From: Georgij Cernysiov Date: Thu, 6 Jun 2024 13:43:33 +0200 Subject: [PATCH 2101/2849] drivers: flash: stm32: move memmap config Move STM32_MEMMAP outside of SOC_FLASH_STM32. That allows memory-mapped application to be built without internal flash controller. Signed-off-by: Georgij Cernysiov --- drivers/flash/Kconfig.stm32 | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/drivers/flash/Kconfig.stm32 b/drivers/flash/Kconfig.stm32 index 9caf7a04de850..0c820da97c1c9 100644 --- a/drivers/flash/Kconfig.stm32 +++ b/drivers/flash/Kconfig.stm32 @@ -6,6 +6,15 @@ # Copyright (c) 2023 Google Inc # SPDX-License-Identifier: Apache-2.0 +config STM32_MEMMAP + bool "NOR Flash in MemoryMapped for XiP" + depends on XIP && \ + (DT_HAS_ST_STM32_OSPI_NOR_ENABLED || \ + DT_HAS_ST_STM32_QSPI_NOR_ENABLED) + help + This option enables the XIP mode for the external NOR flash + mounted on STM32 boards. + config SOC_FLASH_STM32 bool "STM32 flash driver" depends on DT_HAS_ST_STM32_FLASH_CONTROLLER_ENABLED @@ -73,11 +82,4 @@ 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 cd5d5a64f59001d78e3398eeef3c383c1b519795 Mon Sep 17 00:00:00 2001 From: Piotr Koziar Date: Mon, 6 May 2024 12:14:15 +0200 Subject: [PATCH 2102/2849] dts: nrf54h20: add grtc channel 15 to the pool. Adds channel 15 to the pool of grtc channels available for allocation (i.e. with 'z_nrf_grtc_timer_chan_alloc') on nRF54H20. The change is motivated by lack of available channels for the nrf_802154_timestamper when building for nRF54H20. Signed-off-by: Piotr Koziar --- dts/arm/nordic/nrf54h20_cpurad.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dts/arm/nordic/nrf54h20_cpurad.dtsi b/dts/arm/nordic/nrf54h20_cpurad.dtsi index e4a7469dac553..b426d660f3dc0 100644 --- a/dts/arm/nordic/nrf54h20_cpurad.dtsi +++ b/dts/arm/nordic/nrf54h20_cpurad.dtsi @@ -50,7 +50,7 @@ wdt011: &cpurad_wdt011 {}; }; &grtc { - owned-channels = <7 8 9 10 11 12 13 14>; + owned-channels = <7 8 9 10 11 12 13 14 15>; child-owned-channels = <8 9 10 11 12>; nonsecure-channels = <8 9 10 11 12>; interrupts = <109 NRF_DEFAULT_IRQ_PRIORITY>, From 89c4afa3b841eee17b2181edb432f5b7b98b95ef Mon Sep 17 00:00:00 2001 From: Piotr Koziar Date: Mon, 13 May 2024 22:17:47 +0200 Subject: [PATCH 2103/2849] modules: hal_nordic: implement hfclk start/stop for nRF54H20. Clock_control is currently not supported on nRF54H20. This commit adds new way of handling the hfclk targeted for nRF54H20. This solution shall be replaced once the clock_control is supported for nRF54H20. Signed-off-by: Piotr Koziar --- .../platform/nrf_802154_clock_zephyr.c | 80 +++++++++---------- 1 file changed, 39 insertions(+), 41 deletions(-) diff --git a/modules/hal_nordic/nrf_802154/sl_opensource/platform/nrf_802154_clock_zephyr.c b/modules/hal_nordic/nrf_802154/sl_opensource/platform/nrf_802154_clock_zephyr.c index 3a3d9501d0c79..1db86f5ad142d 100644 --- a/modules/hal_nordic/nrf_802154/sl_opensource/platform/nrf_802154_clock_zephyr.c +++ b/modules/hal_nordic/nrf_802154/sl_opensource/platform/nrf_802154_clock_zephyr.c @@ -4,18 +4,21 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include #include #include #include +#include +#if defined(CONFIG_CLOCK_CONTROL_NRF) #include #include +#elif !defined(NRF54H_SERIES) +#error No implementation to start or stop HFCLK due to missing clock_control. +#endif static bool hfclk_is_running; -static bool lfclk_is_running; -static struct onoff_client hfclk_cli; -static struct onoff_client lfclk_cli; void nrf_802154_clock_init(void) { @@ -27,6 +30,15 @@ void nrf_802154_clock_deinit(void) /* Intentionally empty. */ } +bool nrf_802154_clock_hfclk_is_running(void) +{ + return hfclk_is_running; +} + +#if defined(CONFIG_CLOCK_CONTROL_NRF) + +static struct onoff_client hfclk_cli; + static void hfclk_on_callback(struct onoff_manager *mgr, struct onoff_client *cli, uint32_t state, @@ -63,53 +75,39 @@ void nrf_802154_clock_hfclk_stop(void) hfclk_is_running = false; } -bool nrf_802154_clock_hfclk_is_running(void) -{ - return hfclk_is_running; -} +#elif defined(NRF54H_SERIES) -static void lfclk_on_callback(struct onoff_manager *mgr, - struct onoff_client *cli, - uint32_t state, - int res) -{ - lfclk_is_running = true; - nrf_802154_clock_lfclk_ready(); -} +#define NRF_LRCCONF_RADIO_PD NRF_LRCCONF010 +#define MAX_HFXO_RAMP_UP_TIME_US 1000 -void nrf_802154_clock_lfclk_start(void) +static void hfclk_started_timer_handler(struct k_timer *dummy) { - int ret; - struct onoff_manager *mgr = - z_nrf_clock_control_get_onoff(CLOCK_CONTROL_NRF_SUBSYS_LF); - - __ASSERT_NO_MSG(mgr != NULL); - - sys_notify_init_callback(&lfclk_cli.notify, lfclk_on_callback); - - ret = onoff_request(mgr, &lfclk_cli); - __ASSERT_NO_MSG(ret >= 0); + hfclk_is_running = true; + nrf_802154_clock_hfclk_ready(); } -void nrf_802154_clock_lfclk_stop(void) -{ - int ret; - struct onoff_manager *mgr = - z_nrf_clock_control_get_onoff(CLOCK_CONTROL_NRF_SUBSYS_LF); +K_TIMER_DEFINE(hfclk_started_timer, hfclk_started_timer_handler, NULL); - __ASSERT_NO_MSG(mgr != NULL); +void nrf_802154_clock_hfclk_start(void) +{ + /* Use register directly, there is no support for that task in nrf_lrcconf_task_trigger. + * This code might cause troubles if there are other HFXO users in this CPU. + */ + NRF_LRCCONF_RADIO_PD->EVENTS_HFXOSTARTED = 0x0; + NRF_LRCCONF_RADIO_PD->TASKS_REQHFXO = 0x1; - ret = onoff_cancel_or_release(mgr, &lfclk_cli); - __ASSERT_NO_MSG(ret >= 0); - lfclk_is_running = false; + k_timer_start(&hfclk_started_timer, K_USEC(MAX_HFXO_RAMP_UP_TIME_US), K_NO_WAIT); } -bool nrf_802154_clock_lfclk_is_running(void) +void nrf_802154_clock_hfclk_stop(void) { - return lfclk_is_running; -} + /* Use register directly, there is no support for that task in nrf_lrcconf_task_trigger. + * This code might cause troubles if there are other HFXO users in this CPU. + */ + NRF_LRCCONF_RADIO_PD->TASKS_STOPREQHFXO = 0x1; + NRF_LRCCONF_RADIO_PD->EVENTS_HFXOSTARTED = 0x0; -__WEAK void nrf_802154_clock_lfclk_ready(void) -{ - /* Intentionally empty. */ + hfclk_is_running = false; } + +#endif From e66b38263989224c9bb112f8a0ea0fa6942bb6f9 Mon Sep 17 00:00:00 2001 From: Piotr Koziar Date: Wed, 15 May 2024 16:10:59 +0200 Subject: [PATCH 2104/2849] ipc: fix return code of icbmsg backend send operation. This commit fixes the issue where a serialization error was reported after properly sending a data with 'icbmsg' backend. The icbmsg send function's return code is set to the sent data's len as in other backends. The related docs were fixed and updated. Signed-off-by: Piotr Koziar --- include/zephyr/ipc/icmsg.h | 2 +- subsys/ipc/ipc_service/backends/ipc_icbmsg.c | 13 +++++++++---- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/include/zephyr/ipc/icmsg.h b/include/zephyr/ipc/icmsg.h index 3bc03804ca824..80e3412095acb 100644 --- a/include/zephyr/ipc/icmsg.h +++ b/include/zephyr/ipc/icmsg.h @@ -111,7 +111,7 @@ int icmsg_close(const struct icmsg_config_t *conf, * @param[in] len Size of data in the @p msg buffer. * * - * @retval 0 on success. + * @retval Number of sent bytes. * @retval -EBUSY when the instance has not finished handshake with the remote * instance. * @retval -ENODATA when the requested data to send is empty. diff --git a/subsys/ipc/ipc_service/backends/ipc_icbmsg.c b/subsys/ipc/ipc_service/backends/ipc_icbmsg.c index 3759402531326..4a3fdad1adfb4 100644 --- a/subsys/ipc/ipc_service/backends/ipc_icbmsg.c +++ b/subsys/ipc/ipc_service/backends/ipc_icbmsg.c @@ -501,7 +501,7 @@ static int send_control_message(struct backend_data *dev_data, enum msg_type msg r = icmsg_send(&conf->control_config, &dev_data->control_data, &message, sizeof(message)); k_mutex_unlock(&dev_data->mutex); - if (r < 0) { + if (r < sizeof(message)) { LOG_ERR("Cannot send over ICMsg, err %d", r); } return r; @@ -541,7 +541,7 @@ static int send_release(struct backend_data *dev_data, const uint8_t *buffer, * @param[in] size Actual size of the data, can be smaller than allocated, * but it cannot change number of required blocks. * - * @return O or negative error code. + * @return number of bytes sent in the message or negative error code. */ static int send_block(struct backend_data *dev_data, enum msg_type msg_type, uint8_t ept_addr, size_t tx_block_index, size_t size) @@ -656,7 +656,7 @@ static int match_bound_msg(struct backend_data *dev_data, size_t rx_block_index, * * @param[in] ept Endpoint to use. * - * @return O or negative error code. + * @return non-negative value in case of success or negative error code. */ static int send_bound_message(struct backend_data *dev_data, struct ept_data *ept) { @@ -992,7 +992,12 @@ static int send(const struct device *instance, void *token, const void *msg, siz memcpy(buffer, msg, len); /* Send data message. */ - return send_block(dev_data, MSG_DATA, ept->addr, r, len); + r = send_block(dev_data, MSG_DATA, ept->addr, r, len); + if (r < 0) { + return r; + } + + return len; } /** From 17a3c6dc244fed00a9a12a55f120e23d2fa243af Mon Sep 17 00:00:00 2001 From: Piotr Koziar Date: Tue, 21 May 2024 14:03:42 +0200 Subject: [PATCH 2105/2849] modules: hal_nordic: turn off temperature update by default for nRF54H20. Adds an appropriate condition to the Kconfig as the temperature driver is not supported for nRF54H20 devices yet. Without this change, a build with NRF 802.15.4 libraries produces Kconfig error. Signed-off-by: Piotr Koziar --- modules/hal_nordic/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/hal_nordic/Kconfig b/modules/hal_nordic/Kconfig index a7d55e4620aa5..13ab8d9cd2f9c 100644 --- a/modules/hal_nordic/Kconfig +++ b/modules/hal_nordic/Kconfig @@ -55,7 +55,7 @@ endchoice config NRF_802154_TEMPERATURE_UPDATE bool "nRF 802.15.4 temperature update" - default y + default y if !SOC_NRF54H20 help Enable temperature update for nRF 802.15.4 driver From 9037a708ee3b78588ff0ac59199678572845a0f7 Mon Sep 17 00:00:00 2001 From: Piotr Koziar Date: Wed, 22 May 2024 15:14:53 +0200 Subject: [PATCH 2106/2849] drivers: ieee802154_nrf5: Use BLE.ADDR instead of FICR to create EUI64. Use BLE.ADDR to create unique (to some extent) EUI64 on nRF54H20 in some cases inside the IEEE 802.15.4 driver. The amount of EUI64-s available in such a way is very limited (~16 million). However, currently there does not seem to be another feasible way to get device identifiers on nRF54H20 (such are kept in SICR, to which the radio core has no access). Signed-off-by: Piotr Koziar --- drivers/ieee802154/ieee802154_nrf5.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/ieee802154/ieee802154_nrf5.c b/drivers/ieee802154/ieee802154_nrf5.c index a8d64416bc836..13f4132a01dfd 100644 --- a/drivers/ieee802154/ieee802154_nrf5.c +++ b/drivers/ieee802154/ieee802154_nrf5.c @@ -126,7 +126,11 @@ static void nrf5_get_eui64(uint8_t *mac) mac[index++] = (IEEE802154_NRF5_VENDOR_OUI >> 8) & 0xff; mac[index++] = IEEE802154_NRF5_VENDOR_OUI & 0xff; -#if defined(CONFIG_TRUSTED_EXECUTION_NONSECURE) && defined(NRF_FICR_S) +#if defined(NRF54H_SERIES) + /* Can't access SICR with device id on a radio core. Use BLE.ADDR. */ + deviceid[0] = NRF_FICR->BLE.ADDR[0]; + deviceid[1] = NRF_FICR->BLE.ADDR[1]; +#elif defined(CONFIG_TRUSTED_EXECUTION_NONSECURE) && defined(NRF_FICR_S) soc_secure_read_deviceid(deviceid); #else deviceid[0] = nrf_ficr_deviceid_get(NRF_FICR, 0); From e94af5b15393806cc4cce30ca296b7742aeb2def Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Baldassari?= Date: Sat, 20 Apr 2024 21:27:47 -0400 Subject: [PATCH 2107/2849] Litex: clock: Undefined behavior due to unchecked return code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Found via static analysis. Two separate error paths where failing to check the return code leads to undefined behavior: 1. In `litex_clk_get_phase`, the divider stays set to 0 when `litex_clk_get_clkout_divider` errors out, which leads to a division by 0. 2. In `litex_clk_calc_duty_normal`, the `duty` struct is used uninitialized if `litex_clk_get_duty_cycle` errors out. In both case, checking the return code and returning early resolves the issue. Signed-off-by: François Baldassari --- drivers/clock_control/clock_control_litex.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/drivers/clock_control/clock_control_litex.c b/drivers/clock_control/clock_control_litex.c index 2eb0c6b358981..2dd1e159084fc 100644 --- a/drivers/clock_control/clock_control_litex.c +++ b/drivers/clock_control/clock_control_litex.c @@ -905,11 +905,15 @@ static int litex_clk_calc_duty_normal(struct litex_clk_clkout *lcko, uint32_t ht_aprox, synth_duty, min_d; uint8_t high_time_it, edge_it, high_duty, divider = lcko->config.div; + int err; if (calc_new) { duty = lcko->ts_config.duty; } else { - litex_clk_get_duty_cycle(lcko, &duty); + err = litex_clk_get_duty_cycle(lcko, &duty); + if (err != 0) { + return err; + } } high_duty = litex_clk_calc_duty_percent(&duty); @@ -1127,9 +1131,13 @@ int litex_clk_get_phase(struct litex_clk_clkout *lcko) uint32_t divider = 0, fract_cnt, post_glob_div_f, pm, global_period, clkout_period, period; uint8_t phase_mux = 0, delay_time = 0; + int err = 0; litex_clk_get_phase_data(lcko, &phase_mux, &delay_time); - litex_clk_get_clkout_divider(lcko, ÷r, &fract_cnt); + err = litex_clk_get_clkout_divider(lcko, ÷r, &fract_cnt); + if (err != 0) { + return err; + } post_glob_div_f = (uint32_t)litex_clk_get_real_global_frequency(); period_buff = PICOS_IN_SEC; From f8ce4a8f008dc8348f7c59af1ac7ecfa8338e825 Mon Sep 17 00:00:00 2001 From: Valerio Setti Date: Thu, 30 May 2024 10:50:55 +0200 Subject: [PATCH 2108/2849] doc: describe changes from PR 71827 and PR 72243 This commit updates migration-guide and release-notes docs with the changes introduces by PR 71827 and PR 72243. Signed-off-by: Valerio Setti --- doc/releases/migration-guide-3.7.rst | 25 ++++++++++++++++++++----- doc/releases/release-notes-3.7.rst | 13 +++++++++++++ 2 files changed, 33 insertions(+), 5 deletions(-) diff --git a/doc/releases/migration-guide-3.7.rst b/doc/releases/migration-guide-3.7.rst index ffe45d629c5db..46d504d85893d 100644 --- a/doc/releases/migration-guide-3.7.rst +++ b/doc/releases/migration-guide-3.7.rst @@ -92,17 +92,26 @@ Mbed TLS * TLS 1.2, RSA, AES, DES, and all the hash algorithms except SHA-256 (SHA-224, 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. -* The Kconfig options previously named `CONFIG_MBEDTLS_MAC_*_ENABLED` have been renamed. - The `_MAC` and `_ENABLED` parts have been removed from their names. + (:github:`72078`) +* The Kconfig options previously named ``CONFIG_MBEDTLS_MAC_*_ENABLED`` have been renamed. + The ``_MAC`` and ``_ENABLED`` parts have been removed from their names. (:github:`73267`) * The :kconfig:option:`CONFIG_MBEDTLS_HASH_ALL_ENABLED` Kconfig option has been fixed to actually enable all the available hash algorithms. Previously, it used to only enable the SHA-2 ones. -* The `CONFIG_MBEDTLS_HASH_SHA*_ENABLED` Kconfig options have been removed. They were duplicates - of other Kconfig options which are now named `CONFIG_MBEDTLS_SHA*`. -* The `CONFIG_MBEDTLS_MAC_ALL_ENABLED` Kconfig option has been removed. Its equivalent is the + (:github:`73267`) +* The ``CONFIG_MBEDTLS_HASH_SHA*_ENABLED`` Kconfig options have been removed. They were duplicates + of other Kconfig options which are now named ``CONFIG_MBEDTLS_SHA*``. (:github:`73267`) +* The ``CONFIG_MBEDTLS_MAC_ALL_ENABLED`` Kconfig option has been removed. Its equivalent is the combination of :kconfig:option:`CONFIG_MBEDTLS_HASH_ALL_ENABLED` and :kconfig:option:`CONFIG_MBEDTLS_CMAC`. + (:github:`73267`) * The Kconfig options ``CONFIG_MBEDTLS_MAC_MD4_ENABLED``, ``CONFIG_MBEDTLS_CIPHER_ARC4_ENABLED`` and ``CONFIG_MBEDTLS_CIPHER_BLOWFISH_ENABLED`` were removed because they are no more supported in Mbed TLS. (:github:`73222`) +* When there is any PSA crypto provider available in the system + (i.e. :kconfig:option:`CONFIG_MBEDTLS_PSA_CRYPTO_CLIENT` is set), desired PSA crypto + features must be explicitly enabled using proper ``CONFIG_PSA_WANT_*``. (:github:`72243`) +* TLS/X509/PK/MD modules will use PSA crypto APIs instead of legacy ones as soon + as there is any PSA crypto provider available in the system + (i.e. :kconfig:option:`CONFIG_MBEDTLS_PSA_CRYPTO_CLIENT` is set). (:github:`72243`) MCUboot ======= @@ -562,6 +571,12 @@ Networking to receive all the network packets. See details in https://www.man7.org/linux/man-pages/man7/packet.7.html documentation. (:github:`73338`) +* TCP now uses SHA-256 instead of MD5 for ISN generation. The crypto support for + this hash computation was also changed from Mbed TLS to PSA APIs. This was achieved + by making :kconfig:option:`CONFIG_NET_TCP_ISN_RFC6528` depend on + :kconfig:option:`PSA_WANT_ALG_SHA_256` instead of legacy ``CONFIG_MBEDTLS_*`` + features. (:github:`71827`) + Other Subsystems **************** diff --git a/doc/releases/release-notes-3.7.rst b/doc/releases/release-notes-3.7.rst index 434293ce680fa..ac8d50a55a5b2 100644 --- a/doc/releases/release-notes-3.7.rst +++ b/doc/releases/release-notes-3.7.rst @@ -449,6 +449,11 @@ Networking * Removed IPSP support. ``CONFIG_NET_L2_BT`` does not exist anymore. +* TCP: + + * ISN generation now uses SHA-256 instead of MD5. Moreover it now relies on PSA APIs + instead of legacy Mbed TLS functions for hash computation. + USB *** @@ -508,6 +513,14 @@ Libraries / Subsystems * Mbed TLS was updated to 3.6.0. Release notes can be found at: https://github.com/Mbed-TLS/mbedtls/releases/tag/v3.6.0 + * When any PSA crypto provider is available in the system + (:kconfig:option:`CONFIG_MBEDTLS_PSA_CRYPTO_CLIENT` is enabled), desired PSA features + must now be explicitly selected through ``CONFIG_PSA_WANT_xxx`` symbols. + * Choice symbols :kconfig:option:`CONFIG_MBEDTLS_PSA_CRYPTO_LEGACY_RNG` and + :kconfig:option:`CONFIG_MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG` were added in order + to allow the user to specify how Mbed TLS PSA crypto core should generate random numbers. + The former option, which is the default, relies on legacy entropy and CTR_DRBG/HMAC_DRBG + modules, while the latter relies on CSPRNG drivers. * Random From c9a4386a92525e5a847d0d1d62fc3e3500a82310 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20Cab=C3=A9?= Date: Tue, 4 Jun 2024 18:05:28 +0200 Subject: [PATCH 2109/2849] doc: logging: fix LOG_INST_HEXDUMP_DBG link MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit fixed misspelled mention to LOG_INST_HEXDUMP_DBG Signed-off-by: Benjamin Cabé --- doc/services/logging/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/services/logging/index.rst b/doc/services/logging/index.rst index 9e54f8d4da8d0..1193bc6ce7ab9 100644 --- a/doc/services/logging/index.rst +++ b/doc/services/logging/index.rst @@ -53,7 +53,7 @@ For each level the following set of macros are available: - ``LOG_INST_X`` for standard printf-like message associated with the particular instance, e.g. :c:macro:`LOG_INST_INF`. - ``LOG_INST_HEXDUMP_X`` for dumping data associated with the particular - instance, e.g. :c:macro:`LOG_HEXDUMP_INST_DBG` + instance, e.g. :c:macro:`LOG_INST_HEXDUMP_DBG` The warning level also exposes the following additional macro: From d6ed91795d1af3276cbd8c6f5d3d3c3b724b64bb Mon Sep 17 00:00:00 2001 From: Daniel Nejezchleb Date: Thu, 6 Jun 2024 17:35:28 +0200 Subject: [PATCH 2110/2849] net: tcp: Fix context leak during connect Replaced tcp_out() with tcp_out_ext() when sending SYN during tcp connect, so we can intercept error value, beacuse in such case the packet would not be sent at all and the stack would not trigger any mechanism to flush this context so it ends up leaking. These scenarios can arise when the underlaying interface is not properly configured or is disconnected. The conn is marked to be closed and is closed before exiting tcp_in(). Since we can now identify this case we can also exit early in the net_tcp_connect() function and not wait for any timeout. Signed-off-by: Daniel Nejezchleb --- subsys/net/ip/tcp.c | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/subsys/net/ip/tcp.c b/subsys/net/ip/tcp.c index 0c747449f85ec..b891dca05385d 100644 --- a/subsys/net/ip/tcp.c +++ b/subsys/net/ip/tcp.c @@ -2922,11 +2922,16 @@ static enum net_verdict tcp_in(struct tcp *conn, struct net_pkt *pkt) verdict = NET_OK; } else { conn->send_options.mss_found = true; - tcp_out(conn, SYN); - conn->send_options.mss_found = false; - conn_seq(conn, + 1); - next = TCP_SYN_SENT; - tcp_conn_ref(conn); + ret = tcp_out_ext(conn, SYN, NULL /* no data */, conn->seq); + if (ret < 0) { + do_close = true; + close_status = ret; + } else { + conn->send_options.mss_found = false; + conn_seq(conn, + 1); + next = TCP_SYN_SENT; + tcp_conn_ref(conn); + } } break; case TCP_SYN_RECEIVED: @@ -3918,8 +3923,11 @@ int net_tcp_connect(struct net_context *context, (void)tcp_in(conn, NULL); if (!IS_ENABLED(CONFIG_NET_TEST_PROTOCOL)) { - if ((K_TIMEOUT_EQ(timeout, K_NO_WAIT)) && - conn->state != TCP_ESTABLISHED) { + if (conn->state == TCP_UNUSED || conn->state == TCP_CLOSED) { + ret = -errno; + goto out; + } else if ((K_TIMEOUT_EQ(timeout, K_NO_WAIT)) && + conn->state != TCP_ESTABLISHED) { ret = -EINPROGRESS; goto out; } else if (k_sem_take(&conn->connect_sem, timeout) != 0 && From a5c67391bb84b8c419459ee7994851ce62a5c7f7 Mon Sep 17 00:00:00 2001 From: Celina Sophie Kalus Date: Thu, 6 Jun 2024 12:24:26 +0200 Subject: [PATCH 2111/2849] soc: stm32h7: m4: Always enable hardware semaphore clock When BCM4 bit is set to zero, the hardware semaphore clock is never enabled on startup. The hardware semaphores might still randomly work, but very unreliably, and the locking procedure will need several retries despite no competition on the hardware semaphores. This leads to wasted clock cycles on the M4 and sometimes even random kernel panics. This can be solved by always enabling the hardware semaphore clock in the init procedure of the M4, regardless of whether it is used within the initialization or not. On the M7, it is already always enabled. Signed-off-by: Celina Sophie Kalus --- soc/st/stm32/stm32h7x/soc_m4.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/soc/st/stm32/stm32h7x/soc_m4.c b/soc/st/stm32/stm32h7x/soc_m4.c index e2fe8955119a0..9d898178d76f2 100644 --- a/soc/st/stm32/stm32h7x/soc_m4.c +++ b/soc/st/stm32/stm32h7x/soc_m4.c @@ -37,6 +37,9 @@ static int stm32h7_m4_init(void) LL_ART_SetBaseAddress(DT_REG_ADDR(DT_CHOSEN(zephyr_flash))); LL_ART_Enable(); + /* Enable hardware semaphore clock */ + LL_AHB4_GRP1_EnableClock(LL_AHB4_GRP1_PERIPH_HSEM); + /* In case CM4 has not been forced boot by CM7, * CM4 needs to wait until CM7 has setup clock configuration */ @@ -47,7 +50,6 @@ static int stm32h7_m4_init(void) * (system clock config, external memory configuration.. ). * End of system initialization is reached when CM7 takes HSEM. */ - LL_AHB4_GRP1_EnableClock(LL_AHB4_GRP1_PERIPH_HSEM); while ((HSEM->RLR[CFG_HW_ENTRY_STOP_MODE_SEMID] & HSEM_R_LOCK) != HSEM_R_LOCK) ; From 78d9abdab4c5352bc7ea80994ac73f5c66a410b9 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Thu, 6 Jun 2024 14:49:39 +0200 Subject: [PATCH 2112/2849] llext: disable EXPORT_SYMBOL() when CONFIG_LLEXT=n EXPORT_SYMBOL() isn't needed when CONFIG_LLEXT is deselected, it only needlessly creates objects, that make the resulting image larger. Make it a NOP when CONFIG_LLEXT=n. Signed-off-by: Guennadi Liakhovetski --- include/zephyr/llext/symbol.h | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/include/zephyr/llext/symbol.h b/include/zephyr/llext/symbol.h index b9d5c6138a893..62190ed08e586 100644 --- a/include/zephyr/llext/symbol.h +++ b/include/zephyr/llext/symbol.h @@ -89,18 +89,20 @@ struct llext_symtable { * * @param x Symbol to export to extensions */ -#ifdef CONFIG_LLEXT_EXPORT_BUILTINS_BY_SLID +#if defined(CONFIG_LLEXT_EXPORT_BUILTINS_BY_SLID) #define EXPORT_SYMBOL(x) \ static const char Z_GENERIC_SECTION("llext_exports_strtab") __used \ x ## _sym_name[] = STRINGIFY(x); \ static const STRUCT_SECTION_ITERABLE(llext_const_symbol, x ## _sym) = { \ - .name = x ## _sym_name, .addr = (const void *)&x, \ + .name = x ## _sym_name, .addr = (const void *)&x, \ } -#else +#elif defined(CONFIG_LLEXT) #define EXPORT_SYMBOL(x) \ static const STRUCT_SECTION_ITERABLE(llext_const_symbol, x ## _sym) = { \ .name = STRINGIFY(x), .addr = (const void *)&x, \ } +#else +#define EXPORT_SYMBOL(x) #endif /** From 0da71234e6b0a720e4ff1a31f602ecb7a31e5bfe Mon Sep 17 00:00:00 2001 From: Andrej Butok Date: Thu, 6 Jun 2024 14:33:56 +0200 Subject: [PATCH 2113/2849] boards: nxp: kinetis: fix non-optimal sector distribution - Optimize slot sizes for MCUBoot swap move algorithm for frdm_k22f/k64f/k82f, twr_ke18f/kv58f220m, hexiwear_mk64f12 and rddrone_fmuk66 boards. - Use DT_SIZE_K/M macros for slot sizes. Signed-off-by: Andrej Butok --- boards/nxp/frdm_k22f/frdm_k22f.dts | 16 ++++++++-------- boards/nxp/frdm_k64f/frdm_k64f.dts | 16 ++++++++-------- boards/nxp/frdm_k82f/frdm_k82f.dts | 10 +++++----- boards/nxp/hexiwear/hexiwear_mk64f12.dts | 17 ++++++++--------- boards/nxp/rddrone_fmuk66/rddrone_fmuk66.dts | 16 ++++++++-------- boards/nxp/twr_ke18f/twr_ke18f.dts | 20 ++++++++++---------- boards/nxp/twr_kv58f220m/twr_kv58f220m.dts | 20 ++++++++++---------- 7 files changed, 57 insertions(+), 58 deletions(-) diff --git a/boards/nxp/frdm_k22f/frdm_k22f.dts b/boards/nxp/frdm_k22f/frdm_k22f.dts index b3a085560fb15..5c1117a2b5791 100644 --- a/boards/nxp/frdm_k22f/frdm_k22f.dts +++ b/boards/nxp/frdm_k22f/frdm_k22f.dts @@ -204,23 +204,23 @@ zephyr_udc0: &usbotg { boot_partition: partition@0 { label = "mcuboot"; - reg = <0x00000000 0x00010000>; + reg = <0x00000000 DT_SIZE_K(64)>; read-only; }; - /* Note slot 0 has one additional sector, - * this is intended for use with the swap move algorithm + /* The MCUBoot swap-move algorithm uses the last 3 sectors + * of the primary slot0 for swap status and move. */ slot0_partition: partition@10000 { label = "image-0"; - reg = <0x00010000 0x00028800>; + reg = <0x00010000 (DT_SIZE_K(180) + DT_SIZE_K(6))>; }; - slot1_partition: partition@38800 { + slot1_partition: partition@3E800 { label = "image-1"; - reg = <0x00038800 0x00028000>; + reg = <0x0003E800 DT_SIZE_K(180)>; }; - storage_partition: partition@60800 { + storage_partition: partition@6B800 { label = "storage"; - reg = <0x00060800 0x0001f800>; + reg = <0x0006B800 DT_SIZE_K(82)>; }; }; diff --git a/boards/nxp/frdm_k64f/frdm_k64f.dts b/boards/nxp/frdm_k64f/frdm_k64f.dts index 4c42385a794ed..0dbe238c4976f 100644 --- a/boards/nxp/frdm_k64f/frdm_k64f.dts +++ b/boards/nxp/frdm_k64f/frdm_k64f.dts @@ -233,23 +233,23 @@ zephyr_udc0: &usbotg { boot_partition: partition@0 { label = "mcuboot"; - reg = <0x00000000 0x00010000>; + reg = <0x00000000 DT_SIZE_K(64)>; read-only; }; - /* Note slot 0 has one additional sector, - * this is intended for use with the swap move algorithm + /* The MCUBoot swap-move algorithm uses the last 2 sectors + * of the primary slot0 for swap status and move. */ slot0_partition: partition@10000 { label = "image-0"; - reg = <0x00010000 0x00069000>; + reg = <0x00010000 (DT_SIZE_K(416) + DT_SIZE_K(8))>; }; - slot1_partition: partition@79000 { + slot1_partition: partition@7a000 { label = "image-1"; - reg = <0x00079000 0x00068000>; + reg = <0x0007a000 DT_SIZE_K(416)>; }; - storage_partition: partition@e1000 { + storage_partition: partition@e2000 { label = "storage"; - reg = <0x000e1000 0x0001f000>; + reg = <0x000e2000 DT_SIZE_K(120)>; }; }; }; diff --git a/boards/nxp/frdm_k82f/frdm_k82f.dts b/boards/nxp/frdm_k82f/frdm_k82f.dts index e649cb2fa24ab..96640fe64323f 100644 --- a/boards/nxp/frdm_k82f/frdm_k82f.dts +++ b/boards/nxp/frdm_k82f/frdm_k82f.dts @@ -158,14 +158,14 @@ boot_partition: partition@0 { label = "mcuboot"; - reg = <0x0 DT_SIZE_K(48)>; + reg = <0x0 DT_SIZE_K(44)>; }; - /* Note slot 0 has one additional sector, - * this is intended for use with the swap move algorithm + /* The MCUBoot swap-move algorithm uses the last 2 sectors + * of the primary slot0 for swap status and move. */ - slot0_partition: partition@c000 { + slot0_partition: partition@b000 { label = "image-0"; - reg = <0xc000 DT_SIZE_K(100)>; + reg = <0xb000 (DT_SIZE_K(96) + DT_SIZE_K(8))>; }; slot1_partition: partition@25000 { label = "image-1"; diff --git a/boards/nxp/hexiwear/hexiwear_mk64f12.dts b/boards/nxp/hexiwear/hexiwear_mk64f12.dts index d530b6e9036a8..91961b19ad026 100644 --- a/boards/nxp/hexiwear/hexiwear_mk64f12.dts +++ b/boards/nxp/hexiwear/hexiwear_mk64f12.dts @@ -181,26 +181,25 @@ compatible = "fixed-partitions"; #address-cells = <1>; #size-cells = <1>; - boot_partition: partition@0 { label = "mcuboot"; - reg = <0x00000000 0x00010000>; + reg = <0x00000000 DT_SIZE_K(64)>; read-only; }; - /* Note slot 0 has one additional sector, - * this is intended for use with the swap move algorithm + /* The MCUBoot swap-move algorithm uses the last 2 sectors + * of the primary slot0 for swap status and move. */ slot0_partition: partition@10000 { label = "image-0"; - reg = <0x00010000 0x00069000>; + reg = <0x00010000 (DT_SIZE_K(416) + DT_SIZE_K(8))>; }; - slot1_partition: partition@79000 { + slot1_partition: partition@7a000 { label = "image-1"; - reg = <0x00079000 0x00068000>; + reg = <0x0007a000 DT_SIZE_K(416)>; }; - storage_partition: partition@e1000 { + storage_partition: partition@e2000 { label = "storage"; - reg = <0x000e1000 0x0001f000>; + reg = <0x000e2000 DT_SIZE_K(120)>; }; }; }; diff --git a/boards/nxp/rddrone_fmuk66/rddrone_fmuk66.dts b/boards/nxp/rddrone_fmuk66/rddrone_fmuk66.dts index 8d2b01c44ba13..729219dd670e1 100644 --- a/boards/nxp/rddrone_fmuk66/rddrone_fmuk66.dts +++ b/boards/nxp/rddrone_fmuk66/rddrone_fmuk66.dts @@ -236,23 +236,23 @@ zephyr_udc0: &usbotg { boot_partition: partition@0 { label = "mcuboot"; - reg = <0x00000000 0x00010000>; + reg = <0x00000000 DT_SIZE_K(64)>; read-only; }; - /* Note slot 0 has one additional sector, - * this is intended for use with the swap move algorithm + /* The MCUBoot swap-move algorithm uses the last 2 sectors + * of the primary slot0 for swap status and move. */ slot0_partition: partition@10000 { label = "image-0"; - reg = <0x00010000 0x000E9000>; + reg = <0x00010000 (DT_SIZE_K(928) + DT_SIZE_K(8))>; }; - slot1_partition: partition@F9000 { + slot1_partition: partition@FA000 { label = "image-1"; - reg = <0x000F9000 0x000E8000>; + reg = <0x000FA000 DT_SIZE_K(928)>; }; - storage_partition: partition@1e1000 { + storage_partition: partition@1E2000 { label = "storage"; - reg = <0x001e1000 0x0001f000>; + reg = <0x001E2000 DT_SIZE_K(120)>; }; }; }; diff --git a/boards/nxp/twr_ke18f/twr_ke18f.dts b/boards/nxp/twr_ke18f/twr_ke18f.dts index e0f3e1d242c0e..18bbbe7276975 100644 --- a/boards/nxp/twr_ke18f/twr_ke18f.dts +++ b/boards/nxp/twr_ke18f/twr_ke18f.dts @@ -335,25 +335,25 @@ compatible = "fixed-partitions"; #address-cells = <1>; #size-cells = <1>; - boot_partition: partition@0 { label = "mcuboot"; - reg = <0x00000000 0xc000>; + reg = <0x00000000 DT_SIZE_K(64)>; + read-only; }; - /* Note slot 0 has one additional sector, - * this is intended for use with the swap move algorithm + /* The MCUBoot swap-move algorithm uses the last 2 sectors + * of the primary slot0 for swap status and move. */ - slot0_partition: partition@c000 { + slot0_partition: partition@10000 { label = "image-0"; - reg = <0x0000c000 0x37000>; + reg = <0x00010000 (DT_SIZE_K(200) + DT_SIZE_K(8))>; }; - slot1_partition: partition@43000 { + slot1_partition: partition@44000 { label = "image-1"; - reg = <0x00043000 0x36000>; + reg = <0x00044000 DT_SIZE_K(200)>; }; - storage_partition: partition@79000 { + storage_partition: partition@76000 { label = "storage"; - reg = <0x00079000 0x00007000>; + reg = <0x00076000 DT_SIZE_K(40)>; }; }; }; diff --git a/boards/nxp/twr_kv58f220m/twr_kv58f220m.dts b/boards/nxp/twr_kv58f220m/twr_kv58f220m.dts index f79c840942c92..2a59adfd6ef3a 100644 --- a/boards/nxp/twr_kv58f220m/twr_kv58f220m.dts +++ b/boards/nxp/twr_kv58f220m/twr_kv58f220m.dts @@ -113,25 +113,25 @@ compatible = "fixed-partitions"; #address-cells = <1>; #size-cells = <1>; - boot_partition: partition@0 { label = "mcuboot"; - reg = <0x00000000 0x10000>; + reg = <0x00000000 DT_SIZE_K(64)>; + read-only; }; - /* Note slot 0 has one additional sector, - * this is intended for use with the swap move algorithm + /* The MCUBoot swap-move algorithm uses the last 2 sectors + * of the primary slot0 for swap status and move. */ slot0_partition: partition@10000 { label = "image-0"; - reg = <0x00010000 0x68000>; + reg = <0x00010000 (DT_SIZE_K(416) + DT_SIZE_K(16))>; }; - slot1_partition: partition@78000 { + slot1_partition: partition@7C000 { label = "image-1"; - reg = <0x00078000 0x66000>; + reg = <0x0007C000 DT_SIZE_K(416)>; }; - storage_partition: partition@de000 { - label = "image-scratch"; - reg = <0x000de000 0x22000>; + storage_partition: partition@E4000 { + label = "storage"; + reg = <0x000E4000 DT_SIZE_K(112)>; }; }; }; From 502fcac821ad65e706536685b756684b6616104a Mon Sep 17 00:00:00 2001 From: Jakub Zymelka Date: Thu, 6 Jun 2024 14:06:31 +0200 Subject: [PATCH 2114/2849] arch: riscv: core: Enable RISCV IRQs for no multithreading Enable MSTATUS.IEN to allow RISCV interrupts for non-multithreaded applications. Signed-off-by: Jakub Zymelka --- arch/riscv/core/thread.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/riscv/core/thread.c b/arch/riscv/core/thread.c index 60f73a5f531e4..aeb33b31f3b1f 100644 --- a/arch/riscv/core/thread.c +++ b/arch/riscv/core/thread.c @@ -212,6 +212,8 @@ FUNC_NORETURN void z_riscv_switch_to_main_no_multithreading(k_thread_entry_t mai main_stack = (K_THREAD_STACK_BUFFER(z_main_stack) + K_THREAD_STACK_SIZEOF(z_main_stack)); + irq_unlock(MSTATUS_IEN); + __asm__ volatile ( "mv sp, %0; jalr ra, %1, 0" : From 1f058383ae23f6b0a06225b55e74eb6a9d2abd48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20Cab=C3=A9?= Date: Wed, 5 Jun 2024 16:33:05 +0200 Subject: [PATCH 2115/2849] doc: security: improve ETSI 303645 table layout MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Improve ETSI 303645 layout both for HTML (use more appropriate column widths) and PDF (use landscape orientation). Signed-off-by: Benjamin Cabé --- doc/security/standards/etsi-303645.rst | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/doc/security/standards/etsi-303645.rst b/doc/security/standards/etsi-303645.rst index 552756997e251..ce78c96ab676e 100644 --- a/doc/security/standards/etsi-303645.rst +++ b/doc/security/standards/etsi-303645.rst @@ -177,9 +177,13 @@ Provisions Assessment * - N/A - The provision is not applicable to Zephyr or it is product makers responsibility +.. raw:: latex + + \begin{landscape} + .. list-table:: ETSI 303645 provisions assessment using table B.1 :header-rows: 1 - :widths: 17 63 17 63 63 + :widths: 25 80 15 15 60 * - Provision - Description @@ -729,3 +733,7 @@ Provisions Assessment - M C - N/A - + +.. raw:: latex + + \end{landscape} From 61bb79c7eaca11b7be67157b70cecdb8c288a3b7 Mon Sep 17 00:00:00 2001 From: Marek Matej Date: Wed, 29 May 2024 18:01:27 +0200 Subject: [PATCH 2116/2849] soc: espressif: esp32s3: fix memory utilization Fixed bootloader memory layout. Improved memory utilization. Signed-off-by: Marek Matej --- soc/espressif/esp32s3/default.ld | 12 ++++++------ soc/espressif/esp32s3/mcuboot.ld | 11 +++++++---- soc/espressif/esp32s3/memory.h | 16 ++++++++-------- 3 files changed, 21 insertions(+), 18 deletions(-) diff --git a/soc/espressif/esp32s3/default.ld b/soc/espressif/esp32s3/default.ld index 17277f5ebccab..cfe44f010f7ee 100644 --- a/soc/espressif/esp32s3/default.ld +++ b/soc/espressif/esp32s3/default.ld @@ -15,18 +15,18 @@ * If no bootloader is used, we can extend it to gain more user ram. */ #ifdef CONFIG_ESP_SIMPLE_BOOT -user_iram_end = (DRAM_BUFFERS_START + IRAM_DRAM_OFFSET); +user_iram_end = (BOOTLOADER_USER_DRAM_END + IRAM_DRAM_OFFSET); #else user_iram_end = BOOTLOADER_IRAM_LOADER_SEG_START; #endif /* User available SRAM memory segments */ user_dram_seg_org = SRAM1_DRAM_START; -user_iram_seg_org = (SRAM0_IRAM_START + CONFIG_ESP32S3_INSTRUCTION_CACHE_SIZE); -user_dram_end = (user_iram_end - IRAM_DRAM_OFFSET); -user_idram_size = (user_dram_end - SRAM1_DRAM_START); -sram0_iram_size = (SRAM0_SIZE - CONFIG_ESP32S3_INSTRUCTION_CACHE_SIZE); -user_iram_seg_len = (user_idram_size + sram0_iram_size); +user_iram_seg_org = SRAM0_IRAM_START + CONFIG_ESP32S3_INSTRUCTION_CACHE_SIZE; +user_dram_end = BOOTLOADER_IRAM_LOADER_SEG_START - IRAM_DRAM_OFFSET; +user_idram_size = user_dram_end - SRAM1_DRAM_START; +sram0_iram_size = SRAM0_SIZE - CONFIG_ESP32S3_INSTRUCTION_CACHE_SIZE; +user_iram_seg_len = user_idram_size + sram0_iram_size; user_dram_seg_len = user_idram_size; /* Aliases */ diff --git a/soc/espressif/esp32s3/mcuboot.ld b/soc/espressif/esp32s3/mcuboot.ld index 01ad3aded3304..a8ec6a4d150dc 100644 --- a/soc/espressif/esp32s3/mcuboot.ld +++ b/soc/espressif/esp32s3/mcuboot.ld @@ -23,14 +23,17 @@ #define RODATA_REGION dram_seg #define ROMABLE_REGION dram_seg -_bootloader_dram_seg_end = BOOTLOADER_DRAM_SEG_END; +_bootloader_dram_seg_start = BOOTLOADER_DRAM_SEG_START; _bootloader_iram_loader_seg_start = BOOTLOADER_IRAM_LOADER_SEG_START; MEMORY { - iram_seg (RWX) : org = BOOTLOADER_IRAM_SEG_START, len = BOOTLOADER_IRAM_SEG_LEN - iram_loader_seg (RWX) : org = BOOTLOADER_IRAM_LOADER_SEG_START, len = BOOTLOADER_IRAM_LOADER_SEG_LEN - dram_seg (RW) : org = BOOTLOADER_DRAM_SEG_START, len = BOOTLOADER_DRAM_SEG_LEN + iram_seg (RWX) : org = BOOTLOADER_IRAM_SEG_START, + len = BOOTLOADER_IRAM_SEG_LEN + iram_loader_seg (RWX) : org = BOOTLOADER_IRAM_LOADER_SEG_START, + len = BOOTLOADER_IRAM_LOADER_SEG_LEN + dram_seg (RW) : org = BOOTLOADER_DRAM_SEG_START, + len = BOOTLOADER_DRAM_SEG_LEN #ifdef CONFIG_GEN_ISR_TABLES IDT_LIST(RW): org = 0x3ebfe010, len = 0x2000 diff --git a/soc/espressif/esp32s3/memory.h b/soc/espressif/esp32s3/memory.h index 5675acccead6b..4a359c91c8066 100644 --- a/soc/espressif/esp32s3/memory.h +++ b/soc/espressif/esp32s3/memory.h @@ -41,20 +41,20 @@ /* Base address used for calculating memory layout * counted from Dbus backwards and back to the Ibus */ -#define BOOTLOADER_USABLE_DRAM_END DRAM_BUFFERS_START +#define BOOTLOADER_USER_DRAM_END DRAM_BUFFERS_START /* For safety margin between bootloader data section and startup stacks */ #define BOOTLOADER_STACK_OVERHEAD 0x0 -#define BOOTLOADER_DRAM_SEG_LEN 0x6600 -#define BOOTLOADER_IRAM_LOADER_SEG_LEN 0x2c00 -#define BOOTLOADER_IRAM_SEG_LEN 0x9000 +#define BOOTLOADER_DRAM_SEG_LEN 0x6400 +#define BOOTLOADER_IRAM_LOADER_SEG_LEN 0x1a00 +#define BOOTLOADER_IRAM_SEG_LEN 0xa000 /* Start of the lower region is determined by region size and the end of the higher region */ -#define BOOTLOADER_DRAM_SEG_END (BOOTLOADER_USABLE_DRAM_END - BOOTLOADER_STACK_OVERHEAD) -#define BOOTLOADER_DRAM_SEG_START (BOOTLOADER_DRAM_SEG_END - BOOTLOADER_DRAM_SEG_LEN) -#define BOOTLOADER_IRAM_LOADER_SEG_START (BOOTLOADER_DRAM_SEG_START - \ - BOOTLOADER_IRAM_LOADER_SEG_LEN + IRAM_DRAM_OFFSET) +#define BOOTLOADER_IRAM_LOADER_SEG_START (BOOTLOADER_USER_DRAM_END - BOOTLOADER_STACK_OVERHEAD + \ + IRAM_DRAM_OFFSET - BOOTLOADER_IRAM_LOADER_SEG_LEN) #define BOOTLOADER_IRAM_SEG_START (BOOTLOADER_IRAM_LOADER_SEG_START - BOOTLOADER_IRAM_SEG_LEN) +#define BOOTLOADER_DRAM_SEG_END (BOOTLOADER_IRAM_SEG_START - IRAM_DRAM_OFFSET) +#define BOOTLOADER_DRAM_SEG_START (BOOTLOADER_DRAM_SEG_END - BOOTLOADER_DRAM_SEG_LEN) /* Flash */ #ifdef CONFIG_FLASH_SIZE From 9f1a4e3e4f333e5c064e4b13c8712980fb38ca8f Mon Sep 17 00:00:00 2001 From: Marek Matej Date: Wed, 29 May 2024 18:03:29 +0200 Subject: [PATCH 2117/2849] soc: espressif: esp32s3: add cross segment call check Add build check that would detect unwanted calls from the `iram0.loader_text`, which is the last bootloader segment to be alive. Signed-off-by: Marek Matej --- soc/espressif/esp32s3/CMakeLists.txt | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/soc/espressif/esp32s3/CMakeLists.txt b/soc/espressif/esp32s3/CMakeLists.txt index 540881b45ab5b..d60d8aa6dc865 100644 --- a/soc/espressif/esp32s3/CMakeLists.txt +++ b/soc/espressif/esp32s3/CMakeLists.txt @@ -58,6 +58,7 @@ if (CONFIG_SOC_ESP32S3_APPCPU) endif() else() + ## Building for PROCPU set_property(TARGET bintools PROPERTY disassembly_flag_inline_source) @@ -77,6 +78,21 @@ else() endif() +if(CONFIG_MCUBOOT) + # search from cross references between bootloader sections + message("check_callgraph using: ${ESP_IDF_PATH}/tools/ci/check_callgraph.py") + set_property(GLOBAL APPEND PROPERTY extra_post_build_commands + COMMAND + ${PYTHON_EXECUTABLE} ${ESP_IDF_PATH}/tools/ci/check_callgraph.py + ARGS + --rtl-dirs ${CMAKE_BINARY_DIR}/zephyr + --elf-file ${CMAKE_BINARY_DIR}/zephyr/${CONFIG_KERNEL_BIN_NAME}.elf + find-refs + --from-section='.iram0.loader_text' + --to-section='.iram0.text' + --exit-code) +endif() + if(CONFIG_MCUBOOT) set(SOC_LINKER_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/mcuboot.ld CACHE INTERNAL "") elseif(CONFIG_SOC_ESP32S3_APPCPU) From c7c1e453ad704b16e164de295abffd228e3fb275 Mon Sep 17 00:00:00 2001 From: Yassine El Aissaoui Date: Wed, 5 Jun 2024 14:04:16 +0200 Subject: [PATCH 2118/2849] boards: frdm_rw612: Update for BLE enablement - Update Doc with BLE info - Configure board for BLE - Add pinctrl for flexcomm0 in usart mode needed for BLE tester application Signed-off-by: Yassine El Aissaoui --- boards/nxp/frdm_rw612/Kconfig.defconfig | 11 +++++++ boards/nxp/frdm_rw612/doc/index.rst | 33 ++++++++++++++++++- boards/nxp/frdm_rw612/frdm_rw612-pinctrl.dtsi | 7 ++++ boards/nxp/frdm_rw612/frdm_rw612.dts | 13 ++++++++ 4 files changed, 63 insertions(+), 1 deletion(-) create mode 100644 boards/nxp/frdm_rw612/Kconfig.defconfig diff --git a/boards/nxp/frdm_rw612/Kconfig.defconfig b/boards/nxp/frdm_rw612/Kconfig.defconfig new file mode 100644 index 0000000000000..e05311cb77ef5 --- /dev/null +++ b/boards/nxp/frdm_rw612/Kconfig.defconfig @@ -0,0 +1,11 @@ +# FRDM_RW612 board + +# Copyright 2024 NXP +# SPDX-License-Identifier: Apache-2.0 + +if BOARD_FRDM_RW612 + +config FLASH_LOAD_SIZE + default 0x400000 if !BOOTLOADER_MCUBOOT && !NXP_MONOLITHIC_BT + +endif # BOARD_FRDM_RW612 diff --git a/boards/nxp/frdm_rw612/doc/index.rst b/boards/nxp/frdm_rw612/doc/index.rst index caefff181f0fd..9f01fbdca8918 100644 --- a/boards/nxp/frdm_rw612/doc/index.rst +++ b/boards/nxp/frdm_rw612/doc/index.rst @@ -39,7 +39,8 @@ Supported Features +-----------+------------+-----------------------------------+ | USART | on-chip | serial | +-----------+------------+-----------------------------------+ - +| BLE | on-chip | Bluetooth | ++-----------+------------+-----------------------------------+ The default configuration can be found in the defconfig file: @@ -47,6 +48,16 @@ The default configuration can be found in the defconfig file: Other hardware features are not currently supported +Fetch Binary Blobs +****************** + +To support Bluetooth, frdm_rw612 requires fetching binary blobs, which can be +achieved by running the following command: + +.. code-block:: console + + west blobs fetch hal_nxp + Programming and Debugging ************************* @@ -108,6 +119,26 @@ should see the following message in the terminal: ***** Booting Zephyr OS zephyr-v3.6.0 ***** Hello World! frdm_rw612 +Bluetooth +========= + +BLE functionality requires to fetch binary blobs, so make sure to follow +the ``Fetch Binary Blobs`` section first. + +Those binary blobs can be used in two different ways, depending if :kconfig:option:`CONFIG_NXP_MONOLITHIC_BT` +is enabled or not: + +- :kconfig:option:`CONFIG_NXP_MONOLITHIC_BT` is enabled (default): + +The required binary blob will be linked with the application image directly, forming +one single monolithic image. +The user has nothing else to do other than flashing the application to the board. + +- :kconfig:option:`CONFIG_NXP_MONOLITHIC_BT` is disabled: + +In this case, the BLE blob won't be linked with the application, so the user needs to manually +flash the BLE binary blob to the board at the address ``0x18540000``. +The binary blob will be located here: ``/modules/hal/nxp/zephyr/blobs/rw61x/rw61x_sb_ble_a2.bin`` Resources ========= diff --git a/boards/nxp/frdm_rw612/frdm_rw612-pinctrl.dtsi b/boards/nxp/frdm_rw612/frdm_rw612-pinctrl.dtsi index c9b0bcb8984a1..f5ee76025467f 100644 --- a/boards/nxp/frdm_rw612/frdm_rw612-pinctrl.dtsi +++ b/boards/nxp/frdm_rw612/frdm_rw612-pinctrl.dtsi @@ -13,4 +13,11 @@ slew-rate = "normal"; }; }; + + pinmux_flexcomm0_usart: pinmux_flexcomm0_usart { + group0 { + pinmux = ; + slew-rate = "normal"; + }; + }; }; diff --git a/boards/nxp/frdm_rw612/frdm_rw612.dts b/boards/nxp/frdm_rw612/frdm_rw612.dts index ad7237fb6583e..260c4cdd37e13 100644 --- a/boards/nxp/frdm_rw612/frdm_rw612.dts +++ b/boards/nxp/frdm_rw612/frdm_rw612.dts @@ -38,6 +38,14 @@ pinctrl-names = "default"; }; +&flexcomm0 { + compatible = "nxp,lpc-usart"; + status = "disabled"; + current-speed = <115200>; + pinctrl-0 = <&pinmux_flexcomm0_usart>; + pinctrl-names = "default"; +}; + &hsgpio0 { status = "okay"; }; @@ -55,3 +63,8 @@ spi-max-frequency = <133000000>; }; }; + +&hci { + status = "okay"; + wakeup-source; +}; From bb770c59657976bc360232b9fd9c1a1753361cba Mon Sep 17 00:00:00 2001 From: Yassine El Aissaoui Date: Wed, 5 Jun 2024 14:06:49 +0200 Subject: [PATCH 2119/2849] samples: tests: bluetooth: Add support for frdm_rw612 Adding bt_tester support. Adding bt_tester app build with Twister for frdm_rw612 board Fix failing tests/samples due to unsufficent MPU ressources by releasing unnecessary MPU regions. Twister builds added on peripheral/central ht and enabled Power manager on those examples to cover the CI builds with PM enabled. Signed-off-by: Yassine El Aissaoui --- .../bluetooth/central_ht/boards/frdm_rw612.conf | 1 + samples/bluetooth/central_ht/sample.yaml | 1 + .../peripheral_ht/boards/frdm_rw612.conf | 1 + samples/bluetooth/peripheral_ht/sample.yaml | 1 + .../prod_consumer/boards/frdm_rw612.overlay | 17 +++++++++++++++++ .../shared_mem/boards/frdm_rw612.overlay | 17 +++++++++++++++++ tests/bluetooth/tester/boards/frdm_rw612.conf | 6 ++++++ .../bluetooth/tester/boards/frdm_rw612.overlay | 15 +++++++++++++++ tests/bluetooth/tester/testcase.yaml | 1 + tests/crypto/mbedtls/boards/frdm_rw612.overlay | 17 +++++++++++++++++ tests/kernel/common/boards/frdm_rw612.overlay | 17 +++++++++++++++++ .../fatal/exception/boards/frdm_rw612.overlay | 17 +++++++++++++++++ .../mem_protect/boards/frdm_rw612.overlay | 17 +++++++++++++++++ .../stackprot/boards/frdm_rw612.overlay | 17 +++++++++++++++++ .../userspace/boards/frdm_rw612.overlay | 17 +++++++++++++++++ .../thread_stack/boards/frdm_rw612.overlay | 17 +++++++++++++++++ .../threads/tls/boards/frdm_rw612.overlay | 17 +++++++++++++++++ .../thread_safety/boards/frdm_rw612.overlay | 17 +++++++++++++++++ 18 files changed, 213 insertions(+) create mode 100644 samples/bluetooth/central_ht/boards/frdm_rw612.conf create mode 100644 samples/bluetooth/peripheral_ht/boards/frdm_rw612.conf create mode 100644 samples/userspace/prod_consumer/boards/frdm_rw612.overlay create mode 100644 samples/userspace/shared_mem/boards/frdm_rw612.overlay create mode 100644 tests/bluetooth/tester/boards/frdm_rw612.conf create mode 100644 tests/bluetooth/tester/boards/frdm_rw612.overlay create mode 100644 tests/crypto/mbedtls/boards/frdm_rw612.overlay create mode 100644 tests/kernel/common/boards/frdm_rw612.overlay create mode 100644 tests/kernel/fatal/exception/boards/frdm_rw612.overlay create mode 100644 tests/kernel/mem_protect/mem_protect/boards/frdm_rw612.overlay create mode 100644 tests/kernel/mem_protect/stackprot/boards/frdm_rw612.overlay create mode 100644 tests/kernel/mem_protect/userspace/boards/frdm_rw612.overlay create mode 100644 tests/kernel/threads/thread_stack/boards/frdm_rw612.overlay create mode 100644 tests/kernel/threads/tls/boards/frdm_rw612.overlay create mode 100644 tests/lib/newlib/thread_safety/boards/frdm_rw612.overlay diff --git a/samples/bluetooth/central_ht/boards/frdm_rw612.conf b/samples/bluetooth/central_ht/boards/frdm_rw612.conf new file mode 100644 index 0000000000000..2df782efc7115 --- /dev/null +++ b/samples/bluetooth/central_ht/boards/frdm_rw612.conf @@ -0,0 +1 @@ +CONFIG_PM=y diff --git a/samples/bluetooth/central_ht/sample.yaml b/samples/bluetooth/central_ht/sample.yaml index c598e33112cee..48d2803dde561 100644 --- a/samples/bluetooth/central_ht/sample.yaml +++ b/samples/bluetooth/central_ht/sample.yaml @@ -16,5 +16,6 @@ tests: harness: bluetooth platform_allow: - rd_rw612_bga + - frdm_rw612 extra_configs: - CONFIG_NXP_MONOLITHIC_BT=n diff --git a/samples/bluetooth/peripheral_ht/boards/frdm_rw612.conf b/samples/bluetooth/peripheral_ht/boards/frdm_rw612.conf new file mode 100644 index 0000000000000..2df782efc7115 --- /dev/null +++ b/samples/bluetooth/peripheral_ht/boards/frdm_rw612.conf @@ -0,0 +1 @@ +CONFIG_PM=y diff --git a/samples/bluetooth/peripheral_ht/sample.yaml b/samples/bluetooth/peripheral_ht/sample.yaml index a87129f16627c..be53ecd851908 100644 --- a/samples/bluetooth/peripheral_ht/sample.yaml +++ b/samples/bluetooth/peripheral_ht/sample.yaml @@ -28,5 +28,6 @@ tests: harness: bluetooth platform_allow: - rd_rw612_bga + - frdm_rw612 extra_configs: - CONFIG_NXP_MONOLITHIC_BT=n diff --git a/samples/userspace/prod_consumer/boards/frdm_rw612.overlay b/samples/userspace/prod_consumer/boards/frdm_rw612.overlay new file mode 100644 index 0000000000000..5df8d83c40b87 --- /dev/null +++ b/samples/userspace/prod_consumer/boards/frdm_rw612.overlay @@ -0,0 +1,17 @@ +/* + * Copyright 2024 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/frdm_rw612.overlay b/samples/userspace/shared_mem/boards/frdm_rw612.overlay new file mode 100644 index 0000000000000..5df8d83c40b87 --- /dev/null +++ b/samples/userspace/shared_mem/boards/frdm_rw612.overlay @@ -0,0 +1,17 @@ +/* + * Copyright 2024 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/frdm_rw612.conf b/tests/bluetooth/tester/boards/frdm_rw612.conf new file mode 100644 index 0000000000000..ba1ae16dc7c0b --- /dev/null +++ b/tests/bluetooth/tester/boards/frdm_rw612.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/boards/frdm_rw612.overlay b/tests/bluetooth/tester/boards/frdm_rw612.overlay new file mode 100644 index 0000000000000..f82c0f86b1846 --- /dev/null +++ b/tests/bluetooth/tester/boards/frdm_rw612.overlay @@ -0,0 +1,15 @@ +/* + * Copyright 2024 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + chosen { + zephyr,uart-pipe = &flexcomm0; + }; +}; + +&flexcomm0 { + status = "okay"; +}; diff --git a/tests/bluetooth/tester/testcase.yaml b/tests/bluetooth/tester/testcase.yaml index 8a8cb41b1b7ff..93868152f7df4 100644 --- a/tests/bluetooth/tester/testcase.yaml +++ b/tests/bluetooth/tester/testcase.yaml @@ -14,6 +14,7 @@ tests: harness: bluetooth platform_allow: - rd_rw612_bga + - frdm_rw612 extra_configs: - CONFIG_NXP_MONOLITHIC_BT=n bluetooth.general.tester_le_audio: diff --git a/tests/crypto/mbedtls/boards/frdm_rw612.overlay b/tests/crypto/mbedtls/boards/frdm_rw612.overlay new file mode 100644 index 0000000000000..5df8d83c40b87 --- /dev/null +++ b/tests/crypto/mbedtls/boards/frdm_rw612.overlay @@ -0,0 +1,17 @@ +/* + * Copyright 2024 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/frdm_rw612.overlay b/tests/kernel/common/boards/frdm_rw612.overlay new file mode 100644 index 0000000000000..5df8d83c40b87 --- /dev/null +++ b/tests/kernel/common/boards/frdm_rw612.overlay @@ -0,0 +1,17 @@ +/* + * Copyright 2024 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/frdm_rw612.overlay b/tests/kernel/fatal/exception/boards/frdm_rw612.overlay new file mode 100644 index 0000000000000..5df8d83c40b87 --- /dev/null +++ b/tests/kernel/fatal/exception/boards/frdm_rw612.overlay @@ -0,0 +1,17 @@ +/* + * Copyright 2024 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/frdm_rw612.overlay b/tests/kernel/mem_protect/mem_protect/boards/frdm_rw612.overlay new file mode 100644 index 0000000000000..5df8d83c40b87 --- /dev/null +++ b/tests/kernel/mem_protect/mem_protect/boards/frdm_rw612.overlay @@ -0,0 +1,17 @@ +/* + * Copyright 2024 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/frdm_rw612.overlay b/tests/kernel/mem_protect/stackprot/boards/frdm_rw612.overlay new file mode 100644 index 0000000000000..5df8d83c40b87 --- /dev/null +++ b/tests/kernel/mem_protect/stackprot/boards/frdm_rw612.overlay @@ -0,0 +1,17 @@ +/* + * Copyright 2024 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/frdm_rw612.overlay b/tests/kernel/mem_protect/userspace/boards/frdm_rw612.overlay new file mode 100644 index 0000000000000..5df8d83c40b87 --- /dev/null +++ b/tests/kernel/mem_protect/userspace/boards/frdm_rw612.overlay @@ -0,0 +1,17 @@ +/* + * Copyright 2024 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/frdm_rw612.overlay b/tests/kernel/threads/thread_stack/boards/frdm_rw612.overlay new file mode 100644 index 0000000000000..5df8d83c40b87 --- /dev/null +++ b/tests/kernel/threads/thread_stack/boards/frdm_rw612.overlay @@ -0,0 +1,17 @@ +/* + * Copyright 2024 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/frdm_rw612.overlay b/tests/kernel/threads/tls/boards/frdm_rw612.overlay new file mode 100644 index 0000000000000..5df8d83c40b87 --- /dev/null +++ b/tests/kernel/threads/tls/boards/frdm_rw612.overlay @@ -0,0 +1,17 @@ +/* + * Copyright 2024 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/frdm_rw612.overlay b/tests/lib/newlib/thread_safety/boards/frdm_rw612.overlay new file mode 100644 index 0000000000000..5df8d83c40b87 --- /dev/null +++ b/tests/lib/newlib/thread_safety/boards/frdm_rw612.overlay @@ -0,0 +1,17 @@ +/* + * Copyright 2024 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 19d8ade5fa90519d44a2b6d83e813a7c45f9cd5c Mon Sep 17 00:00:00 2001 From: Marcio Ribeiro Date: Thu, 18 Jan 2024 10:45:38 -0300 Subject: [PATCH 2120/2849] drivers: adc: esp32: dma enable adc dma mode operation on ESP32S3 and ESP32C3 Signed-off-by: Marcio Ribeiro --- drivers/adc/Kconfig.esp32 | 12 ++ drivers/adc/adc_esp32.c | 400 +++++++++++++++++++++++++++++++++++++- 2 files changed, 411 insertions(+), 1 deletion(-) diff --git a/drivers/adc/Kconfig.esp32 b/drivers/adc/Kconfig.esp32 index 8fc8c9cabce07..604d0ad49edbe 100644 --- a/drivers/adc/Kconfig.esp32 +++ b/drivers/adc/Kconfig.esp32 @@ -8,3 +8,15 @@ config ADC_ESP32 depends on DT_HAS_ESPRESSIF_ESP32_ADC_ENABLED help Enable the driver implementation for the ESP32 ADC + +if ADC_ESP32 + +config ADC_ESP32_DMA + bool "ESP32 ADC DMA Support" + default n + depends on DT_HAS_ESPRESSIF_ESP32_GDMA_ENABLED + help + Enable the ADC DMA mode for ADC instances + that enable dma channels in their device tree node. + +endif diff --git a/drivers/adc/adc_esp32.c b/drivers/adc/adc_esp32.c index 9b47fdf6bd723..4e45a3ea22e54 100644 --- a/drivers/adc/adc_esp32.c +++ b/drivers/adc/adc_esp32.c @@ -9,12 +9,25 @@ #include #include #include +#include #include +#include #include +#include +#include + +#if defined(CONFIG_ADC_ESP32_DMA) +#if !SOC_GDMA_SUPPORTED +#error "SoCs without GDMA peripheral are not supported!" +#endif +#include +#include +#endif #include #include #include +#include #include LOG_MODULE_REGISTER(adc_esp32, CONFIG_ADC_LOG_LEVEL); @@ -43,9 +56,16 @@ LOG_MODULE_REGISTER(adc_esp32, CONFIG_ADC_LOG_LEVEL); /* Default internal reference voltage */ #define ADC_ESP32_DEFAULT_VREF_INTERNAL (1100) +#define ADC_DMA_BUFFER_SIZE DMA_DESCRIPTOR_BUFFER_MAX_SIZE_4B_ALIGNED + struct adc_esp32_conf { adc_unit_t unit; uint8_t channel_count; +#if defined(CONFIG_ADC_ESP32_DMA) + const struct device *gpio_port; + const struct device *dma_dev; + uint8_t dma_channel; +#endif /* defined(CONFIG_ADC_ESP32_DMA) */ }; struct adc_esp32_data { @@ -54,8 +74,12 @@ struct adc_esp32_data { esp_adc_cal_characteristics_t chars[SOC_ADC_MAX_CHANNEL_NUM]; uint16_t meas_ref_internal; uint16_t *buffer; - uint16_t *buffer_repeat; bool calibrate; +#if defined(CONFIG_ADC_ESP32_DMA) + adc_hal_dma_ctx_t adc_hal_dma_ctx; + uint8_t *dma_buffer; + struct k_sem dma_conv_wait_lock; +#endif /* defined(CONFIG_ADC_ESP32_DMA) */ }; /* Convert zephyr,gain property to the ESP32 attenuation */ @@ -80,6 +104,7 @@ static inline int gain_to_atten(enum adc_gain gain, adc_atten_t *atten) return 0; } +#if !defined(CONFIG_ADC_ESP32_DMA) /* Convert voltage by inverted attenuation to support zephyr gain values */ static void atten_to_gain(adc_atten_t atten, uint32_t *val_mv) { @@ -101,6 +126,7 @@ static void atten_to_gain(adc_atten_t atten, uint32_t *val_mv) break; } } +#endif /* !defined(CONFIG_ADC_ESP32_DMA) */ static bool adc_calibration_init(const struct device *dev) { @@ -120,9 +146,229 @@ static bool adc_calibration_init(const struct device *dev) LOG_ERR("Invalid arg"); break; } + return false; } +#if defined(CONFIG_ADC_ESP32_DMA) + +static void IRAM_ATTR adc_esp32_dma_conv_done(const struct device *dma_dev, void *user_data, + uint32_t channel, int status) +{ + ARG_UNUSED(dma_dev); + ARG_UNUSED(status); + + const struct device *dev = user_data; + struct adc_esp32_data *data = dev->data; + + k_sem_give(&data->dma_conv_wait_lock); +} + +static int adc_esp32_dma_start(const struct device *dev, uint8_t *buf, size_t len) +{ + const struct adc_esp32_conf *conf = dev->config; + struct adc_esp32_data *data = dev->data; + + int err = 0; + struct dma_config dma_cfg = {0}; + struct dma_status dma_status = {0}; + struct dma_block_config dma_blk = {0}; + + err = dma_get_status(conf->dma_dev, conf->dma_channel, &dma_status); + if (err) { + LOG_ERR("Unable to get dma channel[%u] status (%d)", + (unsigned int)conf->dma_channel, err); + return -EINVAL; + } + + if (dma_status.busy) { + LOG_ERR("dma channel[%u] is busy!", (unsigned int)conf->dma_channel); + return -EBUSY; + } + + unsigned int key = irq_lock(); + + dma_cfg.channel_direction = PERIPHERAL_TO_MEMORY; + dma_cfg.dma_callback = adc_esp32_dma_conv_done; + dma_cfg.user_data = (void *)dev; + dma_cfg.dma_slot = ESP_GDMA_TRIG_PERIPH_ADC0; + dma_cfg.block_count = 1; + dma_cfg.head_block = &dma_blk; + dma_blk.block_size = len; + dma_blk.dest_address = (uint32_t)buf; + + err = dma_config(conf->dma_dev, conf->dma_channel, &dma_cfg); + if (err) { + LOG_ERR("Error configuring dma (%d)", err); + goto unlock; + } + + err = dma_start(conf->dma_dev, conf->dma_channel); + if (err) { + LOG_ERR("Error starting dma (%d)", err); + goto unlock; + } + +unlock: + irq_unlock(key); + return err; +} + +static int adc_esp32_dma_stop(const struct device *dev) +{ + const struct adc_esp32_conf *conf = dev->config; + unsigned int key = irq_lock(); + int err = 0; + + err = dma_stop(conf->dma_dev, conf->dma_channel); + if (err) { + LOG_ERR("Error stopping dma (%d)", err); + } + + irq_unlock(key); + return err; +} + +static int adc_esp32_fill_digi_pattern(const struct device *dev, const struct adc_sequence *seq, + void *pattern_config, uint32_t *pattern_len, uint32_t *unit_attenuation) +{ + const struct adc_esp32_conf *conf = dev->config; + struct adc_esp32_data *data = dev->data; + + adc_digi_pattern_config_t *adc_digi_pattern_config = + (adc_digi_pattern_config_t *)pattern_config; + const uint32_t unit_atten_uninit = 999; + uint32_t channel_mask = 1, channels_copy = seq->channels; + + *pattern_len = 0; + *unit_attenuation = unit_atten_uninit; + for (uint8_t channel_id = 0; channel_id < conf->channel_count; channel_id++) { + if (channels_copy & channel_mask) { + if (*unit_attenuation == unit_atten_uninit) { + *unit_attenuation = data->attenuation[channel_id]; + } else if (*unit_attenuation != data->attenuation[channel_id]) { + LOG_ERR("Channel[%u] attenuation different of unit[%u] attenuation", + (unsigned int)channel_id, (unsigned int)conf->unit); + return -EINVAL; + } + + adc_digi_pattern_config->atten = data->attenuation[channel_id]; + adc_digi_pattern_config->channel = channel_id; + adc_digi_pattern_config->unit = conf->unit; + adc_digi_pattern_config->bit_width = seq->resolution; + adc_digi_pattern_config++; + + *pattern_len += 1; + if (*pattern_len > SOC_ADC_PATT_LEN_MAX) { + LOG_ERR("Max pattern len is %d", SOC_ADC_PATT_LEN_MAX); + return -EINVAL; + } + + channels_copy &= ~channel_mask; + if (!channels_copy) { + break; + } + } + channel_mask <<= 1; + } + + return 0; +} + +static void adc_esp32_digi_start(const struct device *dev, void *pattern_config, + uint32_t pattern_len, uint32_t number_of_samplings, + uint32_t sample_freq_hz, uint32_t unit_attenuation) +{ + const struct adc_esp32_conf *conf = dev->config; + struct adc_esp32_data *data = dev->data; + + sar_periph_ctrl_adc_continuous_power_acquire(); + adc_lock_acquire(conf->unit); + +#if SOC_ADC_CALIBRATION_V1_SUPPORTED + adc_set_hw_calibration_code(conf->unit, unit_attenuation); +#endif /* SOC_ADC_CALIBRATION_V1_SUPPORTED */ + +#if SOC_ADC_ARBITER_SUPPORTED + if (conf->unit == ADC_UNIT_2) { + adc_arbiter_t config = ADC_ARBITER_CONFIG_DEFAULT(); + + adc_hal_arbiter_config(&config); + } +#endif /* SOC_ADC_ARBITER_SUPPORTED */ + + adc_hal_digi_ctrlr_cfg_t adc_hal_digi_ctrlr_cfg; + soc_module_clk_t clk_src = ADC_DIGI_CLK_SRC_DEFAULT; + uint32_t clk_src_freq_hz = 0; + + esp_clk_tree_src_get_freq_hz(clk_src, ESP_CLK_TREE_SRC_FREQ_PRECISION_CACHED, + &clk_src_freq_hz); + + adc_hal_digi_ctrlr_cfg.conv_mode = + (conf->unit == ADC_UNIT_1)?ADC_CONV_SINGLE_UNIT_1:ADC_CONV_SINGLE_UNIT_2; + adc_hal_digi_ctrlr_cfg.clk_src = clk_src; + adc_hal_digi_ctrlr_cfg.clk_src_freq_hz = clk_src_freq_hz; + adc_hal_digi_ctrlr_cfg.sample_freq_hz = sample_freq_hz; + adc_hal_digi_ctrlr_cfg.adc_pattern = (adc_digi_pattern_config_t *)pattern_config; + adc_hal_digi_ctrlr_cfg.adc_pattern_len = pattern_len; + + uint32_t number_of_adc_digi_samples = number_of_samplings * pattern_len; + + adc_hal_dma_config_t adc_hal_dma_config = { + .dev = (void *)GDMA_LL_GET_HW(0), + .eof_desc_num = 1, + .eof_step = 1, + .dma_chan = conf->dma_channel, + .eof_num = number_of_adc_digi_samples, + }; + + adc_hal_dma_ctx_config(&data->adc_hal_dma_ctx, &adc_hal_dma_config); + + adc_hal_set_controller(conf->unit, ADC_HAL_CONTINUOUS_READ_MODE); + adc_hal_digi_init(&data->adc_hal_dma_ctx); + adc_hal_digi_controller_config(&data->adc_hal_dma_ctx, &adc_hal_digi_ctrlr_cfg); + adc_hal_digi_start(&data->adc_hal_dma_ctx, data->dma_buffer); +} + +static void adc_esp32_digi_stop(const struct device *dev) +{ + const struct adc_esp32_conf *conf = dev->config; + struct adc_esp32_data *data = dev->data; + + adc_hal_digi_dis_intr(&data->adc_hal_dma_ctx, ADC_HAL_DMA_INTR_MASK); + adc_hal_digi_clr_intr(&data->adc_hal_dma_ctx, ADC_HAL_DMA_INTR_MASK); + adc_hal_digi_stop(&data->adc_hal_dma_ctx); + adc_hal_digi_deinit(&data->adc_hal_dma_ctx); + adc_lock_release(conf->unit); + sar_periph_ctrl_adc_continuous_power_release(); +} + +static void adc_esp32_fill_seq_buffer(const void *seq_buffer, const void *dma_buffer, + uint32_t number_of_samples) +{ + uint16_t *sample = (uint16_t *)seq_buffer; + adc_digi_output_data_t *digi_data = (adc_digi_output_data_t *)dma_buffer; + + for (uint32_t k = 0; k < number_of_samples; k++) { + *sample++ = (uint16_t)(digi_data++)->type2.data; + } +} + +static int adc_esp32_wait_for_dma_conv_done(const struct device *dev) +{ + struct adc_esp32_data *data = dev->data; + int err = 0; + + err = k_sem_take(&data->dma_conv_wait_lock, K_FOREVER); + if (err) { + LOG_ERR("Error taking dma_conv_wait_lock (%d)", err); + } + + return err; +} + +#endif /* defined(CONFIG_ADC_ESP32_DMA) */ + static int adc_esp32_read(const struct device *dev, const struct adc_sequence *seq) { const struct adc_esp32_conf *conf = dev->config; @@ -137,10 +383,12 @@ static int adc_esp32_read(const struct device *dev, const struct adc_sequence *s return -ENOMEM; } +#if !defined(CONFIG_ADC_ESP32_DMA) if (seq->channels > BIT(channel_id)) { LOG_ERR("Multi-channel readings not supported"); return -ENOTSUP; } +#endif /* !defined(CONFIG_ADC_ESP32_DMA) */ if (seq->options) { if (seq->options->extra_samplings) { @@ -148,10 +396,12 @@ static int adc_esp32_read(const struct device *dev, const struct adc_sequence *s return -ENOTSUP; } +#if !defined(CONFIG_ADC_ESP32_DMA) if (seq->options->interval_us) { LOG_ERR("Interval between samplings not supported"); return -ENOTSUP; } +#endif /* !defined(CONFIG_ADC_ESP32_DMA) */ } if (INVALID_RESOLUTION(seq->resolution)) { @@ -176,6 +426,7 @@ static int adc_esp32_read(const struct device *dev, const struct adc_sequence *s adc_set_data_width(conf->unit, WIDTH_MASK(data->resolution[channel_id])); #endif /* CONFIG_SOC_SERIES_ESP32C3 */ +#if !defined(CONFIG_ADC_ESP32_DMA) /* Read raw value */ if (conf->unit == ADC_UNIT_1) { reading = adc1_get_raw(channel_id); @@ -216,6 +467,74 @@ static int adc_esp32_read(const struct device *dev, const struct adc_sequence *s data->buffer = (uint16_t *) seq->buffer; data->buffer[0] = cal; +#else /* !defined(CONFIG_ADC_ESP32_DMA) */ + + int err = 0; + uint32_t adc_pattern_len, unit_attenuation; + adc_digi_pattern_config_t adc_digi_pattern_config[SOC_ADC_MAX_CHANNEL_NUM]; + + err = adc_esp32_fill_digi_pattern(dev, seq, &adc_digi_pattern_config, + &adc_pattern_len, &unit_attenuation); + if (err || adc_pattern_len == 0) { + return -EINVAL; + } + + const struct adc_sequence_options *options = seq->options; + uint32_t sample_freq_hz = SOC_ADC_SAMPLE_FREQ_THRES_HIGH, + number_of_samplings = 1; + + if (options != NULL) { + number_of_samplings = seq->buffer_size / (adc_pattern_len * sizeof(uint16_t)); + + if (options->interval_us) { + sample_freq_hz = MHZ(1) / options->interval_us; + } + } + + if (!number_of_samplings) { + LOG_ERR("buffer_size insufficient to store at least one set of samples!"); + return -EINVAL; + } + + if (sample_freq_hz < SOC_ADC_SAMPLE_FREQ_THRES_LOW || + sample_freq_hz > SOC_ADC_SAMPLE_FREQ_THRES_HIGH) { + LOG_ERR("ADC sampling frequency out of range: %uHz", sample_freq_hz); + return -EINVAL; + } + + uint32_t number_of_adc_samples = number_of_samplings * adc_pattern_len; + uint32_t number_of_adc_dma_data_bytes = + number_of_adc_samples * SOC_ADC_DIGI_DATA_BYTES_PER_CONV; + + if (number_of_adc_dma_data_bytes > ADC_DMA_BUFFER_SIZE) { + LOG_ERR("dma buffer size insufficient to store a complete sequence!"); + return -EINVAL; + } + + err = adc_esp32_dma_start(dev, data->dma_buffer, number_of_adc_dma_data_bytes); + if (err) { + return err; + } + + adc_esp32_digi_start(dev, &adc_digi_pattern_config, adc_pattern_len, number_of_samplings, + sample_freq_hz, unit_attenuation); + + err = adc_esp32_wait_for_dma_conv_done(dev); + if (err) { + return err; + } + + adc_esp32_digi_stop(dev); + + err = adc_esp32_dma_stop(dev); + if (err) { + return err; + } + + adc_esp32_fill_seq_buffer(seq->buffer, data->dma_buffer, number_of_adc_samples); + +#endif /* !defined(CONFIG_ADC_ESP32_DMA) */ + return 0; } @@ -284,6 +603,34 @@ static int adc_esp32_channel_setup(const struct device *dev, const struct adc_ch LOG_DBG("Using ADC calibration method %d", cal); } +#if defined(CONFIG_ADC_ESP32_DMA) + + if (!SOC_ADC_DIG_SUPPORTED_UNIT(conf->unit)) { + LOG_ERR("ADC2 dma mode is no longer supported, please use ADC1!"); + return -EINVAL; + } + + int io_num = adc_channel_io_map[conf->unit][cfg->channel_id]; + + if (io_num < 0) { + LOG_ERR("Channel %u not supported!", cfg->channel_id); + return -ENOTSUP; + } + + struct gpio_dt_spec gpio = { + .port = conf->gpio_port, + .dt_flags = 0, + .pin = io_num, + }; + + err = gpio_pin_configure_dt(&gpio, GPIO_DISCONNECTED); + if (err) { + LOG_ERR("Error disconnecting io (%d)", io_num); + return err; + } + +#endif /* defined(CONFIG_ADC_ESP32_DMA) */ + return 0; } @@ -291,9 +638,41 @@ static int adc_esp32_init(const struct device *dev) { struct adc_esp32_data *data = (struct adc_esp32_data *) dev->data; +#if defined(CONFIG_ADC_ESP32_DMA) + struct adc_esp32_conf *conf = (struct adc_esp32_conf *) dev->config; + + if (!device_is_ready(conf->gpio_port)) { + LOG_ERR("gpio0 port not ready"); + return -ENODEV; + } + + if (k_sem_init(&data->dma_conv_wait_lock, 0, 1)) { + LOG_ERR("dma_conv_wait_lock initialization failed!"); + return -EINVAL; + } + + data->adc_hal_dma_ctx.rx_desc = k_aligned_alloc(sizeof(uint32_t), + sizeof(dma_descriptor_t)); + if (!data->adc_hal_dma_ctx.rx_desc) { + LOG_ERR("rx_desc allocation failed!"); + return -ENOMEM; + } + LOG_DBG("rx_desc = 0x%08X", (unsigned int)data->adc_hal_dma_ctx.rx_desc); + + data->dma_buffer = k_aligned_alloc(sizeof(uint32_t), ADC_DMA_BUFFER_SIZE); + if (!data->dma_buffer) { + LOG_ERR("dma buffer allocation failed!"); + k_free(data->adc_hal_dma_ctx.rx_desc); + return -ENOMEM; + } + LOG_DBG("data->dma_buffer = 0x%08X", (unsigned int)data->dma_buffer); + +#endif /* defined(CONFIG_ADC_ESP32_DMA) */ + for (uint8_t i = 0; i < ARRAY_SIZE(data->resolution); i++) { data->resolution[i] = ADC_RESOLUTION_MAX; } + for (uint8_t i = 0; i < ARRAY_SIZE(data->attenuation); i++) { data->attenuation[i] = ADC_ATTEN_DB_0; } @@ -316,11 +695,30 @@ static const struct adc_driver_api api_esp32_driver_api = { .ref_internal = ADC_ESP32_DEFAULT_VREF_INTERNAL, }; +#if defined(CONFIG_ADC_ESP32_DMA) + +#define ADC_ESP32_CONF_GPIO_PORT_INIT .gpio_port = DEVICE_DT_GET(DT_NODELABEL(gpio0)), + +#define ADC_ESP32_CONF_DMA_INIT(n) .dma_dev = COND_CODE_1(DT_INST_NODE_HAS_PROP(n, dmas), \ + (DEVICE_DT_GET(DT_INST_DMAS_CTLR_BY_IDX(n, 0))), \ + (NULL)), \ + .dma_channel = COND_CODE_1(DT_INST_NODE_HAS_PROP(n, dmas), \ + (DT_INST_DMAS_CELL_BY_IDX(n, 0, channel)), \ + (0xff)), +#else + +#define ADC_ESP32_CONF_GPIO_PORT_INIT +#define ADC_ESP32_CONF_DMA_INIT(inst) + +#endif /* defined(CONFIG_ADC_ESP32_DMA) */ + #define ESP32_ADC_INIT(inst) \ \ static const struct adc_esp32_conf adc_esp32_conf_##inst = { \ .unit = DT_PROP(DT_DRV_INST(inst), unit) - 1, \ .channel_count = DT_PROP(DT_DRV_INST(inst), channel_count), \ + ADC_ESP32_CONF_GPIO_PORT_INIT \ + ADC_ESP32_CONF_DMA_INIT(inst) \ }; \ \ static struct adc_esp32_data adc_esp32_data_##inst = { \ From 86ff968718d02901e300a6f927c1666fe4e259d4 Mon Sep 17 00:00:00 2001 From: Marcio Ribeiro Date: Fri, 24 May 2024 17:19:04 -0300 Subject: [PATCH 2121/2849] tests: drivers: adc adds test case for esp32 adc with dma enabled Signed-off-by: Marcio Ribeiro --- .../boards/esp32s3_devkitc_procpu.conf | 1 + .../boards/esp32s3_devkitc_procpu.overlay | 39 +++++++++++++++++++ .../adc/adc_api/overlay-dma-esp32.conf | 10 +++++ tests/drivers/adc/adc_api/testcase.yaml | 8 ++++ 4 files changed, 58 insertions(+) create mode 100644 tests/drivers/adc/adc_api/boards/esp32s3_devkitc_procpu.conf create mode 100644 tests/drivers/adc/adc_api/boards/esp32s3_devkitc_procpu.overlay create mode 100644 tests/drivers/adc/adc_api/overlay-dma-esp32.conf diff --git a/tests/drivers/adc/adc_api/boards/esp32s3_devkitc_procpu.conf b/tests/drivers/adc/adc_api/boards/esp32s3_devkitc_procpu.conf new file mode 100644 index 0000000000000..b6c5c80f9244a --- /dev/null +++ b/tests/drivers/adc/adc_api/boards/esp32s3_devkitc_procpu.conf @@ -0,0 +1 @@ +CONFIG_ADC_ASYNC=n diff --git a/tests/drivers/adc/adc_api/boards/esp32s3_devkitc_procpu.overlay b/tests/drivers/adc/adc_api/boards/esp32s3_devkitc_procpu.overlay new file mode 100644 index 0000000000000..4db25818ca20f --- /dev/null +++ b/tests/drivers/adc/adc_api/boards/esp32s3_devkitc_procpu.overlay @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2024 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + + / { + zephyr,user { + io-channels = <&adc0 0>, <&adc0 1>; + }; + }; + + &adc0 { + status = "okay"; + #address-cells = <1>; + #size-cells = <0>; + + channel@0 { + reg = <0>; + zephyr,gain = "ADC_GAIN_1_4"; + zephyr,reference = "ADC_REF_INTERNAL"; + zephyr,acquisition-time = ; + zephyr,resolution = <12>; + }; + + channel@1 { + reg = <1>; + zephyr,gain = "ADC_GAIN_1_4"; + zephyr,reference = "ADC_REF_INTERNAL"; + zephyr,acquisition-time = ; + zephyr,resolution = <12>; + }; + + dmas = <&dma 2>; + }; + +&dma { + status = "okay"; +}; diff --git a/tests/drivers/adc/adc_api/overlay-dma-esp32.conf b/tests/drivers/adc/adc_api/overlay-dma-esp32.conf new file mode 100644 index 0000000000000..16ae289abc3a6 --- /dev/null +++ b/tests/drivers/adc/adc_api/overlay-dma-esp32.conf @@ -0,0 +1,10 @@ +# +# Copyright (c) 2024 Espressif Systems (Shanghai) Co., Ltd. +# +# SPDX-License-Identifier: Apache-2.0 +# + +CONFIG_TEST_USERSPACE=n +CONFIG_DMA=y +CONFIG_ADC_ESP32_DMA=y +CONFIG_HEAP_MEM_POOL_SIZE=16384 diff --git a/tests/drivers/adc/adc_api/testcase.yaml b/tests/drivers/adc/adc_api/testcase.yaml index e187756ed03bb..96a24ba22590e 100644 --- a/tests/drivers/adc/adc_api/testcase.yaml +++ b/tests/drivers/adc/adc_api/testcase.yaml @@ -51,3 +51,11 @@ tests: - frdm_k82f integration_platforms: - frdm_k82f + drivers.adc.dma_espressif: + extra_args: + - OVERLAY_CONFIG="overlay-dma-esp32.conf" + depends_on: + - adc + - dma + platform_allow: + - esp32s3_devkitc/esp32s3/procpu From 6cecdb1e145f849861feb74b8c5ca66be129c70d Mon Sep 17 00:00:00 2001 From: Adrien MARTIN Date: Wed, 22 May 2024 11:20:07 +0200 Subject: [PATCH 2122/2849] boards: silabs: efr32xg24_dk2601: fix flash partitions labels mismatch This commit fix the mismatch between flash partition labels and node roles on the efr32xg24_dk2601 board. Signed-off-by: Adrien MARTIN --- boards/silabs/efr32xg24_dk2601b/efr32xg24_dk2601b.dts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/boards/silabs/efr32xg24_dk2601b/efr32xg24_dk2601b.dts b/boards/silabs/efr32xg24_dk2601b/efr32xg24_dk2601b.dts index ffa883da6f9e6..dc0561a75dfa2 100644 --- a/boards/silabs/efr32xg24_dk2601b/efr32xg24_dk2601b.dts +++ b/boards/silabs/efr32xg24_dk2601b/efr32xg24_dk2601b.dts @@ -146,25 +146,25 @@ /* Reserve 464 kB for the application in slot 0 */ slot0_partition: partition@c000 { - label = "storage"; + label = "image-0"; reg = <0x0000c000 0x00074000>; }; /* Reserve 464 kB for the application in slot 1 */ slot1_partition: partition@80000 { - label = "image-0"; + label = "image-1"; reg = <0x00080000 0x00074000>; }; /* Reserve 32 kB for the scratch partition */ scratch_partition: partition@f4000 { - label = "image-1"; + label = "image-scratch"; reg = <0x000f4000 0x00008000>; }; /* Set 528Kb of storage at the end of the 1024Kb of flash */ storage_partition: partition@fc000 { - label = "image-scratch"; + label = "storage"; reg = <0x000fc000 0x00084000>; }; }; From d12044dec500b278d629e6eed1221204c36a6fc7 Mon Sep 17 00:00:00 2001 From: Arunmani Alagarsamy Date: Wed, 22 May 2024 13:03:12 +0530 Subject: [PATCH 2123/2849] boards: silabs: efr32_radio: Add USART pinctrl configuration node this commit introduces a usart pinctrl node to enable the spi functionality in the efr32_radio board. the location* properties have been deprecated so pinctrl support has been added in the device tree included file. Before this commit (using deprecated location properties): - usart@40010400 (DISABLED) After this commit (using pinctrl properties): - usart@40010400 (READY) Signed-off-by: Arunmani Alagarsamy --- .../efr32_radio/efr32_radio-pinctrl.dtsi | 22 +++++++++++++++++++ boards/silabs/efr32_radio/efr32_radio.dtsi | 5 ++--- .../efr32_radio_efr32mg12p432f1024gl125.dts | 10 +++++++++ 3 files changed, 34 insertions(+), 3 deletions(-) diff --git a/boards/silabs/efr32_radio/efr32_radio-pinctrl.dtsi b/boards/silabs/efr32_radio/efr32_radio-pinctrl.dtsi index ade31fddfd824..bb8f7802e6adc 100644 --- a/boards/silabs/efr32_radio/efr32_radio-pinctrl.dtsi +++ b/boards/silabs/efr32_radio/efr32_radio-pinctrl.dtsi @@ -16,4 +16,26 @@ ; }; }; + + usart1_default: usart1_default { + group1 { + psels = , + , + , + , + , + ; + }; + }; + + usart2_default: usart2_default { + group1 { + psels = , + , + , + , + , + ; + }; + }; }; diff --git a/boards/silabs/efr32_radio/efr32_radio.dtsi b/boards/silabs/efr32_radio/efr32_radio.dtsi index b70e1419fbc4a..66902027202bc 100644 --- a/boards/silabs/efr32_radio/efr32_radio.dtsi +++ b/boards/silabs/efr32_radio/efr32_radio.dtsi @@ -68,9 +68,8 @@ #address-cells = <1>; #size-cells = <0>; - location-rx = ; - location-tx = ; - location-clk = ; + pinctrl-0 = <&usart1_default>; + pinctrl-names = "default"; cs-gpios = <&gpioa 4 GPIO_ACTIVE_LOW>; diff --git a/boards/silabs/efr32_radio/efr32_radio_efr32mg12p432f1024gl125.dts b/boards/silabs/efr32_radio/efr32_radio_efr32mg12p432f1024gl125.dts index fd2baf0e87a01..f69a84cc414a6 100644 --- a/boards/silabs/efr32_radio/efr32_radio_efr32mg12p432f1024gl125.dts +++ b/boards/silabs/efr32_radio/efr32_radio_efr32mg12p432f1024gl125.dts @@ -68,6 +68,16 @@ }; }; +&usart2 { + compatible = "silabs,gecko-spi-usart"; + #address-cells = <1>; + #size-cells = <0>; + pinctrl-0 = <&usart2_default>; + pinctrl-names = "default"; + cs-gpios = <&gpioa 9 GPIO_ACTIVE_LOW>; + status = "okay"; +}; + &i2c0 { pinctrl-0 = <&i2c0_default>; pinctrl-names = "default"; From d99c4bdc46da847ab9316d6f0d797e959300740f Mon Sep 17 00:00:00 2001 From: Ali Hozhabri Date: Fri, 1 Mar 2024 17:41:09 +0100 Subject: [PATCH 2124/2849] include: drivers: bluetooth: Introduce BlueNRG reset API Introduce BlueNRG reset API for ST HCI SPI BT driver. Signed-off-by: Ali Hozhabri --- .../drivers/bluetooth/hci_driver_bluenrg.h | 47 +++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 include/zephyr/drivers/bluetooth/hci_driver_bluenrg.h diff --git a/include/zephyr/drivers/bluetooth/hci_driver_bluenrg.h b/include/zephyr/drivers/bluetooth/hci_driver_bluenrg.h new file mode 100644 index 0000000000000..d65b93c586a75 --- /dev/null +++ b/include/zephyr/drivers/bluetooth/hci_driver_bluenrg.h @@ -0,0 +1,47 @@ +/** @file + * @brief BlueNRG HCI extended API. + */ + +/* + * Copyright (c) 2024 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ +#ifndef ZEPHYR_INCLUDE_DRIVERS_BLUETOOTH_HCI_DRIVER_BLUENRG_H_ +#define ZEPHYR_INCLUDE_DRIVERS_BLUETOOTH_HCI_DRIVER_BLUENRG_H_ + +/** + * @brief BlueNRG HCI Driver-Specific API + * @defgroup bluenrg_hci_driver BlueNRG HCI driver extended API + * @ingroup bluetooth + * @{ + */ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** @brief Hardware reset the BlueNRG network coprocessor. + * + * Performs hardware reset of the BLE network coprocessor. + * It can also force to enter firmware updater mode. + * + * @param updater_mode flag to indicate whether updater mode needs to be entered. + * + * @return a non-negative value indicating success, or a + * negative error code for failure + */ + +int bluenrg_bt_reset(bool updater_mode); + +#ifdef __cplusplus +} +#endif + +/** + * @} + */ + +#endif /* ZEPHYR_INCLUDE_DRIVERS_BLUETOOTH_HCI_DRIVER_BLUENRG_H_ */ From 569183bbad3c770d3187aa17332365e864d88081 Mon Sep 17 00:00:00 2001 From: Ali Hozhabri Date: Thu, 14 Mar 2024 18:48:01 +0100 Subject: [PATCH 2125/2849] drivers: bluetooth: hci: Add BlueNRG reset API to ST HCI SPI BT driver Add API to perform hardware reset optionally entering firmware updater mode. Remove redundant declaration for bt_spi_send_aci_config; otherwise, we will have compiler warning if CONFIG_BT_BLUENRG_ACI is not set. Signed-off-by: Ali Hozhabri --- drivers/bluetooth/hci/hci_spi_st.c | 50 +++++++++++++++++++++++++++--- 1 file changed, 45 insertions(+), 5 deletions(-) diff --git a/drivers/bluetooth/hci/hci_spi_st.c b/drivers/bluetooth/hci/hci_spi_st.c index d45dbb592a1e8..d4b964ba21c68 100644 --- a/drivers/bluetooth/hci/hci_spi_st.c +++ b/drivers/bluetooth/hci/hci_spi_st.c @@ -38,7 +38,7 @@ LOG_MODULE_REGISTER(bt_driver); #define READY_NOW 0x02 #define EVT_BLUE_INITIALIZED 0x01 - +#define FW_STARTED_PROPERLY 0X01 /* Offsets */ #define STATUS_HEADER_READY 0 #define STATUS_HEADER_TOREAD 3 @@ -51,6 +51,7 @@ LOG_MODULE_REGISTER(bt_driver); #define EVT_LE_META_SUBEVENT 3 #define EVT_VENDOR_CODE_LSB 3 #define EVT_VENDOR_CODE_MSB 4 +#define REASON_CODE 5 #define CMD_OGF 1 #define CMD_OCF 2 @@ -89,8 +90,6 @@ static struct k_thread spi_rx_thread_data; #define BLUENRG_CONFIG_LL_ONLY_OFFSET 0x2C #define BLUENRG_CONFIG_LL_ONLY_LEN 0x01 -static int bt_spi_send_aci_config(uint8_t offset, const uint8_t *value, size_t value_len); - static const struct spi_dt_spec bus = SPI_DT_SPEC_INST_GET( 0, SPI_OP_MODE_MASTER | SPI_TRANSFER_MSB | SPI_WORD_SET(8) | SPI_LOCK_ON, 0); @@ -110,6 +109,43 @@ struct bt_hci_ext_evt_hdr { uint16_t len; } __packed; +int bluenrg_bt_reset(bool updater_mode) +{ + int err = 0; + /* Assert reset */ + if (!updater_mode) { + gpio_pin_set_dt(&rst_gpio, 1); + k_sleep(K_MSEC(DT_INST_PROP_OR(0, reset_assert_duration_ms, 0))); + gpio_pin_set_dt(&rst_gpio, 0); + } else { +#if DT_HAS_COMPAT_STATUS_OKAY(st_hci_spi_v2) + return -ENOTSUP; +#else /* DT_HAS_COMPAT_STATUS_OKAY(st_hci_spi_v1) */ + gpio_pin_set_dt(&rst_gpio, 1); + gpio_pin_interrupt_configure_dt(&irq_gpio, GPIO_INT_DISABLE); + /* Configure IRQ pin as output and force it high */ + err = gpio_pin_configure_dt(&irq_gpio, GPIO_OUTPUT_ACTIVE); + if (err) { + return err; + } + /* Add reset delay and release reset */ + k_sleep(K_MSEC(DT_INST_PROP_OR(0, reset_assert_duration_ms, 0))); + gpio_pin_set_dt(&rst_gpio, 0); + /* Give firmware some time to read the IRQ high */ + k_sleep(K_MSEC(5)); + gpio_pin_interrupt_configure_dt(&irq_gpio, GPIO_INT_EDGE_TO_ACTIVE); + /* Reconfigure IRQ pin as input */ + err = gpio_pin_configure_dt(&irq_gpio, GPIO_INPUT); + if (err) { + return err; + } + /* Emulate possibly missed rising edge IRQ by signaling the IRQ semaphore */ + k_sem_give(&sem_request); +#endif /* DT_HAS_COMPAT_STATUS_OKAY(st_hci_spi_v2) */ + } + return err; +} + static inline int bt_spi_transceive(void *tx, uint32_t tx_len, void *rx, uint32_t rx_len) { @@ -142,13 +178,17 @@ static void bt_spi_isr(const struct device *unused1, static bool bt_spi_handle_vendor_evt(uint8_t *msg) { bool handled = false; + uint8_t reset_reason; switch (bt_spi_get_evt(msg)) { case EVT_BLUE_INITIALIZED: { - k_sem_give(&sem_initialised); + reset_reason = msg[REASON_CODE]; + if (reset_reason == FW_STARTED_PROPERLY) { + k_sem_give(&sem_initialised); #if defined(CONFIG_BT_BLUENRG_ACI) - handled = true; + handled = true; #endif + } } default: break; From d500a3f35cc89ef17f0b104caf3f9c25d791b8d8 Mon Sep 17 00:00:00 2001 From: Ali Hozhabri Date: Thu, 14 Mar 2024 17:28:15 +0100 Subject: [PATCH 2126/2849] samples: boards: stm32: Add a sample to support ST BlueNRG GUI app Introduce a sample for BlueNRG-based devices to support interaction with ST BlueNRG GUI application based on U(S)ART protocol. Signed-off-by: Ali Hozhabri --- .../bluetooth/interactive_gui/CMakeLists.txt | 8 + .../bluetooth/interactive_gui/README.rst | 37 ++ .../stm32/bluetooth/interactive_gui/prj.conf | 15 + .../bluetooth/interactive_gui/sample.yaml | 12 + .../bluetooth/interactive_gui/src/main.c | 462 ++++++++++++++++++ 5 files changed, 534 insertions(+) create mode 100644 samples/boards/stm32/bluetooth/interactive_gui/CMakeLists.txt create mode 100644 samples/boards/stm32/bluetooth/interactive_gui/README.rst create mode 100644 samples/boards/stm32/bluetooth/interactive_gui/prj.conf create mode 100644 samples/boards/stm32/bluetooth/interactive_gui/sample.yaml create mode 100644 samples/boards/stm32/bluetooth/interactive_gui/src/main.c diff --git a/samples/boards/stm32/bluetooth/interactive_gui/CMakeLists.txt b/samples/boards/stm32/bluetooth/interactive_gui/CMakeLists.txt new file mode 100644 index 0000000000000..37dc403fcca8a --- /dev/null +++ b/samples/boards/stm32/bluetooth/interactive_gui/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(st_interactive_gui) + +target_sources(app PRIVATE src/main.c) diff --git a/samples/boards/stm32/bluetooth/interactive_gui/README.rst b/samples/boards/stm32/bluetooth/interactive_gui/README.rst new file mode 100644 index 0000000000000..e086eec0c8e4e --- /dev/null +++ b/samples/boards/stm32/bluetooth/interactive_gui/README.rst @@ -0,0 +1,37 @@ +.. _samples_boards_stm32_bluetooth_interactive-gui: +.. zephyr:code-sample:: st_bluetooth_interactive_gui + :name: Bluetooth: ST Interactive GUI + :relevant-api: bluenrg_hci_driver bluetooth + +Expose ST BlueNRG Bluetooth network coprocessor over UART + +Overview +********* + +Expose the Bluetooth network coprocessor via UART to a PC to be used +with the ST BlueNRG GUI app. In this case, the main MCU becomes an intermediate level, +and it passes the data between the host (PC) and controller. + +Requirements +************ + +* A board based on BlueNRG BLE module such as :ref:`disco_l475_iot1_board` +* `BlueNRG GUI`_ application installed on your PC + +Default UART settings +********************* + +It depends on the board default settings for ``zephyr,bt-c2h-uart`` DTS property. +The UART default settings are: + +* Baudrate: 115200 bps +* 8 bits, no parity, 1 stop bit + +Building and Running +******************** + +This sample can be found under :zephyr_file:`samples/boards/stm32/bluetooth/interactive_gui` in the +Zephyr tree. + +.. _BlueNRG GUI: + https://www.st.com/en/embedded-software/stsw-bnrgui.html diff --git a/samples/boards/stm32/bluetooth/interactive_gui/prj.conf b/samples/boards/stm32/bluetooth/interactive_gui/prj.conf new file mode 100644 index 0000000000000..74ce94a7cc53d --- /dev/null +++ b/samples/boards/stm32/bluetooth/interactive_gui/prj.conf @@ -0,0 +1,15 @@ +CONFIG_CONSOLE=n +CONFIG_STDOUT_CONSOLE=n +CONFIG_UART_CONSOLE=n +CONFIG_SERIAL=y +CONFIG_UART_INTERRUPT_DRIVEN=y +CONFIG_BT=y +CONFIG_BT_HCI_RAW=y +CONFIG_BT_HCI_RAW_H4=y +CONFIG_BT_HCI_RAW_H4_ENABLE=y +CONFIG_BT_BUF_ACL_RX_SIZE=255 +CONFIG_BT_BUF_CMD_TX_SIZE=255 +CONFIG_BT_BUF_EVT_DISCARDABLE_SIZE=255 +CONFIG_BT_BLUENRG_ACI=n +CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=512 +CONFIG_USB_DEVICE_INITIALIZE_AT_BOOT=y diff --git a/samples/boards/stm32/bluetooth/interactive_gui/sample.yaml b/samples/boards/stm32/bluetooth/interactive_gui/sample.yaml new file mode 100644 index 0000000000000..695c6e93a6f8b --- /dev/null +++ b/samples/boards/stm32/bluetooth/interactive_gui/sample.yaml @@ -0,0 +1,12 @@ +sample: + name: Bluetooth ST Interactive GUI + description: Allows BlueNRG-based boards to connect to BlueNRG GUI application via UART +tests: + sample.boards.stm32.bluetooth.interactive_gui: + harness: bluetooth + platform_allow: + - sensortile_box_pro + - disco_l475_iot1 + tags: + - uart + - bluetooth diff --git a/samples/boards/stm32/bluetooth/interactive_gui/src/main.c b/samples/boards/stm32/bluetooth/interactive_gui/src/main.c new file mode 100644 index 0000000000000..82d008e4d6c9a --- /dev/null +++ b/samples/boards/stm32/bluetooth/interactive_gui/src/main.c @@ -0,0 +1,462 @@ +/* + * Copyright (c) 2024 STMicroelectronics + * Copyright (c) 2016 Nordic Semiconductor ASA + * Copyright (c) 2015-2016 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define LOG_MODULE_NAME gui_hci_uart +LOG_MODULE_REGISTER(LOG_MODULE_NAME); + +static const struct device *const hci_uart_dev = + DEVICE_DT_GET(DT_CHOSEN(zephyr_bt_c2h_uart)); +static K_THREAD_STACK_DEFINE(tx_thread_stack, CONFIG_BT_HCI_TX_STACK_SIZE); +static struct k_thread tx_thread_data; +static K_FIFO_DEFINE(tx_queue); + +/* RX in terms of bluetooth communication */ +static K_FIFO_DEFINE(uart_tx_queue); + +#define H4_ST_EXT_CMD 0x81 +#define H4_ST_VND_CMD 0xFF + +#define ST_IDLE 0 /* Waiting for packet type. */ +#define ST_HDR 1 /* Receiving packet header. */ +#define ST_PAYLOAD 2 /* Receiving packet payload. */ +#define ST_DISCARD 3 /* Dropping packet. */ + +/* Length of a discard/flush buffer. + * This is sized to align with a BLE HCI packet: + * 1 byte H:4 header + 32 bytes ACL/event data + * Bigger values might overflow the stack since this is declared as a local + * variable, smaller ones will force the caller to call into discard more + * often. + */ +#define H4_DISCARD_LEN 33 + +#define RESP_VENDOR_CODE_OFFSET 1 +#define RESP_LEN_OFFSET_LSB 2 +#define RESP_LEN_OFFSET_MSB 3 +#define RESP_CMDCODE_OFFSET 4 +#define RESP_STATUS_OFFSET 5 +#define RESP_PARAM_OFFSET 6 + +/* Types of vendor codes */ +#define VENDOR_CODE_ERROR 0 +#define VENDOR_CODE_RESPONSE 1 + +/* Commands */ +#define VENDOR_CMD_READ_VERSION 0x01 +#define VENDOR_CMD_BLUENRG_RESET 0x04 +#define VENDOR_CMD_HW_BOOTLOADER 0x05 + +struct bt_hci_ext_cmd_hdr { + uint16_t opcode; + uint16_t param_len; +} __packed; + +struct bt_vendor_cmd_hdr { + uint8_t opcode; + uint16_t param_len; +} __packed; + +struct bt_vendor_rsp_hdr { + uint8_t vendor_code; + uint16_t param_len; + uint8_t opcode; + uint8_t status; + uint8_t params[2]; +} __packed; + +static int h4_send(struct net_buf *buf); + +static uint16_t parse_cmd(uint8_t *hci_buffer, uint16_t hci_pckt_len, uint8_t *buffer_out) +{ + uint16_t len = 0; + struct bt_vendor_cmd_hdr *hdr = (struct bt_vendor_cmd_hdr *) hci_buffer; + struct bt_vendor_rsp_hdr *rsp = (struct bt_vendor_rsp_hdr *) (buffer_out + 1); + + buffer_out[0] = H4_ST_VND_CMD; + rsp->vendor_code = VENDOR_CODE_RESPONSE; + rsp->opcode = hdr->opcode; + rsp->status = 0; + + switch (hdr->opcode) { + case VENDOR_CMD_READ_VERSION: + rsp->params[0] = KERNEL_VERSION_MAJOR; + if (KERNEL_PATCHLEVEL >= 9) { + rsp->params[1] = (KERNEL_VERSION_MINOR * 10) + 9; + } else { + rsp->params[1] = (KERNEL_VERSION_MINOR * 10) + KERNEL_PATCHLEVEL; + } + len = 2; + break; +#if DT_HAS_COMPAT_STATUS_OKAY(st_hci_spi_v1) || DT_HAS_COMPAT_STATUS_OKAY(st_hci_spi_v2) + case VENDOR_CMD_BLUENRG_RESET: + bluenrg_bt_reset(0); + break; + case VENDOR_CMD_HW_BOOTLOADER: + bluenrg_bt_reset(1); + break; +#endif /* DT_HAS_COMPAT_STATUS_OKAY(st_hci_spi_v1) || DT_HAS_COMPAT_STATUS_OKAY(st_hci_spi_v2) */ + default: + rsp->vendor_code = VENDOR_CODE_ERROR; + rsp->status = BT_HCI_ERR_UNKNOWN_CMD; + } + + len += 2; /* Status and Command code */ + rsp->param_len = sys_cpu_to_le16(len); + len += RESP_CMDCODE_OFFSET; + + return len; +} + +static int send_evt(uint8_t *response, uint8_t len) +{ + struct net_buf *buf; + + buf = bt_buf_get_rx(BT_BUF_EVT, K_NO_WAIT); + + if (!buf) { + LOG_ERR("EVT no buffer"); + return -ENOMEM; + } + if (len > net_buf_tailroom(buf)) { + LOG_ERR("EVT too long: %d", len); + net_buf_unref(buf); + return -ENOMEM; + } + net_buf_add_mem(buf, response, len); + + return h4_send(buf); +} + +static int h4_read(const struct device *uart, uint8_t *buf, size_t len) +{ + int rx = uart_fifo_read(uart, buf, len); + + LOG_DBG("read %d req %d", rx, len); + return rx; +} + +static bool valid_type(uint8_t type) +{ + return (type == BT_HCI_H4_CMD) | (type == H4_ST_EXT_CMD) | + (type == BT_HCI_H4_ACL) | (type == BT_HCI_H4_ISO) | (type == H4_ST_VND_CMD); +} + +/* Function expects that type is validated and only CMD, ISO or ACL are used. */ +static uint32_t get_len(const uint8_t *hdr_buf, uint8_t type) +{ + switch (type) { + case BT_HCI_H4_CMD: + return ((const struct bt_hci_cmd_hdr *)hdr_buf)->param_len; + case H4_ST_EXT_CMD: + return ((const struct bt_hci_ext_cmd_hdr *)hdr_buf)->param_len; + case H4_ST_VND_CMD: + return ((const struct bt_vendor_cmd_hdr *)hdr_buf)->param_len; + case BT_HCI_H4_ISO: + return bt_iso_hdr_len( + sys_le16_to_cpu(((const struct bt_hci_iso_hdr *)hdr_buf)->len)); + case BT_HCI_H4_ACL: + return sys_le16_to_cpu(((const struct bt_hci_acl_hdr *)hdr_buf)->len); + default: + LOG_ERR("Invalid type: %u", type); + return 0; + } +} + +/* Function expects that type is validated and only CMD, ISO or ACL are used. */ +static int hdr_len(uint8_t type) +{ + switch (type) { + case BT_HCI_H4_CMD: + return sizeof(struct bt_hci_cmd_hdr); + case H4_ST_EXT_CMD: + return sizeof(struct bt_hci_ext_cmd_hdr); + case H4_ST_VND_CMD: + return sizeof(struct bt_vendor_cmd_hdr); + case BT_HCI_H4_ISO: + return sizeof(struct bt_hci_iso_hdr); + case BT_HCI_H4_ACL: + return sizeof(struct bt_hci_acl_hdr); + default: + LOG_ERR("Invalid type: %u", type); + return 0; + } +} + +static struct net_buf *alloc_tx_buf(uint8_t type) +{ + uint8_t alloc_type = type; + struct net_buf *buf; + + switch (type) { + case H4_ST_EXT_CMD: + case BT_HCI_H4_CMD: + case H4_ST_VND_CMD: + alloc_type = BT_HCI_H4_CMD; + break; + case BT_HCI_H4_ISO: + case BT_HCI_H4_ACL: + break; + default: + LOG_ERR("Invalid type: %u", type); + return NULL; + } + buf = bt_buf_get_tx(BT_BUF_H4, K_NO_WAIT, &alloc_type, sizeof(alloc_type)); + if (buf && (type == H4_ST_VND_CMD)) { + bt_buf_set_type(buf, type); + } + return buf; +} + +static void rx_isr(void) +{ + static struct net_buf *buf; + static int remaining; + static uint8_t state; + static uint8_t type; + static uint8_t hdr_buf[MAX(sizeof(struct bt_hci_cmd_hdr), sizeof(struct bt_hci_acl_hdr))]; + int read; + + do { + switch (state) { + case ST_IDLE: + /* Get packet type */ + read = h4_read(hci_uart_dev, &type, sizeof(type)); + /* since we read in loop until no data is in the fifo, + * it is possible that read = 0. + */ + if (read) { + if (valid_type(type)) { + /* Get expected header size and switch + * to receiving header. + */ + remaining = hdr_len(type); + state = ST_HDR; + } else { + LOG_WRN("Unknown header %d", type); + } + } + break; + case ST_HDR: + read = h4_read(hci_uart_dev, &hdr_buf[hdr_len(type) - remaining], + remaining); + remaining -= read; + if (remaining == 0) { + /* Header received. Allocate buffer and get + * payload length. If allocation fails leave + * interrupt. On failed allocation state machine + * is reset. + */ + uint8_t header_length; + + buf = alloc_tx_buf(type); + if (!buf) { + LOG_ERR("No available command buffers!"); + state = ST_IDLE; + return; + } + + remaining = get_len(hdr_buf, type); + header_length = hdr_len(type); + if (type == H4_ST_EXT_CMD) { + /* Convert to regular HCI_CMD */ + if (remaining > 255) { + LOG_ERR("len > 255"); + net_buf_unref(buf); + state = ST_DISCARD; + } else { + header_length--; + } + } + net_buf_add_mem(buf, hdr_buf, header_length); + if (remaining > net_buf_tailroom(buf)) { + LOG_ERR("Not enough space in buffer"); + net_buf_unref(buf); + state = ST_DISCARD; + } else { + state = ST_PAYLOAD; + } + + } + break; + case ST_PAYLOAD: + read = h4_read(hci_uart_dev, net_buf_tail(buf), remaining); + buf->len += read; + remaining -= read; + if (remaining == 0) { + /* Packet received */ + LOG_DBG("putting RX packet in queue."); + net_buf_put(&tx_queue, buf); + state = ST_IDLE; + } + break; + case ST_DISCARD: + uint8_t discard[H4_DISCARD_LEN]; + size_t to_read = MIN(remaining, sizeof(discard)); + + read = h4_read(hci_uart_dev, discard, to_read); + remaining -= read; + if (remaining == 0) { + state = ST_IDLE; + } + break; + default: + read = 0; + __ASSERT_NO_MSG(0); + break; + + } + } while (read); +} + +static void tx_isr(void) +{ + static struct net_buf *buf; + int len; + + if (!buf) { + buf = net_buf_get(&uart_tx_queue, K_NO_WAIT); + if (!buf) { + uart_irq_tx_disable(hci_uart_dev); + return; + } + } + len = uart_fifo_fill(hci_uart_dev, buf->data, buf->len); + net_buf_pull(buf, len); + if (!buf->len) { + net_buf_unref(buf); + buf = NULL; + } +} + +static void bt_uart_isr(const struct device *unused, void *user_data) +{ + ARG_UNUSED(unused); + ARG_UNUSED(user_data); + + if (!(uart_irq_rx_ready(hci_uart_dev) || uart_irq_tx_ready(hci_uart_dev))) { + LOG_DBG("spurious interrupt"); + } + if (uart_irq_tx_ready(hci_uart_dev)) { + tx_isr(); + } + if (uart_irq_rx_ready(hci_uart_dev)) { + rx_isr(); + } +} + +static void tx_thread(void *p1, void *p2, void *p3) +{ + enum bt_buf_type buf_type; + + while (1) { + struct net_buf *buf; + int err = 0; + uint8_t len; + uint8_t response[16]; + + /* Wait until a buffer is available */ + buf = net_buf_get(&tx_queue, K_FOREVER); + buf_type = bt_buf_get_type(buf); + if (buf_type == H4_ST_VND_CMD) { + len = parse_cmd(buf->data, buf->len, response); + err = send_evt(response, len); + if (!err) { + net_buf_unref(buf); + } + } else { + /* Pass buffer to the stack */ + err = bt_send(buf); + } + if (err) { + LOG_ERR("Unable to send (err %d)", err); + net_buf_unref(buf); + } + + /* Give other threads a chance to run if tx_queue keeps getting + * new data all the time. + */ + k_yield(); + } +} + +static int h4_send(struct net_buf *buf) +{ + LOG_DBG("buf %p type %u len %u", buf, bt_buf_get_type(buf), buf->len); + net_buf_put(&uart_tx_queue, buf); + uart_irq_tx_enable(hci_uart_dev); + return 0; +} + +static int hci_uart_init(void) +{ + LOG_DBG(""); + if (!device_is_ready(hci_uart_dev)) { + LOG_ERR("HCI UART %s is not ready", hci_uart_dev->name); + return -EINVAL; + } + uart_irq_rx_disable(hci_uart_dev); + uart_irq_tx_disable(hci_uart_dev); + uart_irq_callback_set(hci_uart_dev, bt_uart_isr); + uart_irq_rx_enable(hci_uart_dev); + return 0; +} + +int main(void) +{ + /* incoming events and data from the controller */ + static K_FIFO_DEFINE(rx_queue); + int err; + + LOG_DBG("Start"); + __ASSERT(hci_uart_dev, "UART device is NULL"); + + /* Enable the raw interface, this will in turn open the HCI driver */ + bt_enable_raw(&rx_queue); + /* Spawn the TX thread and start feeding commands and data to the controller */ + k_thread_create(&tx_thread_data, tx_thread_stack, + K_THREAD_STACK_SIZEOF(tx_thread_stack), tx_thread, + NULL, NULL, NULL, K_PRIO_COOP(7), 0, K_NO_WAIT); + k_thread_name_set(&tx_thread_data, "HCI uart TX"); + + while (1) { + struct net_buf *buf; + + buf = net_buf_get(&rx_queue, K_FOREVER); + err = h4_send(buf); + if (err) { + LOG_ERR("Failed to send"); + } + } + return 0; +} + +SYS_INIT(hci_uart_init, APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEVICE); From f15a2e8ca81371c97d85285eaf0add3ec5a0c280 Mon Sep 17 00:00:00 2001 From: Tomasz Chyrowicz Date: Wed, 5 Jun 2024 16:13:44 +0200 Subject: [PATCH 2127/2849] scripts: nrf_common: Handle SUIT artifacts Handle MPI and root manifest for radio core separately from the main build system logic. Signed-off-by: Tomasz Chyrowicz --- scripts/ci/check_compliance.py | 3 +++ scripts/west_commands/runners/core.py | 30 +++++++++++++++++++-- scripts/west_commands/runners/nrf_common.py | 23 ++++++++++++++++ 3 files changed, 54 insertions(+), 2 deletions(-) diff --git a/scripts/ci/check_compliance.py b/scripts/ci/check_compliance.py index 090559e204923..5ae142f033239 100755 --- a/scripts/ci/check_compliance.py +++ b/scripts/ci/check_compliance.py @@ -943,6 +943,9 @@ def check_no_undef_outside_kconfig(self, kconf): "ZEPHYR_TRY_MASS_ERASE", # MCUBoot setting described in sysbuild # documentation "ZTEST_FAIL_TEST_", # regex in tests/ztest/fail/CMakeLists.txt + "SUIT_MPI_GENERATE", # Used by nRF runners to program provisioning data, based on build configuration + "SUIT_MPI_APP_AREA_PATH", # Used by nRF runners to program provisioning data, based on build configuration + "SUIT_MPI_RAD_AREA_PATH", # Used by nRF runners to program provisioning data, based on build configuration } diff --git a/scripts/west_commands/runners/core.py b/scripts/west_commands/runners/core.py index f411f56cad3ed..10e740a4230f8 100644 --- a/scripts/west_commands/runners/core.py +++ b/scripts/west_commands/runners/core.py @@ -130,6 +130,8 @@ class BuildConfiguration: Kconfig configuration values are available (parsed from .config).''' + config_prefix = 'CONFIG' + def __init__(self, build_dir: str): self.build_dir = build_dir self.options: Dict[str, Union[str, int]] = {} @@ -153,8 +155,9 @@ def getboolean(self, option): def _parse(self): filename = self.path - opt_value = re.compile('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 literal 0 HcmV?d00001 diff --git a/boards/adi/apard32690/doc/index.rst b/boards/adi/apard32690/doc/index.rst new file mode 100644 index 0000000000000..78e39723ed6f2 --- /dev/null +++ b/boards/adi/apard32690/doc/index.rst @@ -0,0 +1,216 @@ +.. _ad_apard32690_sl: + +AD-APARD32690-SL +################ + +Overview +******** +The AD-APARD32690-SL is a platform for prototyping intelligent, secure, and connected field devices. +It has an Arduino Mega-compatible form factor and two Pmod-compatible connectors. +The system includes the MAX32690 ARM Cortex-M4 with FPU-Based Microcontroller and Bluetooth LE 5.2. +The MCU is coupled with external RAM (2 x 512 Mb) and Flash (64 Mb) memories to meet the requirements +of the most demanding applications. The MAXQ1065 security coprocessor enables state of the art +security features such as for root-of-trust, mutual authentication, data confidentiality and +integrity, secure boot, and secure communications. +A 10 Mbps single-pair Ethernet link using the ADIN1110 10BASE-T1L MAC/PHY, enables remote +data acquisition and system configuration. The 10BASE-T1L interface also supports Single-pair +Power over Ethernet (SPoE) and be used for powering the system via an Arduino shield implementing +the required power circuitry. + +The Zephyr port is running on the MAX32690 MCU. + +.. image:: img/apard32690_img.webp + :align: center + :alt: AD-APARD32690-SL Front + +Hardware +******** + +- MAX32690 MCU: + + - Ultra-Efficient Microcontroller for Battery-Powered Applications + + - 120MHz Arm Cortex-M4 Processor with FPU + - 7.3728MHz and 60MHz Low-Power Oscillators + - External Crystal Support (32MHz required for BLE) + - 32.768kHz RTC Clock (Requires External Crystal) + - 8kHz Always-On Ultra-Low Power Oscillator + - 3MB Internal Flash, 1MB Internal SRAM (832kB ECC ON) + - TBDμW/MHz Executing from Cache at 1.1V + - 1.8V and 3.3V I/O with No Level Translators + - External Flash & SRAM Expansion Interfaces + + - Bluetooth 5.2 LE Radio + + - Dedicated, Ultra-Low-Power, 32-Bit RISC-V Coprocessor to Offload Timing-Critical Bluetooth Processing + - Fully Open-Source Bluetooth 5.2 Stack Available + - Supports AoA, AoD, LE Audio, and Mesh + - High-Throughput (2Mbps) Mode + - Long-Range (125kbps and 500kbps) Modes + - Rx Sensitivity: -97.5dBm; Tx Power: +4.5dBm + - Single-Ended Antenna Connection (50Ω) + + - Multiple Peripherals for System Control + + - 16-Channel DMA + - Up To Five Quad SPI Master (60MHz)/Slave (48MHz) + - Up To Four 1Mbaud UARTs with Flow Control + - Up To Two 1MHz I2C Master/Slave + - I2S Master/Slave + - Eight External Channel, 12-bit 1MSPS SAR ADC w/ on-die temperature sensor + - USB 2.0 Hi-Speed Device + - 16 Pulse Train Engines + - Up To Six 32-Bit Timers with 8mA High Drive + - Up To Two CAN 2.0 Controllers + - Up To Four Micro-Power Comparators + - 1-Wire Master + + - Security and Integrity + + - ChipDNA Physically Un-clonable Function (PUF) + - Modular Arithmetic Accelerator (MAA), True Random Number Generator (TRNG) + - Secure Nonvolatile Key Storage, SHA-256, AES-128/192/256 + - Secure Boot ROM + +- External devices connected to the APARD32690: + + - On-Board HyperRAM + - On-Board SPI Flash + - USB 2.0 Type-C interface to the MAX32690 + - SPI PMOD connector + - I2C PMOD connector + - SWD 10-Pin Header + - On-Board Bluetooth 5.2 LE Radio antenna + - MAXQ1065 Ultralow Power Cryptographic Controller with ChipDNA + - ADIN1110 Robust, Industrial, Low Power 10BASE-T1L Ethernet MAC-PHY + - U-Blox NINA-W102 802.11b/g/n module with dual-mode Bluetooth v4.2 + - On-Board 5V, 3.3V, 1.8V, and 1.1V voltage regulators + - 2-Pin external power supply terminal block (5V - 28V DC) + - Board Power Provided by either the USB Port or the 2-Pin connector + - Arduino Mega compatible header. + - Two general-purpose LEDs and one general purpose push button. + + +Supported Features +================== + +Below interfaces are supported by Zephyr on APARD32690. + ++-----------+------------+------------------------------------+ +| Interface | Controller | Driver/Component | ++===========+============+====================================+ +| NVIC | on-chip | nested vector interrupt controller | ++-----------+------------+------------------------------------+ +| SYSTICK | on-chip | systick | ++-----------+------------+------------------------------------+ +| CLOCK | on-chip | clock and reset control | ++-----------+------------+------------------------------------+ +| GPIO | on-chip | gpio | ++-----------+------------+------------------------------------+ +| UART | on-chip | serial | ++-----------+------------+------------------------------------+ +| SPI | on-chip | spi | ++-----------+------------+------------------------------------+ +| ADIN1110 | spi | ADIN1110 10BASE-T1L mac/phy | ++-----------+------------+------------------------------------+ + + +Connections and IOs +=================== + ++-----------+---------------+---------------+--------------------------------------------------------------------------------------------------+ +| Name | Name | Settings | Description | ++===========+===============+===============+==================================================================================================+ +| P55 | SWD TX | | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | 1-2 | | | Connects the SWD UART TX to the (UART) RX port of the U-Blox Nina W102. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | 2-3 | | | Connects the SWD UART TX to the UART0 TX pin of the MAX32690. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | | ++-----------+---------------+---------------+--------------------------------------------------------------------------------------------------+ +| P50 | SWD RX | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | 1-2 | | | Connects the SWD UART RX to the (UART) TX port of the U-Blox Nina W102. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | 2-3 | | | Connects the SWD UART RX to the UART0 RX pin of the MAX32690. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | | ++-----------+---------------+---------------+--------------------------------------------------------------------------------------------------+ +| P51 | SWD POW | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | 1-2 | | | Connects the SWD Vcc pin to 3.3V. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | 2-3 | | | Connects the SWD Vcc pin to 1.8V. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | | ++-----------+---------------+---------------+--------------------------------------------------------------------------------------------------+ +| P38 | UART RX WIFI | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | 1-2 | | | Connect the U-Blox Nina W102 UART RX to the UART2A TX pin of the MAX32690 | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | Open | | | Disconnects the U-Blox Nina W102 UART RX from the UART2A TX pin | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | | ++-----------+---------------+---------------+--------------------------------------------------------------------------------------------------+ +| P58 | UART TX WIFI | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | 1-2 | | | Connect the U-Blox Nina W102 UART TX to the UART2A RX pin of the MAX32690. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | Open | | | Disconnects the U-Blox Nina W102 UART TX from the UART2A RX pin. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | | ++-----------+---------------+---------------+--------------------------------------------------------------------------------------------------+ +| S4 | SW1 | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | On | | | Pulls the ADIN1110's SWPD_EN pin to 3.3V through a resistor. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | Off | | | Leaves the ADIN1110's SWPD_EN pin floating. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | | ++-----------+---------------+---------------+--------------------------------------------------------------------------------------------------+ +| S4 | SW2 | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | On | | | Pulls the ADIN1110's CFG0 pin to 3.3V through a resistor. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | Off | | | Leaves the ADIN1110's CFG0 pin floating. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | | ++-----------+---------------+---------------+--------------------------------------------------------------------------------------------------+ +| S4 | SW3 | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | On | | | Pulls the ADIN1110's CFG1 pin to 3.3V through a resistor. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | Off | | | Leaves the ADIN1110's CFG1 pin floating. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | | ++-----------+---------------+---------------+--------------------------------------------------------------------------------------------------+ + + +Programming and Debugging +************************* + +Flashing +======== + +The MAX32690 MCU can be flashed by connecting an external debug probe to the +SWD port. SWD debug can be accessed through the Cortex 10-pin connector, P9. +Logic levels are either 1.8V or 3.3V (based on P51 selection). + +Once the debug probe is connected to your host computer, then you can simply run the +``west flash`` command to write a firmware image into flash. + +.. note:: + + This board uses OpenOCD as the default debug interface. You can also use + a Segger J-Link with Segger's native tooling by overriding the runner, + appending ``--runner jlink`` to your ``west`` command(s). The J-Link should + be connected to the standard 2*5 pin debug connector (P9) using an + appropriate adapter board and cable. + +Debugging +========= + +Please refer to the `Flashing`_ section and run the ``west debug`` command +instead of ``west flash``. + +References +********** + +- `AD-APARD32690-SL web page`_ + +.. _AD-APARD32690-SL web page: + https://www.analog.com/en/resources/evaluation-hardware-and-software/evaluation-boards-kits/ad-apard32690-sl.html From c0c51a8d40c28254c059474c30fdd4b275b4abdb Mon Sep 17 00:00:00 2001 From: Jamie McCrae Date: Thu, 6 Jun 2024 14:28:46 +0100 Subject: [PATCH 2582/2849] scripts: west: flash: Fix issue with loading outdated domain file Fixes an issue whereby the domains file in sysbuild projects would be loaded and used with outdated information if sysbuild configuration was changed then west flash was ran directly after it Signed-off-by: Jamie McCrae --- scripts/west_commands/flash.py | 8 ++++---- scripts/west_commands/run_common.py | 7 +++++-- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/scripts/west_commands/flash.py b/scripts/west_commands/flash.py index 4f173535be886..484c5b3c65fb5 100644 --- a/scripts/west_commands/flash.py +++ b/scripts/west_commands/flash.py @@ -9,7 +9,8 @@ from west.commands import WestCommand from run_common import add_parser_common, do_run_common, get_build_dir -from build_helpers import load_domains + +from pathlib import Path class Flash(WestCommand): @@ -28,6 +29,5 @@ def do_add_parser(self, parser_adder): def do_run(self, my_args, runner_args): build_dir = get_build_dir(my_args) - domains = load_domains(build_dir).get_domains(my_args.domain, - default_flash_order=True) - do_run_common(self, my_args, runner_args, domains=domains) + domains_file = Path(build_dir) / 'domains.yaml' + do_run_common(self, my_args, runner_args, domain_file=domains_file) diff --git a/scripts/west_commands/run_common.py b/scripts/west_commands/run_common.py index 7cd30c86fe6f7..fd8a85749ea37 100644 --- a/scripts/west_commands/run_common.py +++ b/scripts/west_commands/run_common.py @@ -161,7 +161,7 @@ def add_parser_common(command, parser_adder=None, parser=None): return parser -def do_run_common(command, user_args, user_runner_args, domains=None): +def do_run_common(command, user_args, user_runner_args, domain_file=None): # This is the main routine for all the "west flash", "west debug", # etc. commands. @@ -186,7 +186,7 @@ def do_run_common(command, user_args, user_runner_args, domains=None): if not user_args.skip_rebuild: rebuild(command, build_dir, user_args) - if domains is None: + if domain_file is None: if user_args.domain is None: # No domains are passed down and no domains specified by the user. # So default domain will be used. @@ -195,6 +195,9 @@ def do_run_common(command, user_args, user_runner_args, domains=None): # No domains are passed down, but user has specified domains to use. # Get the user specified domains. domains = load_domains(build_dir).get_domains(user_args.domain) + else: + domains = load_domains(build_dir).get_domains(user_args.domain, + default_flash_order=True) if len(domains) > 1: if len(user_runner_args) > 0: From 57be8588461b7e962b465ea7be705661e3e35f58 Mon Sep 17 00:00:00 2001 From: Ping Wang Date: Mon, 10 Jun 2024 09:03:09 +0200 Subject: [PATCH 2583/2849] Bluetooth: audio: BAP Broadcast Assistant support for multiple connections The current implementation of the BAP Broadcast Assistant only supports a single connection. This PR makes broadcast assistant support multiple BAP scan delegators. Fixes: #67523 Signed-off-by: Ping Wang --- .../bluetooth/audio/bap_broadcast_assistant.c | 396 ++++++++++++------ 1 file changed, 264 insertions(+), 132 deletions(-) diff --git a/subsys/bluetooth/audio/bap_broadcast_assistant.c b/subsys/bluetooth/audio/bap_broadcast_assistant.c index be73351f5459e..d193e36c34ea9 100644 --- a/subsys/bluetooth/audio/bap_broadcast_assistant.c +++ b/subsys/bluetooth/audio/bap_broadcast_assistant.c @@ -90,16 +90,17 @@ struct bap_broadcast_assistant_instance { static sys_slist_t broadcast_assistant_cbs = SYS_SLIST_STATIC_INIT(&broadcast_assistant_cbs); -static struct bap_broadcast_assistant_instance broadcast_assistant; +static struct bap_broadcast_assistant_instance broadcast_assistants[CONFIG_BT_MAX_CONN]; static struct bt_uuid_16 uuid = BT_UUID_INIT_16(0); #define ATT_BUF_SIZE BT_ATT_MAX_ATTRIBUTE_LEN NET_BUF_SIMPLE_DEFINE_STATIC(att_buf, ATT_BUF_SIZE); -static int16_t lookup_index_by_handle(uint16_t handle) +static int16_t lookup_index_by_handle(struct bap_broadcast_assistant_instance *inst, + uint16_t handle) { - for (size_t i = 0U; i < ARRAY_SIZE(broadcast_assistant.recv_state_handles); i++) { - if (broadcast_assistant.recv_state_handles[i] == handle) { + for (size_t i = 0U; i < ARRAY_SIZE(inst->recv_state_handles); i++) { + if (inst->recv_state_handles[i] == handle) { return i; } } @@ -109,6 +110,24 @@ static int16_t lookup_index_by_handle(uint16_t handle) return -1; } +static struct bap_broadcast_assistant_instance *inst_by_conn(struct bt_conn *conn) +{ + struct bap_broadcast_assistant_instance *inst; + + if (conn == NULL) { + LOG_DBG("NULL conn"); + return NULL; + } + + inst = &broadcast_assistants[bt_conn_index(conn)]; + + if (inst->conn == conn) { + return inst; + } + + return NULL; +} + static void bap_broadcast_assistant_discover_complete(struct bt_conn *conn, int err, uint8_t recv_state_count) { @@ -275,10 +294,10 @@ static int parse_recv_state(const void *data, uint16_t length, return 0; } -static void bap_long_op_reset(void) +static void bap_long_op_reset(struct bap_broadcast_assistant_instance *inst) { - broadcast_assistant.busy = false; - broadcast_assistant.long_read_handle = 0; + inst->busy = false; + inst->long_read_handle = 0; net_buf_simple_reset(&att_buf); } @@ -288,6 +307,11 @@ static uint8_t parse_and_send_recv_state(struct bt_conn *conn, uint16_t handle, { int err; int16_t index; + struct bap_broadcast_assistant_instance *inst = inst_by_conn(conn); + + if (inst == NULL) { + return BT_GATT_ITER_STOP; + } err = parse_recv_state(data, length, recv_state); if (err != 0) { @@ -296,17 +320,16 @@ static uint8_t parse_and_send_recv_state(struct bt_conn *conn, uint16_t handle, return BT_GATT_ITER_STOP; } - index = lookup_index_by_handle(handle); + index = lookup_index_by_handle(inst, handle); if (index < 0) { LOG_DBG("Invalid index"); return BT_GATT_ITER_STOP; } - broadcast_assistant.recv_states[index].src_id = recv_state->src_id; - broadcast_assistant.recv_states[index].past_avail = past_available(conn, - &recv_state->addr, - recv_state->adv_sid); + inst->recv_states[index].src_id = recv_state->src_id; + inst->recv_states[index].past_avail = past_available(conn, &recv_state->addr, + recv_state->adv_sid); bap_broadcast_assistant_recv_state_changed(conn, 0, recv_state); @@ -320,13 +343,18 @@ static uint8_t broadcast_assistant_bap_ntf_read_func(struct bt_conn *conn, uint8 struct bt_bap_scan_delegator_recv_state recv_state; uint16_t handle = read->single.handle; uint16_t data_length; + struct bap_broadcast_assistant_instance *inst = inst_by_conn(conn); + + if (inst == NULL) { + return BT_GATT_ITER_STOP; + } LOG_DBG("conn %p err 0x%02x len %u", conn, err, length); if (err) { LOG_DBG("Failed to read: %u", err); memset(read, 0, sizeof(*read)); - bap_long_op_reset(); + bap_long_op_reset(inst); return BT_GATT_ITER_STOP; } @@ -338,7 +366,7 @@ static uint8_t broadcast_assistant_bap_ntf_read_func(struct bt_conn *conn, uint8 LOG_DBG("Buffer full, invalid server response of size %u", length + att_buf.len); memset(read, 0, sizeof(*read)); - bap_long_op_reset(); + bap_long_op_reset(inst); return BT_GATT_ITER_STOP; } @@ -352,7 +380,7 @@ static uint8_t broadcast_assistant_bap_ntf_read_func(struct bt_conn *conn, uint8 /* we reset the buffer so that it is ready for new data */ memset(read, 0, sizeof(*read)); data_length = att_buf.len; - bap_long_op_reset(); + bap_long_op_reset(inst); /* do the parse and callback to send notify to application*/ parse_and_send_recv_state(conn, handle, @@ -364,14 +392,15 @@ static uint8_t broadcast_assistant_bap_ntf_read_func(struct bt_conn *conn, uint8 static void long_bap_read(struct bt_conn *conn, uint16_t handle) { int err; + struct bap_broadcast_assistant_instance *inst = inst_by_conn(conn); - LOG_DBG("conn %p busy %u", conn, broadcast_assistant.busy); - - if (conn == NULL) { - return; /* noop */ + if (inst == NULL) { + return; } - if (broadcast_assistant.busy) { + if (inst->busy) { + LOG_DBG("conn %p busy %u", conn, inst->busy); + /* If the client is busy reading or writing something else, reschedule the * long read. */ @@ -385,33 +414,36 @@ static void long_bap_read(struct bt_conn *conn, uint16_t handle) } /* Wait a connection interval to retry */ - err = k_work_reschedule(&broadcast_assistant.bap_read_work, + err = k_work_reschedule(&inst->bap_read_work, K_USEC(BT_CONN_INTERVAL_TO_US(conn_info.le.interval))); if (err < 0) { LOG_DBG("Failed to reschedule read work: %d", err); - bap_long_op_reset(); + bap_long_op_reset(inst); } return; } - broadcast_assistant.read_params.func = broadcast_assistant_bap_ntf_read_func; - broadcast_assistant.read_params.handle_count = 1U; - broadcast_assistant.read_params.single.handle = handle; - broadcast_assistant.read_params.single.offset = att_buf.len; + inst->read_params.func = broadcast_assistant_bap_ntf_read_func; + inst->read_params.handle_count = 1U; + inst->read_params.single.handle = handle; + inst->read_params.single.offset = att_buf.len; - err = bt_gatt_read(conn, &broadcast_assistant.read_params); + err = bt_gatt_read(conn, &inst->read_params); if (err != 0) { LOG_DBG("Failed to read: %d", err); - bap_long_op_reset(); + bap_long_op_reset(inst); } else { - broadcast_assistant.busy = true; + inst->busy = true; } } static void delayed_bap_read_handler(struct k_work *work) { - long_bap_read(broadcast_assistant.conn, broadcast_assistant.long_read_handle); + struct bap_broadcast_assistant_instance *inst = + CONTAINER_OF((struct k_work_delayable *)work, + struct bap_broadcast_assistant_instance, bap_read_work); + long_bap_read(inst->conn, inst->long_read_handle); } /** @brief Handles notifications and indications from the server */ @@ -422,6 +454,18 @@ static uint8_t notify_handler(struct bt_conn *conn, uint16_t handle = params->value_handle; struct bt_bap_scan_delegator_recv_state recv_state; int16_t index; + struct bap_broadcast_assistant_instance *inst; + + if (conn == NULL) { + /* Indicates that the CCC has been removed - no-op */ + return BT_GATT_ITER_CONTINUE; + } + + inst = inst_by_conn(conn); + + if (inst == NULL) { + return BT_GATT_ITER_STOP; + } if (data == NULL) { LOG_DBG("[UNSUBSCRIBED] %u", handle); @@ -430,14 +474,9 @@ static uint8_t notify_handler(struct bt_conn *conn, return BT_GATT_ITER_STOP; } - if (conn == NULL) { - /* Indicates that the CCC has been removed - no-op */ - return BT_GATT_ITER_CONTINUE; - } - LOG_HEXDUMP_DBG(data, length, "Receive state notification:"); - index = lookup_index_by_handle(handle); + index = lookup_index_by_handle(inst, handle); if (index < 0) { LOG_DBG("Invalid index"); @@ -449,7 +488,7 @@ static uint8_t notify_handler(struct bt_conn *conn, const uint16_t max_ntf_size = bt_gatt_get_mtu(conn) - att_ntf_header_size; /* Cancel any pending long reads containing now obsolete information */ - (void)k_work_cancel_delayable(&broadcast_assistant.bap_read_work); + (void)k_work_cancel_delayable(&inst->bap_read_work); if (length == max_ntf_size) { /* TODO: if we are busy we should not overwrite the long_read_handle, @@ -457,9 +496,9 @@ static uint8_t notify_handler(struct bt_conn *conn, * for each characteristic, similar to the bt_bap_unicast_client_ep * struct for the unicast client */ - broadcast_assistant.long_read_handle = handle; + inst->long_read_handle = handle; - if (!broadcast_assistant.busy) { + if (!inst->busy) { net_buf_simple_add_mem(&att_buf, data, length); } long_bap_read(conn, handle); @@ -467,9 +506,8 @@ static uint8_t notify_handler(struct bt_conn *conn, return parse_and_send_recv_state(conn, handle, data, length, &recv_state); } } else { - broadcast_assistant.recv_states[index].past_avail = false; - bap_broadcast_assistant_recv_state_removed( - conn, broadcast_assistant.recv_states[index].src_id); + inst->recv_states[index].past_avail = false; + bap_broadcast_assistant_recv_state_removed(conn, inst->recv_states[index].src_id); } return BT_GATT_ITER_CONTINUE; @@ -479,9 +517,15 @@ static uint8_t read_recv_state_cb(struct bt_conn *conn, uint8_t err, struct bt_gatt_read_params *params, const void *data, uint16_t length) { + struct bap_broadcast_assistant_instance *inst = inst_by_conn(conn); + + if (inst == NULL) { + return BT_GATT_ITER_STOP; + } + uint16_t handle = params->single.handle; - uint8_t last_handle_index = broadcast_assistant.recv_state_cnt - 1; - uint16_t last_handle = broadcast_assistant.recv_state_handles[last_handle_index]; + uint8_t last_handle_index = inst->recv_state_cnt - 1; + uint16_t last_handle = inst->recv_state_handles[last_handle_index]; struct bt_bap_scan_delegator_recv_state recv_state; int cb_err = err; bool active_recv_state = data != NULL && length != 0; @@ -495,7 +539,7 @@ static uint8_t read_recv_state_cb(struct bt_conn *conn, uint8_t err, if (cb_err == 0 && active_recv_state) { int16_t index; - index = lookup_index_by_handle(handle); + index = lookup_index_by_handle(inst, handle); if (index < 0) { cb_err = BT_GATT_ERR(BT_ATT_ERR_INVALID_HANDLE); } else { @@ -505,13 +549,13 @@ static uint8_t read_recv_state_cb(struct bt_conn *conn, uint8_t err, LOG_DBG("Invalid receive state"); } else { struct bap_broadcast_assistant_recv_state_info *stored_state = - &broadcast_assistant.recv_states[index]; + &inst->recv_states[index]; stored_state->src_id = recv_state.src_id; stored_state->adv_sid = recv_state.adv_sid; stored_state->broadcast_id = recv_state.broadcast_id; bt_addr_le_copy(&stored_state->addr, &recv_state.addr); - broadcast_assistant.recv_states[index].past_avail = + inst->recv_states[index].past_avail = past_available(conn, &recv_state.addr, recv_state.adv_sid); } @@ -521,17 +565,17 @@ static uint8_t read_recv_state_cb(struct bt_conn *conn, uint8_t err, if (cb_err != 0) { LOG_DBG("err %d", cb_err); - if (broadcast_assistant.busy) { - broadcast_assistant.busy = false; + if (inst->busy) { + inst->busy = false; bap_broadcast_assistant_discover_complete(conn, cb_err, 0); } else { bap_broadcast_assistant_recv_state_changed(conn, cb_err, NULL); } } else if (handle == last_handle) { - if (broadcast_assistant.busy) { - const uint8_t recv_state_cnt = broadcast_assistant.recv_state_cnt; + if (inst->busy) { + const uint8_t recv_state_cnt = inst->recv_state_cnt; - broadcast_assistant.busy = false; + inst->busy = false; bap_broadcast_assistant_discover_complete(conn, cb_err, recv_state_cnt); } else { bap_broadcast_assistant_recv_state_changed(conn, cb_err, @@ -539,9 +583,9 @@ static uint8_t read_recv_state_cb(struct bt_conn *conn, uint8_t err, &recv_state : NULL); } } else { - for (uint8_t i = 0U; i < broadcast_assistant.recv_state_cnt; i++) { - if (handle == broadcast_assistant.recv_state_handles[i]) { - if (i + 1 < ARRAY_SIZE(broadcast_assistant.recv_state_handles)) { + for (uint8_t i = 0U; i < inst->recv_state_cnt; i++) { + if (handle == inst->recv_state_handles[i]) { + if (i + 1 < ARRAY_SIZE(inst->recv_state_handles)) { (void)bt_bap_broadcast_assistant_read_recv_state(conn, i + 1); } @@ -555,8 +599,10 @@ static uint8_t read_recv_state_cb(struct bt_conn *conn, uint8_t err, static void discover_init(void) { - k_work_init_delayable(&broadcast_assistant.bap_read_work, delayed_bap_read_handler); - + for (size_t i = 0; i < ARRAY_SIZE(broadcast_assistants); i++) { + k_work_init_delayable(&broadcast_assistants[i].bap_read_work, + delayed_bap_read_handler); + } net_buf_simple_reset(&att_buf); } @@ -571,15 +617,19 @@ static uint8_t char_discover_func(struct bt_conn *conn, { struct bt_gatt_subscribe_params *sub_params = NULL; int err; + struct bap_broadcast_assistant_instance *inst = inst_by_conn(conn); + + if (inst == NULL) { + return BT_GATT_ITER_STOP; + } if (attr == NULL) { - LOG_DBG("Found %u BASS receive states", - broadcast_assistant.recv_state_cnt); + LOG_DBG("Found %u BASS receive states", inst->recv_state_cnt); (void)memset(params, 0, sizeof(*params)); err = bt_bap_broadcast_assistant_read_recv_state(conn, 0); if (err != 0) { - broadcast_assistant.busy = false; + inst->busy = false; bap_broadcast_assistant_discover_complete(conn, err, 0); } @@ -594,24 +644,23 @@ static uint8_t char_discover_func(struct bt_conn *conn, if (bt_uuid_cmp(chrc->uuid, BT_UUID_BASS_CONTROL_POINT) == 0) { LOG_DBG("Control Point"); - broadcast_assistant.cp_handle = attr->handle + 1; + inst->cp_handle = attr->handle + 1; } else if (bt_uuid_cmp(chrc->uuid, BT_UUID_BASS_RECV_STATE) == 0) { - if (broadcast_assistant.recv_state_cnt < + if (inst->recv_state_cnt < CONFIG_BT_BAP_BROADCAST_ASSISTANT_RECV_STATE_COUNT) { - uint8_t idx = broadcast_assistant.recv_state_cnt++; + uint8_t idx = inst->recv_state_cnt++; - LOG_DBG("Receive State %u", broadcast_assistant.recv_state_cnt); - broadcast_assistant.recv_state_handles[idx] = + LOG_DBG("Receive State %u", inst->recv_state_cnt); + inst->recv_state_handles[idx] = attr->handle + 1; - sub_params = &broadcast_assistant.recv_state_sub_params[idx]; - sub_params->disc_params = - &broadcast_assistant.recv_state_disc_params[idx]; + sub_params = &inst->recv_state_sub_params[idx]; + sub_params->disc_params = &inst->recv_state_disc_params[idx]; } } if (sub_params != NULL) { /* With ccc_handle == 0 it will use auto discovery */ - sub_params->end_handle = broadcast_assistant.end_handle; + sub_params->end_handle = inst->end_handle; sub_params->ccc_handle = 0; sub_params->value = BT_GATT_CCC_NOTIFY; sub_params->value_handle = attr->handle + 1; @@ -623,7 +672,7 @@ static uint8_t char_discover_func(struct bt_conn *conn, LOG_DBG("Could not subscribe to handle 0x%04x: %d", sub_params->value_handle, err); - broadcast_assistant.busy = false; + inst->busy = false; LOG_DBG("no handle discover callback"); bap_broadcast_assistant_discover_complete(conn, err, 0); @@ -642,12 +691,17 @@ static uint8_t service_discover_func(struct bt_conn *conn, { int err; struct bt_gatt_service_val *prim_service; + struct bap_broadcast_assistant_instance *inst = inst_by_conn(conn); + + if (inst == NULL) { + return BT_GATT_ITER_STOP; + } if (attr == NULL) { LOG_DBG("Could not discover BASS"); (void)memset(params, 0, sizeof(*params)); - broadcast_assistant.busy = false; + inst->busy = false; err = BT_GATT_ERR(BT_ATT_ERR_NOT_SUPPORTED); bap_broadcast_assistant_discover_complete(conn, err, 0); @@ -659,19 +713,19 @@ static uint8_t service_discover_func(struct bt_conn *conn, if (params->type == BT_GATT_DISCOVER_PRIMARY) { prim_service = (struct bt_gatt_service_val *)attr->user_data; - broadcast_assistant.start_handle = attr->handle + 1; - broadcast_assistant.end_handle = prim_service->end_handle; + inst->start_handle = attr->handle + 1; + inst->end_handle = prim_service->end_handle; - broadcast_assistant.disc_params.uuid = NULL; - broadcast_assistant.disc_params.start_handle = broadcast_assistant.start_handle; - broadcast_assistant.disc_params.end_handle = broadcast_assistant.end_handle; - broadcast_assistant.disc_params.type = BT_GATT_DISCOVER_CHARACTERISTIC; - broadcast_assistant.disc_params.func = char_discover_func; + inst->disc_params.uuid = NULL; + inst->disc_params.start_handle = inst->start_handle; + inst->disc_params.end_handle = inst->end_handle; + inst->disc_params.type = BT_GATT_DISCOVER_CHARACTERISTIC; + inst->disc_params.func = char_discover_func; - err = bt_gatt_discover(conn, &broadcast_assistant.disc_params); + err = bt_gatt_discover(conn, &inst->disc_params); if (err != 0) { LOG_DBG("Discover failed (err %d)", err); - broadcast_assistant.busy = false; + inst->busy = false; bap_broadcast_assistant_discover_complete(conn, err, 0); } } @@ -684,8 +738,13 @@ static void bap_broadcast_assistant_write_cp_cb(struct bt_conn *conn, uint8_t er { struct bt_bap_broadcast_assistant_cb *listener, *next; uint8_t opcode = net_buf_simple_pull_u8(&att_buf); + struct bap_broadcast_assistant_instance *inst = inst_by_conn(conn); + + if (inst == NULL) { + return; + } - broadcast_assistant.busy = false; + inst->busy = false; /* we reset the buffer, so that we are ready for new notifications and writes */ net_buf_simple_reset(&att_buf); @@ -733,25 +792,34 @@ static int bt_bap_broadcast_assistant_common_cp(struct bt_conn *conn, const struct net_buf_simple *buf) { int err; + struct bap_broadcast_assistant_instance *inst; if (conn == NULL) { LOG_DBG("conn is NULL"); return -EINVAL; - } else if (broadcast_assistant.cp_handle == 0) { + } + + inst = inst_by_conn(conn); + + if (inst == NULL) { + return -EINVAL; + } + + if (inst->cp_handle == 0) { LOG_DBG("Handle not set"); return -EINVAL; } - broadcast_assistant.write_params.offset = 0; - broadcast_assistant.write_params.data = buf->data; - broadcast_assistant.write_params.length = buf->len; - broadcast_assistant.write_params.handle = broadcast_assistant.cp_handle; - broadcast_assistant.write_params.func = bap_broadcast_assistant_write_cp_cb; + inst->write_params.offset = 0; + inst->write_params.data = buf->data; + inst->write_params.length = buf->len; + inst->write_params.handle = inst->cp_handle; + inst->write_params.func = bap_broadcast_assistant_write_cp_cb; - err = bt_gatt_write(conn, &broadcast_assistant.write_params); + err = bt_gatt_write(conn, &inst->write_params); if (err == 0) { - broadcast_assistant.busy = true; + inst->busy = true; } return err; @@ -811,11 +879,12 @@ static struct bt_le_scan_cb scan_cb = { * Source_Adv_SID, and Broadcast_ID fields of any Broadcast Receive State characteristic exposed * by the Scan Delegator. */ -static bool broadcast_src_is_duplicate(uint32_t broadcast_id, uint8_t adv_sid, uint8_t addr_type) +static bool broadcast_src_is_duplicate(struct bap_broadcast_assistant_instance *inst, + uint32_t broadcast_id, uint8_t adv_sid, uint8_t addr_type) { - for (size_t i = 0; i < ARRAY_SIZE(broadcast_assistant.recv_states); i++) { + for (size_t i = 0; i < ARRAY_SIZE(inst->recv_states); i++) { const struct bap_broadcast_assistant_recv_state_info *state = - &broadcast_assistant.recv_states[i]; + &inst->recv_states[i]; if (state != NULL && state->broadcast_id == broadcast_id && state->adv_sid == adv_sid && state->addr.type == addr_type) { @@ -887,7 +956,11 @@ static int broadcast_assistant_reset(struct bap_broadcast_assistant_instance *in static void disconnected_cb(struct bt_conn *conn, uint8_t reason) { - (void)broadcast_assistant_reset(&broadcast_assistant); + struct bap_broadcast_assistant_instance *inst = inst_by_conn(conn); + + if (inst) { + (void)broadcast_assistant_reset(inst); + } } BT_CONN_CB_DEFINE(conn_callbacks) = { @@ -897,6 +970,7 @@ BT_CONN_CB_DEFINE(conn_callbacks) = { int bt_bap_broadcast_assistant_discover(struct bt_conn *conn) { int err; + struct bap_broadcast_assistant_instance *inst; if (conn == NULL) { LOG_DBG("conn is NULL"); @@ -904,34 +978,37 @@ int bt_bap_broadcast_assistant_discover(struct bt_conn *conn) return -EINVAL; } - if (broadcast_assistant.busy) { + inst = &broadcast_assistants[bt_conn_index(conn)]; + + if (inst->busy) { LOG_DBG("Instance is busy"); return -EBUSY; } - err = broadcast_assistant_reset(&broadcast_assistant); + err = broadcast_assistant_reset(inst); if (err != 0) { LOG_DBG("Failed to reset broadcast assistant: %d", err); - return err; + return -EINVAL; } + inst->conn = bt_conn_ref(conn); + /* Discover BASS on peer, setup handles and notify */ discover_init(); (void)memcpy(&uuid, BT_UUID_BASS, sizeof(uuid)); - broadcast_assistant.disc_params.func = service_discover_func; - broadcast_assistant.disc_params.uuid = &uuid.uuid; - broadcast_assistant.disc_params.type = BT_GATT_DISCOVER_PRIMARY; - broadcast_assistant.disc_params.start_handle = BT_ATT_FIRST_ATTRIBUTE_HANDLE; - broadcast_assistant.disc_params.end_handle = BT_ATT_LAST_ATTRIBUTE_HANDLE; - err = bt_gatt_discover(conn, &broadcast_assistant.disc_params); + inst->disc_params.func = service_discover_func; + inst->disc_params.uuid = &uuid.uuid; + inst->disc_params.type = BT_GATT_DISCOVER_PRIMARY; + inst->disc_params.start_handle = BT_ATT_FIRST_ATTRIBUTE_HANDLE; + inst->disc_params.end_handle = BT_ATT_LAST_ATTRIBUTE_HANDLE; + err = bt_gatt_discover(conn, &inst->disc_params); if (err != 0) { return err; } - broadcast_assistant.busy = true; - broadcast_assistant.conn = bt_conn_ref(conn); + inst->busy = true; return 0; } @@ -974,16 +1051,24 @@ int bt_bap_broadcast_assistant_scan_start(struct bt_conn *conn, bool start_scan) { struct bt_bap_bass_cp_scan_start *cp; int err; + struct bap_broadcast_assistant_instance *inst; if (conn == NULL) { LOG_DBG("conn is NULL"); return -EINVAL; - } else if (broadcast_assistant.cp_handle == 0) { + } + + inst = inst_by_conn(conn); + if (inst == NULL) { + return -EINVAL; + } + + if (inst->cp_handle == 0) { LOG_DBG("handle not set"); return -EINVAL; - } else if (broadcast_assistant.busy) { + } else if (inst->busy) { LOG_DBG("instance busy"); return -EBUSY; @@ -1004,7 +1089,7 @@ int bt_bap_broadcast_assistant_scan_start(struct bt_conn *conn, bool start_scan) return err; } - broadcast_assistant.scanning = true; + inst->scanning = true; } /* Reset buffer before using */ @@ -1020,22 +1105,30 @@ int bt_bap_broadcast_assistant_scan_stop(struct bt_conn *conn) { struct bt_bap_bass_cp_scan_stop *cp; int err; + struct bap_broadcast_assistant_instance *inst; if (conn == NULL) { LOG_DBG("conn is NULL"); return -EINVAL; - } else if (broadcast_assistant.cp_handle == 0) { + } + + inst = inst_by_conn(conn); + if (inst == NULL) { + return -EINVAL; + } + + if (inst->cp_handle == 0) { LOG_DBG("handle not set"); return -EINVAL; - } else if (broadcast_assistant.busy) { + } else if (inst->busy) { LOG_DBG("instance busy"); return -EBUSY; } - if (broadcast_assistant.scanning) { + if (inst->scanning) { err = bt_le_scan_stop(); if (err != 0) { LOG_DBG("Could not stop scan (%d)", err); @@ -1043,7 +1136,7 @@ int bt_bap_broadcast_assistant_scan_stop(struct bt_conn *conn) return err; } - broadcast_assistant.scanning = false; + inst->scanning = false; } /* Reset buffer before using */ @@ -1059,23 +1152,33 @@ int bt_bap_broadcast_assistant_add_src(struct bt_conn *conn, const struct bt_bap_broadcast_assistant_add_src_param *param) { struct bt_bap_bass_cp_add_src *cp; + struct bap_broadcast_assistant_instance *inst; if (conn == NULL) { LOG_DBG("conn is NULL"); return -EINVAL; - } else if (broadcast_assistant.cp_handle == 0) { + } + + inst = inst_by_conn(conn); + + if (inst == NULL) { + return -EINVAL; + } + + if (inst->cp_handle == 0) { LOG_DBG("handle not set"); return -EINVAL; - } else if (broadcast_assistant.busy) { + } else if (inst->busy) { LOG_DBG("instance busy"); return -EBUSY; } /* Check if this operation would result in a duplicate before proceeding */ - if (broadcast_src_is_duplicate(param->broadcast_id, param->adv_sid, param->addr.type)) { + if (broadcast_src_is_duplicate(inst, param->broadcast_id, + param->adv_sid, param->addr.type)) { LOG_DBG("Broadcast source already exists"); return -EINVAL; @@ -1148,16 +1251,24 @@ int bt_bap_broadcast_assistant_mod_src(struct bt_conn *conn, struct bt_bap_bass_cp_mod_src *cp; bool known_recv_state; bool past_avail; + struct bap_broadcast_assistant_instance *inst; if (conn == NULL) { LOG_DBG("conn is NULL"); return -EINVAL; - } else if (broadcast_assistant.cp_handle == 0) { + } + + inst = inst_by_conn(conn); + if (inst == NULL) { + return -EINVAL; + } + + if (inst->cp_handle == 0) { LOG_DBG("handle not set"); return -EINVAL; - } else if (broadcast_assistant.busy) { + } else if (inst->busy) { LOG_DBG("instance busy"); return -EBUSY; @@ -1175,10 +1286,10 @@ int bt_bap_broadcast_assistant_mod_src(struct bt_conn *conn, */ known_recv_state = false; past_avail = false; - for (size_t i = 0; i < ARRAY_SIZE(broadcast_assistant.recv_states); i++) { - if (broadcast_assistant.recv_states[i].src_id == param->src_id) { + for (size_t i = 0; i < ARRAY_SIZE(inst->recv_states); i++) { + if (inst->recv_states[i].src_id == param->src_id) { known_recv_state = true; - past_avail = broadcast_assistant.recv_states[i].past_avail; + past_avail = inst->recv_states[i].past_avail; break; } } @@ -1243,16 +1354,24 @@ int bt_bap_broadcast_assistant_set_broadcast_code( const uint8_t broadcast_code[BT_AUDIO_BROADCAST_CODE_SIZE]) { struct bt_bap_bass_cp_broadcase_code *cp; + struct bap_broadcast_assistant_instance *inst; if (conn == NULL) { LOG_DBG("conn is NULL"); return -EINVAL; - } else if (broadcast_assistant.cp_handle == 0) { + } + + inst = inst_by_conn(conn); + if (inst == NULL) { + return -EINVAL; + } + + if (inst->cp_handle == 0) { LOG_DBG("handle not set"); return -EINVAL; - } else if (broadcast_assistant.busy) { + } else if (inst->busy) { LOG_DBG("instance busy"); return -EBUSY; @@ -1276,16 +1395,24 @@ int bt_bap_broadcast_assistant_set_broadcast_code( int bt_bap_broadcast_assistant_rem_src(struct bt_conn *conn, uint8_t src_id) { struct bt_bap_bass_cp_rem_src *cp; + struct bap_broadcast_assistant_instance *inst; if (conn == NULL) { LOG_DBG("conn is NULL"); return -EINVAL; - } else if (broadcast_assistant.cp_handle == 0) { + } + + inst = inst_by_conn(conn); + if (inst == NULL) { + return -EINVAL; + } + + if (inst->cp_handle == 0) { LOG_DBG("handle not set"); return -EINVAL; - } else if (broadcast_assistant.busy) { + } else if (inst->busy) { LOG_DBG("instance busy"); return -EBUSY; @@ -1305,6 +1432,7 @@ int bt_bap_broadcast_assistant_read_recv_state(struct bt_conn *conn, uint8_t idx) { int err; + struct bap_broadcast_assistant_instance *inst; if (conn == NULL) { LOG_DBG("conn is NULL"); @@ -1312,27 +1440,31 @@ int bt_bap_broadcast_assistant_read_recv_state(struct bt_conn *conn, return -EINVAL; } - CHECKIF(idx >= ARRAY_SIZE(broadcast_assistant.recv_state_handles)) { + inst = inst_by_conn(conn); + if (inst == NULL) { + return -EINVAL; + } + + CHECKIF(idx >= ARRAY_SIZE(inst->recv_state_handles)) { LOG_DBG("Invalid idx: %u", idx); return -EINVAL; } - if (broadcast_assistant.recv_state_handles[idx] == 0) { + if (inst->recv_state_handles[idx] == 0) { LOG_DBG("handle not set"); return -EINVAL; } - broadcast_assistant.read_params.func = read_recv_state_cb; - broadcast_assistant.read_params.handle_count = 1; - broadcast_assistant.read_params.single.handle = - broadcast_assistant.recv_state_handles[idx]; + inst->read_params.func = read_recv_state_cb; + inst->read_params.handle_count = 1; + inst->read_params.single.handle = inst->recv_state_handles[idx]; - err = bt_gatt_read(conn, &broadcast_assistant.read_params); + err = bt_gatt_read(conn, &inst->read_params); if (err != 0) { - (void)memset(&broadcast_assistant.read_params, 0, - sizeof(broadcast_assistant.read_params)); + (void)memset(&inst->read_params, 0, + sizeof(inst->read_params)); } return err; From b7b7ce08cf881c2704a64866f03d1fd54f9f5a2c Mon Sep 17 00:00:00 2001 From: Frederic Pillon Date: Thu, 16 May 2024 15:07:16 +0200 Subject: [PATCH 2584/2849] board: st: enhance zephyr console support Use Kconfig to properly select console interface. Signed-off-by: Frederic Pillon --- boards/st/sensortile_box_pro/CMakeLists.txt | 3 -- boards/st/sensortile_box_pro/Kconfig | 12 +++++ .../st/sensortile_box_pro/Kconfig.defconfig | 37 ++++++++++++++ boards/st/sensortile_box_pro/board.c | 33 ------------ boards/st/sensortile_box_pro/doc/index.rst | 51 +++++++------------ .../sensortile_box_pro/sensortile_box_pro.dts | 9 ---- .../sensortile_box_pro_defconfig | 13 +---- boards/st/steval_stwinbx1/CMakeLists.txt | 3 -- boards/st/steval_stwinbx1/Kconfig | 12 +++++ boards/st/steval_stwinbx1/Kconfig.defconfig | 37 ++++++++++++++ boards/st/steval_stwinbx1/board.c | 33 ------------ boards/st/steval_stwinbx1/doc/index.rst | 49 +++++++----------- boards/st/steval_stwinbx1/steval_stwinbx1.dts | 12 ----- .../steval_stwinbx1/steval_stwinbx1_defconfig | 13 +---- 14 files changed, 134 insertions(+), 183 deletions(-) delete mode 100644 boards/st/sensortile_box_pro/CMakeLists.txt create mode 100644 boards/st/sensortile_box_pro/Kconfig delete mode 100644 boards/st/sensortile_box_pro/board.c delete mode 100644 boards/st/steval_stwinbx1/CMakeLists.txt create mode 100644 boards/st/steval_stwinbx1/Kconfig delete mode 100644 boards/st/steval_stwinbx1/board.c diff --git a/boards/st/sensortile_box_pro/CMakeLists.txt b/boards/st/sensortile_box_pro/CMakeLists.txt deleted file mode 100644 index f2a184ea87fe5..0000000000000 --- a/boards/st/sensortile_box_pro/CMakeLists.txt +++ /dev/null @@ -1,3 +0,0 @@ -# SPDX-License-Identifier: Apache-2.0 - -zephyr_library_sources(board.c) diff --git a/boards/st/sensortile_box_pro/Kconfig b/boards/st/sensortile_box_pro/Kconfig new file mode 100644 index 0000000000000..d8dc05c44f6a6 --- /dev/null +++ b/boards/st/sensortile_box_pro/Kconfig @@ -0,0 +1,12 @@ +# SENSORTILE_BOX_PRO board configuration + +# Copyright (c) 2024 STMicroelectronics +# SPDX-License-Identifier: Apache-2.0 + +if BOARD_SENSORTILE_BOX_PRO + +config BOARD_SERIAL_BACKEND_CDC_ACM + bool "Use USB CDC as serial console backend" + default y + +endif # BOARD_SENSORTILE_BOX_PRO diff --git a/boards/st/sensortile_box_pro/Kconfig.defconfig b/boards/st/sensortile_box_pro/Kconfig.defconfig index caa346b007540..fb701bd426546 100644 --- a/boards/st/sensortile_box_pro/Kconfig.defconfig +++ b/boards/st/sensortile_box_pro/Kconfig.defconfig @@ -26,6 +26,36 @@ config SPI_STM32_INTERRUPT default y depends on SPI +if BOARD_SERIAL_BACKEND_CDC_ACM + +config USB_DEVICE_STACK + default y + +config USB_CDC_ACM + default SERIAL + +config USB_DEVICE_INITIALIZE_AT_BOOT + default y if CONSOLE + +config SHELL_BACKEND_SERIAL_CHECK_DTR + default SHELL + depends on UART_LINE_CTRL + +config UART_LINE_CTRL + default SHELL + +config USB_DEVICE_REMOTE_WAKEUP + default n + +config USB_DEVICE_VID + default 0x0483 + +config USB_DEVICE_PID + default 0x5740 + +config USB_DEVICE_PRODUCT + default "Zephyr CDC SensorTile.box PRO" + if LOG # Logger cannot use itself to log @@ -35,4 +65,11 @@ endchoice endif # LOG +endif # BOARD_SERIAL_BACKEND_CDC_ACM + +DT_CHOSEN_ZEPHYR_CONSOLE := zephyr,console + +config UART_CONSOLE + default y if $(dt_chosen_enabled,$(DT_CHOSEN_ZEPHYR_CONSOLE)) && CONSOLE + endif # BOARD_SENSORTILE_BOX_PRO diff --git a/boards/st/sensortile_box_pro/board.c b/boards/st/sensortile_box_pro/board.c deleted file mode 100644 index c19d0abe3da6e..0000000000000 --- a/boards/st/sensortile_box_pro/board.c +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (c) 2023 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 sensortile_box_pro_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(sensortile_box_pro_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/sensortile_box_pro/doc/index.rst b/boards/st/sensortile_box_pro/doc/index.rst index e98ddace1bbf8..0d824aa9543e1 100644 --- a/boards/st/sensortile_box_pro/doc/index.rst +++ b/boards/st/sensortile_box_pro/doc/index.rst @@ -219,61 +219,44 @@ Console There are two possible options for Zephyr console output: -- through UART4 which is available on SWD connector (JP2). In this case a JTAG adapter - can be used to connect SensorTile.box PRO 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/sensortile_box_pro/sensortile_box_pro.dts`) - - - comment out the USB configuration macros - (:file:`boards/st/sensortile_box_pro/sensortile_box_pro_defconfig`) +- through USB as USB CDC/ACM class. This is the default case present in the board dts file + and is enabled by :kconfig:option:`CONFIG_BOARD_SERIAL_BACKEND_CDC_ACM`. .. code-block:: dts :caption: boards/st/sensortile_box_pro/sensortile_box_pro.dts / { chosen { - zephyr,console = &uart4; - zephyr,shell-uart = &uart4; - //zephyr,console = &cdc_acm_uart0; - //zephyr,shell-uart = &cdc_acm_uart0; + zephyr,console = &cdc_acm_uart0; + }; + }; + + &zephyr_udc0 { + cdc_acm_uart0: cdc_acm_uart0 { + compatible = "zephyr,cdc-acm-uart"; }; }; -.. code-block:: Kconfig - :caption: boards/st/sensortile_box_pro/sensortile_box_pro_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=0x1235 - #CONFIG_USB_DEVICE_PRODUCT="Zephyr CDC SensorTile.box PRO" - #CONFIG_USB_CDC_ACM_LOG_LEVEL_OFF=y - #CONFIG_USB_DEVICE_INITIALIZE_AT_BOOT=n +- through UART4 which is available on SWD connector (JP2). In this case a JTAG adapter + can be used to connect SensorTile.box PRO and have both SWD and console lines available. + To enable console and shell over UART: -- through USB as USB CDC/ACM class. This is the default case present in the board dts file. + - in your prj.conf, override the board's default configuration by setting :code:`CONFIG_BOARD_SERIAL_BACKEND_CDC_ACM=n` + + - add an overlay file named ``.overlay``: .. code-block:: dts - :caption: boards/st/sensortile_box_pro/sensortile_box_pro.dts / { chosen { - zephyr,console = &cdc_acm_uart0; - }; - }; - - &zephyr_udc0 { - cdc_acm_uart0: cdc_acm_uart0 { - compatible = "zephyr,cdc-acm-uart"; + zephyr,console = &uart4; + zephyr,shell-uart = &uart4; }; }; - Console default settings are 115200 8N1. Programming and Debugging diff --git a/boards/st/sensortile_box_pro/sensortile_box_pro.dts b/boards/st/sensortile_box_pro/sensortile_box_pro.dts index 06185c32d40a3..1d942fe83aeef 100644 --- a/boards/st/sensortile_box_pro/sensortile_box_pro.dts +++ b/boards/st/sensortile_box_pro/sensortile_box_pro.dts @@ -14,15 +14,6 @@ compatible = "st,sensortile-box-pro"; chosen { - /* - * By default, Zephyr console and shell are assigned to - * USB CDC/ACM. To enable console and shell over UART, - * uncomment following lines and set the correct config - * in sensortile_box_pro_defconfig. - * - * zephyr,console = &uart4; - * zephyr,shell-uart = &uart4; - */ zephyr,console = &cdc_acm_uart0; zephyr,shell-uart = &cdc_acm_uart0; zephyr,bt-c2h-uart = &cdc_acm_uart0; diff --git a/boards/st/sensortile_box_pro/sensortile_box_pro_defconfig b/boards/st/sensortile_box_pro/sensortile_box_pro_defconfig index a47f372d78471..ea12679af4817 100644 --- a/boards/st/sensortile_box_pro/sensortile_box_pro_defconfig +++ b/boards/st/sensortile_box_pro/sensortile_box_pro_defconfig @@ -12,20 +12,9 @@ CONFIG_GPIO=y # Enable Clocks CONFIG_CLOCK_CONTROL=y -# config USB and USB console +# Enable 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=0x1235 -CONFIG_USB_DEVICE_PRODUCT="Zephyr CDC SensorTile.box PRO" -CONFIG_USB_DEVICE_INITIALIZE_AT_BOOT=n # enable pin controller CONFIG_PINCTRL=y diff --git a/boards/st/steval_stwinbx1/CMakeLists.txt b/boards/st/steval_stwinbx1/CMakeLists.txt deleted file mode 100644 index f2a184ea87fe5..0000000000000 --- a/boards/st/steval_stwinbx1/CMakeLists.txt +++ /dev/null @@ -1,3 +0,0 @@ -# SPDX-License-Identifier: Apache-2.0 - -zephyr_library_sources(board.c) diff --git a/boards/st/steval_stwinbx1/Kconfig b/boards/st/steval_stwinbx1/Kconfig new file mode 100644 index 0000000000000..520aea81d168a --- /dev/null +++ b/boards/st/steval_stwinbx1/Kconfig @@ -0,0 +1,12 @@ +# STEVAL_STWINBX1 Development kit board configuration + +# Copyright (c) 2024 STMicroelectronics +# SPDX-License-Identifier: Apache-2.0 + +if BOARD_STEVAL_STWINBX1 + +config BOARD_SERIAL_BACKEND_CDC_ACM + bool "Use USB CDC as serial console backend" + default y + +endif # BOARD_STEVAL_STWINBX1 diff --git a/boards/st/steval_stwinbx1/Kconfig.defconfig b/boards/st/steval_stwinbx1/Kconfig.defconfig index 594ebede5a70f..657170dd30344 100644 --- a/boards/st/steval_stwinbx1/Kconfig.defconfig +++ b/boards/st/steval_stwinbx1/Kconfig.defconfig @@ -26,6 +26,36 @@ config SPI_STM32_INTERRUPT default y depends on SPI +if BOARD_SERIAL_BACKEND_CDC_ACM + +config USB_DEVICE_STACK + default y + +config USB_CDC_ACM + default SERIAL + +config USB_DEVICE_INITIALIZE_AT_BOOT + default y if CONSOLE + +config SHELL_BACKEND_SERIAL_CHECK_DTR + default SHELL + depends on UART_LINE_CTRL + +config UART_LINE_CTRL + default SHELL + +config USB_DEVICE_REMOTE_WAKEUP + default n + +config USB_DEVICE_VID + default 0x0483 + +config USB_DEVICE_PID + default 0x5740 + +config USB_DEVICE_PRODUCT + default "Zephyr CDC STEval-STWinbx1" + if LOG # Logger cannot use itself to log @@ -35,4 +65,11 @@ endchoice endif # LOG +endif # BOARD_SERIAL_BACKEND_CDC_ACM + +DT_CHOSEN_ZEPHYR_CONSOLE := zephyr,console + +config UART_CONSOLE + default y if $(dt_chosen_enabled,$(DT_CHOSEN_ZEPHYR_CONSOLE)) && CONSOLE + endif # BOARD_STEVAL_STWINBX1 diff --git a/boards/st/steval_stwinbx1/board.c b/boards/st/steval_stwinbx1/board.c deleted file mode 100644 index 1d98da4aba091..0000000000000 --- a/boards/st/steval_stwinbx1/board.c +++ /dev/null @@ -1,33 +0,0 @@ -/* - * 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/doc/index.rst b/boards/st/steval_stwinbx1/doc/index.rst index 367de5d437348..9027db10e5e82 100644 --- a/boards/st/steval_stwinbx1/doc/index.rst +++ b/boards/st/steval_stwinbx1/doc/index.rst @@ -236,59 +236,44 @@ 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`) +- through USB as USB CDC/ACM class. This is the default case present in the board dts file + and is enabled by :kconfig:option:`CONFIG_BOARD_SERIAL_BACKEND_CDC_ACM`. .. 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; + zephyr,console = &cdc_acm_uart0; }; }; -.. code-block:: Kconfig - :caption: boards/st/steval_stwinbx1/steval_stwinbx1_defconfig + &zephyr_udc0 { + cdc_acm_uart0: cdc_acm_uart0 { + compatible = "zephyr,cdc-acm-uart"; + }; + }; - # 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 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. -- through USB as USB CDC/ACM class. This is the default case present in the board dts file. + To enable console and shell over UART: + + - in your prj.conf, override the board's default configuration by setting :code:`CONFIG_BOARD_SERIAL_BACKEND_CDC_ACM=n` + + - add an overlay file named ``.overlay``: .. 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"; + zephyr,console = &usart2; + zephyr,shell-uart = &usart2; }; }; - Console default settings are 115200 8N1. Programming and Debugging diff --git a/boards/st/steval_stwinbx1/steval_stwinbx1.dts b/boards/st/steval_stwinbx1/steval_stwinbx1.dts index 4debd8cc5c19c..d8c3586320db9 100644 --- a/boards/st/steval_stwinbx1/steval_stwinbx1.dts +++ b/boards/st/steval_stwinbx1/steval_stwinbx1.dts @@ -14,18 +14,6 @@ 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; diff --git a/boards/st/steval_stwinbx1/steval_stwinbx1_defconfig b/boards/st/steval_stwinbx1/steval_stwinbx1_defconfig index c432b5184df15..a078754cd5d9e 100644 --- a/boards/st/steval_stwinbx1/steval_stwinbx1_defconfig +++ b/boards/st/steval_stwinbx1/steval_stwinbx1_defconfig @@ -13,20 +13,9 @@ CONFIG_GPIO_HOGS=y # Enable Clocks CONFIG_CLOCK_CONTROL=y -# config USB and USB console +# Enable 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 From 436f56646bec3eafce99b7de426e42a301ff4e5e Mon Sep 17 00:00:00 2001 From: Jeronimo Agullo Date: Tue, 14 May 2024 09:43:48 +0200 Subject: [PATCH 2585/2849] boards: sparkfun: Add micromod nrf52840 board and asset tracker shield Initial support of Sparkfun Micromod ecosystem with micromod nrf52840 board, asset tracker shield and micromod header definition. Signed-off-by: Jeronimo Agullo --- .../Kconfig.defconfig | 21 ++ .../Kconfig.shield | 5 + .../img/sparkfun_carrier_asset_tracker.webp | Bin 0 -> 62538 bytes .../doc/index.rst | 117 ++++++++++ .../sparkfun_carrier_asset_tracker.overlay | 50 +++++ boards/sparkfun/micromod/Kconfig | 19 ++ boards/sparkfun/micromod/Kconfig.defconfig | 11 + boards/sparkfun/micromod/Kconfig.micromod | 5 + boards/sparkfun/micromod/board.cmake | 9 + boards/sparkfun/micromod/board.yml | 5 + .../micromod/doc/img/sparkfun_micromod.webp | Bin 0 -> 49510 bytes boards/sparkfun/micromod/doc/index.rst | 204 ++++++++++++++++++ .../micromod/micromod_nrf52840-pinctrl.dtsi | 116 ++++++++++ .../sparkfun/micromod/micromod_nrf52840.dts | 200 +++++++++++++++++ .../sparkfun/micromod/micromod_nrf52840.yaml | 26 +++ .../micromod/micromod_nrf52840_defconfig | 19 ++ boards/sparkfun/micromod/pre_dt_board.cmake | 7 + dts/bindings/gpio/sparkfun,micromod-gpio.yaml | 51 +++++ .../adc_api/boards/micromod_nrf52840.overlay | 7 + 19 files changed, 872 insertions(+) create mode 100644 boards/shields/sparkfun_carrier_asset_tracker/Kconfig.defconfig create mode 100644 boards/shields/sparkfun_carrier_asset_tracker/Kconfig.shield create mode 100644 boards/shields/sparkfun_carrier_asset_tracker/doc/img/sparkfun_carrier_asset_tracker.webp create mode 100644 boards/shields/sparkfun_carrier_asset_tracker/doc/index.rst create mode 100644 boards/shields/sparkfun_carrier_asset_tracker/sparkfun_carrier_asset_tracker.overlay create mode 100644 boards/sparkfun/micromod/Kconfig create mode 100644 boards/sparkfun/micromod/Kconfig.defconfig create mode 100644 boards/sparkfun/micromod/Kconfig.micromod create mode 100644 boards/sparkfun/micromod/board.cmake create mode 100644 boards/sparkfun/micromod/board.yml create mode 100644 boards/sparkfun/micromod/doc/img/sparkfun_micromod.webp create mode 100644 boards/sparkfun/micromod/doc/index.rst create mode 100644 boards/sparkfun/micromod/micromod_nrf52840-pinctrl.dtsi create mode 100644 boards/sparkfun/micromod/micromod_nrf52840.dts create mode 100644 boards/sparkfun/micromod/micromod_nrf52840.yaml create mode 100644 boards/sparkfun/micromod/micromod_nrf52840_defconfig create mode 100644 boards/sparkfun/micromod/pre_dt_board.cmake create mode 100644 dts/bindings/gpio/sparkfun,micromod-gpio.yaml create mode 100644 tests/drivers/adc/adc_api/boards/micromod_nrf52840.overlay diff --git a/boards/shields/sparkfun_carrier_asset_tracker/Kconfig.defconfig b/boards/shields/sparkfun_carrier_asset_tracker/Kconfig.defconfig new file mode 100644 index 0000000000000..da44e62a05f1c --- /dev/null +++ b/boards/shields/sparkfun_carrier_asset_tracker/Kconfig.defconfig @@ -0,0 +1,21 @@ +# Copyright (c) 2024 Jerónimo Agulló +# SPDX-License-Identifier: Apache-2.0 + +if SHIELD_SPARKFUN_CARRIER_ASSET_TRACKER + +config SERIAL + default y + +config UART_INTERRUPT_DRIVEN + default y + +config UART_ASYNC_API + default y + +config I2C + default y + +config SPI + default y + +endif # SHIELD_SPARKFUN_CARRIER_ASSET_TRACKER diff --git a/boards/shields/sparkfun_carrier_asset_tracker/Kconfig.shield b/boards/shields/sparkfun_carrier_asset_tracker/Kconfig.shield new file mode 100644 index 0000000000000..71cff2673512b --- /dev/null +++ b/boards/shields/sparkfun_carrier_asset_tracker/Kconfig.shield @@ -0,0 +1,5 @@ +# Copyright (c) 2024 Jerónimo Agulló +# SPDX-License-Identifier: Apache-2.0 + +config SHIELD_SPARKFUN_CARRIER_ASSET_TRACKER + def_bool $(shields_list_contains,sparkfun_carrier_asset_tracker) diff --git a/boards/shields/sparkfun_carrier_asset_tracker/doc/img/sparkfun_carrier_asset_tracker.webp b/boards/shields/sparkfun_carrier_asset_tracker/doc/img/sparkfun_carrier_asset_tracker.webp new file mode 100644 index 0000000000000000000000000000000000000000..a76682a0cef848a3d5217b4ac809eb6c3753893a GIT binary patch literal 62538 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 z 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 + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + aliases { + modem-uart = µmod_1_uart; + modem = &modem; + }; +}; + +µmod_1_uart { + current-speed = <115200>; + hw-flow-control; + status = "okay"; + + modem: sara_r5 { + compatible = "u-blox,sara-r5"; + mdm-power-gpios = <µmod_header 7 0>; /* G2 */ + mdm-reset-gpios = <µmod_header 12 0>; /* D6 */ + status = "okay"; + }; +}; + +µmod_0_spi { + status = "okay"; + /* G0 (SD_CS) */ + cs-gpios = <µmod_header 5 GPIO_ACTIVE_LOW>; + + sdhc0: sdhc@0 { + compatible = "zephyr,sdhc-spi-slot"; + reg = <0>; + status = "okay"; + mmc { + compatible = "zephyr,sdmmc-disk"; + status = "okay"; + }; + spi-max-frequency = ; + }; +}; + +µmod_0_i2c { + max17048: max17048@36 { + compatible = "maxim,max17048"; + reg = <0x36>; + status = "okay"; + }; +}; diff --git a/boards/sparkfun/micromod/Kconfig b/boards/sparkfun/micromod/Kconfig new file mode 100644 index 0000000000000..c85ad61572fd4 --- /dev/null +++ b/boards/sparkfun/micromod/Kconfig @@ -0,0 +1,19 @@ +# Sparkfun micromod board configuration + +# Copyright (c) 2024 Jerónimo Agulló +# SPDX-License-Identifier: Apache-2.0 + +if BOARD_MICROMOD_NRF52840 + +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 + depends on SOC_NRF52840_QIAA + +endif # BOARD_MICROMOD_NRF52840 diff --git a/boards/sparkfun/micromod/Kconfig.defconfig b/boards/sparkfun/micromod/Kconfig.defconfig new file mode 100644 index 0000000000000..50f6c3f582aed --- /dev/null +++ b/boards/sparkfun/micromod/Kconfig.defconfig @@ -0,0 +1,11 @@ +# Sparkfun micromod board configuration + +# Copyright (c) 2024 Jerónimo Agulló +# SPDX-License-Identifier: Apache-2.0 + +if BOARD_MICROMOD_NRF52840 + +config BT_CTLR + default BT + +endif # BOARD_MICROMOD_NRF52840 diff --git a/boards/sparkfun/micromod/Kconfig.micromod b/boards/sparkfun/micromod/Kconfig.micromod new file mode 100644 index 0000000000000..ea40f13ad1a93 --- /dev/null +++ b/boards/sparkfun/micromod/Kconfig.micromod @@ -0,0 +1,5 @@ +# Copyright (c) 2024 Jerónimo Agulló +# SPDX-License-Identifier: Apache-2.0 + +config BOARD_MICROMOD + select SOC_NRF52840_QIAA if BOARD_MICROMOD_NRF52840 diff --git a/boards/sparkfun/micromod/board.cmake b/boards/sparkfun/micromod/board.cmake new file mode 100644 index 0000000000000..55900ba5975e1 --- /dev/null +++ b/boards/sparkfun/micromod/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/openocd-nrf5.board.cmake) +include(${ZEPHYR_BASE}/boards/common/pyocd.board.cmake) +include(${ZEPHYR_BASE}/boards/common/jlink.board.cmake) diff --git a/boards/sparkfun/micromod/board.yml b/boards/sparkfun/micromod/board.yml new file mode 100644 index 0000000000000..851ac345bc538 --- /dev/null +++ b/boards/sparkfun/micromod/board.yml @@ -0,0 +1,5 @@ +board: + name: micromod + vendor: sparkfun + socs: + - name: nrf52840 diff --git a/boards/sparkfun/micromod/doc/img/sparkfun_micromod.webp b/boards/sparkfun/micromod/doc/img/sparkfun_micromod.webp new file mode 100644 index 0000000000000000000000000000000000000000..423c7a3d0f6afd5b5efaebb16f4962018a5b090d GIT binary patch literal 49510 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�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 literal 0 HcmV?d00001 diff --git a/boards/sparkfun/micromod/doc/index.rst b/boards/sparkfun/micromod/doc/index.rst new file mode 100644 index 0000000000000..0ba4c37bbefbf --- /dev/null +++ b/boards/sparkfun/micromod/doc/index.rst @@ -0,0 +1,204 @@ +.. _boardname_linkname: + +SparkFun MicroMod board Processor +################################# + +Overview +******** + +MicroMod is a solderless, modular interface ecosystem that uses the M.2 standard +to mix and match your choice of processor with specific Function Boards or +stand-alone Carrier Boards. A MicroMod processor board is approximately 22x22 mm, +and can insert into any MicroMod carrier board. More information can be found in +the `Micromod specification website`_. + +All Micromod board targets support the following hardware features: + +- USB host mode compliant to 2.0 specification +- GPIO +- 2 UART +- 2 I2C +- 2 SPI +- 2 ADC +- 2 PWM +- Watchdog Timer (WDT) + +.. figure:: img/sparkfun_micromod.webp + :align: center + :alt: Sparkfun Micromod board + + Sparkfun Micromod board (Credit: https://www.sparkfun.com) + +Zephyr currently supports the following SoCs: + +- ``micromod/nrf52840`` + +SparkFun MicroMod nRF52840 board Processor +########################################## + +Overview +******** + +The ``micromod/nrf52840`` board target features the nRF52840 SoC +from Nordic Semiconductor, the SparkFun MicroMod nRF52840 Processor offers +a powerful combination of ARM Cortex-M4 CPU and 2.4 GHz Bluetooth transceiver +in the MicroMod form-factor. More information can be found in +the `Micromod nRF52840 guide`_. + +Hardware +******** + +The ``micromod/nrf52840`` board target supports the following +hardware features: + +- ARM Cortex-M4 CPU with floating point unit (FPU) + + - 1MB internal Flash + - 256kB internal RAM + +- Integrated 2.4GHz radio with support for Bluetooth Low Energy (BLE) and ieee802154 +- USB 2.0 full speed (12 Mbps) controller +- QSPI with 128Mb flash memory +- ARM TrustZone Cryptocell 310 security subsystem +- USB host mode compliant to 2.0 specification +- GPIO +- 2 UART +- 2 I2C +- 2 SPI +- 2 ADC +- 2 PWM +- Watchdog Timer (WDT) + +Supported Features +================== + +The Zephyr ``micromod/nrf52840`` board target supports the following hardware +features: + ++-----------+------------+-------------------------------------+ +| Interface | Controller | Driver/Component | ++===========+============+=====================================+ +| NVIC | on-chip | nested vector interrupt controller | ++-----------+------------+-------------------------------------+ +| SYSTICK | on-chip | system clock | ++-----------+------------+-------------------------------------+ +| RADIO | on-chip | Bluetooth, | +| | | ieee802154 | ++-----------+------------+-------------------------------------+ +| UART | on-chip | serial port | ++-----------+------------+-------------------------------------+ +| GPIO | on-chip | gpio | ++-----------+------------+-------------------------------------+ +| PINMUX | on-chip | pinmux | ++-----------+------------+-------------------------------------+ +| FLASH | on-chip | flash | ++-----------+------------+-------------------------------------+ +| SPI | on-chip | spi | ++-----------+------------+-------------------------------------+ +| I2C | on-chip | i2c | ++-----------+------------+-------------------------------------+ +| USB | on-chip | usb | ++-----------+------------+-------------------------------------+ +| QSPI | on-chip | nordic,nrf-qspi | ++-----------+------------+-------------------------------------+ + + +Connections and IOs +=================== + +LED +--- + +* Led0 (blue) = P0.13 + +Micromod header +--------------- + +* micromod_1_uart = uart0 +* micromod_2_uart = uart1 +* micromod_0_i2c = i2c0 +* micromod_1_i2c = i2c1 +* micromod_0_spi = spi2 +* micromod_header compatible with ``sparkfun,micromod-gpio`` + +Programming and Debugging +************************* + +Applications for the ``micromod/nrf52840`` board target can be +built, flashed, and debugged in the usual way. See +:ref:`build_an_application` and :ref:`application_run` for more details on +building and running. + +Flashing +======== + +Follow the instructions in the :ref:`nordic_segger` page to install +and configure all the necessary software. Further information can be +found in :ref:`nordic_segger_flashing`. Then build and flash +applications as usual (see :ref:`build_an_application` and +:ref:`application_run` for more details). + +The flashing tool will depend on the carrier used along with the board. +In the case of `Sparkfun asset tracking carrier`, it is possible to use +the SWD interface along with a J-Link. + +Here is an example for the :ref:`hello_world` application. + +First, run your favorite terminal program to listen for output. + +.. code-block:: console + + $ minicom -D -b 115200 + +Replace :code:`` with the port where the board nRF52840 DK +can be found. For example, under Linux, :code:`/dev/ttyACM0`. + +Then build and flash the application in the usual way. + +.. zephyr-app-commands:: + :zephyr-app: samples/hello_world + :board: micromod/nrf52840 + :goals: build flash + +Debugging +========= + +Refer to the :ref:`nordic_segger` page to learn about debugging Nordic boards with a +Segger IC. + +In case of using a Nordic Segger Jlink, it is possible to configure the app to use Segger Real +Time Transfer (RTT) for debugging. In this case, build your app with the +:ref:`RTT snippet `. + +Testing the on-board LED +************************ + +There is a sample that allow you to test the LED on the board is working properly +with Zephyr: + +* :zephyr:code-sample:`blinky` + +You can build and flash the example to make sure Zephyr is running correctly on +your board. The button and LED definitions can be found in +:zephyr_file:`boards/sparkfun/micromod/micromod_nrf52840.dts`. + +Testing the 128Mb qspi memory flash +*********************************** + +The ``micromod/nrf52840`` board target has a built-in NOR flash memory connected +to the qspi interface. It can be tested with the samples/drivers/jesd216 app. + +.. zephyr-app-commands:: + :zephyr-app: samples/drivers/jesd216 + :board: micromod/nrf52840 + :goals: build flash + +References +********** + +.. target-notes:: + +.. _Micromod specification website: https://www.sparkfun.com/micromod +.. _Micromod nRF52840 guide: https://learn.sparkfun.com/tutorials/micromod-nrf52840-processor-hookup-guide +.. _J-Link Software and documentation pack: https://www.segger.com/jlink-software.html +.. _nRF52840 Product Specification: http://infocenter.nordicsemi.com/pdf/nRF52840_PS_v1.0.pdf diff --git a/boards/sparkfun/micromod/micromod_nrf52840-pinctrl.dtsi b/boards/sparkfun/micromod/micromod_nrf52840-pinctrl.dtsi new file mode 100644 index 0000000000000..4cba8a1d09814 --- /dev/null +++ b/boards/sparkfun/micromod/micromod_nrf52840-pinctrl.dtsi @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2024 Jerónimo Agulló + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&pinctrl { + uart0_default: uart0_default { + group1 { + psels = , + , + , + ; + }; + }; + + uart0_sleep: uart0_sleep { + group1 { + psels = , + , + , + ; + low-power-enable; + }; + }; + + uart1_default: uart1_default { + group1 { + psels = , + ; + }; + }; + + uart1_sleep: uart1_sleep { + group1 { + psels = , + ; + low-power-enable; + }; + }; + + i2c0_default: i2c0_default { + group1 { + psels = , + ; + }; + }; + + i2c0_sleep: i2c0_sleep { + group1 { + psels = , + ; + low-power-enable; + }; + }; + + i2c1_default: i2c1_default { + group1 { + psels = , + ; + }; + }; + + i2c1_sleep: i2c1_sleep { + group1 { + psels = , + ; + low-power-enable; + }; + }; + + spi0_default: spi0_default { + group1 { + psels = , + , + ; + }; + }; + + spi0_sleep: spi0_sleep { + group1 { + psels = , + , + ; + low-power-enable; + }; + }; + + qspi_default: qspi_default { + group1 { + psels = , + , + , + , + , + ; + nordic,drive-mode = ; + }; + }; + + qspi_sleep: qspi_sleep { + group1 { + psels = , + , + , + , + ; + low-power-enable; + }; + group2 { + psels = ; + low-power-enable; + bias-pull-up; + }; + }; +}; diff --git a/boards/sparkfun/micromod/micromod_nrf52840.dts b/boards/sparkfun/micromod/micromod_nrf52840.dts new file mode 100644 index 0000000000000..345714a5cd378 --- /dev/null +++ b/boards/sparkfun/micromod/micromod_nrf52840.dts @@ -0,0 +1,200 @@ +/* + * Copyright (c) 2024 Jerónimo Agulló + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; +#include +#include "micromod_nrf52840-pinctrl.dtsi" +#include + +/ { + model = "Sparkfun Micrmod nRF52840 board"; + compatible = "sparkfun,micromod-nrf52840"; + + chosen { + zephyr,console = &uart0; + zephyr,sram = &sram0; + zephyr,flash = &flash0; + zephyr,code-partition = &slot0_partition; + zephyr,ieee802154 = &ieee802154; + }; + + /* These aliases are provided for compatibility with samples */ + aliases { + led0 = &led0; + watchdog0 = &wdt0; + }; + + leds { + compatible = "gpio-leds"; + led0: led_0 { + gpios = <&gpio0 13 0>; + label = "Blue LED"; + }; + }; + + micromod_header: connector { + compatible = "sparkfun,micromod-gpio"; + #gpio-cells = <2>; + gpio-map-mask = <0xffffffff 0xffffffc0>; + gpio-map-pass-thru = <0 0x3f>; + gpio-map = <0 0 &gpio0 4 0>, /* A0 */ + <1 0 &gpio0 5 0>, /* A1 */ + <2 0 &gpio0 27 0>, /* D0 */ + <3 0 &gpio1 8 0>, /* D1/CAM_TRIG */ + <4 0 &gpio0 15 0>, /* I2C_INT# */ + <5 0 &gpio0 29 0>, /* G0/BUS0 */ + <6 0 &gpio0 3 0>, /* G1/BUS1 */ + <7 0 &gpio1 13 0>, /* G2/BUS2 */ + <8 0 &gpio1 12 0>, /* G3/BUS3 */ + <9 0 &gpio1 11 0>, /* G4/BUS4 */ + <10 0 &gpio0 17 0>, /* G5/BUS5 */ + <11 0 &gpio1 6 0>, /* G6/BUS6 */ + <12 0 &gpio1 4 0>, /* G7/BUS7 */ + <13 0 &gpio1 14 0>, /* G8 */ + <14 0 &gpio0 9 0>, /* G9/ADC_D-/CAM_HSYNC */ + <15 0 &gpio0 10 0>, /* G10/ADC_D+/CAM_VSYNC */ + //<16 NO CONNECTED /* G11/SWO */ + <17 0 &gpio0 20 0>; /* SPI_CS */ + }; +}; + +&adc { + status = "okay"; +}; + +&gpiote { + status = "okay"; +}; + +&gpio0 { + status = "okay"; +}; + +&gpio1 { + status = "okay"; +}; + +&uicr { + nfct-pins-as-gpios; + gpio-as-nreset; +}; + +&uart0 { + compatible = "nordic,nrf-uarte"; + current-speed = <115200>; + status = "okay"; + pinctrl-0 = <&uart0_default>; + pinctrl-1 = <&uart0_sleep>; + pinctrl-names = "default", "sleep"; +}; + +&uart1 { + compatible = "nordic,nrf-uarte"; + current-speed = <115200>; + status = "okay"; + pinctrl-0 = <&uart1_default>; + pinctrl-1 = <&uart1_sleep>; + pinctrl-names = "default", "sleep"; +}; + +&i2c0 { + compatible = "nordic,nrf-twi"; + status = "okay"; + pinctrl-0 = <&i2c0_default>; + pinctrl-1 = <&i2c0_sleep>; + pinctrl-names = "default", "sleep"; +}; + +&i2c1 { + compatible = "nordic,nrf-twi"; + status = "okay"; + pinctrl-0 = <&i2c1_default>; + pinctrl-1 = <&i2c1_sleep>; + pinctrl-names = "default", "sleep"; +}; + +&spi2 { + compatible = "nordic,nrf-spi"; + status = "okay"; + cs-gpios = <&gpio0 20 GPIO_ACTIVE_LOW>; + pinctrl-0 = <&spi0_default>; + pinctrl-1 = <&spi0_sleep>; + pinctrl-names = "default", "sleep"; +}; + +&qspi { + status = "okay"; + pinctrl-0 = <&qspi_default>; + pinctrl-1 = <&qspi_sleep>; + pinctrl-names = "default", "sleep"; + w25q128jv: w25q128jv@0 { + status="okay"; + compatible = "nordic,qspi-nor"; + reg = <0>; + writeoc = "pp4io"; + readoc = "read4io"; + sck-frequency = ; + jedec-id = [ef 70 18]; + size = ; + has-dpd; + t-enter-dpd = <3000>; + t-exit-dpd = <3000>; + }; +}; + +&ieee802154 { + status = "okay"; +}; + +&flash0 { + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + boot_partition: partition@0 { + label = "mcuboot"; + reg = <0x00000000 0x00010000>; + }; + slot0_partition: partition@10000 { + label = "image-0"; + reg = <0x00010000 0x00076000>; + }; + + slot1_partition: partition@86000 { + label = "image-1"; + reg = <0x00086000 0x00074000>; + }; + + /* + * The flash starting at 0x000f8000 and ending at + * 0x000fffff is reserved for use by the application. + */ + + /* + * Storage partition will be used by FCB/LittleFS/NVS + * if enabled. + */ + + storage_partition: partition@fA000 { + label = "storage"; + reg = <0x000fA000 0x00006000>; + }; + }; +}; + +zephyr_udc0: &usbd { + compatible = "nordic,nrf-usbd"; + status = "okay"; +}; + +// Sparkfun Micromod compatible pins +micromod_1_uart: &uart0 {}; +micromod_2_uart: &uart1 {}; +micromod_0_i2c: &i2c0 {}; +micromod_1_i2c: &i2c1 {}; +micromod_0_spi: &spi2 {}; diff --git a/boards/sparkfun/micromod/micromod_nrf52840.yaml b/boards/sparkfun/micromod/micromod_nrf52840.yaml new file mode 100644 index 0000000000000..3afd626931343 --- /dev/null +++ b/boards/sparkfun/micromod/micromod_nrf52840.yaml @@ -0,0 +1,26 @@ +identifier: micromod/nrf52840 +name: Sparkfun Micromod nRF52840 board +type: mcu +arch: arm +ram: 256 +flash: 1024 +toolchain: + - zephyr + - gnuarmemb + - xtools +supported: + - ble + - gpio + - spi + - qspi + - i2c + - pwm + - adc + - usb_device + - usb_cdc + - watchdog + - micromod_gpio + - micromod_uart + - micromod_i2c + - micromod_spi +vendor: Sparkfun diff --git a/boards/sparkfun/micromod/micromod_nrf52840_defconfig b/boards/sparkfun/micromod/micromod_nrf52840_defconfig new file mode 100644 index 0000000000000..f8f1759f51c15 --- /dev/null +++ b/boards/sparkfun/micromod/micromod_nrf52840_defconfig @@ -0,0 +1,19 @@ +# SPDX-License-Identifier: Apache-2.0 + +# Enable MPU +CONFIG_ARM_MPU=y + +# Enable hardware stack protection +CONFIG_HW_STACK_PROTECTION=y + +# Enable RTT +CONFIG_USE_SEGGER_RTT=y + +# Enable GPIO +CONFIG_GPIO=y + +# Enable console +CONFIG_CONSOLE=y + +# Enable UART +CONFIG_SERIAL=y diff --git a/boards/sparkfun/micromod/pre_dt_board.cmake b/boards/sparkfun/micromod/pre_dt_board.cmake new file mode 100644 index 0000000000000..3369c21d3af5b --- /dev/null +++ b/boards/sparkfun/micromod/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/dts/bindings/gpio/sparkfun,micromod-gpio.yaml b/dts/bindings/gpio/sparkfun,micromod-gpio.yaml new file mode 100644 index 0000000000000..ae0c290aee3ef --- /dev/null +++ b/dts/bindings/gpio/sparkfun,micromod-gpio.yaml @@ -0,0 +1,51 @@ +# Copyright (c) 2024 Jerónimo Agulló +# SPDX-License-Identifier: Apache-2.0 + +description: | + GPIO pins exposed on micromod headers. + + The micromod standard leverages the M.2 connector with 76 pins for + swap between a myriad of supported boards and carriers. + + The micromod standard consists of two lanes with the following + supported buses: + * An 6-pin Power Supply header. No pins on this header are exposed + by this binding. + * Reset, Boot pins and SWD pins not exposed by this binding. + * 2 UART buses. First with RTS and CTS pins, while the 2nd with only + RX and TX pins. Neither of them are exposed by this binding. + * 2 i2c buses. Only the corresponding interrupt pin is exposed by + this binding. + * 2 SPI buses not exposed by this binding. Only SPI CS control pin + is exposed by this binding. + * Audio line not exposed by this binding. + * 2 analog pins (A0 and A1). + * 2 digital pins (D0 and D1). + * 12 General purpose pins (G0 - G11). + + This binding provides a nexus mapping for the analog, digital and + general purpose gpios in the order depicted below: + + - 00 -> A0 PIN 34 + - 01 -> A1 PIN 38 + - 02 -> D0 PIN 10 + - 03 -> D1/CAM_TRIG PIN 18 + - 04 -> I2C_INT# PIN 16 + - 05 -> G0/BUS0 PIN 40 + - 06 -> G1/BUS1 PIN 42 + - 07 -> G2/BUS2 PIN 44 + - 08 -> G3/BUS3 PIN 46 + - 09 -> G4/BUS4 PIN 48 + - 10 -> G5/BUS5 PIN 73 + - 11 -> G6/BUS6 PIN 71 + - 12 -> G7/BUS7 PIN 69 + - 13 -> G8 PIN 67 + - 14 -> G9/ADC_D-/CAM_HSYNC PIN 65 + - 15 -> G10/ADC_D+/CAM_VSYNC PIN 63 + - 16 -> G11/SWO PIN 8 + - 17 -> SPI_CS PIN 55 + + +compatible: "sparkfun,micromod-gpio" + +include: [gpio-nexus.yaml, base.yaml] diff --git a/tests/drivers/adc/adc_api/boards/micromod_nrf52840.overlay b/tests/drivers/adc/adc_api/boards/micromod_nrf52840.overlay new file mode 100644 index 0000000000000..cbc9b08e0e868 --- /dev/null +++ b/tests/drivers/adc/adc_api/boards/micromod_nrf52840.overlay @@ -0,0 +1,7 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright (c) 2024 Jerónimo Agulló + */ + +#include "nordic,nrf-saadc-common.dtsi" From a7123157931210640965cbb3379f4297ab447fa1 Mon Sep 17 00:00:00 2001 From: Emil Gydesen Date: Fri, 26 Apr 2024 15:35:24 +0200 Subject: [PATCH 2586/2849] Samples: Bluetooth: Add CAP initiator unicast sample Adds a CAP initiator unicast sample that simply uses the CAP initiator unicast API to setup streams with a CAP acceptor. To keep it simple no audio or encoding support has been added. Signed-off-by: Emil Gydesen --- .../bluetooth/cap_initiator/CMakeLists.txt | 12 + .../bluetooth/cap_initiator/Kconfig.sysbuild | 15 + samples/bluetooth/cap_initiator/README.rst | 74 ++ .../cap_initiator/overlay-bt_ll_sw_split.conf | 13 + samples/bluetooth/cap_initiator/prj.conf | 29 + samples/bluetooth/cap_initiator/sample.yaml | 30 + .../cap_initiator/src/cap_initiator.h | 15 + .../cap_initiator/src/cap_initiator_unicast.c | 830 ++++++++++++++++++ samples/bluetooth/cap_initiator/src/main.c | 51 ++ .../bluetooth/cap_initiator/sysbuild.cmake | 24 + 10 files changed, 1093 insertions(+) create mode 100644 samples/bluetooth/cap_initiator/CMakeLists.txt create mode 100644 samples/bluetooth/cap_initiator/Kconfig.sysbuild create mode 100644 samples/bluetooth/cap_initiator/README.rst create mode 100644 samples/bluetooth/cap_initiator/overlay-bt_ll_sw_split.conf create mode 100644 samples/bluetooth/cap_initiator/prj.conf create mode 100644 samples/bluetooth/cap_initiator/sample.yaml create mode 100644 samples/bluetooth/cap_initiator/src/cap_initiator.h create mode 100644 samples/bluetooth/cap_initiator/src/cap_initiator_unicast.c create mode 100644 samples/bluetooth/cap_initiator/src/main.c create mode 100644 samples/bluetooth/cap_initiator/sysbuild.cmake diff --git a/samples/bluetooth/cap_initiator/CMakeLists.txt b/samples/bluetooth/cap_initiator/CMakeLists.txt new file mode 100644 index 0000000000000..21d0a06e5e498 --- /dev/null +++ b/samples/bluetooth/cap_initiator/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(cap_initiator) + +target_sources(app PRIVATE + src/main.c + src/cap_initiator_unicast.c +) + +zephyr_library_include_directories(${ZEPHYR_BASE}/samples/bluetooth) diff --git a/samples/bluetooth/cap_initiator/Kconfig.sysbuild b/samples/bluetooth/cap_initiator/Kconfig.sysbuild new file mode 100644 index 0000000000000..f37b265ecbc27 --- /dev/null +++ b/samples/bluetooth/cap_initiator/Kconfig.sysbuild @@ -0,0 +1,15 @@ +# Copyright 2023 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +source "share/sysbuild/Kconfig" + +config NET_CORE_BOARD + string + default "nrf5340dk/nrf5340/cpunet" if "$(BOARD)" = "nrf5340dk" + default "nrf5340_audio_dk/nrf5340/cpunet" if "$(BOARD)" = "nrf5340_audio_dk" + default "nrf5340bsim/nrf5340/cpunet" if $(BOARD_TARGET_STRING) = "NRF5340BSIM_NRF5340_CPUAPP" + +config NET_CORE_IMAGE_HCI_IPC + bool "HCI IPC image on network core" + default y + depends on NET_CORE_BOARD != "" diff --git a/samples/bluetooth/cap_initiator/README.rst b/samples/bluetooth/cap_initiator/README.rst new file mode 100644 index 0000000000000..d88bb7cc1366b --- /dev/null +++ b/samples/bluetooth/cap_initiator/README.rst @@ -0,0 +1,74 @@ +.. zephyr:code-sample:: bluetooth_cap_initiator + :name: Bluetooth: Common Audio Profile Initiator + :relevant-api: bt_cap bt_bap bluetooth + + CAP Initiator sample that connects to CAP Acceptors and setup audio streaming. + +Overview +******** + +Application demonstrating the CAP Initiator functionality. +Starts by scanning for a CAP Acceptor and then connects to and sets up available streams. + +This sample can be found under :zephyr_file:`samples/bluetooth/cap_initiator` in the Zephyr tree. + +Check the :ref:`bluetooth samples section ` for general information. + +Requirements +************ + +* BlueZ running on the host, or +* A board with Bluetooth Low Energy 5.2 support + +Building and Running +******************** + +When building targeting an nrf52 series board with the Zephyr Bluetooth Controller, +use ``-DOVERLAY_CONFIG=overlay-bt_ll_sw_split.conf`` to enable the required ISO +feature support. + +Building for an nrf5340dk +------------------------- + +You can build both the application core image and an appropriate controller image for the network +core with: + +.. zephyr-app-commands:: + :zephyr-app: samples/bluetooth/cap_initiator/ + :board: nrf5340dk/nrf5340/cpuapp + :goals: build + :west-args: --sysbuild + +If you prefer to only build the application core image, you can do so by doing instead: + +.. zephyr-app-commands:: + :zephyr-app: samples/bluetooth/cap_initiator/ + :board: nrf5340dk/nrf5340/cpuapp + :goals: build + +In that case you can pair this application core image with the +:ref:`hci_ipc sample ` +:zephyr_file:`samples/bluetooth/hci_ipc/nrf5340_cpunet_iso-bt_ll_sw_split.conf` configuration. + +Building for a simulated nrf5340bsim +------------------------------------ + +Similarly to how you would for real HW, you can do: + +.. zephyr-app-commands:: + :zephyr-app: samples/bluetooth/cap_initiator/ + :board: nrf5340bsim/nrf5340/cpuapp + :goals: build + :west-args: --sysbuild + +Note this will produce a Linux executable in `./build/zephyr/zephyr.exe`. +For more information, check :ref:`this board documentation `. + +Building for a simulated nrf52_bsim +----------------------------------- + +.. zephyr-app-commands:: + :zephyr-app: samples/bluetooth/cap_initiator/ + :board: nrf52_bsim + :goals: build + :gen-args: -DOVERLAY_CONFIG=overlay-bt_ll_sw_split.conf diff --git a/samples/bluetooth/cap_initiator/overlay-bt_ll_sw_split.conf b/samples/bluetooth/cap_initiator/overlay-bt_ll_sw_split.conf new file mode 100644 index 0000000000000..35d452e15dc38 --- /dev/null +++ b/samples/bluetooth/cap_initiator/overlay-bt_ll_sw_split.conf @@ -0,0 +1,13 @@ +# 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_SCAN_DATA_LEN_MAX=191 + +# Enable support for central ISO in Zephyr Bluetooth Controller +CONFIG_BT_CTLR_CENTRAL_ISO=y + +# 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/cap_initiator/prj.conf b/samples/bluetooth/cap_initiator/prj.conf new file mode 100644 index 0000000000000..254fe45d9d503 --- /dev/null +++ b/samples/bluetooth/cap_initiator/prj.conf @@ -0,0 +1,29 @@ +CONFIG_BT=y +CONFIG_LOG=y +CONFIG_BT_CENTRAL=y +CONFIG_BT_AUDIO=y +CONFIG_BT_EXT_ADV=y +CONFIG_BT_DEVICE_NAME="CAP Initiator" + +CONFIG_BT_SMP=y +CONFIG_BT_TINYCRYPT_ECC=y +CONFIG_BT_KEYS_OVERWRITE_OLDEST=y + +# CAP support +CONFIG_BT_CAP_INITIATOR=y + +# CSIP support +CONFIG_BT_CSIP_SET_COORDINATOR=y + +# BAP support +CONFIG_BT_ISO_MAX_CHAN=2 +CONFIG_BT_BAP_UNICAST_CLIENT=y +CONFIG_BT_BAP_UNICAST_CLIENT_GROUP_STREAM_COUNT=2 +CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT=2 +CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SRC_COUNT=2 + +# Controller configuration +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/cap_initiator/sample.yaml b/samples/bluetooth/cap_initiator/sample.yaml new file mode 100644 index 0000000000000..12a6022bcd7d0 --- /dev/null +++ b/samples/bluetooth/cap_initiator/sample.yaml @@ -0,0 +1,30 @@ +sample: + description: Bluetooth Low Energy Common Audio Profile Initiator sample + name: Bluetooth Low Energy Common Audio Profile Initiator sample +tests: + sample.bluetooth.cap_initiator: + harness: bluetooth + platform_allow: + - qemu_cortex_m3 + - qemu_x86 + - nrf5340dk/nrf5340/cpuapp + - nrf5340bsim/nrf5340/cpuapp + integration_platforms: + - qemu_x86 + - nrf5340dk/nrf5340/cpuapp + tags: bluetooth + sysbuild: true + sample.bluetooth.cap_initiator.bt_ll_sw_split: + harness: bluetooth + platform_allow: + - nrf52_bsim + - nrf52833dk/nrf52833 + - nrf52840dk/nrf52840 + - nrf52840dongle/nrf52840 + integration_platforms: + - nrf52_bsim + - nrf52833dk/nrf52833 + - nrf52840dk/nrf52840 + - nrf52840dongle/nrf52840 + extra_args: OVERLAY_CONFIG=overlay-bt_ll_sw_split.conf + tags: bluetooth diff --git a/samples/bluetooth/cap_initiator/src/cap_initiator.h b/samples/bluetooth/cap_initiator/src/cap_initiator.h new file mode 100644 index 0000000000000..8aecaa87e1d4b --- /dev/null +++ b/samples/bluetooth/cap_initiator/src/cap_initiator.h @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @brief Run the application as a CAP Initiator for unicast + * + * This will start scanning for and connecting to a CAP acceptor, and then attempt to setup + * unicast streams. + * + * @return 0 if success, errno on failure. + */ +int cap_initiator_unicast(void); diff --git a/samples/bluetooth/cap_initiator/src/cap_initiator_unicast.c b/samples/bluetooth/cap_initiator/src/cap_initiator_unicast.c new file mode 100644 index 0000000000000..76be7ef0dad0d --- /dev/null +++ b/samples/bluetooth/cap_initiator/src/cap_initiator_unicast.c @@ -0,0 +1,830 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "cap_initiator.h" + +LOG_MODULE_REGISTER(cap_initiator_unicast, LOG_LEVEL_INF); + +#define SEM_TIMEOUT K_SECONDS(5) + +/* We use the same config for both sink and source streams + * For simplicity we use the mandatory configuration 16_2_1 + */ +static struct bt_bap_lc3_preset unicast_preset_16_2_1 = BT_BAP_LC3_UNICAST_PRESET_16_2_1( + BT_AUDIO_LOCATION_MONO_AUDIO, BT_AUDIO_CONTEXT_TYPE_UNSPECIFIED); +static struct bt_bap_unicast_group *unicast_group; + +/** Struct to contain information for a specific peer (CAP) device */ +struct peer_config { + /** Stream for the source endpoint */ + struct bt_cap_stream source_stream; + /** Stream for the sink endpoint */ + struct bt_cap_stream sink_stream; + /** Semaphore to help wait for a release operation if the source stream is not idle */ + struct k_sem source_stream_sem; + /** Semaphore to help wait for a release operation if the sink stream is not idle */ + struct k_sem sink_stream_sem; + /** Reference to the endpoint for the source stream */ + struct bt_bap_ep *source_ep; + /** Reference to the endpoint for the sink stream */ + struct bt_bap_ep *sink_ep; + /** ACL connection object for the peer device */ + struct bt_conn *conn; +}; + +/* TODO: Expand to multiple ACL connections */ +static struct peer_config peer; + +static K_SEM_DEFINE(sem_proc, 0, 1); +static K_SEM_DEFINE(sem_state_change, 0, 1); +static K_SEM_DEFINE(sem_mtu_exchanged, 0, 1); +static K_SEM_DEFINE(sem_security_changed, 0, 1); + +static void unicast_stream_configured_cb(struct bt_bap_stream *stream, + const struct bt_audio_codec_qos_pref *pref) +{ + LOG_INF("Configured stream %p", stream); + + /* TODO: The preference should be used/taken into account when + * setting the QoS + */ + + LOG_INF("Remote preferences: unframed %s, phy %u, rtn %u, latency %u, pd_min %u, pd_max " + "%u, pref_pd_min %u, pref_pd_max %u", + pref->unframed_supported ? "supported" : "not supported", pref->phy, pref->rtn, + pref->latency, pref->pd_min, pref->pd_max, pref->pref_pd_min, pref->pref_pd_max); +} + +static void unicast_stream_qos_set_cb(struct bt_bap_stream *stream) +{ + LOG_INF("QoS set stream %p", stream); +} + +static void unicast_stream_enabled_cb(struct bt_bap_stream *stream) +{ + LOG_INF("Enabled stream %p", stream); +} + +static void unicast_stream_started_cb(struct bt_bap_stream *stream) +{ + LOG_INF("Started stream %p", stream); +} + +static void unicast_stream_metadata_updated_cb(struct bt_bap_stream *stream) +{ + LOG_INF("Metadata updated stream %p", stream); +} + +static void unicast_stream_disabled_cb(struct bt_bap_stream *stream) +{ + LOG_INF("Disabled stream %p", stream); +} + +static void unicast_stream_stopped_cb(struct bt_bap_stream *stream, uint8_t reason) +{ + LOG_INF("Stopped stream %p with reason 0x%02X", stream, reason); +} + +static void unicast_stream_released_cb(struct bt_bap_stream *stream) +{ + LOG_INF("Released stream %p", stream); + + if (stream == &peer.source_stream.bap_stream) { + k_sem_give(&peer.source_stream_sem); + } else if (stream == &peer.sink_stream.bap_stream) { + k_sem_give(&peer.sink_stream_sem); + } +} + +static void unicast_stream_recv_cb(struct bt_bap_stream *stream, + const struct bt_iso_recv_info *info, struct net_buf *buf) +{ + /* TODO: Add test code */ +} + +static struct bt_bap_stream_ops unicast_stream_ops = { + .configured = unicast_stream_configured_cb, + .qos_set = unicast_stream_qos_set_cb, + .enabled = unicast_stream_enabled_cb, + .started = unicast_stream_started_cb, + .metadata_updated = unicast_stream_metadata_updated_cb, + .disabled = unicast_stream_disabled_cb, + .stopped = unicast_stream_stopped_cb, + .released = unicast_stream_released_cb, + .recv = unicast_stream_recv_cb, +}; + +static bool log_codec_cb(struct bt_data *data, void *user_data) +{ + const char *str = (const char *)user_data; + + LOG_DBG("\t%s: type 0x%02x value_len %u", str, data->type, data->data_len); + LOG_HEXDUMP_DBG(data->data, data->data_len, "\t\tdata"); + + return true; +} + +static void log_codec(const struct bt_audio_codec_cap *codec_cap, enum bt_audio_dir dir) +{ + LOG_INF("codec id 0x%02x cid 0x%04x vid 0x%04x count %u", codec_cap->id, codec_cap->cid, + codec_cap->vid, codec_cap->data_len); + + if (codec_cap->id == BT_HCI_CODING_FORMAT_LC3) { + bt_audio_data_parse(codec_cap->data, codec_cap->data_len, log_codec_cb, "data"); + } else { /* If not LC3, we cannot assume it's LTV */ + LOG_HEXDUMP_DBG(codec_cap->data, codec_cap->data_len, "data"); + } + + bt_audio_data_parse(codec_cap->meta, codec_cap->meta_len, log_codec_cb, "meta"); +} + +static void add_remote_sink(struct bt_bap_ep *ep) +{ + if (peer.sink_ep == NULL) { + LOG_INF("Sink ep: %p", (void *)ep); + peer.sink_ep = ep; + return; + } +} + +static void add_remote_source(struct bt_bap_ep *ep) +{ + if (peer.source_ep == NULL) { + LOG_INF("Source ep: %p", (void *)ep); + peer.source_ep = ep; + return; + } +} + +static void discover_cb(struct bt_conn *conn, int err, enum bt_audio_dir dir) +{ + if (dir == BT_AUDIO_DIR_SINK) { + if (err != 0) { + LOG_ERR("Discovery sinks failed: %d", err); + } else { + LOG_INF("Discover sinks complete"); + } + } else if (dir == BT_AUDIO_DIR_SOURCE) { + if (err != 0) { + LOG_ERR("Discovery sources failed: %d", err); + } else { + LOG_INF("Discover sources complete"); + } + } + + k_sem_give(&sem_proc); +} + +static void pac_record_cb(struct bt_conn *conn, enum bt_audio_dir dir, + const struct bt_audio_codec_cap *codec_cap) +{ + log_codec(codec_cap, dir); +} + +static void endpoint_cb(struct bt_conn *conn, enum bt_audio_dir dir, struct bt_bap_ep *ep) +{ + if (dir == BT_AUDIO_DIR_SOURCE) { + add_remote_source(ep); + } else if (dir == BT_AUDIO_DIR_SINK) { + add_remote_sink(ep); + } +} + +static int discover_sinks(void) +{ + int err; + + LOG_INF("Discovering sink ASEs"); + k_sem_reset(&sem_proc); + + bt_cap_stream_ops_register(&peer.sink_stream, &unicast_stream_ops); + + err = bt_bap_unicast_client_discover(peer.conn, BT_AUDIO_DIR_SINK); + if (err != 0) { + LOG_ERR("Failed to discover sink: %d", err); + return err; + } + + err = k_sem_take(&sem_proc, SEM_TIMEOUT); + if (err != 0) { + LOG_ERR("Timeout on sinks discover: %d", err); + return err; + } + + return err; +} + +static int discover_sources(void) +{ + int err; + + LOG_INF("Discovering source ASEs"); + k_sem_reset(&sem_proc); + + bt_cap_stream_ops_register(&peer.source_stream, &unicast_stream_ops); + + err = bt_bap_unicast_client_discover(peer.conn, BT_AUDIO_DIR_SOURCE); + if (err != 0) { + LOG_ERR("Failed to discover sources: %d", err); + return err; + } + + err = k_sem_take(&sem_proc, SEM_TIMEOUT); + if (err != 0) { + LOG_ERR("Timeout on sources discover: %d", err); + return err; + } + + return 0; +} + +static int unicast_group_create(void) +{ + struct bt_bap_unicast_group_stream_param source_stream_param = { + .qos = &unicast_preset_16_2_1.qos, + .stream = &peer.source_stream.bap_stream, + }; + struct bt_bap_unicast_group_stream_param sink_stream_param = { + .qos = &unicast_preset_16_2_1.qos, + .stream = &peer.sink_stream.bap_stream, + }; + struct bt_bap_unicast_group_stream_pair_param pair_params = {0}; + struct bt_bap_unicast_group_param group_param = {0}; + int err; + + if (peer.source_ep != NULL) { + pair_params.rx_param = &source_stream_param; + } + + if (peer.sink_ep != NULL) { + pair_params.tx_param = &sink_stream_param; + } + + group_param.params_count = 1U; + group_param.params = &pair_params; + + err = bt_bap_unicast_group_create(&group_param, &unicast_group); + if (err != 0) { + LOG_ERR("Failed to create group: %d", err); + return err; + } + + LOG_INF("Created group"); + + return err; +} + +static int unicast_group_delete(void) +{ + int err; + + err = bt_bap_unicast_group_delete(unicast_group); + if (err != 0) { + LOG_ERR("Failed to delete group: %d", err); + return err; + } + unicast_group = NULL; + + LOG_INF("Deleted group"); + + return err; +} + +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) { + LOG_ERR("CAS discovery completed with error: %d", err); + + return; + } + + if (IS_ENABLED(CONFIG_BT_CAP_ACCEPTOR_SET_MEMBER) && csis_inst != NULL) { + LOG_INF("Found CAS with CSIS %p", csis_inst); + /* TODO: Do set member discovery */ + } else { + LOG_INF("Found CAS"); + } + + k_sem_give(&sem_proc); +} + +static void unicast_start_complete_cb(int err, struct bt_conn *conn) +{ + if (err != 0) { + LOG_ERR("Failed to start (failing conn %p): %d", (void *)conn, err); + return; + } + + k_sem_give(&sem_proc); +} + +static int discover_cas(void) +{ + int err; + + LOG_INF("Discovering CAS"); + k_sem_reset(&sem_proc); + + err = bt_cap_initiator_unicast_discover(peer.conn); + if (err != 0) { + LOG_ERR("Failed to discover CAS: %d", err); + return err; + } + + err = k_sem_take(&sem_proc, SEM_TIMEOUT); + if (err != 0) { + LOG_ERR("Timeout on CAS discover: %d", err); + return err; + } + + return err; +} + +static int unicast_audio_start(void) +{ + /* TODO: Expand to start multiple streams on multiple CAP acceptors */ + struct bt_cap_unicast_audio_start_stream_param stream_param[2] = {0}; + struct bt_cap_unicast_audio_start_param param = {0}; + int err; + + LOG_INF("Starting streams"); + + if (peer.sink_ep != NULL) { + stream_param[param.count].member.member = peer.conn; + stream_param[param.count].stream = &peer.sink_stream; + stream_param[param.count].ep = peer.sink_ep; + stream_param[param.count].codec_cfg = &unicast_preset_16_2_1.codec_cfg; + param.count++; + } + + if (peer.source_ep != NULL) { + stream_param[param.count].member.member = peer.conn; + stream_param[param.count].stream = &peer.source_stream; + stream_param[param.count].ep = peer.source_ep; + stream_param[param.count].codec_cfg = &unicast_preset_16_2_1.codec_cfg; + param.count++; + } + + param.type = BT_CAP_SET_TYPE_AD_HOC; + param.stream_params = stream_param; + + err = bt_cap_initiator_unicast_audio_start(¶m); + if (err != 0) { + LOG_ERR("Failed to start unicast audio: %d", err); + return err; + } + + return err; +} + +static void att_mtu_updated_cb(struct bt_conn *conn, uint16_t tx, uint16_t rx) +{ + LOG_INF("MTU exchanged: %u/%u", tx, rx); + k_sem_give(&sem_mtu_exchanged); +} + +static void start_scan(void) +{ + int err; + + err = bt_le_scan_start(BT_LE_SCAN_PASSIVE, NULL); + if (err != 0) { + LOG_ERR("Scanning failed to start: %d", err); + return; + } + + LOG_INF("Scanning successfully started"); +} + +static void connected_cb(struct bt_conn *conn, uint8_t err) +{ + char addr[BT_ADDR_LE_STR_LEN]; + + (void)bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr)); + + if (err != 0) { + LOG_ERR("Failed to connect to %s: %u", addr, err); + + bt_conn_unref(peer.conn); + peer.conn = NULL; + + start_scan(); + return; + } + + if (conn != peer.conn) { + return; + } + + LOG_INF("Connected: %s", addr); + k_sem_give(&sem_state_change); +} + +static void disconnected_cb(struct bt_conn *conn, uint8_t reason) +{ + char addr[BT_ADDR_LE_STR_LEN]; + + if (conn != peer.conn) { + return; + } + + (void)bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr)); + + LOG_INF("Disconnected: %s (reason 0x%02x)", addr, reason); + + bt_conn_unref(peer.conn); + peer.conn = NULL; + + k_sem_give(&sem_state_change); +} + +static void security_changed_cb(struct bt_conn *conn, bt_security_t level, + enum bt_security_err sec_err) +{ + if (sec_err == 0) { + LOG_INF("Security changed: %u", level); + k_sem_give(&sem_security_changed); + } else { + LOG_ERR("Failed to set security level: %d", sec_err); + + if (sec_err == BT_SECURITY_ERR_PIN_OR_KEY_MISSING) { + int err; + + LOG_INF("Removing old key"); + err = bt_unpair(BT_ID_DEFAULT, bt_conn_get_dst(conn)); + if (err != 0) { + LOG_ERR("Failed to remove old key: %d", err); + } + } + } +} + +BT_CONN_CB_DEFINE(conn_callbacks) = { + .connected = connected_cb, + .disconnected = disconnected_cb, + .security_changed = security_changed_cb, +}; + +static bool check_audio_support_and_connect_cb(struct bt_data *data, void *user_data) +{ + char addr_str[BT_ADDR_LE_STR_LEN]; + bt_addr_le_t *addr = user_data; + const struct bt_uuid *uuid; + uint16_t uuid_val; + int err; + + LOG_DBG("[AD]: %u data_len %u", data->type, data->data_len); + + if (data->type != BT_DATA_SVC_DATA16) { + return true; /* Continue parsing to next AD data type */ + } + + if (data->data_len < sizeof(uuid_val)) { + LOG_DBG("AD invalid size %u", data->data_len); + return true; /* Continue parsing to next AD data type */ + } + + /* We are looking for the CAS service data */ + uuid_val = sys_get_le16(data->data); + uuid = BT_UUID_DECLARE_16(uuid_val); + if (bt_uuid_cmp(uuid, BT_UUID_CAS) != 0) { + return true; /* Continue parsing to next AD data type */ + } + + bt_addr_le_to_str(addr, addr_str, sizeof(addr_str)); + LOG_INF("Attempt to connect to %s", addr_str); + + err = bt_le_scan_stop(); + if (err != 0) { + LOG_ERR("Failed to stop scan: %d", err); + return false; + } + + err = bt_conn_le_create(addr, BT_CONN_LE_CREATE_CONN, BT_LE_CONN_PARAM_DEFAULT, &peer.conn); + if (err != 0) { + LOG_WRN("Create conn to failed: %d, restarting scan", err); + start_scan(); + } + + return false; /* Stop parsing */ +} + +static void scan_recv_cb(const struct bt_le_scan_recv_info *info, struct net_buf_simple *buf) +{ + if (peer.conn != NULL) { + /* Already connected */ + return; + } + + /* Check for connectable, extended advertising */ + if (((info->adv_props & BT_GAP_ADV_PROP_EXT_ADV) != 0) && + ((info->adv_props & BT_GAP_ADV_PROP_CONNECTABLE)) != 0) { + /* Check for TMAS support in advertising data */ + bt_data_parse(buf, check_audio_support_and_connect_cb, (void *)info->addr); + } +} + +static int scan_and_connect(void) +{ + int err; + + start_scan(); + + err = k_sem_take(&sem_state_change, K_FOREVER); + if (err != 0) { + LOG_ERR("Failed to take sem_state_change: %d", err); + return err; + } + + return 0; +} + +static void exchange_cb(struct bt_conn *conn, uint8_t err, struct bt_gatt_exchange_params *params) +{ + if (err == BT_ATT_ERR_SUCCESS) { + LOG_INF("MTU exchange done"); + k_sem_give(&sem_proc); + } else { + LOG_ERR("MTU exchange failed: err %u", err); + } +} + +static int exchange_mtu(void) +{ + int err; + + if (!IS_ENABLED(CONFIG_BT_GATT_AUTO_UPDATE_MTU)) { + static struct bt_gatt_exchange_params exchange_params = { + .func = exchange_cb, + }; + + LOG_INF("Exchanging MTU"); + + k_sem_reset(&sem_proc); + + err = bt_gatt_exchange_mtu(peer.conn, &exchange_params); + if (err != 0) { + LOG_ERR("Failed to exchange MTU: %d", err); + } + + err = k_sem_take(&sem_proc, SEM_TIMEOUT); + if (err != 0) { + LOG_ERR("Timeout on MTU exchange request: %d", err); + return err; + } + } + + LOG_INF("Waiting for MTU exchange"); + err = k_sem_take(&sem_mtu_exchanged, SEM_TIMEOUT); + if (err != 0) { + LOG_ERR("Timeout on MTU exchange: %d", err); + return err; + } + + return 0; +} + +static int update_security(void) +{ + int err; + + err = bt_conn_set_security(peer.conn, BT_SECURITY_L2); + if (err != 0) { + LOG_ERR("Failed to set security: %d", err); + return err; + } + + LOG_INF("Waiting for security change"); + err = k_sem_take(&sem_security_changed, SEM_TIMEOUT); + if (err != 0) { + LOG_ERR("Timeout on security: %d", err); + return err; + } + + return 0; +} + +static int init_cap_initiator(void) +{ + static struct bt_bap_unicast_client_cb unicast_client_cbs = { + .discover = discover_cb, + .pac_record = pac_record_cb, + .endpoint = endpoint_cb, + }; + static struct bt_cap_initiator_cb cap_cb = { + .unicast_discovery_complete = cap_discovery_complete_cb, + .unicast_start_complete = unicast_start_complete_cb, + }; + static struct bt_gatt_cb gatt_callbacks = { + .att_mtu_updated = att_mtu_updated_cb, + }; + static struct bt_le_scan_cb scan_callbacks = { + .recv = scan_recv_cb, + }; + int err; + + err = bt_cap_initiator_register_cb(&cap_cb); + if (err != 0) { + LOG_ERR("Failed to register CAP callbacks: %d", err); + + return err; + } + + err = bt_bap_unicast_client_register_cb(&unicast_client_cbs); + if (err != 0) { + LOG_ERR("Failed to register BAP unicast client callbacks: %d", err); + + return err; + } + + bt_gatt_cb_register(&gatt_callbacks); + bt_le_scan_cb_register(&scan_callbacks); + + k_sem_init(&peer.source_stream_sem, 0, 1); + k_sem_init(&peer.sink_stream_sem, 0, 1); + + return 0; +} + +static int reset_cap_initiator(void) +{ + int err; + + LOG_INF("Resetting"); + + if (peer.conn != NULL) { + err = bt_conn_disconnect(peer.conn, BT_HCI_ERR_REMOTE_USER_TERM_CONN); + if (err != 0) { + return err; + } + + err = k_sem_take(&sem_state_change, K_FOREVER); + if (err != 0) { + LOG_ERR("Timeout on disconnect: %d", err); + return err; + } + } + + if (peer.source_stream.bap_stream.ep != NULL) { + err = k_sem_take(&peer.source_stream_sem, SEM_TIMEOUT); + if (err != 0) { + LOG_ERR("Timeout on source_stream_sem: %d", err); + return err; + } + } + + if (peer.sink_stream.bap_stream.ep != NULL) { + err = k_sem_take(&peer.sink_stream_sem, SEM_TIMEOUT); + if (err != 0) { + LOG_ERR("Timeout on sink_stream_sem: %d", err); + return err; + } + } + + if (unicast_group != NULL) { + int err; + + err = unicast_group_delete(); + if (err != 0) { + return err; + } + + return err; + } + + peer.source_ep = NULL; + peer.sink_ep = NULL; + k_sem_reset(&sem_proc); + k_sem_reset(&sem_state_change); + k_sem_reset(&sem_mtu_exchanged); + + return 0; +} + +int cap_initiator_unicast(void) +{ + int err; + + err = init_cap_initiator(); + if (err != 0) { + return err; + } + + LOG_INF("CAP initiator unicast initialized"); + + while (true) { + err = reset_cap_initiator(); + if (err != 0) { + LOG_ERR("Failed to reset"); + + return err; + } + + /* Start scanning for and connecting to CAP Acceptors. CAP Acceptors are identified + * by their advertising data + */ + err = scan_and_connect(); + if (err != 0) { + continue; + } + + /* BAP mandates support for an MTU of at least 65 octets. Because of that, we + * should always exchange the MTU before accessing BAP related services to ensure + * correctness + */ + err = exchange_mtu(); + if (err != 0) { + continue; + } + + /* LE Audio services require encryption with LE Secure Connections, so we increase + * security before attempting to do any LE Audio operations + */ + err = update_security(); + if (err != 0) { + continue; + } + + /* All remote CAP Acceptors shall have the Common Audio Service (CAS) so we start by + * discovering that on the remote device to determine if they are really CAP + * Acceptors. If they are only a BAP Unicast Server we ignore them. + */ + err = discover_cas(); + if (err != 0) { + continue; + } + + /* Discover sink ASEs and capabilities. This may not result in any endpoints if they + * remote device is only a source (e.g. a microphone) + */ + err = discover_sinks(); + if (err != 0) { + continue; + } + + /* Discover source ASEs and capabilities. This may not result in any endpoints if + * they remote device is only a sink (e.g. a speaker) + */ + err = discover_sources(); + if (err != 0) { + continue; + } + + /* Create a unicast group (Connected Isochronous Group (CIG)) based on what we have + * found on the remote device + */ + err = unicast_group_create(); + if (err != 0) { + continue; + } + + /* Execute the start operation which will take one or more streams into the + * streaming state + */ + err = unicast_audio_start(); + if (err != 0) { + continue; + } + + /* Reset if disconnected */ + err = k_sem_take(&sem_state_change, K_FOREVER); + if (err != 0) { + LOG_ERR("Failed to take sem_state_change: err %d", err); + + return err; + } + } + + return 0; +} diff --git a/samples/bluetooth/cap_initiator/src/main.c b/samples/bluetooth/cap_initiator/src/main.c new file mode 100644 index 0000000000000..f40a2a517f5d1 --- /dev/null +++ b/samples/bluetooth/cap_initiator/src/main.c @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +#include +#include +#include +#include +#include + +#include "cap_initiator.h" + +LOG_MODULE_REGISTER(cap_initiator, LOG_LEVEL_INF); + +int main(void) +{ + int err; + + err = bt_enable(NULL); + if (err != 0) { + LOG_ERR("Bluetooth enable failed: %d", err); + + return 0; + } + + LOG_INF("Bluetooth initialized"); + + /* TODO: Add CAP initiator broadcast support*/ + + /* If the CONFIG_BT_CAP_INITIATOR_UNICAST is enabled we call the cap_initiator_unicast + * function that runs the application as a CAP Initiator for unicast. This will attempt to + * scan for and connect to a CAP acceptor to set up a stream + * + * Since cap_initiator_unicast runs as a while (true) loop, this shall be done as the last + * thing in this function + */ + if (IS_ENABLED(CONFIG_BT_CAP_INITIATOR_UNICAST)) { + err = cap_initiator_unicast(); + } + + if (err != 0) { + LOG_ERR("Failed to run CAP Initiator: %d", err); + } + + return 0; +} diff --git a/samples/bluetooth/cap_initiator/sysbuild.cmake b/samples/bluetooth/cap_initiator/sysbuild.cmake new file mode 100644 index 0000000000000..2523aac8ea76f --- /dev/null +++ b/samples/bluetooth/cap_initiator/sysbuild.cmake @@ -0,0 +1,24 @@ +# Copyright (c) 2023 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +if(SB_CONFIG_NET_CORE_IMAGE_HCI_IPC) + # For builds in the nrf5340, we build the netcore image with the controller + + set(NET_APP hci_ipc) + set(NET_APP_SRC_DIR ${ZEPHYR_BASE}/samples/bluetooth/${NET_APP}) + + ExternalZephyrProject_Add( + APPLICATION ${NET_APP} + SOURCE_DIR ${NET_APP_SRC_DIR} + BOARD ${SB_CONFIG_NET_CORE_BOARD} + ) + + set(${NET_APP}_CONF_FILE + ${NET_APP_SRC_DIR}/nrf5340_cpunet_iso-bt_ll_sw_split.conf + CACHE INTERNAL "" + ) + + native_simulator_set_child_images(${DEFAULT_IMAGE} ${NET_APP}) +endif() + +native_simulator_set_final_executable(${DEFAULT_IMAGE}) From daf7d8066a1bc5fe9e1b431a89ad339d8b698e59 Mon Sep 17 00:00:00 2001 From: Emil Gydesen Date: Wed, 1 May 2024 11:36:23 +0200 Subject: [PATCH 2587/2849] Samples: Bluetooth: Add CAP acceptor unicast sample Adds a CAP acceptor unicast sample that simply uses the CAP acceptor implementation to setup streams with a CAP initiator. To keep it simple no audio or encoding support has been added. Signed-off-by: Emil Gydesen --- samples/bluetooth/cap_acceptor/CMakeLists.txt | 12 + .../bluetooth/cap_acceptor/Kconfig.sysbuild | 15 + samples/bluetooth/cap_acceptor/README.rst | 74 ++++ .../cap_acceptor/overlay-bt_ll_sw_split.conf | 13 + samples/bluetooth/cap_acceptor/prj.conf | 36 ++ samples/bluetooth/cap_acceptor/sample.yaml | 30 ++ .../bluetooth/cap_acceptor/src/cap_acceptor.h | 56 +++ .../cap_acceptor/src/cap_acceptor_unicast.c | 356 ++++++++++++++++++ samples/bluetooth/cap_acceptor/src/main.c | 348 +++++++++++++++++ samples/bluetooth/cap_acceptor/sysbuild.cmake | 24 ++ 10 files changed, 964 insertions(+) create mode 100644 samples/bluetooth/cap_acceptor/CMakeLists.txt create mode 100644 samples/bluetooth/cap_acceptor/Kconfig.sysbuild create mode 100644 samples/bluetooth/cap_acceptor/README.rst create mode 100644 samples/bluetooth/cap_acceptor/overlay-bt_ll_sw_split.conf create mode 100644 samples/bluetooth/cap_acceptor/prj.conf create mode 100644 samples/bluetooth/cap_acceptor/sample.yaml create mode 100644 samples/bluetooth/cap_acceptor/src/cap_acceptor.h create mode 100644 samples/bluetooth/cap_acceptor/src/cap_acceptor_unicast.c create mode 100644 samples/bluetooth/cap_acceptor/src/main.c create mode 100644 samples/bluetooth/cap_acceptor/sysbuild.cmake diff --git a/samples/bluetooth/cap_acceptor/CMakeLists.txt b/samples/bluetooth/cap_acceptor/CMakeLists.txt new file mode 100644 index 0000000000000..f8d344cc9810f --- /dev/null +++ b/samples/bluetooth/cap_acceptor/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(cap_acceptor) + +target_sources(app PRIVATE + src/main.c + src/cap_acceptor_unicast.c +) + +zephyr_library_include_directories(${ZEPHYR_BASE}/samples/bluetooth) diff --git a/samples/bluetooth/cap_acceptor/Kconfig.sysbuild b/samples/bluetooth/cap_acceptor/Kconfig.sysbuild new file mode 100644 index 0000000000000..f37b265ecbc27 --- /dev/null +++ b/samples/bluetooth/cap_acceptor/Kconfig.sysbuild @@ -0,0 +1,15 @@ +# Copyright 2023 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +source "share/sysbuild/Kconfig" + +config NET_CORE_BOARD + string + default "nrf5340dk/nrf5340/cpunet" if "$(BOARD)" = "nrf5340dk" + default "nrf5340_audio_dk/nrf5340/cpunet" if "$(BOARD)" = "nrf5340_audio_dk" + default "nrf5340bsim/nrf5340/cpunet" if $(BOARD_TARGET_STRING) = "NRF5340BSIM_NRF5340_CPUAPP" + +config NET_CORE_IMAGE_HCI_IPC + bool "HCI IPC image on network core" + default y + depends on NET_CORE_BOARD != "" diff --git a/samples/bluetooth/cap_acceptor/README.rst b/samples/bluetooth/cap_acceptor/README.rst new file mode 100644 index 0000000000000..dce148cfd0116 --- /dev/null +++ b/samples/bluetooth/cap_acceptor/README.rst @@ -0,0 +1,74 @@ +.. zephyr:code-sample:: bluetooth_cap_acceptor + :name: Bluetooth: Common Audio Profile Acceptor + :relevant-api: bt_cap bt_bap bluetooth + + CAP Acceptor sample that advertises audio availability to CAP Initiators. + +Overview +******** + +Application demonstrating the CAP Acceptor functionality. +Starts by advertising for a CAP Initiator to connect and set up available streams. + +This sample can be found under :zephyr_file:`samples/bluetooth/cap_acceptor` in the Zephyr tree. + +Check the :ref:`bluetooth samples section ` for general information. + +Requirements +************ + +* BlueZ running on the host, or +* A board with Bluetooth Low Energy 5.2 support + +Building and Running +******************** + +When building targeting an nrf52 series board with the Zephyr Bluetooth Controller, +use ``-DOVERLAY_CONFIG=overlay-bt_ll_sw_split.conf`` to enable the required ISO +feature support. + +Building for an nrf5340dk +------------------------- + +You can build both the application core image and an appropriate controller image for the network +core with: + +.. zephyr-app-commands:: + :zephyr-app: samples/bluetooth/cap_acceptor/ + :board: nrf5340dk/nrf5340/cpuapp + :goals: build + :west-args: --sysbuild + +If you prefer to only build the application core image, you can do so by doing instead: + +.. zephyr-app-commands:: + :zephyr-app: samples/bluetooth/cap_acceptor/ + :board: nrf5340dk/nrf5340/cpuapp + :goals: build + +In that case you can pair this application core image with the +:ref:`hci_ipc sample ` +:zephyr_file:`samples/bluetooth/hci_ipc/nrf5340_cpunet_iso-bt_ll_sw_split.conf` configuration. + +Building for a simulated nrf5340bsim +------------------------------------ + +Similarly to how you would for real HW, you can do: + +.. zephyr-app-commands:: + :zephyr-app: samples/bluetooth/cap_acceptor/ + :board: nrf5340bsim/nrf5340/cpuapp + :goals: build + :west-args: --sysbuild + +Note this will produce a Linux executable in `./build/zephyr/zephyr.exe`. +For more information, check :ref:`this board documentation `. + +Building for a simulated nrf52_bsim +----------------------------------- + +.. zephyr-app-commands:: + :zephyr-app: samples/bluetooth/cap_acceptor/ + :board: nrf52_bsim + :goals: build + :gen-args: -DOVERLAY_CONFIG=overlay-bt_ll_sw_split.conf diff --git a/samples/bluetooth/cap_acceptor/overlay-bt_ll_sw_split.conf b/samples/bluetooth/cap_acceptor/overlay-bt_ll_sw_split.conf new file mode 100644 index 0000000000000..e4bcdbad7c533 --- /dev/null +++ b/samples/bluetooth/cap_acceptor/overlay-bt_ll_sw_split.conf @@ -0,0 +1,13 @@ +# 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 central ISO in Zephyr Bluetooth Controller +CONFIG_BT_CTLR_PERIPHERAL_ISO=y + +# 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/cap_acceptor/prj.conf b/samples/bluetooth/cap_acceptor/prj.conf new file mode 100644 index 0000000000000..4a67de1e58226 --- /dev/null +++ b/samples/bluetooth/cap_acceptor/prj.conf @@ -0,0 +1,36 @@ +CONFIG_BT=y +CONFIG_LOG=y +CONFIG_BT_PERIPHERAL=y +CONFIG_BT_ISO_PERIPHERAL=y +CONFIG_BT_GATT_DYNAMIC_DB=y +CONFIG_BT_GATT_CLIENT=y +CONFIG_BT_EXT_ADV=y +CONFIG_BT_DEVICE_NAME="CAP Acceptor" + +CONFIG_BT_AUDIO=y + +CONFIG_BT_SMP=y +CONFIG_BT_KEYS_OVERWRITE_OLDEST=y + +# CAP +CONFIG_BT_CAP_ACCEPTOR=y + +# BAP support +CONFIG_BT_BAP_UNICAST_SERVER=y + +# Mandatory to support at least 1 for ASCS +CONFIG_BT_ATT_PREPARE_COUNT=1 + +# Support an ISO channel per ASE +CONFIG_BT_ASCS=y +CONFIG_BT_ASCS_ASE_SNK_COUNT=1 +CONFIG_BT_ASCS_ASE_SRC_COUNT=1 + +# Support an ISO channel per ASE +CONFIG_BT_ISO_MAX_CHAN=2 + +# PACS +CONFIG_BT_PAC_SNK=y +CONFIG_BT_PAC_SNK_LOC=y +CONFIG_BT_PAC_SRC=y +CONFIG_BT_PAC_SRC_LOC=y diff --git a/samples/bluetooth/cap_acceptor/sample.yaml b/samples/bluetooth/cap_acceptor/sample.yaml new file mode 100644 index 0000000000000..6be99aab18382 --- /dev/null +++ b/samples/bluetooth/cap_acceptor/sample.yaml @@ -0,0 +1,30 @@ +sample: + description: Bluetooth Low Energy Common Audio Profile Acceptor sample + name: Bluetooth Low Energy Common Audio Profile Acceptor sample +tests: + sample.bluetooth.cap_acceptor: + harness: bluetooth + platform_allow: + - qemu_cortex_m3 + - qemu_x86 + - nrf5340dk/nrf5340/cpuapp + - nrf5340bsim/nrf5340/cpuapp + integration_platforms: + - qemu_x86 + - nrf5340dk/nrf5340/cpuapp + tags: bluetooth + sysbuild: true + sample.bluetooth.cap_acceptor.bt_ll_sw_split: + harness: bluetooth + platform_allow: + - nrf52_bsim + - nrf52833dk/nrf52833 + - nrf52840dk/nrf52840 + - nrf52840dongle/nrf52840 + integration_platforms: + - nrf52_bsim + - nrf52833dk/nrf52833 + - nrf52840dk/nrf52840 + - nrf52840dongle/nrf52840 + extra_args: OVERLAY_CONFIG=overlay-bt_ll_sw_split.conf + tags: bluetooth diff --git a/samples/bluetooth/cap_acceptor/src/cap_acceptor.h b/samples/bluetooth/cap_acceptor/src/cap_acceptor.h new file mode 100644 index 0000000000000..20c8da5f1d106 --- /dev/null +++ b/samples/bluetooth/cap_acceptor/src/cap_acceptor.h @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include + +#define SINK_CONTEXT BT_AUDIO_CONTEXT_TYPE_UNSPECIFIED +#define SOURCE_CONTEXT BT_AUDIO_CONTEXT_TYPE_UNSPECIFIED + +/** Struct to contain information for a specific peer (CAP) device */ +struct peer_config { + /** Stream for the source endpoint */ + struct bt_cap_stream source_stream; + /** Stream for the sink endpoint */ + struct bt_cap_stream sink_stream; + /** Semaphore to help wait for a release operation if the source stream is not idle */ + struct k_sem source_stream_sem; + /** Semaphore to help wait for a release operation if the sink stream is not idle */ + struct k_sem sink_stream_sem; + /** ACL connection object for the peer device */ + struct bt_conn *conn; +}; + +/** + * @brief Initialize the unicast part of the CAP Acceptor + * + * @param peer Pointer to the specific peer to initialize the CAP Acceptor for + * + * @retval 0 if success + * @retval -ENOEXEC if callbacks failed to be registered + */ +int init_cap_acceptor_unicast(struct peer_config *peer); + +/** + * @brief Request to allocate a CAP stream + * + * @param dir Audio direction of the stream to allocate + * + * @retval Pointer to the allocated CAP stream + * @retval NULL if no more CAP streams for the @p dir could be allocated + */ +struct bt_cap_stream *stream_alloc(enum bt_audio_dir dir); + +/** + * Notify about a released stream + + * This is used to handle some state checks in the main.c file. + * + * @param cap_stream Pointer to the stream that was released + */ +void stream_released(const struct bt_cap_stream *cap_stream); diff --git a/samples/bluetooth/cap_acceptor/src/cap_acceptor_unicast.c b/samples/bluetooth/cap_acceptor/src/cap_acceptor_unicast.c new file mode 100644 index 0000000000000..87358f79b3ed8 --- /dev/null +++ b/samples/bluetooth/cap_acceptor/src/cap_acceptor_unicast.c @@ -0,0 +1,356 @@ +/** @file + * @brief Bluetooth Common Audio Profile (CAP) Acceptor unicast. + * + * Copyright (c) 2021-2024 Nordic Semiconductor ASA + * Copyright (c) 2023 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "cap_acceptor.h" + +LOG_MODULE_REGISTER(cap_acceptor_unicast, LOG_LEVEL_INF); + +#define PREF_PHY BT_GAP_LE_PHY_2M +#define MIN_PD 20000U +#define MAX_PD 40000U +#define UNFRAMED_SUPPORTED true +#define LATENCY 20U +#define RTN 2U + +static const struct bt_audio_codec_qos_pref qos_pref = BT_AUDIO_CODEC_QOS_PREF( + UNFRAMED_SUPPORTED, PREF_PHY, RTN, LATENCY, MIN_PD, MAX_PD, MIN_PD, MAX_PD); + +static bool log_codec_cfg_cb(struct bt_data *data, void *user_data) +{ + const char *str = (const char *)user_data; + + LOG_DBG("\t%s: type 0x%02x value_len %u", str, data->type, data->data_len); + LOG_HEXDUMP_DBG(data->data, data->data_len, "\t\tdata"); + + return true; +} + +static void log_codec_cfg(const struct bt_audio_codec_cfg *codec_cfg) +{ + LOG_INF("codec_cfg 0x%02x cid 0x%04x vid 0x%04x count %u", codec_cfg->id, codec_cfg->cid, + codec_cfg->vid, codec_cfg->data_len); + + if (codec_cfg->id == BT_HCI_CODING_FORMAT_LC3) { + enum bt_audio_location chan_allocation; + int ret; + + /* LC3 uses the generic LTV format - other codecs might do as well */ + + bt_audio_data_parse(codec_cfg->data, codec_cfg->data_len, log_codec_cfg_cb, "data"); + + ret = bt_audio_codec_cfg_get_freq(codec_cfg); + if (ret > 0) { + LOG_INF("\tFrequency: %d Hz", bt_audio_codec_cfg_freq_to_freq_hz(ret)); + } + + ret = bt_audio_codec_cfg_get_frame_dur(codec_cfg); + if (ret > 0) { + LOG_INF("\tFrame Duration: %d us", + bt_audio_codec_cfg_frame_dur_to_frame_dur_us(ret)); + } + + if (bt_audio_codec_cfg_get_chan_allocation(codec_cfg, &chan_allocation) == 0) { + LOG_INF("\tChannel allocation: 0x%08X", chan_allocation); + } + + ret = bt_audio_codec_cfg_get_octets_per_frame(codec_cfg); + if (ret > 0) { + LOG_INF("\tOctets per frame: %d", ret); + } + + LOG_INF("\tFrames per SDU: %d", + bt_audio_codec_cfg_get_frame_blocks_per_sdu(codec_cfg, true)); + } else { + LOG_HEXDUMP_DBG(codec_cfg->data, codec_cfg->data_len, "data"); + } + + bt_audio_data_parse(codec_cfg->meta, codec_cfg->meta_len, log_codec_cfg_cb, "meta"); +} + +static void log_qos(const struct bt_audio_codec_qos *qos) +{ + LOG_INF("QoS: interval %u framing 0x%02x phy 0x%02x sdu %u rtn %u latency %u pd %u", + qos->interval, qos->framing, qos->phy, qos->sdu, qos->rtn, qos->latency, qos->pd); +} + +static int unicast_server_config_cb(struct bt_conn *conn, const struct bt_bap_ep *ep, + enum bt_audio_dir dir, + const struct bt_audio_codec_cfg *codec_cfg, + struct bt_bap_stream **bap_stream, + struct bt_audio_codec_qos_pref *const pref, + struct bt_bap_ascs_rsp *rsp) +{ + struct bt_cap_stream *cap_stream; + + LOG_INF("ASE Codec Config: conn %p ep %p dir %u", (void *)conn, (void *)ep, dir); + + log_codec_cfg(codec_cfg); + + cap_stream = stream_alloc(dir); + if (cap_stream == NULL) { + LOG_WRN("No streams available"); + *rsp = BT_BAP_ASCS_RSP(BT_BAP_ASCS_RSP_CODE_NO_MEM, BT_BAP_ASCS_REASON_NONE); + + return -ENOMEM; + } + + *bap_stream = &cap_stream->bap_stream; + + LOG_INF("ASE Codec Config bap_stream %p", *bap_stream); + + *pref = qos_pref; + + return 0; +} + +static int unicast_server_reconfig_cb(struct bt_bap_stream *bap_stream, enum bt_audio_dir dir, + const struct bt_audio_codec_cfg *codec_cfg, + struct bt_audio_codec_qos_pref *const pref, + struct bt_bap_ascs_rsp *rsp) +{ + LOG_INF("ASE Codec Reconfig: bap_stream %p", bap_stream); + log_codec_cfg(codec_cfg); + *pref = qos_pref; + + return 0; +} + +static int unicast_server_qos_cb(struct bt_bap_stream *bap_stream, + const struct bt_audio_codec_qos *qos, struct bt_bap_ascs_rsp *rsp) +{ + LOG_INF("QoS: bap_stream %p qos %p", bap_stream, qos); + + log_qos(qos); + + return 0; +} + +static int unicast_server_enable_cb(struct bt_bap_stream *bap_stream, const uint8_t meta[], + size_t meta_len, struct bt_bap_ascs_rsp *rsp) +{ + LOG_INF("Enable: bap_stream %p meta_len %zu", bap_stream, meta_len); + + return 0; +} + +static int unicast_server_start_cb(struct bt_bap_stream *bap_stream, struct bt_bap_ascs_rsp *rsp) +{ + LOG_INF("Start: bap_stream %p", bap_stream); + + return 0; +} + +struct data_func_param { + struct bt_bap_ascs_rsp *rsp; + bool stream_context_present; +}; + +static bool data_func_cb(struct bt_data *data, void *user_data) +{ + struct data_func_param *func_param = (struct data_func_param *)user_data; + + if (data->type == BT_AUDIO_METADATA_TYPE_STREAM_CONTEXT) { + func_param->stream_context_present = true; + } + + return true; +} + +static int unicast_server_metadata_cb(struct bt_bap_stream *bap_stream, const uint8_t meta[], + size_t meta_len, struct bt_bap_ascs_rsp *rsp) +{ + struct data_func_param func_param = { + .rsp = rsp, + .stream_context_present = false, + }; + int err; + + LOG_INF("Metadata: bap_stream %p meta_len %zu", bap_stream, meta_len); + + err = bt_audio_data_parse(meta, meta_len, data_func_cb, &func_param); + if (err != 0) { + return err; + } + + if (!func_param.stream_context_present) { + LOG_ERR("Stream audio context not present"); + *rsp = BT_BAP_ASCS_RSP(BT_BAP_ASCS_RSP_CODE_METADATA_REJECTED, + BT_BAP_ASCS_REASON_NONE); + + return -EINVAL; + } + + return 0; +} + +static int unicast_server_disable_cb(struct bt_bap_stream *bap_stream, struct bt_bap_ascs_rsp *rsp) +{ + LOG_INF("Disable: bap_stream %p", bap_stream); + + return 0; +} + +static int unicast_server_stop_cb(struct bt_bap_stream *bap_stream, struct bt_bap_ascs_rsp *rsp) +{ + LOG_INF("Stop: bap_stream %p", bap_stream); + + return 0; +} + +static int unicast_server_release_cb(struct bt_bap_stream *bap_stream, struct bt_bap_ascs_rsp *rsp) +{ + LOG_INF("Release: bap_stream %p", bap_stream); + + return 0; +} + +static const struct bt_bap_unicast_server_cb unicast_server_cb = { + .config = unicast_server_config_cb, + .reconfig = unicast_server_reconfig_cb, + .qos = unicast_server_qos_cb, + .enable = unicast_server_enable_cb, + .start = unicast_server_start_cb, + .metadata = unicast_server_metadata_cb, + .disable = unicast_server_disable_cb, + .stop = unicast_server_stop_cb, + .release = unicast_server_release_cb, +}; + +static void unicast_stream_configured_cb(struct bt_bap_stream *bap_stream, + const struct bt_audio_codec_qos_pref *pref) +{ + LOG_INF("Configured bap_stream %p", bap_stream); + + /* TODO: The preference should be used/taken into account when + * setting the QoS + */ + + LOG_INF("Local preferences: unframed %s, phy %u, rtn %u, latency %u, pd_min %u, pd_max " + "%u, pref_pd_min %u, pref_pd_max %u", + pref->unframed_supported ? "supported" : "not supported", pref->phy, pref->rtn, + pref->latency, pref->pd_min, pref->pd_max, pref->pref_pd_min, pref->pref_pd_max); +} + +static void unicast_stream_qos_set_cb(struct bt_bap_stream *bap_stream) +{ + LOG_INF("QoS set bap_stream %p", bap_stream); +} + +static void unicast_stream_enabled_cb(struct bt_bap_stream *bap_stream) +{ + struct bt_bap_ep_info ep_info; + int err; + + LOG_INF("Enabled bap_stream %p", bap_stream); + + err = bt_bap_ep_get_info(bap_stream->ep, &ep_info); + if (err != 0) { + LOG_ERR("Failed to get ep info: %d", err); + + return; + } + + if (ep_info.dir == BT_AUDIO_DIR_SINK) { + /* Automatically do the receiver start ready operation */ + err = bt_bap_stream_start(bap_stream); + if (err != 0) { + LOG_ERR("Failed to start: %d", err); + + return; + } + } +} + +static void unicast_stream_started_cb(struct bt_bap_stream *bap_stream) +{ + LOG_INF("Started bap_stream %p", bap_stream); +} + +static void unicast_stream_metadata_updated_cb(struct bt_bap_stream *bap_stream) +{ + LOG_INF("Metadata updated bap_stream %p", bap_stream); +} + +static void unicast_stream_disabled_cb(struct bt_bap_stream *bap_stream) +{ + LOG_INF("Disabled bap_stream %p", bap_stream); +} + +static void unicast_stream_stopped_cb(struct bt_bap_stream *bap_stream, uint8_t reason) +{ + LOG_INF("Stopped bap_stream %p with reason 0x%02X", bap_stream, reason); +} + +static void unicast_stream_released_cb(struct bt_bap_stream *bap_stream) +{ + struct bt_cap_stream *cap_stream = + CONTAINER_OF(bap_stream, struct bt_cap_stream, bap_stream); + + LOG_INF("Released bap_stream %p", bap_stream); + + stream_released(cap_stream); +} + +static void unicast_stream_recv_cb(struct bt_bap_stream *bap_stream, + const struct bt_iso_recv_info *info, struct net_buf *buf) +{ + /* TODO: Add test code */ +} + +int init_cap_acceptor_unicast(struct peer_config *peer) +{ + static struct bt_bap_stream_ops unicast_stream_ops = { + .configured = unicast_stream_configured_cb, + .qos_set = unicast_stream_qos_set_cb, + .enabled = unicast_stream_enabled_cb, + .started = unicast_stream_started_cb, + .metadata_updated = unicast_stream_metadata_updated_cb, + .disabled = unicast_stream_disabled_cb, + .stopped = unicast_stream_stopped_cb, + .released = unicast_stream_released_cb, + .recv = unicast_stream_recv_cb, + }; + static bool cbs_registered; + + if (!cbs_registered) { + int err; + + err = bt_bap_unicast_server_register_cb(&unicast_server_cb); + if (err != 0) { + LOG_ERR("Failed to register BAP unicast server callbacks: %d", err); + + return -ENOEXEC; + } + } + + bt_cap_stream_ops_register(&peer->source_stream, &unicast_stream_ops); + bt_cap_stream_ops_register(&peer->sink_stream, &unicast_stream_ops); + + return 0; +} diff --git a/samples/bluetooth/cap_acceptor/src/main.c b/samples/bluetooth/cap_acceptor/src/main.c new file mode 100644 index 0000000000000..fe53bcb7eaae2 --- /dev/null +++ b/samples/bluetooth/cap_acceptor/src/main.c @@ -0,0 +1,348 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "cap_acceptor.h" + +LOG_MODULE_REGISTER(cap_acceptor, LOG_LEVEL_INF); + +#define SUPPORTED_DURATION (BT_AUDIO_CODEC_CAP_DURATION_7_5 | BT_AUDIO_CODEC_CAP_DURATION_10) +#define MAX_CHAN_PER_STREAM BT_AUDIO_CODEC_CAP_CHAN_COUNT_SUPPORT(2) +#define SUPPORTED_FREQ BT_AUDIO_CODEC_CAP_FREQ_ANY +#define SEM_TIMEOUT K_SECONDS(5) +#define MAX_SDU 155U +#define MIN_SDU 30U +#define FRAMES_PER_SDU 2 + +static const struct bt_data ad[] = { + BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)), + BT_DATA_BYTES(BT_DATA_UUID16_SOME, BT_UUID_16_ENCODE(BT_UUID_ASCS_VAL), + BT_UUID_16_ENCODE(BT_UUID_CAS_VAL)), + BT_DATA(BT_DATA_NAME_COMPLETE, CONFIG_BT_DEVICE_NAME, sizeof(CONFIG_BT_DEVICE_NAME) - 1), + BT_DATA_BYTES(BT_DATA_SVC_DATA16, + BT_UUID_16_ENCODE(BT_UUID_CAS_VAL), + BT_AUDIO_UNICAST_ANNOUNCEMENT_TARGETED), + IF_ENABLED(CONFIG_BT_BAP_UNICAST_SERVER, + (BT_DATA_BYTES(BT_DATA_SVC_DATA16, + BT_UUID_16_ENCODE(BT_UUID_ASCS_VAL), + BT_AUDIO_UNICAST_ANNOUNCEMENT_TARGETED, + BT_BYTES_LIST_LE16(SINK_CONTEXT), + BT_BYTES_LIST_LE16(SOURCE_CONTEXT), + 0x00, /* Metadata length */), + )) +}; + +static struct bt_le_ext_adv *adv; +static struct peer_config peer; + +static K_SEM_DEFINE(sem_state_change, 0, 1); + +static void connected_cb(struct bt_conn *conn, uint8_t err) +{ + char addr[BT_ADDR_LE_STR_LEN]; + + (void)bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr)); + LOG_INF("Connected: %s", addr); + + peer.conn = bt_conn_ref(conn); + k_sem_give(&sem_state_change); +} + +static void disconnected_cb(struct bt_conn *conn, uint8_t reason) +{ + char addr[BT_ADDR_LE_STR_LEN]; + + if (conn != peer.conn) { + return; + } + + (void)bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr)); + LOG_INF("Disconnected: %s (reason 0x%02x)", addr, reason); + + bt_conn_unref(peer.conn); + peer.conn = NULL; + k_sem_give(&sem_state_change); +} + +BT_CONN_CB_DEFINE(conn_callbacks) = { + .connected = connected_cb, + .disconnected = disconnected_cb, +}; + +static int advertise(void) +{ + int err; + + err = bt_le_ext_adv_create(BT_LE_EXT_ADV_CONN, NULL, &adv); + if (err) { + LOG_ERR("Failed to create advertising set: %d", err); + + return err; + } + + err = bt_le_ext_adv_set_data(adv, ad, ARRAY_SIZE(ad), NULL, 0); + if (err) { + LOG_ERR("Failed to set advertising data: %d", err); + + return err; + } + + err = bt_le_ext_adv_start(adv, BT_LE_EXT_ADV_START_DEFAULT); + if (err) { + LOG_ERR("Failed to start advertising set: %d", err); + + return err; + } + + LOG_INF("Advertising successfully started"); + + /* Wait for connection*/ + err = k_sem_take(&sem_state_change, K_FOREVER); + if (err != 0) { + LOG_ERR("Failed to take sem_state_change: err %d", err); + + return err; + } + + return 0; +} + +struct bt_cap_stream *stream_alloc(enum bt_audio_dir dir) +{ + if (dir == BT_AUDIO_DIR_SINK && peer.sink_stream.bap_stream.ep == NULL) { + return &peer.sink_stream; + } else if (dir == BT_AUDIO_DIR_SOURCE && peer.source_stream.bap_stream.ep == NULL) { + return &peer.source_stream; + } + + return NULL; +} + +void stream_released(const struct bt_cap_stream *cap_stream) +{ + if (cap_stream == &peer.source_stream) { + k_sem_give(&peer.source_stream_sem); + } else if (cap_stream == &peer.sink_stream) { + k_sem_give(&peer.sink_stream_sem); + } +} + +static int reset_cap_acceptor(void) +{ + int err; + + LOG_INF("Resetting"); + + if (peer.conn != NULL) { + err = bt_conn_disconnect(peer.conn, BT_HCI_ERR_REMOTE_USER_TERM_CONN); + if (err != 0) { + return err; + } + + err = k_sem_take(&sem_state_change, K_FOREVER); + if (err != 0) { + LOG_ERR("Timeout on disconnect: %d", err); + return err; + } + } + + if (adv != NULL) { + err = bt_le_ext_adv_stop(adv); + if (err != 0) { + LOG_ERR("Failed to stop advertiser: %d", err); + return err; + } + + err = bt_le_ext_adv_delete(adv); + if (err != 0) { + LOG_ERR("Failed to delete advertiser: %d", err); + return err; + } + + adv = NULL; + } + + if (peer.source_stream.bap_stream.ep != NULL) { + err = k_sem_take(&peer.source_stream_sem, SEM_TIMEOUT); + if (err != 0) { + LOG_ERR("Timeout on source_stream_sem: %d", err); + return err; + } + } + + if (peer.sink_stream.bap_stream.ep != NULL) { + err = k_sem_take(&peer.sink_stream_sem, SEM_TIMEOUT); + if (err != 0) { + LOG_ERR("Timeout on sink_stream_sem: %d", err); + return err; + } + } + + k_sem_reset(&sem_state_change); + + return 0; +} + +/** Register the PAC records for PACS */ +static int register_pac(enum bt_audio_dir dir, enum bt_audio_context context, + struct bt_pacs_cap *cap) +{ + int err; + + err = bt_pacs_cap_register(dir, cap); + if (err != 0) { + LOG_ERR("Failed to register capabilities: %d", err); + + return err; + } + + err = bt_pacs_set_location(dir, BT_AUDIO_LOCATION_MONO_AUDIO); + if (err != 0) { + LOG_ERR("Failed to set location: %d", err); + + return err; + } + + err = bt_pacs_set_supported_contexts(dir, context); + if (err != 0 && err != -EALREADY) { + LOG_ERR("Failed to set supported contexts: %d", err); + + return err; + } + + err = bt_pacs_set_available_contexts(dir, context); + if (err != 0 && err != -EALREADY) { + LOG_ERR("Failed to set available contexts: %d", err); + + return err; + } + + return 0; +} + +static int init_cap_acceptor(void) +{ + static const struct bt_audio_codec_cap lc3_codec_cap = BT_AUDIO_CODEC_CAP_LC3( + SUPPORTED_FREQ, SUPPORTED_DURATION, MAX_CHAN_PER_STREAM, MIN_SDU, MAX_SDU, + FRAMES_PER_SDU, (SINK_CONTEXT | SOURCE_CONTEXT)); + int err; + + err = bt_enable(NULL); + if (err != 0) { + LOG_ERR("Bluetooth enable failed: %d", err); + + return 0; + } + + LOG_INF("Bluetooth initialized"); + + if (IS_ENABLED(CONFIG_BT_PAC_SNK)) { + static struct bt_pacs_cap sink_cap = { + .codec_cap = &lc3_codec_cap, + }; + int err; + + err = register_pac(BT_AUDIO_DIR_SINK, SINK_CONTEXT, &sink_cap); + if (err != 0) { + LOG_ERR("Failed to register sink capabilities: %d", err); + + return -ENOEXEC; + } + } + + if (IS_ENABLED(CONFIG_BT_PAC_SRC)) { + static struct bt_pacs_cap source_cap = { + .codec_cap = &lc3_codec_cap, + }; + int err; + + err = register_pac(BT_AUDIO_DIR_SOURCE, SOURCE_CONTEXT, &source_cap); + if (err != 0) { + LOG_ERR("Failed to register sink capabilities: %d", err); + + return -ENOEXEC; + } + } + + return 0; +} + +int main(void) +{ + int err; + + err = init_cap_acceptor(); + if (err != 0) { + return 0; + } + + if (IS_ENABLED(CONFIG_BT_BAP_UNICAST_SERVER)) { + err = init_cap_acceptor_unicast(&peer); + if (err != 0) { + return 0; + } + } + + LOG_INF("CAP Acceptor initialized"); + + while (true) { + err = reset_cap_acceptor(); + if (err != 0) { + LOG_ERR("Failed to reset"); + + break; + } + + /* Start advertising as a CAP Acceptor, which includes setting the required + * advertising data based on the roles we support. The Common Audio Service data is + * always advertised, as CAP Initiators and CAP Commanders will use this to identify + * our device as a CAP Acceptor. + */ + err = advertise(); + if (err != 0) { + continue; + } + + /* After advertising we expect CAP Initiators to connect to us and setup streams, + * and eventually disconnect again. As a CAP Acceptor we just need to react to their + * requests and not do anything else. + */ + + /* Reset if disconnected */ + err = k_sem_take(&sem_state_change, K_FOREVER); + if (err != 0) { + LOG_ERR("Failed to take sem_state_change: err %d", err); + + break; + } + } + + /* TODO: Add CAP acceptor broadcast support */ + + return 0; +} diff --git a/samples/bluetooth/cap_acceptor/sysbuild.cmake b/samples/bluetooth/cap_acceptor/sysbuild.cmake new file mode 100644 index 0000000000000..2523aac8ea76f --- /dev/null +++ b/samples/bluetooth/cap_acceptor/sysbuild.cmake @@ -0,0 +1,24 @@ +# Copyright (c) 2023 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +if(SB_CONFIG_NET_CORE_IMAGE_HCI_IPC) + # For builds in the nrf5340, we build the netcore image with the controller + + set(NET_APP hci_ipc) + set(NET_APP_SRC_DIR ${ZEPHYR_BASE}/samples/bluetooth/${NET_APP}) + + ExternalZephyrProject_Add( + APPLICATION ${NET_APP} + SOURCE_DIR ${NET_APP_SRC_DIR} + BOARD ${SB_CONFIG_NET_CORE_BOARD} + ) + + set(${NET_APP}_CONF_FILE + ${NET_APP_SRC_DIR}/nrf5340_cpunet_iso-bt_ll_sw_split.conf + CACHE INTERNAL "" + ) + + native_simulator_set_child_images(${DEFAULT_IMAGE} ${NET_APP}) +endif() + +native_simulator_set_final_executable(${DEFAULT_IMAGE}) From c07a87abbb8509e19cd7882639c9e3d0d65a4618 Mon Sep 17 00:00:00 2001 From: Emil Gydesen Date: Wed, 1 May 2024 11:46:47 +0200 Subject: [PATCH 2588/2849] tests: Bluetooth: Audio: Add BSIM test of the CAP samples Adds babblesim tests of the CAP Acceptor and the CAP Initiator samples for unicast. This simply checks if at least one stream is connected and is sending (empty) data. This modifies the samples to send data as well as counting the receive ISO data packets. Ideally the TX would be superflous to verify that ISO is working, but a missing feature in the Zephyr LL makes it a requirement. Signed-off-by: Emil Gydesen --- .../nrf5340_audio_dk_nrf5340_cpuapp.conf | 6 ++ .../boards/nrf5340dk_nrf5340_cpuapp.conf | 6 ++ .../bluetooth/cap_acceptor/src/cap_acceptor.h | 2 + .../cap_acceptor/src/cap_acceptor_unicast.c | 81 ++++++++++++++++++- .../nrf5340_audio_dk_nrf5340_cpuapp.conf | 6 ++ .../boards/nrf5340dk_nrf5340_cpuapp.conf | 6 ++ .../cap_initiator/src/cap_initiator_unicast.c | 80 +++++++++++++++++- .../audio_samples/cap/acceptor/CMakeLists.txt | 25 ++++++ .../cap/acceptor/Kconfig.sysbuild | 10 +++ .../audio_samples/cap/acceptor/prj.conf | 2 + .../acceptor/src/cap_acceptor_sample_test.c | 77 ++++++++++++++++++ .../cap/acceptor/src/test_main.c | 14 ++++ .../audio_samples/cap/acceptor/sysbuild.cmake | 6 ++ .../cap/initiator/CMakeLists.txt | 25 ++++++ .../cap/initiator/Kconfig.sysbuild | 10 +++ .../audio_samples/cap/initiator/prj.conf | 2 + .../initiator/src/cap_initiator_sample_test.c | 76 +++++++++++++++++ .../cap/initiator/src/test_main.c | 11 +++ .../cap/initiator/sysbuild.cmake | 6 ++ .../cap/tests_scripts/cap_unicast.sh | 26 ++++++ tests/bsim/bluetooth/audio_samples/compile.sh | 20 +++++ 21 files changed, 495 insertions(+), 2 deletions(-) create mode 100644 samples/bluetooth/cap_acceptor/boards/nrf5340_audio_dk_nrf5340_cpuapp.conf create mode 100644 samples/bluetooth/cap_acceptor/boards/nrf5340dk_nrf5340_cpuapp.conf create mode 100644 samples/bluetooth/cap_initiator/boards/nrf5340_audio_dk_nrf5340_cpuapp.conf create mode 100644 samples/bluetooth/cap_initiator/boards/nrf5340dk_nrf5340_cpuapp.conf create mode 100644 tests/bsim/bluetooth/audio_samples/cap/acceptor/CMakeLists.txt create mode 100644 tests/bsim/bluetooth/audio_samples/cap/acceptor/Kconfig.sysbuild create mode 100644 tests/bsim/bluetooth/audio_samples/cap/acceptor/prj.conf create mode 100644 tests/bsim/bluetooth/audio_samples/cap/acceptor/src/cap_acceptor_sample_test.c create mode 100644 tests/bsim/bluetooth/audio_samples/cap/acceptor/src/test_main.c create mode 100644 tests/bsim/bluetooth/audio_samples/cap/acceptor/sysbuild.cmake create mode 100644 tests/bsim/bluetooth/audio_samples/cap/initiator/CMakeLists.txt create mode 100644 tests/bsim/bluetooth/audio_samples/cap/initiator/Kconfig.sysbuild create mode 100644 tests/bsim/bluetooth/audio_samples/cap/initiator/prj.conf create mode 100644 tests/bsim/bluetooth/audio_samples/cap/initiator/src/cap_initiator_sample_test.c create mode 100644 tests/bsim/bluetooth/audio_samples/cap/initiator/src/test_main.c create mode 100644 tests/bsim/bluetooth/audio_samples/cap/initiator/sysbuild.cmake create mode 100755 tests/bsim/bluetooth/audio_samples/cap/tests_scripts/cap_unicast.sh diff --git a/samples/bluetooth/cap_acceptor/boards/nrf5340_audio_dk_nrf5340_cpuapp.conf b/samples/bluetooth/cap_acceptor/boards/nrf5340_audio_dk_nrf5340_cpuapp.conf new file mode 100644 index 0000000000000..96dc0eb4e3b2c --- /dev/null +++ b/samples/bluetooth/cap_acceptor/boards/nrf5340_audio_dk_nrf5340_cpuapp.conf @@ -0,0 +1,6 @@ +CONFIG_BT_BUF_EVT_RX_SIZE=255 +CONFIG_BT_BUF_ACL_RX_SIZE=255 +CONFIG_BT_BUF_ACL_TX_SIZE=251 +CONFIG_BT_BUF_CMD_TX_SIZE=255 + +CONFIG_BT_TINYCRYPT_ECC=y diff --git a/samples/bluetooth/cap_acceptor/boards/nrf5340dk_nrf5340_cpuapp.conf b/samples/bluetooth/cap_acceptor/boards/nrf5340dk_nrf5340_cpuapp.conf new file mode 100644 index 0000000000000..96dc0eb4e3b2c --- /dev/null +++ b/samples/bluetooth/cap_acceptor/boards/nrf5340dk_nrf5340_cpuapp.conf @@ -0,0 +1,6 @@ +CONFIG_BT_BUF_EVT_RX_SIZE=255 +CONFIG_BT_BUF_ACL_RX_SIZE=255 +CONFIG_BT_BUF_ACL_TX_SIZE=251 +CONFIG_BT_BUF_CMD_TX_SIZE=255 + +CONFIG_BT_TINYCRYPT_ECC=y diff --git a/samples/bluetooth/cap_acceptor/src/cap_acceptor.h b/samples/bluetooth/cap_acceptor/src/cap_acceptor.h index 20c8da5f1d106..7db7dec601924 100644 --- a/samples/bluetooth/cap_acceptor/src/cap_acceptor.h +++ b/samples/bluetooth/cap_acceptor/src/cap_acceptor.h @@ -24,6 +24,8 @@ struct peer_config { struct k_sem sink_stream_sem; /** ACL connection object for the peer device */ struct bt_conn *conn; + /** Current sequence number for TX */ + uint16_t tx_seq_num; }; /** diff --git a/samples/bluetooth/cap_acceptor/src/cap_acceptor_unicast.c b/samples/bluetooth/cap_acceptor/src/cap_acceptor_unicast.c index 87358f79b3ed8..968e46c454fa1 100644 --- a/samples/bluetooth/cap_acceptor/src/cap_acceptor_unicast.c +++ b/samples/bluetooth/cap_acceptor/src/cap_acceptor_unicast.c @@ -7,6 +7,7 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include #include #include #include @@ -22,10 +23,12 @@ #include #include #include +#include #include #include #include #include +#include #include "cap_acceptor.h" @@ -40,6 +43,7 @@ LOG_MODULE_REGISTER(cap_acceptor_unicast, LOG_LEVEL_INF); static const struct bt_audio_codec_qos_pref qos_pref = BT_AUDIO_CODEC_QOS_PREF( UNFRAMED_SUPPORTED, PREF_PHY, RTN, LATENCY, MIN_PD, MAX_PD, MIN_PD, MAX_PD); +uint64_t total_rx_iso_packet_count; /* This value is exposed to test code */ static bool log_codec_cfg_cb(struct bt_data *data, void *user_data) { @@ -290,6 +294,7 @@ static void unicast_stream_enabled_cb(struct bt_bap_stream *bap_stream) static void unicast_stream_started_cb(struct bt_bap_stream *bap_stream) { LOG_INF("Started bap_stream %p", bap_stream); + total_rx_iso_packet_count = 0U; } static void unicast_stream_metadata_updated_cb(struct bt_bap_stream *bap_stream) @@ -320,7 +325,63 @@ static void unicast_stream_released_cb(struct bt_bap_stream *bap_stream) static void unicast_stream_recv_cb(struct bt_bap_stream *bap_stream, const struct bt_iso_recv_info *info, struct net_buf *buf) { - /* TODO: Add test code */ + /* Triggered every time we receive an HCI data packet from the controller. + * A call to this does not indicate valid data + * (see the `info->flags` for which flags to check), + */ + + if ((total_rx_iso_packet_count % 100U) == 0U) { + LOG_INF("Received %llu HCI ISO data packets", total_rx_iso_packet_count); + } + + total_rx_iso_packet_count++; +} + +static void tx_thread_func(void *arg1, void *arg2, void *arg3) +{ + 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 uint8_t data[CONFIG_BT_ISO_TX_MTU]; + struct peer_config *peer = arg1; + struct bt_cap_stream *cap_stream = &peer->source_stream; + struct bt_bap_stream *bap_stream = &cap_stream->bap_stream; + + for (size_t i = 0U; i < ARRAY_SIZE(data); i++) { + data[i] = (uint8_t)i; + } + + while (true) { + /* No-op if stream is not configured */ + if (bap_stream->ep != NULL) { + struct bt_bap_ep_info ep_info; + int err; + + err = bt_bap_ep_get_info(bap_stream->ep, &ep_info); + if (err == 0) { + if (ep_info.state == BT_BAP_EP_STATE_STREAMING) { + struct net_buf *buf; + + buf = net_buf_alloc(&tx_pool, K_FOREVER); + net_buf_reserve(buf, BT_ISO_CHAN_SEND_RESERVE); + + net_buf_add_mem(buf, data, bap_stream->qos->sdu); + + err = bt_cap_stream_send(cap_stream, buf, peer->tx_seq_num); + if (err == 0) { + peer->tx_seq_num++; + continue; /* Attempt to send again ASAP */ + } else { + LOG_ERR("Unable to send: %d", err); + net_buf_unref(buf); + } + } + } + } + + /* In case of any errors, retry with a delay */ + k_sleep(K_MSEC(100)); + } } int init_cap_acceptor_unicast(struct peer_config *peer) @@ -347,10 +408,28 @@ int init_cap_acceptor_unicast(struct peer_config *peer) return -ENOEXEC; } + + cbs_registered = true; } bt_cap_stream_ops_register(&peer->source_stream, &unicast_stream_ops); bt_cap_stream_ops_register(&peer->sink_stream, &unicast_stream_ops); + if (IS_ENABLED(CONFIG_BT_ASCS_ASE_SRC)) { + static bool thread_started; + + if (!thread_started) { + static K_KERNEL_STACK_DEFINE(tx_thread_stack, 1024); + const int tx_thread_prio = K_PRIO_PREEMPT(5); + static struct k_thread tx_thread; + + k_thread_create(&tx_thread, tx_thread_stack, + K_KERNEL_STACK_SIZEOF(tx_thread_stack), tx_thread_func, + peer, NULL, NULL, tx_thread_prio, 0, K_NO_WAIT); + k_thread_name_set(&tx_thread, "TX thread"); + thread_started = true; + } + } + return 0; } diff --git a/samples/bluetooth/cap_initiator/boards/nrf5340_audio_dk_nrf5340_cpuapp.conf b/samples/bluetooth/cap_initiator/boards/nrf5340_audio_dk_nrf5340_cpuapp.conf new file mode 100644 index 0000000000000..96dc0eb4e3b2c --- /dev/null +++ b/samples/bluetooth/cap_initiator/boards/nrf5340_audio_dk_nrf5340_cpuapp.conf @@ -0,0 +1,6 @@ +CONFIG_BT_BUF_EVT_RX_SIZE=255 +CONFIG_BT_BUF_ACL_RX_SIZE=255 +CONFIG_BT_BUF_ACL_TX_SIZE=251 +CONFIG_BT_BUF_CMD_TX_SIZE=255 + +CONFIG_BT_TINYCRYPT_ECC=y diff --git a/samples/bluetooth/cap_initiator/boards/nrf5340dk_nrf5340_cpuapp.conf b/samples/bluetooth/cap_initiator/boards/nrf5340dk_nrf5340_cpuapp.conf new file mode 100644 index 0000000000000..96dc0eb4e3b2c --- /dev/null +++ b/samples/bluetooth/cap_initiator/boards/nrf5340dk_nrf5340_cpuapp.conf @@ -0,0 +1,6 @@ +CONFIG_BT_BUF_EVT_RX_SIZE=255 +CONFIG_BT_BUF_ACL_RX_SIZE=255 +CONFIG_BT_BUF_ACL_TX_SIZE=251 +CONFIG_BT_BUF_CMD_TX_SIZE=255 + +CONFIG_BT_TINYCRYPT_ECC=y diff --git a/samples/bluetooth/cap_initiator/src/cap_initiator_unicast.c b/samples/bluetooth/cap_initiator/src/cap_initiator_unicast.c index 76be7ef0dad0d..030fe3835c365 100644 --- a/samples/bluetooth/cap_initiator/src/cap_initiator_unicast.c +++ b/samples/bluetooth/cap_initiator/src/cap_initiator_unicast.c @@ -24,10 +24,12 @@ #include #include #include +#include #include #include #include #include +#include #include #include "cap_initiator.h" @@ -42,6 +44,7 @@ LOG_MODULE_REGISTER(cap_initiator_unicast, LOG_LEVEL_INF); static struct bt_bap_lc3_preset unicast_preset_16_2_1 = BT_BAP_LC3_UNICAST_PRESET_16_2_1( BT_AUDIO_LOCATION_MONO_AUDIO, BT_AUDIO_CONTEXT_TYPE_UNSPECIFIED); static struct bt_bap_unicast_group *unicast_group; +uint64_t total_rx_iso_packet_count; /* This value is exposed to test code */ /** Struct to contain information for a specific peer (CAP) device */ struct peer_config { @@ -59,6 +62,8 @@ struct peer_config { struct bt_bap_ep *sink_ep; /** ACL connection object for the peer device */ struct bt_conn *conn; + /** Current sequence number for TX */ + uint16_t tx_seq_num; }; /* TODO: Expand to multiple ACL connections */ @@ -97,6 +102,7 @@ static void unicast_stream_enabled_cb(struct bt_bap_stream *stream) static void unicast_stream_started_cb(struct bt_bap_stream *stream) { LOG_INF("Started stream %p", stream); + total_rx_iso_packet_count = 0U; } static void unicast_stream_metadata_updated_cb(struct bt_bap_stream *stream) @@ -128,7 +134,16 @@ static void unicast_stream_released_cb(struct bt_bap_stream *stream) static void unicast_stream_recv_cb(struct bt_bap_stream *stream, const struct bt_iso_recv_info *info, struct net_buf *buf) { - /* TODO: Add test code */ + /* Triggered every time we receive an HCI data packet from the controller. + * A call to this does not indicate valid data + * (see the `info->flags` for which flags to check), + */ + + if ((total_rx_iso_packet_count % 100U) == 0U) { + LOG_INF("Received %llu HCI ISO data packets", total_rx_iso_packet_count); + } + + total_rx_iso_packet_count++; } static struct bt_bap_stream_ops unicast_stream_ops = { @@ -143,6 +158,52 @@ static struct bt_bap_stream_ops unicast_stream_ops = { .recv = unicast_stream_recv_cb, }; +static void tx_thread_func(void *arg1, void *arg2, void *arg3) +{ + 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 uint8_t data[CONFIG_BT_ISO_TX_MTU]; + struct bt_cap_stream *cap_stream = &peer.sink_stream; + struct bt_bap_stream *bap_stream = &cap_stream->bap_stream; + + for (size_t i = 0U; i < ARRAY_SIZE(data); i++) { + data[i] = (uint8_t)i; + } + + while (true) { + /* No-op if stream is not configured */ + if (bap_stream->ep != NULL) { + struct bt_bap_ep_info ep_info; + int err; + + err = bt_bap_ep_get_info(bap_stream->ep, &ep_info); + if (err == 0) { + if (ep_info.state == BT_BAP_EP_STATE_STREAMING) { + struct net_buf *buf; + + buf = net_buf_alloc(&tx_pool, K_FOREVER); + net_buf_reserve(buf, BT_ISO_CHAN_SEND_RESERVE); + + net_buf_add_mem(buf, data, bap_stream->qos->sdu); + + err = bt_cap_stream_send(cap_stream, buf, peer.tx_seq_num); + if (err == 0) { + peer.tx_seq_num++; + continue; /* Attempt to send again ASAP */ + } else { + LOG_ERR("Unable to send: %d", err); + net_buf_unref(buf); + } + } + } + } + + /* In case of any errors, retry with a delay */ + k_sleep(K_MSEC(100)); + } +} + static bool log_codec_cb(struct bt_data *data, void *user_data) { const char *str = (const char *)user_data; @@ -674,6 +735,23 @@ static int init_cap_initiator(void) k_sem_init(&peer.source_stream_sem, 0, 1); k_sem_init(&peer.sink_stream_sem, 0, 1); + if (IS_ENABLED(CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK)) { + static bool thread_started; + + if (!thread_started) { + static K_KERNEL_STACK_DEFINE(tx_thread_stack, 1024); + const int tx_thread_prio = K_PRIO_PREEMPT(5); + static struct k_thread tx_thread; + + k_thread_create(&tx_thread, tx_thread_stack, + K_KERNEL_STACK_SIZEOF(tx_thread_stack), tx_thread_func, + net_buf_pull_be16, NULL, NULL, tx_thread_prio, 0, + K_NO_WAIT); + k_thread_name_set(&tx_thread, "TX thread"); + thread_started = true; + } + } + return 0; } diff --git a/tests/bsim/bluetooth/audio_samples/cap/acceptor/CMakeLists.txt b/tests/bsim/bluetooth/audio_samples/cap/acceptor/CMakeLists.txt new file mode 100644 index 0000000000000..e446554ca73bb --- /dev/null +++ b/tests/bsim/bluetooth/audio_samples/cap/acceptor/CMakeLists.txt @@ -0,0 +1,25 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) + +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(cap_acceptor_self_tets) + +set(cap_acceptor_path ${ZEPHYR_BASE}/samples/bluetooth/cap_acceptor) + +target_sources(app PRIVATE + ${cap_acceptor_path}/src/main.c + ${cap_acceptor_path}/src/cap_acceptor_unicast.c +) + +target_sources(app PRIVATE + src/cap_acceptor_sample_test.c + src/test_main.c +) + +zephyr_library_include_directories(${ZEPHYR_BASE}/samples/bluetooth) + +zephyr_include_directories( + ${BSIM_COMPONENTS_PATH}/libUtilv1/src/ + ${BSIM_COMPONENTS_PATH}/libPhyComv1/src/ + ) diff --git a/tests/bsim/bluetooth/audio_samples/cap/acceptor/Kconfig.sysbuild b/tests/bsim/bluetooth/audio_samples/cap/acceptor/Kconfig.sysbuild new file mode 100644 index 0000000000000..3b2c35e65c55d --- /dev/null +++ b/tests/bsim/bluetooth/audio_samples/cap/acceptor/Kconfig.sysbuild @@ -0,0 +1,10 @@ +# Copyright (c) 2023-2024 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +source "${ZEPHYR_BASE}/samples/bluetooth/cap_acceptor/Kconfig.sysbuild" + +config NATIVE_SIMULATOR_PRIMARY_MCU_INDEX + int + # Let's pass the test arguments to the application MCU test + # otherwise by default they would have gone to the net core. + default 0 if $(BOARD_TARGET_STRING) = "NRF5340BSIM_NRF5340_CPUAPP" diff --git a/tests/bsim/bluetooth/audio_samples/cap/acceptor/prj.conf b/tests/bsim/bluetooth/audio_samples/cap/acceptor/prj.conf new file mode 100644 index 0000000000000..e8122ebe95f46 --- /dev/null +++ b/tests/bsim/bluetooth/audio_samples/cap/acceptor/prj.conf @@ -0,0 +1,2 @@ +# Please build using the sample configuration file: +# ${ZEPHYR_BASE}/samples/bluetooth/cap_acceptor/prj.conf diff --git a/tests/bsim/bluetooth/audio_samples/cap/acceptor/src/cap_acceptor_sample_test.c b/tests/bsim/bluetooth/audio_samples/cap/acceptor/src/cap_acceptor_sample_test.c new file mode 100644 index 0000000000000..2f3260dfd2ef7 --- /dev/null +++ b/tests/bsim/bluetooth/audio_samples/cap/acceptor/src/cap_acceptor_sample_test.c @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2023-2024 Nordic Semiconductor ASA + * Copyright (c) 2017-2019 Oticon A/S + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "bs_types.h" +#include "bs_tracing.h" +#include "bs_utils.h" +#include "time_machine.h" +#include "bstests.h" + +#define WAIT_TIME 10 /* Seconds */ + +#define PASS_THRESHOLD 100 /* Audio packets */ + +extern enum bst_result_t bst_result; + +#define FAIL(...) \ + do { \ + bst_result = Failed; \ + bs_trace_error_time_line(__VA_ARGS__); \ + } while (0) + +#define PASS(...) \ + do { \ + bst_result = Passed; \ + bs_trace_info_time(1, __VA_ARGS__); \ + } while (0) + +static void test_cap_acceptor_sample_init(void) +{ + /* We set an absolute deadline in 30 seconds */ + bst_ticker_set_next_tick_absolute(WAIT_TIME * 1e6); + bst_result = In_progress; +} + +static void test_cap_acceptor_sample_tick(bs_time_t HW_device_time) +{ + /* + * If in WAIT_TIME seconds we did not get enough packets through + * we consider the test failed + */ + + extern uint64_t total_rx_iso_packet_count; + + bs_trace_info_time(2, "%" PRIu64 " packets received, expected >= %i\n", + total_rx_iso_packet_count, PASS_THRESHOLD); + + if (total_rx_iso_packet_count >= PASS_THRESHOLD) { + PASS("cap_acceptor PASSED\n"); + } else { + FAIL("cap_acceptor FAILED (Did not pass after %i seconds)\n", WAIT_TIME); + } +} + +static const struct bst_test_instance test_sample[] = { + { + .test_id = "cap_acceptor", + .test_descr = "Test based on the unicast client sample. " + "It expects to be connected to a compatible unicast server, " + "waits for " STR(WAIT_TIME) " seconds, and checks how " + "many audio packets have been received correctly", + .test_post_init_f = test_cap_acceptor_sample_init, + .test_tick_f = test_cap_acceptor_sample_tick, + }, + BSTEST_END_MARKER +}; + +/* TODO: Add test of reconnection */ + +struct bst_test_list *test_cap_acceptor_sample_install(struct bst_test_list *tests) +{ + tests = bst_add_tests(tests, test_sample); + return tests; +} diff --git a/tests/bsim/bluetooth/audio_samples/cap/acceptor/src/test_main.c b/tests/bsim/bluetooth/audio_samples/cap/acceptor/src/test_main.c new file mode 100644 index 0000000000000..fa6a7c977ce67 --- /dev/null +++ b/tests/bsim/bluetooth/audio_samples/cap/acceptor/src/test_main.c @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2023-2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "bstests.h" + +extern struct bst_test_list *test_cap_acceptor_sample_install(struct bst_test_list *tests); + +bst_test_install_t test_installers[] = { + test_cap_acceptor_sample_install, + NULL +}; diff --git a/tests/bsim/bluetooth/audio_samples/cap/acceptor/sysbuild.cmake b/tests/bsim/bluetooth/audio_samples/cap/acceptor/sysbuild.cmake new file mode 100644 index 0000000000000..be3e589dd3533 --- /dev/null +++ b/tests/bsim/bluetooth/audio_samples/cap/acceptor/sysbuild.cmake @@ -0,0 +1,6 @@ +# Copyright (c) 2023-2024 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +include(${ZEPHYR_BASE}/samples/bluetooth/cap_acceptor/sysbuild.cmake) + +native_simulator_set_primary_mcu_index(${DEFAULT_IMAGE} ${NET_APP}) diff --git a/tests/bsim/bluetooth/audio_samples/cap/initiator/CMakeLists.txt b/tests/bsim/bluetooth/audio_samples/cap/initiator/CMakeLists.txt new file mode 100644 index 0000000000000..786575379c785 --- /dev/null +++ b/tests/bsim/bluetooth/audio_samples/cap/initiator/CMakeLists.txt @@ -0,0 +1,25 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) + +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(cap_initiator_self_tets) + +set(cap_initiator_path ${ZEPHYR_BASE}/samples/bluetooth/cap_initiator) + +target_sources(app PRIVATE + ${cap_initiator_path}/src/main.c + ${cap_initiator_path}/src/cap_initiator_unicast.c +) + +target_sources(app PRIVATE + src/cap_initiator_sample_test.c + src/test_main.c +) + +zephyr_library_include_directories(${ZEPHYR_BASE}/samples/bluetooth) + +zephyr_include_directories( + ${BSIM_COMPONENTS_PATH}/libUtilv1/src/ + ${BSIM_COMPONENTS_PATH}/libPhyComv1/src/ + ) diff --git a/tests/bsim/bluetooth/audio_samples/cap/initiator/Kconfig.sysbuild b/tests/bsim/bluetooth/audio_samples/cap/initiator/Kconfig.sysbuild new file mode 100644 index 0000000000000..c9f3abf294f8f --- /dev/null +++ b/tests/bsim/bluetooth/audio_samples/cap/initiator/Kconfig.sysbuild @@ -0,0 +1,10 @@ +# Copyright (c) 2023-2024 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +source "${ZEPHYR_BASE}/samples/bluetooth/cap_initiator/Kconfig.sysbuild" + +config NATIVE_SIMULATOR_PRIMARY_MCU_INDEX + int + # Let's pass the test arguments to the application MCU test + # otherwise by default they would have gone to the net core. + default 0 if $(BOARD_TARGET_STRING) = "NRF5340BSIM_NRF5340_CPUAPP" diff --git a/tests/bsim/bluetooth/audio_samples/cap/initiator/prj.conf b/tests/bsim/bluetooth/audio_samples/cap/initiator/prj.conf new file mode 100644 index 0000000000000..ab925ee17c0c2 --- /dev/null +++ b/tests/bsim/bluetooth/audio_samples/cap/initiator/prj.conf @@ -0,0 +1,2 @@ +# Please build using the sample configuration file: +# ${ZEPHYR_BASE}/samples/bluetooth/cap_initiator/prj.conf diff --git a/tests/bsim/bluetooth/audio_samples/cap/initiator/src/cap_initiator_sample_test.c b/tests/bsim/bluetooth/audio_samples/cap/initiator/src/cap_initiator_sample_test.c new file mode 100644 index 0000000000000..e6defdbad02ba --- /dev/null +++ b/tests/bsim/bluetooth/audio_samples/cap/initiator/src/cap_initiator_sample_test.c @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2023-2024 Nordic Semiconductor ASA + * Copyright (c) 2017-2019 Oticon A/S + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "bs_types.h" +#include "bs_tracing.h" +#include "bs_utils.h" +#include "time_machine.h" +#include "bstests.h" + +#define WAIT_TIME 10 /* Seconds */ + +#define PASS_THRESHOLD 100 /* Audio packets */ + +extern enum bst_result_t bst_result; + +#define FAIL(...) \ + do { \ + bst_result = Failed; \ + bs_trace_error_time_line(__VA_ARGS__); \ + } while (0) + +#define PASS(...) \ + do { \ + bst_result = Passed; \ + bs_trace_info_time(1, __VA_ARGS__); \ + } while (0) + +static void test_cap_initiator_sample_init(void) +{ + bst_ticker_set_next_tick_absolute(WAIT_TIME * 1e6); + bst_result = In_progress; +} + +static void test_cap_initiator_sample_tick(bs_time_t HW_device_time) +{ + /* + * If in WAIT_TIME seconds we did not get enough packets through + * we consider the test failed + */ + + extern uint64_t total_rx_iso_packet_count; + + bs_trace_info_time(2, "%" PRIu64 " packets received, expected >= %i\n", + total_rx_iso_packet_count, PASS_THRESHOLD); + + if (total_rx_iso_packet_count >= PASS_THRESHOLD) { + PASS("cap_initiator PASSED\n"); + } else { + FAIL("cap_initiator FAILED (Did not pass after %i seconds)\n", WAIT_TIME); + } +} + +static const struct bst_test_instance test_sample[] = { + { + .test_id = "cap_initiator", + .test_descr = "Test based on the unicast client sample. " + "It expects to be connected to a compatible unicast server, " + "waits for " STR(WAIT_TIME) " seconds, and checks how " + "many audio packets have been received correctly", + .test_post_init_f = test_cap_initiator_sample_init, + .test_tick_f = test_cap_initiator_sample_tick, + }, + BSTEST_END_MARKER +}; + +/* TODO: Add test of reconnection */ + +struct bst_test_list *test_cap_initiator_sample_install(struct bst_test_list *tests) +{ + tests = bst_add_tests(tests, test_sample); + return tests; +} diff --git a/tests/bsim/bluetooth/audio_samples/cap/initiator/src/test_main.c b/tests/bsim/bluetooth/audio_samples/cap/initiator/src/test_main.c new file mode 100644 index 0000000000000..3aa6fac9b021e --- /dev/null +++ b/tests/bsim/bluetooth/audio_samples/cap/initiator/src/test_main.c @@ -0,0 +1,11 @@ +/* + * Copyright (c) 2023-2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "bstests.h" + +extern struct bst_test_list *test_cap_initiator_sample_install(struct bst_test_list *tests); + +bst_test_install_t test_installers[] = {test_cap_initiator_sample_install, NULL}; diff --git a/tests/bsim/bluetooth/audio_samples/cap/initiator/sysbuild.cmake b/tests/bsim/bluetooth/audio_samples/cap/initiator/sysbuild.cmake new file mode 100644 index 0000000000000..185eb396b0126 --- /dev/null +++ b/tests/bsim/bluetooth/audio_samples/cap/initiator/sysbuild.cmake @@ -0,0 +1,6 @@ +# Copyright (c) 2023-2024 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +include(${ZEPHYR_BASE}/samples/bluetooth/cap_initiator/sysbuild.cmake) + +native_simulator_set_primary_mcu_index(${DEFAULT_IMAGE} ${NET_APP}) diff --git a/tests/bsim/bluetooth/audio_samples/cap/tests_scripts/cap_unicast.sh b/tests/bsim/bluetooth/audio_samples/cap/tests_scripts/cap_unicast.sh new file mode 100755 index 0000000000000..389ac0182b3a8 --- /dev/null +++ b/tests/bsim/bluetooth/audio_samples/cap/tests_scripts/cap_unicast.sh @@ -0,0 +1,26 @@ +#!/usr/bin/env bash +# Copyright 2023-2024 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +# Simple selfchecking test for the CAP Acceptor sample. +# It relies on the bs_tests hooks to register a test timer callback, which after a deadline +# will check how many audio packets the unicast client has received, and if over a threshold +# it considers the test passed + +simulation_id="cap_unicast_test" +verbosity_level=2 + +source ${ZEPHYR_BASE}/tests/bsim/sh_common.source + +cd ${BSIM_OUT_PATH}/bin + +Execute ./bs_${BOARD_TS}_tests_bsim_bluetooth_audio_samples_cap_initiator_prj_conf \ + -v=${verbosity_level} -s=${simulation_id} -d=0 -RealEncryption=1 -testid=cap_initiator + +Execute ./bs_${BOARD_TS}_tests_bsim_bluetooth_audio_samples_cap_acceptor_prj_conf \ + -v=${verbosity_level} -s=${simulation_id} -d=1 -RealEncryption=1 -testid=cap_acceptor + +Execute ./bs_2G4_phy_v1 -v=${verbosity_level} -s=${simulation_id} \ + -D=2 -sim_length=20e6 $@ -argschannel -at=40 + +wait_for_background_jobs #Wait for all programs in background and return != 0 if any fails diff --git a/tests/bsim/bluetooth/audio_samples/compile.sh b/tests/bsim/bluetooth/audio_samples/compile.sh index b5b19f325f99a..1bec1bb8319c7 100755 --- a/tests/bsim/bluetooth/audio_samples/compile.sh +++ b/tests/bsim/bluetooth/audio_samples/compile.sh @@ -22,6 +22,16 @@ if [ "${BOARD_TS}" == "nrf5340bsim_nrf5340_cpuapp" ]; then app=tests/bsim/bluetooth/audio_samples/bap_broadcast_sink sysbuild=1 \ conf_file=${ZEPHYR_BASE}/samples/bluetooth/bap_broadcast_sink/prj.conf \ exe_name=bs_${BOARD_TS}_${app}_prj_conf sysbuild=1 compile + app=tests/bsim/bluetooth/audio_samples/cap/initiator \ + sample=${ZEPHYR_BASE}/samples/bluetooth/cap_initiator \ + conf_file=${sample}/prj.conf \ + conf_overlay=${sample}/boards/nrf5340_audio_dk_nrf5340_cpuapp.conf \ + exe_name=bs_${BOARD_TS}_${app}_prj_conf sysbuild=1 compile + app=tests/bsim/bluetooth/audio_samples/cap/acceptor \ + sample=${ZEPHYR_BASE}/samples/bluetooth/cap_acceptor \ + conf_file=${sample}/prj.conf \ + conf_overlay=${sample}/boards/nrf5340_audio_dk_nrf5340_cpuapp.conf \ + exe_name=bs_${BOARD_TS}_${app}_prj_conf sysbuild=1 compile else app=samples/bluetooth/bap_unicast_server conf_overlay=overlay-bt_ll_sw_split.conf \ exe_name=bs_${BOARD_TS}_${app}_prj_conf sysbuild=1 compile @@ -36,6 +46,16 @@ else conf_file=${ZEPHYR_BASE}/samples/bluetooth/bap_broadcast_sink/prj.conf \ conf_overlay=${ZEPHYR_BASE}/samples/bluetooth/bap_broadcast_sink/overlay-bt_ll_sw_split.conf \ exe_name=bs_${BOARD_TS}_${app}_prj_conf sysbuild=1 compile + app=tests/bsim/bluetooth/audio_samples/cap/initiator \ + sample=${ZEPHYR_BASE}/samples/bluetooth/cap_initiator \ + conf_file=${sample}/prj.conf \ + conf_overlay=${sample}/overlay-bt_ll_sw_split.conf \ + exe_name=bs_${BOARD_TS}_${app}_prj_conf sysbuild=1 compile + app=tests/bsim/bluetooth/audio_samples/cap/acceptor \ + sample=${ZEPHYR_BASE}/samples/bluetooth/cap_acceptor \ + conf_file=${sample}/prj.conf \ + conf_overlay=${sample}/overlay-bt_ll_sw_split.conf \ + exe_name=bs_${BOARD_TS}_${app}_prj_conf sysbuild=1 compile fi wait_for_background_jobs From e5df99082b9b8889d6f0568eb097417b19133fed Mon Sep 17 00:00:00 2001 From: Emil Gydesen Date: Mon, 6 May 2024 15:30:30 +0200 Subject: [PATCH 2589/2849] MAINTAINERS: Add BT CAP samples to LE audio group Add the CAP initiator and acceptor samples to the files for Bluetooth Audio. This will also automatically support a future CAP Commander sample. Signed-off-by: Emil Gydesen --- MAINTAINERS.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/MAINTAINERS.yml b/MAINTAINERS.yml index 0dfcbda4a129f..b110c29cde4fb 100644 --- a/MAINTAINERS.yml +++ b/MAINTAINERS.yml @@ -450,6 +450,7 @@ Bluetooth Audio: - tests/bluetooth/tester/src/audio/ - doc/connectivity/bluetooth/api/audio/ - samples/bluetooth/bap*/ + - samples/bluetooth/cap*/ - samples/bluetooth/hap*/ - samples/bluetooth/pbp*/ - samples/bluetooth/tmap*/ From b8315431371d9951f7229ed9a150dd3326e17425 Mon Sep 17 00:00:00 2001 From: Luis Ubieda Date: Tue, 14 May 2024 22:16:11 -0400 Subject: [PATCH 2590/2849] doc: shell: Changes to restructure Backends documentation - Unify shell backends in a dedicated section. - Add documentation for the following backends: USB, BLE, RTT. Signed-off-by: Luis Ubieda --- doc/services/shell/index.rst | 106 ++++++++++++++++++++++++----------- 1 file changed, 73 insertions(+), 33 deletions(-) diff --git a/doc/services/shell/index.rst b/doc/services/shell/index.rst index 582ddcd2f9ce7..426ad4195d50d 100644 --- a/doc/services/shell/index.rst +++ b/doc/services/shell/index.rst @@ -40,6 +40,11 @@ interaction is required. This module is a Unix-like shell with these features: enable :kconfig:option:`CONFIG_SHELL_MINIMAL` and selectively enable just the features you want. +.. _backends: + +Backends +******** + The module can be connected to any transport for command input and output. At this point, the following transport layers are implemented: @@ -49,10 +54,76 @@ At this point, the following transport layers are implemented: * Telnet * UART * USB +* Bluetooth LE (NUS) +* RPMSG * DUMMY - not a physical transport layer. +Telnet +====== + +Enabling :kconfig:option:`CONFIG_SHELL_BACKEND_TELNET` will allow users to use telnet +as a shell backend. Connecting to it can be done using PuTTY or any ``telnet`` client. +For example: + +.. code-block:: none + + telnet + +By default the telnet client won't handle telnet commands and configuration. Although +command support can be enabled with :kconfig:option:`CONFIG_SHELL_TELNET_SUPPORT_COMMAND`. +This will give the telnet client access to a very limited set of supported commands but +still can be turned on if needed. One of the command options it supports is the ``ECHO`` +option. This will allow the client to be in character mode (character at a time), +similar to a UART backend in that regard. This will make the client send a character +as soon as it is typed having the effect of increasing the network traffic +considerably. For that cost, it will enable the line editing, +`tab completion `_, and `history `_ +features of the shell. + +USB CDC ACM +=========== + +To configure Shell USB CDC ACM backend, simply add the snippet ``cdc-acm-console`` +to your build: + +.. code-block:: console + + west build -S cdc-acm-console [...] + +Details on the configuration settings are captured in the following files: + +- :zephyr_file:`snippets/cdc-acm-console/cdc-acm-console.conf`. +- :zephyr_file:`snippets/cdc-acm-console/cdc-acm-console.overlay`. + +Bluetooth LE (NUS) +================== + +To configure Bluetooth LE (NUS) backend, simply add the snippet ``nus-console`` +to your build: + +.. code-block:: console + + west build -S nus-console [...] + +Details on the configuration settings are captured in the following files: + +- :zephyr_file:`snippets/nus-console/nus-console.conf`. +- :zephyr_file:`snippets/nus-console/nus-console.overlay`. + +Segget RTT +========== + +To configure Segger RTT backend, add the following configurations to your build: + +- :kconfig:option:`CONFIG_USE_SEGGER_RTT` +- :kconfig:option:`CONFIG_SHELL_BACKEND_RTT` +- :kconfig:option:`CONFIG_SHELL_BACKEND_SERIAL` + +Details on additional configuration settings are captured in: +:zephyr_file:`samples/subsys/shell/shell_module/prj_minimal_rtt.conf`. + Connecting to Segger RTT via TCP (on macOS, for example) -======================================================== +-------------------------------------------------------- On macOS JLinkRTTClient won't let you enter input. Instead, please use following procedure: @@ -74,30 +145,6 @@ procedure: * Now you should have a network connection to RTT that will let you enter input to the shell. - -Telnet Backend -============== - -Enabling :kconfig:option:`CONFIG_SHELL_BACKEND_TELNET` will allow users to use telnet -as a shell backend. Connecting to it can be done using PuTTY or any ``telnet`` client. -For example: - -.. code-block:: none - - telnet - -By default the telnet client won't handle telnet commands and configuration. Although -command support can be enabled with :kconfig:option:`CONFIG_SHELL_TELNET_SUPPORT_COMMAND`. -This will give the telnet client access to a very limited set of supported commands but -still can be turned on if needed. One of the command options it supports is the ``ECHO`` -option. This will allow the client to be in character mode (character at a time), -similar to a UART backend in that regard. This will make the client send a character -as soon as it is typed having the effect of increasing the network traffic -considerably. For that cost, it will enable the line editing, -`tab completion `_, and `history `_ -features of the shell. - - Commands ******** @@ -671,18 +718,11 @@ while a script interfaces over channel 1. This allows interactive use of the shell through JLinkRTTViewer, while the log is written to file. -.. warning:: - Regardless of the channel selection, the RTT log backend must be explicitly - enabled using :kconfig:option:`CONFIG_LOG_BACKEND_RTT` set to ``y``, because it - defaults to ``n`` when the Shell RTT backend is also enabled using - :kconfig:option:`CONFIG_SHELL_BACKEND_RTT` being set to ``y``. +See `shell backends `_ for details on how to enable RTT as a Shell backend. Usage ***** -To create a new shell instance user needs to activate requested -backend using ``menuconfig``. - The following code shows a simple use case of this library: .. code-block:: c From 18b19150afddd3c66c1547cef9cb4daa84700333 Mon Sep 17 00:00:00 2001 From: Luis Ubieda Date: Tue, 14 May 2024 22:17:56 -0400 Subject: [PATCH 2591/2849] doc: shell: Add section for commonly-used commands With details on how to enable them. Signed-off-by: Luis Ubieda --- doc/services/shell/index.rst | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/doc/services/shell/index.rst b/doc/services/shell/index.rst index 426ad4195d50d..8327031e197df 100644 --- a/doc/services/shell/index.rst +++ b/doc/services/shell/index.rst @@ -159,6 +159,41 @@ types: during compile time. Created in the software module. +Commonly-used command groups +============================ + +The following list is a set of useful command groups and how to enable them: + +GPIO +---- + +- :kconfig:option:`CONFIG_GPIO` +- :kconfig:option:`CONFIG_GPIO_SHELL` + +I2C +--- + +- :kconfig:option:`CONFIG_I2C` +- :kconfig:option:`CONFIG_I2C_SHELL` + +Sensor +------ + +- :kconfig:option:`CONFIG_SENSOR` +- :kconfig:option:`CONFIG_SENSOR_SHELL` + +Flash +----- + +- :kconfig:option:`CONFIG_FLASH` +- :kconfig:option:`CONFIG_FLASH_SHELL` + +File-System +----------- + +- :kconfig:option:`CONFIG_FILE_SYSTEM` +- :kconfig:option:`CONFIG_FILE_SYSTEM_SHELL` + Creating commands ================= From 253de6c7a2ec20f777f7c7343dd15008871ef767 Mon Sep 17 00:00:00 2001 From: Luis Ubieda Date: Tue, 14 May 2024 23:49:42 -0400 Subject: [PATCH 2592/2849] samples: shell: shell_module: Add README With basic description of registering different types of Shell commands. Signed-off-by: Luis Ubieda --- samples/subsys/shell/shell_module/README.rst | 115 +++++++++++++++++++ 1 file changed, 115 insertions(+) create mode 100644 samples/subsys/shell/shell_module/README.rst diff --git a/samples/subsys/shell/shell_module/README.rst b/samples/subsys/shell/shell_module/README.rst new file mode 100644 index 0000000000000..6b09a9f19bd72 --- /dev/null +++ b/samples/subsys/shell/shell_module/README.rst @@ -0,0 +1,115 @@ +.. zephyr:code-sample:: shell-module + :name: Custom Shell module + :relevant-api: shell_api + + Register shell commands using the Shell API + +Overview +******** + +This is a simple application demonstrating how to write and register commands +using the :ref:`Shell API `: + +Register Static commands + ``version`` is a static command that prints the kernel version. + +Conditionally Register commands + ``login`` and ``logout`` are conditionally registered commands depending + on :kconfig:option:`CONFIG_SHELL_START_OBSCURED`. + +Register Dynamic commands + See ``dynamic`` command and :zephyr_file:`samples/subsys/shell/shell_module/src/dynamic_cmd.c` + for details on how dynamic commands are implemented. + +Register Dictionary commands + ``dictionary`` implements subsect of dictionary commands. + +Set a Bypass callback + ``bypass`` implements the bypass callback. + +Set a Login command + ``login`` and ``logout`` implement the login and logout mechanism, respectively. + +Obscure user-input with asterisks + ``login`` and ``logout`` implement the feature of enabling and disabling + this functionality, respectively. + +Requirements +************ + +* A target configured with the shell interface, exposed through any of + its :ref:`backends `. + +Building and Running +******************** + +This sample can be found under :zephyr_file:`samples/subsys/shell/shell_module` +in the Zephyr tree. + +The sample can be built for several platforms. + +Emulation Targets +================= + +The sample may run on emulation targets. The following commands build the +application for the qemu_x86. + +.. zephyr-app-commands:: + :zephyr-app: samples/subsys/shell/shell_module + :host-os: unix + :board: qemu_x86 + :goals: run + :compact: + +After running the application, the console displays the shell interface, and +shows the shell prompt, at which point the user may start the interaction. + +On-Hardware +=========== + +.. zephyr-app-commands:: + :zephyr-app: samples/subsys/shell/shell_module + :host-os: unix + :board: nrf52840dk/nrf52840 + :goals: flash + :compact: + +Sample Output +************* + +.. code-block:: console + + uart:~$ + bypass clear date + demo device devmem + dynamic help history + kernel log log_test + rem resize retval + section_cmd shell shell_uart_release + stats version + uart:~$ demo + demo - Demo commands + Subcommands: + dictionary : Dictionary commands + hexdump : Hexdump params command. + params : Print params command. + ping : Ping command. + board : Show board name command. + uart:~$ dynamic + dynamic - Demonstrate dynamic command usage. + Subcommands: + add : Add a new dynamic command. + Example usage: [ dynamic add test ] will add a dynamic command + 'test'. + In this example, command name length is limited to 32 chars. You can + add up to 20 commands. Commands are automatically sorted to ensure + correct shell completion. + execute : Execute a command. + remove : Remove a command. + show : Show all added dynamic commands. + uart:~$ + +Details on Shell Subsystem +========================== + +For more details on the Shell subsystem, check the general :ref:`Shell documentation `. From fb98adc323b414e650774962cc274520a30f3a54 Mon Sep 17 00:00:00 2001 From: Jonathon Penix Date: Wed, 24 Apr 2024 11:19:05 -0700 Subject: [PATCH 2593/2849] kconfig: llvm: arm64: Advertise TLS support when using llvm for arm64 clang and lld both support TLS for arm64/aarch64, so advertise this support in Kconfig. 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 50293b2d61e1c..00ef90d7da363 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 || ARM + depends on RISCV || ARM || ARM64 def_bool y select TOOLCHAIN_SUPPORTS_THREAD_LOCAL_STORAGE From 97a734aa0121666a01b125e148adcb7340b15ab1 Mon Sep 17 00:00:00 2001 From: Jonathon Penix Date: Fri, 8 Mar 2024 16:37:49 -0800 Subject: [PATCH 2594/2849] cmake: llvm: arm64: Set arm64 flags when building with clang Ensure --target and -mcpu/-mfpu/-mtune are set appropriately when building with clang targeting arm64/aarch64. Signed-off-by: Jonathon Penix --- cmake/compiler/clang/target.cmake | 2 ++ cmake/compiler/clang/target_arm64.cmake | 15 +++++++++++++++ cmake/toolchain/llvm/target.cmake | 2 ++ 3 files changed, 19 insertions(+) create mode 100644 cmake/compiler/clang/target_arm64.cmake diff --git a/cmake/compiler/clang/target.cmake b/cmake/compiler/clang/target.cmake index d258cdadcf457..ae92664394c75 100644 --- a/cmake/compiler/clang/target.cmake +++ b/cmake/compiler/clang/target.cmake @@ -31,6 +31,8 @@ if(NOT "${ARCH}" STREQUAL "posix") ) include(${ZEPHYR_BASE}/cmake/compiler/clang/target_arm.cmake) + elseif("${ARCH}" STREQUAL "arm64") + include(${ZEPHYR_BASE}/cmake/compiler/clang/target_arm64.cmake) elseif("${ARCH}" STREQUAL "riscv") include(${ZEPHYR_BASE}/cmake/compiler/gcc/target_riscv.cmake) endif() diff --git a/cmake/compiler/clang/target_arm64.cmake b/cmake/compiler/clang/target_arm64.cmake new file mode 100644 index 0000000000000..44933802d0c49 --- /dev/null +++ b/cmake/compiler/clang/target_arm64.cmake @@ -0,0 +1,15 @@ +# SPDX-License-Identifier: Apache-2.0 +if(DEFINED GCC_M_CPU) + list(APPEND TOOLCHAIN_C_FLAGS -mcpu=${GCC_M_CPU}) + list(APPEND TOOLCHAIN_LD_FLAGS -mcpu=${GCC_M_CPU}) +endif() + +if(DEFINED GCC_M_ARCH) + list(APPEND TOOLCHAIN_C_FLAGS -march=${GCC_M_ARCH}) + list(APPEND TOOLCHAIN_LD_FLAGS -march=${GCC_M_ARCH}) +endif() + +if(DEFINED GCC_M_TUNE) + list(APPEND TOOLCHAIN_C_FLAGS -mtune=${GCC_M_TUNE}) + list(APPEND TOOLCHAIN_LD_FLAGS -mtune=${GCC_M_TUNE}) +endif() diff --git a/cmake/toolchain/llvm/target.cmake b/cmake/toolchain/llvm/target.cmake index 8446e22ced8fb..58c3b8ebbfc4d 100644 --- a/cmake/toolchain/llvm/target.cmake +++ b/cmake/toolchain/llvm/target.cmake @@ -25,6 +25,8 @@ if("${ARCH}" STREQUAL "arm") # Default ARM target supported by all processors. set(triple arm-none-eabi) endif() +elseif("${ARCH}" STREQUAL "arm64") + set(triple aarch64-none-elf) elseif("${ARCH}" STREQUAL "x86") if(CONFIG_64BIT) set(triple x86_64-pc-none-elf) From a4e411bd13bca24d311a2517a55feed4c5faa31a Mon Sep 17 00:00:00 2001 From: Mark Wang Date: Mon, 27 May 2024 15:26:55 +0800 Subject: [PATCH 2595/2849] dts: arm: nxp: enable udc DT on lpc55s69, rt1060 and rt685 define usbphy in DT and controller DT node ref to usbphy node. define the usbphy yaml and update ehci and ip3511 yaml for usbphy. Signed-off-by: Mark Wang --- dts/arm/nxp/nxp_lpc55S6x_common.dtsi | 6 +++++ dts/arm/nxp/nxp_rt10xx.dtsi | 12 ++++++++++ dts/arm/nxp/nxp_rt6xx_common.dtsi | 6 +++++ dts/bindings/usb/nxp,ehci.yaml | 4 ++++ dts/bindings/usb/nxp,lpcip3511.yaml | 4 ++++ dts/bindings/usb/nxp,usbphy.yaml | 33 ++++++++++++++++++++++++++++ 6 files changed, 65 insertions(+) create mode 100644 dts/bindings/usb/nxp,usbphy.yaml diff --git a/dts/arm/nxp/nxp_lpc55S6x_common.dtsi b/dts/arm/nxp/nxp_lpc55S6x_common.dtsi index c87875c7591ae..bc4aa8402552f 100644 --- a/dts/arm/nxp/nxp_lpc55S6x_common.dtsi +++ b/dts/arm/nxp/nxp_lpc55S6x_common.dtsi @@ -385,6 +385,12 @@ status = "disabled"; }; + usbphy1: usbphy@38000 { + compatible = "nxp,usbphy"; + reg = <0x38000 0x1000>; + status = "disabled"; + }; + ctimer0: ctimer@8000 { compatible = "nxp,lpc-ctimer"; reg = <0x8000 0x1000>; diff --git a/dts/arm/nxp/nxp_rt10xx.dtsi b/dts/arm/nxp/nxp_rt10xx.dtsi index fdc50c2b3e69a..df04eff6841bd 100644 --- a/dts/arm/nxp/nxp_rt10xx.dtsi +++ b/dts/arm/nxp/nxp_rt10xx.dtsi @@ -835,6 +835,18 @@ status = "disabled"; }; + usbphy1: usbphy@400d9000 { + compatible = "nxp,usbphy"; + reg = <0x400D9000 0x1000>; + status = "disabled"; + }; + + usbphy2: usbphy@400da000 { + compatible = "nxp,usbphy"; + reg = <0x400DA000 0x1000>; + status = "disabled"; + }; + usdhc1: usdhc@402c0000 { compatible = "nxp,imx-usdhc"; reg = <0x402c0000 0x4000>; diff --git a/dts/arm/nxp/nxp_rt6xx_common.dtsi b/dts/arm/nxp/nxp_rt6xx_common.dtsi index 47d4258ee8e24..9b85ee2586d6c 100644 --- a/dts/arm/nxp/nxp_rt6xx_common.dtsi +++ b/dts/arm/nxp/nxp_rt6xx_common.dtsi @@ -289,6 +289,12 @@ status = "disabled"; }; + usbphy: usbphy@13b000 { + compatible = "nxp,usbphy"; + reg = <0x13b000 0x1000>; + status = "disabled"; + }; + hs_lspi: spi@126000 { compatible = "nxp,lpc-spi"; /* Enabling cs-gpios below will allow using GPIO CS, diff --git a/dts/bindings/usb/nxp,ehci.yaml b/dts/bindings/usb/nxp,ehci.yaml index cf72a69545c9f..8f1569e2060e7 100644 --- a/dts/bindings/usb/nxp,ehci.yaml +++ b/dts/bindings/usb/nxp,ehci.yaml @@ -6,3 +6,7 @@ description: NXP EHCI USB device mode compatible: nxp,ehci include: "nxp,mcux-usbd.yaml" + +properties: + phy_handle: + type: phandle diff --git a/dts/bindings/usb/nxp,lpcip3511.yaml b/dts/bindings/usb/nxp,lpcip3511.yaml index 70ea118883722..3c799e493907d 100644 --- a/dts/bindings/usb/nxp,lpcip3511.yaml +++ b/dts/bindings/usb/nxp,lpcip3511.yaml @@ -6,3 +6,7 @@ description: NXP LPCIP3511 USB device mode compatible: nxp,lpcip3511 include: "nxp,mcux-usbd.yaml" + +properties: + phy_handle: + type: phandle diff --git a/dts/bindings/usb/nxp,usbphy.yaml b/dts/bindings/usb/nxp,usbphy.yaml new file mode 100644 index 0000000000000..0b1f143dde245 --- /dev/null +++ b/dts/bindings/usb/nxp,usbphy.yaml @@ -0,0 +1,33 @@ +# Copyright 2024 NXP +# SPDX-License-Identifier: Apache-2.0 + +description: | + NXP USB high speed phy that is used on NXP RTxxxx, RTxxx, MCX, LPC and Kinetis + platforms if high speed usb is supported on these platforms. + Note: Only some LPC plafforms use it (like: LPC55S69, LPC55S28 and LPC55S16 etc). + +compatible: "nxp,usbphy" + +include: base.yaml + +properties: + tx-d-cal: + type: int + required: true + description: | + It is board level's value that is used to trim the nominal 17.78mA + current source for the High Speed TX drivers on USB_DP and USB_DM. + + tx-cal-45-dp-ohms: + type: int + required: true + description: | + It is board level's value that is used to trim the nominal 17.78mA + current source for the High Speed TX drivers on USB_DP and USB_DM. + + tx-cal-45-dm-ohms: + type: int + required: true + description: | + It is board level's value that is used to trim the nominal 17.78mA + current source for the High Speed TX drivers on USB_DP and USB_DM. From b6b43c3ed70a8a5eaf92c8cef9b1eb1416e22829 Mon Sep 17 00:00:00 2001 From: Mark Wang Date: Mon, 27 May 2024 15:39:48 +0800 Subject: [PATCH 2596/2849] drivers: udc: implement udc_mcux_ehci and udc_mcux_ip3511 udc_mcux_ehci is based on the MCUX USB controller driver (usb_device_ehci.c); udc_mcux_ip3511 is based on the MCUX USB controller driver (usb_device_lpcip3511.c); add related Kconfig and CMake; include the usb_phy.h path in modules/hal_nxp/usb/CMakeLists.txt because udc_mcux.c use it; add related macros to usb_device_config.h; update CMakeLists for udc_mcux_ehci and udc_mcux_ip3511. Signed-off-by: Mark Wang --- drivers/usb/udc/CMakeLists.txt | 2 + drivers/usb/udc/Kconfig | 1 + drivers/usb/udc/Kconfig.mcux | 17 + drivers/usb/udc/udc_mcux_ehci.c | 929 ++++++++++++++++++++++++ drivers/usb/udc/udc_mcux_ip3511.c | 890 +++++++++++++++++++++++ modules/hal_nxp/CMakeLists.txt | 3 + modules/hal_nxp/usb/CMakeLists.txt | 5 +- modules/hal_nxp/usb/usb_device_config.h | 53 ++ 8 files changed, 1899 insertions(+), 1 deletion(-) create mode 100644 drivers/usb/udc/Kconfig.mcux create mode 100644 drivers/usb/udc/udc_mcux_ehci.c create mode 100644 drivers/usb/udc/udc_mcux_ip3511.c diff --git a/drivers/usb/udc/CMakeLists.txt b/drivers/usb/udc/CMakeLists.txt index 2dd77536b2663..6004729d373fc 100644 --- a/drivers/usb/udc/CMakeLists.txt +++ b/drivers/usb/udc/CMakeLists.txt @@ -13,3 +13,5 @@ zephyr_library_sources_ifdef(CONFIG_UDC_SKELETON udc_skeleton.c) zephyr_library_sources_ifdef(CONFIG_UDC_VIRTUAL udc_virtual.c) zephyr_library_sources_ifdef(CONFIG_UDC_STM32 udc_stm32.c) zephyr_library_sources_ifdef(CONFIG_UDC_IT82XX2 udc_it82xx2.c) +zephyr_library_sources_ifdef(CONFIG_UDC_NXP_EHCI udc_mcux_ehci.c) +zephyr_library_sources_ifdef(CONFIG_UDC_NXP_IP3511 udc_mcux_ip3511.c) diff --git a/drivers/usb/udc/Kconfig b/drivers/usb/udc/Kconfig index b407e1212b562..b4d1df0114ad6 100644 --- a/drivers/usb/udc/Kconfig +++ b/drivers/usb/udc/Kconfig @@ -54,5 +54,6 @@ source "drivers/usb/udc/Kconfig.skeleton" source "drivers/usb/udc/Kconfig.virtual" source "drivers/usb/udc/Kconfig.stm32" source "drivers/usb/udc/Kconfig.it82xx2" +source "drivers/usb/udc/Kconfig.mcux" endif # UDC_DRIVER diff --git a/drivers/usb/udc/Kconfig.mcux b/drivers/usb/udc/Kconfig.mcux new file mode 100644 index 0000000000000..f36eab115b0c6 --- /dev/null +++ b/drivers/usb/udc/Kconfig.mcux @@ -0,0 +1,17 @@ +# Copyright 2024 NXP +# SPDX-License-Identifier: Apache-2.0 + +config UDC_NXP_EHCI + bool "NXP MCUX USB EHCI Device controller driver" + default y + depends on DT_HAS_NXP_EHCI_ENABLED + select NOCACHE_MEMORY if HAS_MCUX_CACHE && CPU_HAS_DCACHE + help + NXP MCUX USB Device Controller Driver for EHCI. + +config UDC_NXP_IP3511 + bool "NXP MCUX USB IP3511 Device controller driver" + default y + depends on DT_HAS_NXP_LPCIP3511_ENABLED + help + NXP MCUX USB Device Controller Driver for KHCI. diff --git a/drivers/usb/udc/udc_mcux_ehci.c b/drivers/usb/udc/udc_mcux_ehci.c new file mode 100644 index 0000000000000..e5e56adb46907 --- /dev/null +++ b/drivers/usb/udc/udc_mcux_ehci.c @@ -0,0 +1,929 @@ +/* + * Copyright 2024 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ +#define DT_DRV_COMPAT nxp_ehci + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "udc_common.h" +#include "usb.h" +#include "usb_device_config.h" +#include "usb_device_mcux_drv_port.h" +#include "usb_device_ehci.h" +#ifdef CONFIG_DT_HAS_NXP_USBPHY_ENABLED +#include "usb_phy.h" +#endif + +#include +LOG_MODULE_REGISTER(udc_mcux, CONFIG_UDC_DRIVER_LOG_LEVEL); + +/* + * There is no real advantage to change control endpoint size + * but we can use it for testing UDC driver API and higher layers. + */ +#define USB_MCUX_MPS0 UDC_MPS0_64 +#define USB_MCUX_EP0_SIZE 64 + +#define PRV_DATA_HANDLE(_handle) CONTAINER_OF(_handle, struct udc_mcux_data, mcux_device) + +struct udc_mcux_config { + const usb_device_controller_interface_struct_t *mcux_if; + void (*irq_enable_func)(const struct device *dev); + void (*irq_disable_func)(const struct device *dev); + size_t num_of_eps; + struct udc_ep_config *ep_cfg_in; + struct udc_ep_config *ep_cfg_out; + uintptr_t base; + const struct pinctrl_dev_config *pincfg; +#ifdef CONFIG_DT_HAS_NXP_USBPHY_ENABLED + usb_phy_config_struct_t *phy_config; +#endif +}; + +struct udc_mcux_data { + const struct device *dev; + usb_device_struct_t mcux_device; + uint8_t controller_id; /* 0xFF is invalid value */ +}; + +/* TODO: implement the cache maintenance + * solution1: Use the non-cached buf to do memcpy before/after giving buffer to usb controller. + * solution2: Use cache API to flush/invalid cache. but it needs the given buffer is + * cache line size aligned and the buffer range cover multiple of cache line size block. + * Need to change the usb stack to implement it, will try to implement it later. + */ +#if defined(CONFIG_NOCACHE_MEMORY) +K_HEAP_DEFINE_NOCACHE(mcux_packet_alloc_pool, USB_DEVICE_CONFIG_ENDPOINTS * 2u * 1024u); + +/* allocate non-cached buffer for usb */ +static void *udc_mcux_nocache_alloc(uint32_t size) +{ + void *p = (void *)k_heap_alloc(&mcux_packet_alloc_pool, size, K_NO_WAIT); + + if (p != NULL) { + (void)memset(p, 0, size); + } + + return p; +} + +/* free the allocated non-cached buffer */ +static void udc_mcux_nocache_free(void *p) +{ + if (p == NULL) { + return; + } + k_heap_free(&mcux_packet_alloc_pool, p); +} +#endif + +static int udc_mcux_control(const struct device *dev, usb_device_control_type_t command, + void *param) +{ + const struct udc_mcux_config *config = dev->config; + const usb_device_controller_interface_struct_t *mcux_if = config->mcux_if; + struct udc_mcux_data *priv = udc_get_private(dev); + usb_status_t status; + + status = mcux_if->deviceControl(priv->mcux_device.controllerHandle, + command, param); + + if (status != kStatus_USB_Success) { + return -ENOMEM; + } + + return 0; +} + +/* If ep is busy, return busy. Otherwise feed the buf to controller */ +static int udc_mcux_ep_feed(const struct device *dev, + struct udc_ep_config *const cfg, + struct net_buf *const buf) +{ + const struct udc_mcux_config *config = dev->config; + const usb_device_controller_interface_struct_t *mcux_if = config->mcux_if; + struct udc_mcux_data *priv = udc_get_private(dev); + usb_status_t status = kStatus_USB_Success; + uint8_t *data; + uint32_t len; + unsigned int key; + usb_device_endpoint_status_struct_t ep_status; + + ep_status.endpointAddress = cfg->addr; + udc_mcux_control(dev, kUSB_DeviceControlGetEndpointStatus, &ep_status); + if (ep_status.endpointStatus == kUSB_DeviceEndpointStateStalled) { + return -EACCES; /* stalled */ + } + + key = irq_lock(); + if (!udc_ep_is_busy(dev, cfg->addr)) { + udc_ep_set_busy(dev, cfg->addr, true); + irq_unlock(key); + + if (USB_EP_DIR_IS_OUT(cfg->addr)) { + len = net_buf_tailroom(buf); +#if defined(CONFIG_NOCACHE_MEMORY) + data = (len == 0 ? NULL : udc_mcux_nocache_alloc(len)); +#else + data = net_buf_tail(buf); +#endif + status = mcux_if->deviceRecv(priv->mcux_device.controllerHandle, + cfg->addr, data, len); + } else { + len = buf->len; +#if defined(CONFIG_NOCACHE_MEMORY) + data = (len == 0 ? NULL : udc_mcux_nocache_alloc(len)); + memcpy(data, buf->data, len); +#else + data = buf->data; +#endif + status = mcux_if->deviceSend(priv->mcux_device.controllerHandle, + cfg->addr, data, len); + } + + key = irq_lock(); + if (status != kStatus_USB_Success) { + udc_ep_set_busy(dev, cfg->addr, false); + } + irq_unlock(key); + } else { + irq_unlock(key); + return -EBUSY; + } + + return (status == kStatus_USB_Success ? 0 : -EIO); +} + +/* return success if the ep is busy or stalled. */ +static int udc_mcux_ep_try_feed(const struct device *dev, + struct udc_ep_config *const cfg) +{ + struct net_buf *feed_buf; + + feed_buf = udc_buf_peek(dev, cfg->addr); + if (feed_buf) { + int ret = udc_mcux_ep_feed(dev, cfg, feed_buf); + + return ((ret == -EBUSY || ret == -EACCES || ret == 0) ? 0 : -EIO); + } + + return 0; +} + +/* + * Allocate buffer and initiate a new control OUT transfer. + */ +static int udc_mcux_ctrl_feed_dout(const struct device *dev, + const size_t length) +{ + struct net_buf *buf; + struct udc_ep_config *cfg = udc_get_ep_cfg(dev, USB_CONTROL_EP_OUT); + int ret; + + buf = udc_ctrl_alloc(dev, USB_CONTROL_EP_OUT, length); + if (buf == NULL) { + return -ENOMEM; + } + + net_buf_put(&cfg->fifo, buf); + + ret = udc_mcux_ep_feed(dev, cfg, buf); + + if (ret) { + net_buf_unref(buf); + return ret; + } + + return 0; +} + +static int udc_mcux_handler_setup(const struct device *dev, struct usb_setup_packet *setup) +{ + int err; + struct net_buf *buf; + + LOG_DBG("setup packet"); + buf = udc_ctrl_alloc(dev, USB_CONTROL_EP_OUT, + sizeof(struct usb_setup_packet)); + if (buf == NULL) { + LOG_ERR("Failed to allocate for setup"); + return -EIO; + } + + udc_ep_buf_set_setup(buf); + memcpy(buf->data, setup, 8); + net_buf_add(buf, 8); + + if (setup->RequestType.type == USB_REQTYPE_TYPE_STANDARD && + setup->RequestType.direction == USB_REQTYPE_DIR_TO_DEVICE && + setup->bRequest == USB_SREQ_SET_ADDRESS && + setup->wLength == 0) { + udc_mcux_control(dev, kUSB_DeviceControlPreSetDeviceAddress, + &setup->wValue); + } + + /* Update to next stage of control transfer */ + udc_ctrl_update_stage(dev, buf); + + if (!buf->len) { + return -EIO; + } + + if (udc_ctrl_stage_is_data_out(dev)) { + /* Allocate and feed buffer for data OUT stage */ + LOG_DBG("s:%p|feed for -out-", buf); + err = udc_mcux_ctrl_feed_dout(dev, udc_data_stage_length(buf)); + if (err == -ENOMEM) { + err = udc_submit_ep_event(dev, buf, err); + } + } else if (udc_ctrl_stage_is_data_in(dev)) { + err = udc_ctrl_submit_s_in_status(dev); + } else { + err = udc_ctrl_submit_s_status(dev); + } + + return err; +} + +static int udc_mcux_handler_ctrl_out(const struct device *dev, struct net_buf *buf, + uint8_t *mcux_buf, uint16_t mcux_len) +{ + int err = 0; + uint32_t len; + + len = MIN(net_buf_tailroom(buf), mcux_len); +#if defined(CONFIG_NOCACHE_MEMORY) + memcpy(net_buf_tail(buf), mcux_buf, len); + udc_mcux_nocache_free(mcux_buf); +#endif + net_buf_add(buf, len); + if (udc_ctrl_stage_is_status_out(dev)) { + /* Update to next stage of control transfer */ + udc_ctrl_update_stage(dev, buf); + /* Status stage finished, notify upper layer */ + err = udc_ctrl_submit_status(dev, buf); + } else { + /* Update to next stage of control transfer */ + udc_ctrl_update_stage(dev, buf); + } + + if (udc_ctrl_stage_is_status_in(dev)) { + err = udc_ctrl_submit_s_out_status(dev, buf); + } + + return err; +} + +static int udc_mcux_handler_ctrl_in(const struct device *dev, struct net_buf *buf, + uint8_t *mcux_buf, uint16_t mcux_len) +{ + int err = 0; + uint32_t len; + + len = MIN(buf->len, mcux_len); + buf->data += len; + buf->len -= len; +#if defined(CONFIG_NOCACHE_MEMORY) + udc_mcux_nocache_free(mcux_buf); +#endif + + if (udc_ctrl_stage_is_status_in(dev) || + udc_ctrl_stage_is_no_data(dev)) { + /* Status stage finished, notify upper layer */ + err = udc_ctrl_submit_status(dev, buf); + } + + /* Update to next stage of control transfer */ + udc_ctrl_update_stage(dev, buf); + + if (udc_ctrl_stage_is_status_out(dev)) { + /* + * IN transfer finished, release buffer, + * control OUT buffer should be already fed. + */ + net_buf_unref(buf); + err = udc_mcux_ctrl_feed_dout(dev, 0u); + } + + return err; +} + +static int udc_mcux_handler_non_ctrl_in(const struct device *dev, uint8_t ep, + struct net_buf *buf, uint8_t *mcux_buf, uint16_t mcux_len) +{ + int err; + uint32_t len; + + len = MIN(buf->len, mcux_len); + buf->data += len; + buf->len -= len; + +#if defined(CONFIG_NOCACHE_MEMORY) + udc_mcux_nocache_free(mcux_buf); +#endif + err = udc_submit_ep_event(dev, buf, 0); + udc_mcux_ep_try_feed(dev, udc_get_ep_cfg(dev, ep)); + + return err; +} + +static int udc_mcux_handler_non_ctrl_out(const struct device *dev, uint8_t ep, + struct net_buf *buf, uint8_t *mcux_buf, uint16_t mcux_len) +{ + int err; + uint32_t len; + + len = MIN(net_buf_tailroom(buf), mcux_len); +#if defined(CONFIG_NOCACHE_MEMORY) + memcpy(net_buf_tail(buf), mcux_buf, len); +#endif + net_buf_add(buf, len); + +#if defined(CONFIG_NOCACHE_MEMORY) + udc_mcux_nocache_free(mcux_buf); +#endif + err = udc_submit_ep_event(dev, buf, 0); + udc_mcux_ep_try_feed(dev, udc_get_ep_cfg(dev, ep)); + + return err; +} + +static int udc_mcux_handler_out(const struct device *dev, uint8_t ep, + uint8_t *mcux_buf, uint16_t mcux_len) +{ + int err; + struct net_buf *buf; + unsigned int key; + + buf = udc_buf_get(dev, ep); + + key = irq_lock(); + udc_ep_set_busy(dev, ep, false); + irq_unlock(key); + + if (buf == NULL) { + udc_submit_event(dev, UDC_EVT_ERROR, -ENOBUFS); + return -ENOBUFS; + } + + if (ep == USB_CONTROL_EP_OUT) { + err = udc_mcux_handler_ctrl_out(dev, buf, mcux_buf, mcux_len); + } else { + err = udc_mcux_handler_non_ctrl_out(dev, ep, buf, mcux_buf, mcux_len); + } + + return err; +} + +/* return true - zlp is feed; false - no zlp */ +static bool udc_mcux_handler_zlt(const struct device *dev, uint8_t ep, struct net_buf *buf, + uint16_t mcux_len) +{ + const struct udc_mcux_config *config = dev->config; + const usb_device_controller_interface_struct_t *mcux_if = config->mcux_if; + struct udc_mcux_data *priv = udc_get_private(dev); + + /* The whole transfer is already done by MCUX controller driver. */ + if (mcux_len >= buf->len) { + if (udc_ep_buf_has_zlp(buf)) { + usb_status_t status; + + udc_ep_buf_clear_zlp(buf); + status = mcux_if->deviceRecv(priv->mcux_device.controllerHandle, + ep, NULL, 0); + if (status != kStatus_USB_Success) { + udc_submit_event(dev, UDC_EVT_ERROR, -EIO); + return false; + } + return true; + } + } + + return false; +} + +static int udc_mcux_handler_in(const struct device *dev, uint8_t ep, + uint8_t *mcux_buf, uint16_t mcux_len) +{ + int err; + struct net_buf *buf; + unsigned int key; + + buf = udc_buf_peek(dev, ep); + if (buf == NULL) { + udc_submit_event(dev, UDC_EVT_ERROR, -ENOBUFS); + return -ENOBUFS; + } + + if (udc_mcux_handler_zlt(dev, ep, buf, mcux_len)) { + return 0; + } + + buf = udc_buf_get(dev, ep); + + key = irq_lock(); + udc_ep_set_busy(dev, ep, false); + irq_unlock(key); + + if (buf == NULL) { + udc_submit_event(dev, UDC_EVT_ERROR, -ENOBUFS); + return -ENOBUFS; + } + if (ep == USB_CONTROL_EP_IN) { + err = udc_mcux_handler_ctrl_in(dev, buf, mcux_buf, mcux_len); + } else { + err = udc_mcux_handler_non_ctrl_in(dev, ep, buf, mcux_buf, mcux_len); + } + + return err; +} + +/* NXP MCUX controller driver notify transfers/status through this interface */ +usb_status_t USB_DeviceNotificationTrigger(void *handle, void *msg) +{ + usb_device_callback_message_struct_t *mcux_msg = msg; + uint8_t ep; + usb_device_notification_t mcux_notify; + struct udc_mcux_data *priv; + const struct device *dev; + usb_status_t mcux_status = kStatus_USB_Success; + int err = 0; + + if ((NULL == msg) || (NULL == handle)) { + return kStatus_USB_InvalidHandle; + } + + mcux_notify = (usb_device_notification_t)mcux_msg->code; + priv = (struct udc_mcux_data *)(PRV_DATA_HANDLE(handle)); + dev = priv->dev; + + switch (mcux_notify) { + case kUSB_DeviceNotifyBusReset: + struct udc_ep_config *cfg; + + udc_mcux_control(dev, kUSB_DeviceControlSetDefaultStatus, NULL); + cfg = udc_get_ep_cfg(dev, USB_CONTROL_EP_OUT); + if (cfg->stat.enabled) { + udc_ep_disable_internal(dev, USB_CONTROL_EP_OUT); + } + cfg = udc_get_ep_cfg(dev, USB_CONTROL_EP_IN); + if (cfg->stat.enabled) { + udc_ep_disable_internal(dev, USB_CONTROL_EP_IN); + } + if (udc_ep_enable_internal(dev, USB_CONTROL_EP_OUT, + USB_EP_TYPE_CONTROL, + USB_MCUX_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, + USB_MCUX_EP0_SIZE, 0)) { + LOG_ERR("Failed to enable control endpoint"); + return -EIO; + } + udc_submit_event(dev, UDC_EVT_RESET, 0); + break; + case kUSB_DeviceNotifyError: + udc_submit_event(dev, UDC_EVT_ERROR, -EIO); + break; + case kUSB_DeviceNotifySuspend: + udc_set_suspended(dev, true); + udc_submit_event(dev, UDC_EVT_SUSPEND, 0); + break; + case kUSB_DeviceNotifyResume: + udc_set_suspended(dev, false); + udc_submit_event(dev, UDC_EVT_RESUME, 0); + break; + case kUSB_DeviceNotifyLPMSleep: + break; + case kUSB_DeviceNotifyDetach: + udc_submit_event(dev, UDC_EVT_VBUS_REMOVED, 0); + break; + case kUSB_DeviceNotifyAttach: + udc_submit_event(dev, UDC_EVT_VBUS_READY, 0); + break; + default: + ep = mcux_msg->code; + if (mcux_msg->isSetup) { + struct usb_setup_packet *setup = + (struct usb_setup_packet *)mcux_msg->buffer; + + err = udc_mcux_handler_setup(dev, setup); + } else if (USB_EP_DIR_IS_IN(ep)) { + err = udc_mcux_handler_in(dev, ep, mcux_msg->buffer, mcux_msg->length); + } else { + err = udc_mcux_handler_out(dev, ep, mcux_msg->buffer, mcux_msg->length); + } + + break; + } + + if (unlikely(err)) { + udc_submit_event(dev, UDC_EVT_ERROR, err); + mcux_status = kStatus_USB_Error; + } + return mcux_status; +} + +static void udc_mcux_isr(const struct device *dev) +{ + struct udc_mcux_data *priv = udc_get_private(dev); + + USB_DeviceEhciIsrFunction((void *)(&priv->mcux_device)); +} + +/* Return actual USB device speed */ +static enum udc_bus_speed udc_mcux_device_speed(const struct device *dev) +{ + int err; + uint8_t mcux_speed; + + err = udc_mcux_control(dev, kUSB_DeviceControlGetSpeed, &mcux_speed); + if (err) { + /* + * In the current version of all NXP USB device drivers, + * no error is returned if the parameter is correct. + */ + return UDC_BUS_SPEED_FS; + } + + switch (mcux_speed) { + case USB_SPEED_HIGH: + return UDC_BUS_SPEED_HS; + case USB_SPEED_LOW: + __ASSERT(false, "Low speed mode not supported"); + __fallthrough; + case USB_SPEED_FULL: + __fallthrough; + default: + return UDC_BUS_SPEED_FS; + } +} + +static int udc_mcux_ep_enqueue(const struct device *dev, + struct udc_ep_config *const cfg, + struct net_buf *const buf) +{ + udc_buf_put(cfg, buf); + if (cfg->stat.halted) { + LOG_DBG("ep 0x%02x halted", cfg->addr); + return 0; + } + + return udc_mcux_ep_try_feed(dev, cfg); +} + +static int udc_mcux_ep_dequeue(const struct device *dev, + struct udc_ep_config *const cfg) +{ + struct net_buf *buf; + unsigned int key; + + cfg->stat.halted = false; + buf = udc_buf_get_all(dev, cfg->addr); + if (buf) { + udc_submit_ep_event(dev, buf, -ECONNABORTED); + } + + key = irq_lock(); + udc_ep_set_busy(dev, cfg->addr, false); + irq_unlock(key); + + return 0; +} + +static int udc_mcux_ep_set_halt(const struct device *dev, + struct udc_ep_config *const cfg) +{ + return udc_mcux_control(dev, kUSB_DeviceControlEndpointStall, &cfg->addr); +} + +static int udc_mcux_ep_clear_halt(const struct device *dev, + struct udc_ep_config *const cfg) +{ + (void)udc_mcux_control(dev, kUSB_DeviceControlEndpointUnstall, &cfg->addr); + /* transfer is enqueued after stalled */ + return udc_mcux_ep_try_feed(dev, cfg); +} + +static int udc_mcux_ep_enable(const struct device *dev, + struct udc_ep_config *const cfg) +{ + usb_device_endpoint_init_struct_t ep_init; + + LOG_DBG("Enable ep 0x%02x", cfg->addr); + + ep_init.zlt = 0U; + ep_init.interval = cfg->interval; + ep_init.endpointAddress = cfg->addr; + ep_init.maxPacketSize = cfg->mps; + + switch (cfg->attributes & USB_EP_TRANSFER_TYPE_MASK) { + case USB_EP_TYPE_CONTROL: + ep_init.transferType = USB_ENDPOINT_CONTROL; + break; + case USB_EP_TYPE_BULK: + ep_init.transferType = USB_ENDPOINT_BULK; + break; + case USB_EP_TYPE_INTERRUPT: + ep_init.transferType = USB_ENDPOINT_INTERRUPT; + break; + case USB_EP_TYPE_ISO: + ep_init.transferType = USB_ENDPOINT_ISOCHRONOUS; + break; + default: + return -EINVAL; + } + + return udc_mcux_control(dev, kUSB_DeviceControlEndpointInit, &ep_init); +} + +static int udc_mcux_ep_disable(const struct device *dev, + struct udc_ep_config *const cfg) +{ + LOG_DBG("Disable ep 0x%02x", cfg->addr); + + return udc_mcux_control(dev, kUSB_DeviceControlEndpointDeinit, &cfg->addr); +} + +static int udc_mcux_host_wakeup(const struct device *dev) +{ + return -ENOTSUP; +} + +static int udc_mcux_set_address(const struct device *dev, const uint8_t addr) +{ + uint8_t temp_addr = addr; + + return udc_mcux_control(dev, kUSB_DeviceControlSetDeviceAddress, &temp_addr); +} + +static int udc_mcux_enable(const struct device *dev) +{ + return udc_mcux_control(dev, kUSB_DeviceControlRun, NULL); +} + +static int udc_mcux_disable(const struct device *dev) +{ + return udc_mcux_control(dev, kUSB_DeviceControlStop, NULL); +} + +static int udc_mcux_init(const struct device *dev) +{ + const struct udc_mcux_config *config = dev->config; + const usb_device_controller_interface_struct_t *mcux_if = config->mcux_if; + struct udc_mcux_data *priv = udc_get_private(dev); + usb_status_t status; + + if (priv->controller_id == 0xFFu) { + return -ENOMEM; + } + +#ifdef CONFIG_DT_HAS_NXP_USBPHY_ENABLED + if (config->phy_config != NULL) { + USB_EhciPhyInit(priv->controller_id, 0u, + (usb_phy_config_struct_t *)&config->phy_config); + } +#endif + + /* Init MCUX USB device driver. */ + status = mcux_if->deviceInit(priv->controller_id, + &priv->mcux_device, &(priv->mcux_device.controllerHandle)); + if (status != kStatus_USB_Success) { + return -ENOMEM; + } + + /* enable USB interrupt */ + config->irq_enable_func(dev); + + LOG_DBG("Initialized USB controller %x", (uint32_t)config->base); + + return 0; +} + +static int udc_mcux_shutdown(const struct device *dev) +{ + const struct udc_mcux_config *config = dev->config; + const usb_device_controller_interface_struct_t *mcux_if = config->mcux_if; + struct udc_mcux_data *priv = udc_get_private(dev); + usb_status_t status; + + /* Disable interrupt */ + config->irq_disable_func(dev); + + /* De-init MCUX USB device driver. */ + status = mcux_if->deviceDeinit(priv->mcux_device.controllerHandle); + if (status != kStatus_USB_Success) { + return -ENOMEM; + } + + return 0; +} + +static int udc_mcux_lock(const struct device *dev) +{ + return udc_lock_internal(dev, K_FOREVER); +} + +static int udc_mcux_unlock(const struct device *dev) +{ + return udc_unlock_internal(dev); +} + +static inline void udc_mcux_get_hal_driver_id(struct udc_mcux_data *priv, + const struct udc_mcux_config *config) +{ + /* + * MCUX USB controller drivers use an ID to tell the HAL drivers + * which controller is being used. This part of the code converts + * the base address to the ID value. + */ +#ifdef USBHS_STACK_BASE_ADDRS + uintptr_t usb_base_addrs[] = USBHS_STACK_BASE_ADDRS; +#else + uintptr_t usb_base_addrs[] = USBHS_BASE_ADDRS; +#endif + + /* get the right controller id */ + priv->controller_id = 0xFFu; /* invalid value */ + for (uint8_t i = 0; i < ARRAY_SIZE(usb_base_addrs); i++) { + if (usb_base_addrs[i] == config->base) { + priv->controller_id = kUSB_ControllerEhci0 + i; + break; + } + } +} + +static int udc_mcux_driver_preinit(const struct device *dev) +{ + const struct udc_mcux_config *config = dev->config; + struct udc_data *data = dev->data; + struct udc_mcux_data *priv = data->priv; + int err; + + udc_mcux_get_hal_driver_id(priv, config); + if (priv->controller_id == 0xFFu) { + return -ENOMEM; + } + + k_mutex_init(&data->mutex); + + for (int i = 0; i < config->num_of_eps; i++) { + config->ep_cfg_out[i].caps.out = 1; + if (i == 0) { + config->ep_cfg_out[i].caps.control = 1; + config->ep_cfg_out[i].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 = 1024; + } + + config->ep_cfg_out[i].addr = USB_EP_DIR_OUT | i; + err = udc_register_ep(dev, &config->ep_cfg_out[i]); + if (err != 0) { + LOG_ERR("Failed to register endpoint"); + return err; + } + } + + for (int i = 0; i < config->num_of_eps; i++) { + config->ep_cfg_in[i].caps.in = 1; + if (i == 0) { + config->ep_cfg_in[i].caps.control = 1; + config->ep_cfg_in[i].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 = 1024; + } + + config->ep_cfg_in[i].addr = USB_EP_DIR_IN | i; + err = udc_register_ep(dev, &config->ep_cfg_in[i]); + if (err != 0) { + LOG_ERR("Failed to register endpoint"); + return err; + } + } + + /* Requires udc_mcux_host_wakeup() implementation */ + data->caps.rwup = false; + data->caps.mps0 = USB_MCUX_MPS0; + data->caps.hs = true; + priv->dev = dev; + + pinctrl_apply_state(config->pincfg, PINCTRL_STATE_DEFAULT); + + return 0; +} + +static const struct udc_api udc_mcux_api = { + .device_speed = udc_mcux_device_speed, + .ep_enqueue = udc_mcux_ep_enqueue, + .ep_dequeue = udc_mcux_ep_dequeue, + .ep_set_halt = udc_mcux_ep_set_halt, + .ep_clear_halt = udc_mcux_ep_clear_halt, + .ep_try_config = NULL, + .ep_enable = udc_mcux_ep_enable, + .ep_disable = udc_mcux_ep_disable, + .host_wakeup = udc_mcux_host_wakeup, + .set_address = udc_mcux_set_address, + .enable = udc_mcux_enable, + .disable = udc_mcux_disable, + .init = udc_mcux_init, + .shutdown = udc_mcux_shutdown, + .lock = udc_mcux_lock, + .unlock = udc_mcux_unlock, +}; + +/* EHCI device driver interface */ +static const usb_device_controller_interface_struct_t udc_mcux_if = { + USB_DeviceEhciInit, USB_DeviceEhciDeinit, USB_DeviceEhciSend, + USB_DeviceEhciRecv, USB_DeviceEhciCancel, USB_DeviceEhciControl +}; + +#ifdef CONFIG_DT_HAS_NXP_USBPHY_ENABLED +#define UDC_MCUX_PHY_DEFINE(n) \ +static usb_phy_config_struct_t phy_config_##n = { \ + .D_CAL = DT_PROP_OR(DT_INST_PHANDLE(n, phy_handle), tx_d_cal, 0), \ + .TXCAL45DP = DT_PROP_OR(DT_INST_PHANDLE(n, phy_handle), tx_cal_45_dp_ohms, 0), \ + .TXCAL45DM = DT_PROP_OR(DT_INST_PHANDLE(n, phy_handle), tx_cal_45_dm_ohms, 0), \ +} + +#define UDC_MCUX_PHY_DEFINE_OR(n) \ + COND_CODE_1(DT_NODE_HAS_PROP(DT_DRV_INST(n), phy_handle), \ + (UDC_MCUX_PHY_DEFINE(n)), ()) + +#define UDC_MCUX_PHY_CFG_PTR_OR_NULL(n) \ + .phy_config = COND_CODE_1(DT_NODE_HAS_PROP(DT_DRV_INST(n), phy_handle), \ + (&phy_config_##n), (NULL)) +#else +#define UDC_MCUX_PHY_DEFINE_OR(n) +#define UDC_MCUX_PHY_CFG_PTR_OR_NULL(n) +#endif + +#define USB_MCUX_EHCI_DEVICE_DEFINE(n) \ + UDC_MCUX_PHY_DEFINE_OR(n); \ + \ + static void udc_irq_enable_func##n(const struct device *dev) \ + { \ + IRQ_CONNECT(DT_INST_IRQN(n), \ + DT_INST_IRQ(n, priority), \ + udc_mcux_isr, \ + DEVICE_DT_INST_GET(n), 0); \ + \ + irq_enable(DT_INST_IRQN(n)); \ + } \ + \ + static void udc_irq_disable_func##n(const struct device *dev) \ + { \ + irq_disable(DT_INST_IRQN(n)); \ + } \ + \ + static struct udc_ep_config \ + ep_cfg_out##n[DT_INST_PROP(n, num_bidir_endpoints)]; \ + static struct udc_ep_config \ + ep_cfg_in##n[DT_INST_PROP(n, num_bidir_endpoints)]; \ + \ + PINCTRL_DT_INST_DEFINE(n); \ + \ + static struct udc_mcux_config priv_config_##n = { \ + .base = DT_INST_REG_ADDR(n), \ + .irq_enable_func = udc_irq_enable_func##n, \ + .irq_disable_func = udc_irq_disable_func##n, \ + .num_of_eps = DT_INST_PROP(n, num_bidir_endpoints), \ + .ep_cfg_in = ep_cfg_in##n, \ + .ep_cfg_out = ep_cfg_out##n, \ + .mcux_if = &udc_mcux_if, \ + .pincfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n), \ + UDC_MCUX_PHY_CFG_PTR_OR_NULL(n), \ + }; \ + \ + static struct udc_mcux_data priv_data_##n = { \ + }; \ + \ + static struct udc_data udc_data_##n = { \ + .mutex = Z_MUTEX_INITIALIZER(udc_data_##n.mutex), \ + .priv = &priv_data_##n, \ + }; \ + \ + DEVICE_DT_INST_DEFINE(n, udc_mcux_driver_preinit, NULL, \ + &udc_data_##n, &priv_config_##n, \ + POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEVICE, \ + &udc_mcux_api); + +DT_INST_FOREACH_STATUS_OKAY(USB_MCUX_EHCI_DEVICE_DEFINE) diff --git a/drivers/usb/udc/udc_mcux_ip3511.c b/drivers/usb/udc/udc_mcux_ip3511.c new file mode 100644 index 0000000000000..d3b257e80e75a --- /dev/null +++ b/drivers/usb/udc/udc_mcux_ip3511.c @@ -0,0 +1,890 @@ +/* + * Copyright 2024 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ +#define DT_DRV_COMPAT nxp_lpcip3511 + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "udc_common.h" +#include "usb.h" +#include "usb_device_config.h" +#include "usb_device_mcux_drv_port.h" +#include "usb_device_lpcip3511.h" +#ifdef CONFIG_DT_HAS_NXP_USBPHY_ENABLED +#include "usb_phy.h" +#endif + +#include +LOG_MODULE_REGISTER(udc_mcux, CONFIG_UDC_DRIVER_LOG_LEVEL); + +/* + * There is no real advantage to change control endpoint size + * but we can use it for testing UDC driver API and higher layers. + */ +#define USB_MCUX_MPS0 UDC_MPS0_64 +#define USB_MCUX_EP0_SIZE 64 + +#define PRV_DATA_HANDLE(_handle) CONTAINER_OF(_handle, struct udc_mcux_data, mcux_device) + +struct udc_mcux_config { + const usb_device_controller_interface_struct_t *mcux_if; + void (*irq_enable_func)(const struct device *dev); + void (*irq_disable_func)(const struct device *dev); + size_t num_of_eps; + struct udc_ep_config *ep_cfg_in; + struct udc_ep_config *ep_cfg_out; + uintptr_t base; + const struct pinctrl_dev_config *pincfg; +#ifdef CONFIG_DT_HAS_NXP_USBPHY_ENABLED + usb_phy_config_struct_t *phy_config; +#endif +}; + +struct udc_mcux_data { + const struct device *dev; + usb_device_struct_t mcux_device; + uint8_t controller_id; /* 0xFF is invalid value */ +}; + +static int udc_mcux_control(const struct device *dev, usb_device_control_type_t command, + void *param) +{ + const struct udc_mcux_config *config = dev->config; + const usb_device_controller_interface_struct_t *mcux_if = config->mcux_if; + struct udc_mcux_data *priv = udc_get_private(dev); + usb_status_t status; + + status = mcux_if->deviceControl(priv->mcux_device.controllerHandle, + command, param); + + if (status != kStatus_USB_Success) { + return -ENOMEM; + } + + return 0; +} + +/* If ep is busy, return busy. Otherwise feed the buf to controller */ +static int udc_mcux_ep_feed(const struct device *dev, + struct udc_ep_config *const cfg, + struct net_buf *const buf) +{ + const struct udc_mcux_config *config = dev->config; + const usb_device_controller_interface_struct_t *mcux_if = config->mcux_if; + struct udc_mcux_data *priv = udc_get_private(dev); + usb_status_t status = kStatus_USB_Success; + uint8_t *data; + uint32_t len; + unsigned int key; + usb_device_endpoint_status_struct_t ep_status; + + ep_status.endpointAddress = cfg->addr; + udc_mcux_control(dev, kUSB_DeviceControlGetEndpointStatus, &ep_status); + if (ep_status.endpointStatus == kUSB_DeviceEndpointStateStalled) { + return -EACCES; /* stalled */ + } + + key = irq_lock(); + if (!udc_ep_is_busy(dev, cfg->addr)) { + udc_ep_set_busy(dev, cfg->addr, true); + irq_unlock(key); + + if (USB_EP_DIR_IS_OUT(cfg->addr)) { + len = net_buf_tailroom(buf); + data = net_buf_tail(buf); + status = mcux_if->deviceRecv(priv->mcux_device.controllerHandle, + cfg->addr, data, len); + } else { + len = buf->len; + data = buf->data; + status = mcux_if->deviceSend(priv->mcux_device.controllerHandle, + cfg->addr, data, len); + } + + key = irq_lock(); + if (status != kStatus_USB_Success) { + udc_ep_set_busy(dev, cfg->addr, false); + } + irq_unlock(key); + } else { + irq_unlock(key); + return -EBUSY; + } + + return (status == kStatus_USB_Success ? 0 : -EIO); +} + +/* return success if the ep is busy or stalled. */ +static int udc_mcux_ep_try_feed(const struct device *dev, + struct udc_ep_config *const cfg) +{ + struct net_buf *feed_buf; + + feed_buf = udc_buf_peek(dev, cfg->addr); + if (feed_buf) { + int ret = udc_mcux_ep_feed(dev, cfg, feed_buf); + + return ((ret == -EBUSY || ret == -EACCES || ret == 0) ? 0 : -EIO); + } + + return 0; +} + +/* + * Allocate buffer and initiate a new control OUT transfer. + */ +static int udc_mcux_ctrl_feed_dout(const struct device *dev, + const size_t length) +{ + struct net_buf *buf; + struct udc_ep_config *cfg = udc_get_ep_cfg(dev, USB_CONTROL_EP_OUT); + int ret; + + buf = udc_ctrl_alloc(dev, USB_CONTROL_EP_OUT, length); + if (buf == NULL) { + return -ENOMEM; + } + + net_buf_put(&cfg->fifo, buf); + + ret = udc_mcux_ep_feed(dev, cfg, buf); + + if (ret) { + net_buf_unref(buf); + return ret; + } + + return 0; +} + +static int udc_mcux_handler_setup(const struct device *dev, struct usb_setup_packet *setup) +{ + int err; + struct net_buf *buf; + + LOG_DBG("setup packet"); + buf = udc_ctrl_alloc(dev, USB_CONTROL_EP_OUT, + sizeof(struct usb_setup_packet)); + if (buf == NULL) { + LOG_ERR("Failed to allocate for setup"); + return -EIO; + } + + udc_ep_buf_set_setup(buf); + memcpy(buf->data, setup, 8); + net_buf_add(buf, 8); + + if (setup->RequestType.type == USB_REQTYPE_TYPE_STANDARD && + setup->RequestType.direction == USB_REQTYPE_DIR_TO_DEVICE && + setup->bRequest == USB_SREQ_SET_ADDRESS && + setup->wLength == 0) { + udc_mcux_control(dev, kUSB_DeviceControlPreSetDeviceAddress, + &setup->wValue); + } + + /* Update to next stage of control transfer */ + udc_ctrl_update_stage(dev, buf); + + if (!buf->len) { + return -EIO; + } + + if (udc_ctrl_stage_is_data_out(dev)) { + /* Allocate and feed buffer for data OUT stage */ + LOG_DBG("s:%p|feed for -out-", buf); + err = udc_mcux_ctrl_feed_dout(dev, udc_data_stage_length(buf)); + if (err == -ENOMEM) { + err = udc_submit_ep_event(dev, buf, err); + } + } else if (udc_ctrl_stage_is_data_in(dev)) { + err = udc_ctrl_submit_s_in_status(dev); + } else { + err = udc_ctrl_submit_s_status(dev); + } + + return err; +} + +static int udc_mcux_handler_ctrl_out(const struct device *dev, struct net_buf *buf, + uint8_t *mcux_buf, uint16_t mcux_len) +{ + int err = 0; + uint32_t len; + + len = MIN(net_buf_tailroom(buf), mcux_len); + net_buf_add(buf, len); + if (udc_ctrl_stage_is_status_out(dev)) { + /* Update to next stage of control transfer */ + udc_ctrl_update_stage(dev, buf); + /* Status stage finished, notify upper layer */ + err = udc_ctrl_submit_status(dev, buf); + } else { + /* Update to next stage of control transfer */ + udc_ctrl_update_stage(dev, buf); + } + + if (udc_ctrl_stage_is_status_in(dev)) { + err = udc_ctrl_submit_s_out_status(dev, buf); + } + + return err; +} + +static int udc_mcux_handler_ctrl_in(const struct device *dev, struct net_buf *buf, + uint8_t *mcux_buf, uint16_t mcux_len) +{ + int err = 0; + uint32_t len; + + len = MIN(buf->len, mcux_len); + buf->data += len; + buf->len -= len; + + if (udc_ctrl_stage_is_status_in(dev) || + udc_ctrl_stage_is_no_data(dev)) { + /* Status stage finished, notify upper layer */ + err = udc_ctrl_submit_status(dev, buf); + } + + /* Update to next stage of control transfer */ + udc_ctrl_update_stage(dev, buf); + + if (udc_ctrl_stage_is_status_out(dev)) { + /* + * IN transfer finished, release buffer, + * control OUT buffer should be already fed. + */ + net_buf_unref(buf); + err = udc_mcux_ctrl_feed_dout(dev, 0u); + } + + return err; +} + +static int udc_mcux_handler_non_ctrl_in(const struct device *dev, uint8_t ep, + struct net_buf *buf, uint8_t *mcux_buf, uint16_t mcux_len) +{ + int err; + uint32_t len; + + len = MIN(buf->len, mcux_len); + buf->data += len; + buf->len -= len; + + err = udc_submit_ep_event(dev, buf, 0); + udc_mcux_ep_try_feed(dev, udc_get_ep_cfg(dev, ep)); + + return err; +} + +static int udc_mcux_handler_non_ctrl_out(const struct device *dev, uint8_t ep, + struct net_buf *buf, uint8_t *mcux_buf, uint16_t mcux_len) +{ + int err; + uint32_t len; + + len = MIN(net_buf_tailroom(buf), mcux_len); + net_buf_add(buf, len); + + err = udc_submit_ep_event(dev, buf, 0); + udc_mcux_ep_try_feed(dev, udc_get_ep_cfg(dev, ep)); + + return err; +} + +static int udc_mcux_handler_out(const struct device *dev, uint8_t ep, + uint8_t *mcux_buf, uint16_t mcux_len) +{ + int err; + struct net_buf *buf; + unsigned int key; + + buf = udc_buf_get(dev, ep); + + key = irq_lock(); + udc_ep_set_busy(dev, ep, false); + irq_unlock(key); + + if (buf == NULL) { + udc_submit_event(dev, UDC_EVT_ERROR, -ENOBUFS); + return -ENOBUFS; + } + + if (ep == USB_CONTROL_EP_OUT) { + err = udc_mcux_handler_ctrl_out(dev, buf, mcux_buf, mcux_len); + } else { + err = udc_mcux_handler_non_ctrl_out(dev, ep, buf, mcux_buf, mcux_len); + } + + return err; +} + +/* return true - zlp is feed; false - no zlp */ +static bool udc_mcux_handler_zlt(const struct device *dev, uint8_t ep, struct net_buf *buf, + uint16_t mcux_len) +{ + const struct udc_mcux_config *config = dev->config; + const usb_device_controller_interface_struct_t *mcux_if = config->mcux_if; + struct udc_mcux_data *priv = udc_get_private(dev); + + /* The whole transfer is already done by MCUX controller driver. */ + if (mcux_len >= buf->len) { + if (udc_ep_buf_has_zlp(buf)) { + usb_status_t status; + + udc_ep_buf_clear_zlp(buf); + status = mcux_if->deviceRecv(priv->mcux_device.controllerHandle, + ep, NULL, 0); + if (status != kStatus_USB_Success) { + udc_submit_event(dev, UDC_EVT_ERROR, -EIO); + return false; + } + return true; + } + } + + return false; +} + +static int udc_mcux_handler_in(const struct device *dev, uint8_t ep, + uint8_t *mcux_buf, uint16_t mcux_len) +{ + int err; + struct net_buf *buf; + unsigned int key; + + buf = udc_buf_peek(dev, ep); + if (buf == NULL) { + udc_submit_event(dev, UDC_EVT_ERROR, -ENOBUFS); + return -ENOBUFS; + } + + if (udc_mcux_handler_zlt(dev, ep, buf, mcux_len)) { + return 0; + } + + buf = udc_buf_get(dev, ep); + + key = irq_lock(); + udc_ep_set_busy(dev, ep, false); + irq_unlock(key); + + if (buf == NULL) { + udc_submit_event(dev, UDC_EVT_ERROR, -ENOBUFS); + return -ENOBUFS; + } + if (ep == USB_CONTROL_EP_IN) { + err = udc_mcux_handler_ctrl_in(dev, buf, mcux_buf, mcux_len); + } else { + err = udc_mcux_handler_non_ctrl_in(dev, ep, buf, mcux_buf, mcux_len); + } + + return err; +} + +/* NXP MCUX controller driver notify transfers/status through this interface */ +usb_status_t USB_DeviceNotificationTrigger(void *handle, void *msg) +{ + usb_device_callback_message_struct_t *mcux_msg = msg; + uint8_t ep; + usb_device_notification_t mcux_notify; + struct udc_mcux_data *priv; + const struct device *dev; + usb_status_t mcux_status = kStatus_USB_Success; + int err = 0; + + if ((NULL == msg) || (NULL == handle)) { + return kStatus_USB_InvalidHandle; + } + + mcux_notify = (usb_device_notification_t)mcux_msg->code; + priv = (struct udc_mcux_data *)(PRV_DATA_HANDLE(handle)); + dev = priv->dev; + + switch (mcux_notify) { + case kUSB_DeviceNotifyBusReset: + struct udc_ep_config *cfg; + + udc_mcux_control(dev, kUSB_DeviceControlSetDefaultStatus, NULL); + cfg = udc_get_ep_cfg(dev, USB_CONTROL_EP_OUT); + if (cfg->stat.enabled) { + udc_ep_disable_internal(dev, USB_CONTROL_EP_OUT); + } + cfg = udc_get_ep_cfg(dev, USB_CONTROL_EP_IN); + if (cfg->stat.enabled) { + udc_ep_disable_internal(dev, USB_CONTROL_EP_IN); + } + if (udc_ep_enable_internal(dev, USB_CONTROL_EP_OUT, + USB_EP_TYPE_CONTROL, + USB_MCUX_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, + USB_MCUX_EP0_SIZE, 0)) { + LOG_ERR("Failed to enable control endpoint"); + return -EIO; + } + udc_submit_event(dev, UDC_EVT_RESET, 0); + break; + case kUSB_DeviceNotifyError: + udc_submit_event(dev, UDC_EVT_ERROR, -EIO); + break; + case kUSB_DeviceNotifySuspend: + udc_set_suspended(dev, true); + udc_submit_event(dev, UDC_EVT_SUSPEND, 0); + break; + case kUSB_DeviceNotifyResume: + udc_set_suspended(dev, false); + udc_submit_event(dev, UDC_EVT_RESUME, 0); + break; + case kUSB_DeviceNotifyLPMSleep: + break; + case kUSB_DeviceNotifyDetach: + udc_submit_event(dev, UDC_EVT_VBUS_REMOVED, 0); + break; + case kUSB_DeviceNotifyAttach: + udc_submit_event(dev, UDC_EVT_VBUS_READY, 0); + break; + default: + ep = mcux_msg->code; + if (mcux_msg->isSetup) { + struct usb_setup_packet *setup = + (struct usb_setup_packet *)mcux_msg->buffer; + + err = udc_mcux_handler_setup(dev, setup); + } else if (USB_EP_DIR_IS_IN(ep)) { + err = udc_mcux_handler_in(dev, ep, mcux_msg->buffer, mcux_msg->length); + } else { + err = udc_mcux_handler_out(dev, ep, mcux_msg->buffer, mcux_msg->length); + } + + break; + } + + if (unlikely(err)) { + udc_submit_event(dev, UDC_EVT_ERROR, err); + mcux_status = kStatus_USB_Error; + } + return mcux_status; +} + +static void udc_mcux_isr(const struct device *dev) +{ + struct udc_mcux_data *priv = udc_get_private(dev); + + USB_DeviceLpcIp3511IsrFunction((void *)(&priv->mcux_device)); +} + +/* Return actual USB device speed */ +static enum udc_bus_speed udc_mcux_device_speed(const struct device *dev) +{ + int err; + uint8_t mcux_speed; + + err = udc_mcux_control(dev, kUSB_DeviceControlGetSpeed, &mcux_speed); + if (err) { + /* + * In the current version of all NXP USB device drivers, + * no error is returned if the parameter is correct. + */ + return UDC_BUS_SPEED_FS; + } + + switch (mcux_speed) { + case USB_SPEED_HIGH: + return UDC_BUS_SPEED_HS; + case USB_SPEED_LOW: + __ASSERT(false, "Low speed mode not supported"); + __fallthrough; + case USB_SPEED_FULL: + __fallthrough; + default: + return UDC_BUS_SPEED_FS; + } +} + +static int udc_mcux_ep_enqueue(const struct device *dev, + struct udc_ep_config *const cfg, + struct net_buf *const buf) +{ + udc_buf_put(cfg, buf); + if (cfg->stat.halted) { + LOG_DBG("ep 0x%02x halted", cfg->addr); + return 0; + } + + return udc_mcux_ep_try_feed(dev, cfg); +} + +static int udc_mcux_ep_dequeue(const struct device *dev, + struct udc_ep_config *const cfg) +{ + struct net_buf *buf; + unsigned int key; + + cfg->stat.halted = false; + buf = udc_buf_get_all(dev, cfg->addr); + if (buf) { + udc_submit_ep_event(dev, buf, -ECONNABORTED); + } + + key = irq_lock(); + udc_ep_set_busy(dev, cfg->addr, false); + irq_unlock(key); + + return 0; +} + +static int udc_mcux_ep_set_halt(const struct device *dev, + struct udc_ep_config *const cfg) +{ + return udc_mcux_control(dev, kUSB_DeviceControlEndpointStall, &cfg->addr); +} + +static int udc_mcux_ep_clear_halt(const struct device *dev, + struct udc_ep_config *const cfg) +{ + (void)udc_mcux_control(dev, kUSB_DeviceControlEndpointUnstall, &cfg->addr); + /* transfer is enqueued after stalled */ + return udc_mcux_ep_try_feed(dev, cfg); +} + +static int udc_mcux_ep_enable(const struct device *dev, + struct udc_ep_config *const cfg) +{ + usb_device_endpoint_init_struct_t ep_init; + + LOG_DBG("Enable ep 0x%02x", cfg->addr); + + ep_init.zlt = 0U; + ep_init.interval = cfg->interval; + ep_init.endpointAddress = cfg->addr; + ep_init.maxPacketSize = cfg->mps; + + switch (cfg->attributes & USB_EP_TRANSFER_TYPE_MASK) { + case USB_EP_TYPE_CONTROL: + ep_init.transferType = USB_ENDPOINT_CONTROL; + break; + case USB_EP_TYPE_BULK: + ep_init.transferType = USB_ENDPOINT_BULK; + break; + case USB_EP_TYPE_INTERRUPT: + ep_init.transferType = USB_ENDPOINT_INTERRUPT; + break; + case USB_EP_TYPE_ISO: + ep_init.transferType = USB_ENDPOINT_ISOCHRONOUS; + break; + default: + return -EINVAL; + } + + return udc_mcux_control(dev, kUSB_DeviceControlEndpointInit, &ep_init); +} + +static int udc_mcux_ep_disable(const struct device *dev, + struct udc_ep_config *const cfg) +{ + LOG_DBG("Disable ep 0x%02x", cfg->addr); + + return udc_mcux_control(dev, kUSB_DeviceControlEndpointDeinit, &cfg->addr); +} + +static int udc_mcux_host_wakeup(const struct device *dev) +{ + return -ENOTSUP; +} + +static int udc_mcux_set_address(const struct device *dev, const uint8_t addr) +{ + uint8_t temp_addr = addr; + + return udc_mcux_control(dev, kUSB_DeviceControlSetDeviceAddress, &temp_addr); +} + +static int udc_mcux_enable(const struct device *dev) +{ + return udc_mcux_control(dev, kUSB_DeviceControlRun, NULL); +} + +static int udc_mcux_disable(const struct device *dev) +{ + return udc_mcux_control(dev, kUSB_DeviceControlStop, NULL); +} + +static int udc_mcux_init(const struct device *dev) +{ + const struct udc_mcux_config *config = dev->config; + const usb_device_controller_interface_struct_t *mcux_if = config->mcux_if; + struct udc_mcux_data *priv = udc_get_private(dev); + usb_status_t status; + + if (priv->controller_id == 0xFFu) { + return -ENOMEM; + } + +#ifdef CONFIG_DT_HAS_NXP_USBPHY_ENABLED + if (config->phy_config != NULL) { + USB_EhciPhyInit(priv->controller_id, 0u, + (usb_phy_config_struct_t *)&config->phy_config); + } +#endif + + /* Init MCUX USB device driver. */ + status = mcux_if->deviceInit(priv->controller_id, + &priv->mcux_device, &(priv->mcux_device.controllerHandle)); + if (status != kStatus_USB_Success) { + return -ENOMEM; + } + + /* enable USB interrupt */ + config->irq_enable_func(dev); + + LOG_DBG("Initialized USB controller %x", (uint32_t)config->base); + + return 0; +} + +static int udc_mcux_shutdown(const struct device *dev) +{ + const struct udc_mcux_config *config = dev->config; + const usb_device_controller_interface_struct_t *mcux_if = config->mcux_if; + struct udc_mcux_data *priv = udc_get_private(dev); + usb_status_t status; + + /* Disable interrupt */ + config->irq_disable_func(dev); + + /* De-init MCUX USB device driver. */ + status = mcux_if->deviceDeinit(priv->mcux_device.controllerHandle); + if (status != kStatus_USB_Success) { + return -ENOMEM; + } + + return 0; +} + +static int udc_mcux_lock(const struct device *dev) +{ + return udc_lock_internal(dev, K_FOREVER); +} + +static int udc_mcux_unlock(const struct device *dev) +{ + return udc_unlock_internal(dev); +} + +static inline void udc_mcux_get_hal_driver_id(struct udc_mcux_data *priv, + const struct udc_mcux_config *config) +{ + /* + * MCUX USB controller drivers use an ID to tell the HAL drivers + * which controller is being used. This part of the code converts + * the base address to the ID value. + */ +#ifdef USB_BASE_ADDRS + uintptr_t ip3511_fs_base[] = USB_BASE_ADDRS; +#endif +#ifdef USBHSD_BASE_ADDRS + uintptr_t ip3511_hs_base[] = USBHSD_BASE_ADDRS; +#endif + + /* get the right controller id */ + priv->controller_id = 0xFFu; /* invalid value */ +#ifdef USB_BASE_ADDRS + for (uint8_t i = 0; i < ARRAY_SIZE(ip3511_fs_base); i++) { + if (ip3511_fs_base[i] == config->base) { + priv->controller_id = kUSB_ControllerLpcIp3511Fs0 + i; + break; + } + } +#endif + +#ifdef USBHSD_BASE_ADDRS + if (priv->controller_id == 0xFF) { + for (uint8_t i = 0; i < ARRAY_SIZE(ip3511_hs_base); i++) { + if (ip3511_hs_base[i] == config->base) { + priv->controller_id = kUSB_ControllerLpcIp3511Hs0 + i; + break; + } + } + } +#endif +} + +static int udc_mcux_driver_preinit(const struct device *dev) +{ + const struct udc_mcux_config *config = dev->config; + struct udc_data *data = dev->data; + struct udc_mcux_data *priv = data->priv; + int err; + + udc_mcux_get_hal_driver_id(priv, config); + if (priv->controller_id == 0xFFu) { + return -ENOMEM; + } + + k_mutex_init(&data->mutex); + + for (int i = 0; i < config->num_of_eps; i++) { + config->ep_cfg_out[i].caps.out = 1; + if (i == 0) { + config->ep_cfg_out[i].caps.control = 1; + config->ep_cfg_out[i].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 = 1024; + } + + config->ep_cfg_out[i].addr = USB_EP_DIR_OUT | i; + err = udc_register_ep(dev, &config->ep_cfg_out[i]); + if (err != 0) { + LOG_ERR("Failed to register endpoint"); + return err; + } + } + + for (int i = 0; i < config->num_of_eps; i++) { + config->ep_cfg_in[i].caps.in = 1; + if (i == 0) { + config->ep_cfg_in[i].caps.control = 1; + config->ep_cfg_in[i].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 = 1024; + } + + config->ep_cfg_in[i].addr = USB_EP_DIR_IN | i; + err = udc_register_ep(dev, &config->ep_cfg_in[i]); + if (err != 0) { + LOG_ERR("Failed to register endpoint"); + return err; + } + } + + /* Requires udc_mcux_host_wakeup() implementation */ + data->caps.rwup = false; + data->caps.mps0 = USB_MCUX_MPS0; + if ((priv->controller_id == kUSB_ControllerLpcIp3511Hs0) || + (priv->controller_id == kUSB_ControllerLpcIp3511Hs1)) { + data->caps.hs = true; + } + priv->dev = dev; + + pinctrl_apply_state(config->pincfg, PINCTRL_STATE_DEFAULT); + + return 0; +} + +static const struct udc_api udc_mcux_api = { + .device_speed = udc_mcux_device_speed, + .ep_enqueue = udc_mcux_ep_enqueue, + .ep_dequeue = udc_mcux_ep_dequeue, + .ep_set_halt = udc_mcux_ep_set_halt, + .ep_clear_halt = udc_mcux_ep_clear_halt, + .ep_try_config = NULL, + .ep_enable = udc_mcux_ep_enable, + .ep_disable = udc_mcux_ep_disable, + .host_wakeup = udc_mcux_host_wakeup, + .set_address = udc_mcux_set_address, + .enable = udc_mcux_enable, + .disable = udc_mcux_disable, + .init = udc_mcux_init, + .shutdown = udc_mcux_shutdown, + .lock = udc_mcux_lock, + .unlock = udc_mcux_unlock, +}; + +/* IP3511 device driver interface */ +static const usb_device_controller_interface_struct_t udc_mcux_if = { + USB_DeviceLpc3511IpInit, USB_DeviceLpc3511IpDeinit, USB_DeviceLpc3511IpSend, + USB_DeviceLpc3511IpRecv, USB_DeviceLpc3511IpCancel, USB_DeviceLpc3511IpControl +}; + +#ifdef CONFIG_DT_HAS_NXP_USBPHY_ENABLED +#define UDC_MCUX_PHY_DEFINE(n) \ +static usb_phy_config_struct_t phy_config_##n = { \ + .D_CAL = DT_PROP_OR(DT_INST_PHANDLE(n, phy_handle), tx_d_cal, 0), \ + .TXCAL45DP = DT_PROP_OR(DT_INST_PHANDLE(n, phy_handle), tx_cal_45_dp_ohms, 0), \ + .TXCAL45DM = DT_PROP_OR(DT_INST_PHANDLE(n, phy_handle), tx_cal_45_dm_ohms, 0), \ +} + +#define UDC_MCUX_PHY_DEFINE_OR(n) \ + COND_CODE_1(DT_NODE_HAS_PROP(DT_DRV_INST(n), phy_handle), \ + (UDC_MCUX_PHY_DEFINE(n)), ()) + +#define UDC_MCUX_PHY_CFG_PTR_OR_NULL(n) \ + .phy_config = COND_CODE_1(DT_NODE_HAS_PROP(DT_DRV_INST(n), phy_handle), \ + (&phy_config_##n), (NULL)) +#else +#define UDC_MCUX_PHY_DEFINE_OR(n) +#define UDC_MCUX_PHY_CFG_PTR_OR_NULL(n) +#endif + +#define USB_MCUX_IP3511_DEVICE_DEFINE(n) \ + UDC_MCUX_PHY_DEFINE_OR(n); \ + \ + static void udc_irq_enable_func##n(const struct device *dev) \ + { \ + IRQ_CONNECT(DT_INST_IRQN(n), \ + DT_INST_IRQ(n, priority), \ + udc_mcux_isr, \ + DEVICE_DT_INST_GET(n), 0); \ + \ + irq_enable(DT_INST_IRQN(n)); \ + } \ + \ + static void udc_irq_disable_func##n(const struct device *dev) \ + { \ + irq_disable(DT_INST_IRQN(n)); \ + } \ + \ + static struct udc_ep_config \ + ep_cfg_out##n[DT_INST_PROP(n, num_bidir_endpoints)]; \ + static struct udc_ep_config \ + ep_cfg_in##n[DT_INST_PROP(n, num_bidir_endpoints)]; \ + \ + PINCTRL_DT_INST_DEFINE(n); \ + \ + static struct udc_mcux_config priv_config_##n = { \ + .base = DT_INST_REG_ADDR(n), \ + .irq_enable_func = udc_irq_enable_func##n, \ + .irq_disable_func = udc_irq_disable_func##n, \ + .num_of_eps = DT_INST_PROP(n, num_bidir_endpoints), \ + .ep_cfg_in = ep_cfg_in##n, \ + .ep_cfg_out = ep_cfg_out##n, \ + .mcux_if = &udc_mcux_if, \ + .pincfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n), \ + UDC_MCUX_PHY_CFG_PTR_OR_NULL(n), \ + }; \ + \ + static struct udc_mcux_data priv_data_##n = { \ + }; \ + \ + static struct udc_data udc_data_##n = { \ + .mutex = Z_MUTEX_INITIALIZER(udc_data_##n.mutex), \ + .priv = &priv_data_##n, \ + }; \ + \ + DEVICE_DT_INST_DEFINE(n, udc_mcux_driver_preinit, NULL, \ + &udc_data_##n, &priv_config_##n, \ + POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEVICE, \ + &udc_mcux_api); + +DT_INST_FOREACH_STATUS_OKAY(USB_MCUX_IP3511_DEVICE_DEFINE) diff --git a/modules/hal_nxp/CMakeLists.txt b/modules/hal_nxp/CMakeLists.txt index 7ae7ff304ae4c..98075e4b1e6b8 100644 --- a/modules/hal_nxp/CMakeLists.txt +++ b/modules/hal_nxp/CMakeLists.txt @@ -1,5 +1,6 @@ # # Copyright (c) 2021 Linaro, Limited +# Copyright 2024 NXP # # SPDX-License-Identifier: Apache-2.0 # @@ -7,6 +8,7 @@ if(CONFIG_HAS_MCUX OR CONFIG_HAS_IMX_HAL OR CONFIG_HAS_NXP_S32_HAL) add_subdirectory(${ZEPHYR_CURRENT_MODULE_DIR} hal_nxp) add_subdirectory_ifdef(CONFIG_USB_DEVICE_DRIVER usb) + add_subdirectory_ifdef(CONFIG_UDC_DRIVER usb) zephyr_sources_ifdef(CONFIG_PWM_MCUX_CTIMER ${ZEPHYR_CURRENT_MODULE_DIR}/mcux/mcux-sdk/drivers/ctimer/fsl_ctimer.c) zephyr_include_directories_ifdef(CONFIG_PWM_MCUX_CTIMER @@ -22,6 +24,7 @@ if(CONFIG_HAS_MCUX OR CONFIG_HAS_IMX_HAL OR CONFIG_HAS_NXP_S32_HAL) if(CONFIG_NOCACHE_MEMORY) zephyr_compile_definitions_ifdef(CONFIG_USB_DEVICE_DRIVER DATA_SECTION_IS_CACHEABLE=1) + zephyr_compile_definitions_ifdef(CONFIG_UDC_DRIVER DATA_SECTION_IS_CACHEABLE=1) endif() add_subdirectory_ifdef(CONFIG_BT_H4_NXP_CTLR bt_controller) diff --git a/modules/hal_nxp/usb/CMakeLists.txt b/modules/hal_nxp/usb/CMakeLists.txt index 380aa3aef87af..da427e3601b8c 100644 --- a/modules/hal_nxp/usb/CMakeLists.txt +++ b/modules/hal_nxp/usb/CMakeLists.txt @@ -1,6 +1,9 @@ # -# Copyright (c) 2021, NXP +# Copyright (c) 2021,2024 NXP # # SPDX-License-Identifier: Apache-2.0 # zephyr_include_directories(.) +if(CONFIG_DT_HAS_NXP_USBPHY_ENABLED) +zephyr_include_directories(${ZEPHYR_HAL_NXP_MODULE_DIR}/mcux/middleware/mcux-sdk-middleware-usb/phy) +endif() diff --git a/modules/hal_nxp/usb/usb_device_config.h b/modules/hal_nxp/usb/usb_device_config.h index 31a62ffbfebc5..a97d9181c1b11 100644 --- a/modules/hal_nxp/usb/usb_device_config.h +++ b/modules/hal_nxp/usb/usb_device_config.h @@ -13,6 +13,7 @@ /****************************************************************************** * Definitions *****************************************************************************/ +#ifdef CONFIG_USB_DEVICE_DRIVER /* EHCI instance count */ #ifdef CONFIG_USB_DC_NXP_EHCI #define USB_DEVICE_CONFIG_EHCI (1U) @@ -51,5 +52,57 @@ BUILD_ASSERT(NUM_INSTS <= 1, "Only one USB device supported"); /* Number of endpoints supported */ #define USB_DEVICE_CONFIG_ENDPOINTS (DT_INST_PROP(0, num_bidir_endpoints)) +#else + +#ifdef CONFIG_UDC_NXP_EHCI +#define USB_DEVICE_CONFIG_EHCI (DT_NUM_INST_STATUS_OKAY(nxp_ehci)) +#endif + +#ifdef CONFIG_UDC_NXP_IP3511 + +#if defined(USBHSD_BASE_ADDRS) && defined(USB_BASE_ADDRS) +#define USB_DEVICE_CONFIG_LPCIP3511HS (1U) +#define USB_DEVICE_CONFIG_LPCIP3511FS (1U) + +#else + +#ifdef USBHSD_BASE_ADDRS +#define USB_DEVICE_CONFIG_LPCIP3511HS (DT_NUM_INST_STATUS_OKAY(nxp_lpcip3511)) +#else +#define USB_DEVICE_CONFIG_LPCIP3511HS (0U) +#endif + +#ifdef USB_BASE_ADDRS +#define USB_DEVICE_CONFIG_LPCIP3511FS (DT_NUM_INST_STATUS_OKAY(nxp_lpcip3511)) +#else +#define USB_DEVICE_CONFIG_LPCIP3511FS (0U) +#endif + +#endif +#endif + +/* calculte the num of endponts. + * mcux ip3511 driver doesn't use USB_DEVICE_CONFIG_ENDPOINTS, + * so use ehci endpoint number if ehci is enabled. + */ +#if DT_HAS_COMPAT_STATUS_OKAY(nxp_ehci) +#undef DT_DRV_COMPAT +#define DT_DRV_COMPAT nxp_ehci +#elif DT_HAS_COMPAT_STATUS_OKAY(nxp_lpcip3511) +#undef DT_DRV_COMPAT +#define DT_DRV_COMPAT nxp_lpcip3511 +#endif + +/* Number of endpoints supported */ +#define USB_DEVICE_CONFIG_ENDPOINTS (DT_INST_PROP(0, num_bidir_endpoints)) + +#define USB_DEVICE_CONFIG_SELF_POWER (1U) + +#if ((defined(USB_DEVICE_CONFIG_EHCI)) && (USB_DEVICE_CONFIG_EHCI > 0U)) +/*! @brief How many the DTD are supported. */ +#define USB_DEVICE_CONFIG_EHCI_MAX_DTD (16U) +#endif + +#endif #endif /* __USB_DEVICE_CONFIG_H__ */ From 0c70a72ac7048376e20cef433335e1ce796b70dd Mon Sep 17 00:00:00 2001 From: Mark Wang Date: Mon, 27 May 2024 15:43:27 +0800 Subject: [PATCH 2597/2849] boards: nxp: enable mcux udc on lpc55s69, rt1060 and rt685 set DT node as Okay in board device tree; add board level's d-cal, txcal45dp and txcal45dm to usbphy node; enable usb clock; set USB_STACK_USE_DEDICATED_RAM for lpc55s69 and rt685; load usb.ld for lpc55s69 and rt685. Signed-off-by: Mark Wang --- .../lpcxpresso55s69/lpcxpresso55s69_lpc55s69_cpu0.dts | 8 ++++++++ boards/nxp/mimxrt1060_evk/mimxrt1060_evk.dts | 8 ++++++++ .../mimxrt685_evk/mimxrt685_evk_mimxrt685s_cm33.dts | 8 ++++++++ soc/nxp/imxrt/CMakeLists.txt | 1 + soc/nxp/imxrt/imxrt10xx/soc.c | 10 ++++++++-- soc/nxp/imxrt/imxrt6xx/cm33/CMakeLists.txt | 1 + soc/nxp/imxrt/imxrt6xx/cm33/soc.c | 8 ++++---- soc/nxp/lpc/lpc55xxx/CMakeLists.txt | 3 +++ soc/nxp/lpc/lpc55xxx/soc.c | 6 ++++-- 9 files changed, 45 insertions(+), 8 deletions(-) diff --git a/boards/nxp/lpcxpresso55s69/lpcxpresso55s69_lpc55s69_cpu0.dts b/boards/nxp/lpcxpresso55s69/lpcxpresso55s69_lpc55s69_cpu0.dts index 1b0004464b05b..9c6f9b837cc3c 100644 --- a/boards/nxp/lpcxpresso55s69/lpcxpresso55s69_lpc55s69_cpu0.dts +++ b/boards/nxp/lpcxpresso55s69/lpcxpresso55s69_lpc55s69_cpu0.dts @@ -149,6 +149,14 @@ zephyr_udc0: &usbhs { status = "okay"; + phy_handle = <&usbphy1>; +}; + +&usbphy1 { + status = "okay"; + tx-d-cal = <5>; + tx-cal-45-dp-ohms = <10>; + tx-cal-45-dm-ohms = <10>; }; &ctimer0 { diff --git a/boards/nxp/mimxrt1060_evk/mimxrt1060_evk.dts b/boards/nxp/mimxrt1060_evk/mimxrt1060_evk.dts index 92fa9d6d180e5..47f4901a22389 100644 --- a/boards/nxp/mimxrt1060_evk/mimxrt1060_evk.dts +++ b/boards/nxp/mimxrt1060_evk/mimxrt1060_evk.dts @@ -183,6 +183,14 @@ arduino_i2c: &lpi2c1 { zephyr_udc0: &usb1 { status = "okay"; + phy_handle = <&usbphy1>; +}; + +&usbphy1 { + status = "okay"; + tx-d-cal = <12>; + tx-cal-45-dp-ohms = <6>; + tx-cal-45-dm-ohms = <6>; }; &flexpwm2_pwm3 { diff --git a/boards/nxp/mimxrt685_evk/mimxrt685_evk_mimxrt685s_cm33.dts b/boards/nxp/mimxrt685_evk/mimxrt685_evk_mimxrt685s_cm33.dts index 3464ef6f10a6c..7c7f9bd03b8d1 100644 --- a/boards/nxp/mimxrt685_evk/mimxrt685_evk_mimxrt685s_cm33.dts +++ b/boards/nxp/mimxrt685_evk/mimxrt685_evk_mimxrt685s_cm33.dts @@ -355,6 +355,14 @@ i2s1: &flexcomm3 { zephyr_udc0: &usbhs { status = "okay"; + phy_handle = <&usbphy>; +}; + +&usbphy { + status = "okay"; + tx-d-cal = <12>; + tx-cal-45-dp-ohms = <6>; + tx-cal-45-dm-ohms = <6>; }; &ctimer0 { diff --git a/soc/nxp/imxrt/CMakeLists.txt b/soc/nxp/imxrt/CMakeLists.txt index b42829869e4f6..371938f7543cd 100644 --- a/soc/nxp/imxrt/CMakeLists.txt +++ b/soc/nxp/imxrt/CMakeLists.txt @@ -39,6 +39,7 @@ endif() if(CONFIG_SOC_SERIES_IMXRT6XX OR CONFIG_SOC_SERIES_IMXRT5XX) zephyr_linker_sources_ifdef(CONFIG_USB_DEVICE_DRIVER SECTIONS usb.ld) + zephyr_linker_sources_ifdef(CONFIG_UDC_DRIVER SECTIONS usb.ld) endif() if(CONFIG_MEMC) diff --git a/soc/nxp/imxrt/imxrt10xx/soc.c b/soc/nxp/imxrt/imxrt10xx/soc.c index 789f02099beca..edc5d38f01e87 100644 --- a/soc/nxp/imxrt/imxrt10xx/soc.c +++ b/soc/nxp/imxrt/imxrt10xx/soc.c @@ -243,21 +243,27 @@ static ALWAYS_INLINE void clock_init(void) kIOMUXC_GPR_ENET2RefClkMode, true); #endif -#if DT_NODE_HAS_STATUS(DT_NODELABEL(usb1), okay) && CONFIG_USB_DC_NXP_EHCI +#if DT_NODE_HAS_STATUS(DT_NODELABEL(usb1), okay) && \ + (CONFIG_USB_DC_NXP_EHCI || CONFIG_UDC_NXP_EHCI) CLOCK_EnableUsbhs0PhyPllClock(kCLOCK_Usb480M, DT_PROP_BY_PHANDLE(DT_NODELABEL(usb1), clocks, clock_frequency)); CLOCK_EnableUsbhs0Clock(kCLOCK_Usb480M, DT_PROP_BY_PHANDLE(DT_NODELABEL(usb1), clocks, clock_frequency)); +#if DT_NODE_HAS_STATUS(DT_NODELABEL(usb1), okay) && CONFIG_USB_DC_NXP_EHCI USB_EhciPhyInit(kUSB_ControllerEhci0, CPU_XTAL_CLK_HZ, &usbPhyConfig); #endif +#endif -#if DT_NODE_HAS_STATUS(DT_NODELABEL(usb2), okay) && CONFIG_USB_DC_NXP_EHCI +#if DT_NODE_HAS_STATUS(DT_NODELABEL(usb2), okay) && \ + (CONFIG_USB_DC_NXP_EHCI || CONFIG_UDC_NXP_EHCI) CLOCK_EnableUsbhs1PhyPllClock(kCLOCK_Usb480M, DT_PROP_BY_PHANDLE(DT_NODELABEL(usb2), clocks, clock_frequency)); CLOCK_EnableUsbhs1Clock(kCLOCK_Usb480M, DT_PROP_BY_PHANDLE(DT_NODELABEL(usb2), clocks, clock_frequency)); +#if DT_NODE_HAS_STATUS(DT_NODELABEL(usb1), okay) && CONFIG_USB_DC_NXP_EHCI USB_EhciPhyInit(kUSB_ControllerEhci1, CPU_XTAL_CLK_HZ, &usbPhyConfig); #endif +#endif #if DT_NODE_HAS_STATUS(DT_NODELABEL(usdhc1), okay) && CONFIG_IMX_USDHC /* Configure USDHC clock source and divider */ diff --git a/soc/nxp/imxrt/imxrt6xx/cm33/CMakeLists.txt b/soc/nxp/imxrt/imxrt6xx/cm33/CMakeLists.txt index 7ed2c42c708c0..8ea9e211c2b9b 100644 --- a/soc/nxp/imxrt/imxrt6xx/cm33/CMakeLists.txt +++ b/soc/nxp/imxrt/imxrt6xx/cm33/CMakeLists.txt @@ -18,6 +18,7 @@ zephyr_library_include_directories( ) zephyr_compile_definitions_ifdef(CONFIG_USB_DEVICE_DRIVER USB_STACK_USE_DEDICATED_RAM=1) +zephyr_compile_definitions_ifdef(CONFIG_UDC_DRIVER USB_STACK_USE_DEDICATED_RAM=1) if(CONFIG_FLASH_MCUX_FLEXSPI_XIP) zephyr_code_relocate(FILES flash_clock_setup.c LOCATION RAM) diff --git a/soc/nxp/imxrt/imxrt6xx/cm33/soc.c b/soc/nxp/imxrt/imxrt6xx/cm33/soc.c index bb6ea26ac45b7..d31929947f44f 100644 --- a/soc/nxp/imxrt/imxrt6xx/cm33/soc.c +++ b/soc/nxp/imxrt/imxrt6xx/cm33/soc.c @@ -30,7 +30,7 @@ #include "flash_clock_setup.h" #endif -#if CONFIG_USB_DC_NXP_LPCIP3511 +#if CONFIG_USB_DC_NXP_LPCIP3511 || CONFIG_UDC_NXP_IP3511 #include "usb_phy.h" #include "usb.h" #endif @@ -68,7 +68,7 @@ const clock_audio_pll_config_t g_audioPllConfig = { }; #endif -#if CONFIG_USB_DC_NXP_LPCIP3511 +#if CONFIG_USB_DC_NXP_LPCIP3511 || CONFIG_UDC_NXP_IP3511 /* USB PHY condfiguration */ #define BOARD_USB_PHY_D_CAL (0x0CU) #define BOARD_USB_PHY_TXCAL45DP (0x06U) @@ -124,7 +124,7 @@ __imx_boot_ivt_section void (* const image_vector_table[])(void) = { }; #endif /* CONFIG_NXP_IMXRT_BOOT_HEADER */ -#if CONFIG_USB_DC_NXP_LPCIP3511 +#if CONFIG_USB_DC_NXP_LPCIP3511 || CONFIG_UDC_NXP_IP3511 static void usb_device_clock_init(void) { @@ -244,7 +244,7 @@ static ALWAYS_INLINE void clock_init(void) CLOCK_AttachClk(kSFRO_to_FLEXCOMM0); #endif -#if CONFIG_USB_DC_NXP_LPCIP3511 +#if CONFIG_USB_DC_NXP_LPCIP3511 || CONFIG_UDC_NXP_IP3511 usb_device_clock_init(); #endif diff --git a/soc/nxp/lpc/lpc55xxx/CMakeLists.txt b/soc/nxp/lpc/lpc55xxx/CMakeLists.txt index 429e41722f715..4dae5afa7eee5 100644 --- a/soc/nxp/lpc/lpc55xxx/CMakeLists.txt +++ b/soc/nxp/lpc/lpc55xxx/CMakeLists.txt @@ -14,8 +14,11 @@ zephyr_library_include_directories( if(DEFINED CONFIG_LPC55XXX_USB_RAM) zephyr_linker_sources_ifdef(CONFIG_USB_DEVICE_DRIVER SECTIONS usb.ld) + zephyr_linker_sources_ifdef(CONFIG_UDC_DRIVER + SECTIONS usb.ld) zephyr_compile_definitions_ifdef(CONFIG_USB_DEVICE_DRIVER USB_STACK_USE_DEDICATED_RAM=1) +zephyr_compile_definitions_ifdef(CONFIG_UDC_DRIVER USB_STACK_USE_DEDICATED_RAM=1) endif() # CMSIS SystemInit allows us to skip enabling clock to SRAM banks via diff --git a/soc/nxp/lpc/lpc55xxx/soc.c b/soc/nxp/lpc/lpc55xxx/soc.c index 5072fd8266b54..1dad08a3a0bfd 100644 --- a/soc/nxp/lpc/lpc55xxx/soc.c +++ b/soc/nxp/lpc/lpc55xxx/soc.c @@ -26,7 +26,7 @@ #ifdef CONFIG_GPIO_MCUX_LPC #include #endif -#if CONFIG_USB_DC_NXP_LPCIP3511 +#if CONFIG_USB_DC_NXP_LPCIP3511 || CONFIG_UDC_NXP_IP3511 #include "usb_phy.h" #include "usb.h" #endif @@ -207,7 +207,7 @@ static ALWAYS_INLINE void clock_init(void) CLOCK_EnableClock(kCLOCK_Mailbox); #endif -#if CONFIG_USB_DC_NXP_LPCIP3511 +#if CONFIG_USB_DC_NXP_LPCIP3511 || CONFIG_UDC_NXP_IP3511 #if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(usbfs), nxp_lpcip3511, okay) /*< Turn on USB Phy */ @@ -256,7 +256,9 @@ static ALWAYS_INLINE void clock_init(void) /* enable USB IP clock */ CLOCK_EnableUsbhs0PhyPllClock(kCLOCK_UsbPhySrcExt, CLK_CLK_IN); CLOCK_EnableUsbhs0DeviceClock(kCLOCK_UsbSrcUnused, 0U); +#if CONFIG_USB_DC_NXP_LPCIP3511 USB_EhciPhyInit(kUSB_ControllerLpcIp3511Hs0, CLK_CLK_IN, NULL); +#endif #if defined(FSL_FEATURE_USBHSD_USB_RAM) && (FSL_FEATURE_USBHSD_USB_RAM) memset((uint8_t *)FSL_FEATURE_USBHSD_USB_RAM_BASE_ADDRESS, 0, FSL_FEATURE_USBHSD_USB_RAM); #endif From 1fabbe01f55e2c0ef886ff6ba37f668160036b2e Mon Sep 17 00:00:00 2001 From: Mark Wang Date: Mon, 27 May 2024 15:46:10 +0800 Subject: [PATCH 2598/2849] samples: usb: enable next usb device stack samples on NXP platforms enable next usb device stack samples (cdc_acm, mass and shell) on rt685 and mimxrt1060_evk Signed-off-by: Mark Wang --- samples/subsys/usb/cdc_acm/sample.yaml | 2 ++ samples/subsys/usb/mass/sample.yaml | 2 ++ samples/subsys/usb/shell/sample.yaml | 2 ++ 3 files changed, 6 insertions(+) diff --git a/samples/subsys/usb/cdc_acm/sample.yaml b/samples/subsys/usb/cdc_acm/sample.yaml index 78d02840b8500..c5d616377ce9f 100644 --- a/samples/subsys/usb/cdc_acm/sample.yaml +++ b/samples/subsys/usb/cdc_acm/sample.yaml @@ -19,6 +19,8 @@ tests: - nrf54h20dk/nrf54h20/cpuapp - frdm_k64f - 96b_carbon/stm32f401xe + - mimxrt685_evk/mimxrt685s/cm33 + - mimxrt1060_evk harness: console harness_config: type: one_line diff --git a/samples/subsys/usb/mass/sample.yaml b/samples/subsys/usb/mass/sample.yaml index dca20363d8991..8749a0892a33b 100644 --- a/samples/subsys/usb/mass/sample.yaml +++ b/samples/subsys/usb/mass/sample.yaml @@ -26,6 +26,8 @@ tests: - nrf52840dk/nrf52840 - nrf54h20dk/nrf54h20/cpuapp - frdm_k64f + - mimxrt685_evk/mimxrt685s/cm33 + - mimxrt1060_evk extra_args: - CONF_FILE="usbd_next_prj.conf" - EXTRA_DTC_OVERLAY_FILE="ramdisk.overlay" diff --git a/samples/subsys/usb/shell/sample.yaml b/samples/subsys/usb/shell/sample.yaml index e2525238da25f..c3c88d002f27c 100644 --- a/samples/subsys/usb/shell/sample.yaml +++ b/samples/subsys/usb/shell/sample.yaml @@ -9,6 +9,8 @@ tests: - nrf52840dk/nrf52840 - nrf54h20dk/nrf54h20/cpuapp - frdm_k64f + - mimxrt685_evk/mimxrt685s/cm33 + - mimxrt1060_evk harness: keyboard tags: usb sample.usbh.shell: From a568acbfeaeb6f18a956d8cfc0c30173d10adc1a Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Tue, 11 Jun 2024 14:41:45 +0200 Subject: [PATCH 2599/2849] Bluetooth: Controller: Fix regression due to use of TMR_START_DELAY_US Fix regression due to use of HAL_RADIO_TMR_START_DELAY_US introduced in commit 11bae5cfa95b ("Bluetooth: Controller: Fix missing radio timer comp and range delay"). Signed-off-by: Vinayak Kariappa Chettimada --- subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 f5ecc263cb1c4..b7061d9718770 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 @@ -904,7 +904,7 @@ void sw_switch(uint8_t dir_curr, uint8_t dir_next, uint8_t phy_curr, uint8_t fla if (delay < SW_SWITCH_TIMER->CC[cc]) { nrf_timer_cc_set(SW_SWITCH_TIMER, cc, - (SW_SWITCH_TIMER->CC[cc] - delay - HAL_RADIO_TMR_START_DELAY_US)); + (SW_SWITCH_TIMER->CC[cc] - delay)); } else { nrf_timer_cc_set(SW_SWITCH_TIMER, cc, 1); } From 6d5edf9255ae97c06b5bf6c9766b3a34f7229891 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mo=C5=84?= Date: Thu, 13 Jun 2024 11:14:40 +0200 Subject: [PATCH 2600/2849] tests: usb: fix build all test on qemu_cortex_m3 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reduce RAM disk size from 192 sectors down to 1 sector to solve linking issue due to qemu_cortex_m3 target having too little RAM. The RAM disk size does not really matter in this test case and should be as small as possible. Enable test random generator to solve missing sys_rand_get() required by networking subsystem. Signed-off-by: Tomasz Moń --- tests/subsys/usb/device_next/build_all.conf | 2 ++ tests/subsys/usb/device_next/build_all.overlay | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/subsys/usb/device_next/build_all.conf b/tests/subsys/usb/device_next/build_all.conf index 1b49631bbb687..709594bc5462e 100644 --- a/tests/subsys/usb/device_next/build_all.conf +++ b/tests/subsys/usb/device_next/build_all.conf @@ -29,3 +29,5 @@ CONFIG_USBD_BT_HCI=y CONFIG_UHC_DRIVER=y CONFIG_USB_HOST_STACK=y + +CONFIG_TEST_RANDOM_GENERATOR=y diff --git a/tests/subsys/usb/device_next/build_all.overlay b/tests/subsys/usb/device_next/build_all.overlay index 2cd037e82b34e..87c419ced8b11 100644 --- a/tests/subsys/usb/device_next/build_all.overlay +++ b/tests/subsys/usb/device_next/build_all.overlay @@ -48,7 +48,7 @@ compatible = "zephyr,ram-disk"; disk-name = "RAM"; sector-size = <512>; - sector-count = <192>; + sector-count = <1>; }; cdc_ecm_eth0: cdc_ecm_eth0 { From ea361f095c99ebd97c833220cd290164b9b269b0 Mon Sep 17 00:00:00 2001 From: Nikodem Kastelik Date: Wed, 12 Jun 2024 08:48:53 +0200 Subject: [PATCH 2601/2849] boards: nordic: nrf54h20dk: add DMA attribute to RAM21 & RAM3x This attribute denotes that DMA operation can be performed from a given region. Signed-off-by: Nikodem Kastelik --- boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20-memory_map.dtsi | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20-memory_map.dtsi b/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20-memory_map.dtsi index 834448f33e4cc..e7181c4fba98f 100644 --- a/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20-memory_map.dtsi +++ b/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20-memory_map.dtsi @@ -110,7 +110,7 @@ status = "disabled"; #memory-region-cells = <0>; zephyr,memory-region = "DMA_RAM21"; - zephyr,memory-attr = <( DT_MEM_CACHEABLE )>; + zephyr,memory-attr = <( DT_MEM_DMA | DT_MEM_CACHEABLE )>; }; }; @@ -154,6 +154,7 @@ status = "disabled"; #memory-region-cells = <0>; zephyr,memory-region = "DMA_RAM3x_APP"; + zephyr,memory-attr = <( DT_MEM_DMA )>; }; cpurad_dma_region: memory@1e80 { @@ -162,6 +163,7 @@ status = "disabled"; #memory-region-cells = <0>; zephyr,memory-region = "DMA_RAM3x_RAD"; + zephyr,memory-attr = <( DT_MEM_DMA )>; }; }; }; From 37e511bcbf20fc3513324ea84d643b7a7cea127f Mon Sep 17 00:00:00 2001 From: Nikodem Kastelik Date: Tue, 9 Apr 2024 15:51:52 +0200 Subject: [PATCH 2602/2849] soc: nordic: add dmm component DMM stands for Device Memory Management and its role is to streamline the process of allocating DMA buffer in correct memory region and managing the data cache. Signed-off-by: Nikodem Kastelik --- soc/nordic/common/CMakeLists.txt | 4 + soc/nordic/common/Kconfig | 3 + soc/nordic/common/dmm.c | 297 +++++++++++++++++++++++++++++++ soc/nordic/common/dmm.h | 187 +++++++++++++++++++ soc/nordic/nrf54h/Kconfig | 1 + 5 files changed, 492 insertions(+) create mode 100644 soc/nordic/common/dmm.c create mode 100644 soc/nordic/common/dmm.h diff --git a/soc/nordic/common/CMakeLists.txt b/soc/nordic/common/CMakeLists.txt index 805113f53d6dc..abf8b80d3fa18 100644 --- a/soc/nordic/common/CMakeLists.txt +++ b/soc/nordic/common/CMakeLists.txt @@ -9,6 +9,10 @@ zephyr_library_sources_ifdef(CONFIG_POWEROFF poweroff.c) zephyr_include_directories(.) +if(CONFIG_HAS_NORDIC_DMM) + zephyr_library_sources(dmm.c) +endif() + if(CONFIG_TFM_PARTITION_PLATFORM) zephyr_library_sources(soc_secure.c) zephyr_library_include_directories( diff --git a/soc/nordic/common/Kconfig b/soc/nordic/common/Kconfig index 54e2356c6af93..8de20c37dd4d2 100644 --- a/soc/nordic/common/Kconfig +++ b/soc/nordic/common/Kconfig @@ -1,4 +1,7 @@ # Copyright (c) 2024 Nordic Semiconductor ASA # SPDX-License-Identifier: Apache-2.0 +config HAS_NORDIC_DMM + bool + rsource "vpr/Kconfig" diff --git a/soc/nordic/common/dmm.c b/soc/nordic/common/dmm.c new file mode 100644 index 0000000000000..85f18dfa7e8e8 --- /dev/null +++ b/soc/nordic/common/dmm.c @@ -0,0 +1,297 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include "dmm.h" + +#define _FILTER_MEM(node_id, fn) \ + COND_CODE_1(DT_NODE_HAS_PROP(node_id, zephyr_memory_attr), (fn(node_id)), ()) +#define DT_MEMORY_REGION_FOREACH_STATUS_OKAY_NODE(fn) \ + DT_FOREACH_STATUS_OKAY_NODE_VARGS(_FILTER_MEM, fn) + +#define __BUILD_LINKER_END_VAR(_name) DT_CAT3(__, _name, _end) +#define _BUILD_LINKER_END_VAR(node_id) \ + __BUILD_LINKER_END_VAR(DT_STRING_UNQUOTED(node_id, zephyr_memory_region)) + +#define _BUILD_MEM_REGION(node_id) \ + {.dt_addr = DT_REG_ADDR(node_id), \ + .dt_size = DT_REG_SIZE(node_id), \ + .dt_attr = DT_PROP(node_id, zephyr_memory_attr), \ + .dt_allc = &_BUILD_LINKER_END_VAR(node_id)}, + +/* Generate declarations of linker variables used to determine size of preallocated variables + * stored in memory sections spanning over memory regions. + * These are used to determine memory left for dynamic bounce buffer allocator to work with. + */ +#define _DECLARE_LINKER_VARS(node_id) extern uint32_t _BUILD_LINKER_END_VAR(node_id); +DT_MEMORY_REGION_FOREACH_STATUS_OKAY_NODE(_DECLARE_LINKER_VARS); + +struct dmm_region { + uintptr_t dt_addr; + size_t dt_size; + uint32_t dt_attr; + void *dt_allc; +}; + +struct dmm_heap { + struct sys_heap heap; + const struct dmm_region *region; +}; + +static const struct dmm_region dmm_regions[] = { + DT_MEMORY_REGION_FOREACH_STATUS_OKAY_NODE(_BUILD_MEM_REGION) +}; + +struct { + struct dmm_heap dmm_heaps[ARRAY_SIZE(dmm_regions)]; +} dmm_heaps_data; + +static struct dmm_heap *dmm_heap_find(void *region) +{ + struct dmm_heap *dh; + + for (size_t idx = 0; idx < ARRAY_SIZE(dmm_heaps_data.dmm_heaps); idx++) { + dh = &dmm_heaps_data.dmm_heaps[idx]; + if (dh->region->dt_addr == (uintptr_t)region) { + return dh; + } + } + + return NULL; +} + +static bool is_region_cacheable(const struct dmm_region *region) +{ + return (IS_ENABLED(CONFIG_DCACHE) && (region->dt_attr & DT_MEM_CACHEABLE)); +} + +static bool is_buffer_within_region(uintptr_t start, size_t size, + uintptr_t reg_start, size_t reg_size) +{ + return ((start >= reg_start) && ((start + size) <= (reg_start + reg_size))); +} + +static bool is_user_buffer_correctly_preallocated(void const *user_buffer, size_t user_length, + const struct dmm_region *region) +{ + uintptr_t addr = (uintptr_t)user_buffer; + + if (!is_buffer_within_region(addr, user_length, region->dt_addr, region->dt_size)) { + return false; + } + + if (!is_region_cacheable(region)) { + /* Buffer is contained within non-cacheable region - use it as it is. */ + return true; + } + + if (IS_ALIGNED(addr, DMM_DCACHE_LINE_SIZE)) { + /* If buffer is in cacheable region it must be aligned to data cache line size. */ + return true; + } + + return false; +} + +static size_t dmm_heap_start_get(struct dmm_heap *dh) +{ + return ROUND_UP(dh->region->dt_allc, DMM_DCACHE_LINE_SIZE); +} + +static size_t dmm_heap_size_get(struct dmm_heap *dh) +{ + return (dh->region->dt_size - (dmm_heap_start_get(dh) - dh->region->dt_addr)); +} + +static void *dmm_buffer_alloc(struct dmm_heap *dh, size_t length) +{ + length = ROUND_UP(length, DMM_DCACHE_LINE_SIZE); + return sys_heap_aligned_alloc(&dh->heap, DMM_DCACHE_LINE_SIZE, length); +} + +static void dmm_buffer_free(struct dmm_heap *dh, void *buffer) +{ + sys_heap_free(&dh->heap, buffer); +} + +int dmm_buffer_out_prepare(void *region, void const *user_buffer, size_t user_length, + void **buffer_out) +{ + struct dmm_heap *dh; + + if (user_length == 0) { + /* Assume that zero-length buffers are correct as they are. */ + *buffer_out = (void *)user_buffer; + return 0; + } + + /* Get memory region that specified device can perform DMA transfers from */ + dh = dmm_heap_find(region); + if (dh == NULL) { + return -EINVAL; + } + + /* Check if: + * - provided user buffer is already in correct memory region, + * - provided user buffer is aligned and padded to cache line, + * if it is located in cacheable region. + */ + if (is_user_buffer_correctly_preallocated(user_buffer, user_length, dh->region)) { + /* If yes, assign buffer_out to user_buffer*/ + *buffer_out = (void *)user_buffer; + } else { + /* If no: + * - dynamically allocate buffer in correct memory region that respects cache line + * alignment and padding + */ + *buffer_out = dmm_buffer_alloc(dh, user_length); + /* Return error if dynamic allocation fails */ + if (*buffer_out == NULL) { + return -ENOMEM; + } + /* - copy user buffer contents into allocated buffer */ + memcpy(*buffer_out, user_buffer, user_length); + } + + /* Check if device memory region is cacheable + * If yes, writeback all cache lines associated with output buffer + * (either user or allocated) + */ + if (is_region_cacheable(dh->region)) { + sys_cache_data_flush_range(*buffer_out, user_length); + } + /* If no, no action is needed */ + + return 0; +} + +int dmm_buffer_out_release(void *region, void *buffer_out) +{ + struct dmm_heap *dh; + uintptr_t addr = (uintptr_t)buffer_out; + + /* Get memory region that specified device can perform DMA transfers from */ + dh = dmm_heap_find(region); + if (dh == NULL) { + return -EINVAL; + } + + /* Check if output buffer is contained within memory area + * managed by dynamic memory allocator + */ + if (is_buffer_within_region(addr, 0, dmm_heap_start_get(dh), dmm_heap_size_get(dh))) { + /* If yes, free the buffer */ + dmm_buffer_free(dh, buffer_out); + } + /* If no, no action is needed */ + + return 0; +} + +int dmm_buffer_in_prepare(void *region, void *user_buffer, size_t user_length, void **buffer_in) +{ + struct dmm_heap *dh; + + if (user_length == 0) { + /* Assume that zero-length buffers are correct as they are. */ + *buffer_in = (void *)user_buffer; + return 0; + } + + /* Get memory region that specified device can perform DMA transfers to */ + dh = dmm_heap_find(region); + if (dh == NULL) { + return -EINVAL; + } + + /* Check if: + * - provided user buffer is already in correct memory region, + * - provided user buffer is aligned and padded to cache line, + * if it is located in cacheable region. + */ + if (is_user_buffer_correctly_preallocated(user_buffer, user_length, dh->region)) { + /* If yes, assign buffer_in to user_buffer */ + *buffer_in = user_buffer; + } else { + /* If no, dynamically allocate buffer in correct memory region that respects cache + * line alignment and padding + */ + *buffer_in = dmm_buffer_alloc(dh, user_length); + /* Return error if dynamic allocation fails */ + if (*buffer_in == NULL) { + return -ENOMEM; + } + } + + /* Check if device memory region is cacheable + * If yes, invalidate all cache lines associated with input buffer + * (either user or allocated) to clear potential dirty bits. + */ + if (is_region_cacheable(dh->region)) { + sys_cache_data_invd_range(*buffer_in, user_length); + } + /* If no, no action is needed */ + + return 0; +} + +int dmm_buffer_in_release(void *region, void *user_buffer, size_t user_length, void *buffer_in) +{ + struct dmm_heap *dh; + uintptr_t addr = (uintptr_t)buffer_in; + + /* Get memory region that specified device can perform DMA transfers to, using devicetree */ + dh = dmm_heap_find(region); + if (dh == NULL) { + return -EINVAL; + } + + /* Check if device memory region is cacheable + * If yes, invalidate all cache lines associated with input buffer + * (either user or allocated) + */ + if (is_region_cacheable(dh->region)) { + sys_cache_data_invd_range(buffer_in, user_length); + } + /* If no, no action is needed */ + + /* Check if user buffer and allocated buffer points to the same memory location + * If no, copy allocated buffer to the user buffer + */ + if (buffer_in != user_buffer) { + memcpy(user_buffer, buffer_in, user_length); + } + /* If yes, no action is needed */ + + /* Check if input buffer is contained within memory area + * managed by dynamic memory allocator + */ + if (is_buffer_within_region(addr, 0, dmm_heap_start_get(dh), dmm_heap_size_get(dh))) { + /* If yes, free the buffer */ + dmm_buffer_free(dh, buffer_in); + } + /* If no, no action is needed */ + + return 0; +} + +int dmm_init(void) +{ + struct dmm_heap *dh; + + for (size_t idx = 0; idx < ARRAY_SIZE(dmm_regions); idx++) { + dh = &dmm_heaps_data.dmm_heaps[idx]; + dh->region = &dmm_regions[idx]; + sys_heap_init(&dh->heap, (void *)dmm_heap_start_get(dh), dmm_heap_size_get(dh)); + } + + return 0; +} + +SYS_INIT(dmm_init, POST_KERNEL, 0); diff --git a/soc/nordic/common/dmm.h b/soc/nordic/common/dmm.h new file mode 100644 index 0000000000000..03780f37239d0 --- /dev/null +++ b/soc/nordic/common/dmm.h @@ -0,0 +1,187 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * nRF SoC specific public APIs for Device Memory Management (dmm) subsystem + */ + +#ifndef SOC_NORDIC_COMMON_DMM_H_ +#define SOC_NORDIC_COMMON_DMM_H_ + +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** @cond INTERNAL_HIDDEN */ + +#define DMM_DCACHE_LINE_SIZE \ + COND_CODE_1(IS_ENABLED(CONFIG_DCACHE), (CONFIG_DCACHE_LINE_SIZE), (sizeof(uint8_t))) + +/** + * @brief Get reference to memory region associated with the specified device node + * + * @param node_id Device node. + * + * @return Reference to memory region. NULL if not defined for given device node. + */ +#define DMM_DEV_TO_REG(node_id) \ + COND_CODE_1(DT_NODE_HAS_PROP(node_id, memory_regions), \ + ((void *)DT_REG_ADDR(DT_PHANDLE(node_id, memory_regions))), (NULL)) + +/** + * @brief Preallocate buffer in memory region associated with the specified device node + * + * @param node_id Device node. + */ +#define DMM_MEMORY_SECTION(node_id) \ + COND_CODE_1(DT_NODE_HAS_PROP(node_id, memory_regions), \ + (__attribute__((__section__(LINKER_DT_NODE_REGION_NAME( \ + DT_PHANDLE(node_id, memory_regions))))) \ + __aligned(DMM_DCACHE_LINE_SIZE)), \ + ()) + +#ifdef CONFIG_HAS_NORDIC_DMM + +/** + * @brief Prepare a DMA output buffer for the specified device + * + * Allocate an output buffer in memory region that given device can perform DMA transfers from. + * Copy @p user_buffer contents into it. + * Writeback data cache lines associated with output buffer, if needed. + * + * @note Depending on provided user buffer parameters and SoC architecture, + * dynamic allocation and cache operations might be skipped. + * + * @note @p buffer_out can be released using @ref dmm_buffer_in_release() + * to support transmitting and receiving data to the same buffer. + * + * @warning It is prohibited to read or write @p user_buffer or @p buffer_out contents + * from the time this function is called until @ref dmm_buffer_out_release() + * or @ref dmm_buffer_in_release is called on the same buffer + * or until this function returns with an error. + * + * @param region Memory region associated with device to prepare the buffer for. + * @param user_buffer CPU address (virtual if applicable) of the buffer containing data + * to be processed by the given device. + * @param user_length Length of the buffer containing data to be processed by the given device. + * @param buffer_out Pointer to a bus address of a buffer containing the prepared DMA buffer. + * + * @retval 0 If succeeded. + * @retval -ENOMEM If output buffer could not be allocated. + * @retval -errno Negative errno for other failures. + */ +int dmm_buffer_out_prepare(void *region, void const *user_buffer, size_t user_length, + void **buffer_out); + +/** + * @brief Release the previously prepared DMA output buffer + * + * @param region Memory region associated with device to release the buffer for. + * @param buffer_out Bus address of the DMA output buffer previously prepared + * with @ref dmm_buffer_out_prepare(). + * + * @retval 0 If succeeded. + * @retval -errno Negative errno code on failure. + */ +int dmm_buffer_out_release(void *region, void *buffer_out); + +/** + * @brief Prepare a DMA input buffer for the specified device + * + * Allocate an input buffer in memory region that given device can perform DMA transfers to. + * + * @note Depending on provided user buffer parameters and SoC architecture, + * dynamic allocation might be skipped. + * + * @warning It is prohibited to read or write @p user_buffer or @p buffer_in contents + * from the time this function is called until @ref dmm_buffer_in_release() + * is called on the same buffer or until this function returns with an error. + * + * @param region Memory region associated with device to prepare the buffer for. + * @param user_buffer CPU address (virtual if applicable) of the buffer to be filled with data + * from the given device. + * @param user_length Length of the buffer to be filled with data from the given device. + * @param buffer_in Pointer to a bus address of a buffer containing the prepared DMA buffer. + * + * @retval 0 If succeeded. + * @retval -ENOMEM If input buffer could not be allocated. + * @retval -errno Negative errno for other failures. + */ +int dmm_buffer_in_prepare(void *region, void *user_buffer, size_t user_length, void **buffer_in); + +/** + * @brief Release the previously prepared DMA input buffer + * + * Invalidate data cache lines associated with input buffer, if needed. + * Copy @p buffer_in contents into @p user_buffer, if needed. + * + * @param region Memory region associated with device to release the buffer for. + * @param user_buffer CPU address (virtual if applicable) of the buffer to be filled with data + * from the given device. + * @param user_length Length of the buffer to be filled with data from the given device. + * @param buffer_in Bus address of the DMA input buffer previously prepared + * with @ref dmm_buffer_in_prepare(). + * + * @note @p user_buffer and @p buffer_in arguments pair provided in this function call must match + * the arguments pair provided in prior call to @ref dmm_buffer_out_prepare() + * or @ref dmm_buffer_in_prepare(). + * + * @retval 0 If succeeded. + * @retval -errno Negative errno code on failure. + */ +int dmm_buffer_in_release(void *region, void *user_buffer, size_t user_length, void *buffer_in); + +/** @endcond */ + +#else + +static ALWAYS_INLINE int dmm_buffer_out_prepare(void *region, void const *user_buffer, + size_t user_length, void **buffer_out) +{ + ARG_UNUSED(region); + ARG_UNUSED(user_length); + *buffer_out = (void *)user_buffer; + return 0; +} + +static ALWAYS_INLINE int dmm_buffer_out_release(void *region, void *buffer_out) +{ + ARG_UNUSED(region); + ARG_UNUSED(buffer_out); + return 0; +} + +static ALWAYS_INLINE int dmm_buffer_in_prepare(void *region, void *user_buffer, size_t user_length, + void **buffer_in) +{ + ARG_UNUSED(region); + ARG_UNUSED(user_length); + *buffer_in = user_buffer; + return 0; +} + +static ALWAYS_INLINE int dmm_buffer_in_release(void *region, void *user_buffer, size_t user_length, + void *buffer_in) +{ + ARG_UNUSED(region); + ARG_UNUSED(user_buffer); + ARG_UNUSED(user_length); + ARG_UNUSED(buffer_in); + return 0; +} + +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* SOC_NORDIC_COMMON_DMM_H_ */ diff --git a/soc/nordic/nrf54h/Kconfig b/soc/nordic/nrf54h/Kconfig index a7eb08d9c9fcf..35017812d695b 100644 --- a/soc/nordic/nrf54h/Kconfig +++ b/soc/nordic/nrf54h/Kconfig @@ -7,6 +7,7 @@ config SOC_SERIES_NRF54HX select HAS_NRFS select HAS_NRFX select HAS_NORDIC_DRIVERS + select HAS_NORDIC_DMM config SOC_NRF54H20_CPUAPP select ARM From d67abdd02afce318199a062d4ecc1d93eff6ede5 Mon Sep 17 00:00:00 2001 From: Nikodem Kastelik Date: Mon, 10 Jun 2024 17:06:22 +0200 Subject: [PATCH 2603/2849] tests: boards: nrf: add tests for dmm component Added tests verify output and input buffers allocation using dmm component. Signed-off-by: Nikodem Kastelik --- tests/boards/nrf/dmm/CMakeLists.txt | 10 + .../boards/nrf5340dk_nrf5340_cpuapp.overlay | 56 +++++ .../boards/nrf54h20dk_nrf54h20_cpuapp.overlay | 58 +++++ tests/boards/nrf/dmm/prj.conf | 1 + tests/boards/nrf/dmm/src/main.c | 222 ++++++++++++++++++ tests/boards/nrf/dmm/testcase.yaml | 18 ++ 6 files changed, 365 insertions(+) create mode 100644 tests/boards/nrf/dmm/CMakeLists.txt create mode 100644 tests/boards/nrf/dmm/boards/nrf5340dk_nrf5340_cpuapp.overlay create mode 100644 tests/boards/nrf/dmm/boards/nrf54h20dk_nrf54h20_cpuapp.overlay create mode 100644 tests/boards/nrf/dmm/prj.conf create mode 100644 tests/boards/nrf/dmm/src/main.c create mode 100644 tests/boards/nrf/dmm/testcase.yaml diff --git a/tests/boards/nrf/dmm/CMakeLists.txt b/tests/boards/nrf/dmm/CMakeLists.txt new file mode 100644 index 0000000000000..3d047c9489841 --- /dev/null +++ b/tests/boards/nrf/dmm/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(dmm) + +FILE(GLOB app_sources src/*.c) + +target_sources(app PRIVATE ${app_sources}) diff --git a/tests/boards/nrf/dmm/boards/nrf5340dk_nrf5340_cpuapp.overlay b/tests/boards/nrf/dmm/boards/nrf5340dk_nrf5340_cpuapp.overlay new file mode 100644 index 0000000000000..9d2eceba6678a --- /dev/null +++ b/tests/boards/nrf/dmm/boards/nrf5340dk_nrf5340_cpuapp.overlay @@ -0,0 +1,56 @@ +/ { + aliases { + dut-cache = &spi1; + dut-nocache= &spi3; + }; +}; + +&pinctrl { + spi1_default_alt: spi1_default_alt { + group1 { + psels = , + ; + }; + }; + + spi1_sleep_alt: spi1_sleep_alt { + group1 { + psels = , + ; + low-power-enable; + }; + }; + + spi3_default_alt: spi3_default_alt { + group1 { + psels = , + ; + }; + }; + + spi3_sleep_alt: spi3_sleep_alt { + group1 { + psels = , + ; + low-power-enable; + }; + }; +}; + +&spi1 +{ + compatible = "nordic,nrf-spim"; + status = "okay"; + pinctrl-0 = <&spi1_default_alt>; + pinctrl-1 = <&spi1_sleep_alt>; + pinctrl-names = "default", "sleep"; +}; + +&spi3 +{ + compatible = "nordic,nrf-spim"; + status = "okay"; + pinctrl-0 = <&spi3_default_alt>; + pinctrl-1 = <&spi3_sleep_alt>; + pinctrl-names = "default", "sleep"; +}; diff --git a/tests/boards/nrf/dmm/boards/nrf54h20dk_nrf54h20_cpuapp.overlay b/tests/boards/nrf/dmm/boards/nrf54h20dk_nrf54h20_cpuapp.overlay new file mode 100644 index 0000000000000..513ef21776ff9 --- /dev/null +++ b/tests/boards/nrf/dmm/boards/nrf54h20dk_nrf54h20_cpuapp.overlay @@ -0,0 +1,58 @@ +/ { + aliases { + dut-cache = &spi120; + dut-nocache = &spi130; + }; +}; + +&pinctrl { + spi130_default_alt: spi130_default_alt { + group1 { + psels = , + ; + }; + }; + + spi130_sleep_alt: spi130_sleep_alt { + group1 { + psels = , + ; + low-power-enable; + }; + }; + + spi120_default_alt: spi120_default_alt { + group1 { + psels = , + ; + }; + }; + + spi120_sleep_alt: spi120_sleep_alt { + group1 { + psels = , + ; + low-power-enable; + }; + }; +}; + +&spi130 +{ + compatible = "nordic,nrf-spim"; + status = "okay"; + pinctrl-0 = <&spi130_default_alt>; + pinctrl-1 = <&spi130_sleep_alt>; + pinctrl-names = "default", "sleep"; + memory-regions = <&cpuapp_dma_region>; +}; + +&spi120 +{ + compatible = "nordic,nrf-spim"; + status = "okay"; + pinctrl-0 = <&spi120_default_alt>; + pinctrl-1 = <&spi120_sleep_alt>; + pinctrl-names = "default", "sleep"; + memory-regions = <&dma_fast_region>; +}; diff --git a/tests/boards/nrf/dmm/prj.conf b/tests/boards/nrf/dmm/prj.conf new file mode 100644 index 0000000000000..9467c2926896d --- /dev/null +++ b/tests/boards/nrf/dmm/prj.conf @@ -0,0 +1 @@ +CONFIG_ZTEST=y diff --git a/tests/boards/nrf/dmm/src/main.c b/tests/boards/nrf/dmm/src/main.c new file mode 100644 index 0000000000000..5ddbebfb83823 --- /dev/null +++ b/tests/boards/nrf/dmm/src/main.c @@ -0,0 +1,222 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include + +#include + +#define DUT_CACHE DT_ALIAS(dut_cache) +#define DUT_NOCACHE DT_ALIAS(dut_nocache) + +#define DMM_TEST_GET_REG_START(node_id) \ + COND_CODE_1(DT_NODE_HAS_PROP(node_id, memory_regions), \ + (DT_REG_ADDR(DT_PHANDLE(node_id, memory_regions))), (0)) + +#define DMM_TEST_GET_REG_SIZE(node_id) \ + COND_CODE_1(DT_NODE_HAS_PROP(node_id, memory_regions), \ + (DT_REG_SIZE(DT_PHANDLE(node_id, memory_regions))), (0)) + +struct dmm_test_region { + void *mem_reg; + uintptr_t start; + size_t size; +}; + +enum { + DMM_TEST_REGION_CACHE, + DMM_TEST_REGION_NOCACHE, + DMM_TEST_REGION_COUNT +}; + +struct dmm_fixture { + struct dmm_test_region regions[DMM_TEST_REGION_COUNT]; + uint32_t fill_value; +}; + +static const struct dmm_test_region dmm_test_regions[DMM_TEST_REGION_COUNT] = { + [DMM_TEST_REGION_CACHE] = { + .mem_reg = DMM_DEV_TO_REG(DUT_CACHE), + .start = DMM_TEST_GET_REG_START(DUT_CACHE), + .size = DMM_TEST_GET_REG_SIZE(DUT_CACHE) + }, + [DMM_TEST_REGION_NOCACHE] = { + .mem_reg = DMM_DEV_TO_REG(DUT_NOCACHE), + .start = DMM_TEST_GET_REG_START(DUT_NOCACHE), + .size = DMM_TEST_GET_REG_SIZE(DUT_NOCACHE) + }, +}; + +static void *test_setup(void) +{ + static struct dmm_fixture fixture; + + memcpy(fixture.regions, dmm_test_regions, sizeof(dmm_test_regions)); + fixture.fill_value = 0x1; + return &fixture; +} + +static void test_cleanup(void *argc) +{ +} + +static bool dmm_buffer_in_region_check(struct dmm_test_region *dtr, void *buf, size_t size) +{ + uintptr_t start = (uintptr_t)buf; + + return ((start >= dtr->start) && ((start + size) <= (dtr->start + dtr->size))); +} + +static void dmm_check_output_buffer(struct dmm_test_region *dtr, uint32_t *fill_value, + void *data, size_t size, bool was_prealloc) +{ + void *buf; + int retval; + + memset(data, (*fill_value)++, size); + retval = dmm_buffer_out_prepare(dtr->mem_reg, data, size, &buf); + zassert_ok(retval); + zassert_true(IS_ALIGNED(buf, DMM_DCACHE_LINE_SIZE)); + + if (IS_ENABLED(CONFIG_HAS_NORDIC_DMM)) { + if (was_prealloc) { + zassert_equal(data, buf); + } else { + zassert_not_equal(data, buf); + } + zassert_true(dmm_buffer_in_region_check(dtr, buf, size)); + } else { + zassert_equal(data, buf); + } + sys_cache_data_invd_range(buf, size); + zassert_mem_equal(buf, data, size); + + retval = dmm_buffer_out_release(dtr->mem_reg, buf); + zassert_ok(retval); +} + +static void dmm_check_input_buffer(struct dmm_test_region *dtr, uint32_t *fill_value, + void *data, size_t size, bool was_prealloc, bool is_cached) +{ + void *buf; + int retval; + uint8_t intermediate_buf[128]; + + zassert_true(size < sizeof(intermediate_buf)); + + retval = dmm_buffer_in_prepare(dtr->mem_reg, data, size, &buf); + zassert_ok(retval); + zassert_true(IS_ALIGNED(buf, DMM_DCACHE_LINE_SIZE)); + + if (IS_ENABLED(CONFIG_HAS_NORDIC_DMM)) { + if (was_prealloc) { + zassert_equal(data, buf); + } else { + zassert_not_equal(data, buf); + } + zassert_true(dmm_buffer_in_region_check(dtr, buf, size)); + } else { + zassert_equal(data, buf); + } + + /* Simulate external bus master writing to memory region */ + memset(buf, (*fill_value)++, size); + sys_cache_data_flush_range(buf, size); + /* Preserve actual memory region contents before polluting the cache */ + memcpy(intermediate_buf, buf, size); + if (IS_ENABLED(CONFIG_DCACHE) && is_cached) { + /* Purposefully pollute the cache to make sure library manages cache properly */ + memset(buf, (*fill_value)++, size); + } + + retval = dmm_buffer_in_release(dtr->mem_reg, data, size, buf); + zassert_ok(retval); + + zassert_mem_equal(data, intermediate_buf, size); +} + +ZTEST_USER_F(dmm, test_check_dev_cache_in_allocate) +{ + uint8_t user_data[16]; + + dmm_check_input_buffer(&fixture->regions[DMM_TEST_REGION_CACHE], &fixture->fill_value, + user_data, sizeof(user_data), false, true); +} + +ZTEST_USER_F(dmm, test_check_dev_cache_in_preallocate) +{ + static uint8_t user_data[16] DMM_MEMORY_SECTION(DUT_CACHE); + + dmm_check_input_buffer(&fixture->regions[DMM_TEST_REGION_CACHE], &fixture->fill_value, + user_data, sizeof(user_data), true, true); +} + +ZTEST_USER_F(dmm, test_check_dev_cache_out_allocate) +{ + uint8_t user_data[16]; + + dmm_check_output_buffer(&fixture->regions[DMM_TEST_REGION_CACHE], &fixture->fill_value, + user_data, sizeof(user_data), false); +} + +ZTEST_USER_F(dmm, test_check_dev_cache_out_preallocate) +{ + static uint8_t user_data[16] DMM_MEMORY_SECTION(DUT_CACHE); + + dmm_check_output_buffer(&fixture->regions[DMM_TEST_REGION_CACHE], &fixture->fill_value, + user_data, sizeof(user_data), true); +} + +ZTEST_USER_F(dmm, test_check_dev_nocache_in_allocate) +{ + uint8_t user_data[16]; + + dmm_check_input_buffer(&fixture->regions[DMM_TEST_REGION_NOCACHE], &fixture->fill_value, + user_data, sizeof(user_data), false, false); +} + +ZTEST_USER_F(dmm, test_check_dev_nocache_in_preallocate) +{ + static uint8_t user_data[16] DMM_MEMORY_SECTION(DUT_NOCACHE); + + dmm_check_input_buffer(&fixture->regions[DMM_TEST_REGION_NOCACHE], &fixture->fill_value, + user_data, sizeof(user_data), true, false); +} + +ZTEST_USER_F(dmm, test_check_dev_nocache_out_allocate) +{ + uint8_t user_data[16]; + + dmm_check_output_buffer(&fixture->regions[DMM_TEST_REGION_NOCACHE], &fixture->fill_value, + user_data, sizeof(user_data), false); +} + +ZTEST_USER_F(dmm, test_check_dev_nocache_out_preallocate) +{ + static uint8_t user_data[16] DMM_MEMORY_SECTION(DUT_NOCACHE); + + dmm_check_output_buffer(&fixture->regions[DMM_TEST_REGION_NOCACHE], &fixture->fill_value, + user_data, sizeof(user_data), true); +} + +ZTEST_SUITE(dmm, NULL, test_setup, NULL, test_cleanup, NULL); + +int dmm_test_prepare(void) +{ + const struct dmm_test_region *dtr; + + for (size_t i = 0; i < ARRAY_SIZE(dmm_test_regions); i++) { + dtr = &dmm_test_regions[i]; + memset((void *)dtr->start, 0x00, dtr->size); + } + + return 0; +} + +SYS_INIT(dmm_test_prepare, PRE_KERNEL_1, 0); diff --git a/tests/boards/nrf/dmm/testcase.yaml b/tests/boards/nrf/dmm/testcase.yaml new file mode 100644 index 0000000000000..b5f41f281a5b9 --- /dev/null +++ b/tests/boards/nrf/dmm/testcase.yaml @@ -0,0 +1,18 @@ +common: + tags: drivers + harness: ztest + +tests: + boards.nrf.dmm: + platform_allow: + - nrf54h20dk/nrf54h20/cpuapp + - nrf5340dk/nrf5340/cpuapp + integration_platforms: + - nrf5340dk/nrf5340/cpuapp + - nrf54h20dk/nrf54h20/cpuapp + + boards.nrf.dmm.cache_disabled: + extra_configs: + - CONFIG_DCACHE=n + platform_allow: + - nrf54h20dk/nrf54h20/cpuapp From e2cdd92a522d48e1acf080981bf41ab4effc60ef Mon Sep 17 00:00:00 2001 From: Phi Bang Nguyen Date: Thu, 13 Jun 2024 12:23:08 +0200 Subject: [PATCH 2604/2849] boards: nxp: mimxrt1064: Remove display chosen node As display stuffs have been moved to a shield, the display chosen node must be removed as well as chosen node requires the node to be enabled. Signed-off-by: Phi Bang Nguyen --- boards/nxp/mimxrt1064_evk/mimxrt1064_evk.dts | 1 - 1 file changed, 1 deletion(-) diff --git a/boards/nxp/mimxrt1064_evk/mimxrt1064_evk.dts b/boards/nxp/mimxrt1064_evk/mimxrt1064_evk.dts index 6f752552e7292..7b1a0d0a7d41c 100644 --- a/boards/nxp/mimxrt1064_evk/mimxrt1064_evk.dts +++ b/boards/nxp/mimxrt1064_evk/mimxrt1064_evk.dts @@ -32,7 +32,6 @@ zephyr,console = &lpuart1; zephyr,shell-uart = &lpuart1; zephyr,canbus = &flexcan2; - zephyr,display = &lcdif; }; sdram0: memory@80000000 { From 0e830b3f100d1a1e768857450ada8be0db5a7634 Mon Sep 17 00:00:00 2001 From: David Schneider Date: Thu, 13 Jun 2024 09:08:37 +0200 Subject: [PATCH 2605/2849] doc: kernel: fix braces in code example Add missing closing brace to `k_poll()` loop example. Signed-off-by: David Schneider --- doc/kernel/services/polling.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/kernel/services/polling.rst b/doc/kernel/services/polling.rst index 685a3023d5eb7..b1d08e35d0d1a 100644 --- a/doc/kernel/services/polling.rst +++ b/doc/kernel/services/polling.rst @@ -196,6 +196,7 @@ to :c:macro:`K_POLL_STATE_NOT_READY` by the user. } else if (events[3].state == K_POLL_STATE_PIPE_DATA_AVAILABLE) { ret = k_pipe_get(events[3].pipe, buf, bytes_to_read, &bytes_read, min_xfer, K_NO_WAIT); // handle data + } events[0].state = K_POLL_STATE_NOT_READY; events[1].state = K_POLL_STATE_NOT_READY; events[2].state = K_POLL_STATE_NOT_READY; From 94ded47fa7e9c85a747270fbd5239842fef0c9f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20Cab=C3=A9?= Date: Wed, 12 Jun 2024 15:43:21 +0200 Subject: [PATCH 2606/2849] drivers: crypto: make driver API and conf structs const MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Save precious RAM by making sure driver API and config structs are declared as const Signed-off-by: Benjamin Cabé --- drivers/crypto/crypto_it8xxx2_sha.c | 2 +- drivers/crypto/crypto_it8xxx2_sha_v2.c | 2 +- drivers/crypto/crypto_mchp_xec_symcr.c | 2 +- drivers/crypto/crypto_mcux_dcp.c | 2 +- drivers/crypto/crypto_npcx_sha.c | 2 +- drivers/crypto/crypto_smartbond.c | 2 +- drivers/crypto/crypto_stm32.c | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/crypto/crypto_it8xxx2_sha.c b/drivers/crypto/crypto_it8xxx2_sha.c index b144878de8f19..3fea42f217d28 100644 --- a/drivers/crypto/crypto_it8xxx2_sha.c +++ b/drivers/crypto/crypto_it8xxx2_sha.c @@ -215,7 +215,7 @@ static int it8xxx2_sha_init(const struct device *dev) return 0; } -static struct crypto_driver_api it8xxx2_crypto_api = { +static const struct crypto_driver_api it8xxx2_crypto_api = { .hash_begin_session = it8xxx2_hash_begin_session, .hash_free_session = it8xxx2_hash_session_free, .query_hw_caps = it8xxx2_query_hw_caps, diff --git a/drivers/crypto/crypto_it8xxx2_sha_v2.c b/drivers/crypto/crypto_it8xxx2_sha_v2.c index 48eae76c673c2..6da1cff4c2942 100644 --- a/drivers/crypto/crypto_it8xxx2_sha_v2.c +++ b/drivers/crypto/crypto_it8xxx2_sha_v2.c @@ -340,7 +340,7 @@ static int it8xxx2_sha_init(const struct device *dev) return 0; } -static struct crypto_driver_api it8xxx2_crypto_api = { +static const struct crypto_driver_api it8xxx2_crypto_api = { .hash_begin_session = it8xxx2_hash_begin_session, .hash_free_session = it8xxx2_hash_session_free, .query_hw_caps = it8xxx2_query_hw_caps, diff --git a/drivers/crypto/crypto_mchp_xec_symcr.c b/drivers/crypto/crypto_mchp_xec_symcr.c index 8f47e374d36e6..6bcf4f17c854a 100644 --- a/drivers/crypto/crypto_mchp_xec_symcr.c +++ b/drivers/crypto/crypto_mchp_xec_symcr.c @@ -514,7 +514,7 @@ static int xec_symcr_init(const struct device *dev) return ret; } -static struct crypto_driver_api xec_symcr_api = { +static const struct crypto_driver_api xec_symcr_api = { .query_hw_caps = xec_symcr_query_hw_caps, .hash_begin_session = xec_symcr_hash_session_begin, .hash_free_session = xec_symcr_hash_session_free, diff --git a/drivers/crypto/crypto_mcux_dcp.c b/drivers/crypto/crypto_mcux_dcp.c index 7419a340b0bfb..23232ed9b57cd 100644 --- a/drivers/crypto/crypto_mcux_dcp.c +++ b/drivers/crypto/crypto_mcux_dcp.c @@ -331,7 +331,7 @@ static int crypto_dcp_init(const struct device *dev) return 0; } -static struct crypto_driver_api crypto_dcp_api = { +static const struct crypto_driver_api crypto_dcp_api = { .query_hw_caps = crypto_dcp_query_hw_caps, .cipher_begin_session = crypto_dcp_cipher_begin_session, .cipher_free_session = crypto_dcp_cipher_free_session, diff --git a/drivers/crypto/crypto_npcx_sha.c b/drivers/crypto/crypto_npcx_sha.c index 8aa30846ae23f..20c817f1cf903 100644 --- a/drivers/crypto/crypto_npcx_sha.c +++ b/drivers/crypto/crypto_npcx_sha.c @@ -202,7 +202,7 @@ static int npcx_hash_init(const struct device *dev) return 0; } -static struct crypto_driver_api npcx_crypto_api = { +static const struct crypto_driver_api npcx_crypto_api = { .hash_begin_session = npcx_hash_session_setup, .hash_free_session = npcx_hash_session_free, .query_hw_caps = npcx_query_caps, diff --git a/drivers/crypto/crypto_smartbond.c b/drivers/crypto/crypto_smartbond.c index 8e394e28d9af3..7b8e33799b52c 100644 --- a/drivers/crypto/crypto_smartbond.c +++ b/drivers/crypto/crypto_smartbond.c @@ -922,7 +922,7 @@ crypto_smartbond_hash_set_async_callback(const struct device *dev, hash_completi } #endif -static struct crypto_driver_api crypto_smartbond_driver_api = { +static const struct crypto_driver_api crypto_smartbond_driver_api = { .cipher_begin_session = crypto_smartbond_cipher_begin_session, .cipher_free_session = crypto_smartbond_cipher_free_session, #if defined(CONFIG_CRYPTO_ASYNC) diff --git a/drivers/crypto/crypto_stm32.c b/drivers/crypto/crypto_stm32.c index 67f790f250b85..bb78d65894a5f 100644 --- a/drivers/crypto/crypto_stm32.c +++ b/drivers/crypto/crypto_stm32.c @@ -507,7 +507,7 @@ static struct crypto_stm32_data crypto_stm32_dev_data = { } }; -static struct crypto_stm32_config crypto_stm32_dev_config = { +static const struct crypto_stm32_config crypto_stm32_dev_config = { .pclken = { .enr = DT_INST_CLOCKS_CELL(0, bits), .bus = DT_INST_CLOCKS_CELL(0, bus) From 2a4417bb8ef154a3ea17ab69f1e6bf695d5df41d Mon Sep 17 00:00:00 2001 From: Aksel Skauge Mellbye Date: Tue, 11 Jun 2024 20:01:24 +0200 Subject: [PATCH 2607/2849] soc: silabs: Fix CMake test for soc family Kconfig options need CONFIG_ prefix when tested for in CMakeLists.txt. Fixes regression introduced in e90c89d45311aed6612113cf6bfdce652bba250d that causes all apps to fail to initialize on Silabs socs. Signed-off-by: Aksel Skauge Mellbye --- soc/silabs/common/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/soc/silabs/common/CMakeLists.txt b/soc/silabs/common/CMakeLists.txt index a3e08c2fce19b..7d1ed73666741 100644 --- a/soc/silabs/common/CMakeLists.txt +++ b/soc/silabs/common/CMakeLists.txt @@ -1,6 +1,6 @@ # SPDX-License-Identifier: Apache-2.0 -if(SOC_FAMILY_SILABS_S0 OR SOC_FAMILY_SILABS_S1 OR SOC_FAMILY_SILABS_S2) +if(CONFIG_SOC_FAMILY_SILABS_S0 OR CONFIG_SOC_FAMILY_SILABS_S1 OR CONFIG_SOC_FAMILY_SILABS_S2) zephyr_sources(soc.c) endif() From 0153b34c4ce82b5fcb3a145bc654a26366126a3b Mon Sep 17 00:00:00 2001 From: Marek Matej Date: Tue, 11 Jun 2024 19:19:16 +0200 Subject: [PATCH 2608/2849] manifest: hal_espressif update Update the hal_espressif to include latest esptool version. Improve support for new SoCs as such as ESP32-C6. Fix bugs related to segment alignment. Signed-off-by: Marek Matej --- west.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/west.yml b/west.yml index d4cc4890c9437..59a0ea444692a 100644 --- a/west.yml +++ b/west.yml @@ -157,7 +157,7 @@ manifest: groups: - hal - name: hal_espressif - revision: 5191505f915c0b1c706222f4709925a453e0e858 + revision: 0690c03f1540e8a5082da4c2b997e64bde8f4765 path: modules/hal/espressif west-commands: west/west-commands.yml groups: From 42a0d18ecf8798068a0d1ab3fb886c279524e8f0 Mon Sep 17 00:00:00 2001 From: Luca Burelli Date: Tue, 11 Jun 2024 14:41:35 +0200 Subject: [PATCH 2609/2849] llext: tests: add zassert macros everywhere Most of the current llext tests did not actually check the results of the tests, so the CI reported a pass even if something was wrong when looking at the logs. This patch adds the appropriate zassert_* macros to all the tests, to ensure that they actually perform correctly. Signed-off-by: Luca Burelli --- tests/subsys/llext/simple/src/hello_world_ext.c | 2 ++ tests/subsys/llext/simple/src/movwmovt_ext.c | 8 ++++++-- tests/subsys/llext/simple/src/multi_file_ext1.c | 5 +++++ tests/subsys/llext/simple/src/object_ext.c | 4 ++++ tests/subsys/llext/simple/src/relative_jump_ext.c | 6 ++++++ tests/subsys/llext/simple/src/syscalls_ext.c | 5 ++++- .../subsys/llext/simple/src/threads_kernel_objects_ext.c | 5 +++++ 7 files changed, 32 insertions(+), 3 deletions(-) diff --git a/tests/subsys/llext/simple/src/hello_world_ext.c b/tests/subsys/llext/simple/src/hello_world_ext.c index f3cc2106a11c1..2a8bdf56c95eb 100644 --- a/tests/subsys/llext/simple/src/hello_world_ext.c +++ b/tests/subsys/llext/simple/src/hello_world_ext.c @@ -14,6 +14,7 @@ #include #include #include +#include static const uint32_t number = 42; @@ -21,5 +22,6 @@ void test_entry(void) { printk("hello world\n"); printk("A number is %u\n", number); + zassert_equal(number, 42); } LL_EXTENSION_SYMBOL(test_entry); diff --git a/tests/subsys/llext/simple/src/movwmovt_ext.c b/tests/subsys/llext/simple/src/movwmovt_ext.c index 5400385623a25..21633228778b1 100644 --- a/tests/subsys/llext/simple/src/movwmovt_ext.c +++ b/tests/subsys/llext/simple/src/movwmovt_ext.c @@ -12,20 +12,24 @@ #include #include #include +#include +static int test_var; -static void test_func(void) +static __used void test_func(void) { printk("%s\n", __func__); + test_var = 1; } void test_entry(void) { - test_func(); + test_var = 0; printk("test movwmovt\n"); __asm volatile ("movw r0, #:lower16:test_func"); __asm volatile ("movt r0, #:upper16:test_func"); __asm volatile ("blx r0"); + zassert_equal(test_var, 1, "mov.w and mov.t test failed"); } LL_EXTENSION_SYMBOL(test_entry); diff --git a/tests/subsys/llext/simple/src/multi_file_ext1.c b/tests/subsys/llext/simple/src/multi_file_ext1.c index 018c11af6faa0..e4162a1629f44 100644 --- a/tests/subsys/llext/simple/src/multi_file_ext1.c +++ b/tests/subsys/llext/simple/src/multi_file_ext1.c @@ -11,6 +11,7 @@ #include #include #include +#include /* Test non-static global object relocation */ int number = 0x42; @@ -21,9 +22,13 @@ void test_entry(void) { printk("initial: local %d plus external %d equals %d\n", number, ext_number, ext_sum_fn(ext_number)); + zassert_equal(number, 0x42); + zassert_equal(ext_number, 0x18); number ^= ext_number; ext_number ^= number; number ^= ext_number; + zassert_equal(number, 0x18); + zassert_equal(ext_number, 0x42); printk("updated: local %d plus external %d equals %d\n", number, ext_number, ext_sum_fn(ext_number)); } diff --git a/tests/subsys/llext/simple/src/object_ext.c b/tests/subsys/llext/simple/src/object_ext.c index dd2f9250228b5..41a8bc358ca16 100644 --- a/tests/subsys/llext/simple/src/object_ext.c +++ b/tests/subsys/llext/simple/src/object_ext.c @@ -11,6 +11,7 @@ #include #include #include +#include /* Test non-static global object relocation */ int number = 42; @@ -19,8 +20,11 @@ const char *string = "hello"; void test_entry(void) { printk("number: %d\n", number); + zassert_equal(number, 42); number = 0; printk("number, updated: %d\n", number); + zassert_equal(number, 0); printk("string: %s\n", string); + zassert_ok(strcmp(string, "hello")); } LL_EXTENSION_SYMBOL(test_entry); diff --git a/tests/subsys/llext/simple/src/relative_jump_ext.c b/tests/subsys/llext/simple/src/relative_jump_ext.c index 0619f201cef65..e7f67469b834e 100644 --- a/tests/subsys/llext/simple/src/relative_jump_ext.c +++ b/tests/subsys/llext/simple/src/relative_jump_ext.c @@ -14,6 +14,9 @@ #include #include #include +#include + +static int test_var; void test_relative_jump_1(void); void test_relative_jump_2(void); @@ -24,6 +27,7 @@ void test_relative_jump_5(void); void test_relative_jump_5(void) { printk("relative jump 5\n"); + test_var = 1; } void test_relative_jump_4(void) @@ -53,7 +57,9 @@ void test_relative_jump_3(void) void test_entry(void) { printk("enter\n"); + test_var = 0; test_relative_jump_1(); printk("exit\n"); + zassert_equal(test_var, 1, "relative jump test failed"); } LL_EXTENSION_SYMBOL(test_entry); diff --git a/tests/subsys/llext/simple/src/syscalls_ext.c b/tests/subsys/llext/simple/src/syscalls_ext.c index 9089bfec17e64..f8f073fb6f99f 100644 --- a/tests/subsys/llext/simple/src/syscalls_ext.c +++ b/tests/subsys/llext/simple/src/syscalls_ext.c @@ -10,14 +10,17 @@ #include #include +#include #include "syscalls_ext.h" void test_entry(void) { int input = 41; + int output = ext_syscall_ok(input); printk("Input: %d Expected output: %d Actual output: %d\n", - input, input + 1, ext_syscall_ok(input)); + input, input + 1, output); + zassert_equal(output, input + 1); } LL_EXTENSION_SYMBOL(test_entry); diff --git a/tests/subsys/llext/simple/src/threads_kernel_objects_ext.c b/tests/subsys/llext/simple/src/threads_kernel_objects_ext.c index 21ca839efc40c..fd6b9673c9578 100644 --- a/tests/subsys/llext/simple/src/threads_kernel_objects_ext.c +++ b/tests/subsys/llext/simple/src/threads_kernel_objects_ext.c @@ -12,6 +12,8 @@ #include #include #include +#include + #include "threads_kernel_objects_ext.h" void test_thread(void *arg0, void *arg1, void *arg2) @@ -23,9 +25,12 @@ void test_thread(void *arg0, void *arg1, void *arg2) void test_entry(void) { printk("Give semaphore from main thread\n"); + zassert_not_null(&my_sem); k_sem_give(&my_sem); printk("Creating thread\n"); + zassert_not_null(&my_thread); + zassert_not_null(&my_thread_stack); k_tid_t tid = k_thread_create(&my_thread, (k_thread_stack_t *) &my_thread_stack, MY_THREAD_STACK_SIZE, &test_thread, NULL, NULL, NULL, MY_THREAD_PRIO, MY_THREAD_OPTIONS, K_FOREVER); From d25563f59a2a14640c16c9f244fdaabdda8e5778 Mon Sep 17 00:00:00 2001 From: Luca Burelli Date: Tue, 11 Jun 2024 14:42:00 +0200 Subject: [PATCH 2610/2849] llext: tests: re-initialize variables Some tests depend on global initialized variables, which are then modified during the test. When enabling user mode, the functions are called multiple times but the variables are not reinitialized, resulting in a test failure. This patch adds a run_id variable to the tests to reinitialize the variables when the test is called multiple times. It is purposefully initialized to 41 at startup to detect if the variable is not set up properly by the llext loader. Signed-off-by: Luca Burelli --- .../subsys/llext/simple/src/multi_file_ext1.c | 18 ++++++++++++++++++ tests/subsys/llext/simple/src/object_ext.c | 18 ++++++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/tests/subsys/llext/simple/src/multi_file_ext1.c b/tests/subsys/llext/simple/src/multi_file_ext1.c index e4162a1629f44..bdc8bccaaa128 100644 --- a/tests/subsys/llext/simple/src/multi_file_ext1.c +++ b/tests/subsys/llext/simple/src/multi_file_ext1.c @@ -18,8 +18,24 @@ int number = 0x42; extern int ext_number; int ext_sum_fn(int arg); +int run_id = 41; + void test_entry(void) { + switch (run_id) { + case 41: + /* initial run: test variable initialization */ + break; + case 42: + /* user-mode run: reinit number */ + number = 0x42; + break; + default: + /* possible llext loader issue */ + zassert_unreachable("unexpected run_id %d", run_id); + return; + } + printk("initial: local %d plus external %d equals %d\n", number, ext_number, ext_sum_fn(ext_number)); zassert_equal(number, 0x42); @@ -31,5 +47,7 @@ void test_entry(void) zassert_equal(ext_number, 0x42); printk("updated: local %d plus external %d equals %d\n", number, ext_number, ext_sum_fn(ext_number)); + + run_id += 1; } LL_EXTENSION_SYMBOL(test_entry); diff --git a/tests/subsys/llext/simple/src/object_ext.c b/tests/subsys/llext/simple/src/object_ext.c index 41a8bc358ca16..7efe1a916d64e 100644 --- a/tests/subsys/llext/simple/src/object_ext.c +++ b/tests/subsys/llext/simple/src/object_ext.c @@ -17,8 +17,24 @@ int number = 42; const char *string = "hello"; +int run_id = 41; + void test_entry(void) { + switch (run_id) { + case 41: + /* initial run: test variable initialization */ + break; + case 42: + /* user-mode run: reinit number */ + number = 42; + break; + default: + /* possible llext loader issue */ + zassert_unreachable("unexpected run_id %d", run_id); + return; + } + printk("number: %d\n", number); zassert_equal(number, 42); number = 0; @@ -26,5 +42,7 @@ void test_entry(void) zassert_equal(number, 0); printk("string: %s\n", string); zassert_ok(strcmp(string, "hello")); + + run_id += 1; } LL_EXTENSION_SYMBOL(test_entry); From 87e1ab83c99f7013dece61d78bb3af5eb2a73ca3 Mon Sep 17 00:00:00 2001 From: Luca Burelli Date: Tue, 11 Jun 2024 14:36:31 +0200 Subject: [PATCH 2611/2849] llext: tests: fix "mps2/an385/*_mpu" OOM With the ztest code added, tests were failing with -ENOMEM on the mps2/an385/*_mpu platform due to alignment requirements. Increase the llext test heap size to 32Kbytes to avoid this. Signed-off-by: Luca Burelli --- tests/subsys/llext/simple/prj.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/subsys/llext/simple/prj.conf b/tests/subsys/llext/simple/prj.conf index 2105b798cabe3..5ad4b4e1f4b8e 100644 --- a/tests/subsys/llext/simple/prj.conf +++ b/tests/subsys/llext/simple/prj.conf @@ -2,7 +2,7 @@ CONFIG_ZTEST=y CONFIG_ZTEST_STACK_SIZE=4096 CONFIG_LOG=y CONFIG_LLEXT=y -CONFIG_LLEXT_HEAP_SIZE=16 +CONFIG_LLEXT_HEAP_SIZE=32 CONFIG_LLEXT_LOG_LEVEL_DBG=y CONFIG_APPLICATION_DEFINED_SYSCALL=y From 5c24c79a90c0acb3f42a3a1ecd950dfd2b40b0c3 Mon Sep 17 00:00:00 2001 From: Bjarki Arge Andreasen Date: Mon, 10 Jun 2024 13:15:25 +0200 Subject: [PATCH 2612/2849] modem: pipe: simplify synchronization The design of the pipe is overly complicated compared to the in-tree and planned future use of the pipe module. The pipe is currently designed to protect against multiple threads calling any API simultaineously. This is not neccesary as only one thread ever calls open/close/transmit/receive at once, while the notification APIs are potentially called by a different thread. This commit removes the synchronization of calls to the open/ close/receive/transmit APIs. It also uses a k_event for thread safe event and state handling instead of a k_mutex and k_condvar. The callback is proteced by a k_sem as it modified using the attach/release APIs, which can be called simultaneously to a thread invoking the callback. Signed-off-by: Bjarki Arge Andreasen --- include/zephyr/modem/pipe.h | 12 +- subsys/modem/Kconfig | 1 + subsys/modem/modem_pipe.c | 234 ++++++++++++++++-------------------- 3 files changed, 109 insertions(+), 138 deletions(-) diff --git a/include/zephyr/modem/pipe.h b/include/zephyr/modem/pipe.h index 60e877e44a34a..9b19569251439 100644 --- a/include/zephyr/modem/pipe.h +++ b/include/zephyr/modem/pipe.h @@ -61,21 +61,13 @@ struct modem_pipe_api { modem_pipe_api_close close; }; -enum modem_pipe_state { - MODEM_PIPE_STATE_CLOSED = 0, - MODEM_PIPE_STATE_OPEN, -}; - struct modem_pipe { void *data; struct modem_pipe_api *api; modem_pipe_api_callback callback; void *user_data; - enum modem_pipe_state state; - struct k_mutex lock; - struct k_condvar condvar; - uint8_t receive_ready_pending : 1; - uint8_t transmit_idle_pending : 1; + struct k_spinlock spinlock; + struct k_event event; }; /** diff --git a/subsys/modem/Kconfig b/subsys/modem/Kconfig index 9fd126b557a64..90a4ded36e723 100644 --- a/subsys/modem/Kconfig +++ b/subsys/modem/Kconfig @@ -42,6 +42,7 @@ endif config MODEM_PIPE bool "Modem pipe module" + select EVENTS config MODEM_PIPELINK bool "Modem pipelink module" diff --git a/subsys/modem/modem_pipe.c b/subsys/modem/modem_pipe.c index b0088fdefed29..326c4f4bb751d 100644 --- a/subsys/modem/modem_pipe.c +++ b/subsys/modem/modem_pipe.c @@ -6,8 +6,74 @@ #include -#include -LOG_MODULE_REGISTER(modem_pipe, CONFIG_MODEM_MODULES_LOG_LEVEL); +#define PIPE_EVENT_OPENED_BIT BIT(0) +#define PIPE_EVENT_CLOSED_BIT BIT(1) +#define PIPE_EVENT_RECEIVE_READY_BIT BIT(2) +#define PIPE_EVENT_TRANSMIT_IDLE_BIT BIT(3) + +static void pipe_set_callback(struct modem_pipe *pipe, + modem_pipe_api_callback callback, + void *user_data) +{ + K_SPINLOCK(&pipe->spinlock) { + pipe->callback = callback; + pipe->user_data = user_data; + } +} + +static void pipe_call_callback(struct modem_pipe *pipe, enum modem_pipe_event event) +{ + K_SPINLOCK(&pipe->spinlock) { + if (pipe->callback != NULL) { + pipe->callback(pipe, event, pipe->user_data); + } + } +} + +static uint32_t pipe_test_events(struct modem_pipe *pipe, uint32_t events) +{ + return k_event_test(&pipe->event, events); +} + +static uint32_t pipe_await_events(struct modem_pipe *pipe, uint32_t events) +{ + return k_event_wait(&pipe->event, events, false, K_MSEC(10000)); +} + +static void pipe_post_events(struct modem_pipe *pipe, uint32_t events) +{ + k_event_post(&pipe->event, events); +} + +static void pipe_clear_events(struct modem_pipe *pipe, uint32_t events) +{ + k_event_clear(&pipe->event, events); +} + +static void pipe_set_events(struct modem_pipe *pipe, uint32_t events) +{ + k_event_set(&pipe->event, events); +} + +static int pipe_call_open(struct modem_pipe *pipe) +{ + return pipe->api->open(pipe->data); +} + +static int pipe_call_transmit(struct modem_pipe *pipe, const uint8_t *buf, size_t size) +{ + return pipe->api->transmit(pipe->data, buf, size); +} + +static int pipe_call_receive(struct modem_pipe *pipe, uint8_t *buf, size_t size) +{ + return pipe->api->receive(pipe->data, buf, size); +} + +static int pipe_call_close(struct modem_pipe *pipe) +{ + return pipe->api->close(pipe->data); +} void modem_pipe_init(struct modem_pipe *pipe, void *data, struct modem_pipe_api *api) { @@ -19,216 +85,128 @@ void modem_pipe_init(struct modem_pipe *pipe, void *data, struct modem_pipe_api pipe->api = api; pipe->callback = NULL; pipe->user_data = NULL; - pipe->state = MODEM_PIPE_STATE_CLOSED; - pipe->receive_ready_pending = false; - pipe->transmit_idle_pending = true; - - k_mutex_init(&pipe->lock); - k_condvar_init(&pipe->condvar); + k_event_init(&pipe->event); } int modem_pipe_open(struct modem_pipe *pipe) { int ret; - k_mutex_lock(&pipe->lock, K_FOREVER); - if (pipe->state == MODEM_PIPE_STATE_OPEN) { - k_mutex_unlock(&pipe->lock); + if (pipe_test_events(pipe, PIPE_EVENT_OPENED_BIT)) { return 0; } - ret = pipe->api->open(pipe->data); + ret = pipe_call_open(pipe); if (ret < 0) { - k_mutex_unlock(&pipe->lock); return ret; } - if (pipe->state == MODEM_PIPE_STATE_OPEN) { - k_mutex_unlock(&pipe->lock); - return 0; + if (!pipe_await_events(pipe, PIPE_EVENT_OPENED_BIT)) { + return -EAGAIN; } - k_condvar_wait(&pipe->condvar, &pipe->lock, K_MSEC(10000)); - ret = (pipe->state == MODEM_PIPE_STATE_OPEN) ? 0 : -EAGAIN; - k_mutex_unlock(&pipe->lock); - return ret; + return 0; } int modem_pipe_open_async(struct modem_pipe *pipe) { - int ret; - - k_mutex_lock(&pipe->lock, K_FOREVER); - if (pipe->state == MODEM_PIPE_STATE_OPEN) { - if (pipe->callback != NULL) { - pipe->callback(pipe, MODEM_PIPE_EVENT_OPENED, pipe->user_data); - } - - k_mutex_unlock(&pipe->lock); + if (pipe_test_events(pipe, PIPE_EVENT_OPENED_BIT)) { + pipe_call_callback(pipe, MODEM_PIPE_EVENT_OPENED); return 0; } - ret = pipe->api->open(pipe->data); - k_mutex_unlock(&pipe->lock); - return ret; + return pipe_call_open(pipe); } void modem_pipe_attach(struct modem_pipe *pipe, modem_pipe_api_callback callback, void *user_data) { - k_mutex_lock(&pipe->lock, K_FOREVER); - pipe->callback = callback; - pipe->user_data = user_data; + pipe_set_callback(pipe, callback, user_data); - if (pipe->receive_ready_pending && (pipe->callback != NULL)) { - pipe->callback(pipe, MODEM_PIPE_EVENT_RECEIVE_READY, pipe->user_data); + if (pipe_test_events(pipe, PIPE_EVENT_RECEIVE_READY_BIT)) { + pipe_call_callback(pipe, MODEM_PIPE_EVENT_RECEIVE_READY); } - if (pipe->transmit_idle_pending && (pipe->callback != NULL)) { - pipe->callback(pipe, MODEM_PIPE_EVENT_TRANSMIT_IDLE, pipe->user_data); + if (pipe_test_events(pipe, PIPE_EVENT_TRANSMIT_IDLE_BIT)) { + pipe_call_callback(pipe, MODEM_PIPE_EVENT_TRANSMIT_IDLE); } - - k_mutex_unlock(&pipe->lock); } int modem_pipe_transmit(struct modem_pipe *pipe, const uint8_t *buf, size_t size) { - int ret; - - k_mutex_lock(&pipe->lock, K_FOREVER); - - if (pipe->state == MODEM_PIPE_STATE_CLOSED) { - k_mutex_unlock(&pipe->lock); + if (!pipe_test_events(pipe, PIPE_EVENT_OPENED_BIT)) { return -EPERM; } - ret = pipe->api->transmit(pipe->data, buf, size); - pipe->transmit_idle_pending = false; - k_mutex_unlock(&pipe->lock); - return ret; + pipe_clear_events(pipe, PIPE_EVENT_TRANSMIT_IDLE_BIT); + return pipe_call_transmit(pipe, buf, size); } int modem_pipe_receive(struct modem_pipe *pipe, uint8_t *buf, size_t size) { - int ret; - - k_mutex_lock(&pipe->lock, K_FOREVER); - - if (pipe->state == MODEM_PIPE_STATE_CLOSED) { - k_mutex_unlock(&pipe->lock); + if (!pipe_test_events(pipe, PIPE_EVENT_OPENED_BIT)) { return -EPERM; } - ret = pipe->api->receive(pipe->data, buf, size); - pipe->receive_ready_pending = false; - k_mutex_unlock(&pipe->lock); - return ret; + pipe_clear_events(pipe, PIPE_EVENT_RECEIVE_READY_BIT); + return pipe_call_receive(pipe, buf, size); } void modem_pipe_release(struct modem_pipe *pipe) { - k_mutex_lock(&pipe->lock, K_FOREVER); - pipe->callback = NULL; - pipe->user_data = NULL; - k_mutex_unlock(&pipe->lock); + pipe_set_callback(pipe, NULL, NULL); } int modem_pipe_close(struct modem_pipe *pipe) { int ret; - k_mutex_lock(&pipe->lock, K_FOREVER); - if (pipe->state == MODEM_PIPE_STATE_CLOSED) { - k_mutex_unlock(&pipe->lock); + if (pipe_test_events(pipe, PIPE_EVENT_CLOSED_BIT)) { return 0; } - ret = pipe->api->close(pipe->data); + ret = pipe_call_close(pipe); if (ret < 0) { - k_mutex_unlock(&pipe->lock); return ret; } - if (pipe->state == MODEM_PIPE_STATE_CLOSED) { - k_mutex_unlock(&pipe->lock); - return 0; + if (!pipe_await_events(pipe, PIPE_EVENT_CLOSED_BIT)) { + return -EAGAIN; } - k_condvar_wait(&pipe->condvar, &pipe->lock, K_MSEC(10000)); - ret = (pipe->state == MODEM_PIPE_STATE_CLOSED) ? 0 : -EAGAIN; - k_mutex_unlock(&pipe->lock); - return ret; + return 0; } int modem_pipe_close_async(struct modem_pipe *pipe) { - int ret; - - k_mutex_lock(&pipe->lock, K_FOREVER); - if (pipe->state == MODEM_PIPE_STATE_CLOSED) { - if (pipe->callback != NULL) { - pipe->callback(pipe, MODEM_PIPE_EVENT_CLOSED, pipe->user_data); - } - - k_mutex_unlock(&pipe->lock); + if (pipe_test_events(pipe, PIPE_EVENT_CLOSED_BIT)) { + pipe_call_callback(pipe, MODEM_PIPE_EVENT_CLOSED); return 0; } - ret = pipe->api->close(pipe->data); - k_mutex_unlock(&pipe->lock); - return ret; + return pipe_call_close(pipe); } void modem_pipe_notify_opened(struct modem_pipe *pipe) { - k_mutex_lock(&pipe->lock, K_FOREVER); - pipe->state = MODEM_PIPE_STATE_OPEN; - - if (pipe->callback != NULL) { - pipe->callback(pipe, MODEM_PIPE_EVENT_OPENED, pipe->user_data); - pipe->callback(pipe, MODEM_PIPE_EVENT_TRANSMIT_IDLE, pipe->user_data); - } - - k_condvar_signal(&pipe->condvar); - k_mutex_unlock(&pipe->lock); + pipe_set_events(pipe, PIPE_EVENT_OPENED_BIT | PIPE_EVENT_TRANSMIT_IDLE_BIT); + pipe_call_callback(pipe, MODEM_PIPE_EVENT_OPENED); + pipe_call_callback(pipe, MODEM_PIPE_EVENT_TRANSMIT_IDLE); } void modem_pipe_notify_closed(struct modem_pipe *pipe) { - k_mutex_lock(&pipe->lock, K_FOREVER); - pipe->state = MODEM_PIPE_STATE_CLOSED; - pipe->receive_ready_pending = false; - pipe->transmit_idle_pending = true; - - if (pipe->callback != NULL) { - pipe->callback(pipe, MODEM_PIPE_EVENT_CLOSED, pipe->user_data); - } - - k_condvar_signal(&pipe->condvar); - k_mutex_unlock(&pipe->lock); + pipe_set_events(pipe, PIPE_EVENT_TRANSMIT_IDLE_BIT | PIPE_EVENT_CLOSED_BIT); + pipe_call_callback(pipe, MODEM_PIPE_EVENT_CLOSED); } void modem_pipe_notify_receive_ready(struct modem_pipe *pipe) { - k_mutex_lock(&pipe->lock, K_FOREVER); - - pipe->receive_ready_pending = true; - - if (pipe->callback != NULL) { - pipe->callback(pipe, MODEM_PIPE_EVENT_RECEIVE_READY, pipe->user_data); - } - - k_mutex_unlock(&pipe->lock); + pipe_post_events(pipe, PIPE_EVENT_RECEIVE_READY_BIT); + pipe_call_callback(pipe, MODEM_PIPE_EVENT_RECEIVE_READY); } void modem_pipe_notify_transmit_idle(struct modem_pipe *pipe) { - k_mutex_lock(&pipe->lock, K_FOREVER); - - pipe->transmit_idle_pending = true; - - if (pipe->callback != NULL) { - pipe->callback(pipe, MODEM_PIPE_EVENT_TRANSMIT_IDLE, pipe->user_data); - } - - k_mutex_unlock(&pipe->lock); + pipe_post_events(pipe, PIPE_EVENT_TRANSMIT_IDLE_BIT); + pipe_call_callback(pipe, MODEM_PIPE_EVENT_TRANSMIT_IDLE); } From e902a08832778d0e81aa9a45e4997a049065e6d5 Mon Sep 17 00:00:00 2001 From: Declan Snyder Date: Thu, 6 Jun 2024 14:03:02 -0500 Subject: [PATCH 2613/2849] boards: frdm_rw612: Simple enablements collection A collection of simple enablements to match some of the enablement done for rd_rw612_bga as closely as possible on the frdm_rw612 board. - i2c - spi - dma - mrt - ctimer - os timer - dac - adc - trng (alread was enabled but now listed support) - watchdog Signed-off-by: Declan Snyder --- boards/nxp/frdm_rw612/doc/index.rst | 18 +++++ boards/nxp/frdm_rw612/frdm_rw612-pinctrl.dtsi | 15 ++++ boards/nxp/frdm_rw612/frdm_rw612.dts | 72 +++++++++++++++++++ boards/nxp/frdm_rw612/frdm_rw612.yaml | 10 +++ samples/drivers/adc/adc_dt/frdm_rw612.overlay | 38 ++++++++++ samples/drivers/dac/boards/frdm_rw612.overlay | 12 ++++ .../adc/adc_api/boards/frdm_rw612.overlay | 38 ++++++++++ tests/drivers/dac/dac_api/src/test_dac.c | 3 +- .../loop_transfer/boards/frdm_rw612.overlay | 7 ++ .../spi_loopback/boards/frdm_rw612.overlay | 18 +++++ 10 files changed, 230 insertions(+), 1 deletion(-) create mode 100644 samples/drivers/adc/adc_dt/frdm_rw612.overlay create mode 100644 samples/drivers/dac/boards/frdm_rw612.overlay create mode 100644 tests/drivers/adc/adc_api/boards/frdm_rw612.overlay create mode 100644 tests/drivers/dma/loop_transfer/boards/frdm_rw612.overlay create mode 100644 tests/drivers/spi/spi_loopback/boards/frdm_rw612.overlay diff --git a/boards/nxp/frdm_rw612/doc/index.rst b/boards/nxp/frdm_rw612/doc/index.rst index 9f01fbdca8918..f6aec20817682 100644 --- a/boards/nxp/frdm_rw612/doc/index.rst +++ b/boards/nxp/frdm_rw612/doc/index.rst @@ -41,6 +41,24 @@ Supported Features +-----------+------------+-----------------------------------+ | BLE | on-chip | Bluetooth | +-----------+------------+-----------------------------------+ +| DMA | on-chip | dma | ++-----------+------------+-----------------------------------+ +| SPI | on-chip | spi | ++-----------+------------+-----------------------------------+ +| I2C | on-chip | i2c | ++-----------+------------+-----------------------------------+ +| TRNG | on-chip | entropy | ++-----------+------------+-----------------------------------+ +| WWDT | on-chip | watchdog | ++-----------+------------+-----------------------------------+ +| USBOTG | on-chip | usb | ++-----------+------------+-----------------------------------+ +| CTIMER | on-chip | counter | ++-----------+------------+-----------------------------------+ +| MRT | on-chip | counter | ++-----------+------------+-----------------------------------+ +| OS_TIMER | on-chip | os timer | ++-----------+------------+-----------------------------------+ The default configuration can be found in the defconfig file: diff --git a/boards/nxp/frdm_rw612/frdm_rw612-pinctrl.dtsi b/boards/nxp/frdm_rw612/frdm_rw612-pinctrl.dtsi index 278d288bfe8ae..80a6caa12ed20 100644 --- a/boards/nxp/frdm_rw612/frdm_rw612-pinctrl.dtsi +++ b/boards/nxp/frdm_rw612/frdm_rw612-pinctrl.dtsi @@ -38,4 +38,19 @@ slew-rate = "fast"; }; }; + + pinmux_flexcomm2_i2c: pinmux_flexcomm2_i2c { + group0 { + pinmux = ; + slew-rate = "normal"; + bias-pull-up; + }; + }; + + pinmux_flexcomm1_spi: pinmux_flexcomm1_spi { + group0 { + pinmux = ; + slew-rate = "ultra"; + }; + }; }; diff --git a/boards/nxp/frdm_rw612/frdm_rw612.dts b/boards/nxp/frdm_rw612/frdm_rw612.dts index cafa12afd1dd9..083fd2edfe9fa 100644 --- a/boards/nxp/frdm_rw612/frdm_rw612.dts +++ b/boards/nxp/frdm_rw612/frdm_rw612.dts @@ -14,6 +14,9 @@ aliases { led0 = &green_led; + watchdog0 = &wwdt; + usart-0 = &flexcomm3; + i2c-0 = &flexcomm2; }; chosen { @@ -92,3 +95,72 @@ microchip,interface-type = "rmii"; }; }; + +&wwdt { + status = "okay"; +}; + +&dma0 { + status = "okay"; +}; + +&mrt0_channel0 { + status = "okay"; +}; + +&ctimer0 { + status = "okay"; +}; + +&pmu { + reset-causes-en = , + , + ; +}; + +/* OS Timer is the wakeup source for PM mode 2 */ +&os_timer { + status = "okay"; + wakeup-source; +}; + +&systick { + status = "disabled"; +}; + +&adc0 { + status = "okay"; +}; + +&dac0 { + status = "okay"; +}; + +zephyr_udc0: &usb_otg { + status = "okay"; +}; + +/* + * the default resistors on the board breaks out the MOSI/MISO + * pins to the nets labelled "UART" which go to J1 2 and 4, + * but we are using it for spi mosi and miso here. + * SCK is on J2 6 as labelled. + */ +&flexcomm1 { + compatible = "nxp,lpc-spi"; + pinctrl-0 = <&pinmux_flexcomm1_spi>; + pinctrl-names = "default"; + status = "okay"; + #address-cells = <1>; + #size-cells = <0>; +}; + +arduino_i2c: &flexcomm2 { + compatible = "nxp,lpc-i2c"; + status = "okay"; + clock-frequency = ; + #address-cells = <1>; + #size-cells = <0>; + pinctrl-0 = <&pinmux_flexcomm2_i2c>; + pinctrl-names = "default"; +}; diff --git a/boards/nxp/frdm_rw612/frdm_rw612.yaml b/boards/nxp/frdm_rw612/frdm_rw612.yaml index cbb95c517163b..813330e2b5697 100644 --- a/boards/nxp/frdm_rw612/frdm_rw612.yaml +++ b/boards/nxp/frdm_rw612/frdm_rw612.yaml @@ -16,3 +16,13 @@ ram: 960 flash: 65536 supported: - gpio + - dma + - spi + - i2c + - entropy + - usb_device + - watchdog + - counter + - hwinfo + - adc + - dac diff --git a/samples/drivers/adc/adc_dt/frdm_rw612.overlay b/samples/drivers/adc/adc_dt/frdm_rw612.overlay new file mode 100644 index 0000000000000..32098b10883ce --- /dev/null +++ b/samples/drivers/adc/adc_dt/frdm_rw612.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/dac/boards/frdm_rw612.overlay b/samples/drivers/dac/boards/frdm_rw612.overlay new file mode 100644 index 0000000000000..008f7e3b4ea21 --- /dev/null +++ b/samples/drivers/dac/boards/frdm_rw612.overlay @@ -0,0 +1,12 @@ +/ { + zephyr,user { + dac = <&dac0>; + dac-channel-id = <1>; + dac-resolution = <10>; + }; +}; + +&dac0 { + nxp,conversion-rate = "500K"; + nxp,output-voltage-range = "large"; +}; diff --git a/tests/drivers/adc/adc_api/boards/frdm_rw612.overlay b/tests/drivers/adc/adc_api/boards/frdm_rw612.overlay new file mode 100644 index 0000000000000..53596ab11c413 --- /dev/null +++ b/tests/drivers/adc/adc_api/boards/frdm_rw612.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 = ; + }; +}; diff --git a/tests/drivers/dac/dac_api/src/test_dac.c b/tests/drivers/dac/dac_api/src/test_dac.c index b63410ef53c01..8c32f756f44a6 100644 --- a/tests/drivers/dac/dac_api/src/test_dac.c +++ b/tests/drivers/dac/dac_api/src/test_dac.c @@ -89,7 +89,8 @@ #define DAC_RESOLUTION 12 #define DAC_CHANNEL_ID 0 -#elif defined(CONFIG_BOARD_RD_RW612_BGA) +#elif defined(CONFIG_BOARD_RD_RW612_BGA) || \ + defined(CONFIG_BOARD_FRDM_RW612) #define DAC_DEVICE_NODE DT_NODELABEL(dac0) #define DAC_RESOLUTION 10 diff --git a/tests/drivers/dma/loop_transfer/boards/frdm_rw612.overlay b/tests/drivers/dma/loop_transfer/boards/frdm_rw612.overlay new file mode 100644 index 0000000000000..eb0aab63133fa --- /dev/null +++ b/tests/drivers/dma/loop_transfer/boards/frdm_rw612.overlay @@ -0,0 +1,7 @@ +/* + * Copyright 2023-2024 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +tst_dma0: &dma0 { }; diff --git a/tests/drivers/spi/spi_loopback/boards/frdm_rw612.overlay b/tests/drivers/spi/spi_loopback/boards/frdm_rw612.overlay new file mode 100644 index 0000000000000..d6c22f1e15ee8 --- /dev/null +++ b/tests/drivers/spi/spi_loopback/boards/frdm_rw612.overlay @@ -0,0 +1,18 @@ +/* + * Copyright 2024 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&flexcomm1 { + slow@0 { + compatible = "test-spi-loopback-slow"; + reg = <0>; + spi-max-frequency = <500000>; + }; + fast@0 { + compatible = "test-spi-loopback-fast"; + reg = <0>; + spi-max-frequency = <16000000>; + }; +}; From da1066fa4b018bad05741667a131e9bfc7396605 Mon Sep 17 00:00:00 2001 From: Maciej Perkowski Date: Wed, 5 Jun 2024 12:52:40 +0200 Subject: [PATCH 2614/2849] twister: Add sysbuild boolean to platform definitions More complex platforms require sysbuild to use always, even for such "simple" samples like hello_world. Such platforms can have `sysbuild: true` entry in their board_name.yaml used by twister. Using such entry will tell twister, that sysbuild must always be used on a given platform. Twister is aligned to have information about need of sysbuild at instance (platform + suite) level (was only at suite level before). Instance.sysbuild is true whenever a test suite or a platform requires sysbuild. Twister pytest unit tests are aligned with changes. Signed-off-by: Maciej Perkowski --- scripts/pylib/twister/twisterlib/handlers.py | 2 +- scripts/pylib/twister/twisterlib/platform.py | 3 +++ scripts/pylib/twister/twisterlib/runner.py | 12 ++++++------ scripts/pylib/twister/twisterlib/testinstance.py | 4 +++- scripts/schemas/twister/platform-schema.yaml | 2 ++ .../pytest_integration/test_harness_pytest.py | 1 + scripts/tests/twister/test_handlers.py | 4 ++-- scripts/tests/twister/test_runner.py | 9 +++++---- scripts/tests/twister/test_testinstance.py | 2 +- 9 files changed, 24 insertions(+), 15 deletions(-) diff --git a/scripts/pylib/twister/twisterlib/handlers.py b/scripts/pylib/twister/twisterlib/handlers.py index 8655dc0d54fcc..f832425245002 100755 --- a/scripts/pylib/twister/twisterlib/handlers.py +++ b/scripts/pylib/twister/twisterlib/handlers.py @@ -153,7 +153,7 @@ 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: + if self.instance.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 diff --git a/scripts/pylib/twister/twisterlib/platform.py b/scripts/pylib/twister/twisterlib/platform.py index 44672c36a77cf..6429907928f96 100644 --- a/scripts/pylib/twister/twisterlib/platform.py +++ b/scripts/pylib/twister/twisterlib/platform.py @@ -24,6 +24,8 @@ def __init__(self): self.name = "" self.normalized_name = "" + # if sysbuild to be used by default on a given platform + self.sysbuild = False self.twister = True # if no RAM size is specified by the board, take a default of 128K self.ram = 128 @@ -56,6 +58,7 @@ def load(self, platform_file): self.name = data['identifier'] self.normalized_name = self.name.replace("/", "_") + self.sysbuild = data.get("sysbuild", False) self.twister = data.get("twister", True) # if no RAM size is specified by the board, take a default of 128K self.ram = data.get("ram", 128) diff --git a/scripts/pylib/twister/twisterlib/runner.py b/scripts/pylib/twister/twisterlib/runner.py index 6f723ca477c52..567f125cd8caf 100644 --- a/scripts/pylib/twister/twisterlib/runner.py +++ b/scripts/pylib/twister/twisterlib/runner.py @@ -335,7 +335,7 @@ def run_cmake(self, args="", filter_stages=[]): gen_defines_args = "" warning_command = 'CONFIG_COMPILER_WARNINGS_AS_ERRORS' - if self.testsuite.sysbuild: + if self.instance.sysbuild: warning_command = 'SB_' + warning_command logger.debug("Running cmake on %s for %s" % (self.source_dir, self.platform.name)) @@ -357,7 +357,7 @@ def run_cmake(self, args="", filter_stages=[]): f'-P{canonical_zephyr_base}/cmake/package_helper.cmake', ] - if self.testsuite.sysbuild and not filter_stages: + if self.instance.sysbuild and not filter_stages: logger.debug("Building %s using sysbuild" % (self.source_dir)) source_args = [ f'-S{canonical_zephyr_base}/share/sysbuild', @@ -445,7 +445,7 @@ def parse_generated(self, filter_stages=[]): if self.platform.name == "unit_testing": return {} - if self.testsuite.sysbuild and not filter_stages: + if self.instance.sysbuild and not filter_stages: # Load domain yaml to get default domain build directory domain_path = os.path.join(self.build_dir, "domains.yaml") domains = Domains.from_file(domain_path) @@ -498,7 +498,7 @@ def parse_generated(self, filter_stages=[]): filter_data.update(self.defconfig) filter_data.update(self.cmake_cache) - if self.testsuite.sysbuild and self.env.options.device_testing: + if self.instance.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. @@ -806,7 +806,7 @@ def cleanup_device_testing_artifacts(self): files_to_keep = self._get_binaries() files_to_keep.append(os.path.join('zephyr', 'runners.yaml')) - if self.testsuite.sysbuild: + if self.instance.sysbuild: files_to_keep.append('domains.yaml') for domain in self.instance.domains.get_domains(): files_to_keep += self._get_artifact_allow_list_for_domain(domain.name) @@ -846,7 +846,7 @@ def _get_binaries(self) -> List[str]: # Get binaries for a single-domain build binaries += self._get_binaries_from_runners() # Get binaries in the case of a multiple-domain build - if self.testsuite.sysbuild: + if self.instance.sysbuild: for domain in self.instance.domains.get_domains(): binaries += self._get_binaries_from_runners(domain.name) diff --git a/scripts/pylib/twister/twisterlib/testinstance.py b/scripts/pylib/twister/twisterlib/testinstance.py index b7a46fd5008ac..3540b3e58f201 100644 --- a/scripts/pylib/twister/twisterlib/testinstance.py +++ b/scripts/pylib/twister/twisterlib/testinstance.py @@ -67,6 +67,8 @@ def __init__(self, testsuite, platform, outdir): self.build_dir = os.path.join(outdir, platform.normalized_name, source_dir_rel, testsuite.name) self.run_id = self._get_run_id() self.domains = None + # Instance need to use sysbuild if a given suite or a platform requires it + self.sysbuild = testsuite.sysbuild or platform.sysbuild self.run = False self.testcases: list[TestCase] = [] @@ -335,7 +337,7 @@ def calculate_sizes(self, from_buildlog: bool = False, generate_warning: bool = def get_elf_file(self) -> str: - if self.testsuite.sysbuild: + if self.sysbuild: build_dir = self.domains.get_default_domain().build_dir else: build_dir = self.build_dir diff --git a/scripts/schemas/twister/platform-schema.yaml b/scripts/schemas/twister/platform-schema.yaml index dd9dfe10dafea..c651f83c3e364 100644 --- a/scripts/schemas/twister/platform-schema.yaml +++ b/scripts/schemas/twister/platform-schema.yaml @@ -66,6 +66,8 @@ mapping: type: seq seq: - type: str + "sysbuild": + type: bool "env": type: seq seq: diff --git a/scripts/tests/twister/pytest_integration/test_harness_pytest.py b/scripts/tests/twister/pytest_integration/test_harness_pytest.py index 898f7e5ababde..86628d40ce80c 100644 --- a/scripts/tests/twister/pytest_integration/test_harness_pytest.py +++ b/scripts/tests/twister/pytest_integration/test_harness_pytest.py @@ -19,6 +19,7 @@ def testinstance() -> TestInstance: testsuite = TestSuite('.', 'samples/hello', 'unit.test') testsuite.harness_config = {} testsuite.ignore_faults = False + testsuite.sysbuild = False platform = Platform() testinstance = TestInstance(testsuite, platform, 'outdir') diff --git a/scripts/tests/twister/test_handlers.py b/scripts/tests/twister/test_handlers.py index 79825c4784639..9ae333389fa06 100644 --- a/scripts/tests/twister/test_handlers.py +++ b/scripts/tests/twister/test_handlers.py @@ -445,7 +445,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 + handler.instance.sysbuild = False handler.platform = SimpleNamespace() handler.platform.resc = "file.resc" handler.platform.uart = "uart" @@ -1469,7 +1469,7 @@ def test_qemuhandler_get_default_domain_build_dir( from_file_mock = mock.Mock(return_value=domains_mock) handler = QEMUHandler(mocked_instance, 'build') - handler.instance.testsuite.sysbuild = self_sysbuild + handler.instance.sysbuild = self_sysbuild handler.build_dir = self_build_dir with mock.patch('domains.Domains.from_file', from_file_mock): diff --git a/scripts/tests/twister/test_runner.py b/scripts/tests/twister/test_runner.py index 88ed43a87fef8..e1e12242108ef 100644 --- a/scripts/tests/twister/test_runner.py +++ b/scripts/tests/twister/test_runner.py @@ -42,6 +42,7 @@ def mocked_instance(tmp_path): testsuite.source_dir: str = '' instance.testsuite = testsuite platform = mock.Mock() + platform.sysbuild = False platform.binaries: List[str] = [] instance.platform = platform build_dir = tmp_path / 'build_dir' @@ -131,7 +132,7 @@ def test_if_default_binaries_are_taken_properly(project_builder: ProjectBuilder) os.path.join('zephyr', 'zephyr.elf'), os.path.join('zephyr', 'zephyr.exe'), ] - project_builder.testsuite.sysbuild = False + project_builder.instance.sysbuild = False binaries = project_builder._get_binaries() assert sorted(binaries) == sorted(default_binaries) @@ -139,7 +140,7 @@ def test_if_default_binaries_are_taken_properly(project_builder: ProjectBuilder) def test_if_binaries_from_platform_are_taken_properly(project_builder: ProjectBuilder): platform_binaries = ['spi_image.bin'] project_builder.platform.binaries = platform_binaries - project_builder.testsuite.sysbuild = False + project_builder.instance.sysbuild = False platform_binaries_expected = [os.path.join('zephyr', bin) for bin in platform_binaries] binaries = project_builder._get_binaries() assert sorted(binaries) == sorted(platform_binaries_expected) @@ -698,7 +699,6 @@ def mock_pickle(datafile): return mock.Mock() testsuite_mock = mock.Mock() - testsuite_mock.sysbuild = 'sysbuild' if sysbuild else None testsuite_mock.name = 'dummy.testsuite.name' testsuite_mock.filter = testsuite_filter platform_mock = mock.Mock() @@ -710,6 +710,7 @@ def mock_pickle(datafile): fb = FilterBuilder(testsuite_mock, platform_mock, source_dir, build_dir, mocked_jobserver) instance_mock = mock.Mock() + instance_mock.sysbuild = 'sysbuild' if sysbuild else None fb.instance = instance_mock fb.env = mock.Mock() fb.env.options = mock.Mock() @@ -1675,7 +1676,7 @@ def test_projectbuilder_cleanup_device_testing_artifacts( bins = [os.path.join('zephyr', 'file.bin')] instance_mock = mock.Mock() - instance_mock.testsuite.sysbuild = False + instance_mock.sysbuild = False build_dir = os.path.join('build', 'dir') instance_mock.build_dir = build_dir env_mock = mock.Mock() diff --git a/scripts/tests/twister/test_testinstance.py b/scripts/tests/twister/test_testinstance.py index 4f820532aeaf7..560923173b094 100644 --- a/scripts/tests/twister/test_testinstance.py +++ b/scripts/tests/twister/test_testinstance.py @@ -597,7 +597,7 @@ def test_testinstance_get_elf_file(caplog, tmp_path, testinstance, sysbuild, exp sysbuild_elf2 = zephyr_dir / 'dummy2.elf' sysbuild_elf2.write_bytes(b'0') - testinstance.testsuite.sysbuild = sysbuild + testinstance.sysbuild = sysbuild testinstance.domains = mock.Mock( get_default_domain=mock.Mock( return_value=mock.Mock( From 3137829e72e90b96fdf9fb53742ea1476cadbf0e Mon Sep 17 00:00:00 2001 From: Maciej Perkowski Date: Wed, 5 Jun 2024 14:33:49 +0200 Subject: [PATCH 2615/2849] boards: nrf: Update nrf54h and nrf54l yamls to use sysbuild in twister Nrf54h's and nrf54l's targets are the first targets complex enough that a sysbuild must be used on every build for them. This information is reflected in their yamls. These entries tell twister to always use sysbuild for those targets. Signed-off-by: Maciej Perkowski --- boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpuapp.yaml | 1 + boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpuppr.yaml | 1 + boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpuppr_xip.yaml | 1 + boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpurad.yaml | 1 + boards/nordic/nrf54l15pdk/nrf54l15pdk_nrf54l15_cpuapp.yaml | 1 + boards/nordic/nrf54l15pdk/nrf54l15pdk_nrf54l15_cpuflpr.yaml | 1 + boards/nordic/nrf54l15pdk/nrf54l15pdk_nrf54l15_cpuflpr_xip.yaml | 1 + 7 files changed, 7 insertions(+) diff --git a/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpuapp.yaml b/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpuapp.yaml index 560a4cfa294bc..e07bbee7d14a9 100644 --- a/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpuapp.yaml +++ b/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpuapp.yaml @@ -9,6 +9,7 @@ toolchain: - gnuarmemb - xtools - zephyr +sysbuild: true ram: 256 flash: 296 supported: diff --git a/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpuppr.yaml b/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpuppr.yaml index af81ae6e28edf..8bd648416b60e 100644 --- a/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpuppr.yaml +++ b/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpuppr.yaml @@ -7,6 +7,7 @@ type: mcu arch: riscv toolchain: - zephyr +sysbuild: true ram: 62 flash: 62 supported: diff --git a/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpuppr_xip.yaml b/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpuppr_xip.yaml index d0b1f4481190d..8cfc343647ff9 100644 --- a/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpuppr_xip.yaml +++ b/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpuppr_xip.yaml @@ -7,6 +7,7 @@ type: mcu arch: riscv toolchain: - zephyr +sysbuild: true ram: 62 flash: 64 supported: diff --git a/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpurad.yaml b/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpurad.yaml index e36f2e21ffea6..36c0fc01dce13 100644 --- a/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpurad.yaml +++ b/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpurad.yaml @@ -9,6 +9,7 @@ toolchain: - gnuarmemb - xtools - zephyr +sysbuild: true ram: 192 flash: 256 supported: diff --git a/boards/nordic/nrf54l15pdk/nrf54l15pdk_nrf54l15_cpuapp.yaml b/boards/nordic/nrf54l15pdk/nrf54l15pdk_nrf54l15_cpuapp.yaml index fd563bc6c1e31..9213c49fdd7ba 100644 --- a/boards/nordic/nrf54l15pdk/nrf54l15pdk_nrf54l15_cpuapp.yaml +++ b/boards/nordic/nrf54l15pdk/nrf54l15pdk_nrf54l15_cpuapp.yaml @@ -9,6 +9,7 @@ toolchain: - gnuarmemb - xtools - zephyr +sysbuild: true ram: 188 flash: 324 supported: diff --git a/boards/nordic/nrf54l15pdk/nrf54l15pdk_nrf54l15_cpuflpr.yaml b/boards/nordic/nrf54l15pdk/nrf54l15pdk_nrf54l15_cpuflpr.yaml index f05b6b74a8bec..6e8789aeab79f 100644 --- a/boards/nordic/nrf54l15pdk/nrf54l15pdk_nrf54l15_cpuflpr.yaml +++ b/boards/nordic/nrf54l15pdk/nrf54l15pdk_nrf54l15_cpuflpr.yaml @@ -7,6 +7,7 @@ type: mcu arch: riscv toolchain: - zephyr +sysbuild: true ram: 96 flash: 96 supported: diff --git a/boards/nordic/nrf54l15pdk/nrf54l15pdk_nrf54l15_cpuflpr_xip.yaml b/boards/nordic/nrf54l15pdk/nrf54l15pdk_nrf54l15_cpuflpr_xip.yaml index 0b9d635fb8dae..156cbb6f8b417 100644 --- a/boards/nordic/nrf54l15pdk/nrf54l15pdk_nrf54l15_cpuflpr_xip.yaml +++ b/boards/nordic/nrf54l15pdk/nrf54l15pdk_nrf54l15_cpuflpr_xip.yaml @@ -7,6 +7,7 @@ type: mcu arch: riscv toolchain: - zephyr +sysbuild: true ram: 68 flash: 96 supported: From 5121de6e73731f6fbdb25ec5fef7e468bbfe5ef7 Mon Sep 17 00:00:00 2001 From: Yong Cong Sin Date: Fri, 31 May 2024 18:01:06 +0800 Subject: [PATCH 2616/2849] arch: introduce `arch_stack_walk()` An architecture can indicate that it has an implementation for the `arch_stack_walk()` function by selecting `ARCH_HAS_STACKWALK`. Set the default value of `EXCEPTION_STACK_TRACE_MAX_FRAMES` to `ARCH_STACKWALK_MAX_FRAMES` if the latter is available. Signed-off-by: Yong Cong Sin --- arch/Kconfig | 13 +++++++++++++ include/zephyr/arch/arch_interface.h | 27 +++++++++++++++++++++++++++ subsys/debug/Kconfig | 1 + 3 files changed, 41 insertions(+) diff --git a/arch/Kconfig b/arch/Kconfig index 15d8fc0653bb4..12c1aa8c7daf5 100644 --- a/arch/Kconfig +++ b/arch/Kconfig @@ -409,6 +409,14 @@ config FRAME_POINTER Select Y here to gain precise stack traces at the expense of slightly increased size and decreased speed. +config ARCH_STACKWALK_MAX_FRAMES + int "Max depth for stack walk function" + default 8 + depends on ARCH_HAS_STACKWALK + help + Depending on implementation, this can place a hard limit on the depths of the stack + for the stack walk function to examine. + menu "Interrupt Configuration" config ISR_TABLES_LOCAL_DECLARATION_SUPPORTED @@ -654,6 +662,11 @@ config ARCH_HAS_EXTRA_EXCEPTION_INFO config ARCH_HAS_GDBSTUB bool +config ARCH_HAS_STACKWALK + bool + help + This is selected when the architecture implemented the arch_stack_walk() API. + config ARCH_HAS_COHERENCE bool help diff --git a/include/zephyr/arch/arch_interface.h b/include/zephyr/arch/arch_interface.h index d7c33e511ce50..ae51b4a375999 100644 --- a/include/zephyr/arch/arch_interface.h +++ b/include/zephyr/arch/arch_interface.h @@ -1251,6 +1251,33 @@ bool arch_pcie_msi_vector_connect(msi_vector_t *vector, */ void arch_spin_relax(void); +/** + * stack_trace_callback_fn - Callback for @ref arch_stack_walk + * @param cookie Caller supplied pointer handed back by @ref arch_stack_walk + * @param addr The stack entry address to consume + * + * @return True, if the entry was consumed or skipped. False, if there is no space left to store + */ +typedef bool (*stack_trace_callback_fn)(void *cookie, unsigned long addr); + +/** + * @brief Architecture-specific function to walk the stack + * + * @param callback_fn Callback which is invoked by the architecture code for each entry. + * @param cookie Caller supplied pointer which is handed back to @a callback_fn + * @param thread Pointer to a k_thread struct, can be NULL + * @param esf Pointer to an arch_esf struct, can be NULL + * + * ============ ======= ============================================ + * thread esf + * ============ ======= ============================================ + * thread NULL Stack trace from thread (can be _current) + * thread esf Stack trace starting on esf + * ============ ======= ============================================ + */ +void arch_stack_walk(stack_trace_callback_fn callback_fn, void *cookie, + const struct k_thread *thread, const struct arch_esf *esf); + #ifdef __cplusplus } #endif /* __cplusplus */ diff --git a/subsys/debug/Kconfig b/subsys/debug/Kconfig index d8922ce99eab7..eb4313d2374d6 100644 --- a/subsys/debug/Kconfig +++ b/subsys/debug/Kconfig @@ -382,6 +382,7 @@ config EXCEPTION_STACK_TRACE config EXCEPTION_STACK_TRACE_MAX_FRAMES int "Configures the depth of stack trace" + default ARCH_STACKWALK_MAX_FRAMES if ARCH_HAS_STACKWALK default 8 depends on EXCEPTION_STACK_TRACE help From 726fefd12c660158715d6e8b1d34dcb63cf1d08a Mon Sep 17 00:00:00 2001 From: Yong Cong Sin Date: Fri, 31 May 2024 21:24:54 +0800 Subject: [PATCH 2617/2849] arch: riscv: stacktrace: implement `arch_stack_walk()` Created the `arch_stack_walk()` function out from the original `z_riscv_unwind_stack()`, it's been updated to support unwinding any thread. Updated the stack_unwind test case accordingly. Increased the delay in `test_fatal_on_smp`, to wait for the the fatal thread to be terminated, as stacktrace can take a bit more time. Doubled the kernel/smp testcase timeout from 60 (default) to 120s, as some of the tests can take a little bit more than 60s to finish. Signed-off-by: Yong Cong Sin --- arch/Kconfig | 1 + arch/riscv/core/fatal.c | 6 +- arch/riscv/core/stacktrace.c | 239 +++++++++++++------ tests/arch/common/stack_unwind/testcase.yaml | 8 +- tests/kernel/smp/src/main.c | 2 +- tests/kernel/smp/testcase.yaml | 2 + 6 files changed, 179 insertions(+), 79 deletions(-) diff --git a/arch/Kconfig b/arch/Kconfig index 12c1aa8c7daf5..b597236699066 100644 --- a/arch/Kconfig +++ b/arch/Kconfig @@ -113,6 +113,7 @@ config RISCV select ARCH_SUPPORTS_ROM_START if !SOC_SERIES_ESP32C3 select ARCH_HAS_CODE_DATA_RELOCATION select ARCH_HAS_THREAD_LOCAL_STORAGE + select ARCH_HAS_STACKWALK select IRQ_OFFLOAD_NESTED if IRQ_OFFLOAD select USE_SWITCH_SUPPORTED select USE_SWITCH diff --git a/arch/riscv/core/fatal.c b/arch/riscv/core/fatal.c index d6dd4bc38869a..ea8fa2eb95ecf 100644 --- a/arch/riscv/core/fatal.c +++ b/arch/riscv/core/fatal.c @@ -30,7 +30,7 @@ static const struct z_exc_handle exceptions[] = { #endif /* Stack trace function */ -void z_riscv_unwind_stack(const struct arch_esf *esf); +void z_riscv_unwind_stack(const struct arch_esf *esf, const _callee_saved_t *csf); uintptr_t z_riscv_get_sp_before_exc(const struct arch_esf *esf) { @@ -107,8 +107,8 @@ FUNC_NORETURN void z_riscv_fatal_error_csf(unsigned int reason, const struct arc LOG_ERR(""); } - if (IS_ENABLED(CONFIG_EXCEPTION_STACK_TRACE) && (esf != NULL)) { - z_riscv_unwind_stack(esf); + if (IS_ENABLED(CONFIG_EXCEPTION_STACK_TRACE)) { + z_riscv_unwind_stack(esf, csf); } #endif /* CONFIG_EXCEPTION_DEBUG */ diff --git a/arch/riscv/core/stacktrace.c b/arch/riscv/core/stacktrace.c index cda6748c36371..7a684a9bae9e7 100644 --- a/arch/riscv/core/stacktrace.c +++ b/arch/riscv/core/stacktrace.c @@ -14,68 +14,95 @@ LOG_MODULE_DECLARE(os, CONFIG_KERNEL_LOG_LEVEL); uintptr_t z_riscv_get_sp_before_exc(const struct arch_esf *esf); -#if __riscv_xlen == 32 - #define PR_REG "%08" PRIxPTR -#elif __riscv_xlen == 64 - #define PR_REG "%016" PRIxPTR -#endif - -#define MAX_STACK_FRAMES CONFIG_EXCEPTION_STACK_TRACE_MAX_FRAMES +#define MAX_STACK_FRAMES \ + MAX(CONFIG_EXCEPTION_STACK_TRACE_MAX_FRAMES, CONFIG_ARCH_STACKWALK_MAX_FRAMES) struct stackframe { uintptr_t fp; uintptr_t ra; }; -#ifdef CONFIG_FRAME_POINTER -#define SFP_FMT "fp: " -#else -#define SFP_FMT "sp: " -#endif +typedef bool (*stack_verify_fn)(uintptr_t, const struct k_thread *const, const struct arch_esf *); -#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 inline bool in_irq_stack_bound(uintptr_t addr, uint8_t cpu_id) +{ + uintptr_t start, end; -static bool in_stack_bound(uintptr_t addr, const struct arch_esf *esf) + start = (uintptr_t)K_KERNEL_STACK_BUFFER(z_interrupt_stacks[cpu_id]); + end = start + CONFIG_ISR_STACK_SIZE; + + return (addr >= start) && (addr < end); +} + +static inline bool in_kernel_thread_stack_bound(uintptr_t addr, const struct k_thread *const thread) +{ + uintptr_t start, end; + + start = thread->stack_info.start; + end = Z_STACK_PTR_ALIGN(thread->stack_info.start + thread->stack_info.size); + + return (addr >= start) && (addr < end); +} + +#ifdef CONFIG_USERSPACE +static inline bool in_user_thread_stack_bound(uintptr_t addr, const struct k_thread *const thread) { -#ifdef CONFIG_THREAD_STACK_INFO uintptr_t start, end; + /* See: zephyr/include/zephyr/arch/riscv/arch.h */ + if (IS_ENABLED(CONFIG_PMP_POWER_OF_TWO_ALIGNMENT)) { + start = thread->arch.priv_stack_start - CONFIG_PRIVILEGED_STACK_SIZE; + end = thread->arch.priv_stack_start; + } else { + start = thread->stack_info.start - CONFIG_PRIVILEGED_STACK_SIZE; + end = thread->stack_info.start; + } + + return (addr >= start) && (addr < end); +} +#endif /* CONFIG_USERSPACE */ + +static bool in_fatal_stack_bound(uintptr_t addr, const struct k_thread *const thread, + const struct arch_esf *esf) +{ + ARG_UNUSED(thread); + + if (!IS_ALIGNED(addr, sizeof(uintptr_t))) { + return false; + } + if (_current == NULL || arch_is_in_isr()) { /* We were servicing an interrupt */ uint8_t cpu_id = IS_ENABLED(CONFIG_SMP) ? arch_curr_cpu()->id : 0U; - start = (uintptr_t)K_KERNEL_STACK_BUFFER(z_interrupt_stacks[cpu_id]); - end = start + CONFIG_ISR_STACK_SIZE; + return in_irq_stack_bound(addr, cpu_id); + } #ifdef CONFIG_USERSPACE - } else if (((esf->mstatus & MSTATUS_MPP) == PRV_U) && - ((_current->base.user_options & K_USER) != 0)) { - /* See: zephyr/include/zephyr/arch/riscv/arch.h */ - if (IS_ENABLED(CONFIG_PMP_POWER_OF_TWO_ALIGNMENT)) { - start = _current->arch.priv_stack_start - CONFIG_PRIVILEGED_STACK_SIZE; - end = _current->arch.priv_stack_start; - } else { - start = _current->stack_info.start - CONFIG_PRIVILEGED_STACK_SIZE; - end = _current->stack_info.start; - } -#endif /* CONFIG_USERSPACE */ - } else { - start = _current->stack_info.start; - end = Z_STACK_PTR_ALIGN(_current->stack_info.start + _current->stack_info.size); + if ((esf != NULL) && ((esf->mstatus & MSTATUS_MPP) == PRV_U) && + ((_current->base.user_options & K_USER) != 0)) { + return in_user_thread_stack_bound(addr, _current); } +#endif /* CONFIG_USERSPACE */ - return (addr >= start) && (addr < end); -#else - ARG_UNUSED(addr); + return in_kernel_thread_stack_bound(addr, _current); +} + +static bool in_stack_bound(uintptr_t addr, const struct k_thread *const thread, + const struct arch_esf *esf) +{ ARG_UNUSED(esf); - return true; -#endif /* CONFIG_THREAD_STACK_INFO */ + + if (!IS_ALIGNED(addr, sizeof(uintptr_t))) { + return false; + } + +#ifdef CONFIG_USERSPACE + if ((thread->base.user_options & K_USER) != 0) { + return in_user_thread_stack_bound(addr, thread); + } +#endif /* CONFIG_USERSPACE */ + + return in_kernel_thread_stack_bound(addr, thread); } static inline bool in_text_region(uintptr_t addr) @@ -86,61 +113,131 @@ static inline bool in_text_region(uintptr_t addr) } #ifdef CONFIG_FRAME_POINTER -void z_riscv_unwind_stack(const struct arch_esf *esf) +static void walk_stackframe(stack_trace_callback_fn cb, void *cookie, const struct k_thread *thread, + const struct arch_esf *esf, stack_verify_fn vrfy, + const _callee_saved_t *csf) { - uintptr_t fp = esf->s0; + uintptr_t fp, last_fp = 0; uintptr_t ra; struct stackframe *frame; - LOG_ERR("call trace:"); + if (esf != NULL) { + /* Unwind the provided exception stack frame */ + fp = esf->s0; + ra = esf->mepc; + } else if ((csf == NULL) || (csf == &_current->callee_saved)) { + /* Unwind current thread (default case when nothing is provided ) */ + fp = (uintptr_t)__builtin_frame_address(0); + ra = (uintptr_t)walk_stackframe; + thread = _current; + } else { + /* Unwind the provided thread */ + fp = csf->s0; + ra = csf->ra; + } - for (int i = 0; (i < MAX_STACK_FRAMES) && (fp != 0U) && in_stack_bound(fp, esf);) { - frame = (struct stackframe *)fp - 1; - ra = frame->ra; + for (int i = 0; (i < MAX_STACK_FRAMES) && vrfy(fp, thread, esf) && (fp > last_fp);) { if (in_text_region(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); + if (!cb(cookie, ra)) { + break; + } /* * Increment the iterator only if `ra` is within the text region to get the * most out of it */ i++; } + last_fp = fp; + /* Unwind to the previous frame */ + frame = (struct stackframe *)fp - 1; + ra = frame->ra; fp = frame->fp; } - - LOG_ERR(""); } -#else /* !CONFIG_FRAME_POINTER */ -void z_riscv_unwind_stack(const struct arch_esf *esf) +#else /* !CONFIG_FRAME_POINTER */ +register uintptr_t current_stack_pointer __asm__("sp"); +static void walk_stackframe(stack_trace_callback_fn cb, void *cookie, const struct k_thread *thread, + const struct arch_esf *esf, stack_verify_fn vrfy, + const _callee_saved_t *csf) { - uintptr_t sp = z_riscv_get_sp_before_exc(esf); + uintptr_t sp; uintptr_t ra; - uintptr_t *ksp = (uintptr_t *)sp; + uintptr_t *ksp, last_ksp = 0; + + if (esf != NULL) { + /* Unwind the provided exception stack frame */ + sp = z_riscv_get_sp_before_exc(esf); + ra = esf->mepc; + } else if ((csf == NULL) || (csf == &_current->callee_saved)) { + /* Unwind current thread (default case when nothing is provided ) */ + sp = current_stack_pointer; + ra = (uintptr_t)walk_stackframe; + thread = _current; + } else { + /* Unwind the provided thread */ + sp = csf->sp; + ra = csf->ra; - LOG_ERR("call trace:"); + } - for (int i = 0; (i < MAX_STACK_FRAMES) && ((uintptr_t)ksp != 0U) && - in_stack_bound((uintptr_t)ksp, esf); - ksp++) { - ra = *ksp; + ksp = (uintptr_t *)sp; + for (int i = 0; (i < MAX_STACK_FRAMES) && vrfy((uintptr_t)ksp, thread, esf) && + ((uintptr_t)ksp > last_ksp);) { if (in_text_region(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); + if (!cb(cookie, ra)) { + break; + } /* * Increment the iterator only if `ra` is within the text region to get the * most out of it */ i++; } + last_ksp = (uintptr_t)ksp; + /* Unwind to the previous frame */ + ra = ((struct arch_esf *)ksp++)->ra; } +} +#endif /* CONFIG_FRAME_POINTER */ + +void arch_stack_walk(stack_trace_callback_fn callback_fn, void *cookie, + const struct k_thread *thread, const struct arch_esf *esf) +{ + walk_stackframe(callback_fn, cookie, thread, esf, in_stack_bound, + thread != NULL ? &thread->callee_saved : NULL); +} + +#if __riscv_xlen == 32 +#define PR_REG "%08" PRIxPTR +#elif __riscv_xlen == 64 +#define PR_REG "%016" PRIxPTR +#endif + +#ifdef CONFIG_EXCEPTION_STACK_TRACE_SYMTAB +#define LOG_STACK_TRACE(idx, ra, name, offset) \ + LOG_ERR(" %2d: ra: " PR_REG " [%s+0x%x]", idx, ra, name, offset) +#else +#define LOG_STACK_TRACE(idx, ra, name, offset) LOG_ERR(" %2d: ra: " PR_REG, idx, ra) +#endif /* CONFIG_EXCEPTION_STACK_TRACE_SYMTAB */ +static bool print_trace_address(void *arg, unsigned long ra) +{ + int *i = arg; +#ifdef CONFIG_EXCEPTION_STACK_TRACE_SYMTAB + uint32_t offset = 0; + const char *name = symtab_find_symbol_name(ra, &offset); +#endif + + LOG_STACK_TRACE((*i)++, ra, name, offset); + + return true; +} + +void z_riscv_unwind_stack(const struct arch_esf *esf, const _callee_saved_t *csf) +{ + int i = 0; + + LOG_ERR("call trace:"); + walk_stackframe(print_trace_address, &i, NULL, esf, in_fatal_stack_bound, csf); LOG_ERR(""); } -#endif /* CONFIG_FRAME_POINTER */ diff --git a/tests/arch/common/stack_unwind/testcase.yaml b/tests/arch/common/stack_unwind/testcase.yaml index 1699adeae5d37..b6fbd0f7ed8bb 100644 --- a/tests/arch/common/stack_unwind/testcase.yaml +++ b/tests/arch/common/stack_unwind/testcase.yaml @@ -15,8 +15,8 @@ tests: type: multi_line regex: - "E: call trace:" - - "E: 0: fp: \\w+ ra: \\w+" - - "E: 1: fp: \\w+ ra: \\w+" + - "E: 0: ra: \\w+" + - "E: 1: ra: \\w+" arch.common.stack_unwind.riscv_sp: arch_allow: riscv integration_platforms: @@ -26,8 +26,8 @@ tests: type: multi_line regex: - "E: call trace:" - - "E: 0: sp: \\w+ ra: \\w+" - - "E: 1: sp: \\w+ ra: \\w+" + - "E: 0: ra: \\w+" + - "E: 1: ra: \\w+" arch.common.stack_unwind.x86: arch_allow: x86 extra_configs: diff --git a/tests/kernel/smp/src/main.c b/tests/kernel/smp/src/main.c index 7f556793e670c..de17be4f1db04 100644 --- a/tests/kernel/smp/src/main.c +++ b/tests/kernel/smp/src/main.c @@ -802,7 +802,7 @@ ZTEST(smp, test_fatal_on_smp) K_PRIO_PREEMPT(2), 0, K_NO_WAIT); /* hold cpu and wait for thread trigger exception and being terminated */ - k_busy_wait(2 * DELAY_US); + k_busy_wait(5 * DELAY_US); /* Verify that child thread is no longer running. We can't simply use k_thread_join here * as we don't want to introduce reschedule point here. diff --git a/tests/kernel/smp/testcase.yaml b/tests/kernel/smp/testcase.yaml index db509d300e32f..6138c7c262763 100644 --- a/tests/kernel/smp/testcase.yaml +++ b/tests/kernel/smp/testcase.yaml @@ -1,3 +1,5 @@ +common: + timeout: 120 tests: kernel.multiprocessing.smp: tags: From 61a0f9f1c0a9c99d7ac3faee656efa48c4383d7e Mon Sep 17 00:00:00 2001 From: Yong Cong Sin Date: Sat, 8 Jun 2024 13:12:54 +0800 Subject: [PATCH 2618/2849] arch: riscv: stop printing symbol name at mepc Now that the unwind starts from mepc already, the symbol name at the mepc reg is kinda redundant, so just remove it. Signed-off-by: Yong Cong Sin --- arch/riscv/core/fatal.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/arch/riscv/core/fatal.c b/arch/riscv/core/fatal.c index ea8fa2eb95ecf..779d23905cab0 100644 --- a/arch/riscv/core/fatal.c +++ b/arch/riscv/core/fatal.c @@ -4,7 +4,6 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include #include #include #include @@ -80,14 +79,7 @@ FUNC_NORETURN void z_riscv_fatal_error_csf(unsigned int reason, const struct arc #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 b98a60773b3f2a592b9a1dea4899ec26ca2ab4fb Mon Sep 17 00:00:00 2001 From: Yong Cong Sin Date: Tue, 11 Jun 2024 14:51:02 +0800 Subject: [PATCH 2619/2849] shell: kernel: add command to unwind a thread Add a shell command to unwind a thread using its thread id. uart:~$ kernel threads Scheduler: 11 since last call Threads: *0x80017138 shell_uart options: 0x0, priority: 14 timeout: 0 state: queued, entry: 0x800029ac stack size 3072, unused 1316, usage 1756 / 3072 (57 %) 0x80017ca8 sysworkq options: 0x1, priority: -1 timeout: 0 state: pending, entry: 0x80006842 stack size 1024, unused 644, usage 380 / 1024 (37 %) 0x800177e0 idle options: 0x1, priority: 15 timeout: 0 state: , entry: 0x800065ae stack size 512, unused 180, usage 332 / 512 (64 %) 0x80017950 main options: 0x1, priority: 0 timeout: 13 state: suspended, entry: 0x80006326 stack size 4096, unused 3604, usage 492 / 4096 (12 %) uart:~$ kernel unwind 0x80017ca8 Unwinding 0x80017ca8 sysworkq ra: 0x80007114 [z_swap+0x58] ra: 0x80007ae8 [z_sched_wait+0x10] ra: 0x8000689a [work_queue_main+0x58] ra: 0x800006de [z_thread_entry+0x2e] Signed-off-by: Yong Cong Sin --- subsys/shell/modules/kernel_service.c | 64 +++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/subsys/shell/modules/kernel_service.c b/subsys/shell/modules/kernel_service.c index 992a83f65b51c..246120f923420 100644 --- a/subsys/shell/modules/kernel_service.c +++ b/subsys/shell/modules/kernel_service.c @@ -24,6 +24,7 @@ #if defined(CONFIG_LOG_RUNTIME_FILTERING) #include #endif +#include #if defined(CONFIG_THREAD_MAX_NAME_LEN) #define THREAD_MAX_NAM_LEN CONFIG_THREAD_MAX_NAME_LEN @@ -203,6 +204,66 @@ static int cmd_kernel_threads(const struct shell *sh, return 0; } +#if defined(CONFIG_ARCH_HAS_STACKWALK) + +static bool print_trace_address(void *arg, unsigned long ra) +{ + const struct shell *sh = arg; +#ifdef CONFIG_SYMTAB + uint32_t offset = 0; + const char *name = symtab_find_symbol_name(ra, &offset); + + shell_print(sh, "ra: %p [%s+0x%x]", (void *)ra, name, offset); +#else + shell_print(sh, "ra: %p", (void *)ra); +#endif + + return true; +} + +struct unwind_entry { + const struct k_thread *const thread; + bool valid; +}; + +static void is_valid_thread(const struct k_thread *cthread, void *user_data) +{ + struct unwind_entry *entry = user_data; + + if (cthread == entry->thread) { + entry->valid = true; + } +} + +static int cmd_kernel_unwind(const struct shell *sh, size_t argc, char **argv) +{ + struct k_thread *thread; + + if (argc == 1) { + thread = _current; + } else { + thread = UINT_TO_POINTER(strtoll(argv[1], NULL, 16)); + struct unwind_entry entry = { + .thread = thread, + .valid = false, + }; + + k_thread_foreach_unlocked(is_valid_thread, &entry); + + if (!entry.valid) { + shell_error(sh, "Invalid thread id %p", (void *)thread); + return -EINVAL; + } + } + shell_print(sh, "Unwinding %p %s", (void *)thread, thread->name); + + arch_stack_walk(print_trace_address, (void *)sh, thread, NULL); + + return 0; +} + +#endif /* CONFIG_ARCH_HAS_STACKWALK */ + static void shell_stack_dump(const struct k_thread *thread, void *user_data) { const struct shell *sh = (const struct shell *)user_data; @@ -397,6 +458,9 @@ SHELL_STATIC_SUBCMD_SET_CREATE(sub_kernel, defined(CONFIG_THREAD_MONITOR) SHELL_CMD(stacks, NULL, "List threads stack usage.", cmd_kernel_stacks), SHELL_CMD(threads, NULL, "List kernel threads.", cmd_kernel_threads), +#if defined(CONFIG_ARCH_HAS_STACKWALK) + SHELL_CMD_ARG(unwind, NULL, "Unwind a thread.", cmd_kernel_unwind, 1, 1), +#endif /* CONFIG_ARCH_HAS_STACKWALK */ #endif #if defined(CONFIG_SYS_HEAP_RUNTIME_STATS) && (K_HEAP_MEM_POOL_SIZE > 0) SHELL_CMD(heap, NULL, "System heap usage statistics.", cmd_kernel_heap), From 7bf47f8e8fd32fbec2e7466dbf93a2b2e879268b Mon Sep 17 00:00:00 2001 From: Marek Matej Date: Sat, 25 May 2024 12:07:08 +0200 Subject: [PATCH 2620/2849] soc: espressif: esp32c3: improve memory utilization Change the MCUboot segments layout to incread the memory available in the application. Add missing symbols to mcuboot.ld Signed-off-by: Marek Matej --- soc/espressif/esp32c3/mcuboot.ld | 2 ++ soc/espressif/esp32c3/memory.h | 16 +++++++++------- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/soc/espressif/esp32c3/mcuboot.ld b/soc/espressif/esp32c3/mcuboot.ld index 8f402f566be14..dfb6c74e330a9 100644 --- a/soc/espressif/esp32c3/mcuboot.ld +++ b/soc/espressif/esp32c3/mcuboot.ld @@ -87,6 +87,7 @@ SECTIONS /* Vectors go to IRAM */ _iram_start = ABSOLUTE(.); _init_start = ABSOLUTE(.); + __text_region_start = ABSOLUTE(.); KEEP(*(.exception_vectors.text)); . = ALIGN(256); @@ -133,6 +134,7 @@ SECTIONS . += 16; _text_end = ABSOLUTE(.); + __text_region_end = ABSOLUTE(.); _etext = .; /* Similar to _iram_start, this symbol goes here so it is diff --git a/soc/espressif/esp32c3/memory.h b/soc/espressif/esp32c3/memory.h index f249f8b96432b..6d7ec34b3003a 100644 --- a/soc/espressif/esp32c3/memory.h +++ b/soc/espressif/esp32c3/memory.h @@ -36,21 +36,23 @@ /* Base address used for calculating memory layout * counted from Dbus backwards and back to the Ibus */ -#define BOOTLOADER_USABLE_DRAM_END DRAM_BUFFERS_START +#define BOOTLOADER_USER_DRAM_END DRAM_BUFFERS_START /* For safety margin between bootloader data section and startup stacks */ #define BOOTLOADER_STACK_OVERHEAD 0x0 /* These lengths can be adjusted, if necessary: */ #define BOOTLOADER_DRAM_SEG_LEN 0x9000 -#define BOOTLOADER_IRAM_LOADER_SEG_LEN 0x3000 -#define BOOTLOADER_IRAM_SEG_LEN 0x8000 +#define BOOTLOADER_IRAM_SEG_LEN 0x9000 +#define BOOTLOADER_IRAM_LOADER_SEG_LEN 0x1400 /* Start of the lower region is determined by region size and the end of the higher region */ -#define BOOTLOADER_DRAM_SEG_END (BOOTLOADER_USABLE_DRAM_END + BOOTLOADER_STACK_OVERHEAD) -#define BOOTLOADER_DRAM_SEG_START (BOOTLOADER_DRAM_SEG_END - BOOTLOADER_DRAM_SEG_LEN) -#define BOOTLOADER_IRAM_LOADER_SEG_START (BOOTLOADER_DRAM_SEG_START - \ - BOOTLOADER_IRAM_LOADER_SEG_LEN + IRAM_DRAM_OFFSET) +#define BOOTLOADER_IRAM_LOADER_SEG_END (BOOTLOADER_USER_DRAM_END + \ + BOOTLOADER_STACK_OVERHEAD + IRAM_DRAM_OFFSET) +#define BOOTLOADER_IRAM_LOADER_SEG_START (BOOTLOADER_IRAM_LOADER_SEG_END - \ + BOOTLOADER_IRAM_LOADER_SEG_LEN) #define BOOTLOADER_IRAM_SEG_START (BOOTLOADER_IRAM_LOADER_SEG_START - BOOTLOADER_IRAM_SEG_LEN) +#define BOOTLOADER_DRAM_SEG_START (BOOTLOADER_IRAM_SEG_START - IRAM_DRAM_OFFSET - \ + BOOTLOADER_DRAM_SEG_LEN) /* Flash */ #ifdef CONFIG_FLASH_SIZE From 51e5f2d3e50bda366e9d53a5fb771efc3b992b98 Mon Sep 17 00:00:00 2001 From: Marek Matej Date: Thu, 13 Jun 2024 01:01:09 +0200 Subject: [PATCH 2621/2849] soc: espressif: esp32c3: reorder ROM sections This covers the cases described in common-rom-common-kernel-devices.ld Changing the order of .rodata and .text we prevents to create an overlapped segments issue. Signed-off-by: Marek Matej --- soc/espressif/esp32c3/default.ld | 129 ++++++++++++++++--------------- 1 file changed, 67 insertions(+), 62 deletions(-) diff --git a/soc/espressif/esp32c3/default.ld b/soc/espressif/esp32c3/default.ld index 849f568f1aeb9..45d2824069132 100644 --- a/soc/espressif/esp32c3/default.ld +++ b/soc/espressif/esp32c3/default.ld @@ -641,23 +641,87 @@ SECTIONS /* --- END OF DRAM --- */ + /* --- START OF .flash.text --- */ + + .flash.text_dummy (NOLOAD): + { + . = ALIGN(CACHE_ALIGN); + } GROUP_LINK_IN(ROMABLE_REGION) + + /* Symbols used during the application memory mapping */ + _image_irom_start = LOADADDR(.flash.text); + _image_irom_size = SIZEOF(.flash.text); + _image_irom_vaddr = ADDR(.flash.text); + + .flash.text : ALIGN(CACHE_ALIGN) + { + _stext = .; + _instruction_reserved_start = ABSOLUTE(.); + _text_start = ABSOLUTE(.); + _instruction_reserved_start = ABSOLUTE(.); + __text_region_start = ABSOLUTE(.); + +#if !defined(CONFIG_ESP32_WIFI_IRAM_OPT) + *libnet80211.a:( .wifi0iram .wifi0iram.* .wifislpiram .wifislpiram.*) + *libpp.a:( .wifi0iram .wifi0iram.* .wifislpiram .wifislpiram.*) +#endif /* CONFIG_ESP32_WIFI_IRAM_OPT */ + +#if !defined(CONFIG_ESP32_WIFI_RX_IRAM_OPT) + *libnet80211.a:( .wifirxiram .wifirxiram.* .wifislprxiram .wifislprxiram.*) + *libpp.a:( .wifirxiram .wifirxiram.* .wifislprxiram .wifislprxiram.*) +#endif /* CONFIG_ESP32_WIFI_RX_IRAM_OPT */ + + *(.literal .text .literal.* .text.*) + *(.stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*) + *(.irom0.text) /* catch stray ICACHE_RODATA_ATTR */ + + *(.fini.literal) + *(.fini) + + *(.gnu.version) + + /* CPU will try to prefetch up to 16 bytes of + * of instructions. This means that any configuration (e.g. MMU, PMS) must allow + * safe access to up to 16 bytes after the last real instruction, add + * dummy bytes to ensure this + */ + . += 16; + + _instruction_reserved_end = ABSOLUTE(.); + _text_end = ABSOLUTE(.); + _instruction_reserved_end = ABSOLUTE(.); + __text_region_end = ABSOLUTE(.); + _etext = .; + + } GROUP_DATA_LINK_IN(FLASH_CODE_REGION, ROMABLE_REGION) + + /* --- END OF .flash.text --- */ + /* --- START OF .rodata --- */ /* Align next section to 64k to allow mapping */ - .flash.rodata_dummy (NOLOAD) : + .flash.dummy (NOLOAD) : { . = ALIGN(CACHE_ALIGN); } GROUP_LINK_IN(ROMABLE_REGION) + .flash.rodata_dummy (NOLOAD) : + { + /* Spacer in the IROM address to avoid interfering with the DROM address + * because DROM and IROM regions share the same address space */ + . += SIZEOF(.flash.text); + . = ALIGN(CACHE_ALIGN); + } GROUP_LINK_IN(RODATA_REGION) + /* Symbols used during the application memory mapping */ _image_drom_start = LOADADDR(.flash.rodata); - _image_drom_size = LOADADDR(.flash.rodata_end) + SIZEOF(.flash.rodata_end) - _image_drom_start; + _image_drom_size = _image_rodata_end - _image_rodata_start; _image_drom_vaddr = ADDR(.flash.rodata); .flash.rodata : ALIGN(0x10) { _rodata_reserved_start = ABSOLUTE(.); - _rodata_start = ABSOLUTE(.); + _image_rodata_start = ABSOLUTE(.); *(.rodata_desc .rodata_desc.*) *(.rodata_custom_desc .rodata_custom_desc.*) @@ -728,65 +792,6 @@ SECTIONS /* --- END OF .rodata --- */ - /* --- START OF .flash.text --- */ - - /* Symbols used during the application memory mapping */ - _image_irom_start = LOADADDR(.flash.text); - _image_irom_size = LOADADDR(.flash.text) + SIZEOF(.flash.text) - _image_irom_start; - _image_irom_vaddr = ADDR(.flash.text); - - .flash.text_dummy (NOLOAD): - { - /* Spacer in the IROM address to avoid interfering with the DROM address - * because DROM and IROM regions share the same address space */ - . += _image_rodata_end - _rodata_start; - . = ALIGN(CACHE_ALIGN); - } GROUP_DATA_LINK_IN(FLASH_CODE_REGION, ROMABLE_REGION) - - .flash.text : ALIGN(CACHE_ALIGN) - { - _stext = .; - _instruction_reserved_start = ABSOLUTE(.); - _text_start = ABSOLUTE(.); - _instruction_reserved_start = ABSOLUTE(.); - __text_region_start = ABSOLUTE(.); - -#if !defined(CONFIG_ESP32_WIFI_IRAM_OPT) - *libnet80211.a:( .wifi0iram .wifi0iram.* .wifislpiram .wifislpiram.*) - *libpp.a:( .wifi0iram .wifi0iram.* .wifislpiram .wifislpiram.*) -#endif /* CONFIG_ESP32_WIFI_IRAM_OPT */ - -#if !defined(CONFIG_ESP32_WIFI_RX_IRAM_OPT) - *libnet80211.a:( .wifirxiram .wifirxiram.* .wifislprxiram .wifislprxiram.*) - *libpp.a:( .wifirxiram .wifirxiram.* .wifislprxiram .wifislprxiram.*) -#endif /* CONFIG_ESP32_WIFI_RX_IRAM_OPT */ - - *(.literal .text .literal.* .text.*) - *(.stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*) - *(.irom0.text) /* catch stray ICACHE_RODATA_ATTR */ - - *(.fini.literal) - *(.fini) - - *(.gnu.version) - - /* CPU will try to prefetch up to 16 bytes of - * of instructions. This means that any configuration (e.g. MMU, PMS) must allow - * safe access to up to 16 bytes after the last real instruction, add - * dummy bytes to ensure this - */ - . += 16; - - _instruction_reserved_end = ABSOLUTE(.); - _text_end = ABSOLUTE(.); - _instruction_reserved_end = ABSOLUTE(.); - __text_region_end = ABSOLUTE(.); - _etext = .; - - } GROUP_DATA_LINK_IN(FLASH_CODE_REGION, ROMABLE_REGION) - - /* --- END OF .flash.text --- */ - #ifdef CONFIG_GEN_ISR_TABLES #include #endif From 0dc1414237988aabe9e762f164b7924d2b7613bf Mon Sep 17 00:00:00 2001 From: Johann Fischer Date: Tue, 21 May 2024 18:43:48 +0200 Subject: [PATCH 2622/2849] samples: usb: remove hid-cdc sample We have some other simpler CDC ACM and HID samples in the tree. Providing multiple functions is a core functionality of USB device support, and we have other samples to demonstrate this as well. This sample does not really provide anything unique, but has a few issues such as unsafe HID buffer handling and calling uart_fifo_fill() outside of the UART driver's IRQ context. Remove the hid-cdc sample, as there is no value in this sample, and to avoid spending time fixing and cleaning up the code. Signed-off-by: Johann Fischer --- doc/connectivity/usb/device/usb_device.rst | 4 +- samples/subsys/usb/hid-cdc/CMakeLists.txt | 8 - samples/subsys/usb/hid-cdc/README.rst | 107 --- samples/subsys/usb/hid-cdc/app.overlay | 15 - .../boards/nrf5340dk_nrf5340_cpuapp.conf | 2 - samples/subsys/usb/hid-cdc/prj.conf | 18 - samples/subsys/usb/hid-cdc/sample.yaml | 12 - samples/subsys/usb/hid-cdc/src/main.c | 841 ------------------ 8 files changed, 2 insertions(+), 1005 deletions(-) delete mode 100644 samples/subsys/usb/hid-cdc/CMakeLists.txt delete mode 100644 samples/subsys/usb/hid-cdc/README.rst delete mode 100644 samples/subsys/usb/hid-cdc/app.overlay delete mode 100644 samples/subsys/usb/hid-cdc/boards/nrf5340dk_nrf5340_cpuapp.conf delete mode 100644 samples/subsys/usb/hid-cdc/prj.conf delete mode 100644 samples/subsys/usb/hid-cdc/sample.yaml delete mode 100644 samples/subsys/usb/hid-cdc/src/main.c diff --git a/doc/connectivity/usb/device/usb_device.rst b/doc/connectivity/usb/device/usb_device.rst index 1e5950d2bf88c..acdd07a3a1b57 100644 --- a/doc/connectivity/usb/device/usb_device.rst +++ b/doc/connectivity/usb/device/usb_device.rst @@ -110,7 +110,7 @@ and looks like this: }; }; -Samples :zephyr:code-sample:`usb-cdc-acm` and :zephyr:code-sample:`usb-hid-cdc` have similar overlay files. +Sample :zephyr:code-sample:`usb-cdc-acm` has similar overlay files. And since no special properties are present, it may seem overkill to use devicetree to describe CDC ACM UART. The motivation behind using devicetree is the easy interchangeability of a real UART controller and CDC ACM UART @@ -579,7 +579,7 @@ The following Product IDs are currently used: +----------------------------------------------------+--------+ | :zephyr:code-sample:`usb-cdc-acm-composite` | 0x0002 | +----------------------------------------------------+--------+ -| :zephyr:code-sample:`usb-hid-cdc` | 0x0003 | +| Reserved (previously: usb-hid-cdc) | 0x0003 | +----------------------------------------------------+--------+ | :zephyr:code-sample:`usb-cdc-acm-console` | 0x0004 | +----------------------------------------------------+--------+ diff --git a/samples/subsys/usb/hid-cdc/CMakeLists.txt b/samples/subsys/usb/hid-cdc/CMakeLists.txt deleted file mode 100644 index 8bfa12bacb49c..0000000000000 --- a/samples/subsys/usb/hid-cdc/CMakeLists.txt +++ /dev/null @@ -1,8 +0,0 @@ -# SPDX-License-Identifier: Apache-2.0 - -cmake_minimum_required(VERSION 3.20.0) -find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) -project(hid-cdc) - -FILE(GLOB app_sources src/*.c) -target_sources(app PRIVATE ${app_sources}) diff --git a/samples/subsys/usb/hid-cdc/README.rst b/samples/subsys/usb/hid-cdc/README.rst deleted file mode 100644 index e0678d9d17364..0000000000000 --- a/samples/subsys/usb/hid-cdc/README.rst +++ /dev/null @@ -1,107 +0,0 @@ -.. zephyr:code-sample:: usb-hid-cdc - :name: USB HID and CDC ACM - :relevant-api: _usb_device_core_api usb_hid_class input_interface - - Expose multiple USB HID and CDC ACM instances. - -Overview -******** - -This sample app demonstrates use of multiple USB classes with multiple -instances. It combines two HID instances and two CDC ACM instances. -This sample can be found under :zephyr_file:`samples/subsys/usb/hid-cdc` in the -Zephyr project tree. - -Requirements -************ - -This project requires an USB device driver and multiple endpoints. - -The board hardware must have a push button connected via a GPIO pin. These are -called "User buttons" on many of Zephyr's :ref:`boards`. - -The button must be configured using the ``sw0`` :ref:`devicetree ` -alias, usually in the :ref:`BOARD.dts file `. You will -see this error if you try to build this sample for an unsupported board: - -.. code-block:: none - - Unsupported board: sw0 devicetree alias is not defined - -You may see additional build errors if the ``sw0`` alias exists, but is not -properly defined. - -If the devicetree aliases ``sw1``, ``sw2``, and ``sw3`` are defined, they will -also be used as additional buttons as described below. - -Building and Running -******************** - -This sample can be built for multiple boards. To build and flash it -for the :ref:`nrf52840dk_nrf52840` board: - -.. zephyr-app-commands:: - :zephyr-app: samples/subsys/usb/hid-cdc - :board: nrf52840dk/nrf52840 - :goals: build flash - :compact: - -After you have built and flashed the sample app image to your board, plug the -board into a host device, for example, a PC running Linux. -Two CDC ACM interfaces (for example /dev/ttyACM1 and /dev/ttyACM2) -and two HID devices will be detected: - -.. code-block:: console - - usb 2-2: new full-speed USB device number 3 using ohci-pci - usb 2-2: New USB device found, idVendor=2fe3, idProduct=0003, bcdDevice= 2.03 - usb 2-2: New USB device strings: Mfr=1, Product=2, SerialNumber=3 - usb 2-2: Product: Zephyr HID and CDC ACM sample - usb 2-2: Manufacturer: ZEPHYR - usb 2-2: SerialNumber: 86FE679A598AC47A - cdc_acm 2-2:1.0: ttyACM1: USB ACM device - input: ZEPHYR Zephyr HID and CDC ACM sample as /devices/pci0000:00/0000:00:06.0/usb2/2-2/2-2:1.2/0003:2FE3:0100.0002/input/input8 - hid-generic 0003:2FE3:0100.0002: input,hidraw1: USB HID v1.10 Mouse [ZEPHYR Zephyr HID and CDC ACM sample] on usb-0000:00:06.0-2/input2 - cdc_acm 2-2:1.3: ttyACM2: USB ACM device - input: ZEPHYR Zephyr HID and CDC ACM sample as /devices/pci0000:00/0000:00:06.0/usb2/2-2/2-2:1.5/0003:2FE3:0100.0003/input/input9 - hid-generic 0003:2FE3:0100.0003: input,hidraw2: USB HID v1.10 Keyboard [ZEPHYR Zephyr HID and CDC ACM sample] on usb-0000:00:06.0-2/input5 - -You can now connect to both CDC ACM ports: - -.. code-block:: console - - minicom -D /dev/ttyACM1 -b 115200 - -.. code-block:: console - - minicom -D /dev/ttyACM2 -b 115200 - -After both ports have been connected to, messages explaining usage of each port will be displayed: - -.. code-block:: console - - Welcome to CDC_ACM_0 - Supported commands: - up - moves the mouse up - down - moves the mouse down - right - moves the mouse to right - left - moves the mouse to left - -.. code-block:: console - - Welcome to CDC_ACM_1 - Enter a string and terminate it with ENTER. - It will be sent via HID when BUTTON 2 is pressed. - You can modify it by sending a new one here. - -CDC ACM 0 may be used to control the mouse by typing a command and pressing :kbd:`ENTER`. - -CDC ACM 1 is used to control the keyboard - any string typed into it and finished with :kbd:`ENTER` will be saved -on the device and typed back to the host when BUTTON 2 is pressed. - -Buttons have following functions: - -- Button 0 moves HID mouse in random direction -- Button 1 is a left HID mouse button -- Button 2 types the string sent with CDC ACM 1 using HID keyboard -- Button 3 is a CAPS LOCK on HID keyboard diff --git a/samples/subsys/usb/hid-cdc/app.overlay b/samples/subsys/usb/hid-cdc/app.overlay deleted file mode 100644 index dc6bcf2f10575..0000000000000 --- a/samples/subsys/usb/hid-cdc/app.overlay +++ /dev/null @@ -1,15 +0,0 @@ -/* - * Copyright (c) 2021 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: Apache-2.0 - */ - -&zephyr_udc0 { - cdc_acm_uart0 { - compatible = "zephyr,cdc-acm-uart"; - }; - - cdc_acm_uart1 { - compatible = "zephyr,cdc-acm-uart"; - }; -}; diff --git a/samples/subsys/usb/hid-cdc/boards/nrf5340dk_nrf5340_cpuapp.conf b/samples/subsys/usb/hid-cdc/boards/nrf5340dk_nrf5340_cpuapp.conf deleted file mode 100644 index 48384ea0232a2..0000000000000 --- a/samples/subsys/usb/hid-cdc/boards/nrf5340dk_nrf5340_cpuapp.conf +++ /dev/null @@ -1,2 +0,0 @@ -CONFIG_TEST_RANDOM_GENERATOR=y -CONFIG_TIMER_RANDOM_GENERATOR=y diff --git a/samples/subsys/usb/hid-cdc/prj.conf b/samples/subsys/usb/hid-cdc/prj.conf deleted file mode 100644 index 695f97698a3bd..0000000000000 --- a/samples/subsys/usb/hid-cdc/prj.conf +++ /dev/null @@ -1,18 +0,0 @@ -CONFIG_USB_DEVICE_STACK=y -CONFIG_USB_DEVICE_PRODUCT="Zephyr HID and CDC ACM sample" -CONFIG_USB_DEVICE_PID=0x0003 -CONFIG_USB_DEVICE_INITIALIZE_AT_BOOT=n -CONFIG_ENTROPY_GENERATOR=y -CONFIG_ENTROPY_DEVICE_RANDOM_GENERATOR=y - -CONFIG_USB_DEVICE_HID=y -CONFIG_USB_HID_DEVICE_COUNT=2 - -CONFIG_LOG=y -CONFIG_USB_DRIVER_LOG_LEVEL_INF=y -CONFIG_USB_DEVICE_LOG_LEVEL_INF=y - -CONFIG_SERIAL=y -CONFIG_UART_LINE_CTRL=y - -CONFIG_GPIO=y diff --git a/samples/subsys/usb/hid-cdc/sample.yaml b/samples/subsys/usb/hid-cdc/sample.yaml deleted file mode 100644 index acc25a0ac1a7b..0000000000000 --- a/samples/subsys/usb/hid-cdc/sample.yaml +++ /dev/null @@ -1,12 +0,0 @@ -sample: - name: USB HID CDC ACM sample -tests: - sample.usb.hid-cdc: - depends_on: usb_device - platform_allow: - - nrf52840dk/nrf52840 - - nrf52840dongle/nrf52840 - integration_platforms: - - nrf52840dk/nrf52840 - harness: button - tags: usb diff --git a/samples/subsys/usb/hid-cdc/src/main.c b/samples/subsys/usb/hid-cdc/src/main.c deleted file mode 100644 index 936afb76f0a66..0000000000000 --- a/samples/subsys/usb/hid-cdc/src/main.c +++ /dev/null @@ -1,841 +0,0 @@ -/* - * Copyright (c) 2019 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: Apache-2.0 - */ -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#define LOG_LEVEL LOG_LEVEL_DBG -LOG_MODULE_REGISTER(main); - -#define SW0_NODE DT_ALIAS(sw0) - -#if DT_NODE_HAS_STATUS(SW0_NODE, okay) -static const struct gpio_dt_spec sw0_gpio = GPIO_DT_SPEC_GET(SW0_NODE, gpios); -#endif - -#define SW1_NODE DT_ALIAS(sw1) - -#if DT_NODE_HAS_STATUS(SW1_NODE, okay) -static const struct gpio_dt_spec sw1_gpio = GPIO_DT_SPEC_GET(SW1_NODE, gpios); -#endif - -#define SW2_NODE DT_ALIAS(sw2) - -#if DT_NODE_HAS_STATUS(SW2_NODE, okay) -static const struct gpio_dt_spec sw2_gpio = GPIO_DT_SPEC_GET(SW2_NODE, gpios); -#endif - -#define SW3_NODE DT_ALIAS(sw3) - -#if DT_NODE_HAS_STATUS(SW3_NODE, okay) -static const struct gpio_dt_spec sw3_gpio = GPIO_DT_SPEC_GET(SW3_NODE, gpios); -#endif - -/* Event FIFO */ - -K_FIFO_DEFINE(evt_fifo); - -enum evt_t { - GPIO_BUTTON_0 = 0x00, - GPIO_BUTTON_1 = 0x01, - GPIO_BUTTON_2 = 0x02, - GPIO_BUTTON_3 = 0x03, - CDC_UP = 0x04, - CDC_DOWN = 0x05, - CDC_LEFT = 0x06, - CDC_RIGHT = 0x07, - CDC_UNKNOWN = 0x08, - CDC_STRING = 0x09, - HID_MOUSE_CLEAR = 0x0A, - HID_KBD_CLEAR = 0x0B, - HID_KBD_STRING = 0x0C, -}; - -struct app_evt_t { - sys_snode_t node; - enum evt_t event_type; -}; - -#define FIFO_ELEM_MIN_SZ sizeof(struct app_evt_t) -#define FIFO_ELEM_MAX_SZ sizeof(struct app_evt_t) -#define FIFO_ELEM_COUNT 255 -#define FIFO_ELEM_ALIGN sizeof(unsigned int) - -K_HEAP_DEFINE(event_elem_pool, FIFO_ELEM_MAX_SZ * FIFO_ELEM_COUNT + 256); - -static inline void app_evt_free(struct app_evt_t *ev) -{ - k_heap_free(&event_elem_pool, ev); -} - -static inline void app_evt_put(struct app_evt_t *ev) -{ - k_fifo_put(&evt_fifo, ev); -} - -static inline struct app_evt_t *app_evt_get(void) -{ - return k_fifo_get(&evt_fifo, K_NO_WAIT); -} - -static inline void app_evt_flush(void) -{ - struct app_evt_t *ev; - - do { - ev = app_evt_get(); - if (ev) { - app_evt_free(ev); - } - } while (ev != NULL); -} - -static inline struct app_evt_t *app_evt_alloc(void) -{ - struct app_evt_t *ev; - - ev = k_heap_alloc(&event_elem_pool, - sizeof(struct app_evt_t), - K_NO_WAIT); - if (ev == NULL) { - LOG_ERR("APP event allocation failed!"); - app_evt_flush(); - - ev = k_heap_alloc(&event_elem_pool, - sizeof(struct app_evt_t), - K_NO_WAIT); - if (ev == NULL) { - LOG_ERR("APP event memory corrupted."); - __ASSERT_NO_MSG(0); - return NULL; - } - return NULL; - } - - return ev; -} - -/* HID */ - -static const uint8_t hid_mouse_report_desc[] = HID_MOUSE_REPORT_DESC(2); -static const uint8_t hid_kbd_report_desc[] = HID_KEYBOARD_REPORT_DESC(); - -static K_SEM_DEFINE(evt_sem, 0, 1); /* starts off "not available" */ -static K_SEM_DEFINE(usb_sem, 1, 1); /* starts off "available" */ -static struct gpio_callback gpio_callbacks[4]; - -static char data_buf_mouse[64], data_buf_kbd[64]; -static char string[64]; -static uint8_t chr_ptr_mouse, chr_ptr_kbd, str_pointer; - -#define MOUSE_BTN_REPORT_POS 0 -#define MOUSE_X_REPORT_POS 1 -#define MOUSE_Y_REPORT_POS 2 - -#define MOUSE_BTN_LEFT BIT(0) -#define MOUSE_BTN_RIGHT BIT(1) -#define MOUSE_BTN_MIDDLE BIT(2) - -static const char *welcome = "Welcome to "; -static const char *banner0 = "\r\n" - "Supported commands:\r\n" - "up - moves the mouse up\r\n" - "down - moves the mouse down\r\n" - "right - moves the mouse to right\r\n" - "left - moves the mouse to left\r\n"; -static const char *banner1 = "\r\n" - "Enter a string and terminate " - "it with ENTER.\r\n" - "It will be sent via HID " - "when BUTTON 2 is pressed.\r\n" - "You can modify it by sending " - "a new one here.\r\n"; -static const char *gpio0 = "Button 0 pressed\r\n"; -static const char *gpio1 = "Button 1 pressed\r\n"; -static const char *gpio2 = "Button 2 pressed\r\n"; -static const char *gpio3 = "Button 3 pressed\r\n"; -static const char *unknown = "Command not recognized.\r\n"; -static const char *up = "Mouse up\r\n"; -static const char *down = "Mouse down\r\n"; -static const char *left = "Mouse left\r\n"; -static const char *right = "Mouse right\r\n"; -static const char *evt_fail = "Unknown event detected!\r\n"; -static const char *set_str = "String set to: "; -static const char *endl = "\r\n"; - -static void in_ready_cb(const struct device *dev) -{ - ARG_UNUSED(dev); - - k_sem_give(&usb_sem); -} - -static const struct hid_ops ops = { - .int_in_ready = in_ready_cb, -}; - -static void clear_mouse_report(void) -{ - struct app_evt_t *new_evt = app_evt_alloc(); - - new_evt->event_type = HID_MOUSE_CLEAR; - app_evt_put(new_evt); - k_sem_give(&evt_sem); -} - -static void clear_kbd_report(void) -{ - struct app_evt_t *new_evt = app_evt_alloc(); - - new_evt->event_type = HID_KBD_CLEAR; - app_evt_put(new_evt); - k_sem_give(&evt_sem); -} - -static int ascii_to_hid(uint8_t ascii) -{ - if (ascii < 32) { - /* Character not supported */ - return -1; - } else if (ascii < 48) { - /* Special characters */ - switch (ascii) { - case 32: - return HID_KEY_SPACE; - case 33: - return HID_KEY_1; - case 34: - return HID_KEY_APOSTROPHE; - case 35: - return HID_KEY_3; - case 36: - return HID_KEY_4; - case 37: - return HID_KEY_5; - case 38: - return HID_KEY_7; - case 39: - return HID_KEY_APOSTROPHE; - case 40: - return HID_KEY_9; - case 41: - return HID_KEY_0; - case 42: - return HID_KEY_8; - case 43: - return HID_KEY_EQUAL; - case 44: - return HID_KEY_COMMA; - case 45: - return HID_KEY_MINUS; - case 46: - return HID_KEY_DOT; - case 47: - return HID_KEY_SLASH; - default: - return -1; - } - } else if (ascii < 58) { - /* Numbers */ - if (ascii == 48U) { - return HID_KEY_0; - } else { - return ascii - 19; - } - } else if (ascii < 65) { - /* Special characters #2 */ - switch (ascii) { - case 58: - return HID_KEY_SEMICOLON; - case 59: - return HID_KEY_SEMICOLON; - case 60: - return HID_KEY_COMMA; - case 61: - return HID_KEY_EQUAL; - case 62: - return HID_KEY_DOT; - case 63: - return HID_KEY_SLASH; - case 64: - return HID_KEY_2; - default: - return -1; - } - } else if (ascii < 91) { - /* Uppercase characters */ - return ascii - 61U; - } else if (ascii < 97) { - /* Special characters #3 */ - switch (ascii) { - case 91: - return HID_KEY_LEFTBRACE; - case 92: - return HID_KEY_BACKSLASH; - case 93: - return HID_KEY_RIGHTBRACE; - case 94: - return HID_KEY_6; - case 95: - return HID_KEY_MINUS; - case 96: - return HID_KEY_GRAVE; - default: - return -1; - } - } else if (ascii < 123) { - /* Lowercase letters */ - return ascii - 93; - } else if (ascii < 128) { - /* Special characters #4 */ - switch (ascii) { - case 123: - return HID_KEY_LEFTBRACE; - case 124: - return HID_KEY_BACKSLASH; - case 125: - return HID_KEY_RIGHTBRACE; - case 126: - return HID_KEY_GRAVE; - case 127: - return HID_KEY_DELETE; - default: - return -1; - } - } - - return -1; -} - -static bool needs_shift(uint8_t ascii) -{ - if ((ascii < 33) || (ascii == 39U)) { - return false; - } else if ((ascii >= 33U) && (ascii < 44)) { - return true; - } else if ((ascii >= 44U) && (ascii < 58)) { - return false; - } else if ((ascii == 59U) || (ascii == 61U)) { - return false; - } else if ((ascii >= 58U) && (ascii < 91)) { - return true; - } else if ((ascii >= 91U) && (ascii < 94)) { - return false; - } else if ((ascii == 94U) || (ascii == 95U)) { - return true; - } else if ((ascii > 95) && (ascii < 123)) { - return false; - } else if ((ascii > 122) && (ascii < 127)) { - return true; - } else { - return false; - } -} - -/* CDC ACM */ - -static volatile bool data_transmitted; -static volatile bool data_arrived; - -static void flush_buffer_mouse(void) -{ - chr_ptr_mouse = 0U; - memset(data_buf_mouse, 0, sizeof(data_buf_mouse)); -} - -static void flush_buffer_kbd(void) -{ - chr_ptr_kbd = 0U; - memset(data_buf_kbd, 0, sizeof(data_buf_kbd)); -} - -static void write_data(const struct device *dev, const char *buf, int len) -{ - uart_irq_tx_enable(dev); - - while (len) { - int written; - - data_transmitted = false; - written = uart_fifo_fill(dev, (const uint8_t *)buf, len); - while (data_transmitted == false) { - k_yield(); - } - - len -= written; - buf += written; - } - - uart_irq_tx_disable(dev); -} - -static void cdc_mouse_int_handler(const struct device *dev, void *user_data) -{ - ARG_UNUSED(user_data); - - uart_irq_update(dev); - - if (uart_irq_tx_ready(dev)) { - data_transmitted = true; - } - - if (!uart_irq_rx_ready(dev)) { - return; - } - uint32_t bytes_read; - - while ((bytes_read = uart_fifo_read(dev, - (uint8_t *)data_buf_mouse+chr_ptr_mouse, - sizeof(data_buf_mouse)-chr_ptr_mouse))) { - chr_ptr_mouse += bytes_read; - if (data_buf_mouse[chr_ptr_mouse - 1] == '\r') { - /* ENTER */ - struct app_evt_t *ev = app_evt_alloc(); - - data_buf_mouse[chr_ptr_mouse - 1] = '\0'; - - if (!strcmp(data_buf_mouse, "up")) { - ev->event_type = CDC_UP; - } else if (!strcmp(data_buf_mouse, "down")) { - ev->event_type = CDC_DOWN; - } else if (!strcmp(data_buf_mouse, "right")) { - ev->event_type = CDC_RIGHT; - } else if (!strcmp(data_buf_mouse, "left")) { - ev->event_type = CDC_LEFT; - } else { - ev->event_type = CDC_UNKNOWN; - } - flush_buffer_mouse(); - app_evt_put(ev); - k_sem_give(&evt_sem); - } - - if (chr_ptr_mouse >= sizeof(data_buf_mouse)) { - LOG_WRN("Buffer overflow"); - flush_buffer_mouse(); - } - } -} - -static void cdc_kbd_int_handler(const struct device *dev, void *user_data) -{ - ARG_UNUSED(user_data); - - uart_irq_update(dev); - - if (uart_irq_tx_ready(dev)) { - data_transmitted = true; - } - - if (!uart_irq_rx_ready(dev)) { - return; - } - uint32_t bytes_read; - - while ((bytes_read = uart_fifo_read(dev, - (uint8_t *)data_buf_kbd+chr_ptr_kbd, - sizeof(data_buf_kbd)-chr_ptr_kbd))) { - chr_ptr_kbd += bytes_read; - if (data_buf_kbd[chr_ptr_kbd - 1] == '\r') { - /* ENTER */ - struct app_evt_t *ev = app_evt_alloc(); - - data_buf_kbd[chr_ptr_kbd - 1] = '\0'; - strcpy(string, data_buf_kbd); - ev->event_type = CDC_STRING; - flush_buffer_kbd(); - app_evt_put(ev); - k_sem_give(&evt_sem); - } - } -} - -/* Devices */ - -static void btn0(const struct device *gpio, struct gpio_callback *cb, - uint32_t pins) -{ - struct app_evt_t *ev = app_evt_alloc(); - - ev->event_type = GPIO_BUTTON_0, - app_evt_put(ev); - k_sem_give(&evt_sem); -} - -#if DT_NODE_HAS_STATUS(SW1_NODE, okay) -static void btn1(const struct device *gpio, struct gpio_callback *cb, - uint32_t pins) -{ - struct app_evt_t *ev = app_evt_alloc(); - - ev->event_type = GPIO_BUTTON_1, - app_evt_put(ev); - k_sem_give(&evt_sem); -} -#endif - -#if DT_NODE_HAS_STATUS(SW2_NODE, okay) -static void btn2(const struct device *gpio, struct gpio_callback *cb, - uint32_t pins) -{ - struct app_evt_t *ev = app_evt_alloc(); - - ev->event_type = GPIO_BUTTON_2, - app_evt_put(ev); - k_sem_give(&evt_sem); -} -#endif - -#if DT_NODE_HAS_STATUS(SW3_NODE, okay) -static void btn3(const struct device *gpio, struct gpio_callback *cb, - uint32_t pins) -{ - struct app_evt_t *ev = app_evt_alloc(); - - ev->event_type = GPIO_BUTTON_3, - app_evt_put(ev); - k_sem_give(&evt_sem); -} -#endif - -int callbacks_configure(const struct gpio_dt_spec *gpio, - void (*handler)(const struct device *, struct gpio_callback*, - uint32_t), - struct gpio_callback *callback) -{ - if (!device_is_ready(gpio->port)) { - LOG_ERR("%s: device not ready.", gpio->port->name); - return -ENODEV; - } - - gpio_pin_configure_dt(gpio, GPIO_INPUT); - - gpio_init_callback(callback, handler, BIT(gpio->pin)); - gpio_add_callback(gpio->port, callback); - gpio_pin_interrupt_configure_dt(gpio, GPIO_INT_EDGE_TO_ACTIVE); - - return 0; -} - -static void status_cb(enum usb_dc_status_code status, const uint8_t *param) -{ - LOG_INF("Status %d", status); -} - -#define DEVICE_AND_COMMA(node_id) DEVICE_DT_GET(node_id), - -int main(void) -{ - const struct device *cdc_dev[] = { - DT_FOREACH_STATUS_OKAY(zephyr_cdc_acm_uart, DEVICE_AND_COMMA) - }; - BUILD_ASSERT(ARRAY_SIZE(cdc_dev) >= 2, "Not enough CDC ACM instances"); - const struct device *hid0_dev, *hid1_dev; - struct app_evt_t *ev; - uint32_t dtr = 0U; - int ret; - - /* Configure devices */ - - hid0_dev = device_get_binding("HID_0"); - if (hid0_dev == NULL) { - LOG_ERR("Cannot get USB HID 0 Device"); - return 0; - } - - hid1_dev = device_get_binding("HID_1"); - if (hid1_dev == NULL) { - LOG_ERR("Cannot get USB HID 1 Device"); - return 0; - } - - for (int idx = 0; idx < ARRAY_SIZE(cdc_dev); idx++) { - if (!device_is_ready(cdc_dev[idx])) { - LOG_ERR("CDC ACM device %s is not ready", - cdc_dev[idx]->name); - return 0; - } - } - - if (callbacks_configure(&sw0_gpio, &btn0, &gpio_callbacks[0])) { - LOG_ERR("Failed configuring button 0 callback."); - return 0; - } - -#if DT_NODE_HAS_STATUS(SW1_NODE, okay) - if (callbacks_configure(&sw1_gpio, &btn1, &gpio_callbacks[1])) { - LOG_ERR("Failed configuring button 1 callback."); - return 0; - } -#endif - -#if DT_NODE_HAS_STATUS(SW2_NODE, okay) - if (callbacks_configure(&sw2_gpio, &btn2, &gpio_callbacks[2])) { - LOG_ERR("Failed configuring button 2 callback."); - return 0; - } -#endif - -#if DT_NODE_HAS_STATUS(SW3_NODE, okay) - if (callbacks_configure(&sw3_gpio, &btn3, &gpio_callbacks[3])) { - LOG_ERR("Failed configuring button 3 callback."); - return 0; - } -#endif - - /* Initialize HID */ - - usb_hid_register_device(hid0_dev, hid_mouse_report_desc, - sizeof(hid_mouse_report_desc), &ops); - - usb_hid_register_device(hid1_dev, hid_kbd_report_desc, - sizeof(hid_kbd_report_desc), &ops); - - usb_hid_init(hid0_dev); - usb_hid_init(hid1_dev); - - ret = usb_enable(status_cb); - if (ret != 0) { - LOG_ERR("Failed to enable USB"); - return 0; - } - - /* Initialize CDC ACM */ - for (int idx = 0; idx < ARRAY_SIZE(cdc_dev); idx++) { - LOG_INF("Wait for DTR on %s", cdc_dev[idx]->name); - while (1) { - uart_line_ctrl_get(cdc_dev[idx], - UART_LINE_CTRL_DTR, - &dtr); - if (dtr) { - break; - } else { - /* Give CPU resources to low priority threads. */ - k_sleep(K_MSEC(100)); - } - } - - LOG_INF("DTR on device %s", cdc_dev[idx]->name); - } - - /* Wait 1 sec for the host to do all settings */ - k_busy_wait(USEC_PER_SEC); - - uart_irq_callback_set(cdc_dev[0], cdc_mouse_int_handler); - uart_irq_callback_set(cdc_dev[1], cdc_kbd_int_handler); - - write_data(cdc_dev[0], welcome, strlen(welcome)); - write_data(cdc_dev[0], cdc_dev[0]->name, strlen(cdc_dev[0]->name)); - write_data(cdc_dev[0], banner0, strlen(banner0)); - write_data(cdc_dev[1], welcome, strlen(welcome)); - write_data(cdc_dev[1], cdc_dev[1]->name, strlen(cdc_dev[1]->name)); - write_data(cdc_dev[1], banner1, strlen(banner1)); - - uart_irq_rx_enable(cdc_dev[0]); - uart_irq_rx_enable(cdc_dev[1]); - - while (true) { - k_sem_take(&evt_sem, K_FOREVER); - - while ((ev = app_evt_get()) != NULL) { - switch (ev->event_type) { - case GPIO_BUTTON_0: - { - /* Move the mouse in random direction */ - uint8_t rep[] = {0x00, sys_rand8_get(), - sys_rand8_get(), 0x00}; - - k_sem_take(&usb_sem, K_FOREVER); - hid_int_ep_write(hid0_dev, rep, - sizeof(rep), NULL); - write_data(cdc_dev[0], gpio0, strlen(gpio0)); - clear_mouse_report(); - break; - } - case GPIO_BUTTON_1: - { - /* Press left mouse button */ - uint8_t rep[] = {0x00, 0x00, 0x00, 0x00}; - - rep[MOUSE_BTN_REPORT_POS] |= MOUSE_BTN_LEFT; - k_sem_take(&usb_sem, K_FOREVER); - hid_int_ep_write(hid0_dev, rep, - sizeof(rep), NULL); - write_data(cdc_dev[0], gpio1, strlen(gpio1)); - clear_mouse_report(); - break; - } - case GPIO_BUTTON_2: - { - /* Send string on HID keyboard */ - write_data(cdc_dev[1], gpio2, strlen(gpio2)); - if (strlen(string) > 0) { - struct app_evt_t *ev2 = app_evt_alloc(); - - ev2->event_type = HID_KBD_STRING, - app_evt_put(ev2); - str_pointer = 0U; - k_sem_give(&evt_sem); - } - break; - } - case GPIO_BUTTON_3: - { - /* Toggle CAPS LOCK */ - uint8_t rep[] = {0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, - HID_KEY_CAPSLOCK}; - - k_sem_take(&usb_sem, K_FOREVER); - hid_int_ep_write(hid1_dev, rep, - sizeof(rep), NULL); - write_data(cdc_dev[1], gpio3, strlen(gpio3)); - clear_kbd_report(); - break; - } - case CDC_UP: - { - /* Mouse up */ - uint8_t rep[] = {0x00, 0x00, 0xE0, 0x00}; - - k_sem_take(&usb_sem, K_FOREVER); - hid_int_ep_write(hid0_dev, rep, - sizeof(rep), NULL); - write_data(cdc_dev[0], up, strlen(up)); - clear_mouse_report(); - break; - } - case CDC_DOWN: - { - /* Mouse down */ - uint8_t rep[] = {0x00, 0x00, 0x20, 0x00}; - - k_sem_take(&usb_sem, K_FOREVER); - hid_int_ep_write(hid0_dev, rep, - sizeof(rep), NULL); - write_data(cdc_dev[0], down, strlen(down)); - clear_mouse_report(); - break; - } - case CDC_RIGHT: - { - /* Mouse right */ - uint8_t rep[] = {0x00, 0x20, 0x00, 0x00}; - - k_sem_take(&usb_sem, K_FOREVER); - hid_int_ep_write(hid0_dev, rep, - sizeof(rep), NULL); - write_data(cdc_dev[0], right, strlen(right)); - clear_mouse_report(); - break; - } - case CDC_LEFT: - { - /* Mouse left */ - uint8_t rep[] = {0x00, 0xE0, 0x00, 0x00}; - - k_sem_take(&usb_sem, K_FOREVER); - hid_int_ep_write(hid0_dev, rep, - sizeof(rep), NULL); - write_data(cdc_dev[0], left, strlen(left)); - clear_mouse_report(); - break; - } - case CDC_UNKNOWN: - { - write_data(cdc_dev[0], unknown, strlen(unknown)); - write_data(cdc_dev[1], unknown, strlen(unknown)); - break; - } - case CDC_STRING: - { - write_data(cdc_dev[0], set_str, strlen(set_str)); - write_data(cdc_dev[0], string, strlen(string)); - write_data(cdc_dev[0], endl, strlen(endl)); - - write_data(cdc_dev[1], set_str, strlen(set_str)); - write_data(cdc_dev[1], string, strlen(string)); - write_data(cdc_dev[1], endl, strlen(endl)); - break; - } - case HID_MOUSE_CLEAR: - { - /* Clear mouse report */ - uint8_t rep[] = {0x00, 0x00, 0x00, 0x00}; - - k_sem_take(&usb_sem, K_FOREVER); - hid_int_ep_write(hid0_dev, rep, - sizeof(rep), NULL); - break; - } - case HID_KBD_CLEAR: - { - /* Clear kbd report */ - uint8_t rep[] = {0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00}; - - k_sem_take(&usb_sem, K_FOREVER); - hid_int_ep_write(hid1_dev, rep, - sizeof(rep), NULL); - break; - } - case HID_KBD_STRING: - { - int ch = ascii_to_hid(string[str_pointer]); - - if (ch == -1) { - LOG_WRN("Unsupported character: %d", - string[str_pointer]); - } else { - uint8_t rep[] = {0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00}; - if (needs_shift(string[str_pointer])) { - rep[0] |= - HID_KBD_MODIFIER_RIGHT_SHIFT; - } - rep[7] = ch; - - k_sem_take(&usb_sem, K_FOREVER); - hid_int_ep_write(hid1_dev, rep, - sizeof(rep), NULL); - } - - str_pointer++; - - if (strlen(string) > str_pointer) { - struct app_evt_t *ev2 = app_evt_alloc(); - - ev2->event_type = HID_KBD_STRING, - app_evt_put(ev2); - k_sem_give(&evt_sem); - } else if (strlen(string) == str_pointer) { - clear_kbd_report(); - } - - break; - } - default: - { - LOG_ERR("Unknown event to execute"); - write_data(cdc_dev[0], evt_fail, - strlen(evt_fail)); - write_data(cdc_dev[1], evt_fail, - strlen(evt_fail)); - break; - } - break; - } - app_evt_free(ev); - } - } -} From f3679ab2c21e11e4093a81a27586a3e1596fce4d Mon Sep 17 00:00:00 2001 From: Hess Nathan Date: Mon, 13 May 2024 09:18:08 +0200 Subject: [PATCH 2623/2849] coding guidelines: comply with MISRA Rule 7.4 avoided to assign string literals to non-const char * Signed-off-by: Hess Nathan --- include/zephyr/sys/cbprintf_internal.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/include/zephyr/sys/cbprintf_internal.h b/include/zephyr/sys/cbprintf_internal.h index a96e39c2a75d2..ad6796190384d 100644 --- a/include/zephyr/sys/cbprintf_internal.h +++ b/include/zephyr/sys/cbprintf_internal.h @@ -557,8 +557,9 @@ extern "C" { #ifdef __cplusplus #define Z_CBPRINTF_ARG_SIZE(v) z_cbprintf_cxx_arg_size(v) #else +#define Z_CONSTIFY(v) (_Generic((v), char * : (const char *)(uintptr_t)(v), default : (v))) #define Z_CBPRINTF_ARG_SIZE(v) ({\ - __auto_type __v = (v) + 0; \ + __auto_type __v = (Z_CONSTIFY(v)) + 0; \ /* Static code analysis may complain about unused variable. */ \ (void)__v; \ size_t __arg_size = _Generic((v), \ @@ -582,7 +583,7 @@ extern "C" { #define Z_CBPRINTF_STORE_ARG(buf, arg) do { \ if (Z_CBPRINTF_VA_STACK_LL_DBL_MEMCPY) { \ /* If required, copy arguments by word to avoid unaligned access.*/ \ - __auto_type _v = (arg) + 0; \ + __auto_type _v = (Z_CONSTIFY(arg)) + 0; \ double _d = _Generic((arg) + 0, \ float : (arg) + 0, \ default : \ From 1e3fd5361f3f6a76e71299f72ba0ae8e52320cfa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Stenberg?= Date: Wed, 10 Apr 2024 09:58:08 +0200 Subject: [PATCH 2624/2849] modbus_serial: Disable rx interrupt if buffer fills up MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Disable rx interrupt if the buffer fills up so that rtu_timer can fire and process the buffer. Signed-off-by: Björn Stenberg --- subsys/modbus/modbus_serial.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/subsys/modbus/modbus_serial.c b/subsys/modbus/modbus_serial.c index 13d59c8154a19..b35a4bb35bc64 100644 --- a/subsys/modbus/modbus_serial.c +++ b/subsys/modbus/modbus_serial.c @@ -339,6 +339,12 @@ static void cb_handler_rx(struct modbus_context *ctx) } else { int n; + if (cfg->uart_buf_ctr == CONFIG_MODBUS_BUFFER_SIZE) { + /* Buffer full. Disable interrupt until timeout. */ + modbus_serial_rx_disable(ctx); + return; + } + /* Restart timer on a new character */ k_timer_start(&cfg->rtu_timer, K_USEC(cfg->rtu_timeout), K_NO_WAIT); From c396d8bdbc06677fecd8855dac2b42bf89d5185a Mon Sep 17 00:00:00 2001 From: Mahesh Mahadevan Date: Thu, 11 Apr 2024 09:04:03 -0500 Subject: [PATCH 2625/2849] drivers: clock_control: Update NXP LPC Syscon driver to add FlexIO Add support to get FlexIO clock Signed-off-by: Mahesh Mahadevan --- drivers/clock_control/clock_control_mcux_syscon.c | 6 ++++++ include/zephyr/dt-bindings/clock/mcux_lpc_syscon_clock.h | 2 ++ 2 files changed, 8 insertions(+) diff --git a/drivers/clock_control/clock_control_mcux_syscon.c b/drivers/clock_control/clock_control_mcux_syscon.c index d0d881541e182..b7a39b11d1116 100644 --- a/drivers/clock_control/clock_control_mcux_syscon.c +++ b/drivers/clock_control/clock_control_mcux_syscon.c @@ -352,6 +352,12 @@ static int mcux_lpc_syscon_clock_control_get_subsys_rate( *rate = CLOCK_GetFlexcanClkFreq(1); break; #endif /* defined(CONFIG_CAN_MCUX_FLEXCAN) */ + +#if defined(CONFIG_MCUX_FLEXIO) + case MCUX_FLEXIO0_CLK: + *rate = CLOCK_GetFlexioClkFreq(); + break; +#endif /* defined(CONFIG_MCUX_FLEXIO) */ } return 0; diff --git a/include/zephyr/dt-bindings/clock/mcux_lpc_syscon_clock.h b/include/zephyr/dt-bindings/clock/mcux_lpc_syscon_clock.h index 71241be75ce80..68fcb1df8b742 100644 --- a/include/zephyr/dt-bindings/clock/mcux_lpc_syscon_clock.h +++ b/include/zephyr/dt-bindings/clock/mcux_lpc_syscon_clock.h @@ -87,4 +87,6 @@ #define MCUX_FLEXCAN0_CLK MCUX_LPC_CLK_ID(0x10, 0x00) #define MCUX_FLEXCAN1_CLK MCUX_LPC_CLK_ID(0x10, 0x01) +#define MCUX_FLEXIO0_CLK MCUX_LPC_CLK_ID(0x11, 0x00) + #endif /* ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_MCUX_LPC_SYSCON_H_ */ From 53b5dbfb8842e1c046b50d1b724c92e19cd80988 Mon Sep 17 00:00:00 2001 From: Mahesh Mahadevan Date: Thu, 15 Feb 2024 19:17:39 +0000 Subject: [PATCH 2626/2849] include: mipi_dbi: Add defines for MIPI Type A and B Add defines for MIPI DBI Type A based on Motorola 6800 and Type B baedon Intel 8080 bus Signed-off-by: Mahesh Mahadevan --- dts/bindings/mipi-dbi/mipi-dbi-device.yaml | 12 ++++ .../zephyr/dt-bindings/mipi_dbi/mipi_dbi.h | 56 +++++++++++++++++++ 2 files changed, 68 insertions(+) diff --git a/dts/bindings/mipi-dbi/mipi-dbi-device.yaml b/dts/bindings/mipi-dbi/mipi-dbi-device.yaml index 4f68fadf73151..2cadb4d3a425c 100644 --- a/dts/bindings/mipi-dbi/mipi-dbi-device.yaml +++ b/dts/bindings/mipi-dbi/mipi-dbi-device.yaml @@ -19,6 +19,18 @@ properties: the concordance list (see dt-bindings/mipi_dbi/mipi_dbi.h) 1 MIPI_DBI_MODE_SPI_3WIRE 2 MIPI_DBI_MODE_SPI_4WIRE + 3 MIPI_DBI_MODE_6800_BUS_16_BIT + 4 MIPI_DBI_MODE_6800_BUS_9_BIT + 5 MIPI_DBI_MODE_6800_BUS_8_BIT + 6 MIPI_DBI_MODE_8080_BUS_16_BIT + 7 MIPI_DBI_MODE_8080_BUS_9_BIT + 8 MIPI_DBI_MODE_8080_BUS_8_BIT enum: - 1 - 2 + - 3 + - 4 + - 5 + - 6 + - 7 + - 8 diff --git a/include/zephyr/dt-bindings/mipi_dbi/mipi_dbi.h b/include/zephyr/dt-bindings/mipi_dbi/mipi_dbi.h index 6956e044d11ea..25886635f5962 100644 --- a/include/zephyr/dt-bindings/mipi_dbi/mipi_dbi.h +++ b/include/zephyr/dt-bindings/mipi_dbi/mipi_dbi.h @@ -53,6 +53,62 @@ * -'-------------------------------'-------------------------------'- */ #define MIPI_DBI_MODE_SPI_4WIRE 0x2 +/** + * Parallel Bus protocol for MIPI DBI Type A based on Motorola 6800 bus. + * + * -. .--------. .------------------------ + * CS '---' '---' + * + * ------------------------------------------- + * RESX + * + * .-------------------------------- + * D/CX ----------' + * + * + * R/WX ------------------------------------------- + * + * ------------------------------------------- + * E + * + * .--------. .--------------------------. + * D[15:0]/ -| COMMAND|---| DATA | + * D[8:0]/ '--------' '--------------------------' + * D[7:0] + * + * Please refer to the MIPI DBI specification for a detailed cycle diagram. + */ +#define MIPI_DBI_MODE_6800_BUS_16_BIT 0x3 +#define MIPI_DBI_MODE_6800_BUS_9_BIT 0x4 +#define MIPI_DBI_MODE_6800_BUS_8_BIT 0x5 +/** + * Parallel Bus protocol for MIPI DBI Type B based on Intel 8080 bus. + * + * -. .- + * CS '---------------------------------------' + * + * ------------------------------------------- + * RESX + * + * --. .---------------------------- + * D/CX '-----------' + * + * ---. .--------. .---------------------- + * WRX '---' '---' + * + * ------------------------------------------- + * RDX + * + * .--------. .--------------------------. + * D[15:0]/ ---| COMMAND|---| DATA | + * D[8:0]/ '--------' '--------------------------' + * D[7:0] + * + * Please refer to the MIPI DBI specification for a detailed cycle diagram. + */ +#define MIPI_DBI_MODE_8080_BUS_16_BIT 0x6 +#define MIPI_DBI_MODE_8080_BUS_9_BIT 0x7 +#define MIPI_DBI_MODE_8080_BUS_8_BIT 0x8 /** * @} From 6236779d32a83b15a00d85ef08674f8c1750c4ee Mon Sep 17 00:00:00 2001 From: Mahesh Mahadevan Date: Wed, 12 Jun 2024 11:46:46 -0500 Subject: [PATCH 2627/2849] drivers: display: Update setting the mode in the st7796s driver MIPI mode is read from the device tree. Signed-off-by: Mahesh Mahadevan --- drivers/display/display_st7796s.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/display/display_st7796s.c b/drivers/display/display_st7796s.c index df4271d1b5d19..87c91a13f2b82 100644 --- a/drivers/display/display_st7796s.c +++ b/drivers/display/display_st7796s.c @@ -319,7 +319,8 @@ static const struct display_driver_api st7796s_api = { SPI_OP_MODE_MASTER | \ SPI_WORD_SET(8), \ 0), \ - .mode = MIPI_DBI_MODE_SPI_4WIRE, \ + .mode = DT_INST_PROP_OR(n, mipi_mode, \ + MIPI_DBI_MODE_SPI_4WIRE), \ }, \ .width = DT_INST_PROP(n, width), \ .height = DT_INST_PROP(n, height), \ From 3dd5ffe20adf7e785aae8818b9336199cc373cb0 Mon Sep 17 00:00:00 2001 From: Mahesh Mahadevan Date: Thu, 9 May 2024 13:03:22 -0500 Subject: [PATCH 2628/2849] drivers: display: st7796: Update the logic to invert RGB and BGR 1. Add a property for panels where the RGB is displayed as BGR. 2. Add a check for 8080 8-bit mode and invert RGB and BGR for this case. Signed-off-by: Mahesh Mahadevan --- drivers/display/display_st7796s.c | 63 +++++++++++++++++----- dts/bindings/display/sitronix,st7796s.yaml | 9 ++++ 2 files changed, 60 insertions(+), 12 deletions(-) diff --git a/drivers/display/display_st7796s.c b/drivers/display/display_st7796s.c index 87c91a13f2b82..257a456c84bc5 100644 --- a/drivers/display/display_st7796s.c +++ b/drivers/display/display_st7796s.c @@ -46,6 +46,7 @@ struct st7796s_config { uint8_t pgc[14]; /* Positive gamma control */ uint8_t ngc[14]; /* Negative gamma control */ uint8_t madctl; /* Memory data access control */ + bool rgb_is_inverted; }; static int st7796s_send_cmd(const struct device *dev, @@ -92,6 +93,52 @@ static int st7796s_blanking_off(const struct device *dev) return st7796s_send_cmd(dev, ST7796S_CMD_DISPON, NULL, 0); } +static int st7796s_get_pixelfmt(const struct device *dev) +{ + const struct st7796s_config *config = dev->config; + + /* + * Invert the pixel format for 8-bit 8080 Parallel Interface. + * + * Zephyr uses big endian byte order when the pixel format has + * multiple bytes. + * + * For RGB565, Red is placed in byte 1 and Blue in byte 0. + * For BGR565, Red is placed in byte 0 and Blue in byte 1. + * + * This is not an issue when using a 16-bit interface. + * For RGB565, this would map to Red being in D[11:15] and + * Blue in D[0:4] and vice versa for BGR565. + * + * However this is an issue when using a 8-bit interface. + * For RGB565, Blue is placed in byte 0 as mentioned earlier. + * However the controller expects Red to be in D[3:7] of byte 0. + * + * Hence we report pixel format as RGB when MADCTL setting is BGR + * and vice versa. + */ + if (config->dbi_config.mode == MIPI_DBI_MODE_8080_BUS_8_BIT) { + if (config->madctl & ST7796S_MADCTL_BGR) { + return PIXEL_FORMAT_RGB_565; + } else { + return PIXEL_FORMAT_BGR_565; + } + } + + /* + * Invert the pixel format if rgb_is_inverted is enabled. + * Report pixel format as the same format set in the MADCTL + * if rgb_is_inverted is disabled. + * Report pixel format as RGB if MADCTL setting is BGR and vice versa + * if rgb_is_inverted is enabled. + * It is a workaround for supporting buggy modules that display RGB as BGR. + */ + if (!(config->madctl & ST7796S_MADCTL_BGR) != !config->rgb_is_inverted) { + return PIXEL_FORMAT_BGR_565; + } else { + return PIXEL_FORMAT_RGB_565; + } +} static int st7796s_write(const struct device *dev, const uint16_t x, @@ -118,12 +165,7 @@ static int st7796s_write(const struct device *dev, return ret; } - if (config->madctl & ST7796S_MADCTL_BGR) { - /* Zephyr treats RGB565 as BGR565 */ - pixfmt = PIXEL_FORMAT_RGB_565; - } else { - pixfmt = PIXEL_FORMAT_BGR_565; - } + pixfmt = st7796s_get_pixelfmt(dev); return mipi_dbi_write_display(config->mipi_dbi, &config->dbi_config, buf, @@ -137,12 +179,8 @@ static void st7796s_get_capabilities(const struct device *dev, memset(capabilities, 0, sizeof(struct display_capabilities)); - if (config->madctl & ST7796S_MADCTL_BGR) { - /* Zephyr treats RGB565 as BGR565 */ - capabilities->current_pixel_format = PIXEL_FORMAT_RGB_565; - } else { - capabilities->current_pixel_format = PIXEL_FORMAT_BGR_565; - } + capabilities->current_pixel_format = st7796s_get_pixelfmt(dev); + capabilities->x_resolution = config->width; capabilities->y_resolution = config->height; capabilities->current_orientation = DISPLAY_ORIENTATION_NORMAL; @@ -339,6 +377,7 @@ static const struct display_driver_api st7796s_api = { .pgc = DT_INST_PROP(n, pgc), \ .ngc = DT_INST_PROP(n, ngc), \ .madctl = DT_INST_PROP(n, madctl), \ + .rgb_is_inverted = DT_INST_PROP(n, rgb_is_inverted), \ }; \ \ DEVICE_DT_INST_DEFINE(n, st7796s_init, \ diff --git a/dts/bindings/display/sitronix,st7796s.yaml b/dts/bindings/display/sitronix,st7796s.yaml index 8f67fe81e4158..1c0117235083c 100644 --- a/dts/bindings/display/sitronix,st7796s.yaml +++ b/dts/bindings/display/sitronix,st7796s.yaml @@ -104,3 +104,12 @@ properties: - "2-dot" description: | Display inversion control mode. + + rgb-is-inverted: + type: boolean + description: | + Inverting color format order (RGB->BGR or BGR->RGB) + In the case of enabling this option, API reports pixel-format in capabilities + as the inverted value of the RGB pixel-format specified in MADCTL. + This option is convenient for supporting displays with bugs + where the actual color is different from the pixel format of MADCTL. From b219596cc126a6fd320e5239f7a84f1e1590ab12 Mon Sep 17 00:00:00 2001 From: Mahesh Mahadevan Date: Wed, 10 Apr 2024 08:43:40 -0500 Subject: [PATCH 2629/2849] drivers: mipi_dbi: Add controller driver for NXP FlexIO LCD Add a driver to support the NXP FlexIO LCD controller that uses 8080/6800 bus protocol. Signed-off-by: Mahesh Mahadevan --- drivers/mipi_dbi/CMakeLists.txt | 12 + drivers/mipi_dbi/Kconfig | 1 + drivers/mipi_dbi/Kconfig.nxp_flexio_lcdif | 12 + drivers/mipi_dbi/mipi_dbi_nxp_flexio_lcdif.c | 485 ++++++++++++++++++ dts/arm/nxp/nxp_mcxn94x_common.dtsi | 12 + .../mipi-dbi/nxp,mipi-dbi-flexio-lcdif.yaml | 63 +++ 6 files changed, 585 insertions(+) create mode 100644 drivers/mipi_dbi/Kconfig.nxp_flexio_lcdif create mode 100644 drivers/mipi_dbi/mipi_dbi_nxp_flexio_lcdif.c create mode 100644 dts/bindings/mipi-dbi/nxp,mipi-dbi-flexio-lcdif.yaml diff --git a/drivers/mipi_dbi/CMakeLists.txt b/drivers/mipi_dbi/CMakeLists.txt index fbcdc4d177b6b..5e9f475d151d6 100644 --- a/drivers/mipi_dbi/CMakeLists.txt +++ b/drivers/mipi_dbi/CMakeLists.txt @@ -5,3 +5,15 @@ zephyr_sources_ifdef(CONFIG_MIPI_DBI_SPI mipi_dbi_spi.c) zephyr_sources_ifdef(CONFIG_MIPI_DBI_SMARTBOND mipi_dbi_smartbond.c) zephyr_sources_ifdef(CONFIG_MIPI_DBI_NXP_LCDIC mipi_dbi_nxp_lcdic.c) +zephyr_sources_ifdef(CONFIG_MIPI_DBI_NXP_FLEXIO_LCDIF mipi_dbi_nxp_flexio_lcdif.c) +# Data bus width is used by the SDK driver and processes it as a compile time option +if(CONFIG_MIPI_DBI_NXP_FLEXIO_LCDIF) + dt_chosen(flexio0_lcd PROPERTY "zephyr,display") + dt_prop(data_bus_width PATH "${flexio0_lcd}" PROPERTY "mipi-mode") + # Values for mipi-mode property are defined inside dt-bindings/mipi_dbi/mipi_dbi.h. + # We pass a define to the SDK driver if we are using 8-bit mode. + if((data_bus_width EQUAL 8) OR (data_bus_width EQUAL 5)) + zephyr_compile_definitions(FLEXIO_MCULCD_DATA_BUS_WIDTH=8) + endif() + zephyr_compile_definitions(FLEXIO_MCULCD_LEGACY_GPIO_FUNC=0) +endif() diff --git a/drivers/mipi_dbi/Kconfig b/drivers/mipi_dbi/Kconfig index 16b7fc41c2d0a..51181ddd1e42c 100644 --- a/drivers/mipi_dbi/Kconfig +++ b/drivers/mipi_dbi/Kconfig @@ -24,5 +24,6 @@ config MIPI_DBI_INIT_PRIORITY source "drivers/mipi_dbi/Kconfig.spi" source "drivers/mipi_dbi/Kconfig.smartbond" source "drivers/mipi_dbi/Kconfig.nxp_lcdic" +source "drivers/mipi_dbi/Kconfig.nxp_flexio_lcdif" endif diff --git a/drivers/mipi_dbi/Kconfig.nxp_flexio_lcdif b/drivers/mipi_dbi/Kconfig.nxp_flexio_lcdif new file mode 100644 index 0000000000000..ae4e2ad2d4b00 --- /dev/null +++ b/drivers/mipi_dbi/Kconfig.nxp_flexio_lcdif @@ -0,0 +1,12 @@ +# Copyright 2024 NXP +# SPDX-License-Identifier: Apache-2.0 + +config MIPI_DBI_NXP_FLEXIO_LCDIF + bool "MIPI DBI driver for NXP Flexio LCDIF" + default y + depends on DT_HAS_NXP_MIPI_DBI_FLEXIO_LCDIF_ENABLED + depends on CLOCK_CONTROL + select MCUX_FLEXIO + select DMA + help + Enable support for MIPI DBI driver for NXP FlexIO based LCDIF controller. diff --git a/drivers/mipi_dbi/mipi_dbi_nxp_flexio_lcdif.c b/drivers/mipi_dbi/mipi_dbi_nxp_flexio_lcdif.c new file mode 100644 index 0000000000000..15156cc4fad06 --- /dev/null +++ b/drivers/mipi_dbi/mipi_dbi_nxp_flexio_lcdif.c @@ -0,0 +1,485 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT nxp_mipi_dbi_flexio_lcdif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +LOG_MODULE_REGISTER(display_mcux_flexio_lcdif, CONFIG_DISPLAY_LOG_LEVEL); + +struct stream { + const struct device *dma_dev; + uint32_t channel; /* stores the channel for dma */ + struct dma_config dma_cfg; + struct dma_block_config dma_blk_cfg; +}; + +struct mcux_flexio_lcdif_config { + FLEXIO_MCULCD_Type *flexio_lcd_dev; + const struct device *flexio_dev; + const struct pinctrl_dev_config *pincfg; + const struct nxp_flexio_child *child; + /* Reset GPIO */ + const struct gpio_dt_spec reset; + const struct gpio_dt_spec cs_gpio; + const struct gpio_dt_spec rs_gpio; + const struct gpio_dt_spec rdwr_gpio; +}; + +struct mcux_flexio_lcdif_data { + struct stream dma_tx; + struct k_sem transfer_done; + const struct mipi_dbi_config *active_cfg; + uint8_t data_bus_width; +}; + +static void flexio_lcdif_dma_callback(const struct device *dev, void *arg, + uint32_t channel, int status) +{ + const struct device *flexio_dev = (struct device *)arg; + struct mcux_flexio_lcdif_data *lcdif_data = flexio_dev->data; + const struct mcux_flexio_lcdif_config *config = flexio_dev->config; + FLEXIO_MCULCD_Type *flexio_lcd = config->flexio_lcd_dev; + + FLEXIO_MCULCD_EnableTxDMA(flexio_lcd, false); + + /* Now the data are in shifter, wait for the data send out from the shifter. */ + FLEXIO_MCULCD_WaitTransmitComplete(); + + /* Disable the TX shifter and the timer. */ + FLEXIO_MCULCD_ClearMultiBeatsWriteConfig(flexio_lcd); + + /* De-assert nCS. */ + FLEXIO_MCULCD_StopTransfer(flexio_lcd); + + k_sem_give(&lcdif_data->transfer_done); +} + + +static void flexio_lcdif_set_cs(bool set, void *param) +{ + const struct device *flexio_dev = (struct device *)param; + const struct mcux_flexio_lcdif_config *config = flexio_dev->config; + + gpio_pin_set_dt(&config->cs_gpio, (int)set); +} + +static void flexio_lcdif_set_rs(bool set, void *param) +{ + const struct device *flexio_dev = (struct device *)param; + const struct mcux_flexio_lcdif_config *config = flexio_dev->config; + + gpio_pin_set_dt(&config->rs_gpio, (int)set); +} + +static void flexio_lcdif_set_rd_wr(bool set, void *param) +{ + const struct device *flexio_dev = (struct device *)param; + const struct mcux_flexio_lcdif_config *config = flexio_dev->config; + + gpio_pin_set_dt(&config->rdwr_gpio, (int)set); +} + +static edma_modulo_t flexio_lcdif_get_edma_modulo(uint8_t shifterNum) +{ + edma_modulo_t ret = kEDMA_ModuloDisable; + + switch (shifterNum) { + case 1U: + ret = kEDMA_Modulo4bytes; + break; + case 2U: + ret = kEDMA_Modulo8bytes; + break; + case 4U: + ret = kEDMA_Modulo16bytes; + break; + case 8U: + ret = kEDMA_Modulo32bytes; + break; + default: + ret = kEDMA_ModuloDisable; + break; + } + + return ret; +} + +static void flexio_lcdif_write_data_array(FLEXIO_MCULCD_Type *base, + const void *data, + size_t size) +{ + assert(size > 0U); + + uint32_t i; + const uint8_t *data8Bit; + FLEXIO_Type *flexioBase = base->flexioBase; + + /* Assert the RS pin. */ + base->setRSPin(true, base->userData); + /* For 6800, de-assert the RDWR pin. */ + if (kFLEXIO_MCULCD_6800 == base->busType) { + base->setRDWRPin(false, base->userData); + } + + /* Configure the timer and TX shifter. */ + FLEXIO_MCULCD_SetSingleBeatWriteConfig(base); + + data8Bit = (const uint8_t *)data; + + for (i = 0; i < size; i++) { + flexioBase->SHIFTBUF[base->txShifterStartIndex] = data8Bit[i]; + + /* Wait for the data send out. */ + while (0U == ((1UL << base->timerIndex) & flexioBase->TIMSTAT)) { + } + + /* Clear the timer stat. */ + flexioBase->TIMSTAT = 1UL << base->timerIndex; + } + + /* Stop the timer and TX shifter. */ + FLEXIO_MCULCD_ClearSingleBeatWriteConfig(base); +} + +static int mipi_dbi_flexio_lcdif_configure(const struct device *dev, + const struct mipi_dbi_config *dbi_config) +{ + const struct mcux_flexio_lcdif_config *config = dev->config; + struct mcux_flexio_lcdif_data *lcdif_data = dev->data; + flexio_mculcd_config_t flexioMcuLcdConfig; + int err; + uint32_t clock_freq; + uint32_t mipi_mode = dbi_config->mode; + status_t status; + + /* 9-bit mode is not supported by the SDK driver */ + if ((mipi_mode == MIPI_DBI_MODE_6800_BUS_9_BIT) || + (mipi_mode == MIPI_DBI_MODE_8080_BUS_9_BIT)) { + return -EINVAL; + } + + if (dbi_config == lcdif_data->active_cfg) { + return 0; + } + + err = gpio_pin_configure_dt(&config->cs_gpio, GPIO_OUTPUT_HIGH); + if (err) { + return err; + } + + err = gpio_pin_configure_dt(&config->rs_gpio, GPIO_OUTPUT_HIGH); + if (err) { + return err; + } + + if ((mipi_mode == MIPI_DBI_MODE_6800_BUS_16_BIT) || + (mipi_mode == MIPI_DBI_MODE_6800_BUS_8_BIT)) { + /* RDWR GPIO is only used in 68K mode */ + err = gpio_pin_configure_dt(&config->rdwr_gpio, GPIO_OUTPUT_HIGH); + if (err) { + return err; + } + config->flexio_lcd_dev->busType = kFLEXIO_MCULCD_6800; + } else { + config->flexio_lcd_dev->busType = kFLEXIO_MCULCD_8080; + } + + if ((mipi_mode == MIPI_DBI_MODE_6800_BUS_8_BIT) || + (mipi_mode == MIPI_DBI_MODE_8080_BUS_8_BIT)) { + lcdif_data->data_bus_width = 8; + } else { + lcdif_data->data_bus_width = 16; + } + + FLEXIO_MCULCD_GetDefaultConfig(&flexioMcuLcdConfig); + flexioMcuLcdConfig.baudRate_Bps = dbi_config->config.frequency * + lcdif_data->data_bus_width; + + if (nxp_flexio_get_rate(config->flexio_dev, &clock_freq)) { + return -EINVAL; + } + + nxp_flexio_lock(config->flexio_dev); + /* Resets the FlexIO module, then configures FlexIO MCULCD */ + status = FLEXIO_MCULCD_Init(config->flexio_lcd_dev, &flexioMcuLcdConfig, clock_freq); + nxp_flexio_unlock(config->flexio_dev); + + if (kStatus_Success != status) { + return -EINVAL; + } + + lcdif_data->active_cfg = dbi_config; + + return 0; +} + +static int mipi_dbi_flexio_ldcif_write_display(const struct device *dev, + const struct mipi_dbi_config *dbi_config, + const uint8_t *framebuf, + struct display_buffer_descriptor *desc, + enum display_pixel_format pixfmt) +{ + const struct mcux_flexio_lcdif_config *config = dev->config; + struct mcux_flexio_lcdif_data *lcdif_data = dev->data; + FLEXIO_MCULCD_Type *flexio_lcd = config->flexio_lcd_dev; + struct dma_block_config *blk_cfg; + struct stream *stream = &lcdif_data->dma_tx; + uint8_t num_of_shifters = 0; + int ret; + + ARG_UNUSED(pixfmt); + + ret = mipi_dbi_flexio_lcdif_configure(dev, dbi_config); + if (ret) { + return ret; + } + + num_of_shifters = (flexio_lcd->txShifterEndIndex - flexio_lcd->txShifterStartIndex + 1); + + blk_cfg = &stream->dma_blk_cfg; + + /* Assert the nCS. */ + FLEXIO_MCULCD_StartTransfer(config->flexio_lcd_dev); + + /* prepare the block for this TX DMA channel */ + memset(blk_cfg, 0, sizeof(struct dma_block_config)); + + /* tx direction has memory as source and periph as dest. */ + blk_cfg->source_address = (uint32_t)framebuf; + + /* Destination is FLEXIO Shifters */ + blk_cfg->dest_address = FLEXIO_MCULCD_GetTxDataRegisterAddress(flexio_lcd); + blk_cfg->block_size = desc->buf_size; + /* Transfer in each DMA loop is based on the number of shifters used */ + stream->dma_cfg.source_burst_length = num_of_shifters * 4; + + stream->dma_cfg.head_block = &stream->dma_blk_cfg; + /* Give the client dev as arg, as the callback comes from the dma */ + stream->dma_cfg.user_data = (struct device *)dev; + + /* Set the source size in bytes */ + stream->dma_cfg.source_data_size = lcdif_data->data_bus_width / 8; + + /* Configure the DMA */ + dma_config(lcdif_data->dma_tx.dma_dev, lcdif_data->dma_tx.channel, &stream->dma_cfg); + + /* The DMA driver does not support setting this Modulo value which is required + * in case of the flexio module to form a circular chain between the Shift buffer + * in the FLEXIO module. + */ + EDMA_SetModulo(DMA0, lcdif_data->dma_tx.channel, kEDMA_ModuloDisable, + flexio_lcdif_get_edma_modulo(num_of_shifters)); + + /* For 6800, de-assert the RDWR pin. */ + if (kFLEXIO_MCULCD_6800 == flexio_lcd->busType) { + flexio_lcdif_set_rd_wr(false, (void *)dev); + } + + nxp_flexio_lock(config->flexio_dev); + FLEXIO_MCULCD_SetMultiBeatsWriteConfig(flexio_lcd); + FLEXIO_MCULCD_EnableTxDMA(flexio_lcd, true); + nxp_flexio_unlock(config->flexio_dev); + + /* Start the data transfer */ + dma_start(lcdif_data->dma_tx.dma_dev, lcdif_data->dma_tx.channel); + + /* Wait for transfer done. */ + k_sem_take(&lcdif_data->transfer_done, K_FOREVER); + + return 0; +} + +static int mipi_dbi_flexio_lcdif_command_write(const struct device *dev, + const struct mipi_dbi_config *dbi_config, + uint8_t cmd, const uint8_t *data_buf, + size_t len) +{ + const struct mcux_flexio_lcdif_config *config = dev->config; + FLEXIO_MCULCD_Type *flexio_lcd = config->flexio_lcd_dev; + int ret; + + ARG_UNUSED(dbi_config); + + ret = mipi_dbi_flexio_lcdif_configure(dev, dbi_config); + if (ret) { + return ret; + } + + FLEXIO_MCULCD_StartTransfer(flexio_lcd); + + nxp_flexio_lock(config->flexio_dev); + + FLEXIO_MCULCD_WriteCommandBlocking(flexio_lcd, cmd); + + if ((data_buf != NULL) && (len != 0)) { + flexio_lcdif_write_data_array(flexio_lcd, data_buf, len); + } + + nxp_flexio_unlock(config->flexio_dev); + + FLEXIO_MCULCD_StopTransfer(flexio_lcd); + + return kStatus_Success; + +} + +static int mipi_dbi_flexio_lcdif_reset(const struct device *dev, uint32_t delay) +{ + int err; + const struct mcux_flexio_lcdif_config *config = dev->config; + + /* Check if a reset port is provided to reset the LCD controller */ + if (config->reset.port == NULL) { + return 0; + } + + /* Reset the LCD controller. */ + err = gpio_pin_configure_dt(&config->reset, GPIO_OUTPUT_HIGH); + if (err) { + return err; + } + + err = gpio_pin_set_dt(&config->reset, 0); + if (err < 0) { + return err; + } + + k_msleep(delay); + + err = gpio_pin_set_dt(&config->reset, 1); + if (err < 0) { + return err; + } + + LOG_DBG("%s device reset complete", dev->name); + + return 0; +} + +static int flexio_lcdif_init(const struct device *dev) +{ + const struct mcux_flexio_lcdif_config *config = dev->config; + struct mcux_flexio_lcdif_data *lcdif_data = dev->data; + int err; + uint8_t shifter_end = config->child->res.shifter_count - 1; + + if (!device_is_ready(lcdif_data->dma_tx.dma_dev)) { + LOG_ERR("%s device is not ready", lcdif_data->dma_tx.dma_dev->name); + return -ENODEV; + } + + err = nxp_flexio_child_attach(config->flexio_dev, config->child); + if (err < 0) { + return err; + } + + config->flexio_lcd_dev->txShifterStartIndex = config->child->res.shifter_index[0]; + config->flexio_lcd_dev->txShifterEndIndex = config->child->res.shifter_index[shifter_end]; + + config->flexio_lcd_dev->rxShifterStartIndex = config->flexio_lcd_dev->txShifterStartIndex; + config->flexio_lcd_dev->rxShifterEndIndex = config->flexio_lcd_dev->txShifterEndIndex; + + config->flexio_lcd_dev->timerIndex = config->child->res.timer_index[0]; + + if (config->flexio_lcd_dev->txShifterEndIndex != + config->flexio_lcd_dev->txShifterStartIndex + shifter_end) { + LOG_ERR("Shifters should be continuous"); + return -ENODEV; + } + err = pinctrl_apply_state(config->pincfg, PINCTRL_STATE_DEFAULT); + if (err) { + return err; + } + + /* Pass the FlexIO LCD device as parameter to the function + * callbacks for setting GPIO signals. + */ + config->flexio_lcd_dev->userData = (void *)dev; + + + k_sem_init(&lcdif_data->transfer_done, 0, 1); + + LOG_DBG("%s device init complete", dev->name); + + return 0; +} + +static struct mipi_dbi_driver_api mipi_dbi_lcdif_driver_api = { + .reset = mipi_dbi_flexio_lcdif_reset, + .command_write = mipi_dbi_flexio_lcdif_command_write, + .write_display = mipi_dbi_flexio_ldcif_write_display, +}; + +#define MCUX_FLEXIO_LCDIF_DEVICE_INIT(n) \ + PINCTRL_DT_INST_DEFINE(n); \ + \ + static FLEXIO_MCULCD_Type flexio_mculcd_##n = { \ + .flexioBase = (FLEXIO_Type *)DT_REG_ADDR(DT_INST_PARENT(n)), \ + .dataPinStartIndex = DT_INST_PROP(n, data_pin_start), \ + .ENWRPinIndex = DT_INST_PROP(n, enwr_pin), \ + .RDPinIndex = DT_INST_PROP_OR(n, rd_pin, 0), \ + .setCSPin = flexio_lcdif_set_cs, \ + .setRSPin = flexio_lcdif_set_rs, \ + .setRDWRPin = flexio_lcdif_set_rd_wr, \ + }; \ + \ + static uint8_t mcux_flexio_lcdif_shifters_##n[DT_INST_PROP(n, shifters_count)]; \ + static uint8_t mcux_flexio_lcdif_timers_##n[DT_INST_PROP(n, timers_count)]; \ + \ + static const struct nxp_flexio_child lcdif_child_##n = { \ + .isr = NULL, \ + .user_data = (void *)DEVICE_DT_INST_GET(n), \ + .res = { \ + .shifter_index = mcux_flexio_lcdif_shifters_##n, \ + .shifter_count = ARRAY_SIZE(mcux_flexio_lcdif_shifters_##n), \ + .timer_index = mcux_flexio_lcdif_timers_##n, \ + .timer_count = ARRAY_SIZE(mcux_flexio_lcdif_timers_##n), \ + } \ + }; \ + \ + struct mcux_flexio_lcdif_config mcux_flexio_lcdif_config_##n = { \ + .flexio_lcd_dev = &flexio_mculcd_##n, \ + .flexio_dev = DEVICE_DT_GET(DT_INST_PARENT(n)), \ + .pincfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n), \ + .child = &lcdif_child_##n, \ + .reset = GPIO_DT_SPEC_INST_GET(n, reset_gpios), \ + .cs_gpio = GPIO_DT_SPEC_INST_GET(n, cs_gpios), \ + .rs_gpio = GPIO_DT_SPEC_INST_GET(n, rs_gpios), \ + .rdwr_gpio = GPIO_DT_SPEC_INST_GET_OR(n, rdwr_gpios, {0}), \ + }; \ + struct mcux_flexio_lcdif_data mcux_flexio_lcdif_data_##n = { \ + .dma_tx = { \ + .dma_dev = DEVICE_DT_GET(DT_INST_DMAS_CTLR_BY_NAME(n, tx)), \ + .channel = DT_INST_DMAS_CELL_BY_NAME(n, tx, mux), \ + .dma_cfg = { \ + .channel_direction = MEMORY_TO_MEMORY, \ + .dma_callback = flexio_lcdif_dma_callback, \ + .dest_data_size = 4, \ + .block_count = 1, \ + .dma_slot = DT_INST_DMAS_CELL_BY_NAME(n, tx, source) \ + } \ + }, \ + }; \ + DEVICE_DT_INST_DEFINE(n, \ + &flexio_lcdif_init, \ + NULL, \ + &mcux_flexio_lcdif_data_##n, \ + &mcux_flexio_lcdif_config_##n, \ + POST_KERNEL, \ + CONFIG_MIPI_DBI_INIT_PRIORITY, \ + &mipi_dbi_lcdif_driver_api); + +DT_INST_FOREACH_STATUS_OKAY(MCUX_FLEXIO_LCDIF_DEVICE_INIT) diff --git a/dts/arm/nxp/nxp_mcxn94x_common.dtsi b/dts/arm/nxp/nxp_mcxn94x_common.dtsi index 054ad3700d8c1..c14a6f2698e84 100644 --- a/dts/arm/nxp/nxp_mcxn94x_common.dtsi +++ b/dts/arm/nxp/nxp_mcxn94x_common.dtsi @@ -904,6 +904,18 @@ clk-source = <1>; resolution = <32>; }; + + flexio0: flexio@105000 { + compatible = "nxp,flexio"; + reg = <0x105000 0x1000>; + status = "disabled"; + interrupts = <105 0>; + clocks = <&syscon MCUX_FLEXIO0_CLK>; + flexio0_lcd: flexio0-lcd { + compatible = "nxp,mipi-dbi-flexio-lcdif"; + status = "disabled"; + }; + }; }; &systick { diff --git a/dts/bindings/mipi-dbi/nxp,mipi-dbi-flexio-lcdif.yaml b/dts/bindings/mipi-dbi/nxp,mipi-dbi-flexio-lcdif.yaml new file mode 100644 index 0000000000000..25851966505d9 --- /dev/null +++ b/dts/bindings/mipi-dbi/nxp,mipi-dbi-flexio-lcdif.yaml @@ -0,0 +1,63 @@ +# Copyright 2024 NXP +# SPDX-License-Identifier: Apache-2.0 + +description: NXP FlexIO LCD controller + +compatible: "nxp,mipi-dbi-flexio-lcdif" + +include: [mipi-dbi-controller.yaml, base.yaml, pinctrl-device.yaml] + +properties: + shifters-count: + type: int + required: true + description: | + Number of FlexIO shifters needed. + + timers-count: + type: int + required: true + description: | + Number of FlexIO timers needed. + + enwr-pin: + type: int + required: true + description: | + Pin select for WR(8080 mode), EN(6800 mode). + + rd-pin: + type: int + description: | + Pin select for RD(8080 mode), not used in 6800 mode. + + data-pin-start: + type: int + required: true + description: | + Start index of the data pin. + + cs-gpios: + type: phandle-array + required: true + description: | + CS Pin + GPIO to drive the CS pin. + + rs-gpios: + type: phandle-array + required: true + description: | + RS Pin + GPIO to drive the RS pin. + + rdwr-gpios: + type: phandle-array + description: | + RDWR Pin + GPIO to drive the RDWR pin. This is required for Motorola 68K bus. + + reset-gpios: + type: phandle-array + description: | + Reset GPIO pin. From 3fbd689eaaa050be7980de75a158c85f4ea4d507 Mon Sep 17 00:00:00 2001 From: Mahesh Mahadevan Date: Thu, 11 Apr 2024 07:50:42 -0500 Subject: [PATCH 2630/2849] boards: shield: Add a shield for the NXP LCD-PAR-S035 LCD module NXP LCD-PAR-S035 LCD module will be used by FRDM-X evaluation kits with a parallel LCD connector. Signed-off-by: Mahesh Mahadevan --- boards/shields/lcd_par_s035/Kconfig.defconfig | 16 ++++++++ boards/shields/lcd_par_s035/Kconfig.shield | 5 +++ boards/shields/lcd_par_s035/doc/index.rst | 40 ++++++++++++++++++ .../lcd_par_s035/lcd_par_s035_8080.overlay | 41 +++++++++++++++++++ 4 files changed, 102 insertions(+) create mode 100644 boards/shields/lcd_par_s035/Kconfig.defconfig create mode 100644 boards/shields/lcd_par_s035/Kconfig.shield create mode 100644 boards/shields/lcd_par_s035/doc/index.rst create mode 100644 boards/shields/lcd_par_s035/lcd_par_s035_8080.overlay diff --git a/boards/shields/lcd_par_s035/Kconfig.defconfig b/boards/shields/lcd_par_s035/Kconfig.defconfig new file mode 100644 index 0000000000000..07f0bb7bab1af --- /dev/null +++ b/boards/shields/lcd_par_s035/Kconfig.defconfig @@ -0,0 +1,16 @@ +# Copyright 2024 NXP +# SPDX-License-Identifier: Apache-2.0 + +if SHIELD_LCD_PAR_S035 +if LVGL + +# Enable double buffering +config LV_Z_DOUBLE_VDB + default y + +config LV_Z_BITS_PER_PIXEL + default 16 + +endif # LVGL + +endif # SHIELD_LCD_PAR_S035 diff --git a/boards/shields/lcd_par_s035/Kconfig.shield b/boards/shields/lcd_par_s035/Kconfig.shield new file mode 100644 index 0000000000000..4dba938831b0a --- /dev/null +++ b/boards/shields/lcd_par_s035/Kconfig.shield @@ -0,0 +1,5 @@ +# Copyright 2024 NXP +# SPDX-License-Identifier: Apache-2.0 + +config SHIELD_LCD_PAR_S035 + def_bool $(shields_list_contains,lcd_par_s035_8080) diff --git a/boards/shields/lcd_par_s035/doc/index.rst b/boards/shields/lcd_par_s035/doc/index.rst new file mode 100644 index 0000000000000..fdaa6307e6856 --- /dev/null +++ b/boards/shields/lcd_par_s035/doc/index.rst @@ -0,0 +1,40 @@ +.. _lcd_par_s035: + +NXP LCD_PAR_S035 TFT LCD Module +############################### + +Overview +******** + +The LCD-PAR-S035 is a 3.5” 480x320 IPS TFT LCD module with wide viewing angle +and 5-point capacitive touch functionality. The LCD module can be controlled +through either SPI or parallel (8/16bit) 8080/6800. +More information about the shield can be found +at the `LCD-PAR-S035 product page`_. + +Requirements +************ + +This shield can only be used with FRDM-X evaluation kits with a parallel LCD +connector or a PMOD connector. Currently only the parallel LCD connector is +enabled. + +Programming +*********** + +Set ``-DSHIELD=lcd_par_s035_8080`` when you invoke ``west build``. For +example: + +.. zephyr-app-commands:: + :zephyr-app: samples/drivers/display + :board: frdm_mcxn947/mcxn947/cpu0 + :shield: lcd_par_s035_8080 + :goals: build + +References +********** + +.. target-notes:: + +.. _LCD-PAR-S035 product page: + https://www.nxp.com/design/design-center/development-boards-and-designs/general-purpose-mcus/3-5-480x320-ips-tft-lcd-module:LCD-PAR-S035 diff --git a/boards/shields/lcd_par_s035/lcd_par_s035_8080.overlay b/boards/shields/lcd_par_s035/lcd_par_s035_8080.overlay new file mode 100644 index 0000000000000..eaf7b8b9c03fb --- /dev/null +++ b/boards/shields/lcd_par_s035/lcd_par_s035_8080.overlay @@ -0,0 +1,41 @@ +/* + * Copyright 2024 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +/{ + chosen { + zephyr,display = &st7796s; + }; +}; + +&nxp_flexio_lcd { + status = "okay"; + #address-cells = <1>; + #size-cells = <0>; + st7796s: st7796s@0 { + compatible = "sitronix,st7796s"; + reg = <0>; + /* Baud rate on each pin is 1MHz */ + mipi-max-frequency = <10000000>; + mipi-mode = ; + 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 33]; + 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>; + color-invert; + }; +}; From b2d1e4505febd3c664d38e6a5450205b833cd6f8 Mon Sep 17 00:00:00 2001 From: Mahesh Mahadevan Date: Tue, 16 Apr 2024 13:41:30 -0500 Subject: [PATCH 2631/2849] boards: frdm_mcxn947: Add Display support Add support for the LCD-PAR-S035 display over the FlexIO interface. Signed-off-by: Mahesh Mahadevan --- boards/nxp/frdm_mcxn947/board.c | 5 +++ boards/nxp/frdm_mcxn947/doc/index.rst | 5 +++ .../frdm_mcxn947/frdm_mcxn947-pinctrl.dtsi | 42 +++++++++++++++++++ boards/nxp/frdm_mcxn947/frdm_mcxn947.dtsi | 16 +++++++ .../frdm_mcxn947_mcxn947_cpu0.dts | 4 ++ 5 files changed, 72 insertions(+) diff --git a/boards/nxp/frdm_mcxn947/board.c b/boards/nxp/frdm_mcxn947/board.c index b5394abae3be6..ab41600737c6a 100644 --- a/boards/nxp/frdm_mcxn947/board.c +++ b/boards/nxp/frdm_mcxn947/board.c @@ -302,6 +302,11 @@ static int frdm_mcxn947_init(void) CLOCK_SetupClk16KClocking(kCLOCK_Clk16KToVsys); #endif +#if DT_NODE_HAS_STATUS(DT_NODELABEL(flexio0), okay) + CLOCK_SetClkDiv(kCLOCK_DivFlexioClk, 1u); + CLOCK_AttachClk(kPLL0_to_FLEXIO); +#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 1ed7faf4b0176..7b4a4d9b357b2 100644 --- a/boards/nxp/frdm_mcxn947/doc/index.rst +++ b/boards/nxp/frdm_mcxn947/doc/index.rst @@ -96,6 +96,11 @@ The FRDM-MCXN947 board configuration supports the following hardware features: +-----------+------------+-------------------------------------+ | LPTMR | on-chip | counter | +-----------+------------+-------------------------------------+ +| FLEXIO | on-chip | flexio | ++-----------+------------+-------------------------------------+ +| DISPLAY | on-chip | flexio; MIPI-DBI. Tested with | +| | | :ref:`lcd_par_s035` | ++-----------+------------+-------------------------------------+ Targets available ================== diff --git a/boards/nxp/frdm_mcxn947/frdm_mcxn947-pinctrl.dtsi b/boards/nxp/frdm_mcxn947/frdm_mcxn947-pinctrl.dtsi index 13e6f47f5e5e8..68a1fa17301ff 100644 --- a/boards/nxp/frdm_mcxn947/frdm_mcxn947-pinctrl.dtsi +++ b/boards/nxp/frdm_mcxn947/frdm_mcxn947-pinctrl.dtsi @@ -148,6 +148,7 @@ input-enable; }; }; + pinmux_lpadc0: pinmux_lpadc0 { group0 { pinmux = , @@ -176,4 +177,45 @@ input-enable; }; }; + + pinmux_flexio_lcd: pinmux_flexio_lcd { + group0 { + pinmux = , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + ; + slew-rate = "fast"; + drive-strength = "low"; + input-enable; + }; + group1 { + pinmux = ; + slew-rate = "fast"; + drive-strength = "low"; + input-enable; + bias-pull-up; + }; + group2 { + pinmux = ; + slew-rate = "slow"; + drive-strength = "low"; + input-enable; + bias-pull-up; + }; + }; }; diff --git a/boards/nxp/frdm_mcxn947/frdm_mcxn947.dtsi b/boards/nxp/frdm_mcxn947/frdm_mcxn947.dtsi index 31292bdf72867..77708792e49d2 100644 --- a/boards/nxp/frdm_mcxn947/frdm_mcxn947.dtsi +++ b/boards/nxp/frdm_mcxn947/frdm_mcxn947.dtsi @@ -196,6 +196,22 @@ pinctrl-names = "default"; }; +nxp_flexio_lcd: &flexio0_lcd { + /* DMA channels 0, muxed to FlexIO TX */ + dmas = <&edma0 0 61>; + dma-names = "tx"; + shifters-count = <8>; + timers-count = <1>; + enwr-pin = <1>; + rd-pin = <0>; + data-pin-start = <16>; + reset-gpios = <&gpio4 7 GPIO_ACTIVE_HIGH>; + cs-gpios = <&gpio0 12 GPIO_ACTIVE_HIGH>; + rs-gpios = <&gpio0 7 GPIO_ACTIVE_HIGH>; + pinctrl-0 = <&pinmux_flexio_lcd>; + pinctrl-names = "default"; +}; + &lpcmp0 { pinctrl-0 = <&pinmux_lpcmp0>; 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 f6111bb41f06d..0651a532a1832 100644 --- a/boards/nxp/frdm_mcxn947/frdm_mcxn947_mcxn947_cpu0.dts +++ b/boards/nxp/frdm_mcxn947/frdm_mcxn947_mcxn947_cpu0.dts @@ -178,3 +178,7 @@ zephyr_udc0: &usb1 { &lptmr0 { status = "okay"; }; + +&flexio0 { + status = "okay"; +}; From 7902457437bb7526e0c30891ebdde7de998bd36c Mon Sep 17 00:00:00 2001 From: Andries Kruithof Date: Thu, 8 Feb 2024 14:31:17 +0100 Subject: [PATCH 2632/2849] Bluetooth: audio: test: Unittests for broadcast reception start Implement unit tests for the broadcast reception start procedure, both with proper and with improper parameters. Signed-off-by: Andries Kruithof --- .../audio/cap_commander/CMakeLists.txt | 6 +- tests/bluetooth/audio/cap_commander/prj.conf | 2 +- .../src/test_broadcast_reception.c | 373 ++++++++++++++++++ .../audio/mocks/include/cap_commander.h | 1 + .../bluetooth/audio/mocks/src/cap_commander.c | 7 +- 5 files changed, 385 insertions(+), 4 deletions(-) create mode 100644 tests/bluetooth/audio/cap_commander/src/test_broadcast_reception.c diff --git a/tests/bluetooth/audio/cap_commander/CMakeLists.txt b/tests/bluetooth/audio/cap_commander/CMakeLists.txt index 11a19d9530d58..a947f47b8ea9d 100644 --- a/tests/bluetooth/audio/cap_commander/CMakeLists.txt +++ b/tests/bluetooth/audio/cap_commander/CMakeLists.txt @@ -13,9 +13,11 @@ target_include_directories(testbinary PRIVATE include) target_sources(testbinary PRIVATE - ${ZEPHYR_BASE}/subsys/bluetooth/host/uuid.c - src/main.c + ${ZEPHYR_BASE}/subsys/bluetooth/host/uuid.c + ${ZEPHYR_BASE}/subsys/bluetooth/common/addr.c + src/main.c src/test_common.c src/test_vcp.c src/test_micp.c + src/test_broadcast_reception.c ) diff --git a/tests/bluetooth/audio/cap_commander/prj.conf b/tests/bluetooth/audio/cap_commander/prj.conf index 231fe10c2e184..f7b79fe1876b8 100644 --- a/tests/bluetooth/audio/cap_commander/prj.conf +++ b/tests/bluetooth/audio/cap_commander/prj.conf @@ -18,7 +18,7 @@ CONFIG_BT_CAP_COMMANDER=y CONFIG_BT_BAP_BROADCAST_ASSISTANT=y CONFIG_LOG=y CONFIG_BT_CAP_COMMANDER_LOG_LEVEL_DBG=y - +CONFIG_BT_BAP_BASS_MAX_SUBGROUPS=2 CONFIG_ASSERT=y CONFIG_ASSERT_LEVEL=2 CONFIG_ASSERT_VERBOSE=y diff --git a/tests/bluetooth/audio/cap_commander/src/test_broadcast_reception.c b/tests/bluetooth/audio/cap_commander/src/test_broadcast_reception.c new file mode 100644 index 0000000000000..a978b7ec621d0 --- /dev/null +++ b/tests/bluetooth/audio/cap_commander/src/test_broadcast_reception.c @@ -0,0 +1,373 @@ +/* test_broadcast_reception.c - unit test for broadcast reception */ + +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +#include +#include +#include + +#include "bluetooth.h" +#include "cap_commander.h" +#include "conn.h" +#include "expects_util.h" +#include "cap_mocks.h" +#include "test_common.h" + +#include + +LOG_MODULE_REGISTER(bt_broadcast_reception_test, CONFIG_BT_CAP_COMMANDER_LOG_LEVEL); + +#define FFF_GLOBALS + +#define SID 0x0E +#define ADV_INTERVAL 10 +#define BROADCAST_ID 0x55AA55 + +struct cap_commander_test_broadcast_reception_fixture { + struct bt_conn conns[CONFIG_BT_MAX_CONN]; + + struct bt_bap_bass_subgroup start_subgroups[CONFIG_BT_BAP_BASS_MAX_SUBGROUPS]; + struct bt_cap_commander_broadcast_reception_start_member_param + start_member_params[CONFIG_BT_MAX_CONN]; + struct bt_cap_commander_broadcast_reception_start_param start_param; +}; + +static void test_start_param_init(void *f); + +static void cap_commander_test_broadcast_reception_fixture_init( + struct cap_commander_test_broadcast_reception_fixture *fixture) +{ + for (size_t i = 0; i < ARRAY_SIZE(fixture->conns); i++) { + test_conn_init(&fixture->conns[i]); + } + test_start_param_init(fixture); +} + +static void *cap_commander_test_broadcast_reception_setup(void) +{ + struct cap_commander_test_broadcast_reception_fixture *fixture; + + fixture = malloc(sizeof(*fixture)); + zassert_not_null(fixture); + + return fixture; +} + +static void cap_commander_test_broadcast_reception_before(void *f) +{ + memset(f, 0, sizeof(struct cap_commander_test_broadcast_reception_fixture)); + cap_commander_test_broadcast_reception_fixture_init(f); +} + +static void cap_commander_test_broadcast_reception_after(void *f) +{ + struct cap_commander_test_broadcast_reception_fixture *fixture = f; + + bt_cap_commander_unregister_cb(&mock_cap_commander_cb); + + for (size_t i = 0; i < ARRAY_SIZE(fixture->conns); i++) { + mock_bt_conn_disconnected(&fixture->conns[i], BT_HCI_ERR_REMOTE_USER_TERM_CONN); + } +} + +static void cap_commander_test_broadcast_reception_teardown(void *f) +{ + free(f); +} + +static void test_start_param_init(void *f) +{ + struct cap_commander_test_broadcast_reception_fixture *fixture = f; + int err; + + fixture->start_param.type = BT_CAP_SET_TYPE_AD_HOC; + fixture->start_param.param = fixture->start_member_params; + + fixture->start_param.count = ARRAY_SIZE(fixture->start_member_params); + + for (size_t i = 0; i < ARRAY_SIZE(fixture->start_subgroups); i++) { + fixture->start_subgroups[i].bis_sync = 1 << i; + fixture->start_subgroups[i].metadata_len = 0; + } + + for (size_t i = 0U; i < ARRAY_SIZE(fixture->start_member_params); i++) { + fixture->start_member_params[i].member.member = &fixture->conns[i]; + bt_addr_le_copy(&fixture->start_member_params[i].addr, BT_ADDR_LE_ANY); + fixture->start_member_params[i].adv_sid = SID; + fixture->start_member_params[i].pa_interval = ADV_INTERVAL; + fixture->start_member_params[i].broadcast_id = BROADCAST_ID; + memcpy(fixture->start_member_params[i].subgroups, &fixture->start_subgroups[0], + sizeof(struct bt_bap_bass_subgroup) * CONFIG_BT_BAP_BASS_MAX_SUBGROUPS); + fixture->start_member_params[i].num_subgroups = CONFIG_BT_BAP_BASS_MAX_SUBGROUPS; + } + + for (size_t i = 0; i < ARRAY_SIZE(fixture->conns); i++) { + err = bt_cap_commander_discover(&fixture->conns[i]); + zassert_equal(0, err, "Unexpected return value %d", err); + } + + for (size_t i = 0U; i < ARRAY_SIZE(fixture->start_member_params); i++) { + fixture->start_member_params[i].member.member = &fixture->conns[i]; + } +} + +ZTEST_SUITE(cap_commander_test_broadcast_reception, NULL, + cap_commander_test_broadcast_reception_setup, + cap_commander_test_broadcast_reception_before, + cap_commander_test_broadcast_reception_after, + cap_commander_test_broadcast_reception_teardown); + +ZTEST_F(cap_commander_test_broadcast_reception, test_commander_reception_start) +{ + int err; + + err = bt_cap_commander_register_cb(&mock_cap_commander_cb); + zassert_equal(0, err, "Unexpected return value %d", err); + + err = bt_cap_commander_broadcast_reception_start(&fixture->start_param); + zassert_equal(0, err, "Unexpected return value %d", err); + + zexpect_call_count("bt_cap_commander_cb.broadcast_reception_start", 1, + mock_cap_commander_broadcast_reception_start_cb_fake.call_count); +} + +ZTEST_F(cap_commander_test_broadcast_reception, test_commander_reception_start_one_subgroup) +{ + int err; + + err = bt_cap_commander_register_cb(&mock_cap_commander_cb); + zassert_equal(0, err, "Unexpected return value %d", err); + + /* We test with one subgroup, instead of CONFIG_BT_BAP_BASS_MAX_SUBGROUPS subgroups */ + for (size_t i = 0U; i < CONFIG_BT_MAX_CONN; i++) { + fixture->start_param.param[i].num_subgroups = 1; + } + + err = bt_cap_commander_broadcast_reception_start(&fixture->start_param); + zassert_equal(0, err, "Unexpected return value %d", err); + + zexpect_call_count("bt_cap_commander_cb.broadcast_reception_start", 1, + mock_cap_commander_broadcast_reception_start_cb_fake.call_count); +} + +ZTEST_F(cap_commander_test_broadcast_reception, test_commander_reception_start_double) +{ + int err; + + err = bt_cap_commander_register_cb(&mock_cap_commander_cb); + zassert_equal(0, err, "Unexpected return value %d", err); + + err = bt_cap_commander_broadcast_reception_start(&fixture->start_param); + zassert_equal(0, err, "Unexpected return value %d", err); + + err = bt_cap_commander_broadcast_reception_start(&fixture->start_param); + zassert_equal(0, err, "Unexpected return value %d", err); + + zexpect_call_count("bt_cap_commander_cb.broadcast_reception_start", 2, + mock_cap_commander_broadcast_reception_start_cb_fake.call_count); +} + +ZTEST_F(cap_commander_test_broadcast_reception, test_commander_reception_start_inval_param_null) +{ + int err; + + err = bt_cap_commander_broadcast_reception_start(NULL); + zassert_equal(-EINVAL, err, "Unexpected return value %d", err); + + zexpect_call_count("bt_cap_commander_cb.broadcast_reception_start", 0, + mock_cap_commander_broadcast_reception_start_cb_fake.call_count); +} + +ZTEST_F(cap_commander_test_broadcast_reception, + test_commander_reception_start_inval_param_zero_count) +{ + int err; + + fixture->start_param.count = 0; + + err = bt_cap_commander_broadcast_reception_start(&fixture->start_param); + zassert_equal(-EINVAL, err, "Unexpected return value %d", err); + + zexpect_call_count("bt_cap_commander_cb.broadcast_reception_start", 0, + mock_cap_commander_broadcast_reception_start_cb_fake.call_count); +} + +ZTEST_F(cap_commander_test_broadcast_reception, + test_commander_reception_start_inval_param_high_count) +{ + int err; + + fixture->start_param.count = CONFIG_BT_MAX_CONN + 1; + + err = bt_cap_commander_broadcast_reception_start(&fixture->start_param); + zassert_equal(-EINVAL, err, "Unexpected return value %d", err); + + zexpect_call_count("bt_cap_commander_cb.broadcast_reception_start", 0, + mock_cap_commander_broadcast_reception_start_cb_fake.call_count); +} + +ZTEST_F(cap_commander_test_broadcast_reception, + test_commander_reception_start_inval_param_null_param) +{ + int err; + + fixture->start_param.type = BT_CAP_SET_TYPE_AD_HOC; + fixture->start_param.param = NULL; + fixture->start_param.count = ARRAY_SIZE(fixture->conns); + + err = bt_cap_commander_broadcast_reception_start(&fixture->start_param); + zassert_equal(-EINVAL, err, "Unexpected return value %d", err); + + zexpect_call_count("bt_cap_commander_cb.broadcast_reception_start", 0, + mock_cap_commander_broadcast_reception_start_cb_fake.call_count); +} + +ZTEST_F(cap_commander_test_broadcast_reception, test_commander_reception_start_inval_null_member) +{ + int err; + + fixture->start_param.param[0].member.member = NULL; + + err = bt_cap_commander_broadcast_reception_start(&fixture->start_param); + zassert_equal(-EINVAL, err, "Unexpected return value %d", err); + + zexpect_call_count("bt_cap_commander_cb.broadcast_reception_start", 0, + mock_cap_commander_broadcast_reception_start_cb_fake.call_count); +} + +ZTEST_F(cap_commander_test_broadcast_reception, test_commander_reception_start_inval_missing_cas) +{ + int err; + + fixture->start_param.type = BT_CAP_SET_TYPE_CSIP; + + err = bt_cap_commander_broadcast_reception_start(&fixture->start_param); + zassert_equal(-EINVAL, err, "Unexpected return value %d", err); + + zexpect_call_count("bt_cap_commander_cb.broadcast_reception_start", 0, + mock_cap_commander_broadcast_reception_start_cb_fake.call_count); +} + +ZTEST_F(cap_commander_test_broadcast_reception, test_commander_reception_start_inval_addr_type) +{ + int err; + + fixture->start_param.param[0].addr.type = BT_ADDR_LE_RANDOM + 1; + + err = bt_cap_commander_broadcast_reception_start(&fixture->start_param); + zassert_equal(-EINVAL, err, "Unexpected return value %d", err); + + zexpect_call_count("bt_cap_commander_cb.broadcast_reception_start", 0, + mock_cap_commander_broadcast_reception_start_cb_fake.call_count); +} + +ZTEST_F(cap_commander_test_broadcast_reception, test_commander_reception_start_inval_sid) +{ + int err; + + fixture->start_param.param[0].adv_sid = BT_GAP_SID_MAX + 1; + + err = bt_cap_commander_broadcast_reception_start(&fixture->start_param); + zassert_equal(-EINVAL, err, "Unexpected return value %d", err); + + zexpect_call_count("bt_cap_commander_cb.broadcast_reception_start", 0, + mock_cap_commander_broadcast_reception_start_cb_fake.call_count); +} + +ZTEST_F(cap_commander_test_broadcast_reception, + test_commander_reception_start_inval_pa_interval_low) +{ + int err; + + fixture->start_param.param[0].pa_interval = BT_GAP_PER_ADV_MIN_INTERVAL - 1; + + err = bt_cap_commander_broadcast_reception_start(&fixture->start_param); + zassert_equal(-EINVAL, err, "Unexpected return value %d", err); + + zexpect_call_count("bt_cap_commander_cb.broadcast_reception_start", 0, + mock_cap_commander_broadcast_reception_start_cb_fake.call_count); +} + +/* + * Test for pa_interval_high omitted + * pa_interval is a uint16_t, BT_GAP_PER_ADV_MAX_INTERVAL is defined as 0xFFFF + * and therefor we can not test in the current implementation + */ + +ZTEST_F(cap_commander_test_broadcast_reception, test_commander_reception_start_inval_broadcast_id) +{ + int err; + + fixture->start_param.param[0].broadcast_id = BT_AUDIO_BROADCAST_ID_MAX + 1; + + err = bt_cap_commander_broadcast_reception_start(&fixture->start_param); + zassert_equal(-EINVAL, err, "Unexpected return value %d", err); + + zexpect_call_count("bt_cap_commander_cb.broadcast_reception_start", 0, + mock_cap_commander_broadcast_reception_start_cb_fake.call_count); +} + +ZTEST_F(cap_commander_test_broadcast_reception, test_commander_reception_start_inval_no_subgroups) +{ + int err; + + fixture->start_param.param[0].num_subgroups = 0; + + err = bt_cap_commander_broadcast_reception_start(&fixture->start_param); + zassert_equal(-EINVAL, err, "Unexpected return value %d", err); + + zexpect_call_count("bt_cap_commander_cb.broadcast_reception_start", 0, + mock_cap_commander_broadcast_reception_start_cb_fake.call_count); +} + +ZTEST_F(cap_commander_test_broadcast_reception, test_commander_reception_start_inval_num_subgroups) +{ + int err; + + fixture->start_param.param[0].num_subgroups = CONFIG_BT_BAP_BASS_MAX_SUBGROUPS + 1; + + err = bt_cap_commander_broadcast_reception_start(&fixture->start_param); + zassert_equal(-EINVAL, err, "Unexpected return value %d", err); + + zexpect_call_count("bt_cap_commander_cb.broadcast_reception_start", 0, + mock_cap_commander_broadcast_reception_start_cb_fake.call_count); +} + +ZTEST_F(cap_commander_test_broadcast_reception, + test_commander_reception_start_inval_duplicate_bis_sync) +{ + int err; + + if (CONFIG_BT_BAP_BASS_MAX_SUBGROUPS == 1) { + ztest_test_skip(); + } + + fixture->start_param.param[0].subgroups[0].bis_sync = + fixture->start_param.param[0].subgroups[1].bis_sync; + + err = bt_cap_commander_broadcast_reception_start(&fixture->start_param); + zassert_equal(-EINVAL, err, "Unexpected return value %d", err); + + zexpect_call_count("bt_cap_commander_cb.broadcast_reception_start", 0, + mock_cap_commander_broadcast_reception_start_cb_fake.call_count); +} + +ZTEST_F(cap_commander_test_broadcast_reception, test_commander_reception_start_inval_metadata_len) +{ + int err; + + fixture->start_param.param[0].subgroups[0].metadata_len = + CONFIG_BT_AUDIO_CODEC_CFG_MAX_METADATA_SIZE + 1; + + err = bt_cap_commander_broadcast_reception_start(&fixture->start_param); + zassert_equal(-EINVAL, err, "Unexpected return value %d", err); + + zexpect_call_count("bt_cap_commander_cb.broadcast_reception_start", 0, + mock_cap_commander_broadcast_reception_start_cb_fake.call_count); +} diff --git a/tests/bluetooth/audio/mocks/include/cap_commander.h b/tests/bluetooth/audio/mocks/include/cap_commander.h index 6133ce2ae6416..3f1f8691fd96b 100644 --- a/tests/bluetooth/audio/mocks/include/cap_commander.h +++ b/tests/bluetooth/audio/mocks/include/cap_commander.h @@ -23,5 +23,6 @@ DECLARE_FAKE_VOID_FUNC(mock_cap_commander_volume_mute_changed_cb, struct bt_conn DECLARE_FAKE_VOID_FUNC(mock_cap_commander_volume_offset_changed_cb, struct bt_conn *, int); DECLARE_FAKE_VOID_FUNC(mock_cap_commander_microphone_mute_changed_cb, struct bt_conn *, int); DECLARE_FAKE_VOID_FUNC(mock_cap_commander_microphone_gain_changed_cb, struct bt_conn *, int); +DECLARE_FAKE_VOID_FUNC(mock_cap_commander_broadcast_reception_start_cb, struct bt_conn *, int); #endif /* MOCKS_CAP_COMMANDER_H_ */ diff --git a/tests/bluetooth/audio/mocks/src/cap_commander.c b/tests/bluetooth/audio/mocks/src/cap_commander.c index c652de7946cef..19e382aec2cf5 100644 --- a/tests/bluetooth/audio/mocks/src/cap_commander.c +++ b/tests/bluetooth/audio/mocks/src/cap_commander.c @@ -15,7 +15,8 @@ FAKE(mock_cap_commander_volume_mute_changed_cb) \ FAKE(mock_cap_commander_volume_offset_changed_cb) \ FAKE(mock_cap_commander_microphone_mute_changed_cb) \ - FAKE(mock_cap_commander_microphone_gain_changed_cb) + FAKE(mock_cap_commander_microphone_gain_changed_cb) \ + FAKE(mock_cap_commander_broadcast_reception_start_cb) DEFINE_FAKE_VOID_FUNC(mock_cap_commander_discovery_complete_cb, struct bt_conn *, int, const struct bt_csip_set_coordinator_set_member *, @@ -26,6 +27,7 @@ DEFINE_FAKE_VOID_FUNC(mock_cap_commander_volume_mute_changed_cb, struct bt_conn DEFINE_FAKE_VOID_FUNC(mock_cap_commander_volume_offset_changed_cb, struct bt_conn *, int); DEFINE_FAKE_VOID_FUNC(mock_cap_commander_microphone_mute_changed_cb, struct bt_conn *, int); DEFINE_FAKE_VOID_FUNC(mock_cap_commander_microphone_gain_changed_cb, struct bt_conn *, int); +DEFINE_FAKE_VOID_FUNC(mock_cap_commander_broadcast_reception_start_cb, struct bt_conn *, int); const struct bt_cap_commander_cb mock_cap_commander_cb = { .discovery_complete = mock_cap_commander_discovery_complete_cb, @@ -42,6 +44,9 @@ const struct bt_cap_commander_cb mock_cap_commander_cb = { .microphone_gain_changed = mock_cap_commander_microphone_gain_changed_cb, #endif /* CONFIG_BT_MICP_MIC_CTLR_AICS */ #endif /* CONFIG_BT_MICP_MIC_CTLR */ +#if defined(CONFIG_BT_BAP_BROADCAST_ASSISTANT) + .broadcast_reception_start = mock_cap_commander_broadcast_reception_start_cb, +#endif /* CONFIG_BT_BAP_BROADCAST_ASSISTANT */ }; void mock_cap_commander_init(void) From 0b20e2afa7600b3d2d0a514302bff720ab9865ae Mon Sep 17 00:00:00 2001 From: Marcin Szymczyk Date: Fri, 7 Jun 2024 12:04:18 +0200 Subject: [PATCH 2633/2849] arch: riscv: skip `isr.S` when SW ISR table is not generated `isr.S` depends on `CONFIG_GEN_SW_ISR_TABLE`. Do not build it if SW ISR table is not present. Signed-off-by: Marcin Szymczyk --- arch/riscv/core/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/riscv/core/CMakeLists.txt b/arch/riscv/core/CMakeLists.txt index 07eae41a6e0ce..74d520458ad20 100644 --- a/arch/riscv/core/CMakeLists.txt +++ b/arch/riscv/core/CMakeLists.txt @@ -6,7 +6,6 @@ zephyr_library_sources( cpu_idle.c fatal.c irq_manage.c - isr.S prep_c.c reboot.c reset.S @@ -21,6 +20,7 @@ endif () zephyr_library_sources_ifdef(CONFIG_FPU_SHARING fpu.c fpu.S) zephyr_library_sources_ifdef(CONFIG_DEBUG_COREDUMP coredump.c) zephyr_library_sources_ifdef(CONFIG_IRQ_OFFLOAD irq_offload.c) +zephyr_library_sources_ifdef(CONFIG_GEN_SW_ISR_TABLE isr.S) 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) From 1d9907a712aa537b1d69b729bceec1e703337d4e Mon Sep 17 00:00:00 2001 From: Marcin Szymczyk Date: Fri, 7 Jun 2024 12:08:23 +0200 Subject: [PATCH 2634/2849] soc: common: riscv-privileged: align to no SW ISR table In case of no SW ISR table, `_isr_wrapper` does not exist. Do not use it for exception handling. Future improvements might include setting it to a user-defined handler. Signed-off-by: Marcin Szymczyk --- soc/common/riscv-privileged/vector.S | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/soc/common/riscv-privileged/vector.S b/soc/common/riscv-privileged/vector.S index 5d7f84eab585a..73e41000f150b 100644 --- a/soc/common/riscv-privileged/vector.S +++ b/soc/common/riscv-privileged/vector.S @@ -12,7 +12,9 @@ GTEXT(__start) /* imports */ GTEXT(__initialize) +#if defined(CONFIG_GEN_SW_ISR_TABLE) GTEXT(_isr_wrapper) +#endif SECTION_FUNC(vectors, __start) #if defined(CONFIG_RISCV_GP) @@ -35,7 +37,11 @@ SECTION_FUNC(vectors, __start) * mtvec.base must be aligned to 64 bytes (this is done using * CONFIG_RISCV_TRAP_HANDLER_ALIGNMENT) */ +#if defined(CONFIG_GEN_SW_ISR_TABLE) la t0, _isr_wrapper +#else + add t0, zero, zero +#endif addi t0, t0, 0x03 /* Enable CLIC vectored mode by setting LSB */ csrw mtvec, t0 From 2690cacf659226ee4abf707c0d8618972306657d Mon Sep 17 00:00:00 2001 From: Emil Gydesen Date: Thu, 13 Jun 2024 20:38:55 +0200 Subject: [PATCH 2635/2849] samples: Bluetooth: CAP: Add missing argument to get_chan_allocation The sample was missing a argument to the function. Signed-off-by: Emil Gydesen --- samples/bluetooth/cap_acceptor/src/cap_acceptor_unicast.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/samples/bluetooth/cap_acceptor/src/cap_acceptor_unicast.c b/samples/bluetooth/cap_acceptor/src/cap_acceptor_unicast.c index 968e46c454fa1..9015eb409955a 100644 --- a/samples/bluetooth/cap_acceptor/src/cap_acceptor_unicast.c +++ b/samples/bluetooth/cap_acceptor/src/cap_acceptor_unicast.c @@ -79,7 +79,8 @@ static void log_codec_cfg(const struct bt_audio_codec_cfg *codec_cfg) bt_audio_codec_cfg_frame_dur_to_frame_dur_us(ret)); } - if (bt_audio_codec_cfg_get_chan_allocation(codec_cfg, &chan_allocation) == 0) { + if (bt_audio_codec_cfg_get_chan_allocation(codec_cfg, &chan_allocation, true) == + 0) { LOG_INF("\tChannel allocation: 0x%08X", chan_allocation); } From 8d2dc2f9ef300621295440d21d7b14c9caae8290 Mon Sep 17 00:00:00 2001 From: Daniel DeGrasse Date: Fri, 7 Jun 2024 14:48:50 -0500 Subject: [PATCH 2636/2849] drivers: display: ssd16xx: convert to MIPI DBI API Convert SSD16XX display driver to use MIPI DBI API. This commit also updates in tree board devicetrees to include the emulated MIPI DBI SPI driver. Signed-off-by: Daniel DeGrasse --- boards/phytec/reel_board/reel_board.dts | 88 +++++----- .../reel_board/reel_board_nrf52840_2.overlay | 162 +++++++++--------- .../waveshare_epaper_gdeh0154a07.overlay | 37 ++-- .../waveshare_epaper_gdeh0213b1.overlay | 79 +++++---- .../waveshare_epaper_gdeh0213b72.overlay | 111 ++++++------ .../waveshare_epaper_gdeh029a1.overlay | 73 ++++---- .../waveshare_epaper_gdey0213b74.overlay | 37 ++-- drivers/display/Kconfig.ssd16xx | 2 +- drivers/display/ssd16xx.c | 124 +++----------- .../display/solomon,ssd16xx-common.yaml | 20 +-- 10 files changed, 337 insertions(+), 396 deletions(-) diff --git a/boards/phytec/reel_board/reel_board.dts b/boards/phytec/reel_board/reel_board.dts index c20cf01c0ef00..59c671bc121bc 100644 --- a/boards/phytec/reel_board/reel_board.dts +++ b/boards/phytec/reel_board/reel_board.dts @@ -46,6 +46,54 @@ pwm-led3 = &back_pwm_led; watchdog0 = &wdt0; }; + + mipi_dbi { + compatible = "zephyr,mipi-dbi-spi"; + spi-dev = <&spi1>; + reset-gpios = <&gpio0 15 GPIO_ACTIVE_LOW>; + dc-gpios = <&gpio0 16 GPIO_ACTIVE_HIGH>; + #address-cells = <1>; + #size-cells = <0>; + + ssd16xx: ssd16xxfb@0 { + compatible = "gooddisplay,gdeh0213b1", "solomon,ssd1673"; + mipi-max-frequency = <4000000>; + reg = <0>; + width = <250>; + height = <122>; + busy-gpios = <&gpio0 14 GPIO_ACTIVE_HIGH>; + + full { + gdv = [10 0a]; + sdv = [19]; + vcom = <0xa8>; + border-waveform = <0x71>; + dummy-line = <0x1a>; + gate-line-width = <0x08>; + lut = [ + 22 55 AA 55 AA 55 AA 11 + 00 00 00 00 00 00 00 00 + 1E 1E 1E 1E 1E 1E 1E 1E + 01 00 00 00 00 + ]; + }; + + partial { + gdv = [10 0a]; + sdv = [19]; + vcom = <0xa8>; + border-waveform = <0x71>; + dummy-line = <0x1a>; + gate-line-width = <0x08>; + lut = [ + 18 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 + 0F 01 00 00 00 00 00 00 + 00 00 00 00 00 + ]; + }; + }; + }; }; &spi1 { @@ -56,44 +104,4 @@ pinctrl-0 = <&spi1_default>; pinctrl-1 = <&spi1_sleep>; pinctrl-names = "default", "sleep"; - ssd16xx: ssd16xxfb@0 { - compatible = "gooddisplay,gdeh0213b1", "solomon,ssd1673"; - spi-max-frequency = <4000000>; - reg = <0>; - width = <250>; - height = <122>; - reset-gpios = <&gpio0 15 GPIO_ACTIVE_LOW>; - dc-gpios = <&gpio0 16 GPIO_ACTIVE_LOW>; - busy-gpios = <&gpio0 14 GPIO_ACTIVE_HIGH>; - - full { - gdv = [10 0a]; - sdv = [19]; - vcom = <0xa8>; - border-waveform = <0x71>; - dummy-line = <0x1a>; - gate-line-width = <0x08>; - lut = [ - 22 55 AA 55 AA 55 AA 11 - 00 00 00 00 00 00 00 00 - 1E 1E 1E 1E 1E 1E 1E 1E - 01 00 00 00 00 - ]; - }; - - partial { - gdv = [10 0a]; - sdv = [19]; - vcom = <0xa8>; - border-waveform = <0x71>; - dummy-line = <0x1a>; - gate-line-width = <0x08>; - lut = [ - 18 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 - 0F 01 00 00 00 00 00 00 - 00 00 00 00 00 - ]; - }; - }; }; diff --git a/boards/phytec/reel_board/reel_board_nrf52840_2.overlay b/boards/phytec/reel_board/reel_board_nrf52840_2.overlay index b6652cbf4e8c1..1e7c0ff529dc0 100644 --- a/boards/phytec/reel_board/reel_board_nrf52840_2.overlay +++ b/boards/phytec/reel_board/reel_board_nrf52840_2.overlay @@ -27,6 +27,91 @@ aliases { watchdog0 = &wdt0; }; + + mipi_dbi { + compatible = "zephyr,mipi-dbi-spi"; + spi-dev = <&spi1>; + reset-gpios = <&gpio0 15 GPIO_ACTIVE_LOW>; + dc-gpios = <&gpio0 16 GPIO_ACTIVE_HIGH>; + #address-cells = <1>; + #size-cells = <0>; + + ssd16xx: ssd16xxfb@0 { + compatible = "gooddisplay,gdeh0213b72", "solomon,ssd1675a"; + mipi-max-frequency = <4000000>; + reg = <0>; + width = <250>; + height = <122>; + busy-gpios = <&gpio0 14 GPIO_ACTIVE_HIGH>; + + full { + gdv = [15]; + sdv = [41 a8 32]; + vcom = <0x26>; + border-waveform = <0x03>; + dummy-line = <0x30>; + gate-line-width = <0x0a>; + lut = [ + /* + * Waveform Composition + * + * There are 7 Voltage Source (VS) Level groups + * n = {0,1,2...6}, each group contains + * 4 phases x = {A,B,C,D}. + * 2 bits represent the voltage in a phase: + * 00 – VSS, 01 – VSH1, 10 – VSL, 11 - VSH2 + * + * For example 0x80 represents sequence VSL-VSS-VSS-VSS, + */ + 80 60 40 00 00 00 00 /* LUT0: BB: VS 0..6 */ + 10 60 20 00 00 00 00 /* LUT1: BW: VS 0..6 */ + 80 60 40 00 00 00 00 /* LUT2: WB: VS 0..6 */ + 10 60 20 00 00 00 00 /* LUT3: WW: VS 0..6 */ + 00 00 00 00 00 00 00 /* LUT4: VCOM: VS 0..6 */ + /* + * TPnx determines the length of each phase, + * and RPn repeat count of a sequence. + * TPnA, TPnB, TPnC, TPnD, RPn + * + * For example TP0A=3, TP0B=3, and RP0=2: + * VS sequence : VSL-VSS-VSS-VSS + * number of Gate Pulses (length) : 3 3 0 0 + * repeat count : 2 + */ + 03 03 00 00 02 /* TP0A TP0B TP0C TP0D RP0 */ + 09 09 00 00 02 /* TP1A TP1B TP1C TP1D RP1 */ + 03 03 00 00 02 /* TP2A TP2B TP2C TP2D RP2 */ + 00 00 00 00 00 /* TP3A TP3B TP3C TP3D RP3 */ + 00 00 00 00 00 /* TP4A TP4B TP4C TP4D RP4 */ + 00 00 00 00 00 /* TP5A TP5B TP5C TP5D RP5 */ + 00 00 00 00 00 /* TP6A TP6B TP6C TP6D RP6 */ + ]; + }; + + partial { + gdv = [15]; + sdv = [41 a8 32]; + vcom = <0x26>; + border-waveform = <0x01>; + dummy-line = <0x30>; + gate-line-width = <0x0a>; + lut = [ + 00 00 00 00 00 00 00 /* LUT0: BB: VS0..6 */ + 80 00 00 00 00 00 00 /* LUT1: BW: VS0..6 */ + 40 00 00 00 00 00 00 /* LUT2: WB: VS0..6 */ + 80 00 00 00 00 00 00 /* LUT3: WW: VS0..6 */ + 00 00 00 00 00 00 00 /* LUT4: VCOM: VS0..6 */ + 0A 00 00 00 04 /* TP0A TP0B TP0C TP0D RP0 */ + 00 00 00 00 00 /* TP1A TP1B TP1C TP1D RP1 */ + 00 00 00 00 00 /* TP2A TP2B TP2C TP2D RP2 */ + 00 00 00 00 00 /* TP3A TP3B TP3C TP3D RP3 */ + 00 00 00 00 00 /* TP4A TP4B TP4C TP4D RP4 */ + 00 00 00 00 00 /* TP5A TP5B TP5C TP5D RP5 */ + 00 00 00 00 00 /* TP6A TP6B TP6C TP6D RP6 */ + ]; + }; + }; + }; }; &spi1 { @@ -37,81 +122,4 @@ pinctrl-0 = <&spi1_default>; pinctrl-1 = <&spi1_sleep>; pinctrl-names = "default", "sleep"; - ssd16xx: ssd16xxfb@0 { - compatible = "gooddisplay,gdeh0213b72", "solomon,ssd1675a"; - spi-max-frequency = <4000000>; - reg = <0>; - width = <250>; - height = <122>; - reset-gpios = <&gpio0 15 GPIO_ACTIVE_LOW>; - dc-gpios = <&gpio0 16 GPIO_ACTIVE_LOW>; - busy-gpios = <&gpio0 14 GPIO_ACTIVE_HIGH>; - - full { - gdv = [15]; - sdv = [41 a8 32]; - vcom = <0x26>; - border-waveform = <0x03>; - dummy-line = <0x30>; - gate-line-width = <0x0a>; - lut = [ - /* - * Waveform Composition - * - * There are 7 Voltage Source (VS) Level groups - * n = {0,1,2...6}, each group contains - * 4 phases x = {A,B,C,D}. - * 2 bits represent the voltage in a phase: - * 00 – VSS, 01 – VSH1, 10 – VSL, 11 - VSH2 - * - * For example 0x80 represents sequence VSL-VSS-VSS-VSS, - */ - 80 60 40 00 00 00 00 /* LUT0: BB: VS 0..6 */ - 10 60 20 00 00 00 00 /* LUT1: BW: VS 0..6 */ - 80 60 40 00 00 00 00 /* LUT2: WB: VS 0..6 */ - 10 60 20 00 00 00 00 /* LUT3: WW: VS 0..6 */ - 00 00 00 00 00 00 00 /* LUT4: VCOM: VS 0..6 */ - /* - * TPnx determines the length of each phase, - * and RPn repeat count of a sequence. - * TPnA, TPnB, TPnC, TPnD, RPn - * - * For example TP0A=3, TP0B=3, and RP0=2: - * VS sequence : VSL-VSS-VSS-VSS - * number of Gate Pulses (length) : 3 3 0 0 - * repeat count : 2 - */ - 03 03 00 00 02 /* TP0A TP0B TP0C TP0D RP0 */ - 09 09 00 00 02 /* TP1A TP1B TP1C TP1D RP1 */ - 03 03 00 00 02 /* TP2A TP2B TP2C TP2D RP2 */ - 00 00 00 00 00 /* TP3A TP3B TP3C TP3D RP3 */ - 00 00 00 00 00 /* TP4A TP4B TP4C TP4D RP4 */ - 00 00 00 00 00 /* TP5A TP5B TP5C TP5D RP5 */ - 00 00 00 00 00 /* TP6A TP6B TP6C TP6D RP6 */ - ]; - }; - - partial { - gdv = [15]; - sdv = [41 a8 32]; - vcom = <0x26>; - border-waveform = <0x01>; - dummy-line = <0x30>; - gate-line-width = <0x0a>; - lut = [ - 00 00 00 00 00 00 00 /* LUT0: BB: VS0..6 */ - 80 00 00 00 00 00 00 /* LUT1: BW: VS0..6 */ - 40 00 00 00 00 00 00 /* LUT2: WB: VS0..6 */ - 80 00 00 00 00 00 00 /* LUT3: WW: VS0..6 */ - 00 00 00 00 00 00 00 /* LUT4: VCOM: VS0..6 */ - 0A 00 00 00 04 /* TP0A TP0B TP0C TP0D RP0 */ - 00 00 00 00 00 /* TP1A TP1B TP1C TP1D RP1 */ - 00 00 00 00 00 /* TP2A TP2B TP2C TP2D RP2 */ - 00 00 00 00 00 /* TP3A TP3B TP3C TP3D RP3 */ - 00 00 00 00 00 /* TP4A TP4B TP4C TP4D RP4 */ - 00 00 00 00 00 /* TP5A TP5B TP5C TP5D RP5 */ - 00 00 00 00 00 /* TP6A TP6B TP6C TP6D RP6 */ - ]; - }; - }; }; diff --git a/boards/shields/waveshare_epaper/waveshare_epaper_gdeh0154a07.overlay b/boards/shields/waveshare_epaper/waveshare_epaper_gdeh0154a07.overlay index 7a4dc21f0b70d..6a877a0b08d2c 100644 --- a/boards/shields/waveshare_epaper/waveshare_epaper_gdeh0154a07.overlay +++ b/boards/shields/waveshare_epaper/waveshare_epaper_gdeh0154a07.overlay @@ -10,27 +10,32 @@ chosen { zephyr,display = &ssd16xx_waveshare_epaper_gdeh0154a07; }; -}; -&arduino_spi { - ssd16xx_waveshare_epaper_gdeh0154a07: ssd16xxfb@0 { - compatible = "gooddisplay,gdeh0154a07", "solomon,ssd1681"; - spi-max-frequency = <4000000>; - reg = <0>; - width = <200>; - height = <200>; - dc-gpios = <&arduino_header 15 GPIO_ACTIVE_LOW>; /* D9 */ + mipi_dbi_waveshare_epaper_gdeh0154a07 { + 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 */ - busy-gpios = <&arduino_header 13 GPIO_ACTIVE_HIGH>; /* D7 */ + #address-cells = <1>; + #size-cells = <0>; - tssv = <0x80>; + ssd16xx_waveshare_epaper_gdeh0154a07: ssd16xxfb@0 { + compatible = "gooddisplay,gdeh0154a07", "solomon,ssd1681"; + mipi-max-frequency = <4000000>; + reg = <0>; + width = <200>; + height = <200>; + busy-gpios = <&arduino_header 13 GPIO_ACTIVE_HIGH>; /* D7 */ - full { - border-waveform = <0x05>; - }; + tssv = <0x80>; + + full { + border-waveform = <0x05>; + }; - partial { - border-waveform = <0x3c>; + partial { + border-waveform = <0x3c>; + }; }; }; }; diff --git a/boards/shields/waveshare_epaper/waveshare_epaper_gdeh0213b1.overlay b/boards/shields/waveshare_epaper/waveshare_epaper_gdeh0213b1.overlay index d7c873df0c3ce..1936b48d16a78 100644 --- a/boards/shields/waveshare_epaper/waveshare_epaper_gdeh0213b1.overlay +++ b/boards/shields/waveshare_epaper/waveshare_epaper_gdeh0213b1.overlay @@ -10,47 +10,52 @@ chosen { zephyr,display = &ssd16xx_waveshare_epaper_gdeh0213b1; }; -}; -&arduino_spi { - ssd16xx_waveshare_epaper_gdeh0213b1: ssd16xxfb@0 { - compatible = "gooddisplay,gdeh0213b1", "solomon,ssd1673"; - spi-max-frequency = <4000000>; - reg = <0>; - width = <250>; - height = <120>; - dc-gpios = <&arduino_header 15 GPIO_ACTIVE_LOW>; /* D9 */ + mipi_dbi_waveshare_epaper_gdeh0213b1 { + 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 */ - busy-gpios = <&arduino_header 13 GPIO_ACTIVE_HIGH>; /* D7 */ + #address-cells = <1>; + #size-cells = <0>; - full { - gdv = [10 0a]; - sdv = [19]; - vcom = <0xa8>; - border-waveform = <0x71>; - dummy-line = <0x1a>; - gate-line-width = <0x08>; - lut = [ - 22 55 AA 55 AA 55 AA 11 - 00 00 00 00 00 00 00 00 - 1E 1E 1E 1E 1E 1E 1E 1E - 01 00 00 00 00 - ]; - }; + ssd16xx_waveshare_epaper_gdeh0213b1: ssd16xxfb@0 { + compatible = "gooddisplay,gdeh0213b1", "solomon,ssd1673"; + mipi-max-frequency = <4000000>; + reg = <0>; + width = <250>; + height = <120>; + busy-gpios = <&arduino_header 13 GPIO_ACTIVE_HIGH>; /* D7 */ + + full { + gdv = [10 0a]; + sdv = [19]; + vcom = <0xa8>; + border-waveform = <0x71>; + dummy-line = <0x1a>; + gate-line-width = <0x08>; + lut = [ + 22 55 AA 55 AA 55 AA 11 + 00 00 00 00 00 00 00 00 + 1E 1E 1E 1E 1E 1E 1E 1E + 01 00 00 00 00 + ]; + }; - partial { - gdv = [10 0a]; - sdv = [19]; - vcom = <0xa8>; - border-waveform = <0x71>; - dummy-line = <0x1a>; - gate-line-width = <0x08>; - lut = [ - 18 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 - 0F 01 00 00 00 00 00 00 - 00 00 00 00 00 - ]; + partial { + gdv = [10 0a]; + sdv = [19]; + vcom = <0xa8>; + border-waveform = <0x71>; + dummy-line = <0x1a>; + gate-line-width = <0x08>; + lut = [ + 18 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 + 0F 01 00 00 00 00 00 00 + 00 00 00 00 00 + ]; + }; }; }; }; diff --git a/boards/shields/waveshare_epaper/waveshare_epaper_gdeh0213b72.overlay b/boards/shields/waveshare_epaper/waveshare_epaper_gdeh0213b72.overlay index 37954c57cf19f..362e0905079c8 100644 --- a/boards/shields/waveshare_epaper/waveshare_epaper_gdeh0213b72.overlay +++ b/boards/shields/waveshare_epaper/waveshare_epaper_gdeh0213b72.overlay @@ -10,63 +10,68 @@ chosen { zephyr,display = &ssd16xx_waveshare_epaper_gdeh0213b72; }; -}; -&arduino_spi { - ssd16xx_waveshare_epaper_gdeh0213b72: ssd16xxfb@0 { - compatible = "gooddisplay,gdeh0213b72", "solomon,ssd1675a"; - spi-max-frequency = <4000000>; - reg = <0>; - width = <250>; - height = <120>; - dc-gpios = <&arduino_header 15 GPIO_ACTIVE_LOW>; /* D9 */ + mipi_dbi_waveshare_epaper_gdeh0213b72 { + 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 */ - busy-gpios = <&arduino_header 13 GPIO_ACTIVE_HIGH>; /* D7 */ + #address-cells = <1>; + #size-cells = <0>; - full { - gdv = [15]; - sdv = [41 a8 32]; - vcom = <0x55>; - border-waveform = <0x03>; - dummy-line = <0x30>; - gate-line-width = <0x0a>; - lut = [ - 80 60 40 00 00 00 00 - 10 60 20 00 00 00 00 - 80 60 40 00 00 00 00 - 10 60 20 00 00 00 00 - 00 00 00 00 00 00 00 - 03 03 00 00 02 - 09 09 00 00 02 - 03 03 00 00 02 - 00 00 00 00 00 - 00 00 00 00 00 - 00 00 00 00 00 - 00 00 00 00 00 - ]; - }; + ssd16xx_waveshare_epaper_gdeh0213b72: ssd16xxfb@0 { + compatible = "gooddisplay,gdeh0213b72", "solomon,ssd1675a"; + mipi-max-frequency = <4000000>; + reg = <0>; + width = <250>; + height = <120>; + busy-gpios = <&arduino_header 13 GPIO_ACTIVE_HIGH>; /* D7 */ + + full { + gdv = [15]; + sdv = [41 a8 32]; + vcom = <0x55>; + border-waveform = <0x03>; + dummy-line = <0x30>; + gate-line-width = <0x0a>; + lut = [ + 80 60 40 00 00 00 00 + 10 60 20 00 00 00 00 + 80 60 40 00 00 00 00 + 10 60 20 00 00 00 00 + 00 00 00 00 00 00 00 + 03 03 00 00 02 + 09 09 00 00 02 + 03 03 00 00 02 + 00 00 00 00 00 + 00 00 00 00 00 + 00 00 00 00 00 + 00 00 00 00 00 + ]; + }; - partial { - gdv = [15]; - sdv = [41 a8 32]; - vcom = <0x26>; - border-waveform = <0x01>; - dummy-line = <0x30>; - gate-line-width = <0x0a>; - lut = [ - 00 00 00 00 00 00 00 - 80 00 00 00 00 00 00 - 40 00 00 00 00 00 00 - 80 00 00 00 00 00 00 - 00 00 00 00 00 00 00 - 0A 00 00 00 04 - 00 00 00 00 00 - 00 00 00 00 00 - 00 00 00 00 00 - 00 00 00 00 00 - 00 00 00 00 00 - 00 00 00 00 00 - ]; + partial { + gdv = [15]; + sdv = [41 a8 32]; + vcom = <0x26>; + border-waveform = <0x01>; + dummy-line = <0x30>; + gate-line-width = <0x0a>; + lut = [ + 00 00 00 00 00 00 00 + 80 00 00 00 00 00 00 + 40 00 00 00 00 00 00 + 80 00 00 00 00 00 00 + 00 00 00 00 00 00 00 + 0A 00 00 00 04 + 00 00 00 00 00 + 00 00 00 00 00 + 00 00 00 00 00 + 00 00 00 00 00 + 00 00 00 00 00 + 00 00 00 00 00 + ]; + }; }; }; }; diff --git a/boards/shields/waveshare_epaper/waveshare_epaper_gdeh029a1.overlay b/boards/shields/waveshare_epaper/waveshare_epaper_gdeh029a1.overlay index 0b1b6f4d14f42..734786fcc80be 100644 --- a/boards/shields/waveshare_epaper/waveshare_epaper_gdeh029a1.overlay +++ b/boards/shields/waveshare_epaper/waveshare_epaper_gdeh029a1.overlay @@ -10,45 +10,50 @@ chosen { zephyr,display = &ssd16xx_waveshare_epaper_gdeh029a1; }; -}; -&arduino_spi { - ssd16xx_waveshare_epaper_gdeh029a1: ssd16xxfb@0 { - compatible = "gooddisplay,gdeh029a1", "solomon,ssd1608"; - spi-max-frequency = <4000000>; - reg = <0>; - width = <296>; - height = <128>; - dc-gpios = <&arduino_header 15 GPIO_ACTIVE_LOW>; /* D9 */ + mipi_dbi_waveshare_epaper_gdeh029a1 { + 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 */ - busy-gpios = <&arduino_header 13 GPIO_ACTIVE_HIGH>; /* D7 */ + #address-cells = <1>; + #size-cells = <0>; - softstart = [d7 d6 9d]; + ssd16xx_waveshare_epaper_gdeh029a1: ssd16xxfb@0 { + compatible = "gooddisplay,gdeh029a1", "solomon,ssd1608"; + mipi-max-frequency = <4000000>; + reg = <0>; + width = <296>; + height = <128>; + busy-gpios = <&arduino_header 13 GPIO_ACTIVE_HIGH>; /* D7 */ - full { - vcom = <0x9a>; - border-waveform = <0x33>; - dummy-line = <0x1a>; - gate-line-width = <0x08>; - lut = [ - 50 AA 55 AA 11 00 00 00 - 00 00 00 00 00 00 00 00 - 00 00 00 00 FF FF 1F 00 - 00 00 00 00 00 00 - ]; - }; + softstart = [d7 d6 9d]; + + full { + vcom = <0x9a>; + border-waveform = <0x33>; + dummy-line = <0x1a>; + gate-line-width = <0x08>; + lut = [ + 50 AA 55 AA 11 00 00 00 + 00 00 00 00 00 00 00 00 + 00 00 00 00 FF FF 1F 00 + 00 00 00 00 00 00 + ]; + }; - partial { - vcom = <0xa8>; - border-waveform = <0x01>; - dummy-line = <0x1a>; - gate-line-width = <0x08>; - lut = [ - 10 18 18 08 18 18 08 00 - 00 00 00 00 00 00 00 00 - 00 00 00 00 13 14 44 12 - 00 00 00 00 00 00 - ]; + partial { + vcom = <0xa8>; + border-waveform = <0x01>; + dummy-line = <0x1a>; + gate-line-width = <0x08>; + lut = [ + 10 18 18 08 18 18 08 00 + 00 00 00 00 00 00 00 00 + 00 00 00 00 13 14 44 12 + 00 00 00 00 00 00 + ]; + }; }; }; }; diff --git a/boards/shields/waveshare_epaper/waveshare_epaper_gdey0213b74.overlay b/boards/shields/waveshare_epaper/waveshare_epaper_gdey0213b74.overlay index bd77a1ede516a..8299b7242745d 100644 --- a/boards/shields/waveshare_epaper/waveshare_epaper_gdey0213b74.overlay +++ b/boards/shields/waveshare_epaper/waveshare_epaper_gdey0213b74.overlay @@ -10,27 +10,32 @@ chosen { zephyr,display = &ssd16xx_waveshare_epaper_gdey0213b74; }; -}; -&arduino_spi { - ssd16xx_waveshare_epaper_gdey0213b74: ssd16xxfb@0 { - compatible = "gooddisplay,gdey0213b74", "solomon,ssd1680"; - spi-max-frequency = <4000000>; - reg = <0>; - width = <250>; - height = <122>; - dc-gpios = <&arduino_header 15 GPIO_ACTIVE_LOW>; /* D9 */ + mipi_dbi_waveshare_epaper_gdey0213b74 { + 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 */ - busy-gpios = <&arduino_header 13 GPIO_ACTIVE_HIGH>; /* D7 */ + #address-cells = <1>; + #size-cells = <0>; - tssv = <0x80>; + ssd16xx_waveshare_epaper_gdey0213b74: ssd16xxfb@0 { + compatible = "gooddisplay,gdey0213b74", "solomon,ssd1680"; + mipi-max-frequency = <4000000>; + reg = <0>; + width = <250>; + height = <122>; + busy-gpios = <&arduino_header 13 GPIO_ACTIVE_HIGH>; /* D7 */ - full { - border-waveform = <0x05>; - }; + tssv = <0x80>; + + full { + border-waveform = <0x05>; + }; - partial { - border-waveform = <0x3c>; + partial { + border-waveform = <0x3c>; + }; }; }; }; diff --git a/drivers/display/Kconfig.ssd16xx b/drivers/display/Kconfig.ssd16xx index 1149ff03692e1..097351fec5ea1 100644 --- a/drivers/display/Kconfig.ssd16xx +++ b/drivers/display/Kconfig.ssd16xx @@ -12,6 +12,6 @@ config SSD16XX DT_HAS_SOLOMON_SSD1675A_ENABLED || \ DT_HAS_SOLOMON_SSD1680_ENABLED || \ DT_HAS_SOLOMON_SSD1681_ENABLED - select SPI + select MIPI_DBI help Enable driver for SSD16XX compatible controller. diff --git a/drivers/display/ssd16xx.c b/drivers/display/ssd16xx.c index 16ab70237338c..7dfaa1211771b 100644 --- a/drivers/display/ssd16xx.c +++ b/drivers/display/ssd16xx.c @@ -1,6 +1,7 @@ /* * Copyright (c) 2022 Andreas Sandberg * Copyright (c) 2018-2020 PHYTEC Messtechnik GmbH + * Copyright 2024 NXP * * SPDX-License-Identifier: Apache-2.0 */ @@ -14,7 +15,7 @@ LOG_MODULE_REGISTER(ssd16xx); #include #include #include -#include +#include #include #include @@ -90,10 +91,9 @@ struct ssd16xx_profile { }; struct ssd16xx_config { - struct spi_dt_spec bus; - struct gpio_dt_spec dc_gpio; + const struct device *mipi_dev; + const struct mipi_dbi_config dbi_config; struct gpio_dt_spec busy_gpio; - struct gpio_dt_spec reset_gpio; const struct ssd16xx_quirks *quirks; @@ -126,39 +126,13 @@ static inline int ssd16xx_write_cmd(const struct device *dev, uint8_t cmd, const uint8_t *data, size_t len) { const struct ssd16xx_config *config = dev->config; - struct spi_buf buf = {.buf = &cmd, .len = sizeof(cmd)}; - struct spi_buf_set buf_set = {.buffers = &buf, .count = 1}; - int err = 0; + int err; ssd16xx_busy_wait(dev); - err = gpio_pin_set_dt(&config->dc_gpio, 1); - if (err < 0) { - return err; - } - - err = spi_write_dt(&config->bus, &buf_set); - if (err < 0) { - goto spi_out; - } - - if (data != NULL) { - buf.buf = (void *)data; - buf.len = len; - - err = gpio_pin_set_dt(&config->dc_gpio, 0); - if (err < 0) { - goto spi_out; - } - - err = spi_write_dt(&config->bus, &buf_set); - if (err < 0) { - goto spi_out; - } - } - -spi_out: - spi_release_dt(&config->bus); + err = mipi_dbi_command_write(config->mipi_dev, &config->dbi_config, + cmd, data, len); + mipi_dbi_release(config->mipi_dev, &config->dbi_config); return err; } @@ -173,9 +147,6 @@ static inline int ssd16xx_read_cmd(const struct device *dev, uint8_t cmd, { const struct ssd16xx_config *config = dev->config; const struct ssd16xx_data *dev_data = dev->data; - struct spi_buf buf = {.buf = &cmd, .len = sizeof(cmd)}; - struct spi_buf_set buf_set = {.buffers = &buf, .count = 1}; - int err = 0; if (!dev_data->read_supported) { return -ENOTSUP; @@ -183,34 +154,8 @@ static inline int ssd16xx_read_cmd(const struct device *dev, uint8_t cmd, ssd16xx_busy_wait(dev); - err = gpio_pin_set_dt(&config->dc_gpio, 1); - if (err < 0) { - return err; - } - - err = spi_write_dt(&config->bus, &buf_set); - if (err < 0) { - goto spi_out; - } - - if (data != NULL) { - buf.buf = data; - buf.len = len; - - err = gpio_pin_set_dt(&config->dc_gpio, 0); - if (err < 0) { - goto spi_out; - } - - err = spi_read_dt(&config->bus, &buf_set); - if (err < 0) { - goto spi_out; - } - } - -spi_out: - spi_release_dt(&config->bus); - return err; + return mipi_dbi_command_read(config->mipi_dev, &config->dbi_config, + &cmd, 1, data, len); } static inline size_t push_x_param(const struct device *dev, @@ -911,13 +856,7 @@ static int ssd16xx_controller_init(const struct device *dev) data->blanking_on = false; data->profile = SSD16XX_PROFILE_INVALID; - err = gpio_pin_set_dt(&config->reset_gpio, 1); - if (err < 0) { - return err; - } - - k_msleep(SSD16XX_RESET_DELAY); - err = gpio_pin_set_dt(&config->reset_gpio, 0); + err = mipi_dbi_reset(config->mipi_dev, SSD16XX_RESET_DELAY); if (err < 0) { return err; } @@ -970,35 +909,13 @@ static int ssd16xx_init(const struct device *dev) LOG_DBG(""); - if (!spi_is_ready_dt(&config->bus)) { - LOG_ERR("SPI bus %s not ready", config->bus.bus->name); + if (!device_is_ready(config->mipi_dev)) { + LOG_ERR("MIPI Device not ready"); return -ENODEV; } data->read_supported = - (config->bus.config.operation & SPI_HALF_DUPLEX) != 0; - - if (!gpio_is_ready_dt(&config->reset_gpio)) { - LOG_ERR("Reset GPIO device not ready"); - return -ENODEV; - } - - err = gpio_pin_configure_dt(&config->reset_gpio, GPIO_OUTPUT_INACTIVE); - if (err < 0) { - LOG_ERR("Failed to configure reset GPIO"); - return err; - } - - if (!gpio_is_ready_dt(&config->dc_gpio)) { - LOG_ERR("DC GPIO device not ready"); - return -ENODEV; - } - - err = gpio_pin_configure_dt(&config->dc_gpio, GPIO_OUTPUT_INACTIVE); - if (err < 0) { - LOG_ERR("Failed to configure DC GPIO"); - return err; - } + (config->dbi_config.config.operation & SPI_HALF_DUPLEX) != 0; if (!gpio_is_ready_dt(&config->busy_gpio)) { LOG_ERR("Busy GPIO device not ready"); @@ -1134,12 +1051,13 @@ static struct ssd16xx_quirks quirks_solomon_ssd1681 = { DT_FOREACH_CHILD(n, SSD16XX_PROFILE); \ \ static const struct ssd16xx_config ssd16xx_cfg_ ## n = { \ - .bus = SPI_DT_SPEC_GET(n, \ - SPI_OP_MODE_MASTER | SPI_WORD_SET(8) | \ - SPI_HOLD_ON_CS | SPI_LOCK_ON, \ - 0), \ - .reset_gpio = GPIO_DT_SPEC_GET(n, reset_gpios), \ - .dc_gpio = GPIO_DT_SPEC_GET(n, dc_gpios), \ + .mipi_dev = DEVICE_DT_GET(DT_PARENT(n)), \ + .dbi_config = { \ + .mode = MIPI_DBI_MODE_SPI_4WIRE, \ + .config = MIPI_DBI_SPI_CONFIG_DT(n, \ + SPI_OP_MODE_MASTER | SPI_WORD_SET(8) | \ + SPI_HOLD_ON_CS | SPI_LOCK_ON, 0), \ + }, \ .busy_gpio = GPIO_DT_SPEC_GET(n, busy_gpios), \ .quirks = quirks_ptr, \ .height = DT_PROP(n, height), \ diff --git a/dts/bindings/display/solomon,ssd16xx-common.yaml b/dts/bindings/display/solomon,ssd16xx-common.yaml index 34911dbc18b57..343f9a9c69b48 100644 --- a/dts/bindings/display/solomon,ssd16xx-common.yaml +++ b/dts/bindings/display/solomon,ssd16xx-common.yaml @@ -3,31 +3,13 @@ description: SSD16XX EPD display controller -include: [spi-device.yaml, display-controller.yaml] +include: [mipi-dbi-spi-device.yaml, display-controller.yaml] properties: softstart: type: uint8-array description: Booster soft start values - reset-gpios: - type: phandle-array - required: true - description: RESET pin. - - The RESET pin of SSD16XX is active low. - If connected directly the MCU pin should be configured - as active low. - - dc-gpios: - type: phandle-array - required: true - description: DC pin. - - The DC pin of SSD16XX is active low (transmission command byte). - If connected directly the MCU pin should be configured - as active low. - busy-gpios: type: phandle-array required: true From 323adb9f08c4a2eca8da77c3a94948abb2a5865c Mon Sep 17 00:00:00 2001 From: Daniel DeGrasse Date: Fri, 7 Jun 2024 14:53:43 -0500 Subject: [PATCH 2637/2849] tests: drivers: display: build_all: add ssd16xx Add ssd16xx to display build test Signed-off-by: Daniel DeGrasse --- tests/drivers/build_all/display/app.overlay | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/tests/drivers/build_all/display/app.overlay b/tests/drivers/build_all/display/app.overlay index 67d5bb45a5fbd..0ba2cb33f2c01 100644 --- a/tests/drivers/build_all/display/app.overlay +++ b/tests/drivers/build_all/display/app.overlay @@ -98,6 +98,15 @@ rgb-param = [40 02 14]; mipi-mode = ; }; + + test_mipi_dbi_ssd1680: ssd1680@4 { + compatible = "gooddisplay,gdey0213b74", "solomon,ssd1680"; + mipi-max-frequency = <4000000>; + reg = <4>; + width = <250>; + height = <122>; + busy-gpios = <&test_gpio 0 0>; + }; }; @@ -111,7 +120,7 @@ /* one entry for every devices at spi.dtsi */ cs-gpios = <&test_gpio 0 0 &test_gpio 0 1 &test_gpio 0 2 - &test_gpio 0 3>; + &test_gpio 0 3 &test_gpio 0 4>; test_spi_gc9x01x: gc9x01x@1 { compatible = "galaxycore,gc9x01x"; From 65d2ae6939e890649b661811b49c8294d42ec1e5 Mon Sep 17 00:00:00 2001 From: Daniel DeGrasse Date: Fri, 7 Jun 2024 14:59:44 -0500 Subject: [PATCH 2638/2849] doc: releases: migration-guide-3.7: add note for SSD16XXX displays Add note for SSD16XXX displays, which have been migrated to the MIPI DBI API. This note describes how to define the MIPI DBI wrapper device needed for the SSD16XXX display Signed-off-by: Daniel DeGrasse --- doc/releases/migration-guide-3.7.rst | 45 ++++++++++++++++++++++++++-- 1 file changed, 43 insertions(+), 2 deletions(-) diff --git a/doc/releases/migration-guide-3.7.rst b/doc/releases/migration-guide-3.7.rst index b1f0b50443c28..e6d6fdc114b84 100644 --- a/doc/releases/migration-guide-3.7.rst +++ b/doc/releases/migration-guide-3.7.rst @@ -355,8 +355,8 @@ Display * ST7789V 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. (:github:`73750`) 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: + ``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 @@ -395,6 +395,47 @@ Display }; }; +* SSD16XX based displays now use the MIPI DBI driver class (:github:`73946`). + These displays must now be declared within a MIPI DBI driver wrapper device, + which will manage interfacing with the display. Note that the ``dc-gpios`` + pin has changed polarity with this update. For an example, see below: + + .. code-block:: devicetree + + /* Legacy SSD16XX display definition */ + &spi0 { + ssd1680: ssd1680@0 { + compatible = "solomon,ssd1680"; + reg = <0>; + spi-max-frequency = <4000000>; + reset-gpios = <&gpio0 6 GPIO_ACTIVE_LOW>; + dc-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>; + + ssd1680: ssd1680@0 { + compatible = "solomon,ssd1680"; + reg = <0>; + mipi-max-frequency = <4000000>; + ... + }; + }; + Enhanced Serial Peripheral Interface (eSPI) =========================================== From baa70d8d361c1ee4cda4ee24ea5d5aa2c32f53bf Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Thu, 13 Jun 2024 16:05:03 -0400 Subject: [PATCH 2639/2849] arch/arm64/mmu: fix page table reference counting part 2 Commit f7e11649fdf5 ("arch/arm64/mmu: fix page table reference counting") missed a case where the freeing of a table wasn't propagated properly to all domains. To fix this, the page freeing logic was removed from set_mapping() and a del_mapping() was created instead, to be usedby both by remove_map() and globalize_table(). A test covering this case should definitely be created but that'll come later. Proper operation was verified through manual debug log inspection for now. Signed-off-by: Nicolas Pitre --- arch/arm64/core/mmu.c | 108 ++++++++++++++++++++++++++---------------- 1 file changed, 68 insertions(+), 40 deletions(-) diff --git a/arch/arm64/core/mmu.c b/arch/arm64/core/mmu.c index 946d95a56a4eb..5527fa347ad5d 100644 --- a/arch/arm64/core/mmu.c +++ b/arch/arm64/core/mmu.c @@ -276,15 +276,13 @@ static uint64_t *expand_to_table(uint64_t *pte, unsigned int level) return table; } -static int set_mapping(struct arm_mmu_ptables *ptables, - uintptr_t virt, size_t size, +static int set_mapping(uint64_t *top_table, uintptr_t virt, size_t size, uint64_t desc, bool may_overwrite) { - uint64_t *pte, *ptes[XLAT_LAST_LEVEL + 1]; + uint64_t *table = top_table; + uint64_t *pte; uint64_t level_size; - uint64_t *table = ptables->base_xlat_table; unsigned int level = BASE_XLAT_LEVEL; - int ret = 0; while (size) { __ASSERT(level <= XLAT_LAST_LEVEL, @@ -292,7 +290,6 @@ static int set_mapping(struct arm_mmu_ptables *ptables, /* Locate PTE for given virtual address and page table level */ pte = &table[XLAT_TABLE_VA_IDX(virt, level)]; - ptes[level] = pte; if (is_table_desc(*pte, level)) { /* Move to the next translation table level */ @@ -306,8 +303,7 @@ static int set_mapping(struct arm_mmu_ptables *ptables, LOG_ERR("entry already in use: " "level %d pte %p *pte 0x%016llx", level, pte, *pte); - ret = -EBUSY; - break; + return -EBUSY; } level_size = 1ULL << LEVEL_TO_VA_SIZE_SHIFT(level); @@ -326,8 +322,7 @@ static int set_mapping(struct arm_mmu_ptables *ptables, /* Range doesn't fit, create subtable */ table = expand_to_table(pte, level); if (!table) { - ret = -ENOMEM; - break; + return -ENOMEM; } level++; continue; @@ -337,32 +332,58 @@ static int set_mapping(struct arm_mmu_ptables *ptables, if (is_free_desc(*pte)) { table_usage(pte, 1); } - if (!desc) { - table_usage(pte, -1); - } - /* Create (or erase) block/page descriptor */ + /* Create block/page descriptor */ set_pte_block_desc(pte, desc, level); - /* recursively free unused tables if any */ - while (level != BASE_XLAT_LEVEL && - is_table_unused(pte)) { - dec_table_ref(pte); - pte = ptes[--level]; - set_pte_block_desc(pte, 0, level); - table_usage(pte, -1); - } - move_on: virt += level_size; - desc += desc ? level_size : 0; + desc += level_size; size -= level_size; /* Range is mapped, start again for next range */ - table = ptables->base_xlat_table; + table = top_table; level = BASE_XLAT_LEVEL; } - return ret; + return 0; +} + +static void del_mapping(uint64_t *table, uintptr_t virt, size_t size, + unsigned int level) +{ + size_t step, level_size = 1ULL << LEVEL_TO_VA_SIZE_SHIFT(level); + uint64_t *pte, *subtable; + + for ( ; size; virt += step, size -= step) { + step = level_size - (virt & (level_size - 1)); + if (step > size) { + step = size; + } + pte = &table[XLAT_TABLE_VA_IDX(virt, level)]; + + if (is_free_desc(*pte)) { + continue; + } + + if (is_table_desc(*pte, level)) { + subtable = pte_desc_table(*pte); + del_mapping(subtable, virt, step, level + 1); + if (!is_table_unused(subtable)) { + continue; + } + dec_table_ref(subtable); + } else { + /* + * We assume that block mappings will be unmapped + * as a whole and not partially. + */ + __ASSERT(step == level_size, ""); + } + + /* free this entry */ + *pte = 0; + table_usage(pte, -1); + } } #ifdef CONFIG_USERSPACE @@ -510,6 +531,20 @@ static int globalize_table(uint64_t *dst_table, uint64_t *src_table, continue; } + if (is_free_desc(src_table[i]) && + is_table_desc(dst_table[i], level)) { + uint64_t *subtable = pte_desc_table(dst_table[i]); + + del_mapping(subtable, virt, step, level + 1); + if (is_table_unused(subtable)) { + /* unreference the empty table */ + dst_table[i] = 0; + table_usage(dst_table, -1); + dec_table_ref(subtable); + } + continue; + } + if (step != level_size) { /* boundary falls in the middle of this pte */ __ASSERT(is_table_desc(src_table[i], level), @@ -669,7 +704,7 @@ static int __add_map(struct arm_mmu_ptables *ptables, const char *name, __ASSERT(((virt | phys | size) & (CONFIG_MMU_PAGE_SIZE - 1)) == 0, "address/size are not page aligned\n"); desc |= phys; - return set_mapping(ptables, virt, size, desc, may_overwrite); + return set_mapping(ptables->base_xlat_table, virt, size, desc, may_overwrite); } static int add_map(struct arm_mmu_ptables *ptables, const char *name, @@ -684,20 +719,18 @@ static int add_map(struct arm_mmu_ptables *ptables, const char *name, return ret; } -static int remove_map(struct arm_mmu_ptables *ptables, const char *name, - uintptr_t virt, size_t size) +static void remove_map(struct arm_mmu_ptables *ptables, const char *name, + uintptr_t virt, size_t size) { k_spinlock_key_t key; - int ret; MMU_DEBUG("unmmap [%s]: virt %lx size %lx\n", name, virt, size); __ASSERT(((virt | size) & (CONFIG_MMU_PAGE_SIZE - 1)) == 0, "address/size are not page aligned\n"); key = k_spin_lock(&xlat_lock); - ret = set_mapping(ptables, virt, size, 0, true); + del_mapping(ptables->base_xlat_table, virt, size, BASE_XLAT_LEVEL); k_spin_unlock(&xlat_lock, key); - return ret; } static void invalidate_tlb_all(void) @@ -1049,14 +1082,9 @@ void arch_mem_map(void *virt, uintptr_t phys, size_t size, uint32_t flags) void arch_mem_unmap(void *addr, size_t size) { - int ret = remove_map(&kernel_ptables, "generic", (uintptr_t)addr, size); - - if (ret) { - LOG_ERR("remove_map() returned %d", ret); - } else { - sync_domains((uintptr_t)addr, size); - invalidate_tlb_all(); - } + remove_map(&kernel_ptables, "generic", (uintptr_t)addr, size); + sync_domains((uintptr_t)addr, size); + invalidate_tlb_all(); } int arch_page_phys_get(void *virt, uintptr_t *phys) From 13660dd7b9a18106a91c062166a26f9229e88cdf Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Tue, 28 May 2024 22:23:49 -0400 Subject: [PATCH 2640/2849] demand_paging/backing_store/ram.c: misc fixups First, do align the buffer. The slab code puts pointers in there and it does not like it if those are not properly aligned. And return the actual error code from k_mem_slab_alloc() even if errors shouldn't happen (it did happen to me because of the above ... with assertions disabled). Signed-off-by: Nicolas Pitre --- subsys/demand_paging/backing_store/ram.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/subsys/demand_paging/backing_store/ram.c b/subsys/demand_paging/backing_store/ram.c index 508780f1507db..c6fafc76029b7 100644 --- a/subsys/demand_paging/backing_store/ram.c +++ b/subsys/demand_paging/backing_store/ram.c @@ -51,8 +51,8 @@ * starts getting set for certain page frames after a page-in (and possibly * cleared at a later time). */ -static char backing_store[CONFIG_MMU_PAGE_SIZE * - CONFIG_BACKING_STORE_RAM_PAGES]; +#define BACKING_STORE_SIZE (CONFIG_BACKING_STORE_RAM_PAGES * CONFIG_MMU_PAGE_SIZE) +static char backing_store[BACKING_STORE_SIZE] __aligned(sizeof(void *)); static struct k_mem_slab backing_slabs; static unsigned int free_slabs; @@ -95,7 +95,9 @@ int k_mem_paging_backing_store_location_get(struct k_mem_page_frame *pf, ret = k_mem_slab_alloc(&backing_slabs, &slab, K_NO_WAIT); __ASSERT(ret == 0, "slab count mismatch"); - (void)ret; + if (ret != 0) { + return ret; + } *location = slab_to_location(slab); free_slabs--; From c5642a7b4ded087f739519cf9567a88e00f424e4 Mon Sep 17 00:00:00 2001 From: Grant Ramsay Date: Tue, 11 Jun 2024 15:21:33 +1200 Subject: [PATCH 2641/2849] arch: kconfig: Set flash size/address to 0 by default when !XIP Many boards/SoCs in-tree do this: if !XIP config FLASH_SIZE default 0 config FLASH_BASE_ADDRESS default 0 endif And many other boards are missing this configuration (e.g. stm32 series). Making this the default helps get non-XIP just working Signed-off-by: Grant Ramsay --- arch/Kconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/Kconfig b/arch/Kconfig index b597236699066..2d9b59292cca8 100644 --- a/arch/Kconfig +++ b/arch/Kconfig @@ -226,6 +226,7 @@ DT_CHOSEN_Z_FLASH := zephyr,flash config FLASH_SIZE int "Flash Size in kB" default $(dt_chosen_reg_size_int,$(DT_CHOSEN_Z_FLASH),0,K) if (XIP && (ARM ||ARM64)) || !ARM + default 0 if !XIP help This option specifies the size of the flash in kB. It is normally set by the board's defconfig file and the user should generally avoid modifying @@ -234,6 +235,7 @@ config FLASH_SIZE config FLASH_BASE_ADDRESS hex "Flash Base Address" default $(dt_chosen_reg_addr_hex,$(DT_CHOSEN_Z_FLASH)) if (XIP && (ARM || ARM64)) || !ARM + default 0 if !XIP help This option specifies the base address of the flash on the board. It is normally set by the board's defconfig file and the user should generally From 5914c869311ab51e7c746025d360b76bedd16a7f Mon Sep 17 00:00:00 2001 From: Grant Ramsay Date: Tue, 11 Jun 2024 20:19:08 +1200 Subject: [PATCH 2642/2849] arch: treewide: Remove unnessecary flash size/address defconfig when !XIP FLASH_SIZE=0 and FLASH_BASE_ADDRESS=0 are now the default values when XIP=n Signed-off-by: Grant Ramsay --- boards/96boards/meerkat96/Kconfig.defconfig | 15 --------------- boards/element14/warp7/Kconfig.defconfig | 7 ------- boards/nxp/imx8mm_evk/Kconfig.defconfig | 15 --------------- boards/nxp/imx8mp_evk/Kconfig.defconfig | 15 --------------- boards/nxp/imx8mq_evk/Kconfig.defconfig | 16 ---------------- .../mimx8mm_phyboard_polis/Kconfig.defconfig | 15 --------------- .../mimx8mp_phyboard_pollux/Kconfig.defconfig | 15 --------------- boards/technexion/pico_pi/Kconfig.defconfig | 15 --------------- boards/toradex/colibri_imx7d/Kconfig.defconfig | 16 ---------------- boards/toradex/verdin_imx8mp/Kconfig.defconfig | 15 --------------- soc/nxp/s32/s32k1/Kconfig.defconfig | 7 ------- soc/nxp/s32/s32k3/Kconfig.defconfig | 7 ------- soc/nxp/s32/s32ze/Kconfig.defconfig | 8 -------- .../simplelink/cc32xx/Kconfig.defconfig.cc3220sf | 9 --------- .../simplelink/cc32xx/Kconfig.defconfig.cc3235sf | 9 --------- 15 files changed, 184 deletions(-) delete mode 100644 boards/96boards/meerkat96/Kconfig.defconfig delete mode 100644 boards/nxp/imx8mm_evk/Kconfig.defconfig delete mode 100644 boards/nxp/imx8mp_evk/Kconfig.defconfig delete mode 100644 boards/nxp/imx8mq_evk/Kconfig.defconfig delete mode 100644 boards/phytec/mimx8mm_phyboard_polis/Kconfig.defconfig delete mode 100644 boards/phytec/mimx8mp_phyboard_pollux/Kconfig.defconfig delete mode 100644 boards/technexion/pico_pi/Kconfig.defconfig delete mode 100644 boards/toradex/colibri_imx7d/Kconfig.defconfig delete mode 100644 boards/toradex/verdin_imx8mp/Kconfig.defconfig diff --git a/boards/96boards/meerkat96/Kconfig.defconfig b/boards/96boards/meerkat96/Kconfig.defconfig deleted file mode 100644 index a401b7ecb89bc..0000000000000 --- a/boards/96boards/meerkat96/Kconfig.defconfig +++ /dev/null @@ -1,15 +0,0 @@ -# 96Boards Meerkat96 board - -# Copyright (c) 2019, Linaro Ltd. -# SPDX-License-Identifier: Apache-2.0 - -if BOARD_96B_MEERKAT96 - -if !XIP -config FLASH_SIZE - default 0 -config FLASH_BASE_ADDRESS - default 0 -endif - -endif # BOARD_96B_MEERKAT96 diff --git a/boards/element14/warp7/Kconfig.defconfig b/boards/element14/warp7/Kconfig.defconfig index b73424093e074..fcb09419c3524 100644 --- a/boards/element14/warp7/Kconfig.defconfig +++ b/boards/element14/warp7/Kconfig.defconfig @@ -13,11 +13,4 @@ config FXAS21002_DRDY_INT1 default y depends on FXAS21002_TRIGGER -if !XIP -config FLASH_SIZE - default 0 -config FLASH_BASE_ADDRESS - default 0 -endif - endif # BOARD_WARP7 diff --git a/boards/nxp/imx8mm_evk/Kconfig.defconfig b/boards/nxp/imx8mm_evk/Kconfig.defconfig deleted file mode 100644 index 5cc30c81ed197..0000000000000 --- a/boards/nxp/imx8mm_evk/Kconfig.defconfig +++ /dev/null @@ -1,15 +0,0 @@ -# MIMX8MM EVK board defconfig - -# Copyright (c) 2020, Manivannan Sadhasivam -# SPDX-License-Identifier: Apache-2.0 - -if BOARD_IMX8MM_EVK_MIMX8MM6_M4 - -if !XIP -config FLASH_SIZE - default 0 -config FLASH_BASE_ADDRESS - default 0 -endif - -endif # BOARD_IMX8MM_EVK_MIMX8MM6_M4 diff --git a/boards/nxp/imx8mp_evk/Kconfig.defconfig b/boards/nxp/imx8mp_evk/Kconfig.defconfig deleted file mode 100644 index 3fdc7b3cd9c18..0000000000000 --- a/boards/nxp/imx8mp_evk/Kconfig.defconfig +++ /dev/null @@ -1,15 +0,0 @@ -# MIMX8MP EVK board defconfig - -# Copyright (c) 2021, Laird Connectivity -# SPDX-License-Identifier: Apache-2.0 - -if BOARD_IMX8MP_EVK_MIMX8ML8_M7 || BOARD_IMX8MP_EVK_MIMX8ML8_M7_DDR - -if !XIP -config FLASH_SIZE - default 0 -config FLASH_BASE_ADDRESS - default 0 -endif - -endif # BOARD_IMX8MP_EVK_MIMX8ML8_M7 || BOARD_IMX8MP_EVK_MIMX8ML8_M7_DDR diff --git a/boards/nxp/imx8mq_evk/Kconfig.defconfig b/boards/nxp/imx8mq_evk/Kconfig.defconfig deleted file mode 100644 index 054cfde7fb7fb..0000000000000 --- a/boards/nxp/imx8mq_evk/Kconfig.defconfig +++ /dev/null @@ -1,16 +0,0 @@ -# MIMX8MQ EVK board defconfig - -# Copyright (c) 2021, Kwon Tae-young -# Copyright 2024 NXP -# SPDX-License-Identifier: Apache-2.0 - -if BOARD_IMX8MQ_EVK - -if !XIP -config FLASH_SIZE - default 0 -config FLASH_BASE_ADDRESS - default 0 -endif - -endif # BOARD_IMX8MQ_EVK diff --git a/boards/phytec/mimx8mm_phyboard_polis/Kconfig.defconfig b/boards/phytec/mimx8mm_phyboard_polis/Kconfig.defconfig deleted file mode 100644 index ec8c8486351c7..0000000000000 --- a/boards/phytec/mimx8mm_phyboard_polis/Kconfig.defconfig +++ /dev/null @@ -1,15 +0,0 @@ -# MIMX8MM_PHYBOARD_POLIS board defconfig -# -# Copyright (c) 2022 PHYTEC Messtechnik GmbH -# SPDX-License-Identifier: Apache-2.0 - -if BOARD_MIMX8MM_PHYBOARD_POLIS - -if !XIP -config FLASH_SIZE - default 0 -config FLASH_BASE_ADDRESS - default 0 -endif - -endif # BOARD_MIMX8MM_PHYBOARD_POLIS diff --git a/boards/phytec/mimx8mp_phyboard_pollux/Kconfig.defconfig b/boards/phytec/mimx8mp_phyboard_pollux/Kconfig.defconfig deleted file mode 100644 index e860faf97cfb0..0000000000000 --- a/boards/phytec/mimx8mp_phyboard_pollux/Kconfig.defconfig +++ /dev/null @@ -1,15 +0,0 @@ -# PhyBOARD Pollux (i.MX8MP) defconfig - -# Copyright (c) 2022 PHYTEC Messtechnik GmbH -# SPDX-License-Identifier: Apache-2.0 - -if BOARD_MIMX8MP_PHYBOARD_POLLUX - -if !XIP -config FLASH_SIZE - default 0 -config FLASH_BASE_ADDRESS - default 0 -endif - -endif # BOARD_MIMX8MP_PHYBOARD_POLLUX diff --git a/boards/technexion/pico_pi/Kconfig.defconfig b/boards/technexion/pico_pi/Kconfig.defconfig deleted file mode 100644 index aebd510fe618d..0000000000000 --- a/boards/technexion/pico_pi/Kconfig.defconfig +++ /dev/null @@ -1,15 +0,0 @@ -# Pico-Pi iMX7D M4 board - -# Copyright (c) 2019, Joris Offouga -# SPDX-License-Identifier: Apache-2.0 - -if BOARD_PICO_PI - -if !XIP -config FLASH_SIZE - default 0 -config FLASH_BASE_ADDRESS - default 0 -endif - -endif # BOARD_PICO_PI diff --git a/boards/toradex/colibri_imx7d/Kconfig.defconfig b/boards/toradex/colibri_imx7d/Kconfig.defconfig deleted file mode 100644 index 4f108737fd2aa..0000000000000 --- a/boards/toradex/colibri_imx7d/Kconfig.defconfig +++ /dev/null @@ -1,16 +0,0 @@ -# Colibri iMX7D M4 board - -# Copyright 2017,2024 NXP -# SPDX-License-Identifier: Apache-2.0 - -if BOARD_COLIBRI_IMX7D_MCIMX7D_M4 - -if !XIP -config FLASH_SIZE - default 0 -config FLASH_BASE_ADDRESS - default 0 -endif - - -endif # BOARD_COLIBRI_IMX7D_MCIMX7D_M4 diff --git a/boards/toradex/verdin_imx8mp/Kconfig.defconfig b/boards/toradex/verdin_imx8mp/Kconfig.defconfig deleted file mode 100644 index 76903f1d2e1cc..0000000000000 --- a/boards/toradex/verdin_imx8mp/Kconfig.defconfig +++ /dev/null @@ -1,15 +0,0 @@ -# VERDIN_IMX8MP board defconfig - -# Copyright (c) 2023 Toradex -# SPDX-License-Identifier: Apache-2.0 - -if BOARD_VERDIN_IMX8MP - -if !XIP -config FLASH_SIZE - default 0 -config FLASH_BASE_ADDRESS - default 0 -endif - -endif # BOARD_VERDIN_IMX8MP diff --git a/soc/nxp/s32/s32k1/Kconfig.defconfig b/soc/nxp/s32/s32k1/Kconfig.defconfig index 582ebf0e3269d..c8a43cf554574 100644 --- a/soc/nxp/s32/s32k1/Kconfig.defconfig +++ b/soc/nxp/s32/s32k1/Kconfig.defconfig @@ -15,13 +15,6 @@ config NUM_IRQS config FPU default y if CPU_HAS_FPU -if !XIP -config FLASH_SIZE - default 0 -config FLASH_BASE_ADDRESS - default 0 -endif - # The S32K1xx have 8 MPU regions, which is not enough for both HW stack protection # and userspace. Only enable HW stack protection if userspace is not enabled. config HW_STACK_PROTECTION diff --git a/soc/nxp/s32/s32k3/Kconfig.defconfig b/soc/nxp/s32/s32k3/Kconfig.defconfig index 6c58f348ea64b..2e3609c5377c8 100644 --- a/soc/nxp/s32/s32k3/Kconfig.defconfig +++ b/soc/nxp/s32/s32k3/Kconfig.defconfig @@ -15,13 +15,6 @@ config NUM_IRQS config FPU default y -if !XIP -config FLASH_SIZE - default 0 -config FLASH_BASE_ADDRESS - default 0 -endif - if NET_L2_ETHERNET config NET_TCP_CHECKSUM diff --git a/soc/nxp/s32/s32ze/Kconfig.defconfig b/soc/nxp/s32/s32ze/Kconfig.defconfig index 7deb599e3a24e..5373018fb27c9 100644 --- a/soc/nxp/s32/s32ze/Kconfig.defconfig +++ b/soc/nxp/s32/s32ze/Kconfig.defconfig @@ -18,14 +18,6 @@ config SYS_CLOCK_HW_CYCLES_PER_SEC config MAIN_STACK_SIZE default 1024 -if !XIP -config FLASH_SIZE - default 0 - -config FLASH_BASE_ADDRESS - default 0 -endif # !XIP - if NET_L2_ETHERNET # NETC drops TCP/UDP packets with invalid checksum diff --git a/soc/ti/simplelink/cc32xx/Kconfig.defconfig.cc3220sf b/soc/ti/simplelink/cc32xx/Kconfig.defconfig.cc3220sf index ac26dbe66f748..17ea1bc8f4bb7 100644 --- a/soc/ti/simplelink/cc32xx/Kconfig.defconfig.cc3220sf +++ b/soc/ti/simplelink/cc32xx/Kconfig.defconfig.cc3220sf @@ -16,13 +16,4 @@ config ROM_START_OFFSET default 0x800 if XIP default 0x0 if !XIP -if !XIP - -config FLASH_SIZE - default 0 -config FLASH_BASE_ADDRESS - default 0 - -endif - endif # SOC_CC3220SF diff --git a/soc/ti/simplelink/cc32xx/Kconfig.defconfig.cc3235sf b/soc/ti/simplelink/cc32xx/Kconfig.defconfig.cc3235sf index 9da363f006cb6..be21d6bcf99cf 100644 --- a/soc/ti/simplelink/cc32xx/Kconfig.defconfig.cc3235sf +++ b/soc/ti/simplelink/cc32xx/Kconfig.defconfig.cc3235sf @@ -16,13 +16,4 @@ config ROM_START_OFFSET default 0x800 if XIP default 0x0 if !XIP -if !XIP - -config FLASH_SIZE - default 0 -config FLASH_BASE_ADDRESS - default 0 - -endif - endif # SOC_CC3235SF From 301d24fd88fc5d9e9778fe7a79dde87fb343884c Mon Sep 17 00:00:00 2001 From: Francois Ramu Date: Mon, 10 Jun 2024 14:49:53 +0200 Subject: [PATCH 2643/2849] boards: st: stm32CubeProgrammer runner does not need hex-file path Do not give the path to the zephyr.hex when flashing with the STM32CubeProgrammer in MemoryMapped mode. West flash can retrieve the path and file correctly. Twister cannot find the build directory, the hex file is found correctly, though. Signed-off-by: Francois Ramu --- boards/st/b_u585i_iot02a/board.cmake | 1 - boards/st/stm32h745i_disco/board.cmake | 1 - boards/st/stm32h747i_disco/board.cmake | 1 - boards/st/stm32h750b_dk/board.cmake | 1 - boards/st/stm32h7b3i_dk/board.cmake | 1 - 5 files changed, 5 deletions(-) diff --git a/boards/st/b_u585i_iot02a/board.cmake b/boards/st/b_u585i_iot02a/board.cmake index 8b9544b745b64..dc59f6f17fb75 100644 --- a/boards/st/b_u585i_iot02a/board.cmake +++ b/boards/st/b_u585i_iot02a/board.cmake @@ -14,7 +14,6 @@ endif() if(CONFIG_STM32_MEMMAP) board_runner_args(stm32cubeprogrammer "--port=swd" "--reset-mode=hw") -board_runner_args(stm32cubeprogrammer "--hex-file=${ZEPHYR_BASE}/build/zephyr/zephyr.hex") board_runner_args(stm32cubeprogrammer "--extload=MX25LM51245G_STM32U585I-IOT02A.stldr") else() board_runner_args(stm32cubeprogrammer "--erase" "--port=swd" "--reset-mode=hw") diff --git a/boards/st/stm32h745i_disco/board.cmake b/boards/st/stm32h745i_disco/board.cmake index 94731b3e0f996..d52fff882b734 100644 --- a/boards/st/stm32h745i_disco/board.cmake +++ b/boards/st/stm32h745i_disco/board.cmake @@ -11,7 +11,6 @@ endif() if(CONFIG_STM32_MEMMAP) board_runner_args(stm32cubeprogrammer "--port=swd" "--reset-mode=hw") -board_runner_args(stm32cubeprogrammer "--hex-file=${ZEPHYR_BASE}/build/zephyr/zephyr.hex") board_runner_args(stm32cubeprogrammer "--extload=MT25TL01G_STM32H745I-DISCO.stldr") else() board_runner_args(stm32cubeprogrammer "--port=swd" "--reset-mode=hw") diff --git a/boards/st/stm32h747i_disco/board.cmake b/boards/st/stm32h747i_disco/board.cmake index 288e16557cfd6..cffd0a071e9ba 100644 --- a/boards/st/stm32h747i_disco/board.cmake +++ b/boards/st/stm32h747i_disco/board.cmake @@ -13,7 +13,6 @@ endif() if(CONFIG_STM32_MEMMAP) board_runner_args(stm32cubeprogrammer "--port=swd" "--reset-mode=hw") -board_runner_args(stm32cubeprogrammer "--hex-file=${ZEPHYR_BASE}/build/zephyr/zephyr.hex") board_runner_args(stm32cubeprogrammer "--extload=MT25TL01G_STM32H747I-DISCO.stldr") else() board_runner_args(stm32cubeprogrammer "--port=swd" "--reset-mode=hw") diff --git a/boards/st/stm32h750b_dk/board.cmake b/boards/st/stm32h750b_dk/board.cmake index 56e0e8df96a2a..c38a92dfacc7d 100644 --- a/boards/st/stm32h750b_dk/board.cmake +++ b/boards/st/stm32h750b_dk/board.cmake @@ -5,7 +5,6 @@ board_runner_args(openocd --target-handle=_CHIPNAME.cpu0) if(CONFIG_STM32_MEMMAP) board_runner_args(stm32cubeprogrammer "--port=swd" "--reset-mode=hw") -board_runner_args(stm32cubeprogrammer "--hex-file=${ZEPHYR_BASE}/build/zephyr/zephyr.hex") board_runner_args(stm32cubeprogrammer "--extload=MT25TL01G_STM32H750B-DISCO.stldr") else() board_runner_args(stm32cubeprogrammer "--erase" "--port=swd" "--reset-mode=hw" ) diff --git a/boards/st/stm32h7b3i_dk/board.cmake b/boards/st/stm32h7b3i_dk/board.cmake index 091f1d393a26d..027413fd66cf2 100644 --- a/boards/st/stm32h7b3i_dk/board.cmake +++ b/boards/st/stm32h7b3i_dk/board.cmake @@ -6,7 +6,6 @@ board_runner_args(openocd --target-handle=_CHIPNAME.cpu0) if(CONFIG_STM32_MEMMAP) board_runner_args(stm32cubeprogrammer "--port=swd" "--reset-mode=hw") -board_runner_args(stm32cubeprogrammer "--hex-file=${ZEPHYR_BASE}/build/zephyr/zephyr.hex") board_runner_args(stm32cubeprogrammer "--extload=MX25LM51245G_STM32H7B3I-DISCO.stldr") else() board_runner_args(stm32cubeprogrammer "--erase" "--port=swd" "--reset-mode=hw" ) From f78c51d99d1fc6deb9ec2e76e50f32fee56e8621 Mon Sep 17 00:00:00 2001 From: Rubin Gerritsen Date: Fri, 7 Jun 2024 14:57:32 +0200 Subject: [PATCH 2644/2849] checkpatch: Add exception to BRACKED_SPACE rule for macros When brackets are used in macros, there may sometimes be a space in front of them. The checkpatch script should allow this. The change includes the example that triggered the need for this change. Signed-off-by: Rubin Gerritsen --- scripts/checkpatch.pl | 2 ++ 1 file changed, 2 insertions(+) diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index 27fbd880ef639..c0688e6274182 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -4419,11 +4419,13 @@ sub process { # 1. with a type on the left -- int [] a; # 2. at the beginning of a line for slice initialisers -- [0...10] = 5, # 3. inside a curly brace -- = { [0...10] = 5 } +# 4. inside macro arguments, example: #define HCI_ERR(err) [err] = #err while ($line =~ /(.*?\s)\[/g) { my ($where, $prefix) = ($-[1], $1); if ($prefix !~ /$Type\s+$/ && ($where != 0 || $prefix !~ /^.\s+$/) && $prefix !~ /[{,:]\s+$/ && + $prefix !~ /\#define\s+.+\s+$/ && $prefix !~ /:\s+$/) { if (ERROR("BRACKET_SPACE", "space prohibited before open square bracket '['\n" . $herecurr) && From 774ed6028061cc895c1a71f3215f9c838ce9ee25 Mon Sep 17 00:00:00 2001 From: Ioannis Karachalios Date: Wed, 5 Jun 2024 00:00:39 +0300 Subject: [PATCH 2645/2849] drivers: spi: smartbond: Add async API support This commit should deal with adding support for asynchronous operations. It also adds support for DMA acceleration via a Kconfig variable (enaled by default as DMA should be considered scales faster than the interrupt-driven approach). Signed-off-by: Ioannis Karachalios --- drivers/spi/Kconfig.smartbond | 10 + drivers/spi/spi_smartbond.c | 982 +++++++++++++++++++++++++++++++++- 2 files changed, 970 insertions(+), 22 deletions(-) diff --git a/drivers/spi/Kconfig.smartbond b/drivers/spi/Kconfig.smartbond index 9c003eb915ddc..6198375003634 100644 --- a/drivers/spi/Kconfig.smartbond +++ b/drivers/spi/Kconfig.smartbond @@ -7,3 +7,13 @@ config SPI_SMARTBOND depends on DT_HAS_RENESAS_SMARTBOND_SPI_ENABLED help Enables SPI driver for Renesas SmartBond(tm) DA1469x series MCU. + +config SPI_SMARTBOND_DMA + bool "Renesas Smartbond(tm) SPI with DMA acceleration" + default y + depends on SPI_SMARTBOND + select DMA + help + Enables using the DMA engine instead of interrupt-driven + approach. This acceleration is available only for + asynchronous transfers. diff --git a/drivers/spi/spi_smartbond.c b/drivers/spi/spi_smartbond.c index 730a3b37a9db4..f067da9c0a098 100644 --- a/drivers/spi/spi_smartbond.c +++ b/drivers/spi/spi_smartbond.c @@ -18,31 +18,88 @@ LOG_MODULE_REGISTER(spi_smartbond); #include #include #include +#include +#include #include #include -#define DIVN_CLK 32000000 /* divN_clk 32MHz */ -#define SCLK_FREQ_2MHZ (DIVN_CLK / 14) /* 2.285714MHz*/ -#define SCLK_FREQ_4MHZ (DIVN_CLK / 8) /* 4MHz */ -#define SCLK_FREQ_8MHZ (DIVN_CLK / 4) /* 8MHz */ -#define SCLK_FREQ_16MHZ (DIVN_CLK / 2) /* 16MHz */ +#define DIVN_CLK 32000000 /* DIVN clock: fixed @32MHz */ +#define SCLK_FREQ_2MHZ (DIVN_CLK / 14) /* 2.285714 MHz*/ +#define SCLK_FREQ_4MHZ (DIVN_CLK / 8) /* 4 MHz */ +#define SCLK_FREQ_8MHZ (DIVN_CLK / 4) /* 8 MHz */ +#define SCLK_FREQ_16MHZ (DIVN_CLK / 2) /* 16 MHz */ + +enum spi_smartbond_transfer { + SPI_SMARTBOND_TRANSFER_TX_ONLY, + SPI_SMARTBOND_TRANSFER_RX_ONLY, + SPI_SMARTBOND_TRANSFER_TX_RX, + SPI_SMARTBOND_TRANSFER_NONE +}; + +enum spi_smartbond_dma_channel { + SPI_SMARTBOND_DMA_TX_CHANNEL, + SPI_SMARTBOND_DMA_RX_CHANNEL +}; + +enum spi_smartbond_fifo_mode { + /* Bi-directional mode */ + SPI_SMARTBOND_FIFO_MODE_TX_RX, + /* TX FIFO single depth, no flow control */ + SPI_SMARTBOND_FIFO_MODE_RX_ONLY, + /* RX FIFO single depth, no flow control */ + SPI_SMARTBOND_FIFO_MODE_TX_ONLY, + SPI_SMARTBOND_FIFO_NONE +}; struct spi_smartbond_cfg { SPI_Type *regs; int periph_clock_config; const struct pinctrl_dev_config *pcfg; +#ifdef CONFIG_SPI_SMARTBOND_DMA + int tx_dma_chan; + int rx_dma_chan; + uint8_t tx_slot_mux; + uint8_t rx_slot_mux; + const struct device *tx_dma_ctrl; + const struct device *rx_dma_ctrl; +#endif }; struct spi_smartbond_data { struct spi_context ctx; uint8_t dfs; + #if defined(CONFIG_PM_DEVICE) ATOMIC_DEFINE(pm_policy_state_flag, 1); uint32_t spi_ctrl_reg; #endif + +#ifdef CONFIG_SPI_SMARTBOND_DMA + struct dma_config tx_dma_cfg; + struct dma_config rx_dma_cfg; + struct dma_block_config tx_dma_block_cfg; + struct dma_block_config rx_dma_block_cfg; + struct k_sem rx_dma_sync; + struct k_sem tx_dma_sync; + + ATOMIC_DEFINE(dma_channel_atomic_flag, 2); + +#endif + +#if defined(CONFIG_SPI_ASYNC) || defined(CONFIG_SPI_SMARTBOND_DMA) + size_t rx_len; + size_t tx_len; + size_t transferred; + enum spi_smartbond_transfer transfer_mode; +#endif }; +#define SPI_CTRL_REG_SET_FIELD(_field, _var, _val) \ + (_var) = \ + (((_var) & ~SPI_SPI_CTRL_REG_ ## _field ## _Msk) | \ + (((_val) << SPI_SPI_CTRL_REG_ ## _field ## _Pos) & SPI_SPI_CTRL_REG_ ## _field ## _Msk)) + static inline void spi_smartbond_enable(const struct spi_smartbond_cfg *cfg, bool enable) { if (enable) { @@ -60,6 +117,60 @@ static inline bool spi_smartbond_isenabled(const struct spi_smartbond_cfg *cfg) (!(cfg->regs->SPI_CTRL_REG & SPI_SPI_CTRL_REG_SPI_RST_Msk)); } +static inline void spi_smartbond_write_word(const struct device *dev) +{ + const struct spi_smartbond_cfg *cfg = dev->config; + struct spi_smartbond_data *data = dev->data; + + /* + * No need to typecast the register address as the controller will automatically + * generate the necessary clock cycles based on the data size. + */ + switch (data->dfs) { + case 1: + cfg->regs->SPI_RX_TX_REG = *(uint8_t *)data->ctx.tx_buf; + break; + case 2: + cfg->regs->SPI_RX_TX_REG = sys_get_le16(data->ctx.tx_buf); + break; + case 4: + cfg->regs->SPI_RX_TX_REG = sys_get_le32(data->ctx.tx_buf); + break; + } +} + +static inline void spi_smartbond_write_dummy(const struct device *dev) +{ + const struct spi_smartbond_cfg *cfg = dev->config; + + cfg->regs->SPI_RX_TX_REG = 0x0; +} + +static inline void spi_smartbond_read_word(const struct device *dev) +{ + const struct spi_smartbond_cfg *cfg = dev->config; + struct spi_smartbond_data *data = dev->data; + + switch (data->dfs) { + case 1: + *(uint8_t *)data->ctx.rx_buf = cfg->regs->SPI_RX_TX_REG; + break; + case 2: + sys_put_le16((uint16_t)cfg->regs->SPI_RX_TX_REG, data->ctx.rx_buf); + break; + case 4: + sys_put_le32(cfg->regs->SPI_RX_TX_REG, data->ctx.rx_buf); + break; + } +} + +static inline void spi_smartbond_read_discard(const struct device *dev) +{ + const struct spi_smartbond_cfg *cfg = dev->config; + + (void)cfg->regs->SPI_RX_TX_REG; +} + static inline int spi_smartbond_set_speed(const struct spi_smartbond_cfg *cfg, const uint32_t frequency) { @@ -208,6 +319,732 @@ static int spi_smartbond_configure(const struct spi_smartbond_cfg *cfg, return 0; } +#if defined(CONFIG_SPI_ASYNC) || defined(CONFIG_SPI_SMARTBOND_DMA) +static inline void spi_smartbond_isr_set_status(const struct device *dev, bool status) +{ + const struct spi_smartbond_cfg *cfg = dev->config; + + if (status) { + cfg->regs->SPI_CTRL_REG |= SPI_SPI_CTRL_REG_SPI_MINT_Msk; + } else { + cfg->regs->SPI_CTRL_REG &= ~SPI_SPI_CTRL_REG_SPI_MINT_Msk; + } +} + +static inline bool spi_smartbond_is_busy(const struct device *dev) +{ + const struct spi_smartbond_cfg *cfg = dev->config; + + return (cfg->regs->SPI_CTRL_REG & SPI_SPI_CTRL_REG_SPI_BUSY_Msk); +} + +static inline void spi_smartbond_clear_interrupt(const struct device *dev) +{ + const struct spi_smartbond_cfg *cfg = dev->config; + + cfg->regs->SPI_CLEAR_INT_REG = 0x1; +} + +/* 0 = No RX data available, 1 = data has been transmitted and received */ +static inline bool spi_smartbond_is_rx_data(const struct device *dev) +{ + const struct spi_smartbond_cfg *cfg = dev->config; + + return (cfg->regs->SPI_CTRL_REG & SPI_SPI_CTRL_REG_SPI_INT_BIT_Msk); +} + +static inline uint8_t spi_smartbond_get_fifo_mode(const struct device *dev) +{ + const struct spi_smartbond_cfg *cfg = dev->config; + + return ((cfg->regs->SPI_CTRL_REG & SPI_SPI_CTRL_REG_SPI_FIFO_MODE_Msk) >> + SPI_SPI_CTRL_REG_SPI_FIFO_MODE_Pos); +} + +static void spi_smartbond_set_fifo_mode(const struct device *dev, enum spi_smartbond_fifo_mode mode) +{ + const struct spi_smartbond_cfg *cfg = dev->config; + bool is_enabled = spi_smartbond_isenabled(cfg); + enum spi_smartbond_fifo_mode current_mode = spi_smartbond_get_fifo_mode(dev); + uint32_t spi_ctrl_reg = cfg->regs->SPI_CTRL_REG; + +#ifdef CONFIG_SPI_SMARTBOND_DMA + struct spi_smartbond_data *data = dev->data; +#endif + + if ((current_mode != mode) +#ifdef CONFIG_SPI_SMARTBOND_DMA + || (data->dfs == 4) +#endif + ) { + if (current_mode != SPI_SMARTBOND_FIFO_MODE_RX_ONLY) { + while (spi_smartbond_is_busy(dev)) { + ; + } + } + /* Controller should be disabled when FIFO mode is updated */ + cfg->regs->SPI_CTRL_REG &= ~SPI_SPI_CTRL_REG_SPI_ON_Msk; + +#ifdef CONFIG_SPI_SMARTBOND_DMA + /* + * Workaround for the controller that cannot generate DMA requests + * for 4-byte bus length. + */ + if (data->dfs == 4) { + mode = SPI_SMARTBOND_FIFO_NONE; + } +#endif + SPI_CTRL_REG_SET_FIELD(SPI_FIFO_MODE, spi_ctrl_reg, mode); + + + if (mode != SPI_SMARTBOND_FIFO_NONE) { + SPI_CTRL_REG_SET_FIELD(SPI_DMA_TXREQ_MODE, spi_ctrl_reg, 0); + } else { + SPI_CTRL_REG_SET_FIELD(SPI_DMA_TXREQ_MODE, spi_ctrl_reg, 1); + } + + if (is_enabled) { + SPI_CTRL_REG_SET_FIELD(SPI_ON, spi_ctrl_reg, 1); + } + + cfg->regs->SPI_CTRL_REG = spi_ctrl_reg; + } +} + +static int spi_smartbond_transfer_mode_get(const struct device *dev) +{ + struct spi_smartbond_data *data = dev->data; + struct spi_context *ctx = &data->ctx; + + if (spi_context_rx_buf_on(ctx) || spi_context_tx_buf_on(ctx)) { + /* + * Check only buffers' length as it might happen that current buffer is NULL. + * In such a case the context should be updated and a dummy write/read should + * take place. + */ + if (ctx->rx_len || ctx->tx_len) { + spi_smartbond_set_fifo_mode(dev, SPI_SMARTBOND_FIFO_MODE_TX_RX); + return SPI_SMARTBOND_TRANSFER_TX_RX; + } + + if (!spi_context_rx_buf_on(ctx)) { + spi_smartbond_set_fifo_mode(dev, SPI_SMARTBOND_FIFO_MODE_TX_ONLY); + return SPI_SMARTBOND_TRANSFER_TX_ONLY; + } + + if (!spi_context_tx_buf_on(ctx)) { + /* + * Use the TX/RX mode with TX being dummy. Using the RX only mode + * is a bit tricky as the controller should generate clock cycles + * automatically and immediately after the ISR is enabled. + */ + spi_smartbond_set_fifo_mode(dev, SPI_SMARTBOND_FIFO_MODE_TX_RX); + return SPI_SMARTBOND_TRANSFER_RX_ONLY; + } + } + + /* Return waiting updating the fifo mode */ + return SPI_SMARTBOND_TRANSFER_NONE; +} + +static inline void spi_smartbond_transfer_mode_check_and_update(const struct device *dev) +{ + struct spi_smartbond_data *data = dev->data; + + data->transfer_mode = spi_smartbond_transfer_mode_get(dev); +} +#endif + +#ifdef CONFIG_SPI_ASYNC +static inline bool spi_smartbond_is_tx_full(const struct device *dev) +{ + const struct spi_smartbond_cfg *cfg = dev->config; + + return (cfg->regs->SPI_CTRL_REG & SPI_SPI_CTRL_REG_SPI_TXH_Msk); +} + +static void spi_smartbond_write(const struct device *dev) +{ + struct spi_smartbond_data *data = dev->data; + struct spi_context *ctx = &data->ctx; + + while (spi_context_tx_buf_on(ctx)) { + /* Check if TX FIFO is full as otherwise undefined data should be transmitted. */ + if (spi_smartbond_is_tx_full(dev)) { + spi_smartbond_clear_interrupt(dev); + break; + } + /* Send to TX FIFO and update buffer pointer. */ + spi_smartbond_write_word(dev); + spi_context_update_tx(ctx, data->dfs, 1); + + /* + * It might happen that a NULL buffer with a non-zero length is provided. + * In that case, the bytes should be consumed. + */ + if (ctx->rx_len && !ctx->rx_buf) { + spi_smartbond_read_discard(dev); + spi_context_update_rx(ctx, data->dfs, 1); + } + } +} + +static void spi_smartbond_transfer(const struct device *dev) +{ + struct spi_smartbond_data *data = dev->data; + struct spi_context *ctx = &data->ctx; + + while (data->rx_len) { + /* Zero means that RX FIFO or register is empty */ + if (!spi_smartbond_is_rx_data(dev)) { + break; + } + + if (ctx->rx_buf) { + spi_smartbond_read_word(dev); + } else { + spi_smartbond_read_discard(dev); + } + spi_context_update_rx(ctx, data->dfs, 1); + + spi_smartbond_clear_interrupt(dev); + + data->rx_len--; + data->transferred++; + } + + while (data->tx_len) { + /* Check if TX FIFO is full as otherwise undefined data should be transmitted. */ + if (spi_smartbond_is_tx_full(dev)) { + break; + } + + if (ctx->tx_buf) { + spi_smartbond_write_word(dev); + } else { + spi_smartbond_write_dummy(dev); + } + spi_context_update_tx(ctx, data->dfs, 1); + + data->tx_len--; + } +} + +static void spi_smartbond_read(const struct device *dev) +{ + struct spi_smartbond_data *data = dev->data; + struct spi_context *ctx = &data->ctx; + + while (spi_context_rx_buf_on(ctx)) { + /* Zero means that RX FIFO or register is empty */ + if (!spi_smartbond_is_rx_data(dev)) { + break; + } + + spi_smartbond_read_word(dev); + spi_context_update_rx(ctx, data->dfs, 1); + spi_smartbond_clear_interrupt(dev); + } + + /* Perform dummy access to generate the required clock cycles */ + while (data->tx_len) { + if (spi_smartbond_is_tx_full(dev)) { + break; + } + spi_smartbond_write_dummy(dev); + + data->tx_len--; + } +} + +static void spi_smartbond_isr_trigger(const struct device *dev) +{ + struct spi_smartbond_data *data = dev->data; + struct spi_context *ctx = &data->ctx; + + data->transfer_mode = spi_smartbond_transfer_mode_get(dev); + + switch (data->transfer_mode) { + case SPI_SMARTBOND_TRANSFER_RX_ONLY: + data->tx_len = spi_context_total_rx_len(ctx); + spi_smartbond_read(dev); + break; + case SPI_SMARTBOND_TRANSFER_TX_ONLY: + spi_smartbond_write(dev); + break; + case SPI_SMARTBOND_TRANSFER_TX_RX: + /* + * Each sub-transfer in the descriptor list should be exercised + * separately as it might happen that a buffer is NULL with + * non-zero length. + */ + data->rx_len = spi_context_max_continuous_chunk(ctx); + data->tx_len = data->rx_len; + spi_smartbond_transfer(dev); + break; + case SPI_SMARTBOND_TRANSFER_NONE: + __fallthrough; + default: + __ASSERT_MSG_INFO("Invalid transfer mode"); + break; + } + + spi_smartbond_isr_set_status(dev, true); +} + +static int spi_smartbond_transceive_async(const struct device *dev, + const struct spi_config *spi_cfg, + const struct spi_buf_set *tx_bufs, + const struct spi_buf_set *rx_bufs, spi_callback_t cb, + void *userdata) +{ + const struct spi_smartbond_cfg *cfg = dev->config; + struct spi_smartbond_data *data = dev->data; + struct spi_context *ctx = &data->ctx; + int rc; + + spi_context_lock(ctx, true, cb, userdata, spi_cfg); + + rc = spi_smartbond_configure(cfg, data, spi_cfg); + if (rc == 0) { + spi_smartbond_pm_policy_state_lock_get(data); + spi_context_buffers_setup(ctx, tx_bufs, rx_bufs, data->dfs); + spi_context_cs_control(ctx, true); + + /* + * PM constraints will be released within ISR once all transfers + * are exercised along with de-asserting the #CS line. + */ + spi_smartbond_isr_trigger(dev); + } + /* + * Context will actually be released when \sa spi_context_complete + * is called. + */ + spi_context_release(ctx, rc); + + return rc; +} +#endif + +#if defined(CONFIG_SPI_ASYNC) || defined(CONFIG_SPI_SMARTBOND_DMA) +static void spi_smartbond_isr(void *args) +{ +#ifdef CONFIG_SPI_ASYNC + struct device *dev = args; + struct spi_smartbond_data *data = dev->data; + struct spi_context *ctx = &data->ctx; + + switch (data->transfer_mode) { + case SPI_SMARTBOND_TRANSFER_RX_ONLY: + spi_smartbond_read(dev); + break; + case SPI_SMARTBOND_TRANSFER_TX_ONLY: + spi_smartbond_write(dev); + break; + case SPI_SMARTBOND_TRANSFER_TX_RX: + /* Exersice the type of the next sub-transfer */ + if (!data->rx_len && !data->tx_len) { + spi_smartbond_transfer_mode_check_and_update(dev); + + if (data->transfer_mode == SPI_SMARTBOND_TRANSFER_RX_ONLY) { + data->tx_len = spi_context_total_rx_len(ctx) - data->transferred; + /* Clear in case another truncated transfer should be executed */ + data->transferred = 0; + spi_smartbond_read(dev); + } else if (data->transfer_mode == SPI_SMARTBOND_TRANSFER_TX_ONLY) { + spi_smartbond_write(dev); + } else if (data->transfer_mode == SPI_SMARTBOND_TRANSFER_TX_RX) { + data->rx_len = spi_context_max_continuous_chunk(ctx); + data->tx_len = data->rx_len; + spi_smartbond_transfer(dev); + } + } else { + spi_smartbond_transfer(dev); + } + break; + case SPI_SMARTBOND_TRANSFER_NONE: + __fallthrough; + default: + __ASSERT_MSG_INFO("Invalid transfer mode"); + break; + } + + /* All buffers have been exercised, signal completion */ + if (!spi_context_tx_buf_on(ctx) && !spi_context_rx_buf_on(ctx)) { + spi_smartbond_isr_set_status(dev, false); + + /* Mark completion to trigger callback function */ + spi_context_complete(ctx, dev, 0); + + spi_context_cs_control(ctx, false); + spi_smartbond_pm_policy_state_lock_put(data); + } +#endif +} +#endif + +#ifdef CONFIG_SPI_SMARTBOND_DMA +static uint32_t spi_smartbond_read_dummy_buf; + +/* + * Should be used to flush the RX FIFO in case a transaction is requested + * with NULL pointer and non-zero length. In such a case, data will be + * shifted into the RX FIFO (regardless of whether or not the RX mode is + * disabled) which should then be flushed. Otherwise, a next read operation + * will result in fetching old bytes. + */ +static void spi_smartbond_flush_rx_fifo(const struct device *dev) +{ + while (spi_smartbond_is_busy(dev)) { + }; + while (spi_smartbond_is_rx_data(dev)) { + spi_smartbond_read_discard(dev); + spi_smartbond_clear_interrupt(dev); + } +} + +static int spi_smartbond_dma_tx_channel_request(const struct device *dev) +{ + struct spi_smartbond_data *data = dev->data; + const struct spi_smartbond_cfg *config = dev->config; + + if (!atomic_test_and_set_bit(data->dma_channel_atomic_flag, + SPI_SMARTBOND_DMA_TX_CHANNEL)) { + if (dma_request_channel(config->tx_dma_ctrl, (void *)&config->tx_dma_chan) < 0) { + atomic_clear_bit(data->dma_channel_atomic_flag, + SPI_SMARTBOND_DMA_TX_CHANNEL); + return -EIO; + } + } + + return 0; +} + +#ifdef CONFIG_PM_DEVICE +static void spi_smartbond_dma_tx_channel_release(const struct device *dev) +{ + struct spi_smartbond_data *data = dev->data; + const struct spi_smartbond_cfg *config = dev->config; + + if (atomic_test_and_clear_bit(data->dma_channel_atomic_flag, + SPI_SMARTBOND_DMA_TX_CHANNEL)) { + dma_release_channel(config->tx_dma_ctrl, config->tx_dma_chan); + } +} +#endif + +static int spi_smartbond_dma_rx_channel_request(const struct device *dev) +{ + struct spi_smartbond_data *data = dev->data; + const struct spi_smartbond_cfg *config = dev->config; + + if (!atomic_test_and_set_bit(data->dma_channel_atomic_flag, + SPI_SMARTBOND_DMA_RX_CHANNEL)) { + if (dma_request_channel(config->rx_dma_ctrl, (void *)&config->rx_dma_chan) < 0) { + atomic_clear_bit(data->dma_channel_atomic_flag, + SPI_SMARTBOND_DMA_RX_CHANNEL); + return -EIO; + } + } + + return 0; +} + +#ifdef CONFIG_PM_DEVICE +static void spi_smartbond_dma_rx_channel_release(const struct device *dev) +{ + struct spi_smartbond_data *data = dev->data; + const struct spi_smartbond_cfg *config = dev->config; + + if (atomic_test_and_clear_bit(data->dma_channel_atomic_flag, + SPI_SMARTBOND_DMA_RX_CHANNEL)) { + dma_release_channel(config->rx_dma_ctrl, config->rx_dma_chan); + } +} +#endif + +static void spi_smartbond_tx_dma_cb(const struct device *dma, void *arg, + uint32_t id, int status) +{ + const struct device *dev = arg; + struct spi_smartbond_data *data = dev->data; + struct spi_context *ctx = &data->ctx; + + if (status < 0) { + LOG_WRN("DMA transfer did not complete"); + } + + spi_context_update_tx(ctx, data->dfs, data->tx_len); + k_sem_give(&data->tx_dma_sync); +} + +static void spi_smartbond_rx_dma_cb(const struct device *dma, void *arg, + uint32_t id, int status) +{ + const struct device *dev = arg; + struct spi_smartbond_data *data = dev->data; + struct spi_context *ctx = &data->ctx; + + if (status < 0) { + LOG_WRN("DMA transfer did not complete"); + } + + spi_context_update_rx(ctx, data->dfs, data->rx_len); + k_sem_give(&data->rx_dma_sync); +} + +#ifdef CONFIG_PM_DEVICE +static void spi_smartbond_dma_deconfig(const struct device *dev) +{ + const struct spi_smartbond_cfg *config = dev->config; + + dma_stop(config->rx_dma_ctrl, config->rx_dma_chan); + dma_stop(config->tx_dma_ctrl, config->tx_dma_chan); + + spi_smartbond_dma_rx_channel_release(dev); + spi_smartbond_dma_tx_channel_release(dev); +} +#endif + +static int spi_smartbond_dma_config(const struct device *dev) +{ + struct spi_smartbond_data *data = dev->data; + const struct spi_smartbond_cfg *config = dev->config; + struct dma_config *tx = &data->tx_dma_cfg; + struct dma_config *rx = &data->rx_dma_cfg; + struct dma_block_config *tx_block = &data->tx_dma_block_cfg; + struct dma_block_config *rx_block = &data->rx_dma_block_cfg; + + /* + * DMA RX should be assigned an even number and + * DMA TX should be assigned the right next + * channel (odd number). + */ + if (!(config->tx_dma_chan & 0x1) || + (config->rx_dma_chan & 0x1) || + (config->tx_dma_chan != (config->rx_dma_chan + 1))) { + LOG_ERR("Invalid RX/TX channel selection"); + return -EINVAL; + } + + if (config->tx_slot_mux != config->rx_slot_mux) { + LOG_ERR("TX/RX DMA slots mismatch"); + return -EINVAL; + } + + if (!device_is_ready(config->tx_dma_ctrl) || + !device_is_ready(config->rx_dma_ctrl)) { + LOG_ERR("TX/RX DMA device is not ready"); + return -ENODEV; + } + + if (spi_smartbond_dma_tx_channel_request(dev) < 0) { + LOG_ERR("TX DMA channel is already occupied"); + return -EIO; + } + + if (spi_smartbond_dma_rx_channel_request(dev) < 0) { + LOG_ERR("RX DMA channel is already occupied"); + return -EIO; + } + + tx->channel_direction = MEMORY_TO_PERIPHERAL; + tx->dma_callback = spi_smartbond_tx_dma_cb; + tx->user_data = (void *)dev; + tx->block_count = 1; + tx->head_block = &data->tx_dma_block_cfg; + tx->error_callback_dis = 1; + tx->dma_slot = config->tx_slot_mux; + tx->channel_priority = 2; + + /* Burst mode is not using when DREQ is one */ + tx->source_burst_length = 1; + tx->dest_burst_length = 1; + /* Source and destination data size should reflect DFS value */ + tx->source_data_size = 0; + tx->dest_data_size = 0; + + /* Do not change */ + tx_block->dest_addr_adj = 0x2; + /* Incremental */ + tx_block->source_addr_adj = 0x0; + tx_block->dest_address = (uint32_t)&config->regs->SPI_RX_TX_REG; + + /* + * To be filled when a transaction is requested and + * should reflect the total number of bytes. + */ + tx_block->block_size = 0; + /* Should reflect the TX buffer */ + tx_block->source_address = 0; + + rx->channel_direction = PERIPHERAL_TO_MEMORY; + rx->dma_callback = spi_smartbond_rx_dma_cb; + rx->user_data = (void *)dev; + rx->block_count = 1; + rx->head_block = &data->rx_dma_block_cfg; + rx->error_callback_dis = 1; + rx->dma_slot = config->rx_slot_mux; + rx->channel_priority = 2; + + /* Burst mode is not using when DREQ is one */ + rx->source_burst_length = 1; + rx->dest_burst_length = 1; + /* Source and destination data size should reflect DFS value */ + rx->source_data_size = 0; + rx->dest_data_size = 0; + + /* Do not change */ + rx_block->source_addr_adj = 0x2; + /* Incremenetal */ + rx_block->dest_addr_adj = 0x0; + rx_block->source_address = (uint32_t)&config->regs->SPI_RX_TX_REG; + + /* + * To be filled when a transaction is requested and + * should reflect the total number of bytes. + */ + rx_block->block_size = 0; + /* Should reflect the RX buffer */ + rx_block->dest_address = 0; + + return 0; +} + +static int spi_smartbond_dma_trigger(const struct device *dev) +{ + struct spi_smartbond_data *data = dev->data; + const struct spi_smartbond_cfg *config = dev->config; + struct spi_context *ctx = &data->ctx; + struct dma_config *tx = &data->tx_dma_cfg; + struct dma_config *rx = &data->rx_dma_cfg; + struct dma_block_config *tx_block = &data->tx_dma_block_cfg; + struct dma_block_config *rx_block = &data->rx_dma_block_cfg; + + rx->source_data_size = data->dfs; + rx->dest_data_size = data->dfs; + tx->source_data_size = data->dfs; + tx->dest_data_size = data->dfs; + + data->transfer_mode = spi_smartbond_transfer_mode_get(dev); + do { + switch (data->transfer_mode) { + case SPI_SMARTBOND_TRANSFER_RX_ONLY: + spi_smartbond_flush_rx_fifo(dev); + + data->rx_len = spi_context_max_continuous_chunk(ctx); + data->tx_len = data->rx_len; + + rx_block->block_size = data->rx_len * data->dfs; + tx_block->block_size = rx_block->block_size; + + rx_block->dest_address = (uint32_t)ctx->rx_buf; + rx_block->dest_addr_adj = 0x0; + tx_block->source_address = (uint32_t)&spi_smartbond_read_dummy_buf; + /* Non-incremental */ + tx_block->source_addr_adj = 0x2; + + if (dma_config(config->tx_dma_ctrl, config->tx_dma_chan, tx) < 0) { + LOG_ERR("TX DMA configuration failed"); + return -EINVAL; + } + if (dma_config(config->rx_dma_ctrl, config->rx_dma_chan, rx) < 0) { + LOG_ERR("RX DMA configuration failed"); + return -EINVAL; + } + dma_start(config->rx_dma_ctrl, config->rx_dma_chan); + dma_start(config->tx_dma_ctrl, config->tx_dma_chan); + + /* Wait for the current DMA transfer to complete */ + k_sem_take(&data->tx_dma_sync, K_FOREVER); + k_sem_take(&data->rx_dma_sync, K_FOREVER); + break; + case SPI_SMARTBOND_TRANSFER_TX_ONLY: + spi_smartbond_flush_rx_fifo(dev); + + data->tx_len = spi_context_max_continuous_chunk(ctx); + data->rx_len = data->tx_len; + + tx_block->block_size = data->tx_len * data->dfs; + tx_block->source_address = (uint32_t)ctx->tx_buf; + tx_block->source_addr_adj = 0x0; + + if (dma_config(config->tx_dma_ctrl, config->tx_dma_chan, tx) < 0) { + LOG_ERR("TX DMA configuration failed"); + return -EINVAL; + } + dma_start(config->tx_dma_ctrl, config->tx_dma_chan); + + /* Wait for the current DMA transfer to complete */ + k_sem_take(&data->tx_dma_sync, K_FOREVER); + break; + case SPI_SMARTBOND_TRANSFER_TX_RX: + spi_smartbond_flush_rx_fifo(dev); + + data->rx_len = spi_context_max_continuous_chunk(ctx); + data->tx_len = data->rx_len; + /* + * DMA block size represents total number of bytes whilist, + * context length is divided by the data size (dfs). + */ + tx_block->block_size = data->tx_len * data->dfs; + rx_block->block_size = tx_block->block_size; + + if (ctx->tx_buf) { + tx_block->source_address = (uint32_t)ctx->tx_buf; + tx_block->source_addr_adj = 0x0; + } else { + tx_block->source_address = (uint32_t)&spi_smartbond_read_dummy_buf; + tx_block->source_addr_adj = 0x2; + } + + if (ctx->rx_buf) { + rx_block->dest_address = (uint32_t)ctx->rx_buf; + rx_block->dest_addr_adj = 0x0; + } else { + rx_block->dest_address = (uint32_t)&spi_smartbond_read_dummy_buf; + rx_block->dest_addr_adj = 0x2; + } + + if (dma_config(config->tx_dma_ctrl, config->tx_dma_chan, tx) < 0) { + LOG_ERR("TX DMA configuration failed"); + return -EINVAL; + } + if (dma_config(config->rx_dma_ctrl, config->rx_dma_chan, rx) < 0) { + LOG_ERR("RX DMA configuration failed"); + return -EINVAL; + } + dma_start(config->rx_dma_ctrl, config->rx_dma_chan); + dma_start(config->tx_dma_ctrl, config->tx_dma_chan); + + k_sem_take(&data->tx_dma_sync, K_FOREVER); + k_sem_take(&data->rx_dma_sync, K_FOREVER); + + /* + * Regardless of whether or not the RX FIFO is enabled, received + * bytes are pushed into it. As such, the RXI FIFO should be + * flushed so that a next read access retrives the correct bytes + * and not old ones. + */ + if (!ctx->rx_buf) { + spi_smartbond_flush_rx_fifo(dev); + } + break; + case SPI_SMARTBOND_TRANSFER_NONE: + __fallthrough; + default: + __ASSERT_MSG_INFO("Invalid transfer mode"); + break; + } + + spi_smartbond_transfer_mode_check_and_update(dev); + } while (data->transfer_mode != SPI_SMARTBOND_TRANSFER_NONE); + + return 0; +} +#endif + static int spi_smartbond_transceive(const struct device *dev, const struct spi_config *spi_cfg, const struct spi_buf_set *tx_bufs, const struct spi_buf_set *rx_bufs) @@ -215,54 +1052,57 @@ static int spi_smartbond_transceive(const struct device *dev, const struct spi_c const struct spi_smartbond_cfg *cfg = dev->config; struct spi_smartbond_data *data = dev->data; struct spi_context *ctx = &data->ctx; - uint32_t bitmask; int rc; spi_smartbond_pm_policy_state_lock_get(data); spi_context_lock(&data->ctx, false, NULL, NULL, spi_cfg); + rc = spi_smartbond_configure(cfg, data, spi_cfg); if (rc == 0) { spi_context_buffers_setup(ctx, tx_bufs, rx_bufs, data->dfs); spi_context_cs_control(ctx, true); - bitmask = ~((~0UL) << SPI_WORD_SIZE_GET(data->ctx.config->operation)); +#ifdef CONFIG_SPI_SMARTBOND_DMA + rc = spi_smartbond_dma_trigger(dev); + /* Mark completion to trigger callback function */ + spi_context_complete(ctx, dev, 0); +#else while (spi_context_tx_buf_on(ctx) || spi_context_rx_buf_on(ctx)) { if (spi_context_tx_buf_on(ctx)) { - cfg->regs->SPI_RX_TX_REG = (*(uint32_t *)ctx->tx_buf) & bitmask; + spi_smartbond_write_word(dev); spi_context_update_tx(ctx, data->dfs, 1); } else { - cfg->regs->SPI_RX_TX_REG = 0UL; + spi_smartbond_write_dummy(dev); } while (!(cfg->regs->SPI_CTRL_REG & SPI_SPI_CTRL_REG_SPI_INT_BIT_Msk)) { }; if (spi_context_rx_buf_on(ctx)) { - (*(uint32_t *)ctx->rx_buf) = cfg->regs->SPI_RX_TX_REG & bitmask; + spi_smartbond_read_word(dev); spi_context_update_rx(ctx, data->dfs, 1); } else { - (void)cfg->regs->SPI_RX_TX_REG; + spi_smartbond_read_discard(dev); + /* + * It might happen that a NULL buffer with a non-zero length + * is provided. In that case, the bytes should be consumed. + */ + if (ctx->rx_len) { + spi_context_update_rx(ctx, data->dfs, 1); + } } cfg->regs->SPI_CLEAR_INT_REG = 1UL; } +#endif + + spi_context_cs_control(ctx, false); } - spi_context_cs_control(ctx, false); spi_context_release(&data->ctx, rc); spi_smartbond_pm_policy_state_lock_put(data); return rc; } -#ifdef CONFIG_SPI_ASYNC -static int spi_smartbond_transceive_async(const struct device *dev, - const struct spi_config *spi_cfg, - const struct spi_buf_set *tx_bufs, - const struct spi_buf_set *rx_bufs, spi_callback_t cb, - void *userdata) -{ - return -ENOTSUP; -} -#endif static int spi_smartbond_release(const struct device *dev, const struct spi_config *spi_cfg) { @@ -308,6 +1148,14 @@ static int spi_smartbond_resume(const struct device *dev) return rc; } +#ifdef CONFIG_SPI_SMARTBOND_DMA + rc = spi_smartbond_dma_config(dev); + if (rc < 0) { + LOG_ERR("Failed to configure DMA"); + return rc; + } +#endif + spi_context_unlock_unconditionally(&data->ctx); return 0; @@ -331,6 +1179,10 @@ static int spi_smartbond_suspend(const struct device *dev) LOG_WRN("Failed to configure the SPI pins to inactive state"); } +#ifdef CONFIG_SPI_SMARTBOND_DMA + spi_smartbond_dma_deconfig(dev); +#endif + return ret; } @@ -356,11 +1208,51 @@ static int spi_smartbond_pm_action(const struct device *dev, } #endif +#define SPI_SMARTBOND_ISR_CONNECT \ + IRQ_CONNECT(DT_IRQN(DT_NODELABEL(spi)), DT_IRQ(DT_NODELABEL(spi), priority), \ + spi_smartbond_isr, DEVICE_DT_GET(DT_NODELABEL(spi)), 0); \ + irq_enable(DT_IRQN(DT_NODELABEL(spi))); + +#define SPI2_SMARTBOND_ISR_CONNECT \ + IRQ_CONNECT(DT_IRQN(DT_NODELABEL(spi2)), DT_IRQ(DT_NODELABEL(spi2), priority), \ + spi_smartbond_isr, DEVICE_DT_GET(DT_NODELABEL(spi2)), 0); \ + irq_enable(DT_IRQN(DT_NODELABEL(spi2))); + +#if defined(CONFIG_SPI_ASYNC) || defined(CONFIG_SPI_SMARTBOND_DMA) +static int spi_smartbond_isr_connect(const struct device *dev) +{ + const struct spi_smartbond_cfg *cfg = dev->config; + + switch ((uint32_t)cfg->regs) { + case (uint32_t)SPI: + COND_CODE_1(DT_NODE_HAS_STATUS(DT_NODELABEL(spi), okay), + (SPI_SMARTBOND_ISR_CONNECT), (NULL)); + break; + case (uint32_t)SPI2: + COND_CODE_1(DT_NODE_HAS_STATUS(DT_NODELABEL(spi2), okay), + (SPI2_SMARTBOND_ISR_CONNECT), (NULL)); + break; + default: + return -EINVAL; + } + + return 0; +} +#endif + static int spi_smartbond_init(const struct device *dev) { int ret; struct spi_smartbond_data *data = dev->data; +#if defined(CONFIG_SPI_ASYNC) || defined(CONFIG_SPI_SMARTBOND_DMA) + data->transfer_mode = SPI_SMARTBOND_TRANSFER_NONE; +#endif +#ifdef CONFIG_SPI_SMARTBOND_DMA + k_sem_init(&data->tx_dma_sync, 0, 1); + k_sem_init(&data->rx_dma_sync, 0, 1); +#endif + #ifdef CONFIG_PM_DEVICE_RUNTIME /* Make sure device state is marked as suspended */ pm_device_init_suspended(dev); @@ -373,15 +1265,61 @@ static int spi_smartbond_init(const struct device *dev) #endif spi_context_unlock_unconditionally(&data->ctx); +#if defined(CONFIG_SPI_ASYNC) || defined(CONFIG_SPI_SMARTBOND_DMA) + ret = spi_smartbond_isr_connect(dev); +#endif + return ret; } +#ifdef CONFIG_SPI_SMARTBOND_DMA +#define SPI_SMARTBOND_DMA_TX_INIT(id) \ + .tx_dma_chan = DT_INST_DMAS_CELL_BY_NAME(id, tx, channel), \ + .tx_slot_mux = (uint8_t)DT_INST_DMAS_CELL_BY_NAME(id, tx, config), \ + .tx_dma_ctrl = DEVICE_DT_GET(DT_INST_DMAS_CTLR_BY_NAME(id, tx)), +#else +#define SPI_SMARTBOND_DMA_TX_INIT(id) +#endif + +#ifdef CONFIG_SPI_SMARTBOND_DMA +#define SPI_SMARTBOND_DMA_RX_INIT(id) \ + .rx_dma_chan = DT_INST_DMAS_CELL_BY_NAME(id, rx, channel), \ + .rx_slot_mux = (uint8_t)DT_INST_DMAS_CELL_BY_NAME(id, rx, config), \ + .rx_dma_ctrl = DEVICE_DT_GET(DT_INST_DMAS_CTLR_BY_NAME(id, rx)), +#else +#define SPI_SMARTBOND_DMA_RX_INIT(id) +#endif + +#ifdef CONFIG_SPI_SMARTBOND_DMA +#define SPI_SMARTBOND_DMA_TX_INVALIDATE(id) \ + .tx_dma_chan = 255, \ + .tx_slot_mux = 255, \ + .tx_dma_ctrl = NULL, +#else +#define SPI_SMARTBOND_DMA_TX_INVALIDATE(id) +#endif + +#ifdef CONFIG_SPI_SMARTBOND_DMA +#define SPI_SMARTBOND_DMA_RX_INVALIDATE(id) \ + .rx_dma_chan = 255, \ + .rx_slot_mux = 255, \ + .rx_dma_ctrl = NULL, +#else +#define SPI_SMARTBOND_DMA_RX_INVALIDATE(id) +#endif + #define SPI_SMARTBOND_DEVICE(id) \ PINCTRL_DT_INST_DEFINE(id); \ static const struct spi_smartbond_cfg spi_smartbond_##id##_cfg = { \ .regs = (SPI_Type *)DT_INST_REG_ADDR(id), \ .periph_clock_config = DT_INST_PROP(id, periph_clock_config), \ .pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(id), \ + COND_CODE_1(DT_INST_DMAS_HAS_NAME(id, tx), \ + (SPI_SMARTBOND_DMA_TX_INIT(id)), \ + (SPI_SMARTBOND_DMA_TX_INVALIDATE(id))) \ + COND_CODE_1(DT_INST_DMAS_HAS_NAME(id, rx), \ + (SPI_SMARTBOND_DMA_RX_INIT(id)), \ + (SPI_SMARTBOND_DMA_RX_INVALIDATE(id))) \ }; \ static struct spi_smartbond_data spi_smartbond_##id##_data = { \ SPI_CONTEXT_INIT_LOCK(spi_smartbond_##id##_data, ctx), \ From 406764aec681ff58f3293bf24a1b9f08e0f590ae Mon Sep 17 00:00:00 2001 From: Sadik Ozer Date: Wed, 10 Jan 2024 13:28:53 +0300 Subject: [PATCH 2646/2849] soc: Add the MAX32672 SoC Add MAX32672 Kconfig and dts files Co-authored-by: Maureen Helm Signed-off-by: Sadik Ozer --- dts/arm/adi/max32/max32672-pinctrl.dtsi | 522 +++++++++++++++++++++++ dts/arm/adi/max32/max32672.dtsi | 83 ++++ soc/adi/max32/Kconfig | 3 + soc/adi/max32/Kconfig.defconfig.max32672 | 14 + soc/adi/max32/Kconfig.soc | 5 + soc/adi/max32/soc.yml | 1 + 6 files changed, 628 insertions(+) create mode 100644 dts/arm/adi/max32/max32672-pinctrl.dtsi create mode 100644 dts/arm/adi/max32/max32672.dtsi create mode 100644 soc/adi/max32/Kconfig.defconfig.max32672 diff --git a/dts/arm/adi/max32/max32672-pinctrl.dtsi b/dts/arm/adi/max32/max32672-pinctrl.dtsi new file mode 100644 index 0000000000000..bbc737cc4d3cd --- /dev/null +++ b/dts/arm/adi/max32/max32672-pinctrl.dtsi @@ -0,0 +1,522 @@ +/* + * Copyright (c) 2024 Analog Devices, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +/ { + soc { + pinctrl: pin-controller@40008000 { + + /omit-if-no-ref/ swdio_p0_0: swdio_p0_0 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr0c_ia_p0_0: tmr0c_ia_p0_0 { + pinmux = ; + }; + + /omit-if-no-ref/ swdclk_p0_1: swdclk_p0_1 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr0c_oa_p0_1: tmr0c_oa_p0_1 { + pinmux = ; + }; + + /omit-if-no-ref/ spi0a_miso_p0_2: spi0a_miso_p0_2 { + pinmux = ; + }; + + /omit-if-no-ref/ uart1b_rx_p0_2: uart1b_rx_p0_2 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr1c_ia_p0_2: tmr1c_ia_p0_2 { + pinmux = ; + }; + + /omit-if-no-ref/ spi0a_mosi_p0_3: spi0a_mosi_p0_3 { + pinmux = ; + }; + + /omit-if-no-ref/ uart1b_tx_p0_3: uart1b_tx_p0_3 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr1c_oa_p0_3: tmr1c_oa_p0_3 { + pinmux = ; + }; + + /omit-if-no-ref/ spi0a_sck_p0_4: spi0a_sck_p0_4 { + pinmux = ; + }; + + /omit-if-no-ref/ uart1b_cts_p0_4: uart1b_cts_p0_4 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr2c_ia_p0_4: tmr2c_ia_p0_4 { + pinmux = ; + }; + + /omit-if-no-ref/ spi0a_ss0_p0_5: spi0a_ss0_p0_5 { + pinmux = ; + }; + + /omit-if-no-ref/ uart1b_rts_p0_5: uart1b_rts_p0_5 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr2c_oa_p0_5: tmr2c_oa_p0_5 { + pinmux = ; + }; + + /omit-if-no-ref/ hfx_clk_out_p0_5: hfx_clk_out_p0_5 { + pinmux = ; + }; + + /omit-if-no-ref/ i2c0a_scl_p0_6: i2c0a_scl_p0_6 { + pinmux = ; + }; + + /omit-if-no-ref/ lptmr0b_ia_p0_6: lptmr0b_ia_p0_6 { + pinmux = ; + }; + + /omit-if-no-ref/ spi0c_ss1_p0_6: spi0c_ss1_p0_6 { + pinmux = ; + }; + + /omit-if-no-ref/ qea_p0_6: qea_p0_6 { + pinmux = ; + }; + + /omit-if-no-ref/ i2c0a_sda_p0_7: i2c0a_sda_p0_7 { + pinmux = ; + }; + + /omit-if-no-ref/ lptmr0b_oa_p0_7: lptmr0b_oa_p0_7 { + pinmux = ; + }; + + /omit-if-no-ref/ spi0c_ss2_p0_7: spi0c_ss2_p0_7 { + pinmux = ; + }; + + /omit-if-no-ref/ qeb_p0_7: qeb_p0_7 { + pinmux = ; + }; + + /omit-if-no-ref/ uart0a_rx_p0_8: uart0a_rx_p0_8 { + pinmux = ; + }; + + /omit-if-no-ref/ i2s0a_sdo_p0_8: i2s0a_sdo_p0_8 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr0c_ia_p0_8: tmr0c_ia_p0_8 { + pinmux = ; + }; + + /omit-if-no-ref/ ain0_p0_8: ain0_p0_8 { + pinmux = ; + }; + + /omit-if-no-ref/ uart0a_tx_p0_9: uart0a_tx_p0_9 { + pinmux = ; + }; + + /omit-if-no-ref/ i2s0a_lrclk_p0_9: i2s0a_lrclk_p0_9 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr0c_oa_p0_9: tmr0c_oa_p0_9 { + pinmux = ; + }; + + /omit-if-no-ref/ ain_c0_n_p0_9: ain_c0_n_p0_9 { + pinmux = ; + }; + + /omit-if-no-ref/ uart0a_cts_p0_10: uart0a_cts_p0_10 { + pinmux = ; + }; + + /omit-if-no-ref/ i2s0a_bcllk_p0_10: i2s0a_bcllk_p0_10 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr1c_ia_p0_10: tmr1c_ia_p0_10 { + pinmux = ; + }; + + /omit-if-no-ref/ ain_c0_n_p0_10: ain_c0_n_p0_10 { + pinmux = ; + }; + + /omit-if-no-ref/ uart0a_rts_p0_11: uart0a_rts_p0_11 { + pinmux = ; + }; + + /omit-if-no-ref/ i2s0a_sdi_p0_11: i2s0a_sdi_p0_11 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr1c_oa_p0_11: tmr1c_oa_p0_11 { + pinmux = ; + }; + + /omit-if-no-ref/ ain_c0_n_p0_11: ain_c0_n_p0_11 { + pinmux = ; + }; + + /omit-if-no-ref/ i2c1a_scl_p0_12: i2c1a_scl_p0_12 { + pinmux = ; + }; + + /omit-if-no-ref/ ext_clk2_p0_12: ext_clk2_p0_12 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr2c_ia_p0_12: tmr2c_ia_p0_12 { + pinmux = ; + }; + + /omit-if-no-ref/ ain_c0_p_p0_12: ain_c0_p_p0_12 { + pinmux = ; + }; + + /omit-if-no-ref/ i2c1a_sda_p0_13: i2c1a_sda_p0_13 { + pinmux = ; + }; + + /omit-if-no-ref/ cal32k_p0_13: cal32k_p0_13 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr2c_oa_p0_13: tmr2c_oa_p0_13 { + pinmux = ; + }; + + /omit-if-no-ref/ ain_c0_p_p0_13: ain_c0_p_p0_13 { + pinmux = ; + }; + + /omit-if-no-ref/ spi1a_miso_p0_14: spi1a_miso_p0_14 { + pinmux = ; + }; + + /omit-if-no-ref/ uart2b_rx_p0_14: uart2b_rx_p0_14 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr3c_ia_p0_14: tmr3c_ia_p0_14 { + pinmux = ; + }; + + /omit-if-no-ref/ ain_c0_p_p0_14: ain_c0_p_p0_14 { + pinmux = ; + }; + + /omit-if-no-ref/ spi1a_mosi_p0_15: spi1a_mosi_p0_15 { + pinmux = ; + }; + + /omit-if-no-ref/ uart2b_tx_p0_15: uart2b_tx_p0_15 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr3c_oa_p0_15: tmr3c_oa_p0_15 { + pinmux = ; + }; + + /omit-if-no-ref/ ain_c0_p_p0_15: ain_c0_p_p0_15 { + pinmux = ; + }; + + /omit-if-no-ref/ spi1a_sck_p0_16: spi1a_sck_p0_16 { + pinmux = ; + }; + + /omit-if-no-ref/ uart2b_cts_p0_16: uart2b_cts_p0_16 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr0c_ia_p0_16: tmr0c_ia_p0_16 { + pinmux = ; + }; + + /omit-if-no-ref/ ain8_p0_16: ain8_p0_16 { + pinmux = ; + }; + + /omit-if-no-ref/ spi1a_ss0_p0_17: spi1a_ss0_p0_17 { + pinmux = ; + }; + + /omit-if-no-ref/ uart2b_rts_p0_17: uart2b_rts_p0_17 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr0c_oa_p0_17: tmr0c_oa_p0_17 { + pinmux = ; + }; + + /omit-if-no-ref/ ain9_p0_17: ain9_p0_17 { + pinmux = ; + }; + + /omit-if-no-ref/ i2c2a_scl_p0_18: i2c2a_scl_p0_18 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr1c_ia_p0_18: tmr1c_ia_p0_18 { + pinmux = ; + }; + + /omit-if-no-ref/ ain10_p0_18: ain10_p0_18 { + pinmux = ; + }; + + /omit-if-no-ref/ i2c2a_sda_p0_19: i2c2a_sda_p0_19 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr1c_oa_p0_19: tmr1c_oa_p0_19 { + pinmux = ; + }; + + /omit-if-no-ref/ ain11_p0_19: ain11_p0_19 { + pinmux = ; + }; + + /omit-if-no-ref/ cm4_rx_p0_20: cm4_rx_p0_20 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr2c_ia_p0_20: tmr2c_ia_p0_20 { + pinmux = ; + }; + + /omit-if-no-ref/ cm4_tx_p0_21: cm4_tx_p0_21 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr2c_oa_p0_21: tmr2c_oa_p0_21 { + pinmux = ; + }; + + /omit-if-no-ref/ lptmr1a_ia_p0_22: lptmr1a_ia_p0_22 { + pinmux = ; + }; + + /omit-if-no-ref/ adc_trig_b_p0_22: adc_trig_b_p0_22 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr0c_ia_p0_22: tmr0c_ia_p0_22 { + pinmux = ; + }; + + /omit-if-no-ref/ lptmr1a_oa_p0_23: lptmr1a_oa_p0_23 { + pinmux = ; + }; + + /omit-if-no-ref/ spi0c_ss3_p0_23: spi0c_ss3_p0_23 { + pinmux = ; + }; + + /omit-if-no-ref/ qei_p0_23: qei_p0_23 { + pinmux = ; + }; + + /omit-if-no-ref/ lpuart0a_cts_p0_24: lpuart0a_cts_p0_24 { + pinmux = ; + }; + + /omit-if-no-ref/ uart0b_rx_p0_24: uart0b_rx_p0_24 { + pinmux = ; + }; + + /omit-if-no-ref/ i2s0a_sd0_p0_24: i2s0a_sd0_p0_24 { + pinmux = ; + }; + + /omit-if-no-ref/ qes_p0_24: qes_p0_24 { + pinmux = ; + }; + + /omit-if-no-ref/ lpuart0a_rts_p0_25: lpuart0a_rts_p0_25 { + pinmux = ; + }; + + /omit-if-no-ref/ uart0b_tx_p0_25: uart0b_tx_p0_25 { + pinmux = ; + }; + + /omit-if-no-ref/ i2s0a_lrclk_p0_25: i2s0a_lrclk_p0_25 { + pinmux = ; + }; + + /omit-if-no-ref/ qmatch_p0_25: qmatch_p0_25 { + pinmux = ; + }; + + /omit-if-no-ref/ lpuart0a_rx_p0_26: lpuart0a_rx_p0_26 { + pinmux = ; + }; + + /omit-if-no-ref/ uart0b_cts_p0_26: uart0b_cts_p0_26 { + pinmux = ; + }; + + /omit-if-no-ref/ i2s0c_bclk_p0_26: i2s0c_bclk_p0_26 { + pinmux = ; + }; + + /omit-if-no-ref/ qdir_p0_26: qdir_p0_26 { + pinmux = ; + }; + + /omit-if-no-ref/ lpuart0a_tx_p0_27: lpuart0a_tx_p0_27 { + pinmux = ; + }; + + /omit-if-no-ref/ uart0b_rts_p0_27: uart0b_rts_p0_27 { + pinmux = ; + }; + + /omit-if-no-ref/ i2s0c_sdi_p0_27: i2s0c_sdi_p0_27 { + pinmux = ; + }; + + /omit-if-no-ref/ qerr_p0_27: qerr_p0_27 { + pinmux = ; + }; + + /omit-if-no-ref/ uart1a_rx_p0_28: uart1a_rx_p0_28 { + pinmux = ; + }; + + /omit-if-no-ref/ ext_clk1_p0_28: ext_clk1_p0_28 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr3c_ia_p0_28: tmr3c_ia_p0_28 { + pinmux = ; + }; + + /omit-if-no-ref/ uart1a_tx_p0_29: uart1a_tx_p0_29 { + pinmux = ; + }; + + /omit-if-no-ref/ spi1_ss0_p0_29: spi1_ss0_p0_29 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr3c_oa_p0_29: tmr3c_oa_p0_29 { + pinmux = ; + }; + + /omit-if-no-ref/ adc_trig_d_p0_29: adc_trig_d_p0_29 { + pinmux = ; + }; + + /omit-if-no-ref/ uart1a_cts_p0_30: uart1a_cts_p0_30 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr3c_ia_p0_30: tmr3c_ia_p0_30 { + pinmux = ; + }; + + /omit-if-no-ref/ uart1a_rts_p0_31: uart1a_rts_p0_31 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr3c_oa_p0_31: tmr3c_oa_p0_31 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr1c_ia_p1_0: tmr1c_ia_p1_0 { + pinmux = ; + }; + + /omit-if-no-ref/ spi2a_miso_p1_1: spi2a_miso_p1_1 { + pinmux = ; + }; + + /omit-if-no-ref/ uart0b_rx_p1_1: uart0b_rx_p1_1 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr3c_oa_p1_1: tmr3c_oa_p1_1 { + pinmux = ; + }; + + /omit-if-no-ref/ spi2a_mosi_p1_2: spi2a_mosi_p1_2 { + pinmux = ; + }; + + /omit-if-no-ref/ uart0b_tx_p1_2: uart0b_tx_p1_2 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr3c_ia_p1_2: tmr3c_ia_p1_2 { + pinmux = ; + }; + + /omit-if-no-ref/ div_clk_out_p1_2: div_clk_out_p1_2 { + pinmux = ; + }; + + /omit-if-no-ref/ spi2a_sck_p1_3: spi2a_sck_p1_3 { + pinmux = ; + }; + + /omit-if-no-ref/ uart0b_cts_p1_3: uart0b_cts_p1_3 { + pinmux = ; + }; + + /omit-if-no-ref/ spi2a_ss0_p1_4: spi2a_ss0_p1_4 { + pinmux = ; + }; + + /omit-if-no-ref/ uart0b_rts_p1_4: uart0b_rts_p1_4 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr0c_oa_p1_4: tmr0c_oa_p1_4 { + pinmux = ; + }; + + /omit-if-no-ref/ adc_trig_d_p1_4: adc_trig_d_p1_4 { + pinmux = ; + }; + + /omit-if-no-ref/ uart2a_rx_p1_5: uart2a_rx_p1_5 { + pinmux = ; + }; + + /omit-if-no-ref/ uart2a_tx_p1_6: uart2a_tx_p1_6 { + pinmux = ; + }; + + /omit-if-no-ref/ uart2a_cts_p1_7: uart2a_cts_p1_7 { + pinmux = ; + }; + + /omit-if-no-ref/ uart2a_rts_p1_8: uart2a_rts_p1_8 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr1c_oa_p1_9: tmr1c_oa_p1_9 { + pinmux = ; + }; + }; + }; +}; diff --git a/dts/arm/adi/max32/max32672.dtsi b/dts/arm/adi/max32/max32672.dtsi new file mode 100644 index 0000000000000..0845075cccaa8 --- /dev/null +++ b/dts/arm/adi/max32/max32672.dtsi @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2024 Analog Devices, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +&sram0 { + reg = <0x20000000 DT_SIZE_K(16)>; +}; + +&clk_inro { + clock-frequency = ; +}; + +/delete-node/ &clk_iso; + +/* MAX32672 extra peripherals. */ +/ { + soc { + sram1: memory@20004000 { + compatible = "mmio-sram"; + reg = <0x20004000 DT_SIZE_K(16)>; + }; + + sram2: memory@20008000 { + compatible = "mmio-sram"; + reg = <0x20008000 DT_SIZE_K(64)>; + }; + + sram3: memory@20018000 { + compatible = "mmio-sram"; + reg = <0x20018000 DT_SIZE_K(64)>; + }; + + sram4: memory@20028000 { + compatible = "mmio-sram"; + reg = <0x20028000 DT_SIZE_K(4)>; + }; + + sram5: memory@20029000 { + compatible = "mmio-sram"; + reg = <0x20029000 DT_SIZE_K(4)>; + }; + + sram6: memory@2002a000 { + compatible = "mmio-sram"; + reg = <0x2002a000 DT_SIZE_K(16)>; + }; + + sram7: memory@2002e000 { + compatible = "mmio-sram"; + reg = <0x2002e000 DT_SIZE_K(16)>; + }; + + flc1: flash_controller@40029400 { + compatible = "adi,max32-flash-controller"; + reg = <0x40029400 0x400>; + + #address-cells = <1>; + #size-cells = <1>; + status = "okay"; + + flash1: flash@10080000 { + compatible = "soc-nv-flash"; + reg = <0x10080000 DT_SIZE_K(512)>; + write-block-size = <16>; + erase-block-size = <8192>; + }; + }; + + uart3: serial@40145000 { + compatible = "adi,max32-uart"; + reg = <0x40145000 0x1000>; + clocks = <&gcr ADI_MAX32_CLOCK_BUS2 2>; + clock-source = ; + interrupts = <88 0>; + status = "disabled"; + }; + }; +}; diff --git a/soc/adi/max32/Kconfig b/soc/adi/max32/Kconfig index 9eb62daf6c38c..7bfc9cff192d9 100644 --- a/soc/adi/max32/Kconfig +++ b/soc/adi/max32/Kconfig @@ -14,6 +14,9 @@ config SOC_FAMILY_MAX32 config SOC_MAX32655 select CPU_CORTEX_M4 +config SOC_MAX32672 + select CPU_CORTEX_M4 + config SOC_MAX32680 select CPU_CORTEX_M4 diff --git a/soc/adi/max32/Kconfig.defconfig.max32672 b/soc/adi/max32/Kconfig.defconfig.max32672 new file mode 100644 index 0000000000000..2a7e1aad1c5df --- /dev/null +++ b/soc/adi/max32/Kconfig.defconfig.max32672 @@ -0,0 +1,14 @@ +# Analog Devices MAX32672 MCU + +# Copyright (c) 2024 Analog Devices, Inc. +# SPDX-License-Identifier: Apache-2.0 + +if SOC_MAX32672 + +config SYS_CLOCK_HW_CYCLES_PER_SEC + default $(dt_node_int_prop_int,/clocks/clk_ipo,clock-frequency) + +config NUM_IRQS + default 108 + +endif # SOC_MAX32672 diff --git a/soc/adi/max32/Kconfig.soc b/soc/adi/max32/Kconfig.soc index 5d7baca5582fe..53a4548fcaaf7 100644 --- a/soc/adi/max32/Kconfig.soc +++ b/soc/adi/max32/Kconfig.soc @@ -17,6 +17,10 @@ config SOC_MAX32655_M4 bool select SOC_MAX32655 +config SOC_MAX32672 + bool + select SOC_FAMILY_MAX32 + config SOC_MAX32680 bool select SOC_FAMILY_MAX32 @@ -35,5 +39,6 @@ config SOC_MAX32690_M4 config SOC default "max32655" if SOC_MAX32655 + default "max32672" if SOC_MAX32672 default "max32680" if SOC_MAX32680 default "max32690" if SOC_MAX32690 diff --git a/soc/adi/max32/soc.yml b/soc/adi/max32/soc.yml index 5b2c70d086f97..dd6f42d686087 100644 --- a/soc/adi/max32/soc.yml +++ b/soc/adi/max32/soc.yml @@ -7,6 +7,7 @@ family: - name: max32655 cpuclusters: - name: m4 + - name: max32672 - name: max32680 cpuclusters: - name: m4 From 16dda2c09292e5e31fba4227356025386d3e0be3 Mon Sep 17 00:00:00 2001 From: Sadik Ozer Date: Wed, 10 Jan 2024 16:59:52 +0300 Subject: [PATCH 2647/2849] boards: Add MAX32672FTHR board Added MAX32672FTHR board For more information about this board please check https://www.analog.com/ Co-authored-by: Maureen Helm Signed-off-by: Sadik Ozer --- boards/adi/max32672fthr/Kconfig.max32672fthr | 7 + boards/adi/max32672fthr/board.cmake | 7 + boards/adi/max32672fthr/board.yml | 8 + .../doc/img/max32672fthr_img1.webp | Bin 0 -> 61086 bytes .../doc/img/max32672fthr_img2.webp | Bin 0 -> 31224 bytes boards/adi/max32672fthr/doc/index.rst | 206 ++++++++++++++++++ boards/adi/max32672fthr/max32672fthr.dts | 107 +++++++++ boards/adi/max32672fthr/max32672fthr.yaml | 13 ++ .../adi/max32672fthr/max32672fthr_defconfig | 13 ++ 9 files changed, 361 insertions(+) create mode 100644 boards/adi/max32672fthr/Kconfig.max32672fthr create mode 100644 boards/adi/max32672fthr/board.cmake create mode 100644 boards/adi/max32672fthr/board.yml create mode 100644 boards/adi/max32672fthr/doc/img/max32672fthr_img1.webp create mode 100644 boards/adi/max32672fthr/doc/img/max32672fthr_img2.webp create mode 100644 boards/adi/max32672fthr/doc/index.rst create mode 100644 boards/adi/max32672fthr/max32672fthr.dts create mode 100644 boards/adi/max32672fthr/max32672fthr.yaml create mode 100644 boards/adi/max32672fthr/max32672fthr_defconfig diff --git a/boards/adi/max32672fthr/Kconfig.max32672fthr b/boards/adi/max32672fthr/Kconfig.max32672fthr new file mode 100644 index 0000000000000..71f33f5214a05 --- /dev/null +++ b/boards/adi/max32672fthr/Kconfig.max32672fthr @@ -0,0 +1,7 @@ +# MAX32672FTHR boards configuration + +# Copyright (c) 2024 Analog Devices, Inc. +# SPDX-License-Identifier: Apache-2.0 + +config BOARD_MAX32672FTHR + select SOC_MAX32672 diff --git a/boards/adi/max32672fthr/board.cmake b/boards/adi/max32672fthr/board.cmake new file mode 100644 index 0000000000000..815111de6b74e --- /dev/null +++ b/boards/adi/max32672fthr/board.cmake @@ -0,0 +1,7 @@ +# Copyright (c) 2024 Analog Devices, Inc. +# SPDX-License-Identifier: Apache-2.0 + +board_runner_args(openocd --cmd-pre-init "source [find interface/cmsis-dap.cfg]") +board_runner_args(openocd --cmd-pre-init "source [find target/max32672.cfg]") + +include(${ZEPHYR_BASE}/boards/common/openocd.board.cmake) diff --git a/boards/adi/max32672fthr/board.yml b/boards/adi/max32672fthr/board.yml new file mode 100644 index 0000000000000..c99d16ad4a1f3 --- /dev/null +++ b/boards/adi/max32672fthr/board.yml @@ -0,0 +1,8 @@ +# Copyright (c) 2024 Analog Devices, Inc. +# SPDX-License-Identifier: Apache-2.0 + +board: + name: max32672fthr + vendor: adi + socs: + - name: max32672 diff --git a/boards/adi/max32672fthr/doc/img/max32672fthr_img1.webp b/boards/adi/max32672fthr/doc/img/max32672fthr_img1.webp new file mode 100644 index 0000000000000000000000000000000000000000..9f0e49b247b67407b6bb4ba51e0f33d89aac72aa GIT binary patch literal 61086 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

jU_>`PztNNy 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�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%0D;N_2R`;bHEU`JqSW52ffit0&b4N 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 I000000RLGqqW}N^ literal 0 HcmV?d00001 diff --git a/boards/adi/max32672fthr/doc/index.rst b/boards/adi/max32672fthr/doc/index.rst new file mode 100644 index 0000000000000..6656657881480 --- /dev/null +++ b/boards/adi/max32672fthr/doc/index.rst @@ -0,0 +1,206 @@ +.. _max32672_fthr: + +MAX32672FTHR +############ + +Overview +******** +The MAX32672FTHR is a rapid development platform that helps engineers quickly implement complex +sensor solutions using the MAX32672 Arm® Cortex®-M4. The board also includes the MAX8819 PMIC for +battery and power management. The form factor is a small, 0.9in by 2.6in, dual row header footprint +that is compatible with Adafruit® FeatherWing peripheral expansion boards. The board includes +an OLED display, a RGB indicator LED, and a user pushbutton. The MAX32672FTHR provides +a power-optimized flexible platform for quick proof-ofconcepts and early software development +to enhance time to market. + +The Zephyr port is running on the MAX32672 MCU. + +.. image:: img/max32672fthr_img1.webp + :align: center + :alt: MAX32672FTHR Front + +.. image:: img/max32672fthr_img2.webp + :align: center + :alt: MAX32672FTHR Back + +Hardware +******** + +- MAX32672 MCU: + + - High-Efficiency Microcontroller for Low-Power High-Reliability Devices + + - Arm Cortex-M4 Processor with FPU up to 100MHz + - 1MB Dual-Bank Flash with Error Correction + - 200KB SRAM (160KB with ECC Enabled), Optionally Preserved in Lowest Power Modes + - EEPROM Emulation on Flash + - 16KB Unified Cache with ECC + - Resource Protection Unit (RPU) and MemoryProtection Unit (MPU) + - Dual- or Single-Supply Operation, 1.7V to 3.6V + - Wide Operating Temperature: -40°C to +105°C + + - Flexible Clocking Schemes + + - Internal High-Speed 100MHz Oscillator + - Internal Low-Power 7.3728MHz and Ultra-Low-Power 80kHz Oscillators + - 16MHz–32MHz Oscillator, 32.768kHz Oscillator(External Crystal Required) + - External Clock Input for CPU, LPUART, LPTMR + + - Power Management Maximizes Uptime for Battery Applications + + - 59.8μA/MHz ACTIVE at 0.9V up to 12MHz(CoreMark®) + - 56.6μA/MHz ACTIVE at 1.1V up to 100MHz(While(1)) + - 3.09μA Full Memory Retention Power in BACKUPMode at VDD = 1.8V + - 350nA Ultra-Low-Power RTC at + - Wake from LPUART or LPTMR + + - Optimal Peripheral Mix Provides Platform Scalability + + - Up to 42 General-Purpose I/O Pins + - Up to Three SPI Master/Slave (up to 50Mbps) + - Up to Three 4-Wire UART + - Up to Three I2C Master/Slave 3.4Mbps High Speed + - Up to Four 32-Bit Timers (TMR) + - Up to Two Low-Power 32-Bit Timers (LPTMR) + - One I2S Master/Slave for Digital Audio Interface + - 12-Channel, 12-Bit, 1Msps SAR ADC with On-DieTemperature Sensor + + - Security and Integrity + + - Optional ECDSA-Based Cryptographic SecureBootloader in ROM + - Secure Cryptographic Accelerator for Elliptic Curve + - AES-128/192/256 Hardware Acceleration Engine + +- Benefits and Features of MAX32672FTHR: + + - MAX8819 PMIC with Integrated Charger + - On-Board DAPLink Debug and Programming Interface for Arm Cortex-M4 + - Breadboard-Compatible Headers + - Micro USB Connector + - RGB Indicator LED + - User Pushbutton + - OLED Display + - SWD Debugger + - Virtual UART Console + +Supported Features +================== + +Below interfaces are supported by Zephyr on MAX32672FTHR. + ++-----------+------------+-------------------------------------+ +| Interface | Controller | Driver/Component | ++===========+============+=====================================+ +| NVIC | on-chip | nested vector interrupt controller | ++-----------+------------+-------------------------------------+ +| SYSTICK | on-chip | systick | ++-----------+------------+-------------------------------------+ +| CLOCK | on-chip | clock and reset control | ++-----------+------------+-------------------------------------+ +| GPIO | on-chip | gpio | ++-----------+------------+-------------------------------------+ +| UART | on-chip | serial | ++-----------+------------+-------------------------------------+ + + +Connections and IOs +=================== + +J9 Pinout +********** + ++---------+----------+-------------------------------------------------------------------------------------------------+ +| Pin | Name | Description | ++=========+==========+=================================================================================================+ +| 1 | RST | Master Reset Signal | ++---------+----------+-------------------------------------------------------------------------------------------------+ +| 2 | 3V3 | 3.3V Output. Typically used to provide 3.3V to peripherals connected to the expansion headers. | ++---------+----------+-------------------------------------------------------------------------------------------------+ +| 3 | 1V8 | 1.8V Output. Typically used to provide 1.8V to peripherals connected to the expansion headers. | ++---------+----------+-------------------------------------------------------------------------------------------------+ +| 4 | GND | Ground | ++---------+----------+-------------------------------------------------------------------------------------------------+ +| 5 | P0_11 | GPIO or Analog Input (AIN3 channel). | ++---------+----------+-------------------------------------------------------------------------------------------------+ +| 6 | P0_12 | GPIO or Analog Input (AIN4 channel). | ++---------+----------+-------------------------------------------------------------------------------------------------+ +| 7 | P0_13 | GPIO or Analog Input (AIN5 channel). | ++---------+----------+-------------------------------------------------------------------------------------------------+ +| 8 | P0_22 | GPIO or ADC_TRIG signal. | ++---------+----------+-------------------------------------------------------------------------------------------------+ +| 9 | P0_27 | GPIO or QERR signal. | ++---------+----------+-------------------------------------------------------------------------------------------------+ +| 10 | P0_26 | GPIO or QDIR signal. | ++---------+----------+-------------------------------------------------------------------------------------------------+ +| 11 | P0_16 | GPIO or SPI1 clock signal. | ++---------+----------+-------------------------------------------------------------------------------------------------+ +| 12 | P0_15 | GPIO or SPI1 MOSI signal. | ++---------+----------+-------------------------------------------------------------------------------------------------+ +| 13 | P0_14 | GPIO or SPI1 MISO signal. | ++---------+----------+-------------------------------------------------------------------------------------------------+ +| 14 | P0_28 | GPIO or UART1 Rx signal. | ++---------+----------+-------------------------------------------------------------------------------------------------+ +| 15 | P0_29 | GPIO or UART1 Tx signal. | ++---------+----------+-------------------------------------------------------------------------------------------------+ +| 16 | GND | Ground | ++---------+----------+-------------------------------------------------------------------------------------------------+ + + +J7 Pinout +********** + ++---------+----------+-----------------------------------------------------------------------------------------------------------+ +| Pin | Name | Description | ++=========+==========+===========================================================================================================+ +| 1 | SYS | SYS Switched Connection to the Battery. This is the primary system power supply and automatically | +| | | switches between the battery voltage and the USB supply when available. | ++---------+----------+-----------------------------------------------------------------------------------------------------------+ +| 2 | PWR | In battery-powered mode, turns off the PMIC if shorted to ground. | ++---------+----------+-----------------------------------------------------------------------------------------------------------+ +| 3 | VBUS | USB VBUS Signal. This can be used as a 5V supply when connected to USB. This pin can also be | +| | | used as an input to power the board. | ++---------+----------+-----------------------------------------------------------------------------------------------------------+ +| 4 | P0_5 | GPIO or HFX_CLK_OUT signal. | ++---------+----------+-----------------------------------------------------------------------------------------------------------+ +| 5 | P0_6 | GPIO or QEA signal. | ++---------+----------+-----------------------------------------------------------------------------------------------------------+ +| 6 | P0_7 | GPIO or QEB signal. | ++---------+----------+-----------------------------------------------------------------------------------------------------------+ +| 7 | P0_23 | GPIO or QEI signal. | ++---------+----------+-----------------------------------------------------------------------------------------------------------+ +| 8 | P0_17 | GPIO or SPI1 slave select signal. | ++---------+----------+-----------------------------------------------------------------------------------------------------------+ +| 9 | P0_24 | GPIO or QES signal. | ++---------+----------+-----------------------------------------------------------------------------------------------------------+ +| 10 | P0_25 | GPIO or QMATCH signal. | ++---------+----------+-----------------------------------------------------------------------------------------------------------+ +| 11 | P0_18 | GPIO or I2C2 SCL signal. | ++---------+----------+-----------------------------------------------------------------------------------------------------------+ +| 12 | P0_19 | GPIO or I2C2 SDA signal. | ++---------+----------+-----------------------------------------------------------------------------------------------------------+ + +Programming and Debugging +************************* + +Flashing +======== + +The MAX32625 microcontroller on the board is flashed with DAPLink firmware at the factory. +It allows debugging and flashing the MAX32672 Arm Core over USB. + +Once the debug probe is connected to your host computer, then you can simply run the +``west flash`` command to write a firmware image into flash. + +Debugging +========= + +Please refer to the `Flashing`_ section and run the ``west debug`` command +instead of ``west flash``. + +References +********** + +- `MAX32672FTHR web page`_ + +.. _MAX32672FTHR web page: + https://www.analog.com/en/design-center/evaluation-hardware-and-software/evaluation-boards-kits/max32672fthr.html diff --git a/boards/adi/max32672fthr/max32672fthr.dts b/boards/adi/max32672fthr/max32672fthr.dts new file mode 100644 index 0000000000000..963235b42a914 --- /dev/null +++ b/boards/adi/max32672fthr/max32672fthr.dts @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2024 Analog Devices, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; + +#include +#include +#include +#include + +/ { + model = "Analog Devices MAX32672FTHR"; + compatible = "adi,max32672fthr"; + + chosen { + zephyr,console = &uart0; + zephyr,shell-uart = &uart0; + zephyr,sram = &sram3; + zephyr,flash = &flash0; + }; + + leds { + compatible = "gpio-leds"; + led1: led_1 { + gpios = <&gpio0 2 GPIO_ACTIVE_LOW>; + label = "Red LED"; + }; + led2: led_2 { + gpios = <&gpio0 3 GPIO_ACTIVE_LOW>; + label = "Green LED"; + }; + led3: led_3 { + gpios = <&gpio0 4 GPIO_ACTIVE_LOW>; + label = "Blue LED"; + }; + }; + + buttons { + compatible = "gpio-keys"; + pb1: pb1 { + gpios = <&gpio0 10 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>; + label = "SW2"; + zephyr,code = ; + }; + }; + + /* These aliases are provided for compatibility with samples */ + aliases { + led0 = &led1; + led1 = &led2; + led2 = &led3; + sw0 = &pb1; + }; + + /* Used for accessing other pins */ + feather_header: feather_connector { + compatible = "adafruit-feather-header"; + #gpio-cells = <2>; + gpio-map-mask = <0xffffffff 0xffffffc0>; + gpio-map-pass-thru = <0 0x3f>; + gpio-map = <12 0 &gpio0 19 0>, /* SDA */ + <13 0 &gpio0 18 0>, /* SCL */ + <14 0 &gpio0 25 0>, /* I2S LRCLK */ + <15 0 &gpio0 24 0>, /* I2S SDO */ + <16 0 &gpio0 17 0>, /* SPI1 SS */ + <17 0 &gpio0 23 0>, /* QEI */ + <18 0 &gpio0 7 0>, /* QEB */ + <19 0 &gpio0 6 0>, /* QEA */ + <20 0 &gpio0 5 0>, /* HFX CLK OUT */ + /* 11 not connected */ + <10 0 &gpio0 29 0>, /* TX */ + <9 0 &gpio0 28 0>, /* RX */ + <8 0 &gpio0 14 0>, /* MISO */ + <7 0 &gpio0 15 0>, /* MOSI */ + <6 0 &gpio0 16 0>, /* SCK */ + <5 0 &gpio0 26 0>, /* I2S BCLK */ + <4 0 &gpio0 27 0>, /* I2S SDI */ + <3 0 &gpio0 22 0>, /* ADC_TRG */ + <2 0 &gpio0 13 0>, /* AIN5 */ + <1 0 &gpio0 12 0>, /* AIN4 */ + <0 0 &gpio0 11 0>; /* AIN3 */ + }; +}; + +&uart0 { + pinctrl-0 = <&uart0a_tx_p0_9 &uart0a_rx_p0_8>; + pinctrl-names = "default"; + current-speed = <115200>; + data-bits = <8>; + parity = "none"; + status = "okay"; +}; + +&clk_ipo { + status = "okay"; +}; + +&gpio0 { + status = "okay"; +}; + +&gpio1 { + status = "okay"; +}; diff --git a/boards/adi/max32672fthr/max32672fthr.yaml b/boards/adi/max32672fthr/max32672fthr.yaml new file mode 100644 index 0000000000000..e8272a41146b3 --- /dev/null +++ b/boards/adi/max32672fthr/max32672fthr.yaml @@ -0,0 +1,13 @@ +identifier: max32672fthr +name: max32672fthr +type: mcu +arch: arm +toolchain: + - zephyr + - gnuarmemb + - xtools +supported: + - gpio + - serial +ram: 200 +flash: 1024 diff --git a/boards/adi/max32672fthr/max32672fthr_defconfig b/boards/adi/max32672fthr/max32672fthr_defconfig new file mode 100644 index 0000000000000..a048ab2608ff0 --- /dev/null +++ b/boards/adi/max32672fthr/max32672fthr_defconfig @@ -0,0 +1,13 @@ +# Copyright (c) 2024 Analog Devices, Inc. +# SPDX-License-Identifier: Apache-2.0 + +# Enable GPIO +CONFIG_GPIO=y + +# Console +CONFIG_CONSOLE=y +CONFIG_UART_CONSOLE=y + +# Enable UART +CONFIG_SERIAL=y +CONFIG_UART_INTERRUPT_DRIVEN=y From 63009d7a721a83900df59c9c4e2486e5de7755e0 Mon Sep 17 00:00:00 2001 From: Sadik Ozer Date: Thu, 11 Jan 2024 14:19:11 +0300 Subject: [PATCH 2648/2849] boards: Add MAX32672EVKIT board Add MAX32672EVKIT board files For more information about this board please check https://www.analog.com/ Co-authored-by: Maureen Helm Signed-off-by: Sadik Ozer --- .../adi/max32672evkit/Kconfig.max32672evkit | 7 + boards/adi/max32672evkit/board.cmake | 9 + boards/adi/max32672evkit/board.yml | 8 + .../max32672evkit/doc/img/max32672evkit.webp | Bin 0 -> 50232 bytes boards/adi/max32672evkit/doc/index.rst | 341 ++++++++++++++++++ boards/adi/max32672evkit/max32672evkit.dts | 73 ++++ boards/adi/max32672evkit/max32672evkit.yaml | 13 + .../adi/max32672evkit/max32672evkit_defconfig | 13 + 8 files changed, 464 insertions(+) create mode 100644 boards/adi/max32672evkit/Kconfig.max32672evkit create mode 100644 boards/adi/max32672evkit/board.cmake create mode 100644 boards/adi/max32672evkit/board.yml create mode 100644 boards/adi/max32672evkit/doc/img/max32672evkit.webp create mode 100644 boards/adi/max32672evkit/doc/index.rst create mode 100644 boards/adi/max32672evkit/max32672evkit.dts create mode 100644 boards/adi/max32672evkit/max32672evkit.yaml create mode 100644 boards/adi/max32672evkit/max32672evkit_defconfig diff --git a/boards/adi/max32672evkit/Kconfig.max32672evkit b/boards/adi/max32672evkit/Kconfig.max32672evkit new file mode 100644 index 0000000000000..4b7207a0c90e4 --- /dev/null +++ b/boards/adi/max32672evkit/Kconfig.max32672evkit @@ -0,0 +1,7 @@ +# MAX32672EVKIT boards configuration + +# Copyright (c) 2024 Analog Devices, Inc. +# SPDX-License-Identifier: Apache-2.0 + +config BOARD_MAX32672EVKIT + select SOC_MAX32672 diff --git a/boards/adi/max32672evkit/board.cmake b/boards/adi/max32672evkit/board.cmake new file mode 100644 index 0000000000000..454ec897d2a69 --- /dev/null +++ b/boards/adi/max32672evkit/board.cmake @@ -0,0 +1,9 @@ +# Copyright (c) 2024 Analog Devices, Inc. +# SPDX-License-Identifier: Apache-2.0 + +board_runner_args(openocd --cmd-pre-init "source [find interface/cmsis-dap.cfg]") +board_runner_args(openocd --cmd-pre-init "source [find target/max32672.cfg]") +board_runner_args(jlink "--device=MAX32672" "--reset-after-load") + +include(${ZEPHYR_BASE}/boards/common/openocd.board.cmake) +include(${ZEPHYR_BASE}/boards/common/jlink.board.cmake) diff --git a/boards/adi/max32672evkit/board.yml b/boards/adi/max32672evkit/board.yml new file mode 100644 index 0000000000000..5df99f681bf3c --- /dev/null +++ b/boards/adi/max32672evkit/board.yml @@ -0,0 +1,8 @@ +# Copyright (c) 2024 Analog Devices, Inc. +# SPDX-License-Identifier: Apache-2.0 + +board: + name: max32672evkit + vendor: adi + socs: + - name: max32672 diff --git a/boards/adi/max32672evkit/doc/img/max32672evkit.webp b/boards/adi/max32672evkit/doc/img/max32672evkit.webp new file mode 100644 index 0000000000000000000000000000000000000000..9b9e2245d383237c21232a9c5ccc071241d38f77 GIT binary patch literal 50232 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

qfqPd?PhZ%YX& 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

n&&>8BAGl{5GWq^63Ell5whlf8iFzDRl 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

pA?6AI5Bz18 zW8kNBQV=yFZC30DHny;WFh!r_>nx`w5BizFfGx-l1Hpf`L=9`m{tg%39}SPZOR~Yx zMLnFRf1bbvq^jhUuRGvbr*~eG5O{D?4*Io;2INgb)qw%!A!`#Yodprqt$o3)VtoNc z(}vw#)bIv&Vh;di*hO$WQ5w#2FD5<;=`-1;N%%_^>rj>VG)J|La1Y9Rr~LJhMDfoF zh6i+JWe3^KO}Ed^s1Nh#2^OL&aFybjqAU*G?m=vmmU?QkB0Y^9??EycScuQcjkNgA zBaRq?+W-c|rtYm{aWg!xPdU0(4-z9zi?oK>*aR5+Si_t!YxzAuUsqb1MM!7BgR9Rn zw|5rJ&O(CYyCIBh_mSe4XXh^@(mV*@ACZYjkIKF1IcKHa|7;s8XtS4FuOl7@T^jS{z*8kquHYO1UFsn@{LEsJNAkr3Gnw{wdo`*zQtA=K+t;D&4Fbw##DgDu%y%{ zhW>1RCJj2nzU-fwr1r9YDziO(WLQ<^@jzZD6uaA^N2wzMVY&$#c3m1o@HrEA?V6)A zHr)_-MM2ccTEhye)pIv;Zve%@q1K~25_1{Gskka4?f=o5@p}KTW1Yj*N_|_r8M)pd z+eiaMlV-i9jeZXi!LrF*5OHbHa}71oS4Fu>hG$8m4hmLS`>?JwTt%$;a38}(JPD?2 zn;}giSD%iz_%rl4{pDW`GkI~)H5R;8JU%sD2S>ZJ)|zDWF3!lQUggET$W~{W;)Pi+0i#pdJB%oqfiNU= z&&{cm6_r4p#?74$kOV~ut0{P9x1=Wfw6 zpq3E0G{vV0)zhOdfkxZ7;~)1>Wius_K-ph#zj<1Sw|%#BWS*(l(~)pX^U9t9>Y66JhlPUqO|05maiQ zo&0dWYf-mgc#B`GuiGd++E9|}D~TJ}s*9mwqb%!&3m*$udm~4MT1eUAU(}x|-Gw5I zqY@`--Y9PLJJ@(>6}9`JW`8JgxrP(hI|j=1b{M|h+*5=dMfniDUyl{kG(u>mzke|z z_OyCI-Xwf)f;vW>qYtAaJ2+P5%*fxDiCG6 zjBAgCV-~u4*K!2>O4ntlD86nynaykA7%e8hs}i`>+du$=tUl7%7Gl0cy2WxHS$8~} zYP_d*@RiyfeMnd>^rVPk;yhfYHd9f{50L_V#~#`;tw(>zu=*OV7Awr%=J~%N#$}&@ z20es)umbS=D9Mzw2!Eaz z3fcUuBt#evH!tV{anpVo^zh-?tKzP-UGjQIy3LS4H;Z`et0q4=Os7{UU(9(7mPGO@ zu?w+wWFerPNr_|PYKwkQ!(;4G4rOk5lq;lHTt!UU(P>8sfd+M4jTM9P0CdfgQR?hjmx{NLk%CHom0X@!KJvj(-6Y>EFHLK-Oz`Lspm1tLFuadHk!)iI zH#=1zDl2VWVfj59a>6__5%AYkdFll?QHEsuzGOgV${1&xd zB30k3;~d@5-5Ods)VP)%v{}s|PA-AyT!WZWi{e z9No=e#rS*U$AS@Q=y>JDf!wio<0SlJx)I8neMwGeo|e&kT*2_jR*VwbahJ~rkuOT9 zj3R17s3RXkZkLFY{kx&GR-RUAam|S{fZnw)T^IxK5-Ow+W9ag(&|OCZ^ndr*M|8TPlxTIn`ZVrF!7skOBS31-XKe9t z`xV#cROEOM_wnlkdcz-Dji&Kr%uT}yu8XhSME{JyKDBTyccLQ-me)_5RD`NCRBf&u z(K)?Wx_~mtZstI=qeH&XfoU72dm!5Yl{PXmCMWB4S`SU9gFBRrUkeXDkB9& z<#7b}KN(}l>fEm2O1uASDSy%2K|oz)Fis|VJ-go;6v!nh+t)hz1yA9%u^Lm83N0D0 z0K#!Kfp;XZwg7w}MVJ)a1rwGUaNkWNq&cJ<%^8-eeVf-|W}zI^LKr*)W7zsa<1jxN~FTCMI| zhcaoTx~l@s7eHgPe`j~u=A%!M43f)3xZo+G?(-07)_-QgVUM*~vW*Jd>=-`pz&Pj& z-vUu2$ZP!#A5*6v)K+Ir^k0l90PYOppWN8|S<$Va)3=4>OIM`e1&ROJEclsG`XDnc z*c1acMLlfQ7Yx@YbI4{&0t!f94n@>S-^2TW3-6SO@?TR4hGnp%k$v{;DtGaRp}B0t zR1i>mOSf7l>uS|5u3LX$MbvH0HHwk*aucsc<6^)m>CyNhyE`%-4)n{7j5Q4xBTJdWB{t7HAQn@JuMe&+z@5G(4zcQ)X}*x1)Nzbce~z)Z6QB7x z$WVzDKYo3N>RneE(W$*KL2lsf2x5qc&HvHLFuQDowZ(==&!WNr+4U(v^jX+MoD|Vr zbU^Lr2Xf-Vi9*v!FybAh=Y%se?42sjjGpk89O19?xf7XUjDR89Fc`Uz&=E-mJLHA} zv^Eq+hN{u+SR%YJ_uz;5FL!8B+i-vgI4tMbp2&F~*$d1iP>H+p_q?U9DrQoeWa4 zz5WSmks8+}p*kosjG%WcQYwhr0Sabqub%qnzeB=ATxpm1={OmB$9lQ;t@VaRFX2w& zcl^tcat&%I+#-}&)j@?Yi*f}``U9LtJ%Prei!RZUym|yGQ^3~pVFGI%1Q)nwz$7yJ zE|^;V>1=fa9p&$i<2%NjN8p?_m(L-uI~Ww8iB{wDZqs(Ge~z_{qxr3kkBbKWr1b`D z7El=KVJN~Oytuh+{d;K*)KRO*r8@^aftTeS6M>JKA;Cgk{PT&_Sn!@GF!^Sz%h}q5Z|w1PPNiV z$LWBkzQyt4mY5*fn9F7T&>Z|1!C{jQytD=gT@rys)WJQqKs-m1j^1WM38q|A z6^NU^KR8T4;OhcEjOvQvh5s|Bw%b)kGoT*%+A6J81OY~ABKA$8=w9eI&3b5WX3{^B ztW02ghicXn+WQV3Nn0?>8>8qClpvQc0e2Bn1E^Ga^x;5H9vLRU1}FFImY^TbfX_3W+BfG#t|y z=$;^>H0x@kK%Tah)Ejk%v}*>ARfO}rx1nu;f)%CM4ZSnvxED!z&_{&NW|00K)yC`n z1js_6mQ166E3Ej@ziv$GnB9rtBRUh2Tg_InVrMWX3+Y;Sm!VFaV$PCEI4mI*GA9sJ zKaRxNq}3Qyb?olzLw{y9$-PQ6OvhjS5P}b#BKz+CA!$^wUEDnzbrw{ZHN2*v?M?V#A<0N&@-(mi zAxd5gR>q3qtNg%C?f}7P$sQY@pH)V1Rm7;P?2$t zKzIGq3{G3d2abwXfC*PT??C;Lf|E7XZl%hx=x~RBbx*epN7sFXKWbj1D=pg;$0&n+ zFNxIeGjUPZS?^{FbYVUM3R<*xch?UCfH25Kx-&2ku?O7o-y!T?lm|l*#lK5^919pD zGbtA#NPlv)`P|w*UH#gBVn|TEew8I)#W*#Sng&kBfFVF3tl=@PkcpPor>cX@f`H&U znn0q?uL3yX1!Wv=jFzHIg#iG0XHjao@B#|eqA+BxnNR|s@}E{6b}Ojrm( zN$#;KLwtQ>#f~=qY{aq&ry{Ta`E&vjPyy0aRlLhG?!?8kgjlZ_*o#%jIfSp^s)%+X z40NfdAhk3e;1-o$t$A$Pv7vV_)8=iTe`h%7AuP_w=a{?Ev9EaDD&V>SWW{8cntFQH zjuUQ@ne0wwq6Rky)a1IFcvhowm|;RGRGy&vr=xAp)_p>Vx@n$8->p*3*~N;Q!poKHpWc$*czw&$kVJXlj2)Lxc<4(^%*#C@R5^Rf2(yX~@g18|mG{f~-? zdpGl>ey)>|(op9C>jqSe7oRb_-MOYI+NXUQRVe3$9Ts=`4|wAdu)XP%1t;qNKpz6h zlRq?|vquU0vE)Fm%d+f_vAOk-f{dTFv{ZENXb9v#ZX({=VzpANcC+tNR4$xF2T|MT10hD!uhAIILZ`2#!Z0!FhF9r{&%}c+jK!2l{YW58FK zs%q34l;B9RzQNQie_>4m|83E1tX?|GCwzPX@11j8MIkm^kTO2w92Cusq4YexVJ^Jo zXlCL9Hk_gEzPHK!i>myXj8&U7VLYCx4(~v)3fF6Fe2cA{-}%NC*6xP!y>A<@L{%U~ zW)$Vt+!+p>nsq_Tr;&%v4SQ@bta`LZIbpYYWoc=q=b`@ZA}mXoh!~AIVK)|2eEtBPA2-hvxOg ztl4eab<#qGeNmIV|fR*!4Z<$jpk0ztKS@}r?PVCY|EpPU3JtC zObb}fb*r)1(fEr#BHWdcm%%ncv@JD4MQzWZt}ch4Y1_t{QrHs366w%=c|WZn)ZQ)O zlLiCmdc;`bb<>Xc_h&LYRNGW%epzJluR!qy{;`OD?^^|^+uU#|T>t{w$@q?yz^ED{ zch+H*H4FZ>rV<>XqX3+-If(4erT9U5(F7FQ*dA`wo8;;d1K6sZ=Y@*@DO{i^%)=kv zU+IWOpg{QrQi=*_q(MWP)N4keVU-Wl(0HCq{fctj-ElWlhA-edHqxHE{5$^+wKTT@FjKax=L!Mubf5ZLB7@ZMwZL%0D?yI|I66Venb4 zu#EVnqW!*%U)=4pPusF(aML<*cl;Z#;SkhtAoMJyJP9S%8|Yg`jdvCoQ%gL3mpIJZ ze9G7L+Kj{D-IPpdfDxe9d+W}l9**Q0Q0_g=CO(DKYH2Z527actb3`rg;*aVH^aYop zkYc2$K?W@Ll)woO5&QagtzXPHqW5SE5E<3SCVI)Dz;QKtZ`JF(8EW2LTvW(hPDl>z z0p4AN&t?7^)=zrvyb2F3Riw9K`ZWKCLujX);EUfBx-mf|cg-*U7sKC|!P@HT-LTwZ zda!AWW&BCJNHf(i&XJadiLc7jiZW4-gdwZk7mogp^L2+|4!gf2<@N#+Q6Wpbii1-r zm3Z(q;vDQRu!!9qXPvoh>O2dbE^Pj6;P9=xOT)#S19F@GFEx~^G=p{1>l#xKkdk&M zSCwqoTKcetN^gpZ;q+SIiN4KL+m!V%B6y=(>M3Jy&PQSJxteUu5o8e`GZ_M1Q_>RO zEkk6f9-DU~;C%zTkq{n*M-XVT)S=g_rnXAx`$VqsCx!>FRsNzC#38_3*;x5#y$85S zaa?-=%0%+nzv8pRf&qc@IX7B1esavfp*I49h0Q^XX#f5-W>|{5a-S54keEm0PtMZt zl9x4D(>lyCwuCDpuGr`=i6e!g(;6`8qj6+%MCg%DL>Yx&fTY(J*flDvQh_TtT+6u+ zNSj_b>0yHY+UWP+jr^pGiIoWO_IigBK@_+)n4-9^+(zOA>-3Ma6hp>Z`SyG4Y7f%l zC<3+jsGNFNuediY62Az(Srr*747eqtY%|}PDS|UOH_FkQaO|G5Os^Mgpe?lMsEy)K zP17yxwLYFEf;gV&>KYnltb$MDQDri{c0%N<3xBW=%h>QlBe^ofOh$SjCI~8`>5}td z%ag-Mwu2jnb6I#KaBhwkN)<;bRIreGx4=#~;J)Wgd2HK(4Gd?q2(i$_l%>a($u|+$j06y3+Rsal^EkejC1(gJQAAl3GFhudp8H{j{9J=R{*Nx2sLPs zV9R(3pCTYD*w7Nd&8mnAllJfR!YK5D)YD>E0kGB$z3Q&XR=9twHV0BD2-C$zD?m=G zf7xfCDDGRFOv!W9C3=I$fO}<<224dPkf;2FqfT^enahI+iK<-1^(e`WJMmJp+b|#J zT$eZM^N1`%Q6p2-0gOPJzk8eCRx8t8`YQX8FhR(!>y10O63%FdClKEmYoSN4)O$Jk zFi|#d0f7U4{5+?(4m90Gf7Ww8$0;sDv_zPm&Mh|t@Ksff6B_%U>GObT`c1kmu5=uA z@LT@l1QRABPx`qd>2iVS_DJp%F%(5<(zWJpWrPS7)kgIB;4;?&!^;vWAbOJoE(c(H z{Wt*6$Je2<=C8-3N0z8&&uBGWrAOeN@~@O&q01&UF|1n#d?NO%0PFhZbi6?6^q=uI z28yBMrnFDohIyvpkC7efCMrwPj^m-_xv zchJFaf+j@NIZ3b5nW0JXY0zS`rD~X%H4_UgkG>`O7`-2A&a0z;Bu-9IcNnCKnF{3# z9v0%k`vZoK{_JS7=$bJZ4p)4Xy#0>9I^GkS-lpoPyaYf+LJ|r?PbOtR8=Ew(KJ?lk zchf2ev{4WVIceN)z8QC<9GuKkpN$9OPV6RvHb}pL2(8X5M+_%1N3n~-^>c@k4dPP# zVVL0UB-;8oYE{0WrMn#qPX!-=5QAve=k+m8lSeK_zRXE33IF{$!iOJ*61ay+644Z} zki9L|u9;dxa01Y=QKH=*KA(e9Gbz(V+mikeil^yD)Iu6YhG@xOpuutf$K8xkMa5BwI);;CrlMS2M`C<#dzp!slsKPS zf!&ZQ74pe`>7y%^M74_H0i3p-obkyG3KU>hz}=8weraXhA>Fatb{7vpvm|0-k2Vf^ zd{|RBv#&rF@^bzW6}$>VQJ#-!WtT~gx<|3KXYAI`w}hXKht?kBkN~6E(OikDSo|8h3G^;tvl;RoGK#Q0 zZdB)zfdc&@aE-te2a8iAGaf+U`7%&q_!wCVf`P~SYpi~HedxwGOKnwv+E64Wf=7^o z*n?j=J(W>VRJ#2+_Sng0Srq()aB;S}!H~J|-)n5AX2G3#3|s1zFa{XT;F)%8=L#rnlT$SfEsfSD9zyVu&T#lv}3*&i;W%oG3%Fa4j%0MtsFhR +#include +#include +#include + +/ { + model = "Analog Devices MAX32672EVKIT"; + compatible = "adi,max32672evkit"; + + chosen { + zephyr,console = &uart0; + zephyr,shell-uart = &uart0; + zephyr,sram = &sram3; + zephyr,flash = &flash0; + }; + + leds { + compatible = "gpio-leds"; + led1: led_1 { + gpios = <&gpio0 22 GPIO_ACTIVE_LOW>; + label = "Red LED"; + }; + led2: led_2 { + gpios = <&gpio0 23 GPIO_ACTIVE_LOW>; + label = "Green LED"; + }; + }; + + buttons { + compatible = "gpio-keys"; + pb1: pb1 { + gpios = <&gpio0 18 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>; + label = "SW3"; + zephyr,code = ; + }; + }; + + /* These aliases are provided for compatibility with samples */ + aliases { + led0 = &led1; + led1 = &led2; + sw0 = &pb1; + }; +}; + +&uart0 { + pinctrl-0 = <&uart0a_tx_p0_9 &uart0a_rx_p0_8>; + pinctrl-names = "default"; + current-speed = <115200>; + data-bits = <8>; + parity = "none"; + status = "okay"; +}; + +&clk_ipo { + status = "okay"; +}; + +&gpio0 { + status = "okay"; +}; + +&gpio1 { + status = "okay"; +}; diff --git a/boards/adi/max32672evkit/max32672evkit.yaml b/boards/adi/max32672evkit/max32672evkit.yaml new file mode 100644 index 0000000000000..a7f285ff4cc59 --- /dev/null +++ b/boards/adi/max32672evkit/max32672evkit.yaml @@ -0,0 +1,13 @@ +identifier: max32672evkit +name: max32672evkit +type: mcu +arch: arm +toolchain: + - zephyr + - gnuarmemb + - xtools +supported: + - gpio + - serial +ram: 200 +flash: 1024 diff --git a/boards/adi/max32672evkit/max32672evkit_defconfig b/boards/adi/max32672evkit/max32672evkit_defconfig new file mode 100644 index 0000000000000..a048ab2608ff0 --- /dev/null +++ b/boards/adi/max32672evkit/max32672evkit_defconfig @@ -0,0 +1,13 @@ +# Copyright (c) 2024 Analog Devices, Inc. +# SPDX-License-Identifier: Apache-2.0 + +# Enable GPIO +CONFIG_GPIO=y + +# Console +CONFIG_CONSOLE=y +CONFIG_UART_CONSOLE=y + +# Enable UART +CONFIG_SERIAL=y +CONFIG_UART_INTERRUPT_DRIVEN=y From ae5a15ab0efe623a1105c6398c347b68624adf44 Mon Sep 17 00:00:00 2001 From: Sadik Ozer Date: Wed, 10 Jan 2024 17:21:48 +0300 Subject: [PATCH 2649/2849] tests: drivers: gpio: Enable gpio driver tests for max32672 boards Enable gpio driver test for max32672evkit and fthr boards Signed-off-by: Sadik Ozer --- .../gpio_basic_api/boards/max32672evkit.overlay | 13 +++++++++++++ .../gpio/gpio_basic_api/boards/max32672fthr.overlay | 13 +++++++++++++ 2 files changed, 26 insertions(+) create mode 100644 tests/drivers/gpio/gpio_basic_api/boards/max32672evkit.overlay create mode 100644 tests/drivers/gpio/gpio_basic_api/boards/max32672fthr.overlay diff --git a/tests/drivers/gpio/gpio_basic_api/boards/max32672evkit.overlay b/tests/drivers/gpio/gpio_basic_api/boards/max32672evkit.overlay new file mode 100644 index 0000000000000..1655b0bc850d8 --- /dev/null +++ b/tests/drivers/gpio/gpio_basic_api/boards/max32672evkit.overlay @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2024 Analog Devices, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + resources { + compatible = "test-gpio-basic-api"; + out-gpios = <&gpio0 2 0>; + in-gpios = <&gpio0 3 0>; + }; +}; diff --git a/tests/drivers/gpio/gpio_basic_api/boards/max32672fthr.overlay b/tests/drivers/gpio/gpio_basic_api/boards/max32672fthr.overlay new file mode 100644 index 0000000000000..639347690691d --- /dev/null +++ b/tests/drivers/gpio/gpio_basic_api/boards/max32672fthr.overlay @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2024 Analog Devices, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + resources { + compatible = "test-gpio-basic-api"; + out-gpios = <&gpio0 12 0>; + in-gpios = <&gpio0 13 0>; + }; +}; From cab48b0743ef0eb76c677409cf1833f7e55013e8 Mon Sep 17 00:00:00 2001 From: Ayush Singh Date: Sat, 18 May 2024 17:54:57 +0530 Subject: [PATCH 2650/2849] ieee802154: ieee802154_cc13xx_cc26xx_subg: Fix tcp timeout - If status == PROP_ERROR_RXBUF, that means rx buffer head is not empty. In case of this, RF_EventRxEntryDone is never triggered and thus we enter an infinite loop of nothing happening. Due to this, TCP socket times out. - To fix this, we need to free rx buffer current head. However, it seems better to free all the elements that are already finished instead of just head. - Before 128354ae17fb95ec6c61d73b9060f1a274715464, the buffer was reset every time drv_rx_start was called. However, that also seems wrong for a ring buffer. So I am freeing the finished buffers instead. - Tested on Beagleconnect Freedom. - Fixes https://github.com/zephyrproject-rtos/zephyr/issues/71191 Signed-off-by: Ayush Singh --- drivers/ieee802154/ieee802154_cc13xx_cc26xx_subg.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/ieee802154/ieee802154_cc13xx_cc26xx_subg.c b/drivers/ieee802154/ieee802154_cc13xx_cc26xx_subg.c index 7f2356e8ecfec..3f6d7067705b6 100644 --- a/drivers/ieee802154/ieee802154_cc13xx_cc26xx_subg.c +++ b/drivers/ieee802154/ieee802154_cc13xx_cc26xx_subg.c @@ -403,7 +403,11 @@ static void cmd_prop_rx_adv_callback(RF_Handle h, RF_CmdHandle ch, LOG_DBG("ch: %u cmd: %04x st: %04x e: 0x%" PRIx64, ch, op->commandNo, op->status, e); - if (e & RF_EventRxEntryDone) { + /* If PROP_ERROR_RXBUF is returned, then RF_EventRxEntryDone is never + * triggered. So finished buffers need to be cleaned up even on this + * status. + */ + if (e & RF_EventRxEntryDone || op->status == PROP_ERROR_RXBUF) { drv_rx_done(drv_data); } From c98760df44b0bceabc49fce16fb7cca48dcab642 Mon Sep 17 00:00:00 2001 From: Andreas Klinger Date: Fri, 15 Mar 2024 13:20:46 +0100 Subject: [PATCH 2651/2849] boards: fix openocd deprecated configuration Replace deprecated settings: adapter_khz --> adapter speed adapter_nsrst --> adapter srst delay Tested on olimex stm32_e407 board with olimex arm-usb-tiny-h adapter Signed-off-by: Andreas Klinger --- boards/adafruit/itsybitsy_m4_express/support/openocd.cfg | 2 +- boards/arm/v2m_beetle/support/openocd.cfg | 2 +- .../support/openocd_arty_a7_arm_designstart_m1.cfg | 2 +- .../support/openocd_arty_a7_arm_designstart_m3.cfg | 2 +- boards/espressif/esp32c3_devkitm/support/openocd.cfg | 2 +- boards/luatos/esp32c3_luatos_core/support/openocd.cfg | 2 +- boards/m5stack/stamp_c3/support/openocd.cfg | 2 +- boards/mikroe/mini_m4_for_stm32/support/openocd.cfg | 4 ++-- boards/nxp/lpcxpresso11u68/support/openocd.cfg | 2 +- boards/olimex/stm32_e407/support/openocd.cfg | 9 ++++----- boards/olimex/stm32_h103/support/openocd_olimex_jtag.cfg | 4 ++-- boards/olimex/stm32_h405/support/openocd.cfg | 4 ++-- boards/olimex/stm32_h407/support/openocd.cfg | 4 ++-- boards/olimex/stm32_p405/support/openocd.cfg | 4 ++-- .../rv32m1_vega/support/openocd_rv32m1_vega_ri5cy.cfg | 2 +- .../support/openocd_rv32m1_vega_zero_riscy.cfg | 2 +- boards/others/icev_wireless/support/openocd.cfg | 2 +- boards/seagate/faze/support/openocd.cfg | 2 +- boards/seeed/wio_terminal/support/openocd.cfg | 2 +- boards/seeed/xiao_esp32c3/support/openocd.cfg | 2 +- boards/sipeed/longan_nano/support/openocd.cfg | 2 +- boards/st/st25dv_mb1283_disco/support/openocd.cfg | 2 +- boards/ti/cc1352r_sensortag/support/openocd.cfg | 2 +- 23 files changed, 31 insertions(+), 32 deletions(-) diff --git a/boards/adafruit/itsybitsy_m4_express/support/openocd.cfg b/boards/adafruit/itsybitsy_m4_express/support/openocd.cfg index 096e396efc5f9..4423471225930 100644 --- a/boards/adafruit/itsybitsy_m4_express/support/openocd.cfg +++ b/boards/adafruit/itsybitsy_m4_express/support/openocd.cfg @@ -7,7 +7,7 @@ source [find target/atsame5x.cfg] # TODO(http://openocd.zylin.com/#/c/5706/): lower the clock speed to workaround # an erase timeout. -adapter_khz 500 +adapter speed 500 reset_config srst_only $_TARGETNAME configure -event gdb-attach { diff --git a/boards/arm/v2m_beetle/support/openocd.cfg b/boards/arm/v2m_beetle/support/openocd.cfg index e1d1062ca08f3..36004576d093f 100644 --- a/boards/arm/v2m_beetle/support/openocd.cfg +++ b/boards/arm/v2m_beetle/support/openocd.cfg @@ -22,7 +22,7 @@ if { [info exists CPUTAPID] } { set _CPUTAPID 0x2ba01477 } -adapter_khz 1000 +adapter speed 1000 set _TARGETNAME $_CHIPNAME.cpu diff --git a/boards/digilent/arty_a7/support/openocd_arty_a7_arm_designstart_m1.cfg b/boards/digilent/arty_a7/support/openocd_arty_a7_arm_designstart_m1.cfg index cf9f88347ecbb..213703a924752 100644 --- a/boards/digilent/arty_a7/support/openocd_arty_a7_arm_designstart_m1.cfg +++ b/boards/digilent/arty_a7/support/openocd_arty_a7_arm_designstart_m1.cfg @@ -1,7 +1,7 @@ source [find interface/cmsis-dap.cfg] source [find target/swj-dp.tcl] -adapter_khz 5000 +adapter speed 5000 set _CHIPNAME cortex_m1 set _ENDIAN little diff --git a/boards/digilent/arty_a7/support/openocd_arty_a7_arm_designstart_m3.cfg b/boards/digilent/arty_a7/support/openocd_arty_a7_arm_designstart_m3.cfg index 17dbbb997ffd4..9491c2df0d7e6 100644 --- a/boards/digilent/arty_a7/support/openocd_arty_a7_arm_designstart_m3.cfg +++ b/boards/digilent/arty_a7/support/openocd_arty_a7_arm_designstart_m3.cfg @@ -1,7 +1,7 @@ source [find interface/cmsis-dap.cfg] source [find target/swj-dp.tcl] -adapter_khz 5000 +adapter speed 5000 set _CHIPNAME cortex_m3 set _ENDIAN little diff --git a/boards/espressif/esp32c3_devkitm/support/openocd.cfg b/boards/espressif/esp32c3_devkitm/support/openocd.cfg index 214a4aabf3fc6..92a792fecb8eb 100644 --- a/boards/espressif/esp32c3_devkitm/support/openocd.cfg +++ b/boards/espressif/esp32c3_devkitm/support/openocd.cfg @@ -8,4 +8,4 @@ set ESP_RTOS none source [find interface/ftdi/esp32_devkitj_v1.cfg] source [find target/esp32c3.cfg] -adapter_khz 5000 +adapter speed 5000 diff --git a/boards/luatos/esp32c3_luatos_core/support/openocd.cfg b/boards/luatos/esp32c3_luatos_core/support/openocd.cfg index b93b20ba46ea5..12065b5e63047 100644 --- a/boards/luatos/esp32c3_luatos_core/support/openocd.cfg +++ b/boards/luatos/esp32c3_luatos_core/support/openocd.cfg @@ -9,4 +9,4 @@ source [find interface/esp_usb_jtag.cfg] # source [find interface/ftdi/esp32_devkitj_v1.cfg] source [find target/esp32c3.cfg] -adapter_khz 5000 +adapter speed 5000 diff --git a/boards/m5stack/stamp_c3/support/openocd.cfg b/boards/m5stack/stamp_c3/support/openocd.cfg index 5db52f70d8340..92e47fabefb39 100644 --- a/boards/m5stack/stamp_c3/support/openocd.cfg +++ b/boards/m5stack/stamp_c3/support/openocd.cfg @@ -6,4 +6,4 @@ set ESP_RTOS none source [find interface/esp_usb_jtag.cfg] source [find target/esp32c3.cfg] -adapter_khz 5000 +adapter speed 5000 diff --git a/boards/mikroe/mini_m4_for_stm32/support/openocd.cfg b/boards/mikroe/mini_m4_for_stm32/support/openocd.cfg index b97b1a0527a27..4d5e4008c4039 100644 --- a/boards/mikroe/mini_m4_for_stm32/support/openocd.cfg +++ b/boards/mikroe/mini_m4_for_stm32/support/openocd.cfg @@ -6,8 +6,8 @@ transport select hla_swd source [find target/stm32f4x.cfg] -adapter_khz 1000 -adapter_nsrst_delay 100 +adapter speed 1000 +adapter srst delay 100 jtag_ntrst_delay 100 reset_config srst_only srst_nogate connect_assert_srst diff --git a/boards/nxp/lpcxpresso11u68/support/openocd.cfg b/boards/nxp/lpcxpresso11u68/support/openocd.cfg index 3a59e2b51a500..9d3282f59abf6 100644 --- a/boards/nxp/lpcxpresso11u68/support/openocd.cfg +++ b/boards/nxp/lpcxpresso11u68/support/openocd.cfg @@ -39,4 +39,4 @@ $_TARGETNAME configure -event reset-end { # Enable Zephyr thread awareness. $_TARGETNAME configure -rtos Zephyr -adapter_khz 100 +adapter speed 100 diff --git a/boards/olimex/stm32_e407/support/openocd.cfg b/boards/olimex/stm32_e407/support/openocd.cfg index d97149f96918b..c416c6958c01d 100644 --- a/boards/olimex/stm32_e407/support/openocd.cfg +++ b/boards/olimex/stm32_e407/support/openocd.cfg @@ -1,13 +1,12 @@ -source [find interface/stlink.cfg] +source [find interface/ftdi/olimex-arm-usb-tiny-h.cfg] +# source [find interface/stlink.cfg] set WORKAREASIZE 0x10000 -transport select hla_swd - source [find target/stm32f4x.cfg] -adapter_khz 1000 -adapter_nsrst_delay 100 +adapter speed 1000 +adapter srst delay 100 jtag_ntrst_delay 100 reset_config srst_only srst_nogate diff --git a/boards/olimex/stm32_h103/support/openocd_olimex_jtag.cfg b/boards/olimex/stm32_h103/support/openocd_olimex_jtag.cfg index e953fd32a05c8..3020364ce9c0e 100644 --- a/boards/olimex/stm32_h103/support/openocd_olimex_jtag.cfg +++ b/boards/olimex/stm32_h103/support/openocd_olimex_jtag.cfg @@ -4,8 +4,8 @@ transport select jtag source [find board/olimex_stm32_h103.cfg] -adapter_khz 1000 -adapter_nsrst_delay 100 +adapter speed 1000 +adapter srst delay 100 jtag_ntrst_delay 100 reset_config srst_only srst_nogate diff --git a/boards/olimex/stm32_h405/support/openocd.cfg b/boards/olimex/stm32_h405/support/openocd.cfg index 1f577d2c243e8..427feadd2c193 100644 --- a/boards/olimex/stm32_h405/support/openocd.cfg +++ b/boards/olimex/stm32_h405/support/openocd.cfg @@ -6,8 +6,8 @@ transport select hla_swd source [find target/stm32f4x.cfg] -adapter_khz 1000 -adapter_nsrst_delay 100 +adapter speed 1000 +adapter srst delay 100 jtag_ntrst_delay 100 reset_config srst_only srst_nogate diff --git a/boards/olimex/stm32_h407/support/openocd.cfg b/boards/olimex/stm32_h407/support/openocd.cfg index c48bab3646b36..a9db97fb87f5f 100644 --- a/boards/olimex/stm32_h407/support/openocd.cfg +++ b/boards/olimex/stm32_h407/support/openocd.cfg @@ -6,8 +6,8 @@ transport select jtag source [find target/stm32f4x.cfg] -adapter_khz 1000 -adapter_nsrst_delay 100 +adapter speed 1000 +adapter srst delay 100 jtag_ntrst_delay 100 reset_config srst_only srst_nogate diff --git a/boards/olimex/stm32_p405/support/openocd.cfg b/boards/olimex/stm32_p405/support/openocd.cfg index d97149f96918b..269578295d4f7 100644 --- a/boards/olimex/stm32_p405/support/openocd.cfg +++ b/boards/olimex/stm32_p405/support/openocd.cfg @@ -6,8 +6,8 @@ transport select hla_swd source [find target/stm32f4x.cfg] -adapter_khz 1000 -adapter_nsrst_delay 100 +adapter speed 1000 +adapter srst delay 100 jtag_ntrst_delay 100 reset_config srst_only srst_nogate diff --git a/boards/openisa/rv32m1_vega/support/openocd_rv32m1_vega_ri5cy.cfg b/boards/openisa/rv32m1_vega/support/openocd_rv32m1_vega_ri5cy.cfg index 11f5deb062da2..08a4880dc049c 100644 --- a/boards/openisa/rv32m1_vega/support/openocd_rv32m1_vega_ri5cy.cfg +++ b/boards/openisa/rv32m1_vega/support/openocd_rv32m1_vega_ri5cy.cfg @@ -3,7 +3,7 @@ set _WORKAREASIZE 0x2000 -adapter_khz 1000 +adapter speed 1000 interface jlink transport select jtag diff --git a/boards/openisa/rv32m1_vega/support/openocd_rv32m1_vega_zero_riscy.cfg b/boards/openisa/rv32m1_vega/support/openocd_rv32m1_vega_zero_riscy.cfg index 491dc56a54dfa..71d23a125d3da 100644 --- a/boards/openisa/rv32m1_vega/support/openocd_rv32m1_vega_zero_riscy.cfg +++ b/boards/openisa/rv32m1_vega/support/openocd_rv32m1_vega_zero_riscy.cfg @@ -3,7 +3,7 @@ set _WORKAREASIZE 0x2000 -adapter_khz 1000 +adapter speed 1000 interface jlink transport select jtag diff --git a/boards/others/icev_wireless/support/openocd.cfg b/boards/others/icev_wireless/support/openocd.cfg index 02754ff2a73c1..7421637880c78 100644 --- a/boards/others/icev_wireless/support/openocd.cfg +++ b/boards/others/icev_wireless/support/openocd.cfg @@ -3,4 +3,4 @@ set ESP_RTOS none source [find interface/esp_usb_jtag.cfg] source [find target/esp32c3.cfg] -adapter_khz 5000 +adapter speed 5000 diff --git a/boards/seagate/faze/support/openocd.cfg b/boards/seagate/faze/support/openocd.cfg index d7dc6d82c0d4b..770d566fadd67 100644 --- a/boards/seagate/faze/support/openocd.cfg +++ b/boards/seagate/faze/support/openocd.cfg @@ -36,4 +36,4 @@ $_TARGETNAME configure -event reset-end { # Enable Zephyr thread awareness. $_TARGETNAME configure -rtos Zephyr -adapter_khz 100 +adapter speed 100 diff --git a/boards/seeed/wio_terminal/support/openocd.cfg b/boards/seeed/wio_terminal/support/openocd.cfg index ce9baa8012f1e..6b329e98de806 100644 --- a/boards/seeed/wio_terminal/support/openocd.cfg +++ b/boards/seeed/wio_terminal/support/openocd.cfg @@ -8,7 +8,7 @@ set CHIPNAME atsamd51p19 source [find target/atsame5x.cfg] -adapter_khz 500 +adapter speed 500 reset_config srst_only $_TARGETNAME configure -event gdb-attach { diff --git a/boards/seeed/xiao_esp32c3/support/openocd.cfg b/boards/seeed/xiao_esp32c3/support/openocd.cfg index 02754ff2a73c1..7421637880c78 100644 --- a/boards/seeed/xiao_esp32c3/support/openocd.cfg +++ b/boards/seeed/xiao_esp32c3/support/openocd.cfg @@ -3,4 +3,4 @@ set ESP_RTOS none source [find interface/esp_usb_jtag.cfg] source [find target/esp32c3.cfg] -adapter_khz 5000 +adapter speed 5000 diff --git a/boards/sipeed/longan_nano/support/openocd.cfg b/boards/sipeed/longan_nano/support/openocd.cfg index 4ebb4a0505b53..c28b90767d736 100644 --- a/boards/sipeed/longan_nano/support/openocd.cfg +++ b/boards/sipeed/longan_nano/support/openocd.cfg @@ -13,7 +13,7 @@ ftdi_vid_pid 0x0403 0x6010 ftdi_layout_init 0x0008 0x001b ftdi_layout_signal nSRST -oe 0x0020 -data 0x0020 -adapter_khz 2000 +adapter speed 2000 transport select jtag proc gd32vf103-pre-load {} { diff --git a/boards/st/st25dv_mb1283_disco/support/openocd.cfg b/boards/st/st25dv_mb1283_disco/support/openocd.cfg index 72b4cd7492a21..5d6a3772c5cf6 100644 --- a/boards/st/st25dv_mb1283_disco/support/openocd.cfg +++ b/boards/st/st25dv_mb1283_disco/support/openocd.cfg @@ -4,7 +4,7 @@ transport select hla_swd source [find target/stm32f4x.cfg] -adapter_khz 1000 +adapter speed 1000 reset_config srst_only diff --git a/boards/ti/cc1352r_sensortag/support/openocd.cfg b/boards/ti/cc1352r_sensortag/support/openocd.cfg index 16a135a531a07..beec0517534db 100644 --- a/boards/ti/cc1352r_sensortag/support/openocd.cfg +++ b/boards/ti/cc1352r_sensortag/support/openocd.cfg @@ -1,4 +1,4 @@ source [find board/ti_cc13x2_launchpad.cfg] # Workaround for #21372. This allows OpenOCD to flash correctly # with newer 3.x XDS firmware -adapter_khz 1500 +adapter speed 1500 From 77a3aec34e3fc3ad4f5bd26fc3ca30b4c25c4979 Mon Sep 17 00:00:00 2001 From: frei tycho Date: Wed, 5 Jun 2024 09:51:51 +0000 Subject: [PATCH 2652/2849] lib: added missing parenthesis - added missing parenthesis around macro argument expansion Signed-off-by: frei tycho --- lib/libc/minimal/source/stdout/fprintf.c | 2 +- lib/os/cbprintf_complete.c | 2 +- lib/utils/bitarray.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/libc/minimal/source/stdout/fprintf.c b/lib/libc/minimal/source/stdout/fprintf.c index 147f3e385a962..b3e57aa77e70a 100644 --- a/lib/libc/minimal/source/stdout/fprintf.c +++ b/lib/libc/minimal/source/stdout/fprintf.c @@ -10,7 +10,7 @@ #include #include -#define DESC(d) ((void *)d) +#define DESC(d) ((void *)(d)) int fprintf(FILE *ZRESTRICT stream, const char *ZRESTRICT format, ...) { diff --git a/lib/os/cbprintf_complete.c b/lib/os/cbprintf_complete.c index 206288cb1bbb1..29e35f0276f3b 100644 --- a/lib/os/cbprintf_complete.c +++ b/lib/os/cbprintf_complete.c @@ -1364,7 +1364,7 @@ int z_cbvprintf_impl(cbprintf_cb out, void *ctx, const char *fp, */ #define OUTS(_sp, _ep) do { \ - int rc = outs(out, ctx, _sp, _ep); \ + int rc = outs(out, ctx, (_sp), (_ep)); \ \ if (rc < 0) { \ return rc; \ diff --git a/lib/utils/bitarray.c b/lib/utils/bitarray.c index 509fa5f199f6d..82d4e895bd532 100644 --- a/lib/utils/bitarray.c +++ b/lib/utils/bitarray.c @@ -13,7 +13,7 @@ #include /* Number of bits represented by one bundle */ -#define bundle_bitness(ba) (sizeof(ba->bundles[0]) * 8) +#define bundle_bitness(ba) (sizeof((ba)->bundles[0]) * 8) struct bundle_data { /* Start and end index of bundles */ From 1cfd57177eefe59436142a2b052313a9c4bfc364 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20G=C5=82=C4=85bek?= Date: Mon, 11 Dec 2023 11:15:43 +0100 Subject: [PATCH 2653/2849] tests: timer_api: Use busy slew threshold when checking remaining ticks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On Nordic SoCs, the clock that drives the system timer and the one that is used in busy-waiting may be significantly skewed, so the test cases that compare durations derived from those two clocks need to take into account a proper threshold. After the `z_timeout_expires` function was corrected in 3d29c9fe546cd42554becee9dddcbe2e9e73d5cc, it turned out that the threshold was missing in one check and the related test case started to fail on nRF platforms. This patch adds that threshold there. Signed-off-by: Andrzej Głąbek --- tests/kernel/timer/timer_api/src/main.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/kernel/timer/timer_api/src/main.c b/tests/kernel/timer/timer_api/src/main.c index ba9a76d4085a1..12d1376bc92f2 100644 --- a/tests/kernel/timer/timer_api/src/main.c +++ b/tests/kernel/timer/timer_api/src/main.c @@ -723,9 +723,11 @@ ZTEST_USER(timer_api, test_timer_remaining) * than expected on systems where the requested microsecond * delay cannot be exactly represented as an integer number of * ticks. + * As above, use higher tolerance on platforms where the clock used + * by the kernel timer and the one used for busy-waiting may be skewed. */ - zassert_true(((int64_t)exp_ticks - (int64_t)now) <= (dur_ticks / 2) + 1, - NULL); + zassert_true(((int64_t)exp_ticks - (int64_t)now) + <= (dur_ticks / 2) + 1 + slew_ticks, NULL); } ZTEST_USER(timer_api, test_timeout_abs) From f73471eaf90c0f2fcbb4b1d79f6b07990d5b665a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20G=C5=82=C4=85bek?= Date: Mon, 11 Dec 2023 11:50:07 +0100 Subject: [PATCH 2654/2849] tests: timer_api: Use 64-bit integers in busy slew threshold calculation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 32-bit multiplication overflows for the 130000 ppm value used currently on Nordic SoCs and the duration that is configured to 100000 us. Signed-off-by: Andrzej Głąbek --- tests/kernel/timer/timer_api/src/main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/kernel/timer/timer_api/src/main.c b/tests/kernel/timer/timer_api/src/main.c index 12d1376bc92f2..b996baa72e346 100644 --- a/tests/kernel/timer/timer_api/src/main.c +++ b/tests/kernel/timer/timer_api/src/main.c @@ -45,8 +45,8 @@ struct timer_data { * between the two clocks. Produce a maximum error for a given * duration in microseconds. */ -#define BUSY_SLEW_THRESHOLD_TICKS(_us) \ - k_us_to_ticks_ceil32((_us) * BUSY_TICK_SLEW_PPM \ +#define BUSY_SLEW_THRESHOLD_TICKS(_us) \ + k_us_to_ticks_ceil32((_us) * (uint64_t)BUSY_TICK_SLEW_PPM \ / PPM_DIVISOR) static void duration_expire(struct k_timer *timer); From b22c961e5e9caa7628630bfce1b81b2dfd15f6fd Mon Sep 17 00:00:00 2001 From: Daniel Schultz Date: Thu, 11 Apr 2024 16:12:57 -0700 Subject: [PATCH 2655/2849] scripts: west: runner: openocd: Add gdb-client-port The gdb-port defines the GDB port and the openocd runner passes this value to openocd as well as gdb. However, the TI AM62x board provides multiple ports for each subsystem. For example, systick appears at 3333, A53 as 3334-3337, R5F as 3338 and M4F as 3339. If we want to connect to the M4F, we need to add another port which is different to the to the gdb-port value. This patch adds an additional argument --gdb-client-port to define the port which GDB should connect to. It defaults to 3333, identical to gdb-port. Signed-off-by: Daniel Schultz --- scripts/west_commands/runners/openocd.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/scripts/west_commands/runners/openocd.py b/scripts/west_commands/runners/openocd.py index 5619c583d96eb..6af2b70adb34c 100644 --- a/scripts/west_commands/runners/openocd.py +++ b/scripts/west_commands/runners/openocd.py @@ -37,6 +37,7 @@ def __init__(self, cfg, pre_init=None, reset_halt_cmd=DEFAULT_OPENOCD_RESET_HALT tcl_port=DEFAULT_OPENOCD_TCL_PORT, telnet_port=DEFAULT_OPENOCD_TELNET_PORT, gdb_port=DEFAULT_OPENOCD_GDB_PORT, + gdb_client_port=DEFAULT_OPENOCD_GDB_PORT, gdb_init=None, no_load=False, target_handle=DEFAULT_OPENOCD_TARGET_HANDLE): super().__init__(cfg) @@ -85,6 +86,7 @@ def __init__(self, cfg, pre_init=None, reset_halt_cmd=DEFAULT_OPENOCD_RESET_HALT self.tcl_port = tcl_port self.telnet_port = telnet_port self.gdb_port = gdb_port + self.gdb_client_port = gdb_client_port self.gdb_cmd = [cfg.gdb] if cfg.gdb else None self.tui_arg = ['-tui'] if tui else [] self.halt_arg = [] if no_halt else ['-c halt'] @@ -146,6 +148,9 @@ def do_add_parser(cls, parser): help='openocd telnet port, defaults to 4444') parser.add_argument('--gdb-port', default=DEFAULT_OPENOCD_GDB_PORT, help='openocd gdb port, defaults to 3333') + parser.add_argument('--gdb-client-port', default=DEFAULT_OPENOCD_GDB_PORT, + help='''openocd gdb client port if multiple ports come + up, defaults to 3333''') parser.add_argument('--gdb-init', action='append', help='if given, add GDB init commands') parser.add_argument('--no-halt', action='store_true', @@ -174,8 +179,8 @@ def do_create(cls, cfg, args): use_elf=args.use_elf, no_halt=args.no_halt, no_init=args.no_init, no_targets=args.no_targets, tcl_port=args.tcl_port, telnet_port=args.telnet_port, gdb_port=args.gdb_port, - gdb_init=args.gdb_init, no_load=args.no_load, - target_handle=args.target_handle) + gdb_client_port=args.gdb_client_port, gdb_init=args.gdb_init, + no_load=args.no_load, target_handle=args.target_handle) def print_gdbserver_message(self): if not self.thread_info_enabled: @@ -351,7 +356,7 @@ def do_attach_debug(self, command, **kwargs): pre_init_cmd + self.init_arg + self.targets_arg + self.halt_arg) gdb_cmd = (self.gdb_cmd + self.tui_arg + - ['-ex', 'target extended-remote :{}'.format(self.gdb_port), + ['-ex', 'target extended-remote :{}'.format(self.gdb_client_port), self.elf_name]) if command == 'debug': gdb_cmd.extend(self.load_arg) From 281500f04657c8629206a4e5917fa0ef94b362d1 Mon Sep 17 00:00:00 2001 From: Daniel Schultz Date: Wed, 15 May 2024 08:07:51 +0200 Subject: [PATCH 2656/2849] soc: ti: k3: Enable BUILD_NO_GAP_FILL for all M4 By default, a post build step tries to fill gaps in the output hex file. Since the AM62x, for example, has different, non-contiguous memory sections, it tries to fill a gap over multiple GBs. Disable this feature since the K3 architecture has no dedicated flash for the firmware and stores it in a Linux rootfs. Signed-off-by: Daniel Schultz --- soc/ti/k3/am6x/Kconfig.defconfig | 3 +++ 1 file changed, 3 insertions(+) diff --git a/soc/ti/k3/am6x/Kconfig.defconfig b/soc/ti/k3/am6x/Kconfig.defconfig index f8a999baf50ea..2d9794413e4a4 100644 --- a/soc/ti/k3/am6x/Kconfig.defconfig +++ b/soc/ti/k3/am6x/Kconfig.defconfig @@ -42,4 +42,7 @@ endif # SERIAL config BUILD_OUTPUT_BIN default n if SOC_SERIES_AM6X_M4 +config BUILD_NO_GAP_FILL + default y if SOC_SERIES_AM6X_M4 + endif # SOC_SERIES_AM6X From 680228d5d6cb0179d04ec2dec3845987443f1d54 Mon Sep 17 00:00:00 2001 From: Daniel Schultz Date: Thu, 11 Apr 2024 16:10:08 -0700 Subject: [PATCH 2657/2849] boards: ti: sk_am62: Add OpenOCD support The SK AM62 EVM is equipped with an XDS110 JTAG debugger. Add missing OpenOCD configuration and some documentation to support 'west debug'. Signed-off-by: Daniel Schultz --- boards/ti/sk_am62/board.cmake | 10 ++++++++++ boards/ti/sk_am62/doc/index.rst | 18 ++++++++++++++++++ boards/ti/sk_am62/support/openocd.cfg | 7 +++++++ 3 files changed, 35 insertions(+) create mode 100644 boards/ti/sk_am62/board.cmake create mode 100644 boards/ti/sk_am62/support/openocd.cfg diff --git a/boards/ti/sk_am62/board.cmake b/boards/ti/sk_am62/board.cmake new file mode 100644 index 0000000000000..d148f687c293a --- /dev/null +++ b/boards/ti/sk_am62/board.cmake @@ -0,0 +1,10 @@ +# Texas Instruments Sitara AM62x-SK-M4 EVM +# +# Copyright (c) 2024, PHYTEC Messtechnik GmbH +# +# SPDX-License-Identifier: Apache-2.0 + +if(CONFIG_SOC_AM6234_M4) + board_runner_args(openocd "--no-init" "--no-halt" "--no-targets" "--gdb-client-port=3339") + include(${ZEPHYR_BASE}/boards/common/openocd.board.cmake) +endif() diff --git a/boards/ti/sk_am62/doc/index.rst b/boards/ti/sk_am62/doc/index.rst index 0a93edd1367a0..3dd92386321b2 100644 --- a/boards/ti/sk_am62/doc/index.rst +++ b/boards/ti/sk_am62/doc/index.rst @@ -119,6 +119,21 @@ To allow the board to boot using the SD card, set the boot pins to the SD Card b After changing the boot mode, the board should go through the boot sequence on powering up. The binary will run and print Hello world to the MCU_UART0 port. +Debugging +********* + +The board is equipped with an XDS110 JTAG debugger. To debug a binary, utilize the `debug` build target: + +.. zephyr-app-commands:: + :zephyr-app: + :board: sk_am62/am6234/m4 + :maybe-skip-config: + :goals: debug + +.. hint:: + To utilize this feature, you'll need OpenOCD version 0.12 or higher. Due to the possibility of + older versions being available in package feeds, it's advisable to `build OpenOCD from source`_. + References ********** @@ -136,3 +151,6 @@ AM62x SK EVM TRM: .. _EVM Setup Page: https://software-dl.ti.com/mcu-plus-sdk/esd/AM62X/08_06_00_18/exports/docs/api_guide_am62x/EVM_SETUP_PAGE.html + +.. _build OpenOCD from source: + https://docs.u-boot.org/en/latest/board/ti/k3.html#building-openocd-from-source diff --git a/boards/ti/sk_am62/support/openocd.cfg b/boards/ti/sk_am62/support/openocd.cfg new file mode 100644 index 0000000000000..2b09fb7345a84 --- /dev/null +++ b/boards/ti/sk_am62/support/openocd.cfg @@ -0,0 +1,7 @@ +# Texas Instruments Sitara AM62x-SK-M4 EVM +# +# Copyright (c) 2024, PHYTEC Messtechnik GmbH +# +# SPDX-License-Identifier: Apache-2.0 + +source [find board/ti_am625evm.cfg] From 4e95fde58ccf94290164cc3ac2f302a30f21e4b2 Mon Sep 17 00:00:00 2001 From: Daniel Schultz Date: Fri, 19 Apr 2024 16:08:31 -0700 Subject: [PATCH 2658/2849] boards: phytec: phyboard_lyra: Add OpenOCD support for M4 The phyBOARD-Lyra AM62x is equipped with an XDS110 JTAG debugger. Add missing OpenOCD configuration and some documentation to support 'west debug'. Signed-off-by: Daniel Schultz --- boards/phytec/phyboard_lyra/board.cmake | 10 ++++++++++ .../doc/phyboard_lyra_am62xx_m4.rst | 18 ++++++++++++++++++ .../phytec/phyboard_lyra/support/openocd.cfg | 7 +++++++ 3 files changed, 35 insertions(+) create mode 100644 boards/phytec/phyboard_lyra/board.cmake create mode 100644 boards/phytec/phyboard_lyra/support/openocd.cfg diff --git a/boards/phytec/phyboard_lyra/board.cmake b/boards/phytec/phyboard_lyra/board.cmake new file mode 100644 index 0000000000000..5f42441db6941 --- /dev/null +++ b/boards/phytec/phyboard_lyra/board.cmake @@ -0,0 +1,10 @@ +# PHYTEC phyBOARD-Lyra AM62x M4/A53 +# +# Copyright (c) 2024, PHYTEC Messtechnik GmbH +# +# SPDX-License-Identifier: Apache-2.0 + +if(CONFIG_SOC_AM6234_M4) + board_runner_args(openocd "--no-init" "--no-halt" "--no-targets" "--gdb-client-port=3339") + include(${ZEPHYR_BASE}/boards/common/openocd.board.cmake) +endif() diff --git a/boards/phytec/phyboard_lyra/doc/phyboard_lyra_am62xx_m4.rst b/boards/phytec/phyboard_lyra/doc/phyboard_lyra_am62xx_m4.rst index a8765c0fcc379..0736292446cdd 100644 --- a/boards/phytec/phyboard_lyra/doc/phyboard_lyra_am62xx_m4.rst +++ b/boards/phytec/phyboard_lyra/doc/phyboard_lyra_am62xx_m4.rst @@ -131,6 +131,21 @@ The board should boot into Linux and the binary will run and print Hello world t port. +Debugging +********* + +The board is equipped with an XDS110 JTAG debugger. To debug a binary, utilize the `debug` build target: + +.. zephyr-app-commands:: + :zephyr-app: + :board: phyboard_lyra/am6234/m4 + :maybe-skip-config: + :goals: debug + +.. hint:: + To utilize this feature, you'll need OpenOCD version 0.12 or higher. Due to the possibility of + older versions being available in package feeds, it's advisable to `build OpenOCD from source`_. + .. _PHYTEC AM62x Product Page: https://www.phytec.com/product/phycore-am62x/ @@ -143,3 +158,6 @@ port. .. _phyBOARD SD Card Booting Essentials: https://docs.phytec.com/projects/yocto-phycore-am62x/en/bsp-yocto-ampliphy-am62x-pd23.2.1/bootingessentials/sdcard.html + +.. _build OpenOCD from source: + https://docs.u-boot.org/en/latest/board/ti/k3.html#building-openocd-from-source diff --git a/boards/phytec/phyboard_lyra/support/openocd.cfg b/boards/phytec/phyboard_lyra/support/openocd.cfg new file mode 100644 index 0000000000000..39eed02c40156 --- /dev/null +++ b/boards/phytec/phyboard_lyra/support/openocd.cfg @@ -0,0 +1,7 @@ +# PHYTEC phyBOARD-Lyra AM62x M4/A53 +# +# Copyright (c) 2024, PHYTEC Messtechnik GmbH +# +# SPDX-License-Identifier: Apache-2.0 + +source [find board/ti_am625evm.cfg] From 59b2ef27395219558ad93e27d2f3946843e8aebe Mon Sep 17 00:00:00 2001 From: Prashanth S Date: Tue, 1 Aug 2023 11:11:19 +0530 Subject: [PATCH 2659/2849] drivers: timer: Add TI DM TIMER support TI Dual-Mode timer is used as the arch timer for systick on J721E R5 cores. Add DM Timer for systick timer support. Signed-off-by: Prashanth S Signed-off-by: Andrew Davis --- drivers/timer/CMakeLists.txt | 1 + drivers/timer/Kconfig | 1 + drivers/timer/Kconfig.ti_dm_timer | 13 ++ drivers/timer/ti_dmtimer.c | 167 ++++++++++++++++++++++ dts/bindings/timer/ti,am654-dmtimer.yaml | 16 +++ include/zephyr/drivers/timer/ti_dmtimer.h | 104 ++++++++++++++ 6 files changed, 302 insertions(+) create mode 100644 drivers/timer/Kconfig.ti_dm_timer create mode 100644 drivers/timer/ti_dmtimer.c create mode 100644 dts/bindings/timer/ti,am654-dmtimer.yaml create mode 100644 include/zephyr/drivers/timer/ti_dmtimer.h diff --git a/drivers/timer/CMakeLists.txt b/drivers/timer/CMakeLists.txt index 659d86df80142..ac5bac6c244ad 100644 --- a/drivers/timer/CMakeLists.txt +++ b/drivers/timer/CMakeLists.txt @@ -32,6 +32,7 @@ zephyr_library_sources_ifdef(CONFIG_RISCV_MACHINE_TIMER riscv_machine_timer.c) zephyr_library_sources_ifdef(CONFIG_RV32M1_LPTMR_TIMER rv32m1_lptmr_timer.c) zephyr_library_sources_ifdef(CONFIG_SAM0_RTC_TIMER sam0_rtc_timer.c) zephyr_library_sources_ifdef(CONFIG_STM32_LPTIM_TIMER stm32_lptim_timer.c) +zephyr_library_sources_ifdef(CONFIG_TI_DM_TIMER ti_dmtimer.c) zephyr_library_sources_ifdef(CONFIG_XLNX_PSTTC_TIMER xlnx_psttc_timer.c) zephyr_library_sources_ifdef(CONFIG_XTENSA_TIMER xtensa_sys_timer.c) zephyr_library_sources_ifdef(CONFIG_SMARTBOND_TIMER smartbond_timer.c) diff --git a/drivers/timer/Kconfig b/drivers/timer/Kconfig index 69eb00cbc5e28..3343f78d79ce0 100644 --- a/drivers/timer/Kconfig +++ b/drivers/timer/Kconfig @@ -92,6 +92,7 @@ source "drivers/timer/Kconfig.rv32m1_lptmr" source "drivers/timer/Kconfig.sam0_rtc" source "drivers/timer/Kconfig.smartbond" source "drivers/timer/Kconfig.stm32_lptim" +source "drivers/timer/Kconfig.ti_dm_timer" source "drivers/timer/Kconfig.xlnx_psttc" source "drivers/timer/Kconfig.xtensa" source "drivers/timer/Kconfig.mtk_adsp" diff --git a/drivers/timer/Kconfig.ti_dm_timer b/drivers/timer/Kconfig.ti_dm_timer new file mode 100644 index 0000000000000..42b86e5c6ef8f --- /dev/null +++ b/drivers/timer/Kconfig.ti_dm_timer @@ -0,0 +1,13 @@ +# Copyright (C) 2023 BeagleBoard.org Foundation +# Copyright (C) 2023 S Prashanth +# +# SPDX-License-Identifier: Apache-2.0 + +config TI_DM_TIMER + bool "TI Dual-Mode Timer" + default y + depends on DT_HAS_TI_AM654_TIMER_ENABLED + select TICKLESS_CAPABLE + help + This module implements a kernel device driver for TI Dual-Mode timer. This + driver provides system tick interface. diff --git a/drivers/timer/ti_dmtimer.c b/drivers/timer/ti_dmtimer.c new file mode 100644 index 0000000000000..7b04b92788a21 --- /dev/null +++ b/drivers/timer/ti_dmtimer.c @@ -0,0 +1,167 @@ +/* Copyright (C) 2023 BeagleBoard.org Foundation + * Copyright (C) 2023 S Prashanth + * Copyright (c) 2024 Texas Instruments Incorporated + * Andrew Davis + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include + +#include + +#define DT_DRV_COMPAT ti_am654_timer + +#define TIMER_BASE_ADDR DT_INST_REG_ADDR(0) + +#define TIMER_IRQ_NUM DT_INST_IRQN(0) +#define TIMER_IRQ_PRIO DT_INST_IRQ(0, priority) +#define TIMER_IRQ_FLAGS DT_INST_IRQ(0, flags) + +#define CYC_PER_TICK ((uint32_t)(sys_clock_hw_cycles_per_sec() \ + / CONFIG_SYS_CLOCK_TICKS_PER_SEC)) + +#define MAX_TICKS ((k_ticks_t)(UINT32_MAX / CYC_PER_TICK) - 1) + +static struct k_spinlock lock; + +static uint32_t last_cycle; + +#define TI_DM_TIMER_READ(reg) sys_read32(TIMER_BASE_ADDR + TI_DM_TIMER_ ## reg) + +#define TI_DM_TIMER_MASK(reg) TI_DM_TIMER_ ## reg ## _MASK +#define TI_DM_TIMER_SHIFT(reg) TI_DM_TIMER_ ## reg ## _SHIFT +#define TI_DM_TIMER_WRITE(data, reg, bits) \ + ti_dm_timer_write_masks(data, \ + TIMER_BASE_ADDR + TI_DM_TIMER_ ## reg, \ + TI_DM_TIMER_MASK(reg ## _ ## bits), \ + TI_DM_TIMER_SHIFT(reg ## _ ## bits)) + +static void ti_dm_timer_write_masks(uint32_t data, uint32_t reg, uint32_t mask, uint32_t shift) +{ + uint32_t reg_val; + + reg_val = sys_read32(reg); + reg_val = (reg_val & ~(mask)) | (data << shift); + sys_write32(reg_val, reg); +} + +static void ti_dmtimer_isr(void *data) +{ + /* If no pending event */ + if (!TI_DM_TIMER_READ(IRQSTATUS)) + return; + + k_spinlock_key_t key = k_spin_lock(&lock); + + uint32_t curr_cycle = TI_DM_TIMER_READ(TCRR); + uint32_t delta_cycles = curr_cycle - last_cycle; + uint32_t delta_ticks = delta_cycles / CYC_PER_TICK; + + last_cycle = curr_cycle; + + /* ACK match interrupt */ + TI_DM_TIMER_WRITE(1, IRQSTATUS, MAT_IT_FLAG); + + if (!IS_ENABLED(CONFIG_TICKLESS_KERNEL)) { + /* Setup next match time */ + uint64_t next_cycle = curr_cycle + CYC_PER_TICK; + + TI_DM_TIMER_WRITE(next_cycle, TMAR, COMPARE_VALUE); + } + + k_spin_unlock(&lock, key); + + sys_clock_announce(delta_ticks); +} + +void sys_clock_set_timeout(int32_t ticks, bool idle) +{ + ARG_UNUSED(idle); + if (!IS_ENABLED(CONFIG_TICKLESS_KERNEL)) { + /* Not supported on tickful kernels */ + return; + } + + ticks = (ticks == K_TICKS_FOREVER) ? MAX_TICKS : ticks; + ticks = CLAMP(ticks, 1, (int32_t)MAX_TICKS); + + k_spinlock_key_t key = k_spin_lock(&lock); + + /* Setup next match time */ + uint32_t curr_cycle = TI_DM_TIMER_READ(TCRR); + uint32_t next_cycle = curr_cycle + (ticks * CYC_PER_TICK); + + TI_DM_TIMER_WRITE(next_cycle, TMAR, COMPARE_VALUE); + + k_spin_unlock(&lock, key); +} + +uint32_t sys_clock_cycle_get_32(void) +{ + k_spinlock_key_t key = k_spin_lock(&lock); + + uint32_t curr_cycle = TI_DM_TIMER_READ(TCRR); + + k_spin_unlock(&lock, key); + + return curr_cycle; +} + +unsigned int sys_clock_elapsed(void) +{ + if (!IS_ENABLED(CONFIG_TICKLESS_KERNEL)) { + /* Always return 0 for tickful kernel system */ + return 0; + } + + k_spinlock_key_t key = k_spin_lock(&lock); + + uint32_t curr_cycle = TI_DM_TIMER_READ(TCRR); + uint32_t delta_cycles = curr_cycle - last_cycle; + uint32_t delta_ticks = delta_cycles / CYC_PER_TICK; + + k_spin_unlock(&lock, key); + + return delta_ticks; +} + +static int sys_clock_driver_init(void) +{ + last_cycle = 0; + + IRQ_CONNECT(TIMER_IRQ_NUM, TIMER_IRQ_PRIO, ti_dmtimer_isr, NULL, TIMER_IRQ_FLAGS); + + /* Select autoreload mode */ + TI_DM_TIMER_WRITE(1, TCLR, AR); + + /* Enable match interrupt */ + TI_DM_TIMER_WRITE(1, IRQENABLE_SET, MAT_EN_FLAG); + + /* Load timer counter value */ + TI_DM_TIMER_WRITE(0, TCRR, TIMER_COUNTER); + + /* Load timer load value */ + TI_DM_TIMER_WRITE(0, TLDR, LOAD_VALUE); + + /* Load timer compare value */ + TI_DM_TIMER_WRITE(CYC_PER_TICK, TMAR, COMPARE_VALUE); + + /* Enable compare mode */ + TI_DM_TIMER_WRITE(1, TCLR, CE); + + /* Start the timer */ + TI_DM_TIMER_WRITE(1, TCLR, ST); + + irq_enable(TIMER_IRQ_NUM); + + return 0; +} + +SYS_INIT(sys_clock_driver_init, PRE_KERNEL_2, + CONFIG_SYSTEM_CLOCK_INIT_PRIORITY); diff --git a/dts/bindings/timer/ti,am654-dmtimer.yaml b/dts/bindings/timer/ti,am654-dmtimer.yaml new file mode 100644 index 0000000000000..f2fc8167aba51 --- /dev/null +++ b/dts/bindings/timer/ti,am654-dmtimer.yaml @@ -0,0 +1,16 @@ +# Copyright (C) 2023 BeagleBoard.org Foundation +# Copyright (C) 2023 S Prashanth +# SPDX-License-Identifier: Apache-2.0 + +description: TI Dual-Mode Timer + +compatible: "ti,am654-timer" + +include: base.yaml + +properties: + reg: + required: true + + interrupts: + required: true diff --git a/include/zephyr/drivers/timer/ti_dmtimer.h b/include/zephyr/drivers/timer/ti_dmtimer.h new file mode 100644 index 0000000000000..95f39390fc1f0 --- /dev/null +++ b/include/zephyr/drivers/timer/ti_dmtimer.h @@ -0,0 +1,104 @@ +/* Copyright (C) 2023 BeagleBoard.org Foundation + * Copyright (C) 2023 S Prashanth + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_DRIVERS_TIMERS_TI_DMTIMER_H_ +#define ZEPHYR_DRIVERS_TIMERS_TI_DMTIMER_H_ + +#include + +#define TI_DM_TIMER_TIDR (0x00) +#define TI_DM_TIMER_TIOCP_CFG (0x10) +#define TI_DM_TIMER_IRQ_EOI (0x20) +#define TI_DM_TIMER_IRQSTATUS_RAW (0x24) +#define TI_DM_TIMER_IRQSTATUS (0x28) /* Interrupt status register */ +#define TI_DM_TIMER_IRQENABLE_SET (0x2c) /* Interrupt enable register */ +#define TI_DM_TIMER_IRQENABLE_CLR (0x30) /* Interrupt disable register */ +#define TI_DM_TIMER_IRQWAKEEN (0x34) +#define TI_DM_TIMER_TCLR (0x38) /* Control register */ +#define TI_DM_TIMER_TCRR (0x3c) /* Counter register */ +#define TI_DM_TIMER_TLDR (0x40) /* Load register */ +#define TI_DM_TIMER_TTGR (0x44) +#define TI_DM_TIMER_TWPS (0x48) +#define TI_DM_TIMER_TMAR (0x4c) /* Match register */ +#define TI_DM_TIMER_TCAR1 (0x50) +#define TI_DM_TIMER_TSICR (0x54) +#define TI_DM_TIMER_TCAR2 (0x58) +#define TI_DM_TIMER_TPIR (0x5c) +#define TI_DM_TIMER_TNIR (0x60) +#define TI_DM_TIMER_TCVR (0x64) +#define TI_DM_TIMER_TOCR (0x68) +#define TI_DM_TIMER_TOWR (0x6c) + +#define TI_DM_TIMER_IRQSTATUS_MAT_IT_FLAG_SHIFT (0) +#define TI_DM_TIMER_IRQSTATUS_MAT_IT_FLAG_MASK (0x00000001) + +#define TI_DM_TIMER_IRQSTATUS_OVF_IT_FLAG_SHIFT (1) +#define TI_DM_TIMER_IRQSTATUS_OVF_IT_FLAG_MASK (0x00000002) + +#define TI_DM_TIMER_IRQSTATUS_TCAR_IT_FLAG_SHIFT (2) +#define TI_DM_TIMER_IRQSTATUS_TCAR_IT_FLAG_MASK (0x00000004) + +#define TI_DM_TIMER_IRQENABLE_SET_MAT_EN_FLAG_SHIFT (0) +#define TI_DM_TIMER_IRQENABLE_SET_MAT_EN_FLAG_MASK (0x00000001) + +#define TI_DM_TIMER_IRQENABLE_SET_OVF_EN_FLAG_SHIFT (1) +#define TI_DM_TIMER_IRQENABLE_SET_OVF_EN_FLAG_MASK (0x00000002) + +#define TI_DM_TIMER_IRQENABLE_SET_TCAR_EN_FLAG_SHIFT (2) +#define TI_DM_TIMER_IRQENABLE_SET_TCAR_EN_FLAG_MASK (0x00000004) + +#define TI_DM_TIMER_IRQENABLE_CLR_MAT_EN_FLAG_SHIFT (0) +#define TI_DM_TIMER_IRQENABLE_CLR_MAT_EN_FLAG_MASK (0x00000001) + +#define TI_DM_TIMER_IRQENABLE_CLR_OVF_EN_FLAG_SHIFT (1) +#define TI_DM_TIMER_IRQENABLE_CLR_OVF_EN_FLAG_MASK (0x00000002) + +#define TI_DM_TIMER_IRQENABLE_CLR_TCAR_EN_FLAG_SHIFT (2) +#define TI_DM_TIMER_IRQENABLE_CLR_TCAR_EN_FLAG_MASK (0x00000004) + +#define TI_DM_TIMER_TCLR_ST_SHIFT (0) +#define TI_DM_TIMER_TCLR_ST_MASK (0x00000001) + +#define TI_DM_TIMER_TCLR_AR_SHIFT (1) +#define TI_DM_TIMER_TCLR_AR_MASK (0x00000002) + +#define TI_DM_TIMER_TCLR_PTV_SHIFT (2) +#define TI_DM_TIMER_TCLR_PTV_MASK (0x0000001c) + +#define TI_DM_TIMER_TCLR_PRE_SHIFT (5) +#define TI_DM_TIMER_TCLR_PRE_MASK (0x00000020) + +#define TI_DM_TIMER_TCLR_CE_SHIFT (6) +#define TI_DM_TIMER_TCLR_CE_MASK (0x00000040) + +#define TI_DM_TIMER_TCLR_SCPWM_SHIFT (7) +#define TI_DM_TIMER_TCLR_SCPWM_MASK (0x00000080) + +#define TI_DM_TIMER_TCLR_TCM_SHIFT (8) +#define TI_DM_TIMER_TCLR_TCM_MASK (0x00000300) + +#define TI_DM_TIMER_TCLR_TRG_SHIFT (10) +#define TI_DM_TIMER_TCLR_TRG_MASK (0x00000c00) + +#define TI_DM_TIMER_TCLR_PT_SHIFT (12) +#define TI_DM_TIMER_TCLR_PT_MASK (0x00001000) + +#define TI_DM_TIMER_TCLR_CAPT_MODE_SHIFT (13) +#define TI_DM_TIMER_TCLR_CAPT_MODE_MASK (0x00002000) + +#define TI_DM_TIMER_TCLR_GPO_CFG_SHIFT (14) +#define TI_DM_TIMER_TCLR_GPO_CFG_MASK (0x00004000) + +#define TI_DM_TIMER_TCRR_TIMER_COUNTER_SHIFT (0) +#define TI_DM_TIMER_TCRR_TIMER_COUNTER_MASK (0xffffffff) + +#define TI_DM_TIMER_TLDR_LOAD_VALUE_SHIFT (0) +#define TI_DM_TIMER_TLDR_LOAD_VALUE_MASK (0xffffffff) + +#define TI_DM_TIMER_TMAR_COMPARE_VALUE_SHIFT (0) +#define TI_DM_TIMER_TMAR_COMPARE_VALUE_MASK (0xffffffff) + +#endif /* ZEPHYR_DRIVERS_TIMERS_TI_DMTIMER_H_ */ From 644f6b6e979bda76924e4ccdde38233476e2dda5 Mon Sep 17 00:00:00 2001 From: Torsten Rasmussen Date: Wed, 17 Apr 2024 09:41:24 +0200 Subject: [PATCH 2660/2849] doc: rpi_pico update to cmsis-dap Follow-up: #59076 The PR#59076 updated the board.cmake to use cmsis-dap instead of picoprobe but without updating the documentation. This commit updates the board documentation to match the code changes. Signed-off-by: Torsten Rasmussen --- boards/raspberrypi/rpi_pico/doc/index.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/boards/raspberrypi/rpi_pico/doc/index.rst b/boards/raspberrypi/rpi_pico/doc/index.rst index 8db18d96f043b..a2c3468e34f04 100644 --- a/boards/raspberrypi/rpi_pico/doc/index.rst +++ b/boards/raspberrypi/rpi_pico/doc/index.rst @@ -179,7 +179,7 @@ Here is an example of building and flashing the :zephyr:code-sample:`blinky` app Using OpenOCD ------------- -To use PicoProbe, You must configure **udev**. +To use CMSIS-DAP, You must configure **udev**. Create a file in /etc/udev.rules.d with any name, and write the line below. @@ -206,7 +206,7 @@ Here is an example of building and flashing the :zephyr:code-sample:`blinky` app :zephyr-app: samples/basic/blinky :board: rpi_pico :goals: build flash - :gen-args: -DOPENOCD=/usr/local/bin/openocd -DOPENOCD_DEFAULT_PATH=/usr/local/share/openocd/scripts -DRPI_PICO_DEBUG_ADAPTER=picoprobe + :gen-args: -DOPENOCD=/usr/local/bin/openocd -DOPENOCD_DEFAULT_PATH=/usr/local/share/openocd/scripts -DRPI_PICO_DEBUG_ADAPTER=cmsis-dap Set the environment variables **OPENOCD** to `/usr/local/bin/openocd` and **OPENOCD_DEFAULT_PATH** to `/usr/local/share/openocd/scripts`. This should work @@ -215,9 +215,9 @@ This configuration also works with an environment that is set up by the `pico_se **RPI_PICO_DEBUG_ADAPTER** specifies what debug adapter is used for debugging. -If **RPI_PICO_DEBUG_ADAPTER** was not assigned, `picoprobe` is used by default. +If **RPI_PICO_DEBUG_ADAPTER** was not assigned, `cmsis-dap` is used by default. The other supported adapters are `raspberrypi-swd`, `jlink` and `blackmagicprobe`. -How to connect `picoprobe` and `raspberrypi-swd` is described in `Getting Started with Raspberry Pi Pico`_. +How to connect `cmsis-dap` and `raspberrypi-swd` is described in `Getting Started with Raspberry Pi Pico`_. Any other SWD debug adapter maybe also work with this configuration. The value of **RPI_PICO_DEBUG_ADAPTER** is cached, so it can be omitted from From 1db7caae56a26b88d01eac82ac405544d50737be Mon Sep 17 00:00:00 2001 From: Paulo Santos Date: Tue, 23 Apr 2024 16:21:57 -0300 Subject: [PATCH 2661/2849] kernel: update k_work_schedule_for_queue() docstring This commit updates the missing retval from the underlying call of `submit_to_queue_locked()` when the work was running and has been queued to the queue that was running it. Signed-off-by: Paulo Santos --- include/zephyr/kernel.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/zephyr/kernel.h b/include/zephyr/kernel.h index 8b25d4036d203..7be3ea83d4621 100644 --- a/include/zephyr/kernel.h +++ b/include/zephyr/kernel.h @@ -3632,6 +3632,8 @@ static inline k_ticks_t k_work_delayable_remaining_get( * * @retval 0 if work was already scheduled or submitted. * @retval 1 if work has been scheduled. + * @retval 2 if @p delay is @c K_NO_WAIT and work + * was running and has been queued to the queue that was running it. * @retval -EBUSY if @p delay is @c K_NO_WAIT and * k_work_submit_to_queue() fails with this code. * @retval -EINVAL if @p delay is @c K_NO_WAIT and From 7fb4a748b59ec0ba86a79de0228e12c46aa7bf21 Mon Sep 17 00:00:00 2001 From: Hess Nathan Date: Mon, 29 Apr 2024 14:57:53 +0200 Subject: [PATCH 2662/2849] coding guidelines: comply with MISRA Rule 21.15 - made explicit the copied data type Signed-off-by: Hess Nathan --- lib/os/cbprintf_packaged.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/os/cbprintf_packaged.c b/lib/os/cbprintf_packaged.c index 8b167dfd4da14..d488e8a7233f4 100644 --- a/lib/os/cbprintf_packaged.c +++ b/lib/os/cbprintf_packaged.c @@ -436,7 +436,7 @@ int cbvprintf_package(void *packaged, size_t len, uint32_t flags, return -ENOSPC; } if (Z_CBPRINTF_VA_STACK_LL_DBL_MEMCPY) { - memcpy(buf, &v, size); + memcpy(buf, (uint8_t *)&v, size); } else if (fmt[-1] == 'L') { *(long double *)buf = v.ld; } else { @@ -583,7 +583,7 @@ int cbvprintf_package(void *packaged, size_t len, uint32_t flags, return -ENOSPC; } if (Z_CBPRINTF_VA_STACK_LL_DBL_MEMCPY) { - memcpy(buf, &v, size); + memcpy(buf, (uint8_t *)&v, size); } else if (fmt[-1] == 'L') { *(long double *)buf = v.ld; } else { @@ -699,7 +699,7 @@ int cbvprintf_package(void *packaged, size_t len, uint32_t flags, if (buf0 != NULL) { if (Z_CBPRINTF_VA_STACK_LL_DBL_MEMCPY) { - memcpy(buf, &v, sizeof(long long)); + memcpy(buf, (uint8_t *)&v, sizeof(long long)); } else { *(long long *)buf = v; } @@ -796,7 +796,7 @@ int cbvprintf_package(void *packaged, size_t len, uint32_t flags, /* store the pointer position prefix */ *buf++ = str_ptr_pos[i]; /* copy the string with its terminating '\0' */ - memcpy(buf, s, size); + memcpy(buf, (uint8_t *)s, size); buf += size; } From 974bad62428473f5805103dfe1763f486806b81f Mon Sep 17 00:00:00 2001 From: Hess Nathan Date: Thu, 2 May 2024 11:23:59 +0200 Subject: [PATCH 2663/2849] coding guidelines: comply with MISRA Rule 12.1. -added parentheses verifying lack of ambiguities Signed-off-by: Hess Nathan --- lib/heap/heap.c | 4 ++-- lib/heap/heap.h | 2 +- lib/heap/heap_validate.c | 4 ++-- lib/libc/minimal/source/stdlib/strtol.c | 8 ++++---- lib/libc/minimal/source/stdlib/strtoul.c | 10 +++++----- lib/libc/minimal/source/stdout/stdout_console.c | 8 ++++---- lib/libc/minimal/source/string/string.c | 2 +- lib/os/cbprintf_complete.c | 8 ++++---- lib/os/cbprintf_packaged.c | 12 ++++++------ lib/os/fdtable.c | 4 ++-- lib/os/mutex.c | 4 ++-- lib/os/printk.c | 4 ++-- lib/os/sem.c | 11 +++++------ lib/posix/options/clock.c | 4 ++-- lib/utils/hex.c | 12 ++++++------ lib/utils/timeutil.c | 4 ++-- 16 files changed, 50 insertions(+), 51 deletions(-) diff --git a/lib/heap/heap.c b/lib/heap/heap.c index 45d684128a282..7fb6884c90ee2 100644 --- a/lib/heap/heap.c +++ b/lib/heap/heap.c @@ -265,7 +265,7 @@ void *sys_heap_alloc(struct sys_heap *heap, size_t bytes) struct z_heap *h = heap->heap; void *mem; - if (bytes == 0U || size_too_big(h, bytes)) { + if ((bytes == 0U) || size_too_big(h, bytes)) { return NULL; } @@ -323,7 +323,7 @@ void *sys_heap_aligned_alloc(struct sys_heap *heap, size_t align, size_t bytes) } __ASSERT((align & (align - 1)) == 0, "align must be a power of 2"); - if (bytes == 0 || size_too_big(h, bytes)) { + if ((bytes == 0) || size_too_big(h, bytes)) { return NULL; } diff --git a/lib/heap/heap.h b/lib/heap/heap.h index df11f18b9e0fd..1be3bd9139277 100644 --- a/lib/heap/heap.h +++ b/lib/heap/heap.h @@ -214,7 +214,7 @@ static inline void set_left_chunk_size(struct z_heap *h, chunkid_t c, static inline bool solo_free_header(struct z_heap *h, chunkid_t c) { - return big_heap(h) && chunk_size(h, c) == 1U; + return big_heap(h) && (chunk_size(h, c) == 1U); } static inline size_t chunk_header_bytes(struct z_heap *h) diff --git a/lib/heap/heap_validate.c b/lib/heap/heap_validate.c index af63c8cdd8c75..1a7172e56ae36 100644 --- a/lib/heap/heap_validate.c +++ b/lib/heap/heap_validate.c @@ -31,7 +31,7 @@ static bool in_bounds(struct z_heap *h, chunkid_t c) static bool valid_chunk(struct z_heap *h, chunkid_t c) { VALIDATE(chunk_size(h, c) > 0); - VALIDATE(c + chunk_size(h, c) <= h->end_chunk); + VALIDATE((c + chunk_size(h, c)) <= h->end_chunk); VALIDATE(in_bounds(h, c)); VALIDATE(right_chunk(h, left_chunk(h, c)) == c); VALIDATE(left_chunk(h, right_chunk(h, c)) == c); @@ -128,7 +128,7 @@ bool sys_heap_validate(struct sys_heap *heap) return false; } - if (empty && h->buckets[b].next != 0) { + if (empty && (h->buckets[b].next != 0)) { return false; } } diff --git a/lib/libc/minimal/source/stdlib/strtol.c b/lib/libc/minimal/source/stdlib/strtol.c index fd36fbefd4559..12c7a97585d5a 100644 --- a/lib/libc/minimal/source/stdlib/strtol.c +++ b/lib/libc/minimal/source/stdlib/strtol.c @@ -63,7 +63,7 @@ long strtol(const char *nptr, char **endptr, register int base) c = *s++; } - if ((base == 0 || base == 16) && + if (((base == 0) || (base == 16)) && c == '0' && (*s == 'x' || *s == 'X')) { c = s[1]; s += 2; @@ -71,7 +71,7 @@ long strtol(const char *nptr, char **endptr, register int base) } if (base == 0) { - base = c == '0' ? 8 : 10; + base = (c == '0') ? 8 : 10; } /* @@ -105,7 +105,7 @@ long strtol(const char *nptr, char **endptr, register int base) if (c >= base) { break; } - if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) { + if ((any < 0) || (acc > cutoff) || ((acc == cutoff) && (c > cutlim))) { any = -1; } else { any = 1; @@ -122,7 +122,7 @@ long strtol(const char *nptr, char **endptr, register int base) } if (endptr != NULL) { - *endptr = (char *)(any ? s - 1 : nptr); + *endptr = (char *)(any ? (s - 1) : nptr); } return acc; } diff --git a/lib/libc/minimal/source/stdlib/strtoul.c b/lib/libc/minimal/source/stdlib/strtoul.c index 193c96e83e315..5908d4080c8e4 100644 --- a/lib/libc/minimal/source/stdlib/strtoul.c +++ b/lib/libc/minimal/source/stdlib/strtoul.c @@ -61,15 +61,15 @@ unsigned long strtoul(const char *nptr, char **endptr, register int base) c = *s++; } - if ((base == 0 || base == 16) && - c == '0' && (*s == 'x' || *s == 'X')) { + if (((base == 0) || (base == 16)) && + (c == '0') && ((*s == 'x') || (*s == 'X'))) { c = s[1]; s += 2; base = 16; } if (base == 0) { - base = c == '0' ? 8 : 10; + base = (c == '0') ? 8 : 10; } cutoff = (unsigned long)ULONG_MAX / (unsigned long)base; @@ -85,7 +85,7 @@ unsigned long strtoul(const char *nptr, char **endptr, register int base) if (c >= base) { break; } - if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) { + if ((any < 0) || (acc > cutoff) || ((acc == cutoff) && (c > cutlim))) { any = -1; } else { any = 1; @@ -100,7 +100,7 @@ unsigned long strtoul(const char *nptr, char **endptr, register int base) acc = -acc; } if (endptr != NULL) { - *endptr = (char *)(any ? s - 1 : nptr); + *endptr = (char *)(any ? (s - 1) : nptr); } return acc; } diff --git a/lib/libc/minimal/source/stdout/stdout_console.c b/lib/libc/minimal/source/stdout/stdout_console.c index e3d5a374a53d4..e46f4a04ab41f 100644 --- a/lib/libc/minimal/source/stdout/stdout_console.c +++ b/lib/libc/minimal/source/stdout/stdout_console.c @@ -27,7 +27,7 @@ void __stdout_hook_install(int (*hook)(int c)) int z_impl_zephyr_fputc(int c, FILE *stream) { - return (stream == stdout || stream == stderr) ? _stdout_hook(c) : EOF; + return ((stream == stdout) || (stream == stderr)) ? _stdout_hook(c) : EOF; } #ifdef CONFIG_USERSPACE @@ -50,7 +50,7 @@ int fputs(const char *ZRESTRICT s, FILE *ZRESTRICT stream) ret = fwrite(s, 1, len, stream); - return len == ret ? 0 : EOF; + return (len == ret) ? 0 : EOF; } #undef putc @@ -72,7 +72,7 @@ size_t z_impl_zephyr_fwrite(const void *ZRESTRICT ptr, size_t size, size_t j; const unsigned char *p; - if ((stream != stdout && stream != stderr) || + if (((stream != stdout) && (stream != stderr)) || (nitems == 0) || (size == 0)) { return 0; } @@ -121,5 +121,5 @@ int puts(const char *s) return EOF; } - return fputc('\n', stdout) == EOF ? EOF : 0; + return (fputc('\n', stdout) == EOF) ? EOF : 0; } diff --git a/lib/libc/minimal/source/string/string.c b/lib/libc/minimal/source/string/string.c index 3582f5f5d75ad..041a393440065 100644 --- a/lib/libc/minimal/source/string/string.c +++ b/lib/libc/minimal/source/string/string.c @@ -43,7 +43,7 @@ char *strncpy(char *ZRESTRICT d, const char *ZRESTRICT s, size_t n) { char *dest = d; - while ((n > 0) && *s != '\0') { + while ((n > 0) && (*s != '\0')) { *d = *s; s++; d++; diff --git a/lib/os/cbprintf_complete.c b/lib/os/cbprintf_complete.c index 29e35f0276f3b..08779d15b66f7 100644 --- a/lib/os/cbprintf_complete.c +++ b/lib/os/cbprintf_complete.c @@ -1128,7 +1128,7 @@ static char *encode_float(double value, * representation and correct the precision and zero-pruning * in accordance with the ISO C rule. */ - if (decexp < (-4 + 1) || decexp > precision) { + if ((decexp < (-4 + 1)) || (decexp > precision)) { c += 'e' - 'g'; /* e or E */ if (precision > 0) { precision--; @@ -1173,7 +1173,7 @@ static char *encode_float(double value, if (c == 'f') { if (decexp > 0) { /* Emit the digits above the decimal point. */ - while (decexp > 0 && digit_count > 0) { + while ((decexp > 0) && (digit_count > 0)) { *buf++ = _get_digit(&fract, &digit_count); decexp--; } @@ -1192,7 +1192,7 @@ static char *encode_float(double value, *buf++ = '.'; } - if (decexp < 0 && precision > 0) { + if ((decexp < 0) && (precision > 0)) { conv->pad0_value = -decexp; if (conv->pad0_value > precision) { conv->pad0_value = precision; @@ -1218,7 +1218,7 @@ static char *encode_float(double value, } } - while (precision > 0 && digit_count > 0) { + while ((precision > 0) && (digit_count > 0)) { *buf++ = _get_digit(&fract, &digit_count); precision--; } diff --git a/lib/os/cbprintf_packaged.c b/lib/os/cbprintf_packaged.c index d488e8a7233f4..ab0c7d2fa051a 100644 --- a/lib/os/cbprintf_packaged.c +++ b/lib/os/cbprintf_packaged.c @@ -324,7 +324,7 @@ int cbvprintf_package(void *packaged, size_t len, uint32_t flags, * Otherwise we must ensure we can store at least * the pointer to the format string itself. */ - if (buf0 != NULL && BUF_OFFSET + sizeof(char *) > len) { + if ((buf0 != NULL) && (BUF_OFFSET + sizeof(char *)) > len) { return -ENOSPC; } @@ -432,7 +432,7 @@ int cbvprintf_package(void *packaged, size_t len, uint32_t flags, buf = (void *) ROUND_UP(buf, align); if (buf0 != NULL) { /* make sure it fits */ - if (BUF_OFFSET + size > len) { + if ((BUF_OFFSET + size) > len) { return -ENOSPC; } if (Z_CBPRINTF_VA_STACK_LL_DBL_MEMCPY) { @@ -605,7 +605,7 @@ int cbvprintf_package(void *packaged, size_t len, uint32_t flags, buf = (void *) ROUND_UP(buf, align); /* make sure the data fits */ - if (buf0 != NULL && BUF_OFFSET + size > len) { + if ((buf0 != NULL) && (BUF_OFFSET + size) > len) { return -ENOSPC; } @@ -717,7 +717,7 @@ int cbvprintf_package(void *packaged, size_t len, uint32_t flags, * worth of va_list, or about 127 arguments on a 64-bit system * (twice that on 32-bit systems). That ought to be good enough. */ - if (BUF_OFFSET / sizeof(int) > 255) { + if ((BUF_OFFSET / sizeof(int)) > 255) { __ASSERT(false, "too many format args"); return -EINVAL; } @@ -762,7 +762,7 @@ int cbvprintf_package(void *packaged, size_t len, uint32_t flags, uint8_t pos = str_ptr_pos[i] & STR_POS_MASK; /* make sure it fits */ - if (BUF_OFFSET + 1 > len) { + if ((BUF_OFFSET + 1) > len) { return -ENOSPC; } /* store the pointer position prefix */ @@ -790,7 +790,7 @@ int cbvprintf_package(void *packaged, size_t len, uint32_t flags, } /* make sure it fits */ - if (BUF_OFFSET + 1 + size > len) { + if ((BUF_OFFSET + 1 + size) > len) { return -ENOSPC; } /* store the pointer position prefix */ diff --git a/lib/os/fdtable.c b/lib/os/fdtable.c index b3c4ad13cd037..9343936e6deaf 100644 --- a/lib/os/fdtable.c +++ b/lib/os/fdtable.c @@ -117,7 +117,7 @@ static int _find_fd_entry(void) static int _check_fd(int fd) { - if (fd < 0 || fd >= ARRAY_SIZE(fdtable)) { + if ((fd < 0) || (fd >= ARRAY_SIZE(fdtable))) { errno = EBADF; return -1; } @@ -166,7 +166,7 @@ void *z_get_fd_obj(int fd, const struct fd_op_vtable *vtable, int err) entry = &fdtable[fd]; - if (vtable != NULL && entry->vtable != vtable) { + if ((vtable != NULL) && (entry->vtable != vtable)) { errno = err; return NULL; } diff --git a/lib/os/mutex.c b/lib/os/mutex.c index 9bfcf6368dd99..e8198cd86b3e9 100644 --- a/lib/os/mutex.c +++ b/lib/os/mutex.c @@ -14,7 +14,7 @@ static struct k_mutex *get_k_mutex(struct sys_mutex *mutex) struct k_object *obj; obj = k_object_find(mutex); - if (obj == NULL || obj->type != K_OBJ_SYS_MUTEX) { + if ((obj == NULL) || (obj->type != K_OBJ_SYS_MUTEX)) { return NULL; } @@ -56,7 +56,7 @@ int z_impl_z_sys_mutex_kernel_unlock(struct sys_mutex *mutex) { struct k_mutex *kernel_mutex = get_k_mutex(mutex); - if (kernel_mutex == NULL || kernel_mutex->lock_count == 0) { + if ((kernel_mutex == NULL) || (kernel_mutex->lock_count == 0)) { return -EINVAL; } diff --git a/lib/os/printk.c b/lib/os/printk.c index cb4073fed74af..793c659292d3d 100644 --- a/lib/os/printk.c +++ b/lib/os/printk.c @@ -225,12 +225,12 @@ struct str_context { static int str_out(int c, struct str_context *ctx) { - if (ctx->str == NULL || ctx->count >= ctx->max) { + if ((ctx->str == NULL) || (ctx->count >= ctx->max)) { ctx->count++; return c; } - if (ctx->count == ctx->max - 1) { + if (ctx->count == (ctx->max - 1)) { ctx->str[ctx->count++] = '\0'; } else { ctx->str[ctx->count++] = c; diff --git a/lib/os/sem.c b/lib/os/sem.c index b7676c929c6c4..bb1b3fdc6b8ab 100644 --- a/lib/os/sem.c +++ b/lib/os/sem.c @@ -38,8 +38,7 @@ static inline atomic_t bounded_inc(atomic_t *val, atomic_t minimum, break; } - new_value = old_value < minimum ? - minimum + 1 : old_value + 1; + new_value = ((old_value < minimum) ? minimum : old_value) + 1; } while (atomic_cas(val, old_value, new_value) == 0U); return old_value; @@ -48,8 +47,8 @@ static inline atomic_t bounded_inc(atomic_t *val, atomic_t minimum, int sys_sem_init(struct sys_sem *sem, unsigned int initial_count, unsigned int limit) { - if (sem == NULL || limit == SYS_SEM_MINIMUM || - initial_count > limit || limit > INT_MAX) { + if ((sem == NULL) || (limit == SYS_SEM_MINIMUM) || + (initial_count > limit) || (limit > INT_MAX)) { return -EINVAL; } @@ -103,7 +102,7 @@ unsigned int sys_sem_count_get(struct sys_sem *sem) { int value = atomic_get(&sem->futex.val); - return value > SYS_SEM_MINIMUM ? value : SYS_SEM_MINIMUM; + return (value > SYS_SEM_MINIMUM) ? value : SYS_SEM_MINIMUM; } #else int sys_sem_init(struct sys_sem *sem, unsigned int initial_count, @@ -126,7 +125,7 @@ int sys_sem_take(struct sys_sem *sem, k_timeout_t timeout) int ret_value = 0; ret_value = k_sem_take(&sem->kernel_sem, timeout); - if (ret_value == -EAGAIN || ret_value == -EBUSY) { + if ((ret_value == -EAGAIN) || (ret_value == -EBUSY)) { ret_value = -ETIMEDOUT; } diff --git a/lib/posix/options/clock.c b/lib/posix/options/clock.c index 5fa09daaae6d7..9ef0375803a17 100644 --- a/lib/posix/options/clock.c +++ b/lib/posix/options/clock.c @@ -201,7 +201,7 @@ static int __z_clock_nanosleep(clockid_t clock_id, int flags, const struct times k_spinlock_key_t key; const bool update_rmtp = rmtp != NULL; - if (!(clock_id == CLOCK_REALTIME || clock_id == CLOCK_MONOTONIC)) { + if (!((clock_id == CLOCK_REALTIME) || (clock_id == CLOCK_MONOTONIC))) { errno = EINVAL; return -1; } @@ -211,7 +211,7 @@ static int __z_clock_nanosleep(clockid_t clock_id, int flags, const struct times return -1; } - if (rqtp->tv_sec < 0 || rqtp->tv_nsec < 0 || rqtp->tv_nsec >= NSEC_PER_SEC) { + if ((rqtp->tv_sec < 0) || (rqtp->tv_nsec < 0) || (rqtp->tv_nsec >= NSEC_PER_SEC)) { errno = EINVAL; return -1; } diff --git a/lib/utils/hex.c b/lib/utils/hex.c index f65125e3c6a02..fe4e7351e8502 100644 --- a/lib/utils/hex.c +++ b/lib/utils/hex.c @@ -11,11 +11,11 @@ int char2hex(char c, uint8_t *x) { - if (c >= '0' && c <= '9') { + if ((c >= '0') && (c <= '9')) { *x = c - '0'; - } else if (c >= 'a' && c <= 'f') { + } else if ((c >= 'a') && (c <= 'f')) { *x = c - 'a' + 10; - } else if (c >= 'A' && c <= 'F') { + } else if ((c >= 'A') && (c <= 'F')) { *x = c - 'A' + 10; } else { return -EINVAL; @@ -39,7 +39,7 @@ int hex2char(uint8_t x, char *c) size_t bin2hex(const uint8_t *buf, size_t buflen, char *hex, size_t hexlen) { - if (hexlen < (buflen * 2U + 1U)) { + if (hexlen < ((buflen * 2U) + 1U)) { return 0; } @@ -60,7 +60,7 @@ size_t hex2bin(const char *hex, size_t hexlen, uint8_t *buf, size_t buflen) { uint8_t dec; - if (buflen < hexlen / 2U + hexlen % 2U) { + if (buflen < (hexlen / 2U + hexlen % 2U)) { return 0; } @@ -75,7 +75,7 @@ size_t hex2bin(const char *hex, size_t hexlen, uint8_t *buf, size_t buflen) } /* regular hex conversion */ - for (size_t i = 0; i < hexlen / 2U; i++) { + for (size_t i = 0; i < (hexlen / 2U); i++) { if (char2hex(hex[2U * i], &dec) < 0) { return 0; } diff --git a/lib/utils/timeutil.c b/lib/utils/timeutil.c index 980b2b5f14e06..10800198445ad 100644 --- a/lib/utils/timeutil.c +++ b/lib/utils/timeutil.c @@ -34,9 +34,9 @@ static int64_t time_days_from_civil(int64_t y, { y -= m <= 2; - int64_t era = (y >= 0 ? y : y - 399) / 400; + int64_t era = ((y >= 0) ? y : (y - 399)) / 400; unsigned int yoe = y - era * 400; - unsigned int doy = (153U * (m + (m > 2 ? -3 : 9)) + 2U) / 5U + d; + unsigned int doy = (153U * (m + ((m > 2) ? -3 : 9)) + 2U) / 5U + d; unsigned int doe = yoe * 365U + yoe / 4U - yoe / 100U + doy; return era * 146097 + (time_t)doe - 719468; From 5120744c8d11d4cb30ac4faf731b34f85bd9f875 Mon Sep 17 00:00:00 2001 From: Hess Nathan Date: Fri, 17 May 2024 15:50:24 +0200 Subject: [PATCH 2664/2849] lib: added blanks between operators To adhere to general code style, I added some blanks around operators Signed-off-by: Hess Nathan --- lib/heap/heap_info.c | 4 ++-- lib/libc/minimal/source/stdlib/atoi.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/heap/heap_info.c b/lib/heap/heap_info.c index 80640da2fd42a..c618af2ea0072 100644 --- a/lib/heap/heap_info.c +++ b/lib/heap/heap_info.c @@ -66,8 +66,8 @@ static void heap_print_info(struct z_heap *h, bool dump_chunks) overhead = total - free_bytes - allocated_bytes; printk("\n%zd free bytes, %zd allocated bytes, overhead = %zd bytes (%zd.%zd%%)\n", free_bytes, allocated_bytes, overhead, - (1000 * overhead + total/2) / total / 10, - (1000 * overhead + total/2) / total % 10); + (1000 * overhead + total / 2) / total / 10, + (1000 * overhead + total / 2) / total % 10); } void sys_heap_print_info(struct sys_heap *heap, bool dump_chunks) diff --git a/lib/libc/minimal/source/stdlib/atoi.c b/lib/libc/minimal/source/stdlib/atoi.c index 954f75036e143..a184f70f382b3 100644 --- a/lib/libc/minimal/source/stdlib/atoi.c +++ b/lib/libc/minimal/source/stdlib/atoi.c @@ -53,7 +53,7 @@ int atoi(const char *s) } /* Compute n as a negative number to avoid overflow on INT_MIN */ while (isdigit((unsigned char)*s) != 0) { - n = 10*n - (*s++ - '0'); + n = 10 * n - (*s++ - '0'); } return neg ? n : -n; } From 1bf5af7e897c729cae169d3f8fa65a1afcd5914f Mon Sep 17 00:00:00 2001 From: Reto Schneider Date: Thu, 2 May 2024 17:32:17 +0200 Subject: [PATCH 2665/2849] kernel: banner: Add option to clear screen on boot On each reboot, this option causes the serial output to start top-left on the users terminal, simplifying (human) parsing. Signed-off-by: Reto Schneider --- kernel/Kconfig | 6 ++++++ kernel/banner.c | 9 +++++++++ 2 files changed, 15 insertions(+) diff --git a/kernel/Kconfig b/kernel/Kconfig index 31658b90f3ba8..57c8b2997598c 100644 --- a/kernel/Kconfig +++ b/kernel/Kconfig @@ -467,6 +467,12 @@ config BOOT_DELAY achieved by waiting for DCD on the serial port--however, not all serial ports have DCD. +config BOOT_CLEAR_SCREEN + bool "Clear screen" + help + Use this option to clear the screen before printing anything else. + Using a VT100 enabled terminal on the client side is required for this to work. + config THREAD_MONITOR bool "Thread monitoring" help diff --git a/kernel/banner.c b/kernel/banner.c index 1d95f2b18350c..5cadda0a5e985 100644 --- a/kernel/banner.c +++ b/kernel/banner.c @@ -33,6 +33,15 @@ void boot_banner(void) k_busy_wait(CONFIG_BOOT_DELAY * USEC_PER_MSEC); #endif /* defined(CONFIG_BOOT_DELAY) && (CONFIG_BOOT_DELAY > 0) */ +#if defined(CONFIG_BOOT_CLEAR_SCREEN) + /* \x1b[ = escape sequence + * 3J = erase scrollback + * 2J = erase screen + * H = move cursor to top left + */ + printk("\x1b[3J\x1b[2J\x1b[H"); +#endif /* CONFIG_BOOT_CLEAR_SCREEN */ + #ifdef CONFIG_BOOT_BANNER printk("*** " CONFIG_BOOT_BANNER_STRING " " BANNER_VERSION BANNER_POSTFIX " ***\n"); #endif /* CONFIG_BOOT_BANNER */ From c9d0f15006abad499ba5c2721890cd55c8180ed2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20Cab=C3=A9?= Date: Tue, 4 Jun 2024 10:52:45 +0200 Subject: [PATCH 2666/2849] doc: mem_mgmt: Add missing definition for mem_mgmt doxygen group MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Avoid warning and properly list memory management APIs in Doxygen documentation by actually declaring the mem_mgmt doxygen group Signed-off-by: Benjamin Cabé --- doc/_doxygen/groups.dox | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/doc/_doxygen/groups.dox b/doc/_doxygen/groups.dox index c0c5ab1a7bec1..69a3b892637b7 100644 --- a/doc/_doxygen/groups.dox +++ b/doc/_doxygen/groups.dox @@ -73,4 +73,9 @@ @{ @} +@brief Memory Management APIs +@defgroup mem_mgmt Memory Management APIs +@{ +@} + */ From b29e8ff0d6b221d5987e6a54a7803e06952d2915 Mon Sep 17 00:00:00 2001 From: frei tycho Date: Wed, 5 Jun 2024 09:26:44 +0000 Subject: [PATCH 2667/2849] include: toolchain: added missing parenthesis - added missing parenthesis around macro argument expansion Signed-off-by: frei tycho --- include/zephyr/toolchain/gcc.h | 2 +- include/zephyr/toolchain/mwdt.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/zephyr/toolchain/gcc.h b/include/zephyr/toolchain/gcc.h index 99da187f9e40f..9af23fb219ea1 100644 --- a/include/zephyr/toolchain/gcc.h +++ b/include/zephyr/toolchain/gcc.h @@ -84,7 +84,7 @@ #elif !defined(__cplusplus) && \ (((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 6))) || \ (__STDC_VERSION__) >= 201100) -#define BUILD_ASSERT(EXPR, MSG...) _Static_assert(EXPR, "" MSG) +#define BUILD_ASSERT(EXPR, MSG...) _Static_assert((EXPR), "" MSG) #else #define BUILD_ASSERT(EXPR, MSG...) #endif diff --git a/include/zephyr/toolchain/mwdt.h b/include/zephyr/toolchain/mwdt.h index 0da5e7bbee57a..c4a142e4fb3b0 100644 --- a/include/zephyr/toolchain/mwdt.h +++ b/include/zephyr/toolchain/mwdt.h @@ -99,7 +99,7 @@ /* For cpp98 */ #define BUILD_ASSERT(EXPR, MSG...) #else -#define BUILD_ASSERT(EXPR, MSG...) _Static_assert(EXPR, "" MSG) +#define BUILD_ASSERT(EXPR, MSG...) _Static_assert((EXPR), "" MSG) #endif #define __builtin_arc_nop() _nop() From b1f2eb9a1105018bb1f8edf08464639ed5d5c8d6 Mon Sep 17 00:00:00 2001 From: Jeppe Odgaard Date: Wed, 14 Feb 2024 10:51:01 +0100 Subject: [PATCH 2668/2849] samples: drivers: adc: add nucleo_h563zi Add Nucleo H563ZI board support to ADC sample. Signed-off-by: Jeppe Odgaard --- .../adc/adc_dt/boards/nucleo_h563zi.overlay | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 samples/drivers/adc/adc_dt/boards/nucleo_h563zi.overlay diff --git a/samples/drivers/adc/adc_dt/boards/nucleo_h563zi.overlay b/samples/drivers/adc/adc_dt/boards/nucleo_h563zi.overlay new file mode 100644 index 0000000000000..ad80e9ac5871a --- /dev/null +++ b/samples/drivers/adc/adc_dt/boards/nucleo_h563zi.overlay @@ -0,0 +1,25 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright (c) 2024, Vitrolife A/S + */ + + / { + zephyr,user { + /* CN9 pin 1 */ + io-channels = <&adc1 3>; + }; +}; + +&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>; + }; +}; From af6d790d0e5f322d4f329764276bb105463c4310 Mon Sep 17 00:00:00 2001 From: Dong Wang Date: Wed, 12 Jun 2024 09:28:42 +0800 Subject: [PATCH 2669/2849] drivers: apic_tsc: add dependency of DYNAMIC_INTERRUPTS The reason is that this driver needs to call the function 'irq_connect_dynamic()' which is implemented with DYNAMIC_INTERRUPTS. Signed-off-by: Dong Wang --- drivers/timer/Kconfig.x86 | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/timer/Kconfig.x86 b/drivers/timer/Kconfig.x86 index 436439838f6eb..c0ff7b1f2b597 100644 --- a/drivers/timer/Kconfig.x86 +++ b/drivers/timer/Kconfig.x86 @@ -54,6 +54,7 @@ config APIC_TSC_DEADLINE_TIMER config APIC_TIMER_TSC bool "Local APIC timer using TSC time source" depends on !SMP + depends on DYNAMIC_INTERRUPTS select LOAPIC select TICKLESS_CAPABLE select TIMER_HAS_64BIT_CYCLE_COUNTER From d45605e6a3dfe68e43207d15e3bfc003cbfaa72f Mon Sep 17 00:00:00 2001 From: David Leach Date: Thu, 13 Jun 2024 22:40:44 -0500 Subject: [PATCH 2670/2849] drivers: apic_tsc: revert add dependency of DYNAMIC_INTERRUPTS PR #74127 introduced a dependency loop that appeared to not be caught by CI. Signed-off-by: David Leach --- drivers/timer/Kconfig.x86 | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/timer/Kconfig.x86 b/drivers/timer/Kconfig.x86 index c0ff7b1f2b597..436439838f6eb 100644 --- a/drivers/timer/Kconfig.x86 +++ b/drivers/timer/Kconfig.x86 @@ -54,7 +54,6 @@ config APIC_TSC_DEADLINE_TIMER config APIC_TIMER_TSC bool "Local APIC timer using TSC time source" depends on !SMP - depends on DYNAMIC_INTERRUPTS select LOAPIC select TICKLESS_CAPABLE select TIMER_HAS_64BIT_CYCLE_COUNTER From ff0635d7007d5747d959304cf9f96ec4e3bf48e2 Mon Sep 17 00:00:00 2001 From: Riku Karjalainen Date: Tue, 11 Jun 2024 16:14:49 +0300 Subject: [PATCH 2671/2849] drivers: flash: stm32: fix flash write error handling The stm32 flash driver returns success even though writing failed when instruction cache was enabled. Fix by not overriding error code when re-enabling instruction cache. Signed-off-by: Riku Karjalainen --- drivers/flash/flash_stm32l5x.c | 8 +++++++- drivers/flash/flash_stm32wbax.c | 8 +++++++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/drivers/flash/flash_stm32l5x.c b/drivers/flash/flash_stm32l5x.c index 59b649731e948..49e4259969f23 100644 --- a/drivers/flash/flash_stm32l5x.c +++ b/drivers/flash/flash_stm32l5x.c @@ -367,10 +367,16 @@ int flash_stm32_write_range(const struct device *dev, unsigned int offset, } if (icache_enabled) { + int rc2; + /* Since i-cache was disabled, this would start the * invalidation procedure, so wait for completion. */ - rc = icache_wait_for_invalidate_complete(); + rc2 = icache_wait_for_invalidate_complete(); + + if (!rc) { + rc = rc2; + } /* I-cache should be enabled only after the * invalidation is complete. diff --git a/drivers/flash/flash_stm32wbax.c b/drivers/flash/flash_stm32wbax.c index db158f71a9a27..8660d46c26500 100644 --- a/drivers/flash/flash_stm32wbax.c +++ b/drivers/flash/flash_stm32wbax.c @@ -262,10 +262,16 @@ int flash_stm32_write_range(const struct device *dev, unsigned int offset, } if (icache_enabled) { + int rc2; + /* Since i-cache was disabled, this would start the * invalidation procedure, so wait for completion. */ - rc = icache_wait_for_invalidate_complete(); + rc2 = icache_wait_for_invalidate_complete(); + + if (!rc) { + rc = rc2; + } /* I-cache should be enabled only after the * invalidation is complete. From 72fa07e0bc78f034ffeaade3e0d4a5782cf91e5a Mon Sep 17 00:00:00 2001 From: Dong Wang Date: Wed, 12 Jun 2024 15:42:16 +0800 Subject: [PATCH 2672/2849] manifest: hal_intel: update to lastest revision The update contains all SEDI driver enhancements ported from ISH code base for PV release. Signed-off-by: Dong Wang --- west.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/west.yml b/west.yml index 59a0ea444692a..5c85145297cf1 100644 --- a/west.yml +++ b/west.yml @@ -178,7 +178,7 @@ manifest: groups: - hal - name: hal_intel - revision: 7b4c25669f1513b0d6d6ee78ee42340d91958884 + revision: 0905a528623de56b1bedf817536321bcdbc0efae path: modules/hal/intel groups: - hal From c9a0ab25874f177813195dbafa1a37e2d686f9ab Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Wed, 12 Jun 2024 10:14:51 +0300 Subject: [PATCH 2673/2849] doc: migration-guide-3.7: Mention the removal of CONFIG_BT_NO_DRIVER Mention the removal of the BT_NO_DRIVER option, and explain how drivers are now expected to be enabled or disabled. Also group all bullet points related to the HCI API changes as a dedicated sub list. Signed-off-by: Johan Hedberg --- doc/releases/migration-guide-3.7.rst | 32 ++++++++++++++++------------ 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/doc/releases/migration-guide-3.7.rst b/doc/releases/migration-guide-3.7.rst index e6d6fdc114b84..c2053fdfa6085 100644 --- a/doc/releases/migration-guide-3.7.rst +++ b/doc/releases/migration-guide-3.7.rst @@ -241,20 +241,24 @@ Bluetooth HCI selects which driver instance to use as the controller by looking for a ``zephyr,bt-hci`` chosen property. The devicetree bindings for all HCI drivers derive from a common ``bt-hci.yaml`` base binding. - * As part of the new HCI driver API, the ``zephyr,bt-uart`` chosen property is no longer used, - rather the UART HCI drivers select their UART by looking for the parent devicetree node of the - HCI driver instance node. - * As part of the new HCI driver API, the ``zephyr,bt-hci-ipc`` chosen property is only used for - the controller side, whereas the HCI driver now relies on nodes with the compatible string - ``zephyr,bt-hci-ipc``. - * 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. + + * As part of the new HCI driver API, the ``zephyr,bt-uart`` chosen property is no longer used, + rather the UART HCI drivers select their UART by looking for the parent devicetree node of the + HCI driver instance node. + * As part of the new HCI driver API, the ``zephyr,bt-hci-ipc`` chosen property is only used for + the controller side, whereas the HCI driver now relies on nodes with the compatible string + ``zephyr,bt-hci-ipc``. + * The ``BT_NO_DRIVER`` Kconfig option was removed. HCI drivers are no-longer behind a Kconfig + choice, rather they can now be enabled and disabled independently, mostly based on their + respective devicetree node being enabled or not. + * 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 1c53726e80b866f3e5e6f9d855dd1230e9b58588 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Wed, 12 Jun 2024 10:23:46 +0300 Subject: [PATCH 2674/2849] Bluetooth: Host: Fix deprecation and versioning for HCI APIs Add versioning to the new HCI API so that it shows up officially as unstable, and add a reference to the new API from the old API. Signed-off-by: Johan Hedberg --- include/zephyr/drivers/bluetooth.h | 4 ++++ include/zephyr/drivers/bluetooth/hci_driver.h | 3 +++ 2 files changed, 7 insertions(+) diff --git a/include/zephyr/drivers/bluetooth.h b/include/zephyr/drivers/bluetooth.h index f447c76b79253..1492b647557d8 100644 --- a/include/zephyr/drivers/bluetooth.h +++ b/include/zephyr/drivers/bluetooth.h @@ -11,6 +11,10 @@ /** * @brief Bluetooth HCI APIs * @defgroup bt_hci_api Bluetooth HCI APIs + * + * @since 3.7 + * @version 0.2.0 + * * @ingroup bluetooth * @{ */ diff --git a/include/zephyr/drivers/bluetooth/hci_driver.h b/include/zephyr/drivers/bluetooth/hci_driver.h index 6f76889876e37..55063bf289799 100644 --- a/include/zephyr/drivers/bluetooth/hci_driver.h +++ b/include/zephyr/drivers/bluetooth/hci_driver.h @@ -12,6 +12,9 @@ /** * @brief HCI drivers + * + * @deprecated This is the old HCI driver API. Drivers should use @ref bt_hci_api instead. + * * @defgroup bt_hci_driver HCI drivers * @ingroup bluetooth * @{ From 5aeeae91e2f2952e104544c806a718b3a046de11 Mon Sep 17 00:00:00 2001 From: Anke Xiao Date: Wed, 12 Jun 2024 13:59:14 +0800 Subject: [PATCH 2675/2849] dts: arm: nxp: nxp_ke1xz.dtsi: add i2c periperal info The i2c driver is disabled by default, enabled under board folder for ke17z512 platform. Signed-off-by: Anke Xiao --- dts/arm/nxp/nxp_ke1xz.dtsi | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/dts/arm/nxp/nxp_ke1xz.dtsi b/dts/arm/nxp/nxp_ke1xz.dtsi index d3b55949e454f..9623d5a337353 100644 --- a/dts/arm/nxp/nxp_ke1xz.dtsi +++ b/dts/arm/nxp/nxp_ke1xz.dtsi @@ -9,6 +9,7 @@ #include #include #include +#include / { chosen { @@ -229,6 +230,28 @@ nxp,kinetis-port = <&portd>; }; }; + + lpi2c0: i2c@40066000 { + compatible = "nxp,imx-lpi2c"; + clock-frequency = ; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x40066000 0x1000>; + interrupts = <8 0>; + clocks = <&pcc 0x198 KINETIS_PCC_SRC_FIRC_ASYNC>; + status = "disabled"; + }; + + lpi2c1: i2c@40067000 { + compatible = "nxp,imx-lpi2c"; + clock-frequency = ; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x40067000 0x1000>; + interrupts = <9 0>; + clocks = <&pcc 0x19c KINETIS_PCC_SRC_FIRC_ASYNC>; + status = "disabled"; + }; }; }; From 89a0ff8f615a8a13ef97cbe3c20e2f399ebc97a9 Mon Sep 17 00:00:00 2001 From: Anke Xiao Date: Wed, 12 Jun 2024 14:05:36 +0800 Subject: [PATCH 2676/2849] soc: nxp: kinetis: soc.c: configure i2c driver clock Set the i2c driver clock source when it is Okay. Signed-off-by: Anke Xiao --- soc/nxp/kinetis/ke1xz/soc.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/soc/nxp/kinetis/ke1xz/soc.c b/soc/nxp/kinetis/ke1xz/soc.c index 3aeb5db419efb..b7069b7eae395 100644 --- a/soc/nxp/kinetis/ke1xz/soc.c +++ b/soc/nxp/kinetis/ke1xz/soc.c @@ -118,6 +118,14 @@ static ALWAYS_INLINE void clk_init(void) CLOCK_SetIpSrc(kCLOCK_Lpuart2, DT_CLOCKS_CELL(DT_NODELABEL(lpuart2), ip_source)); #endif +#if DT_NODE_HAS_STATUS(DT_NODELABEL(lpi2c0), okay) + CLOCK_SetIpSrc(kCLOCK_Lpi2c0, + DT_CLOCKS_CELL(DT_NODELABEL(lpi2c0), ip_source)); +#endif +#if DT_NODE_HAS_STATUS(DT_NODELABEL(lpi2c1), okay) + CLOCK_SetIpSrc(kCLOCK_Lpi2c1, + DT_CLOCKS_CELL(DT_NODELABEL(lpi2c1), ip_source)); +#endif } static int ke1xz_init(void) From fdf39a7ab7346fc617c864ef24ac88fea0ca5b15 Mon Sep 17 00:00:00 2001 From: Anke Xiao Date: Wed, 12 Jun 2024 14:15:57 +0800 Subject: [PATCH 2677/2849] boards: nxp: frdm_ke17z512: enable lpi2c0 and lpi2c1 driver Added lpi2c support to test i2c samples Signed-off-by: Anke Xiao --- boards/nxp/frdm_ke17z512/doc/index.rst | 3 +++ .../frdm_ke17z512/frdm_ke17z512-pinctrl.dtsi | 20 +++++++++++++++++++ boards/nxp/frdm_ke17z512/frdm_ke17z512.dts | 12 +++++++++++ boards/nxp/frdm_ke17z512/frdm_ke17z512.yaml | 1 + 4 files changed, 36 insertions(+) diff --git a/boards/nxp/frdm_ke17z512/doc/index.rst b/boards/nxp/frdm_ke17z512/doc/index.rst index d9dc4385a7980..46fe54c63d1ea 100644 --- a/boards/nxp/frdm_ke17z512/doc/index.rst +++ b/boards/nxp/frdm_ke17z512/doc/index.rst @@ -59,6 +59,9 @@ features: | UART | on-chip | uart polling; | | | | uart interrupt | +-----------+------------+-------------------------------------+ +| I2C | on-chip | I2C | ++-----------+------------+-------------------------------------+ + The default configuration can be found in the defconfig file: ``boards/nxp/frdm_ke17z512/frdm_ke17z512_defconfig``. diff --git a/boards/nxp/frdm_ke17z512/frdm_ke17z512-pinctrl.dtsi b/boards/nxp/frdm_ke17z512/frdm_ke17z512-pinctrl.dtsi index cea7e351c9eab..7d745ff8bf628 100644 --- a/boards/nxp/frdm_ke17z512/frdm_ke17z512-pinctrl.dtsi +++ b/boards/nxp/frdm_ke17z512/frdm_ke17z512-pinctrl.dtsi @@ -18,4 +18,24 @@ slew-rate = "slow"; }; }; + + lpi2c0_default: lpi2c0_default { + group0 { + pinmux = , + ; + bias-pull-up; + drive-strength = "low"; + slew-rate = "slow"; + }; + }; + + lpi2c1_default: lpi2c1_default { + group0 { + pinmux = , + ; + bias-pull-up; + drive-strength = "low"; + slew-rate = "slow"; + }; + }; }; diff --git a/boards/nxp/frdm_ke17z512/frdm_ke17z512.dts b/boards/nxp/frdm_ke17z512/frdm_ke17z512.dts index f1f759b9e3132..704ef4811bc1f 100644 --- a/boards/nxp/frdm_ke17z512/frdm_ke17z512.dts +++ b/boards/nxp/frdm_ke17z512/frdm_ke17z512.dts @@ -74,3 +74,15 @@ &gpioe { status = "okay"; }; + +&lpi2c0 { + status = "okay"; + pinctrl-0 = <&lpi2c0_default>; + pinctrl-names = "default"; +}; + +&lpi2c1 { + status = "okay"; + pinctrl-0 = <&lpi2c1_default>; + pinctrl-names = "default"; +}; diff --git a/boards/nxp/frdm_ke17z512/frdm_ke17z512.yaml b/boards/nxp/frdm_ke17z512/frdm_ke17z512.yaml index 4fb3e6f1ad355..f836b931e1e4c 100644 --- a/boards/nxp/frdm_ke17z512/frdm_ke17z512.yaml +++ b/boards/nxp/frdm_ke17z512/frdm_ke17z512.yaml @@ -17,4 +17,5 @@ toolchain: supported: - gpio - uart + - i2c vendor: nxp From 4141b7cb649f3461ae06b37ebd3819700d608eff Mon Sep 17 00:00:00 2001 From: Anke Xiao Date: Wed, 12 Jun 2024 14:21:42 +0800 Subject: [PATCH 2678/2849] tests: drivers: i2c: add i2c support for NXP FRDM-KE17Z512 Added support for NXP FRDM-KE17Z512, and tested i2c_target_api sample. Signed-off-by: Anke Xiao --- .../i2c_target_api/boards/frdm_ke17z512.conf | 2 ++ .../boards/frdm_ke17z512.overlay | 26 +++++++++++++++++++ 2 files changed, 28 insertions(+) create mode 100644 tests/drivers/i2c/i2c_target_api/boards/frdm_ke17z512.conf create mode 100644 tests/drivers/i2c/i2c_target_api/boards/frdm_ke17z512.overlay diff --git a/tests/drivers/i2c/i2c_target_api/boards/frdm_ke17z512.conf b/tests/drivers/i2c/i2c_target_api/boards/frdm_ke17z512.conf new file mode 100644 index 0000000000000..f3d64527b85f3 --- /dev/null +++ b/tests/drivers/i2c/i2c_target_api/boards/frdm_ke17z512.conf @@ -0,0 +1,2 @@ +CONFIG_I2C=y +CONFIG_I2C_TARGET=y diff --git a/tests/drivers/i2c/i2c_target_api/boards/frdm_ke17z512.overlay b/tests/drivers/i2c/i2c_target_api/boards/frdm_ke17z512.overlay new file mode 100644 index 0000000000000..cd4ec6bb5de60 --- /dev/null +++ b/tests/drivers/i2c/i2c_target_api/boards/frdm_ke17z512.overlay @@ -0,0 +1,26 @@ +/* + * Copyright 2024 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* To test this sample, connect + * LPI2C0 SCL(J2-20) --> LPI2C1 SCL(J2-10) + * LPI2C0 SDA(J2-18) --> LPI2C1 SDA(J2-12) + */ + +&lpi2c0 { + eeprom0: eeprom@54 { + compatible = "zephyr,i2c-target-eeprom"; + reg = <0x54>; + size = <256>; + }; +}; + +&lpi2c1 { + eeprom1: eeprom@56 { + compatible = "zephyr,i2c-target-eeprom"; + reg = <0x56>; + size = <256>; + }; +}; From 801028b763e205d8f7696fdd81959985048aad38 Mon Sep 17 00:00:00 2001 From: Declan Snyder Date: Mon, 10 Jun 2024 11:24:47 -0500 Subject: [PATCH 2679/2849] dts: nxp,lpc-gpio: Fix binding to group ports LPC GPIO binding was wrong in that the reg address on the simple soc bus was given as an index of the gpio ports within a gpio controller. Fix this by putting the GPIO node on the simple bus as a single node with the correct base address, and make the ports children of this node. Change the driver to get the port number from the reg address instead of a custom property, and get base address from DT instead of the SDK macro definition. Signed-off-by: Declan Snyder --- drivers/gpio/Kconfig.mcux_lpc | 2 +- drivers/gpio/gpio_mcux_lpc.c | 6 +- dts/arm/nxp/nxp_lpc51u68.dtsi | 31 ++++---- dts/arm/nxp/nxp_lpc54xxx.dtsi | 31 ++++---- dts/arm/nxp/nxp_lpc55S0x_common.dtsi | 30 ++++---- dts/arm/nxp/nxp_lpc55S1x_common.dtsi | 31 ++++---- dts/arm/nxp/nxp_lpc55S2x_common.dtsi | 31 ++++---- dts/arm/nxp/nxp_lpc55S3x_common.dtsi | 45 ++++++----- dts/arm/nxp/nxp_lpc55S6x_common.dtsi | 31 ++++---- dts/arm/nxp/nxp_rt5xx_common.dtsi | 98 ++++++++++++------------ dts/arm/nxp/nxp_rt6xx_common.dtsi | 85 ++++++++++---------- dts/arm/nxp/nxp_rw6xx_common.dtsi | 31 ++++---- dts/bindings/gpio/nxp,lpc-gpio-port.yaml | 34 ++++++++ dts/bindings/gpio/nxp,lpc-gpio.yaml | 47 +++--------- 14 files changed, 290 insertions(+), 243 deletions(-) create mode 100644 dts/bindings/gpio/nxp,lpc-gpio-port.yaml diff --git a/drivers/gpio/Kconfig.mcux_lpc b/drivers/gpio/Kconfig.mcux_lpc index fb2b6cf8905f9..c56af535a029a 100644 --- a/drivers/gpio/Kconfig.mcux_lpc +++ b/drivers/gpio/Kconfig.mcux_lpc @@ -6,6 +6,6 @@ config GPIO_MCUX_LPC bool "MCUX LPC GPIO driver" default y - depends on DT_HAS_NXP_LPC_GPIO_ENABLED + depends on DT_HAS_NXP_LPC_GPIO_PORT_ENABLED help Enable the MCUX LPC pinmux driver. diff --git a/drivers/gpio/gpio_mcux_lpc.c b/drivers/gpio/gpio_mcux_lpc.c index 8895a984dc28d..7c6550e761723 100644 --- a/drivers/gpio/gpio_mcux_lpc.c +++ b/drivers/gpio/gpio_mcux_lpc.c @@ -4,7 +4,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -#define DT_DRV_COMPAT nxp_lpc_gpio +#define DT_DRV_COMPAT nxp_lpc_gpio_port /** @file * @brief GPIO driver for LPC54XXX family @@ -457,10 +457,10 @@ static const struct gpio_driver_api gpio_mcux_lpc_driver_api = { .common = { \ .port_pin_mask = GPIO_PORT_PIN_MASK_FROM_DT_INST(n), \ }, \ - .gpio_base = GPIO, \ + .gpio_base = (GPIO_Type *)DT_REG_ADDR(DT_INST_PARENT(n)), \ .pinmux_base = PINMUX_BASE, \ .int_source = DT_INST_ENUM_IDX(n, int_source), \ - .port_no = DT_INST_PROP(n, port) \ + .port_no = DT_INST_REG_ADDR(n) \ }; \ \ static struct gpio_mcux_lpc_data gpio_mcux_lpc_data_##n; \ diff --git a/dts/arm/nxp/nxp_lpc51u68.dtsi b/dts/arm/nxp/nxp_lpc51u68.dtsi index ff4b43073b621..69c0070a18273 100644 --- a/dts/arm/nxp/nxp_lpc51u68.dtsi +++ b/dts/arm/nxp/nxp_lpc51u68.dtsi @@ -59,22 +59,27 @@ }; }; - gpio0: gpio@0 { + gpio: gpio@4008c000 { compatible = "nxp,lpc-gpio"; reg = <0x4008c000 0x2484>; - int-source = "pint"; - gpio-controller; - #gpio-cells = <2>; - port = <0>; - }; + #address-cells = <1>; + #size-cells = <0>; + + gpio0: gpio@0 { + compatible = "nxp,lpc-gpio-port"; + int-source = "pint"; + gpio-controller; + #gpio-cells = <2>; + reg = <0>; + }; - gpio1: gpio@1 { - compatible = "nxp,lpc-gpio"; - reg = <0x4008C000 0x2484>; - int-source = "pint"; - gpio-controller; - #gpio-cells = <2>; - port = <1>; + gpio1: gpio@1 { + compatible = "nxp,lpc-gpio-port"; + int-source = "pint"; + gpio-controller; + #gpio-cells = <2>; + reg = <1>; + }; }; pint: pint@40004000 { diff --git a/dts/arm/nxp/nxp_lpc54xxx.dtsi b/dts/arm/nxp/nxp_lpc54xxx.dtsi index 78ffb203a84ff..922a93e19ab31 100644 --- a/dts/arm/nxp/nxp_lpc54xxx.dtsi +++ b/dts/arm/nxp/nxp_lpc54xxx.dtsi @@ -114,22 +114,27 @@ }; }; - gpio0: gpio@0 { + gpio: gpio@4008c000 { compatible = "nxp,lpc-gpio"; reg = <0x4008c000 0x2488>; - int-source = "pint"; - gpio-controller; - #gpio-cells = <2>; - port = <0>; - }; + #address-cells = <1>; + #size-cells = <0>; + + gpio0: gpio@0 { + compatible = "nxp,lpc-gpio-port"; + reg = <0>; + int-source = "pint"; + gpio-controller; + #gpio-cells = <2>; + }; - gpio1: gpio@1 { - compatible = "nxp,lpc-gpio"; - reg = <0x4008C000 0x2488>; - int-source = "pint"; - gpio-controller; - #gpio-cells = <2>; - port = <1>; + gpio1: gpio@1 { + compatible = "nxp,lpc-gpio-port"; + reg = <1>; + int-source = "pint"; + gpio-controller; + #gpio-cells = <2>; + }; }; pint: pint@40004000 { diff --git a/dts/arm/nxp/nxp_lpc55S0x_common.dtsi b/dts/arm/nxp/nxp_lpc55S0x_common.dtsi index 4ffb014f2814d..60888d4ea0f7b 100644 --- a/dts/arm/nxp/nxp_lpc55S0x_common.dtsi +++ b/dts/arm/nxp/nxp_lpc55S0x_common.dtsi @@ -117,22 +117,26 @@ }; }; - gpio0: gpio@0 { + gpio: gpio@8c000 { compatible = "nxp,lpc-gpio"; reg = <0x8c000 0x2488>; - int-source = "pint"; - gpio-controller; - #gpio-cells = <2>; - port = <0>; - }; + #address-cells = <1>; + #size-cells = <0>; + gpio0: gpio@0 { + compatible = "nxp,lpc-gpio-port"; + int-source = "pint"; + gpio-controller; + #gpio-cells = <2>; + reg = <0>; + }; - gpio1: gpio@1 { - compatible = "nxp,lpc-gpio"; - reg = <0x8c000 0x2488>; - int-source = "pint"; - gpio-controller; - #gpio-cells = <2>; - port = <1>; + gpio1: gpio@1 { + compatible = "nxp,lpc-gpio-port"; + int-source = "pint"; + gpio-controller; + #gpio-cells = <2>; + reg = <1>; + }; }; pint: pint@4000 { diff --git a/dts/arm/nxp/nxp_lpc55S1x_common.dtsi b/dts/arm/nxp/nxp_lpc55S1x_common.dtsi index 3c6f7fd0b67fa..636f419f77a57 100644 --- a/dts/arm/nxp/nxp_lpc55S1x_common.dtsi +++ b/dts/arm/nxp/nxp_lpc55S1x_common.dtsi @@ -124,22 +124,27 @@ }; }; - gpio0: gpio@0 { + gpio: gpio@8c000 { compatible = "nxp,lpc-gpio"; reg = <0x8c000 0x2488>; - int-source = "pint"; - gpio-controller; - #gpio-cells = <2>; - port = <0>; - }; + #address-cells = <1>; + #size-cells = <0>; - gpio1: gpio@1 { - compatible = "nxp,lpc-gpio"; - reg = <0x8c000 0x2488>; - int-source = "pint"; - gpio-controller; - #gpio-cells = <2>; - port = <1>; + gpio0: gpio@0 { + compatible = "nxp,lpc-gpio-port"; + reg = <0>; + int-source = "pint"; + gpio-controller; + #gpio-cells = <2>; + }; + + gpio1: gpio@1 { + compatible = "nxp,lpc-gpio-port"; + reg = <1>; + int-source = "pint"; + gpio-controller; + #gpio-cells = <2>; + }; }; pint: pint@4000 { diff --git a/dts/arm/nxp/nxp_lpc55S2x_common.dtsi b/dts/arm/nxp/nxp_lpc55S2x_common.dtsi index a751693e201a9..bb29407288c3c 100644 --- a/dts/arm/nxp/nxp_lpc55S2x_common.dtsi +++ b/dts/arm/nxp/nxp_lpc55S2x_common.dtsi @@ -131,22 +131,27 @@ }; }; - gpio0: gpio@0 { + gpio: gpio@8c000 { compatible = "nxp,lpc-gpio"; reg = <0x8c000 0x2488>; - int-source = "pint"; - gpio-controller; - #gpio-cells = <2>; - port = <0>; - }; + #address-cells = <1>; + #size-cells = <0>; - gpio1: gpio@1 { - compatible = "nxp,lpc-gpio"; - reg = <0x8c000 0x2488>; - int-source = "pint"; - gpio-controller; - #gpio-cells = <2>; - port = <1>; + gpio0: gpio@0 { + compatible = "nxp,lpc-gpio-port"; + int-source = "pint"; + gpio-controller; + #gpio-cells = <2>; + reg = <0>; + }; + + gpio1: gpio@1 { + compatible = "nxp,lpc-gpio-port"; + int-source = "pint"; + gpio-controller; + #gpio-cells = <2>; + reg = <1>; + }; }; pint: pint@4000 { diff --git a/dts/arm/nxp/nxp_lpc55S3x_common.dtsi b/dts/arm/nxp/nxp_lpc55S3x_common.dtsi index 6a5621d19b7bd..3b2c079b37ecf 100644 --- a/dts/arm/nxp/nxp_lpc55S3x_common.dtsi +++ b/dts/arm/nxp/nxp_lpc55S3x_common.dtsi @@ -117,30 +117,33 @@ }; }; - gpio0: gpio@0 { + gpio: gpio@8c000 { compatible = "nxp,lpc-gpio"; - reg = <0x8c000 0x278c>; - int-source = "pint"; - gpio-controller; - #gpio-cells = <2>; - port = <0>; - }; + reg = <0x8c000 0x2488>; + #address-cells = <1>; + #size-cells = <0>; + gpio0: gpio@0 { + compatible = "nxp,lpc-gpio-port"; + int-source = "pint"; + gpio-controller; + #gpio-cells = <2>; + reg = <0>; + }; - gpio1: gpio@1 { - compatible = "nxp,lpc-gpio"; - reg = <0x8c000 0x278c>; - int-source = "pint"; - gpio-controller; - #gpio-cells = <2>; - port = <1>; - }; + gpio1: gpio@1 { + compatible = "nxp,lpc-gpio-port"; + int-source = "pint"; + gpio-controller; + #gpio-cells = <2>; + reg = <1>; + }; - gpio2: gpio@2 { - compatible = "nxp,lpc-gpio"; - reg = <0x8c000 0x278c>; - gpio-controller; - #gpio-cells = <2>; - port = <2>; + gpio2: gpio@2 { + compatible = "nxp,lpc-gpio-port"; + gpio-controller; + #gpio-cells = <2>; + reg = <2>; + }; }; dma0: dma-controller@82000 { diff --git a/dts/arm/nxp/nxp_lpc55S6x_common.dtsi b/dts/arm/nxp/nxp_lpc55S6x_common.dtsi index bc4aa8402552f..07883ab825305 100644 --- a/dts/arm/nxp/nxp_lpc55S6x_common.dtsi +++ b/dts/arm/nxp/nxp_lpc55S6x_common.dtsi @@ -161,22 +161,27 @@ }; }; - gpio0: gpio@0 { + gpio: gpio@8c000 { compatible = "nxp,lpc-gpio"; reg = <0x8c000 0x2488>; - int-source = "pint"; - gpio-controller; - #gpio-cells = <2>; - port = <0>; - }; + #address-cells = <1>; + #size-cells = <0>; - gpio1: gpio@1 { - compatible = "nxp,lpc-gpio"; - reg = <0x8c000 0x2488>; - int-source = "pint"; - gpio-controller; - #gpio-cells = <2>; - port = <1>; + gpio0: gpio@0 { + compatible = "nxp,lpc-gpio-port"; + reg = <0>; + int-source = "pint"; + gpio-controller; + #gpio-cells = <2>; + }; + + gpio1: gpio@1 { + compatible = "nxp,lpc-gpio-port"; + reg = <1>; + int-source = "pint"; + gpio-controller; + #gpio-cells = <2>; + }; }; pint: pint@4000 { diff --git a/dts/arm/nxp/nxp_rt5xx_common.dtsi b/dts/arm/nxp/nxp_rt5xx_common.dtsi index 95af8ca31770a..63954b3904dbe 100644 --- a/dts/arm/nxp/nxp_rt5xx_common.dtsi +++ b/dts/arm/nxp/nxp_rt5xx_common.dtsi @@ -154,62 +154,62 @@ reg = <0x2f50 0x10>; }; - gpio0: gpio@0 { + gpio: gpio@100000 { compatible = "nxp,lpc-gpio"; - reg = <0x100000 0x1000>; - int-source = "pint"; - gpio-controller; - #gpio-cells = <2>; - port = <0>; - }; + reg = <0x100000 0x2784>; + #address-cells = <1>; + #size-cells = <0>; - gpio1: gpio@1 { - compatible = "nxp,lpc-gpio"; - reg = <0x100000 0x1000>; - int-source = "pint"; - gpio-controller; - #gpio-cells = <2>; - port = <1>; - }; + gpio0: gpio@0 { + compatible = "nxp,lpc-gpio-port"; + int-source = "pint"; + gpio-controller; + #gpio-cells = <2>; + reg = <0>; + }; - gpio2: gpio@2 { - compatible = "nxp,lpc-gpio"; - reg = <0x100000 0x1000>; - gpio-controller; - #gpio-cells = <2>; - port = <2>; - }; + gpio1: gpio@1 { + compatible = "nxp,lpc-gpio-port"; + int-source = "pint"; + gpio-controller; + #gpio-cells = <2>; + reg = <1>; + }; - gpio3: gpio@3 { - compatible = "nxp,lpc-gpio"; - reg = <0x100000 0x1000>; - gpio-controller; - #gpio-cells = <2>; - port = <3>; - }; + gpio2: gpio@2 { + compatible = "nxp,lpc-gpio-port"; + gpio-controller; + #gpio-cells = <2>; + reg = <2>; + }; - gpio4: gpio@4 { - compatible = "nxp,lpc-gpio"; - reg = <0x100000 0x1000>; - gpio-controller; - #gpio-cells = <2>; - port = <4>; - }; + gpio3: gpio@3 { + compatible = "nxp,lpc-gpio-port"; + gpio-controller; + #gpio-cells = <2>; + reg = <3>; + }; - gpio5: gpio@5 { - compatible = "nxp,lpc-gpio"; - reg = <0x100000 0x1000>; - gpio-controller; - #gpio-cells = <2>; - port = <5>; - }; + gpio4: gpio@4 { + compatible = "nxp,lpc-gpio-port"; + gpio-controller; + #gpio-cells = <2>; + reg = <4>; + }; - gpio6: gpio@6 { - compatible = "nxp,lpc-gpio"; - reg = <0x100000 0x1000>; - gpio-controller; - #gpio-cells = <2>; - port = <6>; + gpio5: gpio@5 { + compatible = "nxp,lpc-gpio-port"; + gpio-controller; + #gpio-cells = <2>; + reg = <5>; + }; + + gpio6: gpio@6 { + compatible = "nxp,lpc-gpio-port"; + gpio-controller; + #gpio-cells = <2>; + reg = <6>; + }; }; pint: pint@25000 { diff --git a/dts/arm/nxp/nxp_rt6xx_common.dtsi b/dts/arm/nxp/nxp_rt6xx_common.dtsi index 9b85ee2586d6c..9cd910e16ded3 100644 --- a/dts/arm/nxp/nxp_rt6xx_common.dtsi +++ b/dts/arm/nxp/nxp_rt6xx_common.dtsi @@ -138,54 +138,55 @@ reg = <0x2f50 0x10>; }; - gpio0: gpio@0 { + gpio: gpio@100000 { compatible = "nxp,lpc-gpio"; - reg = <0x100000 0x1000>; - int-source = "pint"; - gpio-controller; - #gpio-cells = <2>; - port = <0>; - }; + reg = <0x100000 0x2784>; + #address-cells = <1>; + #size-cells = <0>; - gpio1: gpio@1 { - compatible = "nxp,lpc-gpio"; - reg = <0x100000 0x1000>; - int-source = "pint"; - gpio-controller; - #gpio-cells = <2>; - port = <1>; - }; + gpio0: gpio@0 { + compatible = "nxp,lpc-gpio-port"; + int-source = "pint"; + gpio-controller; + #gpio-cells = <2>; + reg = <0>; + }; - gpio2: gpio@2 { - compatible = "nxp,lpc-gpio"; - reg = <0x100000 0x1000>; - gpio-controller; - #gpio-cells = <2>; - port = <2>; - }; + gpio1: gpio@1 { + compatible = "nxp,lpc-gpio-port"; + int-source = "pint"; + gpio-controller; + #gpio-cells = <2>; + reg = <1>; + }; - gpio3: gpio@3 { - compatible = "nxp,lpc-gpio"; - reg = <0x100000 0x1000>; - gpio-controller; - #gpio-cells = <2>; - port = <3>; - }; + gpio2: gpio@2 { + compatible = "nxp,lpc-gpio-port"; + gpio-controller; + #gpio-cells = <2>; + reg = <2>; + }; - gpio4: gpio@4 { - compatible = "nxp,lpc-gpio"; - reg = <0x100000 0x1000>; - gpio-controller; - #gpio-cells = <2>; - port = <4>; - }; + gpio3: gpio@3 { + compatible = "nxp,lpc-gpio-port"; + gpio-controller; + #gpio-cells = <2>; + reg = <3>; + }; - gpio7: gpio@7 { - compatible = "nxp,lpc-gpio"; - reg = <0x100000 0x1000>; - gpio-controller; - #gpio-cells = <2>; - port = <7>; + gpio4: gpio@4 { + compatible = "nxp,lpc-gpio-port"; + gpio-controller; + #gpio-cells = <2>; + reg = <4>; + }; + + gpio7: gpio@7 { + compatible = "nxp,lpc-gpio-port"; + gpio-controller; + #gpio-cells = <2>; + reg = <7>; + }; }; pint: pint@25000 { diff --git a/dts/arm/nxp/nxp_rw6xx_common.dtsi b/dts/arm/nxp/nxp_rw6xx_common.dtsi index 229d8b299db29..86bb92eb6b048 100644 --- a/dts/arm/nxp/nxp_rw6xx_common.dtsi +++ b/dts/arm/nxp/nxp_rw6xx_common.dtsi @@ -164,22 +164,27 @@ clk-divider = <1>; }; - hsgpio0: hsgpio@0 { + hsgpio: hsgpio@100000 { compatible = "nxp,lpc-gpio"; reg = <0x100000 0x4000>; - gpio-controller; - #gpio-cells = <2>; - port = <0>; - int-source = "pint"; - }; + #address-cells = <1>; + #size-cells = <0>; - hsgpio1: hsgpio@1 { - compatible = "nxp,lpc-gpio"; - reg = <0x100000 0x4000>; - gpio-controller; - #gpio-cells = <2>; - port = <1>; - int-source = "pint"; + hsgpio0: gpio@0 { + compatible = "nxp,lpc-gpio-port"; + gpio-controller; + #gpio-cells = <2>; + reg = <0>; + int-source = "pint"; + }; + + hsgpio1: gpio@1 { + compatible = "nxp,lpc-gpio-port"; + gpio-controller; + #gpio-cells = <2>; + reg = <1>; + int-source = "pint"; + }; }; usb_otg: usbotg@145000 { diff --git a/dts/bindings/gpio/nxp,lpc-gpio-port.yaml b/dts/bindings/gpio/nxp,lpc-gpio-port.yaml new file mode 100644 index 0000000000000..43cdec363b44b --- /dev/null +++ b/dts/bindings/gpio/nxp,lpc-gpio-port.yaml @@ -0,0 +1,34 @@ +# Copyright 2019-2022, 2024 NXP +# SPDX-License-Identifier: Apache-2.0 + +description: LPC GPIO port device. + +compatible: "nxp,lpc-gpio-port" + +include: [gpio-controller.yaml, base.yaml] + +properties: + reg: + required: true + + "#gpio-cells": + const: 2 + + int-source: + type: string + default: "none" + enum: + - "pint" + - "int-a" + - "int-b" + - "none" + description: | + Interrupt source for the gpio port. For ports that can use the PINT + as an interrupt source for their pins (typically ports 0 and 1), + this can be set to PINT. Otherwise, the property should be set to "int-a" + or "int-b" if interrupt support is desired, and the appropriate IRQ number + should set for the device. + +gpio-cells: + - pin + - flags diff --git a/dts/bindings/gpio/nxp,lpc-gpio.yaml b/dts/bindings/gpio/nxp,lpc-gpio.yaml index 52716cba7de63..19b31bc284ca4 100644 --- a/dts/bindings/gpio/nxp,lpc-gpio.yaml +++ b/dts/bindings/gpio/nxp,lpc-gpio.yaml @@ -1,48 +1,23 @@ -# Copyright (c) 2019-22, NXP +# Copyright 2024 NXP # SPDX-License-Identifier: Apache-2.0 +# This binding is for the gpio device, +# which has multiple ports that share the same +# base address. It is the ports that are +# functionally gpio devices. + description: LPC GPIO node compatible: "nxp,lpc-gpio" -include: [gpio-controller.yaml, base.yaml] +include: base.yaml properties: reg: required: true - "#gpio-cells": - const: 2 - - port: - type: int - required: true - description: The GPIO port this node describes - enum: - - 0 - - 1 - - 2 - - 3 - - 4 - - 5 - - 6 - - 7 - - int-source: - type: string - default: "none" - enum: - - "pint" - - "int-a" - - "int-b" - - "none" - description: | - Interrupt source for the gpio port. For ports that can use the PINT - as an interrupt source for their pins (typically ports 0 and 1), - this can be set to PINT. Otherwise, the property should be set to "int-a" - or "int-b" if interrupt support is desired, and the appropriate IRQ number - should set for the device. + "#address-cells": + const: 1 -gpio-cells: - - pin - - flags + "#size-cells": + const: 0 From 4bf9e62ba0321aecaf5988197490958b64583ef5 Mon Sep 17 00:00:00 2001 From: Declan Snyder Date: Mon, 10 Jun 2024 11:31:57 -0500 Subject: [PATCH 2680/2849] boards: nxp: Remove suppression of LPC DTC warns DTC warnings are useful and we should keep them enabled. Signed-off-by: Declan Snyder --- boards/nxp/frdm_rw612/pre_dt_board.cmake | 2 -- boards/nxp/lpcxpresso11u68/pre_dt_board.cmake | 9 --------- boards/nxp/lpcxpresso51u68/pre_dt_board.cmake | 5 ----- boards/nxp/lpcxpresso54114/pre_dt_board.cmake | 5 ----- boards/nxp/lpcxpresso55s06/pre_dt_board.cmake | 12 ------------ boards/nxp/lpcxpresso55s16/pre_dt_board.cmake | 9 --------- boards/nxp/lpcxpresso55s28/pre_dt_board.cmake | 9 --------- boards/nxp/lpcxpresso55s36/pre_dt_board.cmake | 9 --------- boards/nxp/lpcxpresso55s69/pre_dt_board.cmake | 9 --------- boards/nxp/mimxrt595_evk/pre_dt_board.cmake | 5 ----- boards/nxp/mimxrt685_evk/pre_dt_board.cmake | 5 ----- boards/nxp/rd_rw612_bga/pre_dt_board.cmake | 2 -- 12 files changed, 81 deletions(-) delete mode 100644 boards/nxp/lpcxpresso11u68/pre_dt_board.cmake delete mode 100644 boards/nxp/lpcxpresso51u68/pre_dt_board.cmake delete mode 100644 boards/nxp/lpcxpresso54114/pre_dt_board.cmake delete mode 100644 boards/nxp/lpcxpresso55s06/pre_dt_board.cmake delete mode 100644 boards/nxp/lpcxpresso55s16/pre_dt_board.cmake delete mode 100644 boards/nxp/lpcxpresso55s28/pre_dt_board.cmake delete mode 100644 boards/nxp/lpcxpresso55s36/pre_dt_board.cmake delete mode 100644 boards/nxp/lpcxpresso55s69/pre_dt_board.cmake delete mode 100644 boards/nxp/mimxrt595_evk/pre_dt_board.cmake delete mode 100644 boards/nxp/mimxrt685_evk/pre_dt_board.cmake diff --git a/boards/nxp/frdm_rw612/pre_dt_board.cmake b/boards/nxp/frdm_rw612/pre_dt_board.cmake index 2c56668e4355a..5da215a0a3bef 100644 --- a/boards/nxp/frdm_rw612/pre_dt_board.cmake +++ b/boards/nxp/frdm_rw612/pre_dt_board.cmake @@ -1,7 +1,5 @@ # 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") diff --git a/boards/nxp/lpcxpresso11u68/pre_dt_board.cmake b/boards/nxp/lpcxpresso11u68/pre_dt_board.cmake deleted file mode 100644 index 2e3b3ff69ec50..0000000000000 --- a/boards/nxp/lpcxpresso11u68/pre_dt_board.cmake +++ /dev/null @@ -1,9 +0,0 @@ -# Copyright (c) 2019, NXP -# SPDX-License-Identifier: Apache-2.0 - -# Suppress DTC warnings due to all GPIO nodes sharing the same register address. -list(APPEND EXTRA_DTC_FLAGS "-Wno-simple_bus_reg") - -# Suppress "unique_unit_address_if_enabled" to handle the following overlaps: -# - /soc/flash@0 & /soc/gpio@0 -list(APPEND EXTRA_DTC_FLAGS "-Wno-unique_unit_address_if_enabled") diff --git a/boards/nxp/lpcxpresso51u68/pre_dt_board.cmake b/boards/nxp/lpcxpresso51u68/pre_dt_board.cmake deleted file mode 100644 index 665c78c7838fd..0000000000000 --- a/boards/nxp/lpcxpresso51u68/pre_dt_board.cmake +++ /dev/null @@ -1,5 +0,0 @@ -# Copyright (c) 2021 metraTec GmbH -# SPDX-License-Identifier: Apache-2.0 - -# Suppress "simple_bus_reg" on LPC boards as all GPIO ports use the same register. -list(APPEND EXTRA_DTC_FLAGS "-Wno-simple_bus_reg") diff --git a/boards/nxp/lpcxpresso54114/pre_dt_board.cmake b/boards/nxp/lpcxpresso54114/pre_dt_board.cmake deleted file mode 100644 index 4918baef9a7f6..0000000000000 --- a/boards/nxp/lpcxpresso54114/pre_dt_board.cmake +++ /dev/null @@ -1,5 +0,0 @@ -# Copyright (c) 2019, NXP -# SPDX-License-Identifier: Apache-2.0 - -# Suppress "simple_bus_reg" on LPC boards as all GPIO ports use the same register. -list(APPEND EXTRA_DTC_FLAGS "-Wno-simple_bus_reg") diff --git a/boards/nxp/lpcxpresso55s06/pre_dt_board.cmake b/boards/nxp/lpcxpresso55s06/pre_dt_board.cmake deleted file mode 100644 index 180748da25b36..0000000000000 --- a/boards/nxp/lpcxpresso55s06/pre_dt_board.cmake +++ /dev/null @@ -1,12 +0,0 @@ -# -# Copyright (c) 2022 metraTec -# -# SPDX-License-Identifier: Apache-2.0 -# - -# Suppress "simple_bus_reg" on LPC boards as all GPIO ports use the same register. -list(APPEND EXTRA_DTC_FLAGS "-Wno-simple_bus_reg") - -# Suppress "unique_unit_address_if_enabled" to handle the following overlaps: -# - /soc/peripheral@40000000/syscon@0 & /soc/peripheral@40000000/gpio@0 -list(APPEND EXTRA_DTC_FLAGS "-Wno-unique_unit_address_if_enabled") diff --git a/boards/nxp/lpcxpresso55s16/pre_dt_board.cmake b/boards/nxp/lpcxpresso55s16/pre_dt_board.cmake deleted file mode 100644 index dbc704b3f54ac..0000000000000 --- a/boards/nxp/lpcxpresso55s16/pre_dt_board.cmake +++ /dev/null @@ -1,9 +0,0 @@ -# Copyright (c) 2020 Henrik Brix Andersen -# SPDX-License-Identifier: Apache-2.0 - -# Suppress "simple_bus_reg" on LPC boards as all GPIO ports use the same register. -list(APPEND EXTRA_DTC_FLAGS "-Wno-simple_bus_reg") - -# Suppress "unique_unit_address_if_enabled" to handle the following overlaps: -# - /soc/peripheral@40000000/syscon@0 & /soc/peripheral@40000000/gpio@0 -list(APPEND EXTRA_DTC_FLAGS "-Wno-unique_unit_address_if_enabled") diff --git a/boards/nxp/lpcxpresso55s28/pre_dt_board.cmake b/boards/nxp/lpcxpresso55s28/pre_dt_board.cmake deleted file mode 100644 index fcdd6b77a2bca..0000000000000 --- a/boards/nxp/lpcxpresso55s28/pre_dt_board.cmake +++ /dev/null @@ -1,9 +0,0 @@ -# Copyright (c) 2020 Lemonbeat GmbH -# SPDX-License-Identifier: Apache-2.0 - -# Suppress "simple_bus_reg" on LPC boards as all GPIO ports use the same register. -list(APPEND EXTRA_DTC_FLAGS "-Wno-simple_bus_reg") - -# Suppress "unique_unit_address_if_enabled" to handle the following overlaps: -# - /soc/peripheral@40000000/syscon@0 & /soc/peripheral@40000000/gpio@0 -list(APPEND EXTRA_DTC_FLAGS "-Wno-unique_unit_address_if_enabled") diff --git a/boards/nxp/lpcxpresso55s36/pre_dt_board.cmake b/boards/nxp/lpcxpresso55s36/pre_dt_board.cmake deleted file mode 100644 index d97bfca8cf1f9..0000000000000 --- a/boards/nxp/lpcxpresso55s36/pre_dt_board.cmake +++ /dev/null @@ -1,9 +0,0 @@ -# Copyright 2022 NXP -# SPDX-License-Identifier: Apache-2.0 - -# Suppress "simple_bus_reg" on LPC boards as all GPIO ports use the same register. -list(APPEND EXTRA_DTC_FLAGS "-Wno-simple_bus_reg") - -# Suppress "unique_unit_address_if_enabled" to handle the following overlaps: -# - /soc/peripheral@40000000/syscon@0 & /soc/peripheral@40000000/gpio@0 -list(APPEND EXTRA_DTC_FLAGS "-Wno-unique_unit_address_if_enabled") diff --git a/boards/nxp/lpcxpresso55s69/pre_dt_board.cmake b/boards/nxp/lpcxpresso55s69/pre_dt_board.cmake deleted file mode 100644 index a7c79990aa54f..0000000000000 --- a/boards/nxp/lpcxpresso55s69/pre_dt_board.cmake +++ /dev/null @@ -1,9 +0,0 @@ -# Copyright (c) 2019, NXP -# SPDX-License-Identifier: Apache-2.0 - -# Suppress "simple_bus_reg" on LPC boards as all GPIO ports use the same register. -list(APPEND EXTRA_DTC_FLAGS "-Wno-simple_bus_reg") - -# Suppress "unique_unit_address_if_enabled" to handle the following overlaps: -# - /soc/peripheral@40000000/syscon@0 & /soc/peripheral@40000000/gpio@0 -list(APPEND EXTRA_DTC_FLAGS "-Wno-unique_unit_address_if_enabled") diff --git a/boards/nxp/mimxrt595_evk/pre_dt_board.cmake b/boards/nxp/mimxrt595_evk/pre_dt_board.cmake deleted file mode 100644 index 5dd7773bba415..0000000000000 --- a/boards/nxp/mimxrt595_evk/pre_dt_board.cmake +++ /dev/null @@ -1,5 +0,0 @@ -# Copyright (c) 2022, NXP -# SPDX-License-Identifier: Apache-2.0 - -# Suppress "simple_bus_reg" on RT5XX boards as all GPIO ports use the same register. -list(APPEND EXTRA_DTC_FLAGS "-Wno-simple_bus_reg") diff --git a/boards/nxp/mimxrt685_evk/pre_dt_board.cmake b/boards/nxp/mimxrt685_evk/pre_dt_board.cmake deleted file mode 100644 index e23600abc7732..0000000000000 --- a/boards/nxp/mimxrt685_evk/pre_dt_board.cmake +++ /dev/null @@ -1,5 +0,0 @@ -# Copyright (c) 2020, NXP -# SPDX-License-Identifier: Apache-2.0 - -# Suppress "simple_bus_reg" on RT6XX boards as all GPIO ports use the same register. -list(APPEND EXTRA_DTC_FLAGS "-Wno-simple_bus_reg") diff --git a/boards/nxp/rd_rw612_bga/pre_dt_board.cmake b/boards/nxp/rd_rw612_bga/pre_dt_board.cmake index 2c56668e4355a..5da215a0a3bef 100644 --- a/boards/nxp/rd_rw612_bga/pre_dt_board.cmake +++ b/boards/nxp/rd_rw612_bga/pre_dt_board.cmake @@ -1,7 +1,5 @@ # 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 163ddc0e84e7295c76d7c06604f7819ca42201dd Mon Sep 17 00:00:00 2001 From: Declan Snyder Date: Wed, 12 Jun 2024 22:10:54 -0500 Subject: [PATCH 2681/2849] boards: lpcxpresso5s69//ns: Fix mbedtls build err Fix issue where when building with TFM and PSA client there is an error from want RSA key type not being defined in mbedTLS library. Signed-off-by: Declan Snyder --- boards/nxp/lpcxpresso55s69/Kconfig.defconfig | 3 +++ 1 file changed, 3 insertions(+) diff --git a/boards/nxp/lpcxpresso55s69/Kconfig.defconfig b/boards/nxp/lpcxpresso55s69/Kconfig.defconfig index 5a48b7afe2402..de1910595b4a3 100644 --- a/boards/nxp/lpcxpresso55s69/Kconfig.defconfig +++ b/boards/nxp/lpcxpresso55s69/Kconfig.defconfig @@ -42,6 +42,9 @@ config FLASH_LOAD_SIZE default 0x40000 if (!TFM_BL2 && BUILD_WITH_TFM) default $(dt_chosen_reg_size_hex,$(DT_CHOSEN_Z_CODE_PARTITION)) +config PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY + default y if MBEDTLS_PSA_CRYPTO_CLIENT && MBEDTLS_KEY_EXCHANGE_RSA_ENABLED + endif # TRUSTED_EXECUTION_NONSECURE || BOARD_LPCXPRESSO55S69_LPC55S69_CPU1 choice TFM_PROFILE_TYPE From 0666fe2a3552536bfa9d679251b4277c4764b3c0 Mon Sep 17 00:00:00 2001 From: Sercan Erat Date: Sat, 8 Jun 2024 18:28:30 +0300 Subject: [PATCH 2682/2849] boards: rak: Add Rak11720 board MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Added support for the Rak11720 board. Rak11720 is a WisBlock Core module with Apollo3 Blue SoC from Ambiq and a Semtech SX1262 LoRa® transceiver. For more information about this board please check: https://docs.rakwireless.com/Product-Categories/WisDuo/RAK11720-Module/Overview/#product-description There are known issues that have been identified while communicating with SX1262 transceiver: - Gpio interrupt handling error: ambiq_gpio_pin_interrupt_configure function is not able to configure SX1262 Dio1 interrupt pin correctly. Please check issue 73958. - Spi communication error: Rak11720 uses a custom CS pin. Firstly, custom CS pin support is necessary. Secondly, spi_ambiq_xfer function is not able to communicate with SX1262 transceiver. Please check issue 73959. These issues have been documented for future solutions. Despite these limitations, the current support enables basic functionality. Examples can be build by below command for Rak11720: west build -b rak11720 samples/hello_world Signed-off-by: Sercan Erat --- boards/rak/rak11720/Kconfig.rak11720 | 6 + boards/rak/rak11720/board.cmake | 7 + boards/rak/rak11720/board.yml | 5 + boards/rak/rak11720/doc/img/rak11720.webp | Bin 0 -> 37642 bytes boards/rak/rak11720/doc/index.rst | 122 +++++++++++++ boards/rak/rak11720/rak11720.dts | 156 +++++++++++++++++ boards/rak/rak11720/rak11720.yaml | 21 +++ .../rak11720/rak11720_apollo3-pinctrl.dtsi | 162 ++++++++++++++++++ boards/rak/rak11720/rak11720_defconfig | 8 + 9 files changed, 487 insertions(+) create mode 100644 boards/rak/rak11720/Kconfig.rak11720 create mode 100644 boards/rak/rak11720/board.cmake create mode 100644 boards/rak/rak11720/board.yml create mode 100644 boards/rak/rak11720/doc/img/rak11720.webp create mode 100644 boards/rak/rak11720/doc/index.rst create mode 100644 boards/rak/rak11720/rak11720.dts create mode 100644 boards/rak/rak11720/rak11720.yaml create mode 100644 boards/rak/rak11720/rak11720_apollo3-pinctrl.dtsi create mode 100644 boards/rak/rak11720/rak11720_defconfig diff --git a/boards/rak/rak11720/Kconfig.rak11720 b/boards/rak/rak11720/Kconfig.rak11720 new file mode 100644 index 0000000000000..a91bc261d333a --- /dev/null +++ b/boards/rak/rak11720/Kconfig.rak11720 @@ -0,0 +1,6 @@ +# Copyright (c) 2024 RAKwireless Technology Co., Ltd. +# Sercan Erat +# SPDX-License-Identifier: Apache-2.0 + +config BOARD_RAK11720 + select SOC_APOLLO3_BLUE diff --git a/boards/rak/rak11720/board.cmake b/boards/rak/rak11720/board.cmake new file mode 100644 index 0000000000000..026b5a25115bc --- /dev/null +++ b/boards/rak/rak11720/board.cmake @@ -0,0 +1,7 @@ +# Copyright (c) 2024 RAKwireless Technology Co., Ltd. +# Sercan Erat +# 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/rak/rak11720/board.yml b/boards/rak/rak11720/board.yml new file mode 100644 index 0000000000000..827beef7e7648 --- /dev/null +++ b/boards/rak/rak11720/board.yml @@ -0,0 +1,5 @@ +board: + name: rak11720 + vendor: rakwireless + socs: + - name: apollo3_blue diff --git a/boards/rak/rak11720/doc/img/rak11720.webp b/boards/rak/rak11720/doc/img/rak11720.webp new file mode 100644 index 0000000000000000000000000000000000000000..4c513024c782b5e6c5e2bc50c7fa472b8cd5b50c GIT binary patch literal 37642 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 PjH5QQfB*mh00000l*B4T literal 0 HcmV?d00001 diff --git a/boards/rak/rak11720/doc/index.rst b/boards/rak/rak11720/doc/index.rst new file mode 100644 index 0000000000000..7f4054a90d5ff --- /dev/null +++ b/boards/rak/rak11720/doc/index.rst @@ -0,0 +1,122 @@ +.. _rak11720: + +RAK11720 +######## + +The RAK11720 is a WisBlock Core module for RAK WisBlock. +It is based on the powerful ultra-low power Apollo3 Blue SoC (AMA3B1KK-KBR-B0) +from Ambiq together with a Semtech SX1262 LoRa® transceiver. + +The AMA3B1KK-KBR-B0 has an integrated Bluetooth Low Energy transceiver +that enhances the communication capabilities. The RAK11720 stamp module +comes in the same size and footprint as our RAK3172 module which gives +you the opportunity to enhance your existing designs +with BLE without designing a new PCB. + +.. image:: img/rak11720.webp + :align: center + :alt: RAK11720 + +Hardware +******** + +The easiset way to use a RAK11720, is the WisBlock Modular system. +A WisBlock Base board (RAK19007) which provides the power +supply and programming/debug interface is the base to plug a +RAK11722 (WisBlock Core module with the RAK11720) in. + +- 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 +- Semtech SX1262 low power high range LoRa transceiver +- iPEX connectors for the LORA antenna and BLE antenna. +- 2 user LEDs on RAK19007 WisBlock Base board +- Powered by either Micro USB, 3.7V rechargeable battery or a 5V Solar Panel Port + +For more information about the RAK11720 stamp module: + +- `WisDuo RAK11720 Website`_ +- `WisBlock RAK11722 Website`_ + +Supported Features +================== + +The RAK11720 module configuration supports the following hardware features: + ++-----------+------------+----------------------+ +| Interface | Controller | Driver/Component | ++===========+============+======================+ +| MPU | on-chip | arch/arm | ++-----------+------------+----------------------+ +| NVIC | on-chip | arch/arm | ++-----------+------------+----------------------+ +| SYSTICK | on-chip | systick | ++-----------+------------+----------------------+ +| STIMER | on-chip | stimer | ++-----------+------------+----------------------+ +| GPIO | on-chip | gpio | ++-----------+------------+----------------------+ +| UART | on-chip | serial | ++-----------+------------+----------------------+ +| WDT | on-chip | watchdog | ++-----------+------------+----------------------+ +| RADIO | on-chip | bluetooth | ++-----------+------------+----------------------+ +| RADIO | on-board | LoRa (SX1262) | ++-----------+------------+----------------------+ + +The default configuration can be found in the defconfig file: +``boards/rak/rak11720/rak11720_defconfig``. + +Programming and Debugging +========================= + +The RAK11720 board shall be connected to a Segger Embedded Debugger Unit +`J-Link OB `_. This provides a debug +interface to the Apollo3 Blue chip. You can use JLink to communicate with +the Apollo3 Blue. + +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: rak11720 + :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! rak11720/apollo3_blue + +.. _WisDuo RAK11720 Website: + https://docs.rakwireless.com/Product-Categories/WisDuo/RAK11720-Module/Overview/#product-description + +.. _WisBlock RAK11722 Website: + https://docs.rakwireless.com/Product-Categories/WisBlock/RAK11722/Overview/#product-description + +.. _SEGGER J-Link software: + https://www.segger.com/downloads/jlink + +.. _pylink: + https://github.com/Square/pylink diff --git a/boards/rak/rak11720/rak11720.dts b/boards/rak/rak11720/rak11720.dts new file mode 100644 index 0000000000000..4a2a5f1845729 --- /dev/null +++ b/boards/rak/rak11720/rak11720.dts @@ -0,0 +1,156 @@ +/* + * Copyright (c) 2024 RAKwireless Technology Co., Ltd. + * Sercan Erat + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; +#include +#include +#include "rak11720_apollo3-pinctrl.dtsi" + +/ { + model = "RAKwireless RAK11720 WisBlock LPWAN Module"; + compatible = "ambiq,rak11720"; + + chosen { + zephyr,itcm = &tcm; + zephyr,sram = &sram0; + zephyr,flash = &flash0; + zephyr,console = &uart0; + zephyr,shell-uart = &uart0; + zephyr,uart-pipe = &uart0; + zephyr,flash-controller = &flash; + }; + + aliases { + watchdog0 = &wdt0; + led0 = &blue_led; + led1 = &green_led; + lora0 = &lora; + }; + + leds { + compatible = "gpio-leds"; + blue_led: led_2 { + gpios = <&gpio32_63 13 GPIO_ACTIVE_HIGH>; + label = "Blue LED"; + }; + green_led: led_1 { + gpios = <&gpio32_63 12 GPIO_ACTIVE_HIGH>; + label = "Green LED"; + }; + }; +}; + +&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>; + }; + }; +}; + +&bleif { + pinctrl-0 = <&bleif_default>; + pinctrl-names = "default"; + status = "okay"; +}; + +&uart0 { + current-speed = <115200>; + pinctrl-0 = <&uart0_default>; + pinctrl-names = "default"; + status = "okay"; +}; + +&wdt0 { + status = "okay"; +}; + +&i2c2 { + compatible = "ambiq,i2c"; + pinctrl-0 = <&i2c2_default>; + pinctrl-names = "default"; + clock-frequency = ; + status = "okay"; +}; + +&spi0 { + compatible = "ambiq,spi"; + pinctrl-0 = <&spi0_default>; + pinctrl-names = "default"; + clock-frequency = ; + status = "okay"; +}; + +&spi1 { + compatible = "ambiq,spi"; + status = "okay"; + pinctrl-0 = <&spi1_default>; + pinctrl-names = "default"; + clock-frequency = ; + cs-gpios = <&gpio0_31 11 GPIO_ACTIVE_LOW>; + + lora: lora@0 { + compatible = "semtech,sx1262"; + reg = <0>; + reset-gpios = <&gpio0_31 17 GPIO_ACTIVE_LOW>; + busy-gpios = <&gpio0_31 16 GPIO_ACTIVE_HIGH>; + dio1-gpios = <&gpio0_31 15 GPIO_ACTIVE_HIGH>; + antenna-enable-gpios = <&gpio0_31 18 GPIO_ACTIVE_LOW>; + dio2-tx-enable; + dio3-tcxo-voltage = ; + tcxo-power-startup-delay-ms = <5>; + spi-max-frequency = ; + }; +}; + +&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"; +}; + +&gpio32_63 { + status = "okay"; +}; diff --git a/boards/rak/rak11720/rak11720.yaml b/boards/rak/rak11720/rak11720.yaml new file mode 100644 index 0000000000000..43efd09ce87e9 --- /dev/null +++ b/boards/rak/rak11720/rak11720.yaml @@ -0,0 +1,21 @@ +identifier: rak11720 +name: RAK11720 +type: mcu +arch: arm +ram: 384 +flash: 976 +toolchain: + - zephyr + - gnuarmemb +supported: + - uart + - watchdog + - counter + - gpio + - spi + - i2c + - lora +testing: + ignore_tags: + - net +vendor: rak diff --git a/boards/rak/rak11720/rak11720_apollo3-pinctrl.dtsi b/boards/rak/rak11720/rak11720_apollo3-pinctrl.dtsi new file mode 100644 index 0000000000000..df81c2098e049 --- /dev/null +++ b/boards/rak/rak11720/rak11720_apollo3-pinctrl.dtsi @@ -0,0 +1,162 @@ +/* + * Copyright (c) 2024 RAKwireless Technology Co., Ltd. + * Sercan Erat + * 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>; + }; + }; + + bleif_default: bleif_default{ + group1 { + pinmux = , + , + , + , + , + ; + }; + }; +}; diff --git a/boards/rak/rak11720/rak11720_defconfig b/boards/rak/rak11720/rak11720_defconfig new file mode 100644 index 0000000000000..33690ff27206c --- /dev/null +++ b/boards/rak/rak11720/rak11720_defconfig @@ -0,0 +1,8 @@ +# Copyright (c) 2024 RAKwireless Technology Co., Ltd. +# Sercan Erat +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_CONSOLE=y +CONFIG_UART_CONSOLE=y +CONFIG_SERIAL=y +CONFIG_UART_INTERRUPT_DRIVEN=y From 89e27b931233afe292232ea087c1768d82da9090 Mon Sep 17 00:00:00 2001 From: Luca Burelli Date: Fri, 7 Jun 2024 23:21:30 +0200 Subject: [PATCH 2683/2849] llext: improve debug messages The recent llext_map_sections() rework changed the way debug messages are output so that the names of most skipped sections are not printed at all. This makes debugging harder since the section names are useful to identify the contents at a glance. Also print a few additional fields from the section header, and use 0x prefixes for hex numbers. Signed-off-by: Luca Burelli --- subsys/llext/llext_load.c | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/subsys/llext/llext_load.c b/subsys/llext/llext_load.c index 287e6ff8edc9a..17946f36f3f35 100644 --- a/subsys/llext/llext_load.c +++ b/subsys/llext/llext_load.c @@ -136,15 +136,17 @@ static int llext_find_tables(struct llext_loader *ldr) return ret; } - LOG_DBG("section %d at %zx: name %d, type %d, flags %zx, " - "ofs %zx, addr %zx, size %zd", - i, pos, + LOG_DBG("section %d at 0x%zx: name %d, type %d, flags 0x%zx, " + "addr 0x%zx, size %zd, link %d, info %d", + i, + (size_t)shdr.sh_offset, shdr.sh_name, shdr.sh_type, (size_t)shdr.sh_flags, - (size_t)shdr.sh_offset, (size_t)shdr.sh_addr, - (size_t)shdr.sh_size); + (size_t)shdr.sh_size, + shdr.sh_link, + shdr.sh_info); switch (shdr.sh_type) { case SHT_SYMTAB: @@ -204,12 +206,6 @@ static int llext_map_sections(struct llext_loader *ldr, struct llext *ext) return ret; } - if ((shdr.sh_type != SHT_PROGBITS && shdr.sh_type != SHT_NOBITS) || - !(shdr.sh_flags & SHF_ALLOC) || - shdr.sh_size == 0) { - continue; - } - name = llext_string(ldr, ext, LLEXT_MEM_SHSTRTAB, shdr.sh_name); /* Identify the section type by its flags */ @@ -229,8 +225,8 @@ static int llext_map_sections(struct llext_loader *ldr, struct llext *ext) } break; default: - LOG_DBG("Not copied section %s", name); - continue; + mem_idx = LLEXT_MEM_COUNT; + break; } /* Special exception for .exported_sym */ @@ -238,6 +234,13 @@ static int llext_map_sections(struct llext_loader *ldr, struct llext *ext) mem_idx = LLEXT_MEM_EXPORT; } + if (mem_idx == LLEXT_MEM_COUNT || + !(shdr.sh_flags & SHF_ALLOC) || + shdr.sh_size == 0) { + LOG_DBG("section %d name %s skipped", i, name); + continue; + } + LOG_DBG("section %d name %s maps to idx %d", i, name, mem_idx); ldr->sect_map[i] = mem_idx; From a976a1a25c66dc3f1d60444b649c1aeb58438f24 Mon Sep 17 00:00:00 2001 From: Luca Burelli Date: Thu, 6 Jun 2024 18:17:28 +0200 Subject: [PATCH 2684/2849] llext: llext_load: document memory management policy The do_llext_load function is responsible for loading an extension from a file, and for this purpose it calls a number of functions that a) allocate memory, and b) can fail. This creates the opportunity for memory leaks if the error paths are not handled correctly. This commit adds a comment at the beginning of the function to document the memory management policy that has to be followed in this file: cleanup is not performed in the error paths, and all memory is freed at the end of the do_llext_load() function, both in the case of error and of successful loading. As an improvement, the symbol table is not freed if the LLEXT log level is set to debug, so that it can be used, for example, to inspect the symbols of the loaded extension. Signed-off-by: Luca Burelli --- subsys/llext/llext.c | 2 +- subsys/llext/llext_load.c | 53 +++++++++++++++++++++++++++++++++++---- 2 files changed, 49 insertions(+), 6 deletions(-) diff --git a/subsys/llext/llext.c b/subsys/llext/llext.c index d00d952b76e33..3a890835c57c4 100644 --- a/subsys/llext/llext.c +++ b/subsys/llext/llext.c @@ -136,7 +136,6 @@ int llext_load(struct llext_loader *ldr, const char *name, struct llext **ext, ret = -ENOMEM; goto out; } - memset(*ext, 0, sizeof(struct llext)); ret = do_llext_load(ldr, *ext, ldr_parm); if (ret < 0) { @@ -179,6 +178,7 @@ int llext_unload(struct llext **ext) k_mutex_unlock(&llext_lock); llext_free_sections(tmp); + llext_free(tmp->sym_tab.syms); llext_free(tmp->exp_tab.syms); llext_free(tmp); diff --git a/subsys/llext/llext_load.c b/subsys/llext/llext_load.c index 17946f36f3f35..0af584e2deff6 100644 --- a/subsys/llext/llext_load.c +++ b/subsys/llext/llext_load.c @@ -18,6 +18,24 @@ LOG_MODULE_DECLARE(llext, CONFIG_LLEXT_LOG_LEVEL); #include "llext_priv.h" +/* + * NOTICE: Functions in this file do not clean up allocations in their error + * paths; instead, this is performed once and for all when leaving the parent + * `do_llext_load()` function. This approach consolidates memory management + * in a single place, simplifying error handling and reducing the risk of + * memory leaks. + * + * The following rationale applies: + * + * - The input `struct llext` and fields in `struct loader` are zero-filled + * at the beginning of the do_llext_load function, so that every pointer is + * set to NULL and every bool is false. + * - If some function called by do_llext_load allocates memory, it does so by + * immediately writing the pointer in the `ext` and `ldr` structures. + * - do_llext_load() will clean up the memory allocated by the functions it + * calls, taking into account if the load process was successful or not. + */ + static const char ELF_MAGIC[] = {0x7f, 'E', 'L', 'F'}; elf_shdr_t *llext_section_by_name(struct llext_loader *ldr, const char *search_name) @@ -550,6 +568,12 @@ int do_llext_load(struct llext_loader *ldr, struct llext *ext, { int ret; + /* Zero all memory that is affected by the loading process + * (see the NOTICE at the top of this file). + */ + memset(ext, 0, sizeof(*ext)); + ldr->sect_map = NULL; + LOG_DBG("Loading ELF data..."); ret = llext_load_elf_data(ldr, ext); if (ret != 0) { @@ -628,20 +652,39 @@ int do_llext_load(struct llext_loader *ldr, struct llext *ext, } out: + /* + * Free resources only used during loading. Note that this exploits + * the fact that freeing a NULL pointer has no effect. + */ + llext_free(ldr->sect_map); + ldr->sect_map = NULL; + + /* Until proper inter-llext linking is implemented, the symbol table is + * not useful outside of the loading process; keep it only if debugging + * is enabled and no error is detected. + */ + if (!(IS_ENABLED(CONFIG_LLEXT_LOG_LEVEL_DBG) && ret == 0)) { + llext_free(ext->sym_tab.syms); + ext->sym_tab.sym_cnt = 0; + ext->sym_tab.syms = NULL; + } if (ret != 0) { - LOG_DBG("Failed to load extension, freeing memory..."); + LOG_DBG("Failed to load extension: %d", ret); + + /* Since the loading process failed, free the resources that + * were allocated for the lifetime of the extension as well, + * such as section data and exported symbols. + */ llext_free_sections(ext); llext_free(ext->exp_tab.syms); + ext->exp_tab.sym_cnt = 0; + ext->exp_tab.syms = NULL; } else { LOG_DBG("loaded module, .text at %p, .rodata at %p", ext->mem[LLEXT_MEM_TEXT], ext->mem[LLEXT_MEM_RODATA]); } - ext->sym_tab.sym_cnt = 0; - llext_free(ext->sym_tab.syms); - ext->sym_tab.syms = NULL; - return ret; } From 817bbda5ccd76deed1503df5b909751062d7f0f1 Mon Sep 17 00:00:00 2001 From: Luca Burelli Date: Wed, 12 Jun 2024 17:56:26 +0200 Subject: [PATCH 2685/2849] llext: read all section headers at once This change reads all section headers at once, instead of reading them one by one. This is more efficient and allows to further simplify the code downstream. The section headers are directly accessed from the file buffer if the llext_peek() function is supported by the loader. Otherwise, they are read into a buffer allocated on the heap and used only during the llext_load() function. Signed-off-by: Luca Burelli --- include/zephyr/llext/loader.h | 2 ++ subsys/llext/llext_load.c | 46 ++++++++++++++++++++++++++++++++--- 2 files changed, 45 insertions(+), 3 deletions(-) diff --git a/include/zephyr/llext/loader.h b/include/zephyr/llext/loader.h index 7eb49d611bed3..60f0e54058238 100644 --- a/include/zephyr/llext/loader.h +++ b/include/zephyr/llext/loader.h @@ -71,6 +71,8 @@ struct llext_loader { /** @cond ignore */ elf_ehdr_t hdr; elf_shdr_t sects[LLEXT_MEM_COUNT]; + elf_shdr_t *sect_hdrs; + bool sect_hdrs_on_heap; enum llext_mem *sect_map; uint32_t sect_cnt; /** @endcond */ diff --git a/subsys/llext/llext_load.c b/subsys/llext/llext_load.c index 0af584e2deff6..259b7a8f7f86b 100644 --- a/subsys/llext/llext_load.c +++ b/subsys/llext/llext_load.c @@ -107,6 +107,17 @@ static int llext_load_elf_data(struct llext_loader *ldr, struct llext *ext) return -EINVAL; } + /* + * Read all ELF section headers and initialize maps. Buffers allocated + * below are freed when leaving do_llext_load(), so don't count them in + * alloc_size. + */ + + if (ldr->hdr.e_shentsize != sizeof(elf_shdr_t)) { + LOG_ERR("Invalid section header size %d", ldr->hdr.e_shentsize); + return -EINVAL; + } + ldr->sect_cnt = ldr->hdr.e_shnum; memset(ldr->sects, 0, sizeof(ldr->sects)); @@ -115,12 +126,36 @@ static int llext_load_elf_data(struct llext_loader *ldr, struct llext *ext) ldr->sect_map = llext_alloc(sect_map_sz); if (!ldr->sect_map) { - LOG_ERR("Failed to allocate memory for section map, size %zu", sect_map_sz); + LOG_ERR("Failed to allocate section map, size %zu", sect_map_sz); return -ENOMEM; } - memset(ldr->sect_map, 0, sect_map_sz); - ext->alloc_size += sect_map_sz; + + ldr->sect_hdrs = llext_peek(ldr, ldr->hdr.e_shoff); + if (ldr->sect_hdrs) { + ldr->sect_hdrs_on_heap = false; + } else { + size_t sect_hdrs_sz = ldr->sect_cnt * sizeof(ldr->sect_hdrs[0]); + + ldr->sect_hdrs_on_heap = true; + ldr->sect_hdrs = llext_alloc(sect_hdrs_sz); + if (!ldr->sect_hdrs) { + LOG_ERR("Failed to allocate section headers, size %zu", sect_hdrs_sz); + return -ENOMEM; + } + + ret = llext_seek(ldr, ldr->hdr.e_shoff); + if (ret != 0) { + LOG_ERR("Failed to seek for section headers"); + return ret; + } + + ret = llext_read(ldr, ldr->sect_hdrs, sect_hdrs_sz); + if (ret != 0) { + LOG_ERR("Failed to read section headers"); + return ret; + } + } return 0; } @@ -660,6 +695,11 @@ int do_llext_load(struct llext_loader *ldr, struct llext *ext, llext_free(ldr->sect_map); ldr->sect_map = NULL; + if (ldr->sect_hdrs_on_heap) { + llext_free(ldr->sect_hdrs); + } + ldr->sect_hdrs = NULL; + /* Until proper inter-llext linking is implemented, the symbol table is * not useful outside of the loading process; keep it only if debugging * is enabled and no error is detected. From 08eb314c35d4b3bac7d62e1221cf793d10ba3e1f Mon Sep 17 00:00:00 2001 From: Luca Burelli Date: Fri, 7 Jun 2024 23:27:10 +0200 Subject: [PATCH 2686/2849] llext: refactor: use cached section headers The section headers are now available in the loader structure, so we can use those directly instead of reading them from the ELF file every time. This commit contains no logic changes; it removes all copies of the header loading code and replaces them with direct access to the cached section headers. Signed-off-by: Luca Burelli --- subsys/llext/llext_link.c | 34 +++------- subsys/llext/llext_load.c | 137 ++++++++++++-------------------------- 2 files changed, 54 insertions(+), 117 deletions(-) diff --git a/subsys/llext/llext_link.c b/subsys/llext/llext_link.c index 9fb484f8ddee0..51bb4ca171c05 100644 --- a/subsys/llext/llext_link.c +++ b/subsys/llext/llext_link.c @@ -163,35 +163,23 @@ static void llext_link_plt(struct llext_loader *ldr, struct llext *ext, int llext_link(struct llext_loader *ldr, struct llext *ext, bool do_local) { uintptr_t loc = 0; - elf_shdr_t shdr; elf_rela_t rel; elf_sym_t sym; elf_word rel_cnt = 0; const char *name; int i, ret; - size_t pos; - - for (i = 0, pos = ldr->hdr.e_shoff; - i < ldr->hdr.e_shnum - 1; - i++, pos += ldr->hdr.e_shentsize) { - ret = llext_seek(ldr, pos); - if (ret != 0) { - return ret; - } - ret = llext_read(ldr, &shdr, sizeof(elf_shdr_t)); - if (ret != 0) { - return ret; - } + for (i = 0; i < ldr->sect_cnt; ++i) { + elf_shdr_t *shdr = ldr->sect_hdrs + i; /* find relocation sections */ - if (shdr.sh_type != SHT_REL && shdr.sh_type != SHT_RELA) { + if (shdr->sh_type != SHT_REL && shdr->sh_type != SHT_RELA) { continue; } - rel_cnt = shdr.sh_size / shdr.sh_entsize; + rel_cnt = shdr->sh_size / shdr->sh_entsize; - name = llext_string(ldr, ext, LLEXT_MEM_SHSTRTAB, shdr.sh_name); + name = llext_string(ldr, ext, LLEXT_MEM_SHSTRTAB, shdr->sh_name); if (strcmp(name, ".rel.text") == 0) { loc = (uintptr_t)ext->mem[LLEXT_MEM_TEXT]; @@ -207,13 +195,13 @@ int llext_link(struct llext_loader *ldr, struct llext *ext, bool do_local) loc = (uintptr_t)ext->mem[LLEXT_MEM_EXPORT]; } else if (strcmp(name, ".rela.plt") == 0 || strcmp(name, ".rela.dyn") == 0) { - llext_link_plt(ldr, ext, &shdr, do_local, NULL); + llext_link_plt(ldr, ext, shdr, do_local, NULL); continue; } else if (strncmp(name, ".rela", 5) == 0 && strlen(name) > 5) { elf_shdr_t *tgt = llext_section_by_name(ldr, name + 5); if (tgt) - llext_link_plt(ldr, ext, &shdr, do_local, tgt); + llext_link_plt(ldr, ext, shdr, do_local, tgt); continue; } else if (strcmp(name, ".rel.dyn") == 0) { /* we assume that first load segment starts at MEM_TEXT */ @@ -221,16 +209,16 @@ int llext_link(struct llext_loader *ldr, struct llext *ext, bool do_local) } LOG_DBG("relocation section %s (%d) linked to section %d has %zd relocations", - name, i, shdr.sh_link, (size_t)rel_cnt); + name, i, shdr->sh_link, (size_t)rel_cnt); for (int j = 0; j < rel_cnt; j++) { /* get each relocation entry */ - ret = llext_seek(ldr, shdr.sh_offset + j * shdr.sh_entsize); + ret = llext_seek(ldr, shdr->sh_offset + j * shdr->sh_entsize); if (ret != 0) { return ret; } - ret = llext_read(ldr, &rel, shdr.sh_entsize); + ret = llext_read(ldr, &rel, shdr->sh_entsize); if (ret != 0) { return ret; } @@ -271,7 +259,7 @@ int llext_link(struct llext_loader *ldr, struct llext *ext, bool do_local) if (link_addr == 0) { LOG_ERR("Undefined symbol with no entry in " "symbol table %s, offset %zd, link section %d", - name, (size_t)rel.r_offset, shdr.sh_link); + name, (size_t)rel.r_offset, shdr->sh_link); return -ENODATA; } diff --git a/subsys/llext/llext_load.c b/subsys/llext/llext_load.c index 259b7a8f7f86b..d870ac6256d12 100644 --- a/subsys/llext/llext_load.c +++ b/subsys/llext/llext_load.c @@ -40,23 +40,17 @@ static const char ELF_MAGIC[] = {0x7f, 'E', 'L', 'F'}; elf_shdr_t *llext_section_by_name(struct llext_loader *ldr, const char *search_name) { - elf_shdr_t *shdr; - unsigned int i; - size_t pos; - - for (i = 0, pos = ldr->hdr.e_shoff; - i < ldr->hdr.e_shnum; - i++, pos += ldr->hdr.e_shentsize) { - shdr = llext_peek(ldr, pos); - if (!shdr) { - /* The peek() method isn't supported */ - return NULL; - } + int i; + for (i = 0; i < ldr->sect_cnt; ++i) { + elf_shdr_t *shdr = ldr->sect_hdrs + i; const char *name = llext_peek(ldr, ldr->sects[LLEXT_MEM_SHSTRTAB].sh_offset + shdr->sh_name); - + if (!name) { + /* The peek() method isn't supported */ + return NULL; + } if (!strcmp(name, search_name)) { return shdr; } @@ -120,8 +114,6 @@ static int llext_load_elf_data(struct llext_loader *ldr, struct llext *ext) ldr->sect_cnt = ldr->hdr.e_shnum; - memset(ldr->sects, 0, sizeof(ldr->sects)); - size_t sect_map_sz = ldr->sect_cnt * sizeof(ldr->sect_map[0]); ldr->sect_map = llext_alloc(sect_map_sz); @@ -165,58 +157,42 @@ static int llext_load_elf_data(struct llext_loader *ldr, struct llext *ext) */ static int llext_find_tables(struct llext_loader *ldr) { - int sect_cnt, i, ret; - size_t pos; - elf_shdr_t shdr; + int sect_cnt, i; - ldr->sects[LLEXT_MEM_SHSTRTAB] = - ldr->sects[LLEXT_MEM_STRTAB] = - ldr->sects[LLEXT_MEM_SYMTAB] = (elf_shdr_t){0}; + memset(ldr->sects, 0, sizeof(ldr->sects)); /* Find symbol and string tables */ - for (i = 0, sect_cnt = 0, pos = ldr->hdr.e_shoff; - i < ldr->hdr.e_shnum && sect_cnt < 3; - i++, pos += ldr->hdr.e_shentsize) { - ret = llext_seek(ldr, pos); - if (ret != 0) { - LOG_ERR("failed seeking to position %zu\n", pos); - return ret; - } - - ret = llext_read(ldr, &shdr, sizeof(elf_shdr_t)); - if (ret != 0) { - LOG_ERR("failed reading section header at position %zu\n", pos); - return ret; - } + for (i = 0, sect_cnt = 0; i < ldr->sect_cnt; ++i) { + elf_shdr_t *shdr = ldr->sect_hdrs + i; LOG_DBG("section %d at 0x%zx: name %d, type %d, flags 0x%zx, " "addr 0x%zx, size %zd, link %d, info %d", i, - (size_t)shdr.sh_offset, - shdr.sh_name, - shdr.sh_type, - (size_t)shdr.sh_flags, - (size_t)shdr.sh_addr, - (size_t)shdr.sh_size, - shdr.sh_link, - shdr.sh_info); - - switch (shdr.sh_type) { + (size_t)shdr->sh_offset, + shdr->sh_name, + shdr->sh_type, + (size_t)shdr->sh_flags, + (size_t)shdr->sh_addr, + (size_t)shdr->sh_size, + shdr->sh_link, + shdr->sh_info); + + switch (shdr->sh_type) { case SHT_SYMTAB: case SHT_DYNSYM: LOG_DBG("symtab at %d", i); - ldr->sects[LLEXT_MEM_SYMTAB] = shdr; + ldr->sects[LLEXT_MEM_SYMTAB] = *shdr; ldr->sect_map[i] = LLEXT_MEM_SYMTAB; sect_cnt++; break; case SHT_STRTAB: if (ldr->hdr.e_shstrndx == i) { LOG_DBG("shstrtab at %d", i); - ldr->sects[LLEXT_MEM_SHSTRTAB] = shdr; + ldr->sects[LLEXT_MEM_SHSTRTAB] = *shdr; ldr->sect_map[i] = LLEXT_MEM_SHSTRTAB; } else { LOG_DBG("strtab at %d", i); - ldr->sects[LLEXT_MEM_STRTAB] = shdr; + ldr->sects[LLEXT_MEM_STRTAB] = *shdr; ldr->sect_map[i] = LLEXT_MEM_STRTAB; } sect_cnt++; @@ -241,37 +217,25 @@ static int llext_find_tables(struct llext_loader *ldr) */ static int llext_map_sections(struct llext_loader *ldr, struct llext *ext) { - int i, j, ret; - size_t pos; - elf_shdr_t shdr; + int i, j; const char *name; - for (i = 0, pos = ldr->hdr.e_shoff; - i < ldr->hdr.e_shnum; - i++, pos += ldr->hdr.e_shentsize) { - ret = llext_seek(ldr, pos); - if (ret != 0) { - return ret; - } - - ret = llext_read(ldr, &shdr, sizeof(elf_shdr_t)); - if (ret != 0) { - return ret; - } + for (i = 0; i < ldr->sect_cnt; ++i) { + elf_shdr_t *shdr = ldr->sect_hdrs + i; - name = llext_string(ldr, ext, LLEXT_MEM_SHSTRTAB, shdr.sh_name); + name = llext_string(ldr, ext, LLEXT_MEM_SHSTRTAB, shdr->sh_name); /* Identify the section type by its flags */ enum llext_mem mem_idx; - switch (shdr.sh_type) { + switch (shdr->sh_type) { case SHT_NOBITS: mem_idx = LLEXT_MEM_BSS; break; case SHT_PROGBITS: - if (shdr.sh_flags & SHF_EXECINSTR) { + if (shdr->sh_flags & SHF_EXECINSTR) { mem_idx = LLEXT_MEM_TEXT; - } else if (shdr.sh_flags & SHF_WRITE) { + } else if (shdr->sh_flags & SHF_WRITE) { mem_idx = LLEXT_MEM_DATA; } else { mem_idx = LLEXT_MEM_RODATA; @@ -288,8 +252,8 @@ static int llext_map_sections(struct llext_loader *ldr, struct llext *ext) } if (mem_idx == LLEXT_MEM_COUNT || - !(shdr.sh_flags & SHF_ALLOC) || - shdr.sh_size == 0) { + !(shdr->sh_flags & SHF_ALLOC) || + shdr->sh_size == 0) { LOG_DBG("section %d name %s skipped", i, name); continue; } @@ -301,10 +265,10 @@ static int llext_map_sections(struct llext_loader *ldr, struct llext *ext) if (sect->sh_type == SHT_NULL) { /* First section of this type, copy all info */ - *sect = shdr; + memcpy(sect, shdr, sizeof(*sect)); } else { /* Make sure the sections are compatible before merging */ - if (shdr.sh_flags != sect->sh_flags) { + if (shdr->sh_flags != sect->sh_flags) { LOG_ERR("Unsupported section flags for %s (mem %d)", name, mem_idx); return -ENOEXEC; @@ -325,8 +289,8 @@ static int llext_map_sections(struct llext_loader *ldr, struct llext *ext) * merging these sections, make sure the delta * in VMAs matches that of file offsets. */ - if (shdr.sh_addr - sect->sh_addr != - shdr.sh_offset - sect->sh_offset) { + if (shdr->sh_addr - sect->sh_addr != + shdr->sh_offset - sect->sh_offset) { LOG_ERR("Incompatible section addresses " "for %s (mem %d)", name, mem_idx); return -ENOEXEC; @@ -337,10 +301,10 @@ static int llext_map_sections(struct llext_loader *ldr, struct llext *ext) * Extend the current section to include the new one * (overlaps are detected later) */ - size_t address = MIN(sect->sh_addr, shdr.sh_addr); - size_t bot_ofs = MIN(sect->sh_offset, shdr.sh_offset); + size_t address = MIN(sect->sh_addr, shdr->sh_addr); + size_t bot_ofs = MIN(sect->sh_offset, shdr->sh_offset); size_t top_ofs = MAX(sect->sh_offset + sect->sh_size, - shdr.sh_offset + shdr.sh_size); + shdr->sh_offset + shdr->sh_size); sect->sh_addr = address; sect->sh_offset = bot_ofs; @@ -552,30 +516,15 @@ static int llext_copy_symbols(struct llext_loader *ldr, struct llext *ext, base = ext->mem[ldr->sect_map[sect]]; section_addr = ldr->sects[ldr->sect_map[sect]].sh_addr; } else { - /* Section header isn't stored, have to read it */ - size_t shdr_pos = ldr->hdr.e_shoff + sect * ldr->hdr.e_shentsize; - elf_shdr_t shdr; - - ret = llext_seek(ldr, shdr_pos); - if (ret != 0) { - LOG_ERR("failed seeking to position %zu\n", shdr_pos); - return ret; - } - - ret = llext_read(ldr, &shdr, sizeof(elf_shdr_t)); - if (ret != 0) { - LOG_ERR("failed reading section header at position %zu\n", - shdr_pos); - return ret; - } + elf_shdr_t *shdr = ldr->sect_hdrs + sect; - base = llext_peek(ldr, shdr.sh_offset); + base = llext_peek(ldr, shdr->sh_offset); if (!base) { LOG_ERR("cannot handle arbitrary sections without .peek\n"); return -EOPNOTSUPP; } - section_addr = shdr.sh_addr; + section_addr = shdr->sh_addr; } if (pre_located) { From 895ef1d6c5466a900264163b5191a183c05d7dbd Mon Sep 17 00:00:00 2001 From: Francois Ramu Date: Mon, 11 Mar 2024 17:48:58 +0100 Subject: [PATCH 2687/2849] drivers: hwinfo: stm32 driver supports the stm32h7rs serie Add the support of the stm32h7rs serie to the HWinfo driver. UID base is 0x8FFF800 Signed-off-by: Francois Ramu --- drivers/hwinfo/hwinfo_stm32.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/hwinfo/hwinfo_stm32.c b/drivers/hwinfo/hwinfo_stm32.c index 75029d7495ceb..239e54972f7e3 100644 --- a/drivers/hwinfo/hwinfo_stm32.c +++ b/drivers/hwinfo/hwinfo_stm32.c @@ -150,7 +150,7 @@ int z_impl_hwinfo_get_reset_cause(uint32_t *cause) if (LL_PWR_IsActiveFlag_C1SB()) { flags |= RESET_LOW_POWER_WAKE; } -#elif defined(PWR_FLAG_SB) +#elif defined(PWR_FLAG_SB) || defined(PWR_FLAG_SBF) if (LL_PWR_IsActiveFlag_SB()) { flags |= RESET_LOW_POWER_WAKE; } @@ -169,6 +169,8 @@ int z_impl_hwinfo_clear_reset_cause(void) LL_PWR_ClearFlag_CPU2(); #elif defined(CONFIG_SOC_SERIES_STM32H7X) && defined(CORE_CM7) LL_PWR_ClearFlag_CPU(); +#elif defined(CONFIG_SOC_SERIES_STM32H7RSX) + LL_PWR_ClearFlag_STOP_SB(); #elif defined(CONFIG_SOC_SERIES_STM32MP1X) LL_PWR_ClearFlag_MCU(); #elif defined(CONFIG_SOC_SERIES_STM32WLX) || defined(CONFIG_SOC_SERIES_STM32WBX) From 24ff13e92ca39055877aa57b366a33b982d70d02 Mon Sep 17 00:00:00 2001 From: Francois Ramu Date: Mon, 11 Mar 2024 17:46:54 +0100 Subject: [PATCH 2688/2849] drivers: watchdog: stm32 wdg driver support stm32H7RS serie Add the stm32h7rs serie to the stm32 WDG driver Signed-off-by: Francois Ramu --- drivers/watchdog/wdt_iwdg_stm32.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/watchdog/wdt_iwdg_stm32.c b/drivers/watchdog/wdt_iwdg_stm32.c index bafd8f579df6c..6c6846abf61fa 100644 --- a/drivers/watchdog/wdt_iwdg_stm32.c +++ b/drivers/watchdog/wdt_iwdg_stm32.c @@ -99,6 +99,8 @@ static int iwdg_stm32_setup(const struct device *dev, uint8_t options) #endif #if defined(CONFIG_SOC_SERIES_STM32H7X) LL_DBGMCU_APB4_GRP1_FreezePeriph(LL_DBGMCU_APB4_GRP1_IWDG1_STOP); +#elif defined(CONFIG_SOC_SERIES_STM32H7RSX) + LL_DBGMCU_APB4_GRP1_FreezePeriph(LL_DBGMCU_APB4_GRP1_IWDG_STOP); #else LL_DBGMCU_APB1_GRP1_FreezePeriph(LL_DBGMCU_APB1_GRP1_IWDG_STOP); #endif From da8a812582446e94c6a8d4cd677aab91c8b42678 Mon Sep 17 00:00:00 2001 From: Francois Ramu Date: Thu, 7 Mar 2024 11:58:27 +0100 Subject: [PATCH 2689/2849] drivers: adc: stm32 adc driver supporting the stm32H7RS Introduce the stm32h7RS serie to the ADC driver, based on the stm32h7: two ADC 12 resolution For stm32h7rs ADC calibration, the LL_ADC_SetCalibrationFactor is not used. Signed-off-by: Francois Ramu --- drivers/adc/adc_stm32.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/adc/adc_stm32.c b/drivers/adc/adc_stm32.c index 1ed8db1c54abc..3e5c67ad4586d 100644 --- a/drivers/adc/adc_stm32.c +++ b/drivers/adc/adc_stm32.c @@ -46,7 +46,7 @@ LOG_MODULE_REGISTER(adc_stm32); #include #include -#ifdef CONFIG_SOC_SERIES_STM32H7X +#if defined(CONFIG_SOC_SERIES_STM32H7X) || defined(CONFIG_SOC_SERIES_STM32H7RSX) #include #endif @@ -522,6 +522,7 @@ static void adc_stm32_calibration_start(const struct device *dev) defined(CONFIG_SOC_SERIES_STM32L4X) || \ defined(CONFIG_SOC_SERIES_STM32L5X) || \ defined(CONFIG_SOC_SERIES_STM32H5X) || \ + defined(CONFIG_SOC_SERIES_STM32H7RSX) || \ defined(CONFIG_SOC_SERIES_STM32WBX) || \ defined(CONFIG_SOC_SERIES_STM32G4X) LL_ADC_StartCalibration(adc, LL_ADC_SINGLE_ENDED); @@ -556,6 +557,7 @@ static int adc_stm32_calibrate(const struct device *dev) #if defined(CONFIG_SOC_SERIES_STM32C0X) || \ defined(CONFIG_SOC_SERIES_STM32F0X) || \ defined(CONFIG_SOC_SERIES_STM32G0X) || \ + defined(CONFIG_SOC_SERIES_STM32H7RSX) || \ defined(CONFIG_SOC_SERIES_STM32L0X) || \ defined(CONFIG_SOC_SERIES_STM32WBAX) || \ defined(CONFIG_SOC_SERIES_STM32WLX) @@ -606,6 +608,7 @@ static int adc_stm32_calibrate(const struct device *dev) linear_calib_buffer = *(uint32_t *)( ADC_LINEAR_CALIB_REG_1_ADDR + channel_offset + count ); + LL_ADC_SetCalibrationLinearFactor( adc, LL_ADC_CALIB_LINEARITY_WORD1 << count, linear_calib_buffer @@ -1425,6 +1428,7 @@ static int adc_stm32_init(const struct device *dev) defined(CONFIG_SOC_SERIES_STM32G4X) || \ defined(CONFIG_SOC_SERIES_STM32H5X) || \ defined(CONFIG_SOC_SERIES_STM32H7X) || \ + defined(CONFIG_SOC_SERIES_STM32H7RSX) || \ defined(CONFIG_SOC_SERIES_STM32U5X) /* * L4, WB, G4, H5, H7 and U5 series STM32 needs to be awaken from deep sleep @@ -1485,6 +1489,7 @@ static int adc_stm32_suspend_setup(const struct device *dev) defined(CONFIG_SOC_SERIES_STM32G4X) || \ defined(CONFIG_SOC_SERIES_STM32H5X) || \ defined(CONFIG_SOC_SERIES_STM32H7X) || \ + defined(CONFIG_SOC_SERIES_STM32H7RSX) || \ defined(CONFIG_SOC_SERIES_STM32U5X) /* * L4, WB, G4, H5, H7 and U5 series STM32 needs to be put into From b014150508a79b98042f15b2acd668112884869b Mon Sep 17 00:00:00 2001 From: Francois Ramu Date: Thu, 14 Mar 2024 09:04:40 +0100 Subject: [PATCH 2690/2849] drivers: flash: stm32h7 flash driver supports the stm32h7rs serie Add the support of the stm32h7rs serie to the flash stm32h7 driver Remap Flash registers to the stm32h7rs serie. Signed-off-by: Francois Ramu --- drivers/flash/CMakeLists.txt | 2 ++ drivers/flash/flash_stm32.h | 11 ++++++++++ drivers/flash/flash_stm32h7x.c | 38 ++++++++++++++++++++++++++++++++-- 3 files changed, 49 insertions(+), 2 deletions(-) diff --git a/drivers/flash/CMakeLists.txt b/drivers/flash/CMakeLists.txt index 744a6a5862c85..76ee659d0b133 100644 --- a/drivers/flash/CMakeLists.txt +++ b/drivers/flash/CMakeLists.txt @@ -73,6 +73,8 @@ endif() if(CONFIG_SOC_FLASH_STM32) if(CONFIG_SOC_SERIES_STM32H7X) zephyr_library_sources_ifdef(CONFIG_DT_HAS_ST_STM32H7_FLASH_CONTROLLER_ENABLED flash_stm32h7x.c) + elseif(CONFIG_SOC_SERIES_STM32H7RSX) + zephyr_library_sources_ifdef(CONFIG_DT_HAS_ST_STM32H7_FLASH_CONTROLLER_ENABLED flash_stm32h7x.c) elseif(CONFIG_SOC_SERIES_STM32WBAX) if(CONFIG_BT_STM32WBA) # BLE is enabled. Use implementation over Flash Manager for coexistence wit RF activities diff --git a/drivers/flash/flash_stm32.h b/drivers/flash/flash_stm32.h index 3583a1379c6cd..ca08b7e16ae1c 100644 --- a/drivers/flash/flash_stm32.h +++ b/drivers/flash/flash_stm32.h @@ -45,6 +45,17 @@ struct flash_stm32_priv { #define OPTR OPTCR #endif /* CONFIG_SOC_SERIES_STM32H5X */ +/* Register mapping for the stm32H7RS serie (single bank)*/ +#if defined(CONFIG_SOC_SERIES_STM32H7RSX) +#define FLASH_NB_32BITWORD_IN_FLASHWORD 4 /* 128 bits */ +#define CR1 CR +#define SR1 SR +/* flash sectore Nb [0-7] */ +#define FLASH_CR_SNB FLASH_CR_SSN +#define FLASH_CR_SNB_Pos FLASH_CR_SSN_Pos +#define KEYR1 KEYR +#endif /* CONFIG_SOC_SERIES_STM32H7RSX */ + /* Differentiate between arm trust-zone non-secure/secure, and others. */ #if defined(FLASH_NSSR_NSBSY) || defined(FLASH_NSSR_BSY) /* For mcu w. TZ in non-secure mode */ #define FLASH_SECURITY_NS diff --git a/drivers/flash/flash_stm32h7x.c b/drivers/flash/flash_stm32h7x.c index 271bb413194cd..8896fa7433fd6 100644 --- a/drivers/flash/flash_stm32h7x.c +++ b/drivers/flash/flash_stm32h7x.c @@ -14,8 +14,13 @@ #include #include #include +#if defined(CONFIG_SOC_SERIES_STM32H7RSX) +#include +#include +#else #include #include +#endif /* CONFIG_SOC_SERIES_STM32H7RSX */ #include "flash_stm32.h" #include "stm32_hsem.h" @@ -117,14 +122,41 @@ static int flash_stm32_check_status(const struct device *dev) * ECC errors. Corrected data is returned for single ECC * errors, so in this case we just log a warning. */ - uint32_t const error_bank1 = (FLASH_FLAG_ALL_ERRORS_BANK1 - & ~FLASH_FLAG_SNECCERR_BANK1); #ifdef DUAL_BANK uint32_t const error_bank2 = (FLASH_FLAG_ALL_ERRORS_BANK2 & ~FLASH_FLAG_SNECCERR_BANK2); #endif uint32_t sr; +#if defined(CONFIG_SOC_SERIES_STM32H7RSX) + uint32_t const error_bank = (FLASH_FLAG_ECC_ERRORS + & ~FLASH_FLAG_SNECCERR + & ~FLASH_FLAG_DBECCERR); + + + /* Read the Interrupt status flags. */ + sr = regs->ISR; + if (sr & (FLASH_FLAG_SNECCERR)) { + uint32_t word = regs->ECCSFADDR & FLASH_ECCSFADDR_SEC_FADD; + + LOG_WRN("Bank%d ECC error at 0x%08x", 1, + word * 4 * FLASH_NB_32BITWORD_IN_FLASHWORD); + } + + if (sr & (FLASH_FLAG_DBECCERR)) { + uint32_t word = regs->ECCDFADDR & FLASH_ECCDFADDR_DED_FADD; + + LOG_WRN("Bank%d ECC error at 0x%08x", 1, + word * 4 * FLASH_NB_32BITWORD_IN_FLASHWORD); + } + + /* Clear the ECC flags (including FA) */ + regs->ICR = FLASH_FLAG_ECC_ERRORS; + if (sr & error_bank) { +#else + uint32_t const error_bank1 = (FLASH_FLAG_ALL_ERRORS_BANK1 + & ~FLASH_FLAG_SNECCERR_BANK1); + /* Read the status flags. */ sr = regs->SR1; if (sr & (FLASH_FLAG_SNECCERR_BANK1|FLASH_FLAG_DBECCERR_BANK1)) { @@ -135,7 +167,9 @@ static int flash_stm32_check_status(const struct device *dev) } /* Clear the flags (including FA1R) */ regs->CCR1 = FLASH_FLAG_ALL_BANK1; + if (sr & error_bank1) { +#endif /* CONFIG_SOC_SERIES_STM32H7RSX */ LOG_ERR("Status Bank%d: 0x%08x", 1, sr); return -EIO; } From 4ade2a88e4de82253453ed84a91ea6bdaaa67216 Mon Sep 17 00:00:00 2001 From: Francois Ramu Date: Thu, 30 May 2024 13:27:58 +0200 Subject: [PATCH 2691/2849] dts: arm: stm32h7 add wdg and adc, rng node to stm32h7R/h7S devices Add the IWDG and WWDG watchdog peripherals the ADC1 & 2 peripherals with sensor for die temperature and voltage the RNG entropy generator Signed-off-by: Francois Ramu --- dts/arm/st/h7rs/stm32h7rs.dtsi | 92 ++++++++++++++++++++++++++++++++++ 1 file changed, 92 insertions(+) diff --git a/dts/arm/st/h7rs/stm32h7rs.dtsi b/dts/arm/st/h7rs/stm32h7rs.dtsi index d0f5712eb263b..35432a9b91510 100644 --- a/dts/arm/st/h7rs/stm32h7rs.dtsi +++ b/dts/arm/st/h7rs/stm32h7rs.dtsi @@ -11,6 +11,8 @@ #include #include #include +#include +#include #include #include #include @@ -21,6 +23,7 @@ / { chosen { + zephyr,entropy = &rng; zephyr,flash-controller = &flash; }; @@ -160,9 +163,18 @@ compatible = "st,stm32-flash-controller", "st,stm32h7-flash-controller"; reg = <0x52002000 0x400>; interrupts = <8 0>; + clocks = <&rcc STM32_CLOCK_BUS_AHB3 0x00000100>; #address-cells = <1>; #size-cells = <1>; + + flash0: flash@8000000 { + compatible = "st,stm32-nv-flash", "soc-nv-flash"; + write-block-size = <32>; + erase-block-size = ; + /* maximum erase time for a 8K sector */ + max-erase-time = <3>; + }; }; rcc: rcc@58024400 { @@ -467,6 +479,21 @@ status = "disabled"; }; + iwdg: iwdg1: watchdog@58004800 { + compatible = "st,stm32-watchdog"; + reg = <0x58004800 0x400>; + interrupts = <3 0>; + status = "disabled"; + }; + + wwdg: wwdg1: watchdog@40002c00 { + compatible = "st,stm32-window-watchdog"; + reg = <0x40002c00 0x1000>; + clocks = <&rcc STM32_CLOCK_BUS_APB1 0x00000800>; + interrupts = <4 7>; + status = "disabled"; + }; + timers1: timers@42000000 { compatible = "st,stm32-timers"; reg = <0x42000000 0x400>; @@ -696,6 +723,71 @@ interrupt-names = "wakeup"; status = "disabled"; }; + + adc1: adc@40022000 { + compatible = "st,stm32-adc"; + reg = <0x40022000 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_AHB1 0x00000020>; + interrupts = <38 0>; + status = "disabled"; + #io-channel-cells = <1>; + resolutions = ; + sampling-times = <3 7 13 25 48 93 248 641>; + st,adc-sequencer = ; + }; + + adc2: adc@40022100 { + compatible = "st,stm32-adc"; + reg = <0x40022100 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_AHB1 0x00000020>; + interrupts = <38 0>; + status = "disabled"; + #io-channel-cells = <1>; + resolutions = ; + sampling-times = <3 7 13 25 48 93 248 641>; + st,adc-sequencer = ; + }; + + rng: rng@48020000 { + compatible = "st,stm32-rng"; + reg = <0x48020000 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_AHB3 0x00000001>; + interrupts = <37 0>; + status = "disabled"; + }; + }; + + die_temp: dietemp { + compatible = "st,stm32-temp-cal"; + ts-cal1-addr = <0x08FFF814>; + ts-cal2-addr = <0x08FFF818>; + ts-cal1-temp = <30>; + ts-cal2-temp = <130>; + ts-cal-vrefanalog = <3300>; + ts-cal-resolution = <12>; + io-channels = <&adc1 16>; + status = "disabled"; + }; + + vbat: vbat { + compatible = "st,stm32-vbat"; + ratio = <4>; + status = "disabled"; + io-channels = <&adc2 16>; + }; + + vref: vref { + compatible = "st,stm32-vref"; + vrefint-cal-addr = <0x08fff810>; + vrefint-cal-mv = <3300>; + status = "disabled"; + io-channels = <&adc1 17>; }; }; From e78cdc823d2f4b5168ca8b62eac1bec604afd701 Mon Sep 17 00:00:00 2001 From: Francois Ramu Date: Mon, 27 May 2024 11:11:43 +0200 Subject: [PATCH 2692/2849] boards: arm: stm32h7s78 disco kit supporting more features Add the ADC, WDG, entropy features to the stm32h7s78_dk disco kit Signed-off-by: Francois Ramu --- boards/st/stm32h7s78_dk/doc/index.rst | 6 +++ boards/st/stm32h7s78_dk/stm32h7s78_dk.dts | 44 +++++++++++++++++++ .../{stm32h7s78.yaml => stm32h7s78_dk.yaml} | 3 ++ 3 files changed, 53 insertions(+) rename boards/st/stm32h7s78_dk/{stm32h7s78.yaml => stm32h7s78_dk.yaml} (84%) diff --git a/boards/st/stm32h7s78_dk/doc/index.rst b/boards/st/stm32h7s78_dk/doc/index.rst index 3cea4994c779c..8951ba16fdcd8 100644 --- a/boards/st/stm32h7s78_dk/doc/index.rst +++ b/boards/st/stm32h7s78_dk/doc/index.rst @@ -168,9 +168,15 @@ hardware features: +-----------+------------+-------------------------------------+ | PINMUX | on-chip | pinmux | +-----------+------------+-------------------------------------+ +| RNG | on-chip | True Random number generator | ++-----------+------------+-------------------------------------+ | UART | on-chip | serial port-polling; | | | | serial port-interrupt | +-----------+------------+-------------------------------------+ +| WATCHDOG | on-chip | independent watchdog | ++-----------+------------+-------------------------------------+ +| ADC | on-chip | ADC Controller | ++-----------+------------+-------------------------------------+ | SPI | on-chip | spi bus | +-----------+------------+-------------------------------------+ diff --git a/boards/st/stm32h7s78_dk/stm32h7s78_dk.dts b/boards/st/stm32h7s78_dk/stm32h7s78_dk.dts index d8bb4444b184a..6cd70cbe60d07 100644 --- a/boards/st/stm32h7s78_dk/stm32h7s78_dk.dts +++ b/boards/st/stm32h7s78_dk/stm32h7s78_dk.dts @@ -53,6 +53,10 @@ aliases { led0 = &blue_led; sw0 = &user_button; + watchdog0 = &iwdg; + die-temp0 = &die_temp; + volt-sensor0 = &vref; + volt-sensor1 = &vbat; }; }; @@ -129,6 +133,34 @@ }; }; +&rng { + status = "okay"; +}; + +&iwdg { + status = "okay"; +}; + +&wwdg { + status = "okay"; +}; + +&adc1 { + pinctrl-0 = <&adc1_inp6_pf12>; /* Arduino A3 */ + pinctrl-names = "default"; + st,adc-clock-source = ; + st,adc-prescaler = <4>; + status = "okay"; +}; + +&adc2 { + pinctrl-0 = <&adc2_inp2_pf13>; /* Arduino A4 */ + pinctrl-names = "default"; + st,adc-clock-source = ; + st,adc-prescaler = <4>; + status = "okay"; +}; + &spi4 { pinctrl-0 = <&spi4_nss_pe4 &spi4_sck_pe12 &spi4_miso_pe13 &spi4_mosi_pe14>; @@ -140,3 +172,15 @@ pinctrl-0 = <&i2c1_scl_pb6 &i2c1_sda_pb9>; pinctrl-names = "default"; }; + +&die_temp { + status = "okay"; +}; + +&vref { + status = "okay"; +}; + +&vbat { + status = "okay"; +}; diff --git a/boards/st/stm32h7s78_dk/stm32h7s78.yaml b/boards/st/stm32h7s78_dk/stm32h7s78_dk.yaml similarity index 84% rename from boards/st/stm32h7s78_dk/stm32h7s78.yaml rename to boards/st/stm32h7s78_dk/stm32h7s78_dk.yaml index 16df86085ca4c..e48895cbce1bb 100644 --- a/boards/st/stm32h7s78_dk/stm32h7s78.yaml +++ b/boards/st/stm32h7s78_dk/stm32h7s78_dk.yaml @@ -10,4 +10,7 @@ supported: - arduino_gpio - gpio - uart + - watchdog + - entropy + - adc vendor: st From 2146813cb3268c455e21f4fbd34d0be5f7dfddcb Mon Sep 17 00:00:00 2001 From: Francois Ramu Date: Fri, 7 Jun 2024 16:49:27 +0200 Subject: [PATCH 2693/2849] tests: drivers: adc stm32 api testing on the stm32h7s78 disco kit add the stm32h7s78_dk disco kit to run the tests drivers This testcase is executed (XiP) from the external NOR of the stm32h7s78_dk board. Signed-off-by: Francois Ramu --- .../adc/adc_api/boards/stm32h7s78_dk.overlay | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 tests/drivers/adc/adc_api/boards/stm32h7s78_dk.overlay diff --git a/tests/drivers/adc/adc_api/boards/stm32h7s78_dk.overlay b/tests/drivers/adc/adc_api/boards/stm32h7s78_dk.overlay new file mode 100644 index 0000000000000..3464f131f8190 --- /dev/null +++ b/tests/drivers/adc/adc_api/boards/stm32h7s78_dk.overlay @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2024 STMicroelectronics4 + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + zephyr,user { + /* adjust channel number according to pinmux in board.dts */ + io-channels = <&adc1 6>; + }; +}; + +&adc1 { + pinctrl-0 = <&adc1_inp6_pf12>; /* Arduino A3 */ + + #address-cells = <1>; + #size-cells = <0>; + + channel@6 { + reg = <6>; + zephyr,gain = "ADC_GAIN_1"; + zephyr,reference = "ADC_REF_INTERNAL"; + zephyr,acquisition-time = ; + zephyr,resolution = <12>; + }; +}; From 3cf630fb0bcf5d95a735170a43608aea8e619d31 Mon Sep 17 00:00:00 2001 From: Johann Fischer Date: Sat, 2 Jun 2018 00:48:08 +0200 Subject: [PATCH 2694/2849] driver: add SWDP driver interface API and bit-bang driver Add Serial Wire Debug Port interface driver API and bit-bang driver. The driver requires a simple Hardware Interface Circuits (HICs), where signals CLK, DOUT, DIN, ENn, OE_ENn, RESETn are connected to board GPIOs and buffered signals SWD_CLK and SWD_DIO to the target. Signal OE_ENn controls the direction of the Serial Wire (SWD_DIO), ENn the buffers SWD_CLK possibly others and enables/disables HIC. Signed-off-by: Johann Fischer Signed-off-by: Johann Fischer --- drivers/CMakeLists.txt | 1 + drivers/Kconfig | 1 + drivers/dp/CMakeLists.txt | 5 + drivers/dp/Kconfig | 30 ++ drivers/dp/swdp_bitbang.c | 633 ++++++++++++++++++++++++ dts/bindings/misc/zephyr,swdp-gpio.yaml | 46 ++ include/zephyr/drivers/swdp.h | 92 ++++ 7 files changed, 808 insertions(+) create mode 100644 drivers/dp/CMakeLists.txt create mode 100644 drivers/dp/Kconfig create mode 100644 drivers/dp/swdp_bitbang.c create mode 100644 dts/bindings/misc/zephyr,swdp-gpio.yaml create mode 100644 include/zephyr/drivers/swdp.h diff --git a/drivers/CMakeLists.txt b/drivers/CMakeLists.txt index e1dbab7e1a201..7332e1e354181 100644 --- a/drivers/CMakeLists.txt +++ b/drivers/CMakeLists.txt @@ -31,6 +31,7 @@ add_subdirectory_ifdef(CONFIG_DAC dac) add_subdirectory_ifdef(CONFIG_DAI dai) add_subdirectory_ifdef(CONFIG_DISPLAY display) add_subdirectory_ifdef(CONFIG_DMA dma) +add_subdirectory_ifdef(CONFIG_DP_DRIVER dp) add_subdirectory_ifdef(CONFIG_EDAC edac) add_subdirectory_ifdef(CONFIG_EEPROM eeprom) add_subdirectory_ifdef(CONFIG_ENTROPY_GENERATOR entropy) diff --git a/drivers/Kconfig b/drivers/Kconfig index ac07add3c1f5c..b1aec9de129fe 100644 --- a/drivers/Kconfig +++ b/drivers/Kconfig @@ -24,6 +24,7 @@ source "drivers/dai/Kconfig" source "drivers/disk/Kconfig" source "drivers/display/Kconfig" source "drivers/dma/Kconfig" +source "drivers/dp/Kconfig" source "drivers/edac/Kconfig" source "drivers/eeprom/Kconfig" source "drivers/entropy/Kconfig" diff --git a/drivers/dp/CMakeLists.txt b/drivers/dp/CMakeLists.txt new file mode 100644 index 0000000000000..dd49b759ab817 --- /dev/null +++ b/drivers/dp/CMakeLists.txt @@ -0,0 +1,5 @@ +# Copyright (c) 2019, PHYTEC Messtechnik GmbH +# SPDX-License-Identifier: Apache-2.0 + +zephyr_library() +zephyr_library_sources_ifdef(CONFIG_SWDP_BITBANG_DRIVER swdp_bitbang.c) diff --git a/drivers/dp/Kconfig b/drivers/dp/Kconfig new file mode 100644 index 0000000000000..77e33811a3930 --- /dev/null +++ b/drivers/dp/Kconfig @@ -0,0 +1,30 @@ +# Copyright (c) 2019 Phytec Messtechnik GmbH +# +# SPDX-License-Identifier: Apache-2.0 + +menuconfig DP_DRIVER + bool "Debug Port interface driver [EXPERIMENTAL]" + select EXPERIMENTAL + help + Enable Debug Port interface driver + +if DP_DRIVER + +module = DP_DRIVER +module-str = dp drv +source "subsys/logging/Kconfig.template.log_config" + +config DP_DRIVER_INIT_PRIO + int "Debug Port driver initialization priority" + default 80 + help + Set the initialization priority number. + +config SWDP_BITBANG_DRIVER + bool "Serial Wire Debug Port bit-bang driver" + default y + depends on DT_HAS_ZEPHYR_SWDP_GPIO_ENABLED + help + Serial Wire Debug Port bit-bang driver. + +endif # DP_DRIVER diff --git a/drivers/dp/swdp_bitbang.c b/drivers/dp/swdp_bitbang.c new file mode 100644 index 0000000000000..6da04655cc011 --- /dev/null +++ b/drivers/dp/swdp_bitbang.c @@ -0,0 +1,633 @@ +/* + * Copyright (c) 2018-2019 PHYTEC Messtechnik GmbH + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* + * This file is based on SW_DP.c from CMSIS-DAP Source (Revision: V2.0.0) + * https://github.com/ARM-software/CMSIS_5/tree/develop/CMSIS/DAP/Firmware + * Copyright (c) 2013-2017, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + */ + + +/* Serial Wire Debug Port interface bit-bang driver */ + +#define DT_DRV_COMPAT zephyr_swdp_gpio + +#include +#include +#include + +#include +LOG_MODULE_REGISTER(swdp, CONFIG_DP_DRIVER_LOG_LEVEL); + +#if defined(CONFIG_SOC_SERIES_NRF52X) +#define CPU_CLOCK 64000000U +#else +#define CPU_CLOCK CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC +#endif + +#define CLOCK_DELAY(swclk_freq, port_write_cycles) \ + ((CPU_CLOCK / 2 / swclk_freq) - port_write_cycles) + +/* + * Default SWCLK frequency in Hz. + * sw_clock can be used to overwrite this default value. + */ +#define SWDP_DEFAULT_SWCLK_FREQUENCY 1000000U + +#define DELAY_SLOW_CYCLES 3U + +struct sw_config { + struct gpio_dt_spec clk; + struct gpio_dt_spec dout; + struct gpio_dt_spec din; + struct gpio_dt_spec dnoe; + struct gpio_dt_spec noe; + struct gpio_dt_spec reset; + uint32_t port_write_cycles; + void *clk_reg; + void *dout_reg; + void *din_reg; + void *dnoe_reg; +}; + +struct sw_cfg_data { + uint32_t clock_delay; + uint8_t turnaround; + bool data_phase; + bool fast_clock; +}; + +static uint8_t sw_request_lut[16] = {0U}; + +static void mk_sw_request_lut(void) +{ + uint32_t parity = 0U; + + for (int request = 0; request < sizeof(sw_request_lut); request++) { + parity = request; + parity ^= parity >> 2; + parity ^= parity >> 1; + + /* + * Move A[3:3], RnW, APnDP bits to their position, + * add start bit, stop bit(6), and park bit. + */ + sw_request_lut[request] = BIT(7) | (request << 1) | BIT(0); + /* Add parity bit */ + if (parity & 0x01U) { + sw_request_lut[request] |= BIT(5); + } + } + + LOG_HEXDUMP_DBG(sw_request_lut, sizeof(sw_request_lut), "request lut"); +} + +static ALWAYS_INLINE uint32_t sw_get32bit_parity(uint32_t data) +{ + data ^= data >> 16; + data ^= data >> 8; + data ^= data >> 4; + data ^= data >> 2; + data ^= data >> 1; + + return data & 1U; +} + +static ALWAYS_INLINE void pin_delay_asm(uint32_t delay) +{ +#if defined(CONFIG_SOC_SERIES_NRF52X) + __asm volatile ("movs r3, %[p]\n" + ".start_%=:\n" + "subs r3, #1\n" + "bne .start_%=\n" + : + : [p] "r" (delay) + : "r3", "cc" + ); +#else +#error "Not defined for this SoC family" +#endif +} + +static ALWAYS_INLINE void pin_platform_set(void *base, uint8_t pin) +{ +#if defined(CONFIG_SOC_SERIES_NRF52X) + NRF_GPIO_Type * reg = base; + + reg->OUTSET = BIT(pin); +#else +#error "Not defined for this SoC family" +#endif +} + +static ALWAYS_INLINE void pin_platform_clr(void *base, uint8_t pin) +{ +#if defined(CONFIG_SOC_SERIES_NRF52X) + NRF_GPIO_Type * reg = base; + + reg->OUTCLR = BIT(pin); +#else +#error "Not defined for this SoC family" +#endif +} + +static ALWAYS_INLINE uint32_t pin_platform_get(void *base, uint8_t pin) +{ +#if defined(CONFIG_SOC_SERIES_NRF52X) + NRF_GPIO_Type * reg = base; + + return ((reg->IN >> pin) & 1); +#else +#error "Not defined for this SoC family" +#endif +} + +/* Set SWCLK DAP hardware output pin to high level */ +static ALWAYS_INLINE void pin_swclk_set(const struct device *dev) +{ + const struct sw_config *config = dev->config; + const struct gpio_dt_spec *dt_spec = &config->clk; + + pin_platform_set(config->clk_reg, dt_spec->pin); +} + +/* Set SWCLK DAP hardware output pin to low level */ +static ALWAYS_INLINE void pin_swclk_clr(const struct device *dev) +{ + const struct sw_config *config = dev->config; + const struct gpio_dt_spec *dt_spec = &config->clk; + + pin_platform_clr(config->clk_reg, dt_spec->pin); +} + +/* Set the SWDIO DAP hardware output pin to high level */ +static ALWAYS_INLINE void pin_swdio_set(const struct device *dev) +{ + const struct sw_config *config = dev->config; + const struct gpio_dt_spec *dt_spec = &config->dout; + + pin_platform_set(config->dout_reg, dt_spec->pin); +} + +/* Set the SWDIO DAP hardware output pin to low level */ +static ALWAYS_INLINE void pin_swdio_clr(const struct device *dev) +{ + const struct sw_config *config = dev->config; + const struct gpio_dt_spec *dt_spec = &config->dout; + + pin_platform_clr(config->dout_reg, dt_spec->pin); +} + +/* Set the SWDIO DAP hardware output pin to bit level */ +static ALWAYS_INLINE void pin_swdio_out(const struct device *dev, + const uint32_t bit) +{ + const struct sw_config *config = dev->config; + const struct gpio_dt_spec *dt_spec = &config->dout; + + if (bit & 1U) { + pin_platform_set(config->dout_reg, dt_spec->pin); + } else { + pin_platform_clr(config->dout_reg, dt_spec->pin); + } +} + +/* Return current level of the SWDIO DAP hardware input pin */ +static ALWAYS_INLINE uint32_t pin_swdio_in(const struct device *dev) +{ + const struct sw_config *config = dev->config; + const struct gpio_dt_spec *dt_spec = &config->din; + + return pin_platform_get(config->din_reg, dt_spec->pin); +} + +/* + * Configure the SWDIO DAP hardware to output mode. + * This is default configuration for every transfer. + */ +static ALWAYS_INLINE void pin_swdio_out_enable(const struct device *dev) +{ + const struct sw_config *config = dev->config; + const struct gpio_dt_spec *dt_spec = &config->dnoe; + + pin_platform_set(config->dnoe_reg, dt_spec->pin); +} + +/* + * Configure the SWDIO DAP hardware to input mode. + */ +static ALWAYS_INLINE void pin_swdio_out_disable(const struct device *dev) +{ + const struct sw_config *config = dev->config; + const struct gpio_dt_spec *dt_spec = &config->dnoe; + + pin_platform_clr(config->dnoe_reg, dt_spec->pin); +} + +#define SW_CLOCK_CYCLE(dev, delay) \ + do { \ + pin_swclk_clr(dev); \ + pin_delay_asm(delay); \ + pin_swclk_set(dev); \ + pin_delay_asm(delay); \ + } while (0) + +#define SW_WRITE_BIT(dev, bit, delay) \ + do { \ + pin_swdio_out(dev, bit); \ + pin_swclk_clr(dev); \ + pin_delay_asm(delay); \ + pin_swclk_set(dev); \ + pin_delay_asm(delay); \ + } while (0) + +#define SW_READ_BIT(dev, bit, delay) \ + do { \ + pin_swclk_clr(dev); \ + pin_delay_asm(delay); \ + bit = pin_swdio_in(dev); \ + pin_swclk_set(dev); \ + pin_delay_asm(delay); \ + } while (0) + +static int sw_sequence(const struct device *dev, uint32_t count, + const uint8_t *data) +{ + struct sw_cfg_data *sw_data = dev->data; + unsigned int key; + uint32_t val = 0; + uint32_t n = 0; + + LOG_DBG("count %u", count); + LOG_HEXDUMP_DBG(data, count, "sequence bit data"); + key = irq_lock(); + + while (count--) { + if (n == 0U) { + val = *data++; + n = 8U; + } + if (val & 1U) { + pin_swdio_set(dev); + } else { + pin_swdio_clr(dev); + } + SW_CLOCK_CYCLE(dev, sw_data->clock_delay); + val >>= 1; + n--; + } + + irq_unlock(key); + + return 0; +} + +static ALWAYS_INLINE void sw_cycle_turnaround(const struct device *dev) +{ + struct sw_cfg_data *sw_data = dev->data; + uint32_t n; + + for (n = sw_data->turnaround; n; n--) { + SW_CLOCK_CYCLE(dev, sw_data->clock_delay); + } +} + +static int sw_transfer(const struct device *dev, + const uint8_t request, uint32_t *const data, + const uint8_t idle_cycles, uint8_t *const response) +{ + struct sw_cfg_data *sw_data = dev->data; + unsigned int key; + uint32_t ack; + uint32_t bit; + uint32_t val; + uint32_t parity = 0; + uint32_t n; + + LOG_DBG("request 0x%02x idle %u", request, idle_cycles); + if (!(request & SWDP_REQUEST_RnW)) { + LOG_DBG("write data 0x%08x", *data); + parity = sw_get32bit_parity(*data); + } + + key = irq_lock(); + + val = sw_request_lut[request & 0xFU]; + for (n = 8U; n; n--) { + SW_WRITE_BIT(dev, val, sw_data->clock_delay); + val >>= 1; + } + + pin_swdio_out_disable(dev); + sw_cycle_turnaround(dev); + + /* Acknowledge response */ + SW_READ_BIT(dev, bit, sw_data->clock_delay); + ack = bit << 0; + SW_READ_BIT(dev, bit, sw_data->clock_delay); + ack |= bit << 1; + SW_READ_BIT(dev, bit, sw_data->clock_delay); + ack |= bit << 2; + + if (ack == SWDP_ACK_OK) { + /* Data transfer */ + if (request & SWDP_REQUEST_RnW) { + /* Read data */ + val = 0U; + for (n = 32U; n; n--) { + /* Read RDATA[0:31] */ + SW_READ_BIT(dev, bit, sw_data->clock_delay); + val >>= 1; + val |= bit << 31; + } + + /* Read parity bit */ + SW_READ_BIT(dev, bit, sw_data->clock_delay); + sw_cycle_turnaround(dev); + pin_swdio_out_enable(dev); + + if ((sw_get32bit_parity(val) ^ bit) & 1U) { + ack = SWDP_TRANSFER_ERROR; + } + + if (data) { + *data = val; + } + + } else { + sw_cycle_turnaround(dev); + + pin_swdio_out_enable(dev); + /* Write data */ + val = *data; + for (n = 32U; n; n--) { + SW_WRITE_BIT(dev, val, sw_data->clock_delay); + val >>= 1; + } + + /* Write parity bit */ + SW_WRITE_BIT(dev, parity, sw_data->clock_delay); + } + /* Idle cycles */ + n = idle_cycles; + if (n) { + pin_swdio_out(dev, 0U); + for (; n; n--) { + SW_CLOCK_CYCLE(dev, sw_data->clock_delay); + } + } + + pin_swdio_out(dev, 1U); + irq_unlock(key); + if (request & SWDP_REQUEST_RnW) { + LOG_DBG("read data 0x%08x", *data); + } + + if (response) { + *response = (uint8_t)ack; + } + + return 0; + } + + if ((ack == SWDP_ACK_WAIT) || (ack == SWDP_ACK_FAULT)) { + /* WAIT OR fault response */ + if (sw_data->data_phase) { + for (n = 32U + 1U + sw_data->turnaround; n; n--) { + /* Dummy Read RDATA[0:31] + Parity */ + SW_CLOCK_CYCLE(dev, sw_data->clock_delay); + } + } else { + sw_cycle_turnaround(dev); + } + + pin_swdio_out_enable(dev); + pin_swdio_out(dev, 1U); + irq_unlock(key); + LOG_DBG("Transfer wait or fault"); + if (response) { + *response = (uint8_t)ack; + } + + return 0; + } + + /* Protocol error */ + for (n = sw_data->turnaround + 32U + 1U; n; n--) { + /* Back off data phase */ + SW_CLOCK_CYCLE(dev, sw_data->clock_delay); + } + + pin_swdio_out_enable(dev); + pin_swdio_out(dev, 1U); + irq_unlock(key); + LOG_INF("Protocol error"); + if (response) { + *response = (uint8_t)ack; + } + + return 0; +} + +static int sw_set_pins(const struct device *dev, + const uint8_t pins, const uint8_t value) +{ + const struct sw_config *config = dev->config; + + LOG_DBG("pins 0x%02x value 0x%02x", pins, value); + + if (pins & BIT(SWDP_SWCLK_PIN)) { + if (value & BIT(SWDP_SWCLK_PIN)) { + gpio_pin_set_dt(&config->clk, 1); + } else { + gpio_pin_set_dt(&config->clk, 0); + } + } + + if (pins & BIT(SWDP_SWDIO_PIN)) { + if (value & BIT(SWDP_SWDIO_PIN)) { + gpio_pin_set_dt(&config->dout, 1); + } else { + gpio_pin_set_dt(&config->dout, 0); + } + } + + if (pins & BIT(SWDP_nRESET_PIN)) { + if (value & BIT(SWDP_nRESET_PIN)) { + gpio_pin_set_dt(&config->reset, 1); + } else { + gpio_pin_set_dt(&config->reset, 0); + } + } + + return 0; +} + +static int sw_get_pins(const struct device *dev, uint8_t *const state) +{ + const struct sw_config *config = dev->config; + uint32_t val; + + val = gpio_pin_get_dt(&config->reset); + *state = val ? BIT(SWDP_nRESET_PIN) : 0; + + val = gpio_pin_get_dt(&config->din); + *state |= val ? BIT(SWDP_SWDIO_PIN) : 0; + + val = gpio_pin_get_dt(&config->clk); + *state |= val ? BIT(SWDP_SWCLK_PIN) : 0; + + LOG_DBG("pins state 0x%02x", *state); + + return 0; +} + +static int sw_set_clock(const struct device *dev, const uint32_t clock) +{ + const struct sw_config *config = dev->config; + struct sw_cfg_data *sw_data = dev->data; + uint32_t delay; + + sw_data->fast_clock = false; + delay = ((CPU_CLOCK / 2U) + (clock - 1U)) / clock; + + if (delay > config->port_write_cycles) { + delay -= config->port_write_cycles; + delay = (delay + (DELAY_SLOW_CYCLES - 1U)) / DELAY_SLOW_CYCLES; + } else { + delay = 1U; + } + + sw_data->clock_delay = delay; + + LOG_WRN("cpu_clock %d, delay %d", CPU_CLOCK, sw_data->clock_delay); + + return 0; +} + +static int sw_configure(const struct device *dev, + const uint8_t turnaround, const bool data_phase) +{ + struct sw_cfg_data *sw_data = dev->data; + + sw_data->turnaround = turnaround; + sw_data->data_phase = data_phase; + + LOG_INF("turnaround %d, data_phase %d", + sw_data->turnaround, sw_data->data_phase); + + return 0; +} + +static int sw_port_on(const struct device *dev) +{ + const struct sw_config *config = dev->config; + + gpio_pin_set_dt(&config->clk, 1); + gpio_pin_set_dt(&config->dout, 1); + gpio_pin_set_dt(&config->dnoe, 1); + gpio_pin_set_dt(&config->noe, 1); + gpio_pin_set_dt(&config->reset, 1); + + return 0; +} + +static int sw_port_off(const struct device *dev) +{ + const struct sw_config *config = dev->config; + + gpio_pin_set_dt(&config->dnoe, 0); + gpio_pin_set_dt(&config->noe, 0); + gpio_pin_set_dt(&config->reset, 1); + + return 0; +} + +static int sw_gpio_init(const struct device *dev) +{ + const struct sw_config *config = dev->config; + struct sw_cfg_data *sw_data = dev->data; + int ret; + + ret = gpio_pin_configure_dt(&config->clk, GPIO_OUTPUT_ACTIVE); + if (ret) { + return ret; + } + + ret = gpio_pin_configure_dt(&config->dout, GPIO_OUTPUT_ACTIVE); + if (ret) { + return ret; + } + + ret = gpio_pin_configure_dt(&config->din, GPIO_INPUT); + if (ret) { + return ret; + } + + ret = gpio_pin_configure_dt(&config->dnoe, GPIO_OUTPUT_INACTIVE); + if (ret) { + return ret; + } + + ret = gpio_pin_configure_dt(&config->noe, GPIO_OUTPUT_INACTIVE); + if (ret) { + return ret; + } + + ret = gpio_pin_configure_dt(&config->reset, GPIO_OUTPUT_INACTIVE); + if (ret) { + return ret; + } + + sw_data->turnaround = 1U; + sw_data->data_phase = false; + sw_data->fast_clock = false; + sw_data->clock_delay = CLOCK_DELAY(SWDP_DEFAULT_SWCLK_FREQUENCY, + config->port_write_cycles); + mk_sw_request_lut(); + + return 0; +} + +static struct swdp_api swdp_bitbang_api = { + .swdp_sequence = sw_sequence, + .swdp_transfer = sw_transfer, + .swdp_set_pins = sw_set_pins, + .swdp_get_pins = sw_get_pins, + .swdp_set_clock = sw_set_clock, + .swdp_configure = sw_configure, + .swdp_port_on = sw_port_on, + .swdp_port_off = sw_port_off, +}; + +#define SW_GPIOS_GET_REG(n, gpios) \ + INT_TO_POINTER(DT_REG_ADDR(DT_PHANDLE(DT_DRV_INST(n), gpios))) + +#define SW_DEVICE_DEFINE(n) \ + static const struct sw_config sw_cfg_##n = { \ + .clk = GPIO_DT_SPEC_INST_GET(n, clk_gpios), \ + .dout = GPIO_DT_SPEC_INST_GET(n, dout_gpios), \ + .din = GPIO_DT_SPEC_INST_GET(n, din_gpios), \ + .dnoe = GPIO_DT_SPEC_INST_GET(n, dnoe_gpios), \ + .noe = GPIO_DT_SPEC_INST_GET(n, noe_gpios), \ + .reset = GPIO_DT_SPEC_INST_GET(n, reset_gpios), \ + .port_write_cycles = DT_INST_PROP(n, port_write_cycles), \ + .clk_reg = SW_GPIOS_GET_REG(n, clk_gpios), \ + .dout_reg = SW_GPIOS_GET_REG(n, dout_gpios), \ + .din_reg = SW_GPIOS_GET_REG(n, din_gpios), \ + .dnoe_reg = SW_GPIOS_GET_REG(n, dnoe_gpios), \ + }; \ + \ + static struct sw_cfg_data sw_data_##n; \ + \ + DEVICE_DT_INST_DEFINE(n, sw_gpio_init, NULL, \ + &sw_data_##n, &sw_cfg_##n, \ + POST_KERNEL, CONFIG_DP_DRIVER_INIT_PRIO, \ + &swdp_bitbang_api); \ + +DT_INST_FOREACH_STATUS_OKAY(SW_DEVICE_DEFINE) diff --git a/dts/bindings/misc/zephyr,swdp-gpio.yaml b/dts/bindings/misc/zephyr,swdp-gpio.yaml new file mode 100644 index 0000000000000..3264dd5800141 --- /dev/null +++ b/dts/bindings/misc/zephyr,swdp-gpio.yaml @@ -0,0 +1,46 @@ +# Copyright (c) 2019, Phytec Messtechnik GmbH +# SPDX-License-Identifier: Apache-2.0 + +description: > + This is a representation of the Serial Wire Debug Port interface + implementation by GPIO bit-banging. + +compatible: "zephyr,swdp-gpio" + +include: base.yaml + +properties: + clk-gpios: + type: phandle-array + required: true + description: GPIO pin used for SWCLK output + + dout-gpios: + type: phandle-array + required: true + description: GPIO pin used for SWDIO output + + din-gpios: + type: phandle-array + required: true + description: GPIO pin used for SWDIO input + + dnoe-gpios: + type: phandle-array + required: true + description: GPIO pin used for SWDIO NOE output + + noe-gpios: + type: phandle-array + required: true + description: GPIO pin used for SWD NOE output + + reset-gpios: + type: phandle-array + required: true + description: GPIO pin used for RESET output + + port-write-cycles: + type: int + required: true + description: Number of processor cycles for I/O Port write operations diff --git a/include/zephyr/drivers/swdp.h b/include/zephyr/drivers/swdp.h new file mode 100644 index 0000000000000..f15a4b40ecd09 --- /dev/null +++ b/include/zephyr/drivers/swdp.h @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2019 PHYTEC Messtechnik GmbH + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * @brief Serial Wire Debug Port interface driver API + */ + +#ifndef ZEPHYR_INCLUDE_SWDP_H_ +#define ZEPHYR_INCLUDE_SWDP_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* SWDP packet request bits */ +#define SWDP_REQUEST_APnDP BIT(0) +#define SWDP_REQUEST_RnW BIT(1) +#define SWDP_REQUEST_A2 BIT(2) +#define SWDP_REQUEST_A3 BIT(3) + +/* SWDP acknowledge response bits */ +#define SWDP_ACK_OK BIT(0) +#define SWDP_ACK_WAIT BIT(1) +#define SWDP_ACK_FAULT BIT(2) + +/* SWDP transfer or parity error */ +#define SWDP_TRANSFER_ERROR BIT(3) + +/* SWDP Interface pins */ +#define SWDP_SWCLK_PIN 0U +#define SWDP_SWDIO_PIN 1U +#define SWDP_nRESET_PIN 7U + +/* + * Serial Wire Interface (SWDP) driver API. + * This is the mandatory API any Serial Wire driver needs to expose. + */ +struct swdp_api { + /* Generate SWJ Sequence according to sequence bit count and bit data */ + int (*swdp_sequence)(const struct device *dev, + uint32_t count, + const uint8_t *data); + + /* + * Perform SWDP transfer based on host request value and store + * acknowledge response bits ACK[0:2]. + */ + int (*swdp_transfer)(const struct device *dev, + uint8_t request, + uint32_t *data, + uint8_t idle_cycles, + uint8_t *response); + + /* Set SWCLK, SWDPIO, and nRESET pins state */ + int (*swdp_set_pins)(const struct device *dev, + uint8_t pins, uint8_t value); + + /* Get SWCLK, SWDPIO, and nRESET pins state */ + int (*swdp_get_pins)(const struct device *dev, uint8_t *state); + + /* Set SWCLK frequency */ + int (*swdp_set_clock)(const struct device *dev, uint32_t clock); + + /* + * Configure interface, line turnaround and whether data phase is + * forced after WAIN and FAULT response. + */ + int (*swdp_configure)(const struct device *dev, + uint8_t turnaround, + bool data_phase); + + /* + * Enable interface, set SWDPIO to output mode + * and set SWCLK and nRESET to default high level. + */ + int (*swdp_port_on)(const struct device *dev); + + /* Disables interface, set SWCLK, SWDPIO, nRESET to High-Z mode. */ + int (*swdp_port_off)(const struct device *dev); +}; + +#ifdef __cplusplus +} +#endif + +#endif /* ZEPHYR_INCLUDE_SWDP_H_ */ From 7c9259abbceb84880906e4d8e594308db0ae00f0 Mon Sep 17 00:00:00 2001 From: Johann Fischer Date: Wed, 9 Oct 2019 00:02:30 +0200 Subject: [PATCH 2695/2849] dap: add CMSIS-DAP compatible controller Add CMSIS-DAP compatible controller which is a handler between the host interface and SWD driver. The controller follows CMSIS-DAP reference implementation. It expects a request buffer from the host interface, splits it to simple transfers and forwards to the DP driver, and finally returns a response buffer to the host. Interface to the host can be implemented with USB HID device support. Controller implements only SW-DP support and is tested with pyOCD and ADIv5.x. Signed-off-by: Johann Fischer --- dts/bindings/misc/zephyr,swdp-gpio.yaml | 72 +- subsys/CMakeLists.txt | 1 + subsys/Kconfig | 1 + subsys/dap/CMakeLists.txt | 7 + subsys/dap/Kconfig | 24 + subsys/dap/cmsis_dap.c | 925 ++++++++++++++++++++++++ subsys/dap/cmsis_dap.h | 119 +++ 7 files changed, 1113 insertions(+), 36 deletions(-) create mode 100644 subsys/dap/CMakeLists.txt create mode 100644 subsys/dap/Kconfig create mode 100644 subsys/dap/cmsis_dap.c create mode 100644 subsys/dap/cmsis_dap.h diff --git a/dts/bindings/misc/zephyr,swdp-gpio.yaml b/dts/bindings/misc/zephyr,swdp-gpio.yaml index 3264dd5800141..5d38449ad494e 100644 --- a/dts/bindings/misc/zephyr,swdp-gpio.yaml +++ b/dts/bindings/misc/zephyr,swdp-gpio.yaml @@ -2,45 +2,45 @@ # SPDX-License-Identifier: Apache-2.0 description: > - This is a representation of the Serial Wire Debug Port interface - implementation by GPIO bit-banging. + This is a representation of the Serial Wire Debug Port interface + implementation by GPIO bit-banging. compatible: "zephyr,swdp-gpio" include: base.yaml properties: - clk-gpios: - type: phandle-array - required: true - description: GPIO pin used for SWCLK output - - dout-gpios: - type: phandle-array - required: true - description: GPIO pin used for SWDIO output - - din-gpios: - type: phandle-array - required: true - description: GPIO pin used for SWDIO input - - dnoe-gpios: - type: phandle-array - required: true - description: GPIO pin used for SWDIO NOE output - - noe-gpios: - type: phandle-array - required: true - description: GPIO pin used for SWD NOE output - - reset-gpios: - type: phandle-array - required: true - description: GPIO pin used for RESET output - - port-write-cycles: - type: int - required: true - description: Number of processor cycles for I/O Port write operations + clk-gpios: + type: phandle-array + required: true + description: GPIO pin used for SWCLK output + + dout-gpios: + type: phandle-array + required: true + description: GPIO pin used for SWDIO output + + din-gpios: + type: phandle-array + required: true + description: GPIO pin used for SWDIO input + + dnoe-gpios: + type: phandle-array + required: true + description: GPIO pin used for SWDIO NOE output + + noe-gpios: + type: phandle-array + required: true + description: GPIO pin used for SWD NOE output + + reset-gpios: + type: phandle-array + required: true + description: GPIO pin used for RESET output + + port-write-cycles: + type: int + required: true + description: Number of processor cycles for I/O Port write operations diff --git a/subsys/CMakeLists.txt b/subsys/CMakeLists.txt index ccd2c8c88bff7..584559fa50e67 100644 --- a/subsys/CMakeLists.txt +++ b/subsys/CMakeLists.txt @@ -37,6 +37,7 @@ add_subdirectory_ifdef(CONFIG_ARM_SIP_SVC_SUBSYS sip_svc) add_subdirectory_ifdef(CONFIG_BINDESC bindesc) add_subdirectory_ifdef(CONFIG_BT bluetooth) add_subdirectory_ifdef(CONFIG_CONSOLE_SUBSYS console) +add_subdirectory_ifdef(CONFIG_DAP dap) add_subdirectory_ifdef(CONFIG_DEMAND_PAGING demand_paging) add_subdirectory_ifdef(CONFIG_DISK_ACCESS disk) add_subdirectory_ifdef(CONFIG_DSP dsp) diff --git a/subsys/Kconfig b/subsys/Kconfig index 2e083fb4c89cd..2c708e26d59ec 100644 --- a/subsys/Kconfig +++ b/subsys/Kconfig @@ -11,6 +11,7 @@ source "subsys/bindesc/Kconfig" source "subsys/bluetooth/Kconfig" source "subsys/canbus/Kconfig" source "subsys/console/Kconfig" +source "subsys/dap/Kconfig" source "subsys/debug/Kconfig" source "subsys/demand_paging/Kconfig" source "subsys/dfu/Kconfig" diff --git a/subsys/dap/CMakeLists.txt b/subsys/dap/CMakeLists.txt new file mode 100644 index 0000000000000..c021d24071176 --- /dev/null +++ b/subsys/dap/CMakeLists.txt @@ -0,0 +1,7 @@ +# Copyright (c) 2019, PHYTEC Messtechnik GmbH +# SPDX-License-Identifier: Apache-2.0 + +zephyr_include_directories(${CMAKE_CURRENT_SOURCE_DIR}) + +zephyr_library() +zephyr_library_sources(cmsis_dap.c) diff --git a/subsys/dap/Kconfig b/subsys/dap/Kconfig new file mode 100644 index 0000000000000..434859581022e --- /dev/null +++ b/subsys/dap/Kconfig @@ -0,0 +1,24 @@ +# Copyright (c) 2018-2019 PHYTEC Messtechnik GmbH +# SPDX-License-Identifier: Apache-2.0 + +menuconfig DAP + bool "Debug Access Port support [EXPERIMENTAL]" + select EXPERIMENTAL + select DP_DRIVER + help + Debug Access Port support (currently CMSIS DAP only) + +if DAP + +config CMSIS_DAP_PACKET_COUNT + int "Maximum packet buffers for request and response data." + default 4 + range 1 255 + help + Maximum packet buffers for request and response data. + +module = DAP +module-str = dap +source "subsys/logging/Kconfig.template.log_config" + +endif # DAP diff --git a/subsys/dap/cmsis_dap.c b/subsys/dap/cmsis_dap.c new file mode 100644 index 0000000000000..f1fc537366e3d --- /dev/null +++ b/subsys/dap/cmsis_dap.c @@ -0,0 +1,925 @@ +/* + * Copyright (c) 2018-2019 PHYTEC Messtechnik GmbH + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* + * This file is based on DAP.c from CMSIS-DAP Source (Revision: V2.0.0) + * https://github.com/ARM-software/CMSIS_5/tree/develop/CMSIS/DAP/Firmware + * Copyright (c) 2013-2017 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include + +#include + +#include +LOG_MODULE_REGISTER(dap, CONFIG_DAP_LOG_LEVEL); + +const char dap_fw_ver[] = DAP_FW_VER; + +#define DAP_STATE_CONNECTED 0 + +struct dap_context { + struct device *swdp_dev; + atomic_t state; + uint8_t debug_port; + uint8_t capabilities; + uint8_t pkt_size; + struct { + /* Idle cycles after transfer */ + uint8_t idle_cycles; + /* Number of retries after WAIT response */ + uint16_t retry_count; + /* Number of retries if read value does not match */ + uint16_t match_retry; + /* Match Mask */ + uint32_t match_mask; + } transfer; +}; + +static struct dap_context dap_ctx[1]; + +/* Get DAP Information */ +static uint16_t dap_info(struct dap_context *const ctx, + const uint8_t *const request, + uint8_t *const response) +{ + uint8_t *info = response + 1; + uint8_t id = request[0]; + uint8_t length = 0U; + + switch (id) { + case DAP_ID_VENDOR: + LOG_DBG("ID_VENDOR unsupported"); + break; + case DAP_ID_PRODUCT: + LOG_DBG("ID_PRODUCT unsupported"); + break; + case DAP_ID_SER_NUM: + LOG_DBG("ID_SER_NUM unsupported"); + break; + case DAP_ID_FW_VER: + LOG_DBG("ID_FW_VER"); + memcpy(info, dap_fw_ver, sizeof(dap_fw_ver)); + length = (uint8_t)sizeof(dap_fw_ver); + break; + case DAP_ID_DEVICE_VENDOR: + LOG_DBG("ID_DEVICE_VENDOR unsupported"); + break; + case DAP_ID_DEVICE_NAME: + LOG_DBG("ID_DEVICE_NAME unsupported"); + break; + case DAP_ID_CAPABILITIES: + info[0] = ctx->capabilities; + LOG_DBG("ID_CAPABILITIES 0x%0x", info[0]); + length = 1U; + break; + case DAP_ID_SWO_BUFFER_SIZE: + LOG_DBG("ID_SWO_BUFFER_SIZE unsupported"); + break; + case DAP_ID_PACKET_SIZE: + LOG_DBG("ID_PACKET_SIZE"); + sys_put_le16(ctx->capabilities, &info[0]); + length = 2U; + break; + case DAP_ID_PACKET_COUNT: + LOG_DBG("ID_PACKET_COUNT"); + info[0] = CONFIG_CMSIS_DAP_PACKET_COUNT; + length = 1U; + break; + default: + LOG_DBG("unsupported ID"); + break; + } + + response[0] = (uint8_t)length; + + return length + 1U; +} + +/* Process Host Status command and prepare response */ +static uint16_t dap_host_status(struct dap_context *const ctx, + const uint8_t *const request, + uint8_t *const response) +{ + switch (request[0]) { + case DAP_DEBUGGER_CONNECTED: + if (request[1]) { + LOG_INF("Debugger connected"); + } else { + LOG_INF("Debugger disconnected"); + } + break; + case DAP_TARGET_RUNNING: + LOG_DBG("unsupported"); + break; + default: + *response = DAP_ERROR; + return 1U; + } + + response[0] = DAP_OK; + return 1U; +} + +/* Process Connect command and prepare response */ +static uint16_t dap_connect(struct dap_context *const ctx, + const uint8_t *const request, + uint8_t *const response) +{ + const struct swdp_api *api = ctx->swdp_dev->api; + uint8_t port; + + if (request[0] == DAP_PORT_AUTODETECT) { + port = DAP_PORT_SWD; + } else { + port = request[0]; + } + + switch (port) { + case DAP_PORT_SWD: + LOG_INF("port swd"); + ctx->debug_port = DAP_PORT_SWD; + + if (atomic_test_and_set_bit(&ctx->state, + DAP_STATE_CONNECTED)) { + LOG_ERR("DAP device is already connected"); + port = DAP_ERROR; + break; + } + + api->swdp_port_on(ctx->swdp_dev); + break; + case DAP_PORT_JTAG: + LOG_ERR("port unsupported"); + port = DAP_ERROR; + break; + default: + LOG_DBG("port disabled"); + port = DAP_PORT_DISABLED; + break; + } + + response[0] = port; + return 1U; +} + +/* Process Disconnect command and prepare response */ +static uint16_t dap_disconnect(struct dap_context *const ctx, + uint8_t *const response) +{ + const struct swdp_api *api = ctx->swdp_dev->api; + + LOG_DBG(""); + + ctx->debug_port = DAP_PORT_DISABLED; + + if (atomic_test_bit(&ctx->state, DAP_STATE_CONNECTED)) { + api->swdp_port_off(ctx->swdp_dev); + } else { + LOG_WRN("DAP device is not connected"); + } + + response[0] = DAP_OK; + atomic_clear_bit(&ctx->state, DAP_STATE_CONNECTED); + + return 1; +} + +/* Process Delay command and prepare response */ +static uint16_t dap_delay(struct dap_context *const ctx, + const uint8_t *const request, + uint8_t *const response) +{ + uint16_t delay = sys_get_le16(&request[0]); + + LOG_DBG("dap delay %u ms", delay); + + k_busy_wait(delay * USEC_PER_MSEC); + response[0] = DAP_OK; + + return 1U; +} + +/* Process Reset Target command and prepare response */ +static uint16_t dap_reset_target(struct dap_context *const ctx, + uint8_t *const response) +{ + response[0] = DAP_OK; + response[1] = 0U; + LOG_WRN("unsupported"); + + return 2; +} + +/* Process SWJ Pins command and prepare response */ +static uint16_t dap_swj_pins(struct dap_context *const ctx, + const uint8_t *const request, + uint8_t *const response) +{ + const struct swdp_api *api = ctx->swdp_dev->api; + uint8_t value = request[0]; + uint8_t select = request[1]; + uint32_t wait = sys_get_le32(&request[2]); + uint8_t state; + + if (!atomic_test_bit(&ctx->state, DAP_STATE_CONNECTED)) { + LOG_ERR("DAP device is not connected"); + response[0] = DAP_ERROR; + return 1U; + } + + /* Skip if nothing selected. */ + if (select) { + api->swdp_set_pins(ctx->swdp_dev, select, value); + } + + /* TODO: implement wait */ + api->swdp_get_pins(ctx->swdp_dev, &state); + LOG_ERR("select 0x%02x, value 0x%02x, wait %u, state 0x%02x", + select, value, wait, state); + + response[0] = state; + + return sizeof(state); +} + +/* Process SWJ Clock command and prepare response */ +static uint16_t dap_swj_clock(struct dap_context *const ctx, + const uint8_t *const request, + uint8_t *const response) +{ + const struct swdp_api *api = ctx->swdp_dev->api; + uint32_t clk = sys_get_le32(&request[0]); + + LOG_DBG("clock %d", clk); + + if (atomic_test_bit(&ctx->state, DAP_STATE_CONNECTED)) { + if (clk) { + api->swdp_set_clock(ctx->swdp_dev, clk); + response[0] = DAP_OK; + } else { + response[0] = DAP_ERROR; + } + } else { + LOG_WRN("DAP device is not connected"); + response[0] = DAP_OK; + } + + return 1U; +} + +/* Process SWJ Sequence command and prepare response */ +static uint16_t dap_swj_sequence(struct dap_context *const ctx, + const uint8_t *const request, + uint8_t *const response) +{ + const struct swdp_api *api = ctx->swdp_dev->api; + uint16_t count = request[0]; + + LOG_DBG("count %u", count); + + if (count == 0U) { + count = 256U; + } + + if (!atomic_test_bit(&ctx->state, DAP_STATE_CONNECTED)) { + LOG_ERR("DAP device is not connected"); + response[0] = DAP_ERROR; + return 1U; + } + + api->swdp_sequence(ctx->swdp_dev, count, &request[1]); + response[0] = DAP_OK; + + return 1U; +} + +/* Process SWD Configure command and prepare response */ +static uint16_t dap_swdp_configure(struct dap_context *const ctx, + const uint8_t *const request, + uint8_t *const response) +{ + const struct swdp_api *api = ctx->swdp_dev->api; + uint8_t turnaround = (request[0] & 0x03U) + 1U; + bool data_phase = (request[0] & 0x04U) ? true : false; + + if (!atomic_test_bit(&ctx->state, DAP_STATE_CONNECTED)) { + LOG_ERR("DAP device is not connected"); + response[0] = DAP_ERROR; + return 1U; + } + + api->swdp_configure(ctx->swdp_dev, turnaround, data_phase); + response[0] = DAP_OK; + + return 1U; +} + +/* Process Transfer Configure command and prepare response */ +static uint16_t dap_transfer_cfg(struct dap_context *const ctx, + const uint8_t *const request, + uint8_t *const response) +{ + + ctx->transfer.idle_cycles = request[0]; + ctx->transfer.retry_count = sys_get_le16(&request[1]); + ctx->transfer.match_retry = sys_get_le16(&request[3]); + LOG_DBG("idle_cycles %d, retry_count %d, match_retry %d", + ctx->transfer.idle_cycles, + ctx->transfer.retry_count, + ctx->transfer.match_retry); + + response[0] = DAP_OK; + return 1U; +} + +static inline uint8_t do_swdp_transfer(struct dap_context *const ctx, + const uint8_t req_val, + uint32_t *data) +{ + const struct swdp_api *api = ctx->swdp_dev->api; + uint32_t retry = ctx->transfer.retry_count; + uint8_t rspns_val; + + do { + api->swdp_transfer(ctx->swdp_dev, + req_val, + data, + ctx->transfer.idle_cycles, + &rspns_val); + } while ((rspns_val == SWDP_ACK_WAIT) && retry--); + + return rspns_val; +} + +static uint8_t swdp_transfer_match(struct dap_context *const ctx, + const uint8_t req_val, + const uint32_t match_val) +{ + uint32_t match_retry = ctx->transfer.match_retry; + uint32_t data; + uint8_t rspns_val; + + if (req_val & SWDP_REQUEST_APnDP) { + /* Post AP read, result will be returned on the next transfer */ + rspns_val = do_swdp_transfer(ctx, req_val, NULL); + if (rspns_val != SWDP_ACK_OK) { + return rspns_val; + } + } + + do { + /* + * Read register until its value matches + * or retry counter expires + */ + rspns_val = do_swdp_transfer(ctx, req_val, &data); + if (rspns_val != SWDP_ACK_OK) { + return rspns_val; + } + + } while (((data & ctx->transfer.match_mask) != match_val) && + match_retry--); + + if ((data & ctx->transfer.match_mask) != match_val) { + rspns_val |= DAP_TRANSFER_MISMATCH; + } + + return rspns_val; +} + +/* + * Process SWD Transfer command and prepare response + * pyOCD counterpart is _encode_transfer_data. + * Packet format: one byte DAP_index (ignored) + * one bytes transfer_count + * following by number transfer_count pairs of + * one byte request (register) + * four byte data (for write request only) + */ +static uint16_t dap_swdp_transfer(struct dap_context *const ctx, + const uint8_t *const request, + uint8_t *const response) +{ + uint8_t *rspns_buf; + const uint8_t *req_buf; + uint8_t rspns_cnt = 0; + uint8_t rspns_val = 0; + bool post_read = false; + uint32_t check_write = 0; + uint8_t req_cnt; + uint8_t req_val; + uint32_t match_val; + uint32_t data; + + /* Ignore DAP index request[0] */ + req_cnt = request[1]; + req_buf = request + sizeof(req_cnt) + 1; + rspns_buf = response + (sizeof(rspns_cnt) + sizeof(rspns_val)); + + for (; req_cnt; req_cnt--) { + req_val = *req_buf++; + if (req_val & SWDP_REQUEST_RnW) { + /* Read register */ + if (post_read) { + /* + * Read was posted before, read previous AP + * data or post next AP read. + */ + if ((req_val & (SWDP_REQUEST_APnDP | + DAP_TRANSFER_MATCH_VALUE)) != + SWDP_REQUEST_APnDP) { + req_val = DP_RDBUFF | SWDP_REQUEST_RnW; + post_read = false; + } + + rspns_val = do_swdp_transfer(ctx, req_val, &data); + if (rspns_val != SWDP_ACK_OK) { + break; + } + + /* Store previous AP data */ + sys_put_le32(data, rspns_buf); + rspns_buf += sizeof(data); + } + if (req_val & DAP_TRANSFER_MATCH_VALUE) { + LOG_INF("match value read"); + /* Read with value match */ + match_val = sys_get_le32(req_buf); + req_buf += sizeof(match_val); + + rspns_val = swdp_transfer_match(ctx, req_val, match_val); + if (rspns_val != SWDP_ACK_OK) { + break; + } + + } else if (req_val & SWDP_REQUEST_APnDP) { + /* Normal read */ + if (!post_read) { + /* Post AP read */ + rspns_val = do_swdp_transfer(ctx, req_val, NULL); + if (rspns_val != SWDP_ACK_OK) { + break; + } + post_read = true; + } + } else { + /* Read DP register */ + rspns_val = do_swdp_transfer(ctx, req_val, &data); + if (rspns_val != SWDP_ACK_OK) { + break; + } + /* Store data */ + sys_put_le32(data, rspns_buf); + rspns_buf += sizeof(data); + } + check_write = 0U; + } else { + /* Write register */ + if (post_read) { + /* Read previous data */ + rspns_val = do_swdp_transfer(ctx, + DP_RDBUFF | SWDP_REQUEST_RnW, + &data); + if (rspns_val != SWDP_ACK_OK) { + break; + } + + /* Store previous data */ + sys_put_le32(data, rspns_buf); + rspns_buf += sizeof(data); + post_read = false; + } + /* Load data */ + data = sys_get_le32(req_buf); + req_buf += sizeof(data); + if (req_val & DAP_TRANSFER_MATCH_MASK) { + /* Write match mask */ + ctx->transfer.match_mask = data; + rspns_val = SWDP_ACK_OK; + } else { + /* Write DP/AP register */ + rspns_val = do_swdp_transfer(ctx, req_val, &data); + if (rspns_val != SWDP_ACK_OK) { + break; + } + + check_write = 1U; + } + } + rspns_cnt++; + } + + if (rspns_val == SWDP_ACK_OK) { + if (post_read) { + /* Read previous data */ + rspns_val = do_swdp_transfer(ctx, + DP_RDBUFF | SWDP_REQUEST_RnW, + &data); + if (rspns_val != SWDP_ACK_OK) { + goto end; + } + + /* Store previous data */ + sys_put_le32(data, rspns_buf); + rspns_buf += sizeof(data); + } else if (check_write) { + /* Check last write */ + rspns_val = do_swdp_transfer(ctx, + DP_RDBUFF | SWDP_REQUEST_RnW, + NULL); + } + } + +end: + response[0] = rspns_cnt; + response[1] = rspns_val; + + return (rspns_buf - response); +} + +/* Delegate DAP Transfer command */ +static uint16_t dap_transfer(struct dap_context *const ctx, + const uint8_t *const request, + uint8_t *const response) +{ + uint16_t retval; + + if (!atomic_test_bit(&ctx->state, DAP_STATE_CONNECTED)) { + LOG_ERR("DAP device is not connected"); + response[0] = DAP_ERROR; + return 1U; + } + + switch (ctx->debug_port) { + case DAP_PORT_SWD: + retval = dap_swdp_transfer(ctx, request, response); + break; + case DAP_PORT_JTAG: + default: + LOG_ERR("port unsupported"); + response[0] = DAP_ERROR; + retval = 1U; + } + + return retval; +} + +/* + * Process SWD DAP_TransferBlock command and prepare response. + * pyOCD counterpart is _encode_transfer_block_data. + * Packet format: one byte DAP_index (ignored) + * two bytes transfer_count + * one byte block_request (register) + * data[transfer_count * sizeof(uint32_t)] + */ +static uint16_t dap_swdp_transferblock(struct dap_context *const ctx, + const uint8_t *const request, + uint8_t *const response) +{ + uint32_t data; + uint8_t *rspns_buf; + const uint8_t *req_buf; + uint16_t rspns_cnt = 0; + uint16_t req_cnt; + uint8_t rspns_val = 0; + uint8_t req_val; + + req_cnt = sys_get_le16(&request[1]); + req_val = request[3]; + req_buf = request + (sizeof(req_cnt) + sizeof(req_val) + 1); + rspns_buf = response + (sizeof(rspns_cnt) + sizeof(rspns_val)); + + if (req_cnt == 0U) { + goto end; + } + + if (req_val & SWDP_REQUEST_RnW) { + /* Read register block */ + if (req_val & SWDP_REQUEST_APnDP) { + /* Post AP read */ + rspns_val = do_swdp_transfer(ctx, req_val, NULL); + if (rspns_val != SWDP_ACK_OK) { + goto end; + } + } + + while (req_cnt--) { + /* Read DP/AP register */ + if ((req_cnt == 0U) && + (req_val & SWDP_REQUEST_APnDP)) { + /* Last AP read */ + req_val = DP_RDBUFF | SWDP_REQUEST_RnW; + } + + rspns_val = do_swdp_transfer(ctx, req_val, &data); + if (rspns_val != SWDP_ACK_OK) { + goto end; + } + + /* Store data */ + sys_put_le32(data, rspns_buf); + rspns_buf += sizeof(data); + rspns_cnt++; + } + } else { + /* Write register block */ + while (req_cnt--) { + /* Load data */ + data = sys_get_le32(req_buf); + req_buf += sizeof(data); + /* Write DP/AP register */ + rspns_val = do_swdp_transfer(ctx, req_val, &data); + if (rspns_val != SWDP_ACK_OK) { + goto end; + } + + rspns_cnt++; + } + /* Check last write */ + rspns_val = do_swdp_transfer(ctx, DP_RDBUFF | SWDP_REQUEST_RnW, NULL); + } + +end: + sys_put_le16(rspns_cnt, &response[0]); + response[2] = rspns_val; + + LOG_DBG("Received %u, to transmit %u, response count %u", + req_buf - request, + rspns_buf - response, + rspns_cnt * 4); + + return (rspns_buf - response); +} + +/* Delegate Transfer Block command */ +static uint16_t dap_transferblock(struct dap_context *const ctx, + const uint8_t *const request, + uint8_t *const response) +{ + uint16_t retval; + + if (!atomic_test_bit(&ctx->state, DAP_STATE_CONNECTED)) { + LOG_ERR("DAP device is not connected"); + /* Clear response count */ + sys_put_le16(0U, &response[0]); + /* Clear DAP response (ACK) value */ + response[2] = 0U; + return 3U; + } + + switch (ctx->debug_port) { + case DAP_PORT_SWD: + retval = dap_swdp_transferblock(ctx, request, response); + break; + case DAP_PORT_JTAG: + default: + LOG_ERR("port unsupported"); + /* Clear response count */ + sys_put_le16(0U, &response[0]); + /* Clear DAP response (ACK) value */ + response[2] = 0U; + retval = 3U; + } + + return retval; +} + +/* Process SWD Write ABORT command and prepare response */ +static uint16_t dap_swdp_writeabort(struct dap_context *const ctx, + const uint8_t *const request, + uint8_t *const response) +{ + const struct swdp_api *api = ctx->swdp_dev->api; + /* Load data (Ignore DAP index in request[0]) */ + uint32_t data = sys_get_le32(&request[1]); + + /* Write Abort register */ + api->swdp_transfer(ctx->swdp_dev, DP_ABORT, &data, + ctx->transfer.idle_cycles, NULL); + + response[0] = DAP_OK; + return 1U; +} + +/* Delegate DAP Write ABORT command */ +static uint16_t dap_writeabort(struct dap_context *const ctx, + const uint8_t *const request, + uint8_t *const response) +{ + uint16_t retval; + + if (!atomic_test_bit(&ctx->state, DAP_STATE_CONNECTED)) { + LOG_ERR("DAP device is not connected"); + response[0] = DAP_ERROR; + return 1U; + } + + switch (ctx->debug_port) { + case DAP_PORT_SWD: + retval = dap_swdp_writeabort(ctx, request, response); + break; + case DAP_PORT_JTAG: + default: + LOG_ERR("port unsupported"); + response[0] = DAP_ERROR; + retval = 1U; + } + return retval; +} + +/* Process DAP Vendor command request */ +static uint16_t dap_process_vendor_cmd(struct dap_context *const ctx, + const uint8_t *const request, + uint8_t *const response) +{ + response[0] = ID_DAP_INVALID; + return 1U; +} + +/* + * Process DAP command request and prepare response + * request: pointer to request data + * response: pointer to response data + * return: number of bytes in response + * + * All the subsequent command functions have the same parameter + * and return value structure. + */ +static uint16_t dap_process_cmd(struct dap_context *const ctx, + const uint8_t *request, + uint8_t *response) +{ + uint16_t retval; + + LOG_HEXDUMP_DBG(request, 8, "req"); + + if ((*request >= ID_DAP_VENDOR0) && (*request <= ID_DAP_VENDOR31)) { + return dap_process_vendor_cmd(ctx, request, response); + } + + *response++ = *request; + LOG_DBG("request 0x%02x", *request); + + switch (*request++) { + case ID_DAP_INFO: + retval = dap_info(ctx, request, response); + break; + case ID_DAP_HOST_STATUS: + retval = dap_host_status(ctx, request, response); + break; + case ID_DAP_CONNECT: + retval = dap_connect(ctx, request, response); + break; + case ID_DAP_DISCONNECT: + retval = dap_disconnect(ctx, response); + break; + case ID_DAP_DELAY: + retval = dap_delay(ctx, request, response); + break; + case ID_DAP_RESET_TARGET: + retval = dap_reset_target(ctx, response); + break; + case ID_DAP_SWJ_PINS: + retval = dap_swj_pins(ctx, request, response); + break; + case ID_DAP_SWJ_CLOCK: + retval = dap_swj_clock(ctx, request, response); + break; + case ID_DAP_SWJ_SEQUENCE: + retval = dap_swj_sequence(ctx, request, response); + break; + case ID_DAP_SWDP_CONFIGURE: + retval = dap_swdp_configure(ctx, request, response); + break; + case ID_DAP_JTAG_SEQUENCE: + LOG_ERR("JTAG sequence unsupported"); + retval = 1; + *response = DAP_ERROR; + break; + case ID_DAP_JTAG_CONFIGURE: + LOG_ERR("JTAG configure unsupported"); + retval = 1; + *response = DAP_ERROR; + break; + case ID_DAP_JTAG_IDCODE: + LOG_ERR("JTAG IDCODE unsupported"); + retval = 1; + *response = DAP_ERROR; + break; + case ID_DAP_TRANSFER_CONFIGURE: + retval = dap_transfer_cfg(ctx, request, response); + break; + case ID_DAP_TRANSFER: + retval = dap_transfer(ctx, request, response); + break; + case ID_DAP_TRANSFER_BLOCK: + retval = dap_transferblock(ctx, request, response); + break; + case ID_DAP_WRITE_ABORT: + retval = dap_writeabort(ctx, request, response); + break; + case ID_DAP_SWO_TRANSPORT: + LOG_ERR("SWO Transport unsupported"); + retval = 1; + *response = DAP_ERROR; + break; + case ID_DAP_SWO_MODE: + LOG_ERR("SWO Mode unsupported"); + retval = 1; + *response = DAP_ERROR; + break; + case ID_DAP_SWO_BAUDRATE: + LOG_ERR("SWO Baudrate unsupported"); + retval = 1; + *response = DAP_ERROR; + break; + case ID_DAP_SWO_CONTROL: + LOG_ERR("SWO Control unsupported"); + retval = 1; + *response = DAP_ERROR; + break; + case ID_DAP_SWO_STATUS: + LOG_ERR("SWO Status unsupported"); + retval = 1; + *response = DAP_ERROR; + break; + case ID_DAP_SWO_DATA: + LOG_ERR("SWO Data unsupported"); + retval = 1; + *response = DAP_ERROR; + break; + + default: + *(response - 1) = ID_DAP_INVALID; + return 1U; + } + + return (1U + retval); +} + +/* + * Execute DAP command (process request and prepare response) + * request: pointer to request data + * response: pointer to response data + * return: number of bytes in response + */ +uint32_t dap_execute_cmd(const uint8_t *request, + uint8_t *response) +{ + uint32_t retval; + uint16_t n; + uint8_t count; + + if (request[0] == ID_DAP_EXECUTE_COMMANDS) { + /* copy command and increment */ + *response++ = *request++; + count = request[0]; + request += sizeof(count); + response[0] = count; + response += sizeof(count); + retval = sizeof(count) + 1U; + LOG_WRN("(untested) ID DAP EXECUTE_COMMANDS count %u", count); + while (count--) { + n = dap_process_cmd(&dap_ctx[0], request, response); + retval += n; + request += n; + response += n; + } + return retval; + } + + return dap_process_cmd(&dap_ctx[0], request, response); +} + +int dap_setup(const struct device *const dev) +{ + dap_ctx[0].swdp_dev = (void *)dev; + + if (!device_is_ready(dap_ctx[0].swdp_dev)) { + LOG_ERR("SWD driver not ready"); + return -ENODEV; + } + + /* Default settings */ + dap_ctx[0].pkt_size = 64U; + dap_ctx[0].debug_port = 0U; + dap_ctx[0].transfer.idle_cycles = 0U; + dap_ctx[0].transfer.retry_count = 100U; + dap_ctx[0].transfer.match_retry = 0U; + dap_ctx[0].transfer.match_mask = 0U; + dap_ctx[0].capabilities = DAP_SUPPORTS_ATOMIC_COMMANDS | + DAP_DP_SUPPORTS_SWD; + + return 0; +} diff --git a/subsys/dap/cmsis_dap.h b/subsys/dap/cmsis_dap.h new file mode 100644 index 0000000000000..0117ec1ab56a3 --- /dev/null +++ b/subsys/dap/cmsis_dap.h @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2018-2019 PHYTEC Messtechnik GmbH + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* + * This file is based on DAP.c from CMSIS-DAP Source (Revision: V2.0.0) + * https://github.com/ARM-software/CMSIS_5/tree/develop/CMSIS/DAP/Firmware + * Copyright (c) 2013-2017 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * @brief DAP controller private header + */ + +#ifndef ZEPHYR_INCLUDE_CMSIS_DAP_H_ +#define ZEPHYR_INCLUDE_CMSIS_DAP_H_ + +#include + +/* Firmware Version */ +#define DAP_FW_VER "1.10" + +/* DAP Command IDs */ +#define ID_DAP_INFO 0x00U +#define ID_DAP_HOST_STATUS 0x01U +#define ID_DAP_CONNECT 0x02U +#define ID_DAP_DISCONNECT 0x03U +#define ID_DAP_TRANSFER_CONFIGURE 0x04U +#define ID_DAP_TRANSFER 0x05U +#define ID_DAP_TRANSFER_BLOCK 0x06U +#define ID_DAP_TRANSFER_ABORT 0x07U +#define ID_DAP_WRITE_ABORT 0x08U +#define ID_DAP_DELAY 0x09U +#define ID_DAP_RESET_TARGET 0x0AU +#define ID_DAP_SWJ_PINS 0x10U +#define ID_DAP_SWJ_CLOCK 0x11U +#define ID_DAP_SWJ_SEQUENCE 0x12U +#define ID_DAP_SWDP_CONFIGURE 0x13U +#define ID_DAP_JTAG_SEQUENCE 0x14U +#define ID_DAP_JTAG_CONFIGURE 0x15U +#define ID_DAP_JTAG_IDCODE 0x16U +#define ID_DAP_SWO_TRANSPORT 0x17U +#define ID_DAP_SWO_MODE 0x18U +#define ID_DAP_SWO_BAUDRATE 0x19U +#define ID_DAP_SWO_CONTROL 0x1AU +#define ID_DAP_SWO_STATUS 0x1BU +#define ID_DAP_SWO_DATA 0x1CU + +#define ID_DAP_QUEUE_COMMANDS 0x7EU +#define ID_DAP_EXECUTE_COMMANDS 0x7FU + +/* DAP Vendor Command IDs */ +#define ID_DAP_VENDOR0 0x80U +#define ID_DAP_VENDOR31 0x9FU +#define ID_DAP_INVALID 0xFFU + +/* DAP Status Code */ +#define DAP_OK 0U +#define DAP_ERROR 0xFFU + +/* DAP ID */ +#define DAP_ID_VENDOR 0x01U +#define DAP_ID_PRODUCT 0x02U +#define DAP_ID_SER_NUM 0x03U +#define DAP_ID_FW_VER 0x04U +#define DAP_ID_DEVICE_VENDOR 0x05U +#define DAP_ID_DEVICE_NAME 0x06U +#define DAP_ID_CAPABILITIES 0xF0U +#define DAP_ID_SWO_BUFFER_SIZE 0xFDU +#define DAP_ID_PACKET_COUNT 0xFEU +#define DAP_ID_PACKET_SIZE 0xFFU + +/* DAP Host Status */ +#define DAP_DEBUGGER_CONNECTED 0U +#define DAP_TARGET_RUNNING 1U + +/* DAP Port */ +#define DAP_PORT_AUTODETECT 0U +#define DAP_PORT_DISABLED 0U +#define DAP_PORT_SWD 1U +#define DAP_PORT_JTAG 2U + +/* DAP transfer request bits */ +#define DAP_TRANSFER_MATCH_VALUE BIT(4) +#define DAP_TRANSFER_MATCH_MASK BIT(5) + +/* DAP transfer response bits */ +#define DAP_TRANSFER_MISMATCH BIT(4) + +/* DAP controller capabilities */ +#define DAP_DP_SUPPORTS_SWD BIT(0) +#define DAP_DP_SUPPORTS_JTAG BIT(1) +#define DAP_SWO_SUPPORTS_UART BIT(2) +#define DAP_SWO_SUPPORTS_MANCHESTER BIT(3) +#define DAP_SUPPORTS_ATOMIC_COMMANDS BIT(4) +#define DAP_SUPPORTS_TIMESTAMP_CLOCK BIT(5) +#define DAP_SWO_SUPPORTS_STREAM BIT(6) + +/* DP Register (DPv1) */ +#define DP_IDCODE 0x00U +#define DP_ABORT 0x00U +#define DP_CTRL_STAT 0x04U +#define DP_SELECT 0x08U +#define DP_RESEND 0x08U +#define DP_RDBUFF 0x0CU + +#define DAP_MBMSG_REGISTER_IFACE 0x0U +#define DAP_MBMSG_FROM_IFACE 0x1U +#define DAP_MBMSG_FROM_CONTROLLER 0x2U + +/* Keep it internal until an other interface has been implemented. */ +int dap_setup(const struct device *const dev); +uint32_t dap_execute_cmd(const uint8_t *request, uint8_t *response); + +#endif /* ZEPHYR_INCLUDE_CMSIS_DAP_H_ */ From e46e72320e61139383816c43f8ae81f6987a57bf Mon Sep 17 00:00:00 2001 From: Johan Carlsson Date: Fri, 21 Apr 2023 14:47:09 +0200 Subject: [PATCH 2696/2849] dap: add Konfig option to set maximum packet size This also fixes a bug where the packet size returned was only 17 byte. Signed-off-by: Johan Carlsson --- subsys/dap/Kconfig | 7 +++++++ subsys/dap/cmsis_dap.c | 6 +++--- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/subsys/dap/Kconfig b/subsys/dap/Kconfig index 434859581022e..71c2b6034b98b 100644 --- a/subsys/dap/Kconfig +++ b/subsys/dap/Kconfig @@ -17,6 +17,13 @@ config CMSIS_DAP_PACKET_COUNT help Maximum packet buffers for request and response data. +config CMSIS_DAP_PACKET_SIZE + int "Maximum packet size for request and response data." + default 64 + range 64 512 + help + Maximum packet size for request and response data. + module = DAP module-str = dap source "subsys/logging/Kconfig.template.log_config" diff --git a/subsys/dap/cmsis_dap.c b/subsys/dap/cmsis_dap.c index f1fc537366e3d..2bdd23378ea52 100644 --- a/subsys/dap/cmsis_dap.c +++ b/subsys/dap/cmsis_dap.c @@ -33,7 +33,7 @@ struct dap_context { atomic_t state; uint8_t debug_port; uint8_t capabilities; - uint8_t pkt_size; + uint16_t pkt_size; struct { /* Idle cycles after transfer */ uint8_t idle_cycles; @@ -88,7 +88,7 @@ static uint16_t dap_info(struct dap_context *const ctx, break; case DAP_ID_PACKET_SIZE: LOG_DBG("ID_PACKET_SIZE"); - sys_put_le16(ctx->capabilities, &info[0]); + sys_put_le16(ctx->pkt_size, &info[0]); length = 2U; break; case DAP_ID_PACKET_COUNT: @@ -912,7 +912,7 @@ int dap_setup(const struct device *const dev) } /* Default settings */ - dap_ctx[0].pkt_size = 64U; + dap_ctx[0].pkt_size = CONFIG_CMSIS_DAP_PACKET_SIZE; dap_ctx[0].debug_port = 0U; dap_ctx[0].transfer.idle_cycles = 0U; dap_ctx[0].transfer.retry_count = 100U; From f5ccc3c82ccd428bfbc4f6b1f10290ac0ddd75e2 Mon Sep 17 00:00:00 2001 From: Johan Carlsson Date: Sun, 23 Apr 2023 23:35:33 +0200 Subject: [PATCH 2697/2849] dap: do not return error in DAP connect command If a host client crashes or fails to disconnect, the probe will hang. Allow a new connection without raising errors. Signed-off-by: Johan Carlsson Signed-off-by: Johann Fischer --- subsys/dap/cmsis_dap.c | 1 - 1 file changed, 1 deletion(-) diff --git a/subsys/dap/cmsis_dap.c b/subsys/dap/cmsis_dap.c index 2bdd23378ea52..dba65495e43e3 100644 --- a/subsys/dap/cmsis_dap.c +++ b/subsys/dap/cmsis_dap.c @@ -153,7 +153,6 @@ static uint16_t dap_connect(struct dap_context *const ctx, if (atomic_test_and_set_bit(&ctx->state, DAP_STATE_CONNECTED)) { LOG_ERR("DAP device is already connected"); - port = DAP_ERROR; break; } From 3ef2c66a8ad0d347e68b6fe5f74b8e67b8f60e9e Mon Sep 17 00:00:00 2001 From: Maximilian Deubel Date: Fri, 7 Jul 2023 15:22:22 +0200 Subject: [PATCH 2698/2849] driver: swdp_bitbang: rework pin configurations Move low-level GPIO functions to a separate file and use GPIO driver API if low-level GPIO support is not available for the platform. Allows alternative pin configuration using only two pins, clk and dio. Improve binding description. Signed-off-by: Maximilian Deubel Signed-off-by: Johann Fischer --- drivers/dp/Kconfig | 1 + drivers/dp/swdp_bitbang.c | 340 ++++++++++++++---------- drivers/dp/swdp_ll_pin.h | 84 ++++++ dts/bindings/misc/zephyr,swdp-gpio.yaml | 84 +++++- 4 files changed, 357 insertions(+), 152 deletions(-) create mode 100644 drivers/dp/swdp_ll_pin.h diff --git a/drivers/dp/Kconfig b/drivers/dp/Kconfig index 77e33811a3930..b811529bcb5ce 100644 --- a/drivers/dp/Kconfig +++ b/drivers/dp/Kconfig @@ -24,6 +24,7 @@ config SWDP_BITBANG_DRIVER bool "Serial Wire Debug Port bit-bang driver" default y depends on DT_HAS_ZEPHYR_SWDP_GPIO_ENABLED + depends on GPIO help Serial Wire Debug Port bit-bang driver. diff --git a/drivers/dp/swdp_bitbang.c b/drivers/dp/swdp_bitbang.c index 6da04655cc011..e283c76c3e667 100644 --- a/drivers/dp/swdp_bitbang.c +++ b/drivers/dp/swdp_bitbang.c @@ -21,15 +21,11 @@ #include #include +#include "swdp_ll_pin.h" + #include LOG_MODULE_REGISTER(swdp, CONFIG_DP_DRIVER_LOG_LEVEL); -#if defined(CONFIG_SOC_SERIES_NRF52X) -#define CPU_CLOCK 64000000U -#else -#define CPU_CLOCK CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC -#endif - #define CLOCK_DELAY(swclk_freq, port_write_cycles) \ ((CPU_CLOCK / 2 / swclk_freq) - port_write_cycles) @@ -44,15 +40,15 @@ LOG_MODULE_REGISTER(swdp, CONFIG_DP_DRIVER_LOG_LEVEL); struct sw_config { struct gpio_dt_spec clk; struct gpio_dt_spec dout; - struct gpio_dt_spec din; + struct gpio_dt_spec dio; struct gpio_dt_spec dnoe; + void *dout_reg; + void *dio_reg; + void *dnoe_reg; struct gpio_dt_spec noe; struct gpio_dt_spec reset; uint32_t port_write_cycles; void *clk_reg; - void *dout_reg; - void *din_reg; - void *dnoe_reg; }; struct sw_cfg_data { @@ -98,102 +94,78 @@ static ALWAYS_INLINE uint32_t sw_get32bit_parity(uint32_t data) return data & 1U; } -static ALWAYS_INLINE void pin_delay_asm(uint32_t delay) -{ -#if defined(CONFIG_SOC_SERIES_NRF52X) - __asm volatile ("movs r3, %[p]\n" - ".start_%=:\n" - "subs r3, #1\n" - "bne .start_%=\n" - : - : [p] "r" (delay) - : "r3", "cc" - ); -#else -#error "Not defined for this SoC family" -#endif -} - -static ALWAYS_INLINE void pin_platform_set(void *base, uint8_t pin) -{ -#if defined(CONFIG_SOC_SERIES_NRF52X) - NRF_GPIO_Type * reg = base; - - reg->OUTSET = BIT(pin); -#else -#error "Not defined for this SoC family" -#endif -} - -static ALWAYS_INLINE void pin_platform_clr(void *base, uint8_t pin) -{ -#if defined(CONFIG_SOC_SERIES_NRF52X) - NRF_GPIO_Type * reg = base; - - reg->OUTCLR = BIT(pin); -#else -#error "Not defined for this SoC family" -#endif -} - -static ALWAYS_INLINE uint32_t pin_platform_get(void *base, uint8_t pin) -{ -#if defined(CONFIG_SOC_SERIES_NRF52X) - NRF_GPIO_Type * reg = base; - - return ((reg->IN >> pin) & 1); -#else -#error "Not defined for this SoC family" -#endif -} - /* Set SWCLK DAP hardware output pin to high level */ static ALWAYS_INLINE void pin_swclk_set(const struct device *dev) { const struct sw_config *config = dev->config; - const struct gpio_dt_spec *dt_spec = &config->clk; - pin_platform_set(config->clk_reg, dt_spec->pin); + if (FAST_BITBANG_HW_SUPPORT) { + swdp_ll_pin_set(config->clk_reg, config->clk.pin); + } else { + gpio_pin_set_dt(&config->clk, 1); + } } /* Set SWCLK DAP hardware output pin to low level */ static ALWAYS_INLINE void pin_swclk_clr(const struct device *dev) { const struct sw_config *config = dev->config; - const struct gpio_dt_spec *dt_spec = &config->clk; - pin_platform_clr(config->clk_reg, dt_spec->pin); + if (FAST_BITBANG_HW_SUPPORT) { + swdp_ll_pin_clr(config->clk_reg, config->clk.pin); + } else { + gpio_pin_set_dt(&config->clk, 0); + } } /* Set the SWDIO DAP hardware output pin to high level */ static ALWAYS_INLINE void pin_swdio_set(const struct device *dev) { const struct sw_config *config = dev->config; - const struct gpio_dt_spec *dt_spec = &config->dout; - pin_platform_set(config->dout_reg, dt_spec->pin); + if (config->dout.port) { + if (FAST_BITBANG_HW_SUPPORT) { + swdp_ll_pin_set(config->dout_reg, config->dout.pin); + } else { + gpio_pin_set_dt(&config->dout, 1); + } + } else { + if (FAST_BITBANG_HW_SUPPORT) { + swdp_ll_pin_set(config->dio_reg, config->dio.pin); + } else { + gpio_pin_set_dt(&config->dio, 1); + } + } } /* Set the SWDIO DAP hardware output pin to low level */ static ALWAYS_INLINE void pin_swdio_clr(const struct device *dev) { const struct sw_config *config = dev->config; - const struct gpio_dt_spec *dt_spec = &config->dout; - pin_platform_clr(config->dout_reg, dt_spec->pin); + if (config->dout.port) { + if (FAST_BITBANG_HW_SUPPORT) { + swdp_ll_pin_clr(config->dout_reg, config->dout.pin); + } else { + gpio_pin_set_dt(&config->dout, 0); + } + } else { + if (FAST_BITBANG_HW_SUPPORT) { + swdp_ll_pin_clr(config->dio_reg, config->dio.pin); + } else { + gpio_pin_set_dt(&config->dio, 0); + } + } } /* Set the SWDIO DAP hardware output pin to bit level */ static ALWAYS_INLINE void pin_swdio_out(const struct device *dev, const uint32_t bit) { - const struct sw_config *config = dev->config; - const struct gpio_dt_spec *dt_spec = &config->dout; - if (bit & 1U) { - pin_platform_set(config->dout_reg, dt_spec->pin); + pin_swdio_set(dev); } else { - pin_platform_clr(config->dout_reg, dt_spec->pin); + pin_swdio_clr(dev); } } @@ -201,9 +173,12 @@ static ALWAYS_INLINE void pin_swdio_out(const struct device *dev, static ALWAYS_INLINE uint32_t pin_swdio_in(const struct device *dev) { const struct sw_config *config = dev->config; - const struct gpio_dt_spec *dt_spec = &config->din; - return pin_platform_get(config->din_reg, dt_spec->pin); + if (FAST_BITBANG_HW_SUPPORT) { + return swdp_ll_pin_get(config->dio_reg, config->dio.pin); + } else { + return gpio_pin_get_dt(&config->dio); + } } /* @@ -213,9 +188,20 @@ static ALWAYS_INLINE uint32_t pin_swdio_in(const struct device *dev) static ALWAYS_INLINE void pin_swdio_out_enable(const struct device *dev) { const struct sw_config *config = dev->config; - const struct gpio_dt_spec *dt_spec = &config->dnoe; - pin_platform_set(config->dnoe_reg, dt_spec->pin); + if (config->dnoe.port) { + if (FAST_BITBANG_HW_SUPPORT) { + swdp_ll_pin_set(config->dnoe_reg, config->dnoe.pin); + } else { + gpio_pin_set_dt(&config->dnoe, 1); + } + } else { + if (FAST_BITBANG_HW_SUPPORT) { + swdp_ll_pin_output(config->dio_reg, config->dio.pin); + } else { + gpio_pin_configure_dt(&config->dio, GPIO_OUTPUT_ACTIVE); + } + } } /* @@ -224,9 +210,20 @@ static ALWAYS_INLINE void pin_swdio_out_enable(const struct device *dev) static ALWAYS_INLINE void pin_swdio_out_disable(const struct device *dev) { const struct sw_config *config = dev->config; - const struct gpio_dt_spec *dt_spec = &config->dnoe; - pin_platform_clr(config->dnoe_reg, dt_spec->pin); + if (config->dnoe.port) { + if (FAST_BITBANG_HW_SUPPORT) { + swdp_ll_pin_clr(config->dnoe_reg, config->dnoe.pin); + } else { + gpio_pin_set_dt(&config->dnoe, 0); + } + } else { + if (FAST_BITBANG_HW_SUPPORT) { + swdp_ll_pin_input(config->dio_reg, config->dio.pin); + } else { + gpio_pin_configure_dt(&config->dio, GPIO_INPUT); + } + } } #define SW_CLOCK_CYCLE(dev, delay) \ @@ -260,13 +257,14 @@ static int sw_sequence(const struct device *dev, uint32_t count, { struct sw_cfg_data *sw_data = dev->data; unsigned int key; - uint32_t val = 0; - uint32_t n = 0; + uint32_t val = 0; /* current byte */ + uint32_t n = 0; /* bit counter */ - LOG_DBG("count %u", count); + LOG_DBG("writing %u bits", count); LOG_HEXDUMP_DBG(data, count, "sequence bit data"); key = irq_lock(); + pin_swdio_out_enable(dev); while (count--) { if (n == 0U) { val = *data++; @@ -309,6 +307,8 @@ static int sw_transfer(const struct device *dev, uint32_t parity = 0; uint32_t n; + pin_swdio_out_enable(dev); + LOG_DBG("request 0x%02x idle %u", request, idle_cycles); if (!(request & SWDP_REQUEST_RnW)) { LOG_DBG("write data 0x%08x", *data); @@ -449,19 +449,31 @@ static int sw_set_pins(const struct device *dev, } } - if (pins & BIT(SWDP_SWDIO_PIN)) { - if (value & BIT(SWDP_SWDIO_PIN)) { - gpio_pin_set_dt(&config->dout, 1); - } else { - gpio_pin_set_dt(&config->dout, 0); + if (config->dout_reg != NULL) { + if (pins & BIT(SWDP_SWDIO_PIN)) { + if (value & BIT(SWDP_SWDIO_PIN)) { + gpio_pin_set_dt(&config->dout, 1); + } else { + gpio_pin_set_dt(&config->dout, 0); + } + } + } else { + if (pins & BIT(SWDP_SWDIO_PIN)) { + if (value & BIT(SWDP_SWDIO_PIN)) { + gpio_pin_set_dt(&config->dio, 1); + } else { + gpio_pin_set_dt(&config->dio, 0); + } } } - if (pins & BIT(SWDP_nRESET_PIN)) { - if (value & BIT(SWDP_nRESET_PIN)) { - gpio_pin_set_dt(&config->reset, 1); - } else { - gpio_pin_set_dt(&config->reset, 0); + if (config->reset.port) { + if (pins & BIT(SWDP_nRESET_PIN)) { + if (value & BIT(SWDP_nRESET_PIN)) { + gpio_pin_set_dt(&config->reset, 1); + } else { + gpio_pin_set_dt(&config->reset, 0); + } } } @@ -473,10 +485,12 @@ static int sw_get_pins(const struct device *dev, uint8_t *const state) const struct sw_config *config = dev->config; uint32_t val; - val = gpio_pin_get_dt(&config->reset); - *state = val ? BIT(SWDP_nRESET_PIN) : 0; + if (config->reset.port) { + val = gpio_pin_get_dt(&config->reset); + *state = val ? BIT(SWDP_nRESET_PIN) : 0; + } - val = gpio_pin_get_dt(&config->din); + val = gpio_pin_get_dt(&config->dio); *state |= val ? BIT(SWDP_SWDIO_PIN) : 0; val = gpio_pin_get_dt(&config->clk); @@ -529,10 +543,28 @@ static int sw_port_on(const struct device *dev) const struct sw_config *config = dev->config; gpio_pin_set_dt(&config->clk, 1); - gpio_pin_set_dt(&config->dout, 1); - gpio_pin_set_dt(&config->dnoe, 1); - gpio_pin_set_dt(&config->noe, 1); - gpio_pin_set_dt(&config->reset, 1); + + if (config->dnoe.port) { + gpio_pin_set_dt(&config->dnoe, 1); + } + + if (config->dout.port) { + gpio_pin_set_dt(&config->dout, 1); + } else { + int ret; + + ret = gpio_pin_configure_dt(&config->dio, GPIO_OUTPUT_ACTIVE); + if (ret) { + return ret; + } + } + + if (config->noe.port) { + gpio_pin_set_dt(&config->noe, 1); + } + if (config->reset.port) { + gpio_pin_set_dt(&config->reset, 1); + } return 0; } @@ -541,9 +573,27 @@ static int sw_port_off(const struct device *dev) { const struct sw_config *config = dev->config; - gpio_pin_set_dt(&config->dnoe, 0); - gpio_pin_set_dt(&config->noe, 0); - gpio_pin_set_dt(&config->reset, 1); + if (config->dnoe.port) { + gpio_pin_set_dt(&config->dnoe, 0); + } + + if (config->dout.port) { + gpio_pin_set_dt(&config->dout, 0); + } else { + int ret; + + ret = gpio_pin_configure_dt(&config->dio, GPIO_INPUT); + if (ret) { + return ret; + } + } + + if (config->noe.port) { + gpio_pin_set_dt(&config->noe, 0); + } + if (config->reset.port) { + gpio_pin_set_dt(&config->reset, 1); + } return 0; } @@ -559,29 +609,37 @@ static int sw_gpio_init(const struct device *dev) return ret; } - ret = gpio_pin_configure_dt(&config->dout, GPIO_OUTPUT_ACTIVE); + ret = gpio_pin_configure_dt(&config->dio, GPIO_INPUT); if (ret) { return ret; } - ret = gpio_pin_configure_dt(&config->din, GPIO_INPUT); - if (ret) { - return ret; + if (config->dout.port) { + ret = gpio_pin_configure_dt(&config->dout, GPIO_OUTPUT_ACTIVE); + if (ret) { + return ret; + } } - ret = gpio_pin_configure_dt(&config->dnoe, GPIO_OUTPUT_INACTIVE); - if (ret) { - return ret; + if (config->dnoe.port) { + ret = gpio_pin_configure_dt(&config->dnoe, GPIO_OUTPUT_INACTIVE); + if (ret) { + return ret; + } } - ret = gpio_pin_configure_dt(&config->noe, GPIO_OUTPUT_INACTIVE); - if (ret) { - return ret; + if (config->noe.port) { + ret = gpio_pin_configure_dt(&config->noe, GPIO_OUTPUT_INACTIVE); + if (ret) { + return ret; + } } - ret = gpio_pin_configure_dt(&config->reset, GPIO_OUTPUT_INACTIVE); - if (ret) { - return ret; + if (config->reset.port) { + ret = gpio_pin_configure_dt(&config->reset, GPIO_OUTPUT_ACTIVE); + if (ret) { + return ret; + } } sw_data->turnaround = 1U; @@ -605,29 +663,35 @@ static struct swdp_api swdp_bitbang_api = { .swdp_port_off = sw_port_off, }; -#define SW_GPIOS_GET_REG(n, gpios) \ - INT_TO_POINTER(DT_REG_ADDR(DT_PHANDLE(DT_DRV_INST(n), gpios))) - -#define SW_DEVICE_DEFINE(n) \ - static const struct sw_config sw_cfg_##n = { \ - .clk = GPIO_DT_SPEC_INST_GET(n, clk_gpios), \ - .dout = GPIO_DT_SPEC_INST_GET(n, dout_gpios), \ - .din = GPIO_DT_SPEC_INST_GET(n, din_gpios), \ - .dnoe = GPIO_DT_SPEC_INST_GET(n, dnoe_gpios), \ - .noe = GPIO_DT_SPEC_INST_GET(n, noe_gpios), \ - .reset = GPIO_DT_SPEC_INST_GET(n, reset_gpios), \ - .port_write_cycles = DT_INST_PROP(n, port_write_cycles), \ - .clk_reg = SW_GPIOS_GET_REG(n, clk_gpios), \ - .dout_reg = SW_GPIOS_GET_REG(n, dout_gpios), \ - .din_reg = SW_GPIOS_GET_REG(n, din_gpios), \ - .dnoe_reg = SW_GPIOS_GET_REG(n, dnoe_gpios), \ - }; \ - \ - static struct sw_cfg_data sw_data_##n; \ - \ - DEVICE_DT_INST_DEFINE(n, sw_gpio_init, NULL, \ - &sw_data_##n, &sw_cfg_##n, \ - POST_KERNEL, CONFIG_DP_DRIVER_INIT_PRIO, \ - &swdp_bitbang_api); \ +#define SW_GPIOS_GET_REG(n, gpios) \ + COND_CODE_1(DT_INST_NODE_HAS_PROP(n, gpios), \ + (INT_TO_POINTER(DT_REG_ADDR(DT_PHANDLE(DT_DRV_INST(n), gpios)))), \ + (NULL)) + +#define SW_DEVICE_DEFINE(n) \ + BUILD_ASSERT((DT_INST_NODE_HAS_PROP(n, dout_gpios)) == \ + (DT_INST_NODE_HAS_PROP(n, dnoe_gpios)), \ + "Either the dout-gpios or dnoe-gpios property is missing."); \ + \ + static const struct sw_config sw_cfg_##n = { \ + .clk = GPIO_DT_SPEC_INST_GET(n, clk_gpios), \ + .clk_reg = SW_GPIOS_GET_REG(n, clk_gpios), \ + .dio = GPIO_DT_SPEC_INST_GET(n, dio_gpios), \ + .dio_reg = SW_GPIOS_GET_REG(n, dio_gpios), \ + .dout = GPIO_DT_SPEC_INST_GET_OR(n, dout_gpios, {0}), \ + .dout_reg = SW_GPIOS_GET_REG(n, dout_gpios), \ + .dnoe = GPIO_DT_SPEC_INST_GET_OR(n, dnoe_gpios, {0}), \ + .dnoe_reg = SW_GPIOS_GET_REG(n, dnoe_gpios), \ + .noe = GPIO_DT_SPEC_INST_GET_OR(n, noe_gpios, {0}), \ + .reset = GPIO_DT_SPEC_INST_GET_OR(n, reset_gpios, {0}), \ + .port_write_cycles = DT_INST_PROP(n, port_write_cycles), \ + }; \ + \ + static struct sw_cfg_data sw_data_##n; \ + \ + DEVICE_DT_INST_DEFINE(n, sw_gpio_init, NULL, \ + &sw_data_##n, &sw_cfg_##n, \ + POST_KERNEL, CONFIG_DP_DRIVER_INIT_PRIO, \ + &swdp_bitbang_api); DT_INST_FOREACH_STATUS_OKAY(SW_DEVICE_DEFINE) diff --git a/drivers/dp/swdp_ll_pin.h b/drivers/dp/swdp_ll_pin.h new file mode 100644 index 0000000000000..3044931a228a8 --- /dev/null +++ b/drivers/dp/swdp_ll_pin.h @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +#if defined(CONFIG_SOC_SERIES_NRF52X) +#define CPU_CLOCK 64000000U +#else +#define CPU_CLOCK CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC +#endif + +#if defined(CONFIG_SOC_SERIES_NRF52X) || defined(CONFIG_SOC_SERIES_NRF53X) +#define FAST_BITBANG_HW_SUPPORT 1 +#else +#define FAST_BITBANG_HW_SUPPORT 0 +#endif + +static ALWAYS_INLINE void pin_delay_asm(uint32_t delay) +{ +#if defined(CONFIG_CPU_CORTEX_M) + __asm volatile ("movs r3, %[p]\n" + ".start_%=:\n" + "subs r3, #1\n" + "bne .start_%=\n" + : + : [p] "r" (delay) + : "r3", "cc" + ); +#else +#warning "Pin delay is not defined" +#endif +} + +static ALWAYS_INLINE void swdp_ll_pin_input(void *const base, uint8_t pin) +{ +#if defined(CONFIG_SOC_SERIES_NRF52X) || defined(CONFIG_SOC_SERIES_NRF53X) + NRF_GPIO_Type * reg = base; + + reg->PIN_CNF[pin] = 0b0000; +#endif +} + +static ALWAYS_INLINE void swdp_ll_pin_output(void *const base, uint8_t pin) +{ +#if defined(CONFIG_SOC_SERIES_NRF52X) || defined(CONFIG_SOC_SERIES_NRF53X) + NRF_GPIO_Type * reg = base; + + reg->PIN_CNF[pin] = 0b0001; +#endif +} + + +static ALWAYS_INLINE void swdp_ll_pin_set(void *const base, uint8_t pin) +{ +#if defined(CONFIG_SOC_SERIES_NRF52X) || defined(CONFIG_SOC_SERIES_NRF53X) + NRF_GPIO_Type * reg = base; + + reg->OUTSET = BIT(pin); +#endif +} + +static ALWAYS_INLINE void swdp_ll_pin_clr(void *const base, uint8_t pin) +{ +#if defined(CONFIG_SOC_SERIES_NRF52X) || defined(CONFIG_SOC_SERIES_NRF53X) + NRF_GPIO_Type * reg = base; + + reg->OUTCLR = BIT(pin); +#endif +} + +static ALWAYS_INLINE uint32_t swdp_ll_pin_get(void *const base, uint8_t pin) +{ +#if defined(CONFIG_SOC_SERIES_NRF52X) || defined(CONFIG_SOC_SERIES_NRF53X) + NRF_GPIO_Type * reg = base; + + return ((reg->IN >> pin) & 1); +#else + return 0UL; +#endif +} diff --git a/dts/bindings/misc/zephyr,swdp-gpio.yaml b/dts/bindings/misc/zephyr,swdp-gpio.yaml index 5d38449ad494e..c6d6aa55e7fa8 100644 --- a/dts/bindings/misc/zephyr,swdp-gpio.yaml +++ b/dts/bindings/misc/zephyr,swdp-gpio.yaml @@ -1,10 +1,60 @@ -# Copyright (c) 2019, Phytec Messtechnik GmbH +# Copyright (c) 2019 Phytec Messtechnik GmbH +# Copyright (c) 2023 Nordic Semiconductor ASA # SPDX-License-Identifier: Apache-2.0 -description: > +description: | This is a representation of the Serial Wire Debug Port interface implementation by GPIO bit-banging. + Schematic using dual-supply bus transceiver and separate dout and dnoe pins + + VCC_3V3 VCC_REF + ^ ^ + | +-------------+ | + +-------|vcca vccb|-----+ + | | + clk-gpios -------|a b|-------------- SWD CLK + | | + noe-gpios -------|dir gnd|-----+ + +-------------+ | + 74LVC1T45 v + GND + + + VCC_3V3 VCC_REF + ^ ^ + | +-------------+ | + +-------|vcca vccb|-----+ + | | + dio-gpios -------|a b|------------*- SWD DIO + | | | + +-------|dir gnd|-----+ | + | +-------------+ | | + v 74LVC1T45 v | + GND GND | + | + | + VCC_3V3 VCC_REF | + ^ ^ | + | +-------------+ | | + +-------|vcca vccb|-----+ | + | | | + dout-gpios -------|a b|------------+ + | | + dnoe-gpios -------|dir gnd|-----+ + +-------------+ | + 74LVC1T45 v + GND + + Direct connection using only dio pin for SWD DIO. + + clk-gpios ------------------------------------ SWD CLK + + dio-gpios ------------------------------------ SWD DIO + + Of course, bidirectional bus transceiver between dio and SWD DIO can also be + used together with noe pin to enable/disable transceivers. + compatible: "zephyr,swdp-gpio" include: base.yaml @@ -15,32 +65,38 @@ properties: required: true description: GPIO pin used for SWCLK output - dout-gpios: + dio-gpios: type: phandle-array required: true - description: GPIO pin used for SWDIO output + description: | + GPIO pin used for SWDIO input. This pin is also used for the SWDIO output + if separate output pin is not defined. - din-gpios: + dout-gpios: type: phandle-array - required: true - description: GPIO pin used for SWDIO input + description: | + Optional GPIO pin used for SWDIO output. dnoe-gpios: type: phandle-array - required: true - description: GPIO pin used for SWDIO NOE output + description: | + GPIO pin used to disable the SWDIO output buffer behind optional + pin dout-gpios. noe-gpios: type: phandle-array - required: true - description: GPIO pin used for SWD NOE output + description: | + Optional pin to disable all bus transceivers if any are present. reset-gpios: type: phandle-array - required: true - description: GPIO pin used for RESET output + description: | + Optional GPIO pin used for RESET output. port-write-cycles: type: int required: true - description: Number of processor cycles for I/O Port write operations + description: | + Number of processor cycles for I/O Port write operations.For example, the + GPIO clock may be different from the CPU clock. This can usually be + found in the SoC documentation. From 3e8f9fb7dfff9e717da8c67b0519db23352112be Mon Sep 17 00:00:00 2001 From: Johann Fischer Date: Thu, 31 Aug 2023 17:10:00 +0200 Subject: [PATCH 2699/2849] drivers: swdp_bitbang: add SW output sequence Add API to read count bits from SWDIO into data LSB first. Signed-off-by: Maximilian Deubel Signed-off-by: Johann Fischer --- drivers/dp/swdp_bitbang.c | 40 +++++++++++++++++++++++++++++++---- include/zephyr/drivers/swdp.h | 11 +++++++--- subsys/dap/cmsis_dap.c | 2 +- 3 files changed, 45 insertions(+), 8 deletions(-) diff --git a/drivers/dp/swdp_bitbang.c b/drivers/dp/swdp_bitbang.c index e283c76c3e667..f3c5fcc50d2d6 100644 --- a/drivers/dp/swdp_bitbang.c +++ b/drivers/dp/swdp_bitbang.c @@ -252,8 +252,8 @@ static ALWAYS_INLINE void pin_swdio_out_disable(const struct device *dev) pin_delay_asm(delay); \ } while (0) -static int sw_sequence(const struct device *dev, uint32_t count, - const uint8_t *data) +static int sw_output_sequence(const struct device *dev, uint32_t count, + const uint8_t *data) { struct sw_cfg_data *sw_data = dev->data; unsigned int key; @@ -285,6 +285,37 @@ static int sw_sequence(const struct device *dev, uint32_t count, return 0; } +static int sw_input_sequence(const struct device *dev, uint32_t count, + uint8_t *data) +{ + struct sw_cfg_data *sw_data = dev->data; + unsigned int key; + uint32_t val = 0U; /* current byte */ + uint32_t n = 8U; /* bit counter */ + uint32_t bit; + + LOG_DBG("reading %u bits", count); + key = irq_lock(); + + pin_swdio_out_disable(dev); + while (count--) { + if (n == 0U) { + *data++ = val; + val = 0; + n = 8U; + } + SW_READ_BIT(dev, bit, sw_data->clock_delay); + LOG_DBG("Read bit: %d", bit); + val = (val << 1 | bit); + n--; + } + + *data = val; /* write last byte */ + irq_unlock(key); + + return 0; +} + static ALWAYS_INLINE void sw_cycle_turnaround(const struct device *dev) { struct sw_cfg_data *sw_data = dev->data; @@ -653,7 +684,8 @@ static int sw_gpio_init(const struct device *dev) } static struct swdp_api swdp_bitbang_api = { - .swdp_sequence = sw_sequence, + .swdp_output_sequence = sw_output_sequence, + .swdp_input_sequence = sw_input_sequence, .swdp_transfer = sw_transfer, .swdp_set_pins = sw_set_pins, .swdp_get_pins = sw_get_pins, @@ -669,7 +701,7 @@ static struct swdp_api swdp_bitbang_api = { (NULL)) #define SW_DEVICE_DEFINE(n) \ - BUILD_ASSERT((DT_INST_NODE_HAS_PROP(n, dout_gpios)) == \ + BUILD_ASSERT((DT_INST_NODE_HAS_PROP(n, dout_gpios)) == \ (DT_INST_NODE_HAS_PROP(n, dnoe_gpios)), \ "Either the dout-gpios or dnoe-gpios property is missing."); \ \ diff --git a/include/zephyr/drivers/swdp.h b/include/zephyr/drivers/swdp.h index f15a4b40ecd09..c1f06e521510a 100644 --- a/include/zephyr/drivers/swdp.h +++ b/include/zephyr/drivers/swdp.h @@ -43,9 +43,14 @@ extern "C" { */ struct swdp_api { /* Generate SWJ Sequence according to sequence bit count and bit data */ - int (*swdp_sequence)(const struct device *dev, - uint32_t count, - const uint8_t *data); + int (*swdp_output_sequence)(const struct device *dev, + uint32_t count, + const uint8_t *data); + + /* Read count bits from SWDIO into data LSB first */ + int (*swdp_input_sequence)(const struct device *dev, + uint32_t count, + uint8_t *data); /* * Perform SWDP transfer based on host request value and store diff --git a/subsys/dap/cmsis_dap.c b/subsys/dap/cmsis_dap.c index dba65495e43e3..2e345f999625f 100644 --- a/subsys/dap/cmsis_dap.c +++ b/subsys/dap/cmsis_dap.c @@ -297,7 +297,7 @@ static uint16_t dap_swj_sequence(struct dap_context *const ctx, return 1U; } - api->swdp_sequence(ctx->swdp_dev, count, &request[1]); + api->swdp_output_sequence(ctx->swdp_dev, count, &request[1]); response[0] = DAP_OK; return 1U; From 6522dd7f5395bd4f65d1d608d7dbf4339ea7c9ed Mon Sep 17 00:00:00 2001 From: Maximilian Deubel Date: Fri, 7 Jul 2023 15:23:55 +0200 Subject: [PATCH 2700/2849] dap: implement wait for SWJ pins command Implement wait for SWJ pins command. Signed-off-by: Maximilian Deubel --- subsys/dap/cmsis_dap.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/subsys/dap/cmsis_dap.c b/subsys/dap/cmsis_dap.c index 2e345f999625f..455fa367604a9 100644 --- a/subsys/dap/cmsis_dap.c +++ b/subsys/dap/cmsis_dap.c @@ -229,6 +229,7 @@ static uint16_t dap_swj_pins(struct dap_context *const ctx, uint8_t value = request[0]; uint8_t select = request[1]; uint32_t wait = sys_get_le32(&request[2]); + int64_t timeout_ticks; uint8_t state; if (!atomic_test_bit(&ctx->state, DAP_STATE_CONNECTED)) { @@ -242,10 +243,17 @@ static uint16_t dap_swj_pins(struct dap_context *const ctx, api->swdp_set_pins(ctx->swdp_dev, select, value); } - /* TODO: implement wait */ - api->swdp_get_pins(ctx->swdp_dev, &state); - LOG_ERR("select 0x%02x, value 0x%02x, wait %u, state 0x%02x", - select, value, wait, state); + timeout_ticks = k_uptime_ticks() + (CONFIG_SYS_CLOCK_TICKS_PER_SEC / 1000000 * wait); + + do { + api->swdp_get_pins(ctx->swdp_dev, &state); + LOG_INF("select 0x%02x, value 0x%02x, wait %u, state 0x%02x", + select, value, wait, state); + if ((value & select) == (state & select)) { + LOG_DBG("swdp_get_pins succeeded before timeout"); + break; + } + } while (k_uptime_ticks() - timeout_ticks > 0); response[0] = state; From 58d9d889aa11ca88871b755256c6cb9298b62922 Mon Sep 17 00:00:00 2001 From: Maximilian Deubel Date: Fri, 7 Jul 2023 15:25:55 +0200 Subject: [PATCH 2701/2849] dap: add support for DAP_INFO string elements Add support for DAP_INFO string elements. Signed-off-by: Maximilian Deubel --- subsys/dap/Kconfig | 24 ++++++++++++++ subsys/dap/cmsis_dap.c | 74 +++++++++++++++++++++++++++++++++++++----- subsys/dap/cmsis_dap.h | 10 ++++++ 3 files changed, 99 insertions(+), 9 deletions(-) diff --git a/subsys/dap/Kconfig b/subsys/dap/Kconfig index 71c2b6034b98b..2436ba71c4eec 100644 --- a/subsys/dap/Kconfig +++ b/subsys/dap/Kconfig @@ -24,6 +24,30 @@ config CMSIS_DAP_PACKET_SIZE help Maximum packet size for request and response data. +config CMSIS_DAP_PROBE_VENDOR + string "Probe vendor" + default "Zephyr" + +config CMSIS_DAP_PROBE_NAME + string "Probe name" + default "CMSIS-DAP" + +config CMSIS_DAP_BOARD_VENDOR + string "Target board vendor" + default "" + +config CMSIS_DAP_BOARD_NAME + string "Target board name" + default "" + +config CMSIS_DAP_DEVICE_VENDOR + string "Target device vendor" + default "" + +config CMSIS_DAP_DEVICE_NAME + string "Target device name" + default "" + module = DAP module-str = dap source "subsys/logging/Kconfig.template.log_config" diff --git a/subsys/dap/cmsis_dap.c b/subsys/dap/cmsis_dap.c index 455fa367604a9..bab57301209f3 100644 --- a/subsys/dap/cmsis_dap.c +++ b/subsys/dap/cmsis_dap.c @@ -18,14 +18,13 @@ #include #include #include +#include #include #include LOG_MODULE_REGISTER(dap, CONFIG_DAP_LOG_LEVEL); -const char dap_fw_ver[] = DAP_FW_VER; - #define DAP_STATE_CONNECTED 0 struct dap_context { @@ -48,6 +47,25 @@ struct dap_context { static struct dap_context dap_ctx[1]; +BUILD_ASSERT(sizeof(CONFIG_CMSIS_DAP_PROBE_VENDOR) <= + MIN(CONFIG_CMSIS_DAP_PACKET_SIZE - 2, UINT8_MAX - 2), + "PROBE_VENDOR string is too long."); +BUILD_ASSERT(sizeof(CONFIG_CMSIS_DAP_PROBE_NAME) <= + MIN(CONFIG_CMSIS_DAP_PACKET_SIZE - 2, UINT8_MAX - 2), + "PROBE_NAME string is too long."); +BUILD_ASSERT(sizeof(CONFIG_CMSIS_DAP_BOARD_VENDOR) <= + MIN(CONFIG_CMSIS_DAP_PACKET_SIZE - 2, UINT8_MAX - 2), + "BOARD_VENDOR string is too long."); +BUILD_ASSERT(sizeof(CONFIG_CMSIS_DAP_BOARD_NAME) <= + MIN(CONFIG_CMSIS_DAP_PACKET_SIZE - 2, UINT8_MAX - 2), + "BOARD_NAME string is too long."); +BUILD_ASSERT(sizeof(CONFIG_CMSIS_DAP_DEVICE_VENDOR) <= + MIN(CONFIG_CMSIS_DAP_PACKET_SIZE - 2, UINT8_MAX - 2), + "DEVICE_VENDOR string is too long."); +BUILD_ASSERT(sizeof(CONFIG_CMSIS_DAP_DEVICE_NAME) <= + MIN(CONFIG_CMSIS_DAP_PACKET_SIZE - 2, UINT8_MAX - 2), + "DEVICE_NAME string is too long."); + /* Get DAP Information */ static uint16_t dap_info(struct dap_context *const ctx, const uint8_t *const request, @@ -59,30 +77,68 @@ static uint16_t dap_info(struct dap_context *const ctx, switch (id) { case DAP_ID_VENDOR: - LOG_DBG("ID_VENDOR unsupported"); + LOG_DBG("ID_VENDOR"); + memcpy(info, CONFIG_CMSIS_DAP_PROBE_VENDOR, + sizeof(CONFIG_CMSIS_DAP_PROBE_VENDOR)); + length = sizeof(CONFIG_CMSIS_DAP_PROBE_VENDOR); break; case DAP_ID_PRODUCT: - LOG_DBG("ID_PRODUCT unsupported"); + LOG_DBG("ID_PRODUCT"); + memcpy(info, CONFIG_CMSIS_DAP_PROBE_NAME, + sizeof(CONFIG_CMSIS_DAP_PROBE_NAME)); + length = sizeof(CONFIG_CMSIS_DAP_PROBE_NAME); break; case DAP_ID_SER_NUM: + /* optional to implement */ LOG_DBG("ID_SER_NUM unsupported"); break; case DAP_ID_FW_VER: LOG_DBG("ID_FW_VER"); - memcpy(info, dap_fw_ver, sizeof(dap_fw_ver)); - length = (uint8_t)sizeof(dap_fw_ver); + memcpy(info, DAP_FW_VER, sizeof(DAP_FW_VER)); + length = sizeof(DAP_FW_VER); break; case DAP_ID_DEVICE_VENDOR: - LOG_DBG("ID_DEVICE_VENDOR unsupported"); + LOG_DBG("ID_DEVICE_VENDOR"); + memcpy(info, CONFIG_CMSIS_DAP_DEVICE_VENDOR, + sizeof(CONFIG_CMSIS_DAP_DEVICE_VENDOR)); + length = sizeof(CONFIG_CMSIS_DAP_DEVICE_VENDOR); break; case DAP_ID_DEVICE_NAME: - LOG_DBG("ID_DEVICE_NAME unsupported"); + LOG_DBG("ID_DEVICE_NAME"); + memcpy(info, CONFIG_CMSIS_DAP_DEVICE_NAME, + sizeof(CONFIG_CMSIS_DAP_DEVICE_NAME)); + length = sizeof(CONFIG_CMSIS_DAP_DEVICE_NAME); + break; + case DAP_ID_BOARD_VENDOR: + LOG_DBG("ID_BOARD_VENDOR"); + memcpy(info, CONFIG_CMSIS_DAP_BOARD_VENDOR, + sizeof(CONFIG_CMSIS_DAP_BOARD_VENDOR)); + length = sizeof(CONFIG_CMSIS_DAP_BOARD_VENDOR); + break; + case DAP_ID_BOARD_NAME: + memcpy(info, CONFIG_CMSIS_DAP_BOARD_NAME, + sizeof(CONFIG_CMSIS_DAP_BOARD_NAME)); + length = sizeof(CONFIG_CMSIS_DAP_BOARD_NAME); + LOG_DBG("ID_BOARD_NAME"); + break; + case DAP_ID_PRODUCT_FW_VER: + /* optional to implement */ + LOG_DBG("ID_PRODUCT_FW_VER unsupported"); break; case DAP_ID_CAPABILITIES: info[0] = ctx->capabilities; LOG_DBG("ID_CAPABILITIES 0x%0x", info[0]); length = 1U; break; + case DAP_ID_TIMESTAMP_CLOCK: + LOG_DBG("ID_TIMESTAMP_CLOCK unsupported"); + break; + case DAP_ID_UART_RX_BUFFER_SIZE: + LOG_DBG("ID_UART_RX_BUFFER_SIZE unsupported"); + break; + case DAP_ID_UART_TX_BUFFER_SIZE: + LOG_DBG("ID_UART_TX_BUFFER_SIZE unsupported"); + break; case DAP_ID_SWO_BUFFER_SIZE: LOG_DBG("ID_SWO_BUFFER_SIZE unsupported"); break; @@ -101,7 +157,7 @@ static uint16_t dap_info(struct dap_context *const ctx, break; } - response[0] = (uint8_t)length; + response[0] = length; return length + 1U; } diff --git a/subsys/dap/cmsis_dap.h b/subsys/dap/cmsis_dap.h index 0117ec1ab56a3..2e1fe10e83620 100644 --- a/subsys/dap/cmsis_dap.h +++ b/subsys/dap/cmsis_dap.h @@ -36,13 +36,17 @@ #define ID_DAP_WRITE_ABORT 0x08U #define ID_DAP_DELAY 0x09U #define ID_DAP_RESET_TARGET 0x0AU + #define ID_DAP_SWJ_PINS 0x10U #define ID_DAP_SWJ_CLOCK 0x11U #define ID_DAP_SWJ_SEQUENCE 0x12U + #define ID_DAP_SWDP_CONFIGURE 0x13U + #define ID_DAP_JTAG_SEQUENCE 0x14U #define ID_DAP_JTAG_CONFIGURE 0x15U #define ID_DAP_JTAG_IDCODE 0x16U + #define ID_DAP_SWO_TRANSPORT 0x17U #define ID_DAP_SWO_MODE 0x18U #define ID_DAP_SWO_BAUDRATE 0x19U @@ -69,7 +73,13 @@ #define DAP_ID_FW_VER 0x04U #define DAP_ID_DEVICE_VENDOR 0x05U #define DAP_ID_DEVICE_NAME 0x06U +#define DAP_ID_BOARD_VENDOR 0x07U +#define DAP_ID_BOARD_NAME 0x08U +#define DAP_ID_PRODUCT_FW_VER 0x09U #define DAP_ID_CAPABILITIES 0xF0U +#define DAP_ID_TIMESTAMP_CLOCK 0xF1U +#define DAP_ID_UART_RX_BUFFER_SIZE 0xFBU +#define DAP_ID_UART_TX_BUFFER_SIZE 0xFCU #define DAP_ID_SWO_BUFFER_SIZE 0xFDU #define DAP_ID_PACKET_COUNT 0xFEU #define DAP_ID_PACKET_SIZE 0xFFU From e31cdc00a0a28bc246c75cdf7dd27366b31b09ba Mon Sep 17 00:00:00 2001 From: Johann Fischer Date: Thu, 31 Aug 2023 18:01:15 +0200 Subject: [PATCH 2702/2849] dap: react properly to unsupported UART commands Add ID_DAP_UART_* command definitions and react properly to unsupported UART commands. Signed-off-by: Maximilian Deubel Signed-off-by: Johann Fischer --- subsys/dap/cmsis_dap.c | 25 +++++++++++++++++++++++++ subsys/dap/cmsis_dap.h | 6 ++++++ 2 files changed, 31 insertions(+) diff --git a/subsys/dap/cmsis_dap.c b/subsys/dap/cmsis_dap.c index bab57301209f3..76127c801d458 100644 --- a/subsys/dap/cmsis_dap.c +++ b/subsys/dap/cmsis_dap.c @@ -922,6 +922,31 @@ static uint16_t dap_process_cmd(struct dap_context *const ctx, retval = 1; *response = DAP_ERROR; break; + case ID_DAP_UART_TRANSPORT: + LOG_ERR("UART Transport unsupported"); + retval = 1; + *response = DAP_ERROR; + break; + case ID_DAP_UART_CONFIGURE: + LOG_ERR("UART Configure unsupported"); + retval = 1; + *response = DAP_ERROR; + break; + case ID_DAP_UART_CONTROL: + LOG_ERR("UART Control unsupported"); + retval = 1; + *response = DAP_ERROR; + break; + case ID_DAP_UART_STATUS: + LOG_ERR("UART Status unsupported"); + retval = 1; + *response = DAP_ERROR; + break; + case ID_DAP_UART_TRANSFER: + LOG_ERR("UART Transfer unsupported"); + retval = 1; + *response = DAP_ERROR; + break; default: *(response - 1) = ID_DAP_INVALID; diff --git a/subsys/dap/cmsis_dap.h b/subsys/dap/cmsis_dap.h index 2e1fe10e83620..787dc822b79ec 100644 --- a/subsys/dap/cmsis_dap.h +++ b/subsys/dap/cmsis_dap.h @@ -54,6 +54,12 @@ #define ID_DAP_SWO_STATUS 0x1BU #define ID_DAP_SWO_DATA 0x1CU +#define ID_DAP_UART_TRANSPORT 0x1FU +#define ID_DAP_UART_CONFIGURE 0x20U +#define ID_DAP_UART_CONTROL 0x22U +#define ID_DAP_UART_STATUS 0x23U +#define ID_DAP_UART_TRANSFER 0x21U + #define ID_DAP_QUEUE_COMMANDS 0x7EU #define ID_DAP_EXECUTE_COMMANDS 0x7FU From 9a9afb0b54324ef28b6ca0a1c4ee5e66b51805ec Mon Sep 17 00:00:00 2001 From: Johann Fischer Date: Thu, 31 Aug 2023 18:01:51 +0200 Subject: [PATCH 2703/2849] dap: implement DAP SWD sequence command DAP SWD sequence command is a requirement to support CMSIS-DAPv2. Raise supported version to "2.1.0". Signed-off-by: Maximilian Deubel Signed-off-by: Johann Fischer --- subsys/dap/cmsis_dap.c | 49 ++++++++++++++++++++++++++++++++++++++++++ subsys/dap/cmsis_dap.h | 3 ++- 2 files changed, 51 insertions(+), 1 deletion(-) diff --git a/subsys/dap/cmsis_dap.c b/subsys/dap/cmsis_dap.c index 76127c801d458..5bf3f01976ff5 100644 --- a/subsys/dap/cmsis_dap.c +++ b/subsys/dap/cmsis_dap.c @@ -638,6 +638,52 @@ static uint16_t dap_transfer(struct dap_context *const ctx, return retval; } +static uint16_t dap_swdp_sequence(struct dap_context *const ctx, + const uint8_t *const request, + uint8_t *const response) +{ + const struct swdp_api *api = ctx->swdp_dev->api; + const uint8_t *request_data = request + 1; + uint8_t *response_data = response + 1; + uint8_t count = request[0]; + uint8_t num_cycles; + uint32_t num_bytes; + bool input; + + switch (ctx->debug_port) { + case DAP_PORT_SWD: + response[0] = DAP_OK; + break; + case DAP_PORT_JTAG: + default: + LOG_ERR("port unsupported"); + response[0] = DAP_ERROR; + return 1U; + } + + for (size_t i = 0; i < count; ++i) { + input = *request_data & BIT(7); + num_cycles = *request_data & BIT_MASK(7); + num_bytes = (num_cycles + 7) >> 3; /* rounded up to full bytes */ + + if (num_cycles == 0) { + num_cycles = 64; + } + + request_data += 1; + + if (input) { + api->swdp_input_sequence(ctx->swdp_dev, num_cycles, response_data); + response_data += num_bytes; + } else { + api->swdp_output_sequence(ctx->swdp_dev, num_cycles, request_data); + request_data += num_bytes; + } + } + + return response_data - response; +} + /* * Process SWD DAP_TransferBlock command and prepare response. * pyOCD counterpart is _encode_transfer_block_data. @@ -865,6 +911,9 @@ static uint16_t dap_process_cmd(struct dap_context *const ctx, case ID_DAP_SWDP_CONFIGURE: retval = dap_swdp_configure(ctx, request, response); break; + case ID_DAP_SWDP_SEQUENCE: + retval = dap_swdp_sequence(ctx, request, response); + break; case ID_DAP_JTAG_SEQUENCE: LOG_ERR("JTAG sequence unsupported"); retval = 1; diff --git a/subsys/dap/cmsis_dap.h b/subsys/dap/cmsis_dap.h index 787dc822b79ec..d8869e2160a90 100644 --- a/subsys/dap/cmsis_dap.h +++ b/subsys/dap/cmsis_dap.h @@ -22,7 +22,7 @@ #include /* Firmware Version */ -#define DAP_FW_VER "1.10" +#define DAP_FW_VER "2.1.0" /* DAP Command IDs */ #define ID_DAP_INFO 0x00U @@ -42,6 +42,7 @@ #define ID_DAP_SWJ_SEQUENCE 0x12U #define ID_DAP_SWDP_CONFIGURE 0x13U +#define ID_DAP_SWDP_SEQUENCE 0x1DU #define ID_DAP_JTAG_SEQUENCE 0x14U #define ID_DAP_JTAG_CONFIGURE 0x15U From 94f48c7a78ed657f79958ae3ff5e602d617ff910 Mon Sep 17 00:00:00 2001 From: Johann Fischer Date: Fri, 13 Jan 2023 00:41:34 +0100 Subject: [PATCH 2704/2849] samples: debug: add CMSIS DAP sample using USB as interface Add CMSIS DAP sample using USB as interface. Signed-off-by: Maximilian Deubel Signed-off-by: Johann Fischer --- samples/subsys/dap/CMakeLists.txt | 9 + samples/subsys/dap/README.rst | 57 +++ samples/subsys/dap/app.overlay | 17 + .../dap/boards/nrf52840dk_nrf52840.overlay | 19 + samples/subsys/dap/prj.conf | 19 + samples/subsys/dap/sample.yaml | 16 + samples/subsys/dap/src/main.c | 370 ++++++++++++++++++ 7 files changed, 507 insertions(+) create mode 100644 samples/subsys/dap/CMakeLists.txt create mode 100644 samples/subsys/dap/README.rst create mode 100644 samples/subsys/dap/app.overlay create mode 100644 samples/subsys/dap/boards/nrf52840dk_nrf52840.overlay create mode 100644 samples/subsys/dap/prj.conf create mode 100644 samples/subsys/dap/sample.yaml create mode 100644 samples/subsys/dap/src/main.c diff --git a/samples/subsys/dap/CMakeLists.txt b/samples/subsys/dap/CMakeLists.txt new file mode 100644 index 0000000000000..72ea1953b3c18 --- /dev/null +++ b/samples/subsys/dap/CMakeLists.txt @@ -0,0 +1,9 @@ +# Copyright (c) 2023 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(dap) + +FILE(GLOB app_sources src/*.c) +target_sources(app PRIVATE ${app_sources}) diff --git a/samples/subsys/dap/README.rst b/samples/subsys/dap/README.rst new file mode 100644 index 0000000000000..dcecb9440b515 --- /dev/null +++ b/samples/subsys/dap/README.rst @@ -0,0 +1,57 @@ +.. _dap-sample: + +DAP Sample Application +###################### + +Overview +******** + +This sample app demonstrates use of a SWDP interface driver and CMSIS DAP +controller through USB Bulk interface. + +Requirements +************ + +This sample supports multiple hardware configurations: + +The simplest configuration would be to connect `SWDIO` to `dio`, `SWDCLK` to `clk` +and optionally `nRESET` to `reset`. The optional `noe` pin is used to enable the port, +e.g. if the SWD connections are multiplexed. + +Building and Running +******************** + +In order for our debug adapter to be recognized by pyOCD we need to change +Zephyr's VID/PID to IDs known to pyOCD, this is up to the user. +The following commands build and flash DAP sample. + +.. zephyr-app-commands:: + :zephyr-app: samples/subsys/dap + :board: nrf52840dk_nrf52840 + :goals: flash + :compact: + +Connect HIC to the target and try some pyOCD commands, for example: + +.. code-block:: console + + pyocd commander -t nrf52840 + + 0029527 W Board ID FE5D is not recognized [mbed_board] + Connected to NRF52840 [Sleeping]: FE5D244DFE1F33DB + pyocd> read32 0x20004f18 32 + 20004f18: 20001160 2000244c 00000000 0000e407 | ..` .$L........| + 20004f28: ffffffff ffffffff 00000000 aaaaaaaa |................| + pyocd> halt + Successfully halted device + pyocd> reg + general registers: + lr: 0x00009cdd r7: 0x00000000 (0) + pc: 0x000033ca r8: 0x00000000 (0) + r0: 0x00000000 (0) r9: 0x00000000 (0) + r1: 0x20002854 (536881236) r10: 0x00000000 (0) + r2: 0x20000be4 (536873956) r11: 0x00000000 (0) + r3: 0x00000000 (0) r12: 0x00000000 (0) + r4: 0x200017e8 (536877032) sp: 0x20002898 + r5: 0x20001867 (536877159) xpsr: 0x61000000 (1627389952) + r6: 0x00000000 (0) diff --git a/samples/subsys/dap/app.overlay b/samples/subsys/dap/app.overlay new file mode 100644 index 0000000000000..a0ab85fccd6d8 --- /dev/null +++ b/samples/subsys/dap/app.overlay @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + dp0 { + compatible = "zephyr,swdp-gpio"; + status = "okay"; + + clk-gpios = <&arduino_header 10 GPIO_ACTIVE_HIGH>; /* D4 */ + noe-gpios = <&arduino_header 9 GPIO_ACTIVE_HIGH>; /* D3 */ + dio-gpios = <&arduino_header 8 GPIO_PULL_UP>; /* D2 */ + port-write-cycles = <2>; + }; +}; diff --git a/samples/subsys/dap/boards/nrf52840dk_nrf52840.overlay b/samples/subsys/dap/boards/nrf52840dk_nrf52840.overlay new file mode 100644 index 0000000000000..82438d36d9211 --- /dev/null +++ b/samples/subsys/dap/boards/nrf52840dk_nrf52840.overlay @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + dp0 { + compatible = "zephyr,swdp-gpio"; + status = "okay"; + clk-gpios = <&arduino_header 10 GPIO_ACTIVE_HIGH>; /* D4 */ + dio-gpios = <&arduino_header 8 GPIO_PULL_UP>; /* D2 */ + dout-gpios = <&arduino_header 9 GPIO_ACTIVE_HIGH>; /* D3 */ + dnoe-gpios = <&arduino_header 12 GPIO_ACTIVE_HIGH>; /* D6 */ + noe-gpios = <&arduino_header 11 GPIO_ACTIVE_HIGH>; /* D5 */ + reset-gpios = <&arduino_header 13 GPIO_ACTIVE_HIGH>; /* D7 */ + port-write-cycles = <2>; + }; +}; diff --git a/samples/subsys/dap/prj.conf b/samples/subsys/dap/prj.conf new file mode 100644 index 0000000000000..85e26acafa9fc --- /dev/null +++ b/samples/subsys/dap/prj.conf @@ -0,0 +1,19 @@ +CONFIG_STDOUT_CONSOLE=y +CONFIG_USB_DEVICE_STACK=y +CONFIG_USB_DEVICE_BOS=y +CONFIG_SERIAL=y +CONFIG_USB_DEVICE_PRODUCT="Zephyr CMSIS-DAP" +CONFIG_USB_DEVICE_PID=0x0204 +CONFIG_UART_INTERRUPT_DRIVEN=y +CONFIG_UART_LINE_CTRL=y +CONFIG_USB_DEVICE_INITIALIZE_AT_BOOT=n + +CONFIG_LOG=y + +CONFIG_USB_DRIVER_LOG_LEVEL_INF=y +CONFIG_USB_DEVICE_LOG_LEVEL_INF=y +CONFIG_DAP_LOG_LEVEL_INF=y +CONFIG_DP_DRIVER_LOG_LEVEL_INF=y +CONFIG_DAP=y +CONFIG_GPIO=y +CONFIG_NET_BUF=y diff --git a/samples/subsys/dap/sample.yaml b/samples/subsys/dap/sample.yaml new file mode 100644 index 0000000000000..65264fa242943 --- /dev/null +++ b/samples/subsys/dap/sample.yaml @@ -0,0 +1,16 @@ +sample: + name: DAP USB +tests: + sample.dap.bulk: + build_only: true + depends_on: arduino_gpio usb_device + platform_allow: + - nrf52840dk/nrf52840 + - frdm_k64f + tags: dap + sample.dap.bulk.nrf: + build_only: true + depends_on: gpio usb_device + platform_allow: + - nrf52840dk/nrf52840 + tags: dap diff --git a/samples/subsys/dap/src/main.c b/samples/subsys/dap/src/main.c new file mode 100644 index 0000000000000..d680f89a23330 --- /dev/null +++ b/samples/subsys/dap/src/main.c @@ -0,0 +1,370 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +LOG_MODULE_REGISTER(dap_sample, LOG_LEVEL_INF); + +NET_BUF_POOL_FIXED_DEFINE(dapusb_rx_pool, CONFIG_CMSIS_DAP_PACKET_COUNT, + CONFIG_CMSIS_DAP_PACKET_SIZE, 0, NULL); + +static uint8_t rx_buf[CONFIG_CMSIS_DAP_PACKET_SIZE]; +static uint8_t tx_buf[CONFIG_CMSIS_DAP_PACKET_SIZE]; + +static K_FIFO_DEFINE(dap_rx_queue); + +#define DAP_IFACE_STR_DESC "CMSIS-DAP v2" + +struct dap_iface_descriptor { + uint8_t bLength; + uint8_t bDescriptorType; + uint8_t bString[USB_BSTRING_LENGTH(DAP_IFACE_STR_DESC)]; +} __packed; + +USBD_STRING_DESCR_USER_DEFINE(primary) struct dap_iface_descriptor dap_iface_desc = { + .bLength = USB_STRING_DESCRIPTOR_LENGTH(DAP_IFACE_STR_DESC), + .bDescriptorType = USB_DESC_STRING, + .bString = DAP_IFACE_STR_DESC +}; + +#define DAP_USB_EP_IN 0x81 +#define DAP_USB_EP_OUT 0x01 +#define DAP_USB_EP_IN_IDX 0 +#define DAP_USB_EP_OUT_IDX 1 + +#define WEBUSB_VENDOR_CODE 0x21 +#define WINUSB_VENDOR_CODE 0x20 + +/* {CDB3B5AD-293B-4663-AA36-1AAE46463776} */ +#define CMSIS_DAP_V2_DEVICE_INTERFACE_GUID \ + '{', 0x00, 'C', 0x00, 'D', 0x00, 'B', 0x00, '3', 0x00, 'B', 0x00, \ + '5', 0x00, 'A', 0x00, 'D', 0x00, '-', 0x00, '2', 0x00, '9', 0x00, \ + '3', 0x00, 'B', 0x00, '-', 0x00, '4', 0x00, '6', 0x00, '6', 0x00, \ + '3', 0x00, '-', 0x00, 'A', 0x00, 'A', 0x00, '3', 0x00, '6', 0x00, \ + '-', 0x00, '1', 0x00, 'A', 0x00, 'A', 0x00, 'E', 0x00, '4', 0x00, \ + '6', 0x00, '4', 0x00, '6', 0x00, '3', 0x00, '7', 0x00, '7', 0x00, \ + '6', 0x00, '}', 0x00, 0x00, 0x00, 0x00, 0x00 + +#define COMPATIBLE_ID_WINUSB \ + 'W', 'I', 'N', 'U', 'S', 'B', 0x00, 0x00 + +static struct msosv2_descriptor { + struct msosv2_descriptor_set_header header; +#if defined(CONFIG_USB_COMPOSITE_DEVICE) + struct msosv2_function_subset_header subset_header; +#endif + struct msosv2_compatible_id compatible_id; + struct msosv2_guids_property guids_property; +} __packed msosv2_cmsis_dap_desc = { + /* + * Microsoft OS 2.0 descriptor set. This tells Windows what kind + * of device this is and to install the WinUSB driver. + */ + .header = { + .wLength = sizeof(struct msosv2_descriptor_set_header), + .wDescriptorType = MS_OS_20_SET_HEADER_DESCRIPTOR, + .dwWindowsVersion = 0x06030000, + .wTotalLength = sizeof(struct msosv2_descriptor), + }, +#if defined(CONFIG_USB_COMPOSITE_DEVICE) + .subset_header = { + .wLength = sizeof(struct msosv2_function_subset_header), + .wDescriptorType = MS_OS_20_SUBSET_HEADER_FUNCTION, + .wSubsetLength = sizeof(struct msosv2_function_subset_header) + + sizeof(struct msosv2_compatible_id) + + sizeof(struct msosv2_guids_property), + }, +#endif + .compatible_id = { + .wLength = sizeof(struct msosv2_compatible_id), + .wDescriptorType = MS_OS_20_FEATURE_COMPATIBLE_ID, + .CompatibleID = {COMPATIBLE_ID_WINUSB}, + }, + .guids_property = { + .wLength = sizeof(struct msosv2_guids_property), + .wDescriptorType = MS_OS_20_FEATURE_REG_PROPERTY, + .wPropertyDataType = MS_OS_20_PROPERTY_DATA_REG_MULTI_SZ, + .wPropertyNameLength = 42, + .PropertyName = {DEVICE_INTERFACE_GUIDS_PROPERTY_NAME}, + .wPropertyDataLength = 80, + .bPropertyData = {CMSIS_DAP_V2_DEVICE_INTERFACE_GUID}, + }, +}; + +USB_DEVICE_BOS_DESC_DEFINE_CAP struct usb_bos_msosv2_desc { + struct usb_bos_platform_descriptor platform; + struct usb_bos_capability_msos cap; +} __packed bos_cap_msosv2 = { + /* Microsoft OS 2.0 Platform Capability Descriptor */ + .platform = { + .bLength = sizeof(struct usb_bos_platform_descriptor) + + sizeof(struct usb_bos_capability_msos), + .bDescriptorType = USB_DESC_DEVICE_CAPABILITY, + .bDevCapabilityType = USB_BOS_CAPABILITY_PLATFORM, + .bReserved = 0, + .PlatformCapabilityUUID = { + /** + * MS OS 2.0 Platform Capability ID + * D8DD60DF-4589-4CC7-9CD2-659D9E648A9F + */ + 0xDF, 0x60, 0xDD, 0xD8, + 0x89, 0x45, + 0xC7, 0x4C, + 0x9C, 0xD2, + 0x65, 0x9D, 0x9E, 0x64, 0x8A, 0x9F, + }, + }, + .cap = { + /* Windows version (8.1) (0x06030000) */ + .dwWindowsVersion = sys_cpu_to_le32(0x06030000), + .wMSOSDescriptorSetTotalLength = + sys_cpu_to_le16(sizeof(msosv2_cmsis_dap_desc)), + .bMS_VendorCode = WINUSB_VENDOR_CODE, + .bAltEnumCode = 0x00 + }, +}; + +USB_DEVICE_BOS_DESC_DEFINE_CAP struct usb_bos_webusb_desc { + struct usb_bos_platform_descriptor platform; + struct usb_bos_capability_webusb cap; +} __packed bos_cap_webusb = { + /* WebUSB Platform Capability Descriptor: + * https://wicg.github.io/webusb/#webusb-platform-capability-descriptor + */ + .platform = { + .bLength = sizeof(struct usb_bos_platform_descriptor) + + sizeof(struct usb_bos_capability_webusb), + .bDescriptorType = USB_DESC_DEVICE_CAPABILITY, + .bDevCapabilityType = USB_BOS_CAPABILITY_PLATFORM, + .bReserved = 0, + /* WebUSB Platform Capability UUID + * 3408b638-09a9-47a0-8bfd-a0768815b665 + */ + .PlatformCapabilityUUID = { + 0x38, 0xB6, 0x08, 0x34, + 0xA9, 0x09, + 0xA0, 0x47, + 0x8B, 0xFD, + 0xA0, 0x76, 0x88, 0x15, 0xB6, 0x65, + }, + }, + .cap = { + .bcdVersion = sys_cpu_to_le16(0x0100), + .bVendorCode = WEBUSB_VENDOR_CODE, + .iLandingPage = 0x01 + } +}; + +/* URL Descriptor: https://wicg.github.io/webusb/#url-descriptor */ +static const uint8_t webusb_origin_url[] = { + /* Length, DescriptorType, Scheme */ + 24, 0x03, 0x01, + 'w', 'w', 'w', '.', + 'z', 'e', 'p', 'h', 'y', 'r', 'p', 'r', 'o', 'j', 'e', 'c', 't', '.', + 'o', 'r', 'g', '/', +}; + +static int msosv2_vendor_handle_req(struct usb_setup_packet *setup, + int32_t *len, uint8_t **data) +{ + if (usb_reqtype_is_to_device(setup)) { + return -ENOTSUP; + } + + if (setup->bRequest == WEBUSB_VENDOR_CODE && setup->wIndex == 0x02) { + *data = (uint8_t *)(&webusb_origin_url); + *len = sizeof(webusb_origin_url); + + LOG_DBG("Get URL request"); + + return 0; + } + + if (setup->bRequest == WINUSB_VENDOR_CODE && + setup->wIndex == MS_OS_20_DESCRIPTOR_INDEX) { + *data = (uint8_t *)(&msosv2_cmsis_dap_desc); + *len = sizeof(msosv2_cmsis_dap_desc); + + LOG_DBG("Get MS OS Descriptors v2"); + + return 0; + } + + return -ENOTSUP; +} + +USBD_CLASS_DESCR_DEFINE(primary, 0) struct { + struct usb_if_descriptor if0; + struct usb_ep_descriptor if0_out_ep; + struct usb_ep_descriptor if0_in_ep; +} __packed dapusb_desc = { + .if0 = { + .bLength = sizeof(struct usb_if_descriptor), + .bDescriptorType = USB_DESC_INTERFACE, + .bInterfaceNumber = 0, + .bAlternateSetting = 0, + .bNumEndpoints = 2, + .bInterfaceClass = USB_BCC_VENDOR, + .bInterfaceSubClass = 0, + .bInterfaceProtocol = 0, + .iInterface = 0, + }, + .if0_out_ep = { + .bLength = sizeof(struct usb_ep_descriptor), + .bDescriptorType = USB_DESC_ENDPOINT, + .bEndpointAddress = DAP_USB_EP_OUT, + .bmAttributes = USB_DC_EP_BULK, + .wMaxPacketSize = sys_cpu_to_le16(CONFIG_CMSIS_DAP_PACKET_SIZE), + .bInterval = 0, + }, + .if0_in_ep = { + .bLength = sizeof(struct usb_ep_descriptor), + .bDescriptorType = USB_DESC_ENDPOINT, + .bEndpointAddress = DAP_USB_EP_IN, + .bmAttributes = USB_DC_EP_BULK, + .wMaxPacketSize = sys_cpu_to_le16(CONFIG_CMSIS_DAP_PACKET_SIZE), + .bInterval = 0, + }, +}; + +static struct usb_ep_cfg_data dapusb_ep_data[] = { + { + .ep_cb = usb_transfer_ep_callback, + .ep_addr = DAP_USB_EP_OUT + }, + { + .ep_cb = usb_transfer_ep_callback, + .ep_addr = DAP_USB_EP_IN + } +}; + +static void iface_string_desc_init(struct usb_cfg_data *bulk_cfg) +{ + struct usb_if_descriptor *bulk_if = bulk_cfg->interface_descriptor; + + bulk_if->iInterface = usb_get_str_descriptor_idx(&dap_iface_desc); +} + +static void dapusb_read_cb(uint8_t ep, int size, void *priv) +{ + struct usb_cfg_data *cfg = priv; + struct net_buf *buf; + + LOG_DBG("cfg %p ep %x size %u", cfg, ep, size); + + if (size <= 0) { + goto read_cb_done; + } + + buf = net_buf_alloc(&dapusb_rx_pool, K_FOREVER); + net_buf_add_mem(buf, rx_buf, MIN(size, CONFIG_CMSIS_DAP_PACKET_SIZE)); + k_fifo_put(&dap_rx_queue, buf); + +read_cb_done: + usb_transfer(ep, rx_buf, sizeof(rx_buf), USB_TRANS_READ, dapusb_read_cb, cfg); +} + +static void dapusb_dev_status_cb(struct usb_cfg_data *cfg, + enum usb_dc_status_code status, + const uint8_t *param) +{ + ARG_UNUSED(param); + + if (status == USB_DC_CONFIGURED) { + dapusb_read_cb(cfg->endpoint[DAP_USB_EP_IN_IDX].ep_addr, 0, cfg); + } +} + +static void dapusb_interface_config(struct usb_desc_header *head, + uint8_t bInterfaceNumber) +{ + ARG_UNUSED(head); + + dapusb_desc.if0.bInterfaceNumber = bInterfaceNumber; +#if defined(CONFIG_USB_COMPOSITE_DEVICE) + msosv2_cmsis_dap_desc.subset_header.bFirstInterface = bInterfaceNumber; +#endif +} + +USBD_DEFINE_CFG_DATA(dapusb_config) = { + .usb_device_description = NULL, + .interface_config = dapusb_interface_config, + .interface_descriptor = &dapusb_desc.if0, + .cb_usb_status = dapusb_dev_status_cb, + .interface = { + .class_handler = NULL, + .custom_handler = NULL, + .vendor_handler = msosv2_vendor_handle_req, + }, + .num_endpoints = ARRAY_SIZE(dapusb_ep_data), + .endpoint = dapusb_ep_data +}; + +static int dap_usb_process(void) +{ + uint8_t ep = dapusb_config.endpoint[DAP_USB_EP_OUT_IDX].ep_addr; + struct net_buf *buf; + size_t len; + int err; + + buf = k_fifo_get(&dap_rx_queue, K_FOREVER); + + len = dap_execute_cmd(buf->data, tx_buf); + LOG_DBG("response length %u, starting with [0x%02X, 0x%02X]", + len, tx_buf[0], tx_buf[1]); + net_buf_unref(buf); + + err = usb_transfer_sync(ep, tx_buf, len, USB_TRANS_WRITE | USB_TRANS_NO_ZLP); + if (err < 0 || err != len) { + LOG_ERR("usb_transfer_sync failed, %d", err); + return -EIO; + } + + return 0; +} + +int main(void) +{ + const struct device *const swd_dev = DEVICE_DT_GET_ONE(zephyr_swdp_gpio); + int ret; + + if (!device_is_ready(swd_dev)) { + LOG_ERR("SWD device is not ready"); + return -ENODEV; + } + + ret = dap_setup(swd_dev); + if (ret) { + LOG_ERR("Failed to initialize DAP controller, %d", ret); + return ret; + } + + /* Add MS OS 2.0 BOS descriptor to BOS structure */ + usb_bos_register_cap((void *)&bos_cap_msosv2); + /* Point interface index to string descriptor */ + iface_string_desc_init(&dapusb_config); + + ret = usb_enable(NULL); + if (ret != 0) { + LOG_ERR("Failed to enable USB"); + return 0; + } + + while (!dap_usb_process()) { + } + + return usb_disable(); +} From 05a45a19e35a793afa7e68b65822d4cddcc139a9 Mon Sep 17 00:00:00 2001 From: Maximilian Deubel Date: Fri, 24 May 2024 15:43:16 +0200 Subject: [PATCH 2705/2849] dap: fix timeout handling Use k_timepoint_t for timeout handling in the swj_pins function. Signed-off-by: Maximilian Deubel --- subsys/dap/cmsis_dap.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/subsys/dap/cmsis_dap.c b/subsys/dap/cmsis_dap.c index 5bf3f01976ff5..4148346e15f5f 100644 --- a/subsys/dap/cmsis_dap.c +++ b/subsys/dap/cmsis_dap.c @@ -285,7 +285,7 @@ static uint16_t dap_swj_pins(struct dap_context *const ctx, uint8_t value = request[0]; uint8_t select = request[1]; uint32_t wait = sys_get_le32(&request[2]); - int64_t timeout_ticks; + k_timepoint_t end = sys_timepoint_calc(K_USEC(wait)); uint8_t state; if (!atomic_test_bit(&ctx->state, DAP_STATE_CONNECTED)) { @@ -299,8 +299,6 @@ static uint16_t dap_swj_pins(struct dap_context *const ctx, api->swdp_set_pins(ctx->swdp_dev, select, value); } - timeout_ticks = k_uptime_ticks() + (CONFIG_SYS_CLOCK_TICKS_PER_SEC / 1000000 * wait); - do { api->swdp_get_pins(ctx->swdp_dev, &state); LOG_INF("select 0x%02x, value 0x%02x, wait %u, state 0x%02x", @@ -309,7 +307,7 @@ static uint16_t dap_swj_pins(struct dap_context *const ctx, LOG_DBG("swdp_get_pins succeeded before timeout"); break; } - } while (k_uptime_ticks() - timeout_ticks > 0); + } while (!sys_timepoint_expired(end)); response[0] = state; From f1b6073a278d6f7ed57fc28f3caf04062443fb24 Mon Sep 17 00:00:00 2001 From: Maximilian Deubel Date: Fri, 24 May 2024 16:43:22 +0200 Subject: [PATCH 2706/2849] driver: swdp_bitbang: hardcode request lut Hardcode the lookup table for SWDP requests. This is an optimization to save some space. Documentation was added to understand the values. Signed-off-by: Maximilian Deubel --- drivers/dp/swdp_bitbang.c | 39 ++++++++++++++------------------------- 1 file changed, 14 insertions(+), 25 deletions(-) diff --git a/drivers/dp/swdp_bitbang.c b/drivers/dp/swdp_bitbang.c index f3c5fcc50d2d6..ba46c629604aa 100644 --- a/drivers/dp/swdp_bitbang.c +++ b/drivers/dp/swdp_bitbang.c @@ -58,30 +58,20 @@ struct sw_cfg_data { bool fast_clock; }; -static uint8_t sw_request_lut[16] = {0U}; - -static void mk_sw_request_lut(void) -{ - uint32_t parity = 0U; - - for (int request = 0; request < sizeof(sw_request_lut); request++) { - parity = request; - parity ^= parity >> 2; - parity ^= parity >> 1; - - /* - * Move A[3:3], RnW, APnDP bits to their position, - * add start bit, stop bit(6), and park bit. - */ - sw_request_lut[request] = BIT(7) | (request << 1) | BIT(0); - /* Add parity bit */ - if (parity & 0x01U) { - sw_request_lut[request] |= BIT(5); - } - } - - LOG_HEXDUMP_DBG(sw_request_lut, sizeof(sw_request_lut), "request lut"); -} +/* + * Move A[2:3], RnW, APnDP bits to their position, + * add start bit, stop bit(6), park bit and parity bit. + * For example, reading IDCODE would be APnDP=0, RnW=1, A2=0, A3=0. + * The request would be 0xa5, which is 10100101 in binary. + * + * For more information, see: + * - CMSIS-DAP Command Specification, DAP_Transfer + * - ARM Debug Interface v5 Architecture Specification + */ +const static uint8_t sw_request_lut[16] = { + 0x81, 0xa3, 0xa5, 0x87, 0xa9, 0x8b, 0x8d, 0xaf, + 0xb1, 0x93, 0x95, 0xb7, 0x99, 0xbb, 0xbd, 0x9f +}; static ALWAYS_INLINE uint32_t sw_get32bit_parity(uint32_t data) { @@ -678,7 +668,6 @@ static int sw_gpio_init(const struct device *dev) sw_data->fast_clock = false; sw_data->clock_delay = CLOCK_DELAY(SWDP_DEFAULT_SWCLK_FREQUENCY, config->port_write_cycles); - mk_sw_request_lut(); return 0; } From 96112ade749f6d65b5d5f051e253c98c354e9679 Mon Sep 17 00:00:00 2001 From: Maximilian Deubel Date: Fri, 24 May 2024 16:20:46 +0200 Subject: [PATCH 2707/2849] drivers: swdp: document API This patch adds documentation for the SWDP API. Signed-off-by: Maximilian Deubel Signed-off-by: Johann Fischer --- include/zephyr/drivers/swdp.h | 84 ++++++++++++++++++++++++++++------- 1 file changed, 69 insertions(+), 15 deletions(-) diff --git a/include/zephyr/drivers/swdp.h b/include/zephyr/drivers/swdp.h index c1f06e521510a..d742280e883f9 100644 --- a/include/zephyr/drivers/swdp.h +++ b/include/zephyr/drivers/swdp.h @@ -42,19 +42,39 @@ extern "C" { * This is the mandatory API any Serial Wire driver needs to expose. */ struct swdp_api { - /* Generate SWJ Sequence according to sequence bit count and bit data */ + /** + * @brief Write count bits to SWDIO from data LSB first + * + * @param dev SWDP device + * @param count Number of bits to write + * @param data Bits to write + * @return 0 on success, or error code + */ int (*swdp_output_sequence)(const struct device *dev, uint32_t count, const uint8_t *data); - /* Read count bits from SWDIO into data LSB first */ + /** + * @brief Read count bits from SWDIO into data LSB first + * + * @param dev SWDP device + * @param count Number of bits to read + * @param data Buffer to store bits read + * @return 0 on success, or error code + */ int (*swdp_input_sequence)(const struct device *dev, uint32_t count, uint8_t *data); - /* - * Perform SWDP transfer based on host request value and store - * acknowledge response bits ACK[0:2]. + /** + * @brief Perform SWDP transfer and store response + * + * @param dev SWDP device + * @param request SWDP request bits + * @param data Data to be transferred with request + * @param idle_cycles Idle cycles between request and response + * @param response Buffer to store response (ACK/WAIT/FAULT) + * @return 0 on success, or error code */ int (*swdp_transfer)(const struct device *dev, uint8_t request, @@ -62,31 +82,65 @@ struct swdp_api { uint8_t idle_cycles, uint8_t *response); - /* Set SWCLK, SWDPIO, and nRESET pins state */ + /** + * @brief Set SWCLK, SWDPIO, and nRESET pins state + * @note The bit positions are defined by the SWDP_*_PIN macros. + * + * @param dev SWDP device + * @param pins Bitmask of pins to set + * @param value Value to set pins to + * @return 0 on success, or error code + */ int (*swdp_set_pins)(const struct device *dev, uint8_t pins, uint8_t value); - /* Get SWCLK, SWDPIO, and nRESET pins state */ + /** + * @brief Get SWCLK, SWDPIO, and nRESET pins state + * @note The bit positions are defined by the SWDP_*_PIN macros. + * + * @param dev SWDP device + * @param state Place to store pins state + * @return 0 on success, or error code + */ int (*swdp_get_pins)(const struct device *dev, uint8_t *state); - /* Set SWCLK frequency */ + /** + * @brief Set SWDP clock frequency + * + * @param dev SWDP device + * @param clock Clock frequency in Hz + * @return 0 on success, or error code + */ int (*swdp_set_clock)(const struct device *dev, uint32_t clock); - /* - * Configure interface, line turnaround and whether data phase is - * forced after WAIN and FAULT response. + /** + * @brief Configure SWDP interface + * + * @param dev SWDP device + * @param turnaround Line turnaround cycles + * @param data_phase Always generate Data Phase (also on WAIT/FAULT) + * @return 0 on success, or error code */ int (*swdp_configure)(const struct device *dev, uint8_t turnaround, bool data_phase); - /* - * Enable interface, set SWDPIO to output mode - * and set SWCLK and nRESET to default high level. + /** + * @brief Enable interface, set pins to default state + * + * @note SWDPIO is set to output mode, SWCLK and nRESET are set to high level. + * + * @param dev SWDP device + * @return 0 on success, or error code */ int (*swdp_port_on)(const struct device *dev); - /* Disables interface, set SWCLK, SWDPIO, nRESET to High-Z mode. */ + /** + * @brief Disable interface, set pins to High-Z mode + * + * @param dev SWDP device + * @return 0 on success, or error code + */ int (*swdp_port_off)(const struct device *dev); }; From bb66d1188c1a629e910b4b7dcf0ec421a00f7958 Mon Sep 17 00:00:00 2001 From: Yong Cong Sin Date: Fri, 14 Jun 2024 11:47:35 +0800 Subject: [PATCH 2708/2849] arch: riscv: stacktrace: conditionally check stack_info Check if an address is in the thread stack only when `CONFIG_THREAD_STACK_INFO` is enabled, since otherwise the `stack_info` will not be available. This fixes compilation error when `CONFIG_THREAD_STACK_INFO` is explicitly disabled. Signed-off-by: Yong Cong Sin --- arch/riscv/core/stacktrace.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/arch/riscv/core/stacktrace.c b/arch/riscv/core/stacktrace.c index 7a684a9bae9e7..563d6cad14454 100644 --- a/arch/riscv/core/stacktrace.c +++ b/arch/riscv/core/stacktrace.c @@ -36,12 +36,19 @@ static inline bool in_irq_stack_bound(uintptr_t addr, uint8_t cpu_id) static inline bool in_kernel_thread_stack_bound(uintptr_t addr, const struct k_thread *const thread) { +#ifdef CONFIG_THREAD_STACK_INFO uintptr_t start, end; start = thread->stack_info.start; end = Z_STACK_PTR_ALIGN(thread->stack_info.start + thread->stack_info.size); return (addr >= start) && (addr < end); +#else + ARG_UNUSED(addr); + ARG_UNUSED(thread); + /* Return false as we can't check if the addr is in the thread stack without stack info */ + return false; +#endif } #ifdef CONFIG_USERSPACE From c2950bec73655dc83f5445bb9c2f89fbf7c09155 Mon Sep 17 00:00:00 2001 From: Alberto Escolar Piedras Date: Fri, 14 Jun 2024 09:14:14 +0200 Subject: [PATCH 2709/2849] ci: bsim tests: Fix for missing result xml files Do not fail during results merge if twister or the bsim workflows did not run (or produce an xml). Depending on what has changed in a PR and therefore what tests are run this can happen. Signed-off-by: Alberto Escolar Piedras --- .github/workflows/bsim-tests.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/bsim-tests.yaml b/.github/workflows/bsim-tests.yaml index 6149a51f5996b..271cc1dbfe7ff 100644 --- a/.github/workflows/bsim-tests.yaml +++ b/.github/workflows/bsim-tests.yaml @@ -163,7 +163,7 @@ jobs: - name: Merge Test Results run: | pip3 install junitparser junit2html - junitparser merge ./bsim_*/*bsim_results.*.xml ./twister-out/twister.xml junit.xml + junitparser merge --glob "./bsim_*/*bsim_results.*.xml" "./twister-out/twister.xml" junit.xml junit2html junit.xml junit.html - name: Upload Unit Test Results in HTML From 9ae5352372dd9965805980e0c712612f21ed2229 Mon Sep 17 00:00:00 2001 From: Alberto Escolar Piedras Date: Fri, 14 Jun 2024 10:02:38 +0200 Subject: [PATCH 2710/2849] tests/bsim/run_parallel.sh: Do not attempt to run parallel with no tests If there is no tests in the test list, do not attempt to run parallel. This avoids parallel trying to attempt to read the input from the terminal in that case. Signed-off-by: Alberto Escolar Piedras --- tests/bsim/run_parallel.sh | 42 ++++++++++++++++++++------------------ 1 file changed, 22 insertions(+), 20 deletions(-) diff --git a/tests/bsim/run_parallel.sh b/tests/bsim/run_parallel.sh index 0faf0e308feb5..01eb4bd6aa529 100755 --- a/tests/bsim/run_parallel.sh +++ b/tests/bsim/run_parallel.sh @@ -74,27 +74,29 @@ export CLEAN_XML="sed -E -e 's/&/\&/g' -e 's//\>/g' \ echo -n "" > $tmp_res_file if [ `command -v parallel` ]; then - parallel ' - echo "" - start=$(date +%s%N) - {} $@ &> {#}.log ; result=$? - dur=$(($(date +%s%N) - $start)) - dur_s=$(awk -vdur=$dur "BEGIN { printf(\"%0.3f\", dur/1000000000)}") - if [ $result -ne 0 ]; then - (>&2 echo -e "\e[91m{} FAILED\e[39m ($dur_s s)") - (>&2 cat {#}.log) - echo "" - cat {#}.log | eval $CLEAN_XML - echo "" - rm {#}.log - echo "" - exit 1 - else - (>&2 echo -e "{} PASSED ($dur_s s)") - rm {#}.log - echo "" + if [ ${n_cases} -gt 0 ]; then + parallel ' + echo "" + start=$(date +%s%N) + {} $@ &> {#}.log ; result=$? + dur=$(($(date +%s%N) - $start)) + dur_s=$(awk -vdur=$dur "BEGIN { printf(\"%0.3f\", dur/1000000000)}") + if [ $result -ne 0 ]; then + (>&2 echo -e "\e[91m{} FAILED\e[39m ($dur_s s)") + (>&2 cat {#}.log) + echo "" + cat {#}.log | eval $CLEAN_XML + echo "" + rm {#}.log + echo "" + exit 1 + else + (>&2 echo -e "{} PASSED ($dur_s s)") + rm {#}.log + echo "" + fi + ' ::: $all_cases >> $tmp_res_file ; err=$? fi - ' ::: $all_cases >> $tmp_res_file ; err=$? else #fallback in case parallel is not installed for case in $all_cases; do echo "" >> $tmp_res_file From 811387600a66bf78f20609e4bd548700b28a9566 Mon Sep 17 00:00:00 2001 From: Andries Kruithof Date: Thu, 29 Feb 2024 09:42:25 +0100 Subject: [PATCH 2711/2849] Bluetooth: Audio: CAP: babblesim test for broadcast reception start Add a babblesim test for the broadcast reception start procedure from the CAP commander Signed-off-by: Andries Kruithof --- .../audio/src/bap_broadcast_sink_test.c | 24 +- .../bluetooth/audio/src/cap_acceptor_test.c | 222 +++++++- .../bluetooth/audio/src/cap_commander_test.c | 495 +++++++++++++++++- .../test_scripts/cap_broadcast_reception.sh | 35 ++ 4 files changed, 758 insertions(+), 18 deletions(-) create mode 100755 tests/bsim/bluetooth/audio/test_scripts/cap_broadcast_reception.sh 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 143375d6f9ce3..cf9484740647c 100644 --- a/tests/bsim/bluetooth/audio/src/bap_broadcast_sink_test.c +++ b/tests/bsim/bluetooth/audio/src/bap_broadcast_sink_test.c @@ -36,12 +36,12 @@ #if defined(CONFIG_BT_BAP_BROADCAST_SINK) extern enum bst_result_t bst_result; -CREATE_FLAG(broadcaster_found); +CREATE_FLAG(flag_broadcaster_found); CREATE_FLAG(flag_base_received); CREATE_FLAG(flag_base_metadata_updated); -CREATE_FLAG(pa_synced); +CREATE_FLAG(flag_pa_synced); CREATE_FLAG(flag_syncable); -CREATE_FLAG(pa_sync_lost); +CREATE_FLAG(flag_pa_sync_lost); CREATE_FLAG(flag_received); CREATE_FLAG(flag_pa_request); CREATE_FLAG(flag_bis_sync_requested); @@ -265,7 +265,7 @@ static bool scan_check_and_sync_broadcast(struct bt_data *data, void *user_data) struct bt_uuid_16 adv_uuid; uint32_t broadcast_id; - if (TEST_FLAG(broadcaster_found)) { + if (TEST_FLAG(flag_broadcaster_found)) { /* no-op*/ return false; } @@ -293,7 +293,7 @@ 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); - SET_FLAG(broadcaster_found); + SET_FLAG(flag_broadcaster_found); /* Store info for PA sync parameters */ memcpy(&broadcaster_info, info, sizeof(broadcaster_info)); @@ -322,7 +322,7 @@ static void bap_pa_sync_synced_cb(struct bt_le_per_adv_sync *sync, printk("PA sync %p synced for broadcast sink with broadcast ID 0x%06X\n", sync, broadcaster_broadcast_id); - SET_FLAG(pa_synced); + SET_FLAG(flag_pa_synced); } } @@ -333,7 +333,7 @@ static void bap_pa_sync_terminated_cb(struct bt_le_per_adv_sync *sync, printk("PA sync %p lost with reason %u\n", sync, info->reason); pa_sync = NULL; - SET_FLAG(pa_sync_lost); + SET_FLAG(flag_pa_sync_lost); } } @@ -640,9 +640,9 @@ static int init(void) bt_le_per_adv_sync_cb_register(&bap_pa_sync_cb); bt_le_scan_cb_register(&bap_scan_cb); - UNSET_FLAG(broadcaster_found); + UNSET_FLAG(flag_broadcaster_found); UNSET_FLAG(flag_base_received); - UNSET_FLAG(pa_synced); + UNSET_FLAG(flag_pa_synced); for (size_t i = 0U; i < ARRAY_SIZE(streams); i++) { streams[i] = bap_stream_from_audio_test_stream(&broadcast_sink_streams[i]); @@ -710,7 +710,7 @@ static void test_scan_and_pa_sync(void) return; } - WAIT_FOR_FLAG(broadcaster_found); + WAIT_FOR_FLAG(flag_broadcaster_found); printk("Broadcast source found, stopping scan\n"); err = bt_le_scan_stop(); @@ -728,7 +728,7 @@ static void test_scan_and_pa_sync(void) } printk("Waiting for PA sync\n"); - WAIT_FOR_FLAG(pa_synced); + WAIT_FOR_FLAG(flag_pa_synced); } static void test_broadcast_sink_create(void) @@ -976,7 +976,7 @@ static void test_main(void) * either way will work. */ printk("Waiting for PA disconnected\n"); - WAIT_FOR_FLAG(pa_sync_lost); + WAIT_FOR_FLAG(flag_pa_sync_lost); printk("Waiting for streams to be stopped\n"); for (size_t i = 0U; i < ARRAY_SIZE(streams); i++) { diff --git a/tests/bsim/bluetooth/audio/src/cap_acceptor_test.c b/tests/bsim/bluetooth/audio/src/cap_acceptor_test.c index 3b36c0646f3d1..4e7485b97d0da 100644 --- a/tests/bsim/bluetooth/audio/src/cap_acceptor_test.c +++ b/tests/bsim/bluetooth/audio/src/cap_acceptor_test.c @@ -46,11 +46,15 @@ extern enum bst_result_t bst_result; #define SOURCE_CONTEXT (BT_AUDIO_CONTEXT_TYPE_UNSPECIFIED | BT_AUDIO_CONTEXT_TYPE_NOTIFICATIONS) CREATE_FLAG(flag_broadcaster_found); +CREATE_FLAG(flag_broadcast_code); CREATE_FLAG(flag_base_received); CREATE_FLAG(flag_pa_synced); CREATE_FLAG(flag_syncable); CREATE_FLAG(flag_received); CREATE_FLAG(flag_pa_sync_lost); +CREATE_FLAG(flag_pa_request); +CREATE_FLAG(flag_bis_sync_requested); +CREATE_FLAG(flag_base_metadata_updated); static struct bt_bap_broadcast_sink *g_broadcast_sink; static struct bt_le_scan_recv_info broadcaster_info; @@ -58,6 +62,9 @@ static bt_addr_le_t broadcaster_addr; static struct bt_le_per_adv_sync *pa_sync; static uint32_t broadcaster_broadcast_id; static struct audio_test_stream broadcast_sink_streams[CONFIG_BT_BAP_BROADCAST_SNK_STREAM_COUNT]; +static struct bt_le_ext_adv *ext_adv; +static uint32_t requested_bis_sync; +static const struct bt_bap_scan_delegator_recv_state *req_recv_state; static const struct bt_audio_codec_cap codec_cap = BT_AUDIO_CODEC_CAP_LC3( BT_AUDIO_CODEC_CAP_FREQ_ANY, BT_AUDIO_CODEC_CAP_DURATION_ANY, @@ -110,6 +117,8 @@ static bool subgroup_data_func_cb(struct bt_data *data, void *user_data) static bool valid_subgroup_metadata_cb(const struct bt_bap_base_subgroup *subgroup, void *user_data) { + static uint8_t metadata[CONFIG_BT_AUDIO_CODEC_CFG_MAX_METADATA_SIZE]; + static size_t metadata_size; bool stream_context_found = false; uint8_t *meta; int ret; @@ -120,6 +129,14 @@ static bool valid_subgroup_metadata_cb(const struct bt_bap_base_subgroup *subgro return false; } + if (TEST_FLAG(flag_base_received) && + ((size_t)ret != metadata_size || memcmp(meta, metadata, metadata_size) != 0)) { + printk("Metadata updated\n"); + SET_FLAG(flag_base_metadata_updated); + } + + metadata_size = (size_t)ret; + ret = bt_audio_data_parse(meta, (size_t)ret, subgroup_data_func_cb, &stream_context_found); if (ret != 0 && ret != -ECANCELED) { return false; @@ -139,10 +156,6 @@ static void base_recv_cb(struct bt_bap_broadcast_sink *sink, const struct bt_bap uint32_t base_bis_index_bitfield = 0U; int ret; - if (TEST_FLAG(flag_base_received)) { - return; - } - ret = bt_bap_base_get_subgroup_count(base); if (ret < 0) { FAIL("Failed to get subgroup count: %d\n", ret); @@ -286,7 +299,7 @@ static void recv_cb(struct bt_bap_stream *stream, const struct bt_iso_recv_info { struct audio_test_stream *test_stream = audio_test_stream_from_bap_stream(stream); - if ((test_stream->rx_cnt % 100U) == 0U) { + if ((test_stream->rx_cnt % 50U) == 0U) { printk("[%zu]: Incoming audio on stream %p len %u and ts %u\n", test_stream->rx_cnt, stream, buf->len, info->ts); } @@ -359,6 +372,77 @@ static struct bt_bap_stream_ops unicast_stream_ops = { .enabled = unicast_stream_enabled_cb, }; +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) +{ + if (recv_state->pa_sync_state == BT_BAP_PA_STATE_SYNCED || + recv_state->pa_sync_state == BT_BAP_PA_STATE_INFO_REQ) { + /* Already syncing */ + /* TODO: Terminate existing sync and then sync to new?*/ + return -EALREADY; + } + + printk("Sync request\n"); + req_recv_state = recv_state; + + bt_addr_le_copy(&broadcaster_addr, &req_recv_state->addr); + broadcaster_info.sid = req_recv_state->adv_sid; + broadcaster_info.interval = pa_interval; + + SET_FLAG(flag_pa_request); + + return 0; +} + +static int pa_sync_term_req_cb(struct bt_conn *conn, + const struct bt_bap_scan_delegator_recv_state *recv_state) +{ + if (pa_sync == NULL || recv_state->pa_sync_state == BT_BAP_PA_STATE_NOT_SYNCED) { + return -EALREADY; + } + + req_recv_state = recv_state; + + UNSET_FLAG(flag_pa_request); + + return 0; +} + +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]) +{ + /* We only care about a single subgroup in this test */ + requested_bis_sync = bis_sync_req[0]; + broadcaster_broadcast_id = recv_state->broadcast_id; + if (bis_sync_req[0] != 0) { + SET_FLAG(flag_bis_sync_requested); + } else { + UNSET_FLAG(flag_bis_sync_requested); + } + + return 0; +} + +static void broadcast_code_cb(struct bt_conn *conn, + const struct bt_bap_scan_delegator_recv_state *recv_state, + const uint8_t broadcast_code[BT_AUDIO_BROADCAST_CODE_SIZE]) +{ + printk("Broadcast code received for %p\n", recv_state); + + req_recv_state = recv_state; + + SET_FLAG(flag_broadcast_code); +} + +static struct bt_bap_scan_delegator_cb scan_delegator_cbs = { + .pa_sync_req = pa_sync_req_cb, + .pa_sync_term_req = pa_sync_term_req_cb, + .bis_sync_req = bis_sync_req_cb, + .broadcast_code = broadcast_code_cb, +}; + /* TODO: Expand with CAP service data */ static const struct bt_data cap_acceptor_ad[] = { BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)), @@ -558,6 +642,35 @@ static int set_supported_contexts(void) return 0; } +void test_start_adv(void) +{ + int err; + + /* Create a connectable non-scannable advertising set */ + err = bt_le_ext_adv_create(BT_LE_ADV_CONN_ONE_TIME, NULL, &ext_adv); + if (err != 0) { + FAIL("Failed to create advertising set (err %d)\n", err); + + return; + } + + /* Add cap acceptor advertising data */ + err = bt_le_ext_adv_set_data(ext_adv, cap_acceptor_ad, ARRAY_SIZE(cap_acceptor_ad), NULL, + 0); + if (err != 0) { + FAIL("Failed to set advertising data (err %d)\n", err); + + return; + } + + err = bt_le_ext_adv_start(ext_adv, BT_LE_EXT_ADV_START_DEFAULT); + if (err != 0) { + FAIL("Failed to start advertising set (err %d)\n", err); + + return; + } +} + static void set_available_contexts(void) { int err; @@ -644,6 +757,7 @@ static void init(void) FAIL("Advertising failed to start (err %d)\n", err); return; } + test_start_adv(); } if (IS_ENABLED(CONFIG_BT_BAP_BROADCAST_SINK)) { @@ -662,10 +776,15 @@ static void init(void) bt_bap_broadcast_sink_register_cb(&broadcast_sink_cbs); bt_le_per_adv_sync_cb_register(&bap_pa_sync_cb); bt_le_scan_cb_register(&bap_scan_cb); + bt_bap_scan_delegator_register_cb(&scan_delegator_cbs); UNSET_FLAG(flag_broadcaster_found); + UNSET_FLAG(flag_broadcast_code); UNSET_FLAG(flag_base_received); UNSET_FLAG(flag_pa_synced); + UNSET_FLAG(flag_pa_request); + UNSET_FLAG(flag_received); + UNSET_FLAG(flag_base_metadata_updated); for (size_t i = 0U; i < ARRAY_SIZE(broadcast_sink_streams); i++) { bt_cap_stream_ops_register( @@ -899,6 +1018,93 @@ static void test_cap_acceptor_broadcast(void) PASS("CAP acceptor broadcast passed\n"); } +static void test_cap_acceptor_broadcast_reception(void) +{ + static struct bt_bap_stream *bap_streams[ARRAY_SIZE(broadcast_sink_streams)]; + size_t stream_count; + int err; + + init(); + + WAIT_FOR_FLAG(flag_pa_request); + + err = pa_sync_create(); + if (err != 0) { + FAIL("Could not create Broadcast PA sync: %d\n", err); + return; + } + + printk("Waiting for PA sync\n"); + WAIT_FOR_FLAG(flag_pa_synced); + + err = bt_bap_broadcast_sink_create(pa_sync, broadcaster_broadcast_id, &g_broadcast_sink); + if (err != 0) { + FAIL("Unable to create the sink: %d\n", err); + return; + } + + if (req_recv_state->num_subgroups == 0) { + FAIL("Number of subgroups is 0"); + return; + } + + printk("Broadcast source PA synced, waiting for BASE\n"); + WAIT_FOR_FLAG(flag_base_received); + printk("BASE received\n"); + + WAIT_FOR_FLAG(flag_syncable); + + for (size_t i = 0U; i < ARRAY_SIZE(broadcast_sink_streams); i++) { + bap_streams[i] = bap_stream_from_audio_test_stream(&broadcast_sink_streams[i]); + } + + printk("Syncing the sink\n"); + stream_count = 0; + for (int i = 1; i < BT_ISO_MAX_GROUP_ISO_COUNT; i++) { + if ((bis_index_bitfield & BIT(i)) != 0) { + stream_count++; + } + } + + err = bt_bap_broadcast_sink_sync(g_broadcast_sink, bis_index_bitfield, bap_streams, NULL); + if (err != 0) { + FAIL("Unable to sync the sink: %d\n", err); + return; + } + + /* Wait for all to be started */ + printk("Waiting for %zu streams to be started\n", stream_count); + for (size_t i = 0U; i < stream_count; i++) { + k_sem_take(&sem_broadcast_started, K_FOREVER); + } + + printk("Waiting for data\n"); + WAIT_FOR_FLAG(flag_received); + + backchannel_sync_send_all(); /* let others know we have received some data */ + + printk("Waiting for meta update\n"); + WAIT_FOR_FLAG(flag_base_metadata_updated); + + backchannel_sync_send_all(); /* let others know we have received a metadata update */ + + backchannel_sync_send_all(); /* let broadcaster know we can stop the source */ + + /* The order of PA sync lost and BIG Sync lost is irrelevant + * and depend on timeout parameters. We just wait for PA first, but + * either way will work. + */ + printk("Waiting for PA disconnected\n"); + WAIT_FOR_FLAG(flag_pa_sync_lost); + + printk("Waiting for %zu streams to be stopped\n", stream_count); + for (size_t i = 0U; i < stream_count; i++) { + k_sem_take(&sem_broadcast_stopped, K_FOREVER); + } + + PASS("CAP acceptor broadcast reception passed\n"); +} + static void test_cap_acceptor_capture_and_render(void) { init(); @@ -927,6 +1133,12 @@ static const struct bst_test_instance test_cap_acceptor[] = { .test_tick_f = test_tick, .test_main_f = test_cap_acceptor_broadcast, }, + { + .test_id = "cap_acceptor_broadcast_reception", + .test_pre_init_f = test_init, + .test_tick_f = test_tick, + .test_main_f = test_cap_acceptor_broadcast_reception, + }, { .test_id = "cap_acceptor_capture_and_render", .test_pre_init_f = test_init, diff --git a/tests/bsim/bluetooth/audio/src/cap_commander_test.c b/tests/bsim/bluetooth/audio/src/cap_commander_test.c index a196db2f0b91f..0d69b6ba69196 100644 --- a/tests/bsim/bluetooth/audio/src/cap_commander_test.c +++ b/tests/bsim/bluetooth/audio/src/cap_commander_test.c @@ -39,10 +39,20 @@ extern enum bst_result_t bst_result; static struct bt_conn *connected_conns[CONFIG_BT_MAX_CONN]; static volatile size_t connected_conn_cnt; +static struct bt_le_scan_recv_info broadcaster_info; +static bt_addr_le_t broadcaster_addr; +static struct bt_le_per_adv_sync *g_pa_sync; +static uint32_t broadcaster_broadcast_id; + +static uint8_t received_base[UINT8_MAX]; +static uint8_t received_base_size; + 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; +static struct k_sem sem_bass_discovered; + CREATE_FLAG(flag_mtu_exchanged); CREATE_FLAG(flag_volume_changed); CREATE_FLAG(flag_volume_mute_changed); @@ -50,6 +60,14 @@ CREATE_FLAG(flag_volume_offset_changed); CREATE_FLAG(flag_microphone_mute_changed); CREATE_FLAG(flag_microphone_gain_changed); +CREATE_FLAG(flag_broadcast_reception_start); +CREATE_FLAG(flag_broadcaster_found); +CREATE_FLAG(flag_base_received); +CREATE_FLAG(flag_recv_state_updated_with_bis_sync); +CREATE_FLAG(flag_pa_synced); +CREATE_FLAG(flag_pa_sync_lost); +CREATE_FLAG(flag_syncable); + 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) @@ -133,6 +151,18 @@ static void cap_microphone_gain_changed_cb(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) +static void cap_broadcast_reception_start_cb(struct bt_conn *conn, int err) +{ + if (err != 0) { + FAIL("Failed to perform broadcast reception start for conn %p: %d\n", conn, err); + return; + } + + SET_FLAG(flag_broadcast_reception_start); +} +#endif /* CONFIG_BT_BAP_BROADCAST_ASSISTANT*/ + static struct bt_cap_commander_cb cap_cb = { .discovery_complete = cap_discovery_complete_cb, #if defined(CONFIG_BT_VCP_VOL_CTLR) @@ -148,6 +178,9 @@ static struct bt_cap_commander_cb cap_cb = { .microphone_gain_changed = cap_microphone_gain_changed_cb, #endif /* CONFIG_BT_MICP_MIC_CTLR_AICS */ #endif /* CONFIG_BT_MICP_MIC_CTLR */ +#if defined(CONFIG_BT_BAP_BROADCAST_ASSISTANT) + .broadcast_reception_start = cap_broadcast_reception_start_cb, +#endif /* CONFIG_BT_BAP_BROADCAST_ASSISTANT*/ }; static void cap_vcp_discover_cb(struct bt_vcp_vol_ctlr *vol_ctlr, int err, uint8_t vocs_count, @@ -210,6 +243,267 @@ static void cap_disconnected_cb(struct bt_conn *conn, uint8_t reason) k_sem_give(&sem_disconnected); } +static uint16_t interval_to_sync_timeout(uint16_t pa_interval) +{ + uint16_t pa_timeout; + + if (pa_interval == BT_BAP_PA_INTERVAL_UNKNOWN) { + /* Use maximum value to maximize chance of success */ + pa_timeout = BT_GAP_PER_ADV_MAX_TIMEOUT; + } else { + uint32_t interval_ms; + 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) / 10; + + /* Enforce restraints */ + pa_timeout = CLAMP(timeout, BT_GAP_PER_ADV_MIN_TIMEOUT, BT_GAP_PER_ADV_MAX_TIMEOUT); + } + + return pa_timeout; +} + +static int pa_sync_create(void) +{ + struct bt_le_per_adv_sync_param create_params = {0}; + int err; + + bt_addr_le_copy(&create_params.addr, &broadcaster_addr); + create_params.options = 0; + create_params.sid = broadcaster_info.sid; + create_params.skip = PA_SYNC_SKIP; + create_params.timeout = interval_to_sync_timeout(broadcaster_info.interval); + + err = bt_le_per_adv_sync_create(&create_params, &g_pa_sync); + return err; +} + +static bool scan_check_and_sync_broadcast(struct bt_data *data, void *user_data) +{ + const struct bt_le_scan_recv_info *info = user_data; + char le_addr[BT_ADDR_LE_STR_LEN]; + struct bt_uuid_16 adv_uuid; + uint32_t broadcast_id; + + if (TEST_FLAG(flag_broadcaster_found)) { + /* no-op*/ + printk("NO OP\n"); + return false; + } + + if (data->type != BT_DATA_SVC_DATA16) { + return true; + } + + if (data->data_len < BT_UUID_SIZE_16 + BT_AUDIO_BROADCAST_ID_SIZE) { + return true; + } + + if (!bt_uuid_create(&adv_uuid.uuid, data->data, BT_UUID_SIZE_16)) { + return true; + } + + if (bt_uuid_cmp(&adv_uuid.uuid, BT_UUID_BROADCAST_AUDIO)) { + return true; + } + + broadcast_id = sys_get_le24(data->data + BT_UUID_SIZE_16); + + bt_addr_le_to_str(info->addr, le_addr, sizeof(le_addr)); + + printk("Found broadcaster with ID 0x%06X and addr %s and sid 0x%02X\n", broadcast_id, + le_addr, info->sid); + printk("Adv type %02X interval %u", info->adv_type, info->interval); + + SET_FLAG(flag_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; +} + +static void broadcast_scan_recv(const struct bt_le_scan_recv_info *info, struct net_buf_simple *ad) +{ + if (info->interval != 0U) { + bt_data_parse(ad, scan_check_and_sync_broadcast, (void *)info); + } +} + +static struct bt_le_scan_cb bap_scan_cb = { + .recv = broadcast_scan_recv, +}; + +static void bap_pa_sync_synced_cb(struct bt_le_per_adv_sync *sync, + struct bt_le_per_adv_sync_synced_info *info) +{ + if (sync == g_pa_sync) { + printk("PA sync %p synced for broadcast sink with broadcast ID 0x%06X\n", sync, + broadcaster_broadcast_id); + SET_FLAG(flag_pa_synced); + } +} + +static void bap_pa_sync_terminated_cb(struct bt_le_per_adv_sync *sync, + const struct bt_le_per_adv_sync_term_info *info) +{ + if (sync == g_pa_sync) { + printk("CAP commander test PA sync %p lost with reason %u\n", sync, info->reason); + g_pa_sync = NULL; + + SET_FLAG(flag_pa_sync_lost); + } +} + +static bool base_store(struct bt_data *data, void *user_data) +{ + const struct bt_bap_base *base = bt_bap_base_get_base_from_ad(data); + uint8_t base_size; + int base_subgroup_count; + + /* Base is NULL if the data does not contain a valid BASE */ + if (base == NULL) { + return true; + } + + /* Can not fit all the received subgroups with the size CONFIG_BT_BAP_BASS_MAX_SUBGROUPS */ + base_subgroup_count = bt_bap_base_get_subgroup_count(base); + if (base_subgroup_count < 0 || base_subgroup_count > CONFIG_BT_BAP_BASS_MAX_SUBGROUPS) { + printk("Got invalid subgroup count: %d\n", base_subgroup_count); + return true; + } + + base_size = data->data_len - BT_UUID_SIZE_16; /* the BASE comes after the UUID */ + + /* Compare BASE and copy if different */ + if (base_size != received_base_size || memcmp(base, received_base, base_size) != 0) { + (void)memcpy(received_base, base, base_size); + received_base_size = base_size; + } + + /* Stop parsing */ + return false; +} + +static void pa_recv(struct bt_le_per_adv_sync *sync, + const struct bt_le_per_adv_sync_recv_info *info, struct net_buf_simple *buf) +{ + if (TEST_FLAG(flag_base_received)) { + return; + } + + bt_data_parse(buf, base_store, NULL); + SET_FLAG(flag_base_received); +} + +static struct bt_le_per_adv_sync_cb bap_pa_sync_cb = { + .synced = bap_pa_sync_synced_cb, + .term = bap_pa_sync_terminated_cb, + .recv = pa_recv, +}; + +static void bap_broadcast_assistant_discover_cb(struct bt_conn *conn, int err, + uint8_t recv_state_count) +{ + if (err == 0) { + printk("BASS discover done with %u recv states\n", recv_state_count); + } else { + printk("BASS discover failed (%d)\n", err); + } + + k_sem_give(&sem_bass_discovered); +} + +static void bap_broadcast_assistant_add_src_cb(struct bt_conn *conn, int err) +{ + if (err == 0) { + printk("BASS add source successful\n"); + } else { + printk("BASS add source failed (%d)\n", err); + } +} + +static bool metadata_entry(struct bt_data *data, void *user_data) +{ + char metadata[CONFIG_BT_AUDIO_CODEC_CFG_MAX_METADATA_SIZE]; + + (void)bin2hex(data->data, data->data_len, metadata, sizeof(metadata)); + + printk("\t\tMetadata length %u, type %u, data: %s\n", data->data_len, data->type, metadata); + + return true; +} + +static void +bap_broadcast_assistant_recv_state_cb(struct bt_conn *conn, int err, + const struct bt_bap_scan_delegator_recv_state *state) +{ + char le_addr[BT_ADDR_LE_STR_LEN]; + char bad_code[BT_AUDIO_BROADCAST_CODE_SIZE * 2 + 1]; + + if (err != 0) { + FAIL("BASS recv state read failed (%d)\n", err); + return; + } + + if (state == NULL) { + /* Empty receive state */ + return; + } + + bt_addr_le_to_str(&state->addr, le_addr, sizeof(le_addr)); + (void)bin2hex(state->bad_code, BT_AUDIO_BROADCAST_CODE_SIZE, bad_code, sizeof(bad_code)); + printk("BASS recv state: src_id %u, addr %s, sid %u, sync_state %u, " + "encrypt_state %u%s%s\n", + state->src_id, le_addr, state->adv_sid, state->pa_sync_state, state->encrypt_state, + state->encrypt_state == BT_BAP_BIG_ENC_STATE_BAD_CODE ? ", bad code" : "", bad_code); + + if (state->encrypt_state == BT_BAP_BIG_ENC_STATE_BAD_CODE) { + FAIL("Encryption state is BT_BAP_BIG_ENC_STATE_BAD_CODE"); + return; + } + + for (uint8_t i = 0; i < state->num_subgroups; i++) { + const struct bt_bap_bass_subgroup *subgroup = &state->subgroups[i]; + struct net_buf_simple buf; + + printk("\t[%d]: BIS sync %u, metadata_len %u\n", i, subgroup->bis_sync, + subgroup->metadata_len); + + net_buf_simple_init_with_data(&buf, (void *)subgroup->metadata, + subgroup->metadata_len); + bt_data_parse(&buf, metadata_entry, NULL); + + if (subgroup->bis_sync != 0) { + SET_FLAG(flag_recv_state_updated_with_bis_sync); + } + } + +#if defined(CONFIG_BT_PER_ADV_SYNC_TRANSFER_SENDER) + if (state->pa_sync_state == BT_BAP_PA_STATE_INFO_REQ) { + err = bt_le_per_adv_sync_transfer(g_pa_sync, conn, BT_UUID_BASS_VAL); + if (err != 0) { + FAIL("Could not transfer periodic adv sync: %d\n", err); + return; + } + } +#endif /* CONFIG_BT_PER_ADV_SYNC_TRANSFER_SENDER */ + + if (state->pa_sync_state == BT_BAP_PA_STATE_SYNCED) { + } +} + +static struct bt_bap_broadcast_assistant_cb ba_cbs = { + .discover = bap_broadcast_assistant_discover_cb, + .recv_state = bap_broadcast_assistant_recv_state_cb, + .add_src = bap_broadcast_assistant_add_src_cb, +}; + static void init(size_t acceptor_cnt) { static struct bt_conn_cb conn_cb = { @@ -244,10 +538,35 @@ static void init(size_t acceptor_cnt) return; } + err = bt_bap_broadcast_assistant_register_cb(&ba_cbs); + if (err != 0) { + FAIL("Failed to register broadcast assistant callbacks (err %d)\n"); + return; + } + + bt_le_per_adv_sync_cb_register(&bap_pa_sync_cb); + bt_le_scan_cb_register(&bap_scan_cb); + k_sem_init(&sem_disconnected, 0, acceptor_cnt); k_sem_init(&sem_cas_discovered, 0, acceptor_cnt); + k_sem_init(&sem_bass_discovered, 0, acceptor_cnt); k_sem_init(&sem_vcs_discovered, 0, acceptor_cnt); k_sem_init(&sem_mics_discovered, 0, acceptor_cnt); + + UNSET_FLAG(flag_mtu_exchanged); + UNSET_FLAG(flag_volume_changed); + UNSET_FLAG(flag_volume_mute_changed); + UNSET_FLAG(flag_volume_offset_changed); + UNSET_FLAG(flag_microphone_mute_changed); + UNSET_FLAG(flag_microphone_gain_changed); + + UNSET_FLAG(flag_broadcast_reception_start); + UNSET_FLAG(flag_broadcaster_found); + UNSET_FLAG(flag_base_received); + UNSET_FLAG(flag_recv_state_updated_with_bis_sync); + UNSET_FLAG(flag_pa_synced); + UNSET_FLAG(flag_pa_sync_lost); + UNSET_FLAG(flag_syncable); } static void cap_device_found(const bt_addr_le_t *addr, int8_t rssi, uint8_t type, @@ -330,10 +649,13 @@ static void disconnect_acl(size_t acceptor_cnt) for (size_t i = 0U; i < acceptor_cnt; i++) { const int err = k_sem_take(&sem_disconnected, SEM_TIMEOUT); - if (err != 0) { + if (err == 0) { + connected_conn_cnt--; + } else { const struct bt_conn *conn = connected_conns[i]; FAIL("Failed to take sem_disconnected for %p: %d", (void *)conn, err); + return; } } } @@ -367,6 +689,69 @@ static void discover_cas(size_t acceptor_cnt) } } +static void discover_bass(size_t acceptor_cnt) +{ + k_sem_reset(&sem_bass_discovered); + + if (acceptor_cnt > 1) { + FAIL("Current implementation does not support multiple connections for the " + "broadcast assistant"); + return; + } + + for (size_t i = 0U; i < acceptor_cnt; i++) { + int err; + + err = bt_bap_broadcast_assistant_discover(connected_conns[i]); + if (err != 0) { + FAIL("Failed to discover BASS on the sink (err %d)\n", err); + return; + } + } + + for (size_t i = 0U; i < acceptor_cnt; i++) { + const int err = k_sem_take(&sem_bass_discovered, SEM_TIMEOUT); + + if (err != 0) { + FAIL("Failed to take sem_bass_discovered for %p: %d", + (void *)connected_conns[i], err); + } + } +} + +static void pa_sync_to_broadcaster(void) +{ + int err; + + err = bt_le_scan_start(BT_LE_SCAN_ACTIVE, NULL); + if (err != 0) { + FAIL("Unable to start scan for broadcast sources: %d", err); + return; + } + + printk("Searching for a broadcaster\n"); + WAIT_FOR_FLAG(flag_broadcaster_found); + + err = bt_le_scan_stop(); + if (err != 0) { + FAIL("bt_le_scan_stop failed with %d\n", err); + return; + } + + printk("Scan stopped, attempting to PA sync to the broadcaster with id 0x%06X\n", + broadcaster_broadcast_id); + err = pa_sync_create(); + if (err != 0) { + FAIL("Could not create Broadcast PA sync: %d\n", err); + return; + } + + WAIT_FOR_FLAG(flag_pa_synced); /* todo from bap_pa_sync_synced_cb, bap_pa_sync_cb */ + + printk("Broadcast source PA synced, waiting for BASE\n"); + WAIT_FOR_FLAG(flag_base_received); +} + static void discover_vcs(size_t acceptor_cnt) { k_sem_reset(&sem_vcs_discovered); @@ -564,6 +949,65 @@ static void test_change_microphone_gain(void) printk("Microphone gain changed\n"); } +static void test_broadcast_reception_start(size_t acceptor_count) +{ + struct bt_cap_commander_broadcast_reception_start_param reception_start_param = {0}; + struct bt_cap_commander_broadcast_reception_start_member_param param[CONFIG_BT_MAX_CONN] = { + 0}; + int err; + + reception_start_param.type = BT_CAP_SET_TYPE_AD_HOC; + reception_start_param.count = acceptor_count; + reception_start_param.param = param; + + for (size_t i = 0; i < acceptor_count; i++) { + uint32_t bis_sync[CONFIG_BT_BAP_BASS_MAX_SUBGROUPS]; + size_t num_subgroups; + + reception_start_param.param[i].member.member = connected_conns[i]; + bt_addr_le_copy(&reception_start_param.param[i].addr, &broadcaster_addr); + reception_start_param.param[i].adv_sid = broadcaster_info.sid; + reception_start_param.param[i].pa_interval = broadcaster_info.interval; + reception_start_param.param[i].broadcast_id = broadcaster_broadcast_id; + num_subgroups = + bt_bap_base_get_subgroup_count((const struct bt_bap_base *)received_base); + err = bt_bap_base_get_bis_indexes((const struct bt_bap_base *)received_base, + bis_sync); + if (err != 0) { + FAIL("Could not populate subgroup information: %d\n", err); + return; + } + + reception_start_param.param[i].num_subgroups = num_subgroups; + for (size_t j = 0; j < num_subgroups; j++) { + reception_start_param.param[i].subgroups[j].bis_sync = bis_sync[j]; + } + } + + err = bt_cap_commander_broadcast_reception_start(&reception_start_param); + if (err != 0) { + FAIL("Could not initiate broadcast reception start: %d\n", err); + return; + } + + WAIT_FOR_FLAG(flag_broadcast_reception_start); +} + +static void test_broadcast_reception_stop(size_t acceptor_count) +{ + struct bt_cap_commander_broadcast_reception_stop_param reception_stop_param; + int err; + + /* reception stop is not implemented yet, for now the following command will fail*/ + reception_stop_param.type = BT_CAP_SET_TYPE_AD_HOC; + reception_stop_param.members = NULL; + reception_stop_param.count = 0U; + err = bt_cap_commander_broadcast_reception_stop(&reception_stop_param); + if (err != 0) { + printk("Command not implemented yet, could not stop broadcast reception %d\n", err); + } +} + static void test_main_cap_commander_capture_and_render(void) { const size_t acceptor_cnt = get_dev_cnt() - 1; /* Assume all other devices are acceptors @@ -613,6 +1057,49 @@ static void test_main_cap_commander_capture_and_render(void) PASS("CAP commander capture and rendering passed\n"); } +static void test_main_cap_commander_broadcast_reception(void) +{ + size_t acceptor_count; + + /* The test consists of N devices + * 1 device is the broadcast source + * 1 device is the CAP commander + * This leaves N - 2 devices for the acceptor + */ + acceptor_count = get_dev_cnt() - 2; + printk("Acceptor count: %d\n", acceptor_count); + + init(acceptor_count); + + for (size_t i = 0U; i < acceptor_count; i++) { + scan_and_connect(); + + WAIT_FOR_FLAG(flag_mtu_exchanged); + } + + /* TODO: We should use CSIP to find set members */ + discover_cas(acceptor_count); + discover_bass(acceptor_count); + + pa_sync_to_broadcaster(); + + test_broadcast_reception_start(acceptor_count); + + backchannel_sync_wait_any(); /* wait for the acceptor to receive data */ + + backchannel_sync_wait_any(); /* wait for the acceptor to receive a metadata update + */ + + test_broadcast_reception_stop(acceptor_count); + + backchannel_sync_wait_any(); /* wait for the acceptor to stop reception */ + + /* Disconnect all CAP acceptors */ + disconnect_acl(acceptor_count); + + PASS("Broadcast reception passed\n"); +} + static const struct bst_test_instance test_cap_commander[] = { { .test_id = "cap_commander_capture_and_render", @@ -620,6 +1107,12 @@ static const struct bst_test_instance test_cap_commander[] = { .test_tick_f = test_tick, .test_main_f = test_main_cap_commander_capture_and_render, }, + { + .test_id = "cap_commander_broadcast_reception", + .test_post_init_f = test_init, + .test_tick_f = test_tick, + .test_main_f = test_main_cap_commander_broadcast_reception, + }, BSTEST_END_MARKER, }; diff --git a/tests/bsim/bluetooth/audio/test_scripts/cap_broadcast_reception.sh b/tests/bsim/bluetooth/audio/test_scripts/cap_broadcast_reception.sh new file mode 100755 index 0000000000000..32cee89fa84fe --- /dev/null +++ b/tests/bsim/bluetooth/audio/test_scripts/cap_broadcast_reception.sh @@ -0,0 +1,35 @@ +#!/usr/bin/env bash +# +# Copyright (c) 2024 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: Apache-2.0 + +SIMULATION_ID="cap_broadcast_reception" +VERBOSITY_LEVEL=2 +NR_OF_DEVICES=3 + +source ${ZEPHYR_BASE}/tests/bsim/sh_common.source + +cd ${BSIM_OUT_PATH}/bin + +printf "\n\n======== Running CAP commander broadcast reception start and stop test =========\n\n" + +Execute ./bs_${BOARD_TS}_tests_bsim_bluetooth_audio_prj_conf \ + -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=0 -testid=cap_commander_broadcast_reception \ + -rs=46 -D=${NR_OF_DEVICES} + +Execute ./bs_${BOARD_TS}_tests_bsim_bluetooth_audio_prj_conf \ + -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=1 -testid=broadcast_source \ + -rs=23 -D=${NR_OF_DEVICES} + +Execute ./bs_${BOARD_TS}_tests_bsim_bluetooth_audio_prj_conf \ + -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} -d=2 -testid=cap_acceptor_broadcast_reception \ + -rs=69 -D=${NR_OF_DEVICES} + +# Simulation time should be larger than the WAIT_TIME in common.h +Execute ./bs_2G4_phy_v1 -v=${VERBOSITY_LEVEL} -s=${SIMULATION_ID} \ + -D=${NR_OF_DEVICES} -sim_length=60e6 $@ + + + +wait_for_background_jobs From 768c45a11dd00ba105778f579dbe0b1c007220ec Mon Sep 17 00:00:00 2001 From: Rubin Gerritsen Date: Thu, 13 Jun 2024 15:23:51 +0200 Subject: [PATCH 2712/2849] Bluetooth: Controller: Clarify that it can be overridden out of tree Nordic devices are commonly used with the nRF Connect SDK. There the SoftDevice Controller is set as the default Bluetooth Controller. To avoid confusion when reading DTS and Kconfig files, clarify this by adding a note. Signed-off-by: Rubin Gerritsen --- dts/arm/nordic/nrf52805.dtsi | 3 +++ dts/arm/nordic/nrf52810.dtsi | 3 +++ dts/arm/nordic/nrf52811.dtsi | 3 +++ dts/arm/nordic/nrf52820.dtsi | 3 +++ dts/arm/nordic/nrf52832.dtsi | 3 +++ dts/arm/nordic/nrf52833.dtsi | 3 +++ dts/arm/nordic/nrf52840.dtsi | 3 +++ dts/arm/nordic/nrf5340_cpunet.dtsi | 3 +++ dts/common/nordic/nrf54l15.dtsi | 3 +++ subsys/bluetooth/controller/Kconfig | 3 +++ 10 files changed, 30 insertions(+) diff --git a/dts/arm/nordic/nrf52805.dtsi b/dts/arm/nordic/nrf52805.dtsi index b375ef1706975..36213c186526c 100644 --- a/dts/arm/nordic/nrf52805.dtsi +++ b/dts/arm/nordic/nrf52805.dtsi @@ -88,6 +88,9 @@ status = "okay"; ble-2mbps-supported; + /* Note: In the nRF Connect SDK the SoftDevice Controller + * is added and set as the default Bluetooth Controller. + */ bt_hci_controller: bt_hci_controller { compatible = "zephyr,bt-hci-ll-sw-split"; status = "okay"; diff --git a/dts/arm/nordic/nrf52810.dtsi b/dts/arm/nordic/nrf52810.dtsi index 0c95fe96e70df..18b2e430943da 100644 --- a/dts/arm/nordic/nrf52810.dtsi +++ b/dts/arm/nordic/nrf52810.dtsi @@ -92,6 +92,9 @@ status = "okay"; ble-2mbps-supported; + /* Note: In the nRF Connect SDK the SoftDevice Controller + * is added and set as the default Bluetooth Controller. + */ bt_hci_controller: bt_hci_controller { compatible = "zephyr,bt-hci-ll-sw-split"; status = "okay"; diff --git a/dts/arm/nordic/nrf52811.dtsi b/dts/arm/nordic/nrf52811.dtsi index 2176bfa93c744..12615364cef37 100644 --- a/dts/arm/nordic/nrf52811.dtsi +++ b/dts/arm/nordic/nrf52811.dtsi @@ -104,6 +104,9 @@ status = "disabled"; }; + /* Note: In the nRF Connect SDK the SoftDevice Controller + * is added and set as the default Bluetooth Controller. + */ bt_hci_controller: bt_hci_controller { compatible = "zephyr,bt-hci-ll-sw-split"; status = "okay"; diff --git a/dts/arm/nordic/nrf52820.dtsi b/dts/arm/nordic/nrf52820.dtsi index d6bd6e65f66cf..21bb88aa99ce5 100644 --- a/dts/arm/nordic/nrf52820.dtsi +++ b/dts/arm/nordic/nrf52820.dtsi @@ -100,6 +100,9 @@ status = "disabled"; }; + /* Note: In the nRF Connect SDK another Bluetooth controller + * is added and set as the default. + */ bt_hci_controller: bt_hci_controller { compatible = "zephyr,bt-hci-ll-sw-split"; status = "okay"; diff --git a/dts/arm/nordic/nrf52832.dtsi b/dts/arm/nordic/nrf52832.dtsi index bdb76a05d5b59..f467c5fc5c000 100644 --- a/dts/arm/nordic/nrf52832.dtsi +++ b/dts/arm/nordic/nrf52832.dtsi @@ -92,6 +92,9 @@ status = "okay"; ble-2mbps-supported; + /* Note: In the nRF Connect SDK the SoftDevice Controller + * is added and set as the default Bluetooth Controller. + */ bt_hci_controller: bt_hci_controller { compatible = "zephyr,bt-hci-ll-sw-split"; status = "okay"; diff --git a/dts/arm/nordic/nrf52833.dtsi b/dts/arm/nordic/nrf52833.dtsi index 40c3f1efcad4b..1a27a14447bbf 100644 --- a/dts/arm/nordic/nrf52833.dtsi +++ b/dts/arm/nordic/nrf52833.dtsi @@ -99,6 +99,9 @@ status = "disabled"; }; + /* Note: In the nRF Connect SDK the SoftDevice Controller + * is added and set as the default Bluetooth Controller. + */ bt_hci_controller: bt_hci_controller { compatible = "zephyr,bt-hci-ll-sw-split"; status = "okay"; diff --git a/dts/arm/nordic/nrf52840.dtsi b/dts/arm/nordic/nrf52840.dtsi index 120a5a87b1355..5d209533a1ae9 100644 --- a/dts/arm/nordic/nrf52840.dtsi +++ b/dts/arm/nordic/nrf52840.dtsi @@ -94,6 +94,9 @@ status = "disabled"; }; + /* Note: In the nRF Connect SDK the SoftDevice Controller + * is added and set as the default Bluetooth Controller. + */ bt_hci_controller: bt_hci_controller { compatible = "zephyr,bt-hci-ll-sw-split"; status = "okay"; diff --git a/dts/arm/nordic/nrf5340_cpunet.dtsi b/dts/arm/nordic/nrf5340_cpunet.dtsi index 4e05f4a1df02e..77b77759b2205 100644 --- a/dts/arm/nordic/nrf5340_cpunet.dtsi +++ b/dts/arm/nordic/nrf5340_cpunet.dtsi @@ -102,6 +102,9 @@ status = "disabled"; }; + /* Note: In the nRF Connect SDK the SoftDevice Controller + * is added and set as the default Bluetooth Controller. + */ bt_hci_controller: bt_hci_controller { compatible = "zephyr,bt-hci-ll-sw-split"; status = "okay"; diff --git a/dts/common/nordic/nrf54l15.dtsi b/dts/common/nordic/nrf54l15.dtsi index 8896b94f87488..122e4fdf42aaf 100644 --- a/dts/common/nordic/nrf54l15.dtsi +++ b/dts/common/nordic/nrf54l15.dtsi @@ -265,6 +265,9 @@ status = "disabled"; }; + /* Note: In the nRF Connect SDK the SoftDevice Controller + * is added and set as the default Bluetooth Controller. + */ bt_hci_controller: bt_hci_controller { compatible = "zephyr,bt-hci-ll-sw-split"; status = "disabled"; diff --git a/subsys/bluetooth/controller/Kconfig b/subsys/bluetooth/controller/Kconfig index 2fcaf73b8c69e..3166a4950ddb0 100644 --- a/subsys/bluetooth/controller/Kconfig +++ b/subsys/bluetooth/controller/Kconfig @@ -125,6 +125,9 @@ choice BT_LL_CHOICE prompt "Bluetooth Link Layer Selection" help Select the Bluetooth Link Layer to compile. + The link layer choice list can be extended out of tree. + In the nRF Connect SDK, the SoftDevice Controller is selected + and set as the default Bluetooth Controller. config BT_LL_SW_SPLIT bool "Software-based BLE Link Layer" From ab9fd0b5c96b0bad082f3994051fa15623eb491f Mon Sep 17 00:00:00 2001 From: Jens Rehhoff Thomsen Date: Wed, 12 Jun 2024 14:20:37 +0200 Subject: [PATCH 2713/2849] Bluetooth: BAP: Add bt_bap_base_get_size function bt_bap_base_get_size function returns the size of the BASE. Fixes #73847 Signed-off-by: Jens Rehhoff Thomsen --- include/zephyr/bluetooth/audio/bap.h | 10 ++++ .../bap_broadcast_assistant/src/main.c | 16 ++++-- subsys/bluetooth/audio/bap_base.c | 52 +++++++++++++++++++ subsys/bluetooth/audio/bap_broadcast_sink.c | 11 ++-- .../audio/shell/bap_broadcast_assistant.c | 16 ++++-- tests/bluetooth/audio/bap_base/src/main.c | 19 +++++++ 6 files changed, 111 insertions(+), 13 deletions(-) diff --git a/include/zephyr/bluetooth/audio/bap.h b/include/zephyr/bluetooth/audio/bap.h index 00957b2b81be5..1ee66b59170f6 100644 --- a/include/zephyr/bluetooth/audio/bap.h +++ b/include/zephyr/bluetooth/audio/bap.h @@ -1440,6 +1440,16 @@ struct bt_bap_base_subgroup_bis { */ const struct bt_bap_base *bt_bap_base_get_base_from_ad(const struct bt_data *ad); +/** + * @brief Get the size of a BASE + * + * @param base The BASE pointer + * + * @retval -EINVAL if arguments are invalid + * @retval The size of the BASE + */ +int bt_bap_base_get_size(const struct bt_bap_base *base); + /** * @brief Get the presentation delay value of a BASE * diff --git a/samples/bluetooth/bap_broadcast_assistant/src/main.c b/samples/bluetooth/bap_broadcast_assistant/src/main.c index 3c8bdf1de6985..500a8d2c290b1 100644 --- a/samples/bluetooth/bap_broadcast_assistant/src/main.c +++ b/samples/bluetooth/bap_broadcast_assistant/src/main.c @@ -42,7 +42,7 @@ static uint16_t selected_pa_interval; static bt_addr_le_t selected_addr; static struct bt_le_per_adv_sync *pa_sync; static uint8_t received_base[UINT8_MAX]; -static uint8_t received_base_size; +static size_t received_base_size; static struct bt_bap_bass_subgroup bass_subgroups[CONFIG_BT_BAP_BASS_MAX_SUBGROUPS]; @@ -133,7 +133,7 @@ static bool device_found(struct bt_data *data, void *user_data) static bool base_store(struct bt_data *data, void *user_data) { const struct bt_bap_base *base = bt_bap_base_get_base_from_ad(data); - uint8_t base_size; + int base_size; int base_subgroup_count; /* Base is NULL if the data does not contain a valid BASE */ @@ -148,13 +148,19 @@ static bool base_store(struct bt_data *data, void *user_data) return true; } - base_size = data->data_len - BT_UUID_SIZE_16; /* the BASE comes after the UUID */ + base_size = bt_bap_base_get_size(base); + if (base_size < 0) { + printk("BASE get size failed (%d)\n", base_size); + + return true; + } /* Compare BASE and copy if different */ k_mutex_lock(&base_store_mutex, K_FOREVER); - if (base_size != received_base_size || memcmp(base, received_base, base_size) != 0) { + if ((size_t)base_size != received_base_size || + memcmp(base, received_base, (size_t)base_size) != 0) { (void)memcpy(received_base, base, base_size); - received_base_size = base_size; + received_base_size = (size_t)base_size; } k_mutex_unlock(&base_store_mutex); diff --git a/subsys/bluetooth/audio/bap_base.c b/subsys/bluetooth/audio/bap_base.c index a649f7446592f..cb3a521d268a2 100644 --- a/subsys/bluetooth/audio/bap_base.c +++ b/subsys/bluetooth/audio/bap_base.c @@ -221,6 +221,58 @@ const struct bt_bap_base *bt_bap_base_get_base_from_ad(const struct bt_data *ad) return base; } +int bt_bap_base_get_size(const struct bt_bap_base *base) +{ + struct net_buf_simple net_buf; + uint8_t subgroup_count; + size_t size = 0; + + CHECKIF(base == NULL) { + LOG_DBG("base is NULL"); + + return -EINVAL; + } + + net_buf_simple_init_with_data(&net_buf, (void *)base, BASE_MAX_SIZE); + base_pull_pd(&net_buf); + size += BASE_PD_SIZE; + subgroup_count = net_buf_simple_pull_u8(&net_buf); + size += BASE_SUBGROUP_COUNT_SIZE; + + /* Parse subgroup data */ + for (uint8_t i = 0U; i < subgroup_count; i++) { + uint8_t bis_count; + uint8_t len; + + bis_count = base_pull_bis_count(&net_buf); + size += BASE_NUM_BIS_SIZE; + + base_pull_codec_id(&net_buf, NULL); + size += BASE_CODEC_ID_SIZE; + + /* Codec config */ + len = base_pull_ltv(&net_buf, NULL); + size += len + BASE_CC_LEN_SIZE; + + /* meta */ + len = base_pull_ltv(&net_buf, NULL); + size += len + BASE_META_LEN_SIZE; + + /* Parse BIS data */ + for (uint8_t j = 0U; j < bis_count; j++) { + /* BIS index */ + net_buf_simple_pull_u8(&net_buf); + size += BASE_BIS_INDEX_SIZE; + + /* Codec config */ + len = base_pull_ltv(&net_buf, NULL); + size += len + BASE_BIS_CC_LEN_SIZE; + } + } + + return (int)size; +} + int bt_bap_base_get_pres_delay(const struct bt_bap_base *base) { struct net_buf_simple net_buf; diff --git a/subsys/bluetooth/audio/bap_broadcast_sink.c b/subsys/bluetooth/audio/bap_broadcast_sink.c index c91c4325e8944..2ab984a73bfc5 100644 --- a/subsys/bluetooth/audio/bap_broadcast_sink.c +++ b/subsys/bluetooth/audio/bap_broadcast_sink.c @@ -748,7 +748,7 @@ static bool pa_decode_base(struct bt_data *data, void *user_data) struct bt_bap_broadcast_sink *sink = (struct bt_bap_broadcast_sink *)user_data; const struct bt_bap_base *base = bt_bap_base_get_base_from_ad(data); struct bt_bap_broadcast_sink_cb *listener; - size_t base_size; + int base_size; int ret; /* Base is NULL if the data does not contain a valid BASE */ @@ -794,11 +794,16 @@ static bool pa_decode_base(struct bt_data *data, void *user_data) } /* We provide the BASE without the service data UUID */ - base_size = data->data_len - BT_UUID_SIZE_16; + base_size = bt_bap_base_get_size(base); + if (base_size < 0) { + LOG_DBG("BASE get size failed (%d)", base_size); + + return false; + } SYS_SLIST_FOR_EACH_CONTAINER(&sink_cbs, listener, _node) { if (listener->base_recv != NULL) { - listener->base_recv(sink, base, base_size); + listener->base_recv(sink, base, (size_t)base_size); } } diff --git a/subsys/bluetooth/audio/shell/bap_broadcast_assistant.c b/subsys/bluetooth/audio/shell/bap_broadcast_assistant.c index 85be52069ab58..d0b4dd6410a54 100644 --- a/subsys/bluetooth/audio/shell/bap_broadcast_assistant.c +++ b/subsys/bluetooth/audio/shell/bap_broadcast_assistant.c @@ -39,7 +39,7 @@ #define INVALID_BROADCAST_ID 0xFFFFFFFFU static uint8_t received_base[UINT8_MAX]; -static uint8_t received_base_size; +static size_t received_base_size; static struct bt_auto_scan { uint32_t broadcast_id; @@ -52,19 +52,25 @@ static struct bt_auto_scan { static bool pa_decode_base(struct bt_data *data, void *user_data) { const struct bt_bap_base *base = bt_bap_base_get_base_from_ad(data); - uint8_t base_size; + int base_size; /* Base is NULL if the data does not contain a valid BASE */ if (base == NULL) { return true; } - base_size = data->data_len - BT_UUID_SIZE_16; /* the BASE comes after the UUID */ + base_size = bt_bap_base_get_size(base); + if (base_size < 0) { + shell_error(ctx_shell, "BASE get size failed (%d)", base_size); + + return true; + } /* Compare BASE and print if different */ - if (base_size != received_base_size || memcmp(base, received_base, base_size) != 0) { + if ((size_t)base_size != received_base_size || + memcmp(base, received_base, (size_t)base_size) != 0) { (void)memcpy(received_base, base, base_size); - received_base_size = base_size; + received_base_size = (size_t)base_size; print_base((const struct bt_bap_base *)received_base); } diff --git a/tests/bluetooth/audio/bap_base/src/main.c b/tests/bluetooth/audio/bap_base/src/main.c index 7a101e19df128..5a8e24809202d 100644 --- a/tests/bluetooth/audio/bap_base/src/main.c +++ b/tests/bluetooth/audio/bap_base/src/main.c @@ -154,6 +154,25 @@ ZTEST_F(bap_base_test_suite, test_base_get_base_from_ad_inval_param_uuid) zassert_is_null(base); } +ZTEST_F(bap_base_test_suite, test_base_get_size) +{ + const struct bt_bap_base *base = bt_bap_base_get_base_from_ad(&fixture->valid_base_ad); + int ret; + + zassert_not_null(base); + + ret = bt_bap_base_get_size(base); + zassert_equal(ret, 70, "Unexpected BASE size: %d", ret); +} + +ZTEST_F(bap_base_test_suite, test_base_get_size_inval_param_null) +{ + int ret; + + ret = bt_bap_base_get_size(NULL); + zassert_equal(ret, -EINVAL, "Unexpected return value: %d", ret); +} + ZTEST_F(bap_base_test_suite, test_base_get_pres_delay) { const struct bt_bap_base *base = bt_bap_base_get_base_from_ad(&fixture->valid_base_ad); From 35cc774aa504eb56ae35bfcc44d0e069a62e2af6 Mon Sep 17 00:00:00 2001 From: Seppo Takalo Date: Wed, 12 Jun 2024 15:37:49 +0300 Subject: [PATCH 2714/2849] net: lwm2m: Retry DTLS handshake before dropping to bootstrap Allow DTLS handshake to be retried before the engine drops into bootstrap. Otherwise any termporary failure, for example DNS failure might drop us into bootstrap without retrying. Now all the retry logic should be in sm_do_network_error(). sm_do_registration() should only fall back to bootstrap if there is configuration error. Signed-off-by: Seppo Takalo --- subsys/net/lib/lwm2m/lwm2m_rd_client.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/subsys/net/lib/lwm2m/lwm2m_rd_client.c b/subsys/net/lib/lwm2m/lwm2m_rd_client.c index 2ff37566772c3..0443a425b7594 100644 --- a/subsys/net/lib/lwm2m/lwm2m_rd_client.c +++ b/subsys/net/lib/lwm2m/lwm2m_rd_client.c @@ -1073,7 +1073,7 @@ static void sm_do_registration(void) ret = lwm2m_engine_start(client.ctx); if (ret < 0) { LOG_ERR("Cannot init LWM2M engine (%d)", ret); - goto bootstrap_or_retry; + goto retry; } } @@ -1081,11 +1081,12 @@ static void sm_do_registration(void) return; bootstrap_or_retry: - lwm2m_engine_stop(client.ctx); if (!client.server_disabled && fallback_to_bootstrap()) { + lwm2m_engine_stop(client.ctx); return; } - +retry: + lwm2m_engine_stop(client.ctx); set_sm_state(ENGINE_NETWORK_ERROR); } From e63c691a86264bb34a9721c262bd01f8f4489ba2 Mon Sep 17 00:00:00 2001 From: Piotr Kosycarz Date: Wed, 12 Jun 2024 14:41:12 +0200 Subject: [PATCH 2715/2849] samples: sensor: bme680: Allow coverage calculation Sample must end to dump coverage data. Signed-off-by: Piotr Kosycarz --- samples/sensor/bme680/src/main.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/samples/sensor/bme680/src/main.c b/samples/sensor/bme680/src/main.c index 93a1c4b82627a..1464504ce436c 100644 --- a/samples/sensor/bme680/src/main.c +++ b/samples/sensor/bme680/src/main.c @@ -21,7 +21,11 @@ int main(void) printf("Device %p name is %s\n", dev, dev->name); +#ifndef CONFIG_COVERAGE while (1) { +#else + for (int i = 0; i < 5; i++) { +#endif k_sleep(K_MSEC(3000)); sensor_sample_fetch(dev); From 1b3725e099d414cc10c1b74874eeb42d9eac5189 Mon Sep 17 00:00:00 2001 From: Piotr Kosycarz Date: Wed, 12 Jun 2024 14:38:10 +0200 Subject: [PATCH 2716/2849] samples: sensor: accel_polling: Allow coverage calculation Sample must end to dump coverage data. Signed-off-by: Piotr Kosycarz --- samples/sensor/accel_polling/src/main.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/samples/sensor/accel_polling/src/main.c b/samples/sensor/accel_polling/src/main.c index ef0ecbbb7bc3f..13e8cc3787ced 100644 --- a/samples/sensor/accel_polling/src/main.c +++ b/samples/sensor/accel_polling/src/main.c @@ -62,7 +62,11 @@ int main(void) } } +#ifndef CONFIG_COVERAGE while (1) { +#else + for (int i = 0; i < 5; i++) { +#endif for (size_t i = 0; i < ARRAY_SIZE(sensors); i++) { ret = print_accels(sensors[i]); if (ret < 0) { From a3e1e398bf611c75e11da42db6ebc38cc4539e4c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20G=C5=82=C4=85b?= Date: Wed, 12 Jun 2024 12:21:40 +0200 Subject: [PATCH 2717/2849] boards: nordic: nrf54h20: Add ADC to the list of supported peripherals MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ADC driver was aligned to nrf54h20 target. Enable ADC Twister tests on that platform. Signed-off-by: Sebastian Głąb --- boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpuapp.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpuapp.yaml b/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpuapp.yaml index e07bbee7d14a9..1fb5a03987527 100644 --- a/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpuapp.yaml +++ b/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpuapp.yaml @@ -13,6 +13,7 @@ sysbuild: true ram: 256 flash: 296 supported: + - adc - can - counter - gpio From cc9bd6d77e0a606f6f1acbe32e5ee96b3f57a7a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20G=C5=82=C4=85b?= Date: Wed, 12 Jun 2024 12:25:26 +0200 Subject: [PATCH 2718/2849] samples: drivers: adc: adc_dt: Add nrf54h20 to platform_allow MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Enable test execution on nrf54h20dk. Overlay file already exists. Signed-off-by: Sebastian Głąb --- samples/drivers/adc/adc_dt/sample.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/samples/drivers/adc/adc_dt/sample.yaml b/samples/drivers/adc/adc_dt/sample.yaml index c758d27e3ad94..48c4e3181eb36 100644 --- a/samples/drivers/adc/adc_dt/sample.yaml +++ b/samples/drivers/adc/adc_dt/sample.yaml @@ -16,6 +16,7 @@ tests: - nrf51dk/nrf51822 - nrf52840dk/nrf52840 - nrf54l15pdk/nrf54l15/cpuapp + - nrf54h20dk/nrf54h20/cpuapp - mec172xevb_assy6906 - gd32f350r_eval - gd32f450i_eval From 48fc6877e42f3325ca04db78c7f681909f0aebf7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20G=C5=82=C4=85b?= Date: Wed, 12 Jun 2024 12:29:41 +0200 Subject: [PATCH 2719/2849] samples: drivers: adc: adc_sequence: Enable test execution on nrf54h20 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add overlay file for nrf54h20 cpuapp target. Add nrf54h20 target to platform_allow. Signed-off-by: Sebastian Głąb --- .../boards/nrf54h20dk_nrf54h20_cpuapp.overlay | 51 +++++++++++++++++++ samples/drivers/adc/adc_sequence/sample.yaml | 1 + 2 files changed, 52 insertions(+) create mode 100644 samples/drivers/adc/adc_sequence/boards/nrf54h20dk_nrf54h20_cpuapp.overlay diff --git a/samples/drivers/adc/adc_sequence/boards/nrf54h20dk_nrf54h20_cpuapp.overlay b/samples/drivers/adc/adc_sequence/boards/nrf54h20dk_nrf54h20_cpuapp.overlay new file mode 100644 index 0000000000000..5f7e20136b49c --- /dev/null +++ b/samples/drivers/adc/adc_sequence/boards/nrf54h20dk_nrf54h20_cpuapp.overlay @@ -0,0 +1,51 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright (c) 2024 Nordic Semiconductor ASA + */ + +/ { + aliases { + adc0 = &adc; + }; +}; + +/ { + 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_2"; + zephyr,reference = "ADC_REF_INTERNAL"; + zephyr,acquisition-time = ; + zephyr,input-positive = ; /* P1.01 */ + zephyr,resolution = <10>; + }; + + channel@1 { + reg = <1>; + zephyr,gain = "ADC_GAIN_1_2"; + zephyr,reference = "ADC_REF_INTERNAL"; + zephyr,acquisition-time = ; + zephyr,input-positive = ; /* P1.02 */ + zephyr,resolution = <12>; + zephyr,oversampling = <8>; + }; + + channel@7 { + reg = <7>; + zephyr,gain = "ADC_GAIN_1_2"; + zephyr,reference = "ADC_REF_INTERNAL"; + zephyr,acquisition-time = ; + zephyr,input-positive = ; /* P1.03 */ + zephyr,input-negative = ; /* P1.07 */ + zephyr,resolution = <12>; + }; +}; diff --git a/samples/drivers/adc/adc_sequence/sample.yaml b/samples/drivers/adc/adc_sequence/sample.yaml index 5afd54ead3a29..cec7ee09bc825 100644 --- a/samples/drivers/adc/adc_sequence/sample.yaml +++ b/samples/drivers/adc/adc_sequence/sample.yaml @@ -10,6 +10,7 @@ tests: - cy8cproto_062_4343w - nrf52840dk/nrf52840 - nrf54l15pdk/nrf54l15/cpuapp + - nrf54h20dk/nrf54h20/cpuapp integration_platforms: - nrf52840dk/nrf52840 harness: console From e5f6cee9fb156e9393c55b696714da2a894af348 Mon Sep 17 00:00:00 2001 From: Yangbo Lu Date: Tue, 11 Jun 2024 13:52:03 +0900 Subject: [PATCH 2720/2849] drivers: ethernet: phy_realtek_rtl8211f: fix monitor work schedule Monitor work should be scheduled for non-interrupt mode. Signed-off-by: Yangbo Lu --- drivers/ethernet/phy/phy_realtek_rtl8211f.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/ethernet/phy/phy_realtek_rtl8211f.c b/drivers/ethernet/phy/phy_realtek_rtl8211f.c index b1765a500bc5a..c62ed1d4cbeac 100644 --- a/drivers/ethernet/phy/phy_realtek_rtl8211f.c +++ b/drivers/ethernet/phy/phy_realtek_rtl8211f.c @@ -510,6 +510,7 @@ static int phy_rt_rtl8211f_init(const struct device *dev) #if DT_ANY_INST_HAS_PROP_STATUS_OKAY(int_gpios) if (!config->interrupt_gpio.port) { + phy_rt_rtl8211f_monitor_work_handler(&data->phy_monitor_work.work); goto skip_int_gpio; } @@ -589,6 +590,8 @@ static int phy_rt_rtl8211f_init(const struct device *dev) return ret; } skip_int_gpio: +#else + phy_rt_rtl8211f_monitor_work_handler(&data->phy_monitor_work.work); #endif /* DT_ANY_INST_HAS_PROP_STATUS_OKAY(int_gpios) */ return 0; From b77dab61996068484abac8cc7f1576c8ab8df2af Mon Sep 17 00:00:00 2001 From: Yangbo Lu Date: Tue, 11 Jun 2024 15:09:48 +0900 Subject: [PATCH 2721/2849] drivers: ethernet: phy_realtek_rtl8211f: enable RGMII TX/RX delay The RGMII specifies output TXC/RXC and TXD/RXD without any clock skew. Need to add skew on clock line to make sure the other side sample right data. This can also be done in PCB traces. This patch is to enable RGMII TX/RX delay to ensure timing. Signed-off-by: Yangbo Lu --- drivers/ethernet/phy/phy_realtek_rtl8211f.c | 49 ++++++++++++++++++++- 1 file changed, 47 insertions(+), 2 deletions(-) diff --git a/drivers/ethernet/phy/phy_realtek_rtl8211f.c b/drivers/ethernet/phy/phy_realtek_rtl8211f.c index c62ed1d4cbeac..d0f25750128a9 100644 --- a/drivers/ethernet/phy/phy_realtek_rtl8211f.c +++ b/drivers/ethernet/phy/phy_realtek_rtl8211f.c @@ -39,6 +39,12 @@ LOG_MODULE_REGISTER(LOG_MODULE_NAME); #define PHY_RT_RTL8211F_PAGSR_REG (0x1F) +#define PHY_RT_RTL8211F_PAGE_MIICR_ADDR (0xD08) +#define PHY_RT_RTL8211F_MIICR1_REG (0x11) +#define PHY_RT_RTL8211F_MIICR2_REG (0x15) +#define PHY_RT_RTL8211F_MIICR1_TXDLY_MASK BIT(8) +#define PHY_RT_RTL8211F_MIICR2_RXDLY_MASK BIT(3) + #define PHY_RT_RTL8211F_PAGE_INTR_PIN_ADDR (0xD40) #define PHY_RT_RTL8211F_INTR_PIN_REG (0x16) #define PHY_RT_RTL8211F_INTR_PIN_MASK BIT(5) @@ -475,9 +481,7 @@ static int phy_rt_rtl8211f_init(const struct device *dev) { const struct rt_rtl8211f_config *config = dev->config; struct rt_rtl8211f_data *data = dev->data; -#if DT_ANY_INST_HAS_PROP_STATUS_OKAY(int_gpios) uint32_t reg_val; -#endif /* DT_ANY_INST_HAS_PROP_STATUS_OKAY(int_gpios) */ int ret; data->dev = dev; @@ -506,6 +510,47 @@ static int phy_rt_rtl8211f_init(const struct device *dev) return ret; } + /* Set RGMII Tx/Rx Delay. */ + ret = phy_rt_rtl8211f_write(dev, PHY_RT_RTL8211F_PAGSR_REG, + PHY_RT_RTL8211F_PAGE_MIICR_ADDR); + if (ret) { + LOG_ERR("Error writing phy (%d) page select register", config->addr); + return ret; + } + + ret = phy_rt_rtl8211f_read(dev, PHY_RT_RTL8211F_MIICR1_REG, ®_val); + if (ret) { + LOG_ERR("Error reading phy (%d) mii control register1", config->addr); + return ret; + } + + reg_val |= PHY_RT_RTL8211F_MIICR1_TXDLY_MASK; + ret = phy_rt_rtl8211f_write(dev, PHY_RT_RTL8211F_MIICR1_REG, reg_val); + if (ret) { + LOG_ERR("Error writing phy (%d) mii control register1", config->addr); + return ret; + } + + ret = phy_rt_rtl8211f_read(dev, PHY_RT_RTL8211F_MIICR2_REG, ®_val); + if (ret) { + LOG_ERR("Error reading phy (%d) mii control register2", config->addr); + return ret; + } + + reg_val |= PHY_RT_RTL8211F_MIICR2_RXDLY_MASK; + ret = phy_rt_rtl8211f_write(dev, PHY_RT_RTL8211F_MIICR2_REG, reg_val); + if (ret) { + LOG_ERR("Error writing phy (%d) mii control register2", config->addr); + return ret; + } + + /* Restore to default page 0 */ + ret = phy_rt_rtl8211f_write(dev, PHY_RT_RTL8211F_PAGSR_REG, 0); + if (ret) { + LOG_ERR("Error writing phy (%d) page select register", config->addr); + return ret; + } + k_work_init_delayable(&data->phy_monitor_work, phy_rt_rtl8211f_monitor_work_handler); #if DT_ANY_INST_HAS_PROP_STATUS_OKAY(int_gpios) From 58a54e34523deb9e052bcb5e4381062ac67329d3 Mon Sep 17 00:00:00 2001 From: Marcel Birthelmer Date: Sat, 8 Jun 2024 12:01:58 -0700 Subject: [PATCH 2722/2849] soc: samd51: Fix xosc32 initialization At osc32k_init in the soc_samd5x.c file the start-up value of 7 which is reserved. This fixes the startup timeout and control gain with the correct values. Signed-off-by: Marcel Birthelmer Signed-off-by: Gerson Fernando Budke --- soc/atmel/sam0/common/soc_samd5x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/soc/atmel/sam0/common/soc_samd5x.c b/soc/atmel/sam0/common/soc_samd5x.c index e680163202f59..d8a71386f6616 100644 --- a/soc/atmel/sam0/common/soc_samd5x.c +++ b/soc/atmel/sam0/common/soc_samd5x.c @@ -24,7 +24,7 @@ static void osc32k_init(void) { OSC32KCTRL->XOSC32K.reg = OSC32KCTRL_XOSC32K_ENABLE | OSC32KCTRL_XOSC32K_XTALEN | OSC32KCTRL_XOSC32K_EN32K | OSC32KCTRL_XOSC32K_RUNSTDBY - | OSC32KCTRL_XOSC32K_STARTUP(7); + | OSC32KCTRL_XOSC32K_STARTUP(6) | OSC32KCTRL_XOSC32K_CGM_XT; while (!OSC32KCTRL->STATUS.bit.XOSC32KRDY) { } From a593f344b5428c4a46a36ec2c7893c98f4a90960 Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Tue, 11 Jun 2024 12:00:43 +0000 Subject: [PATCH 2723/2849] tests/storage/flash_map: Fix erase and flatten test Fix offset read for verification and comparison of read to erased value, where type mismatch has been causing fails in comparisons. Fixes #74066 Signed-off-by: Dominik Ermel --- tests/subsys/storage/flash_map/src/main.c | 29 +++++++++++++++-------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/tests/subsys/storage/flash_map/src/main.c b/tests/subsys/storage/flash_map/src/main.c index 18fea4b2421fd..4d219e422c780 100644 --- a/tests/subsys/storage/flash_map/src/main.c +++ b/tests/subsys/storage/flash_map/src/main.c @@ -225,21 +225,28 @@ ZTEST(flash_map, test_flash_area_erase_and_flatten) rc = flash_area_erase(fa, 0, fa->fa_size); zassert_true(rc == 0, "flash area erase fail"); + TC_PRINT("Flash area info:\n"); + TC_PRINT("\tpointer:\t %p\n", &fa); + TC_PRINT("\toffset:\t %ld\n", (long)fa->fa_off); + TC_PRINT("\tsize:\t %ld\n", (long)fa->fa_size); + /* we work under assumption that flash_fill is working and tested */ - for (i = 0; erased && i < fa->fa_size; ++i) { + i = 0; + while (erased && i < fa->fa_size) { uint8_t buf[32]; int chunk = MIN(sizeof(buf), fa->fa_size - i); - rc = flash_read(flash_dev, i, buf, chunk); - zassert_equal(rc, 0, "Unexpected read fail"); + rc = flash_read(flash_dev, fa->fa_off + i, buf, chunk); + zassert_equal(rc, 0, "Unexpected read fail with error %d", rc); for (int ii = 0; ii < chunk; ++ii, ++i) { - if (buf[ii] != flash_area_erased_val(fa)) { + if ((uint8_t)buf[ii] != (uint8_t)flash_area_erased_val(fa)) { erased = false; break; } } } - zassert_true(erased, "Erase failed at index %d", i); + zassert_true(erased, "Erase failed at dev abosolute offset index %d", + i + fa->fa_off); rc = flash_fill(flash_dev, 0xaa, fa->fa_off, fa->fa_size); zassert_true(rc == 0, "flash device fill fail"); @@ -247,20 +254,22 @@ ZTEST(flash_map, test_flash_area_erase_and_flatten) rc = flash_area_flatten(fa, 0, fa->fa_size); erased = true; - for (i = 0; erased && i < fa->fa_size; ++i) { + i = 0; + while (erased && i < fa->fa_size) { uint8_t buf[32]; int chunk = MIN(sizeof(buf), fa->fa_size - i); - rc = flash_read(flash_dev, i, buf, chunk); - zassert_equal(rc, 0, "Unexpected read fail"); + rc = flash_read(flash_dev, fa->fa_off + i, buf, chunk); + zassert_equal(rc, 0, "Unexpected read fail with error %d", rc); for (int ii = 0; ii < chunk; ++ii, ++i) { - if (buf[ii] != flash_area_erased_val(fa)) { + if ((uint8_t)buf[ii] != (uint8_t)flash_area_erased_val(fa)) { erased = false; break; } } } - zassert_true(erased, "Flatten/Erase failed at index %d", i); + zassert_true(erased, "Flatten/Erase failed at dev absolute offset %d", + i + fa->fa_off); } ZTEST_SUITE(flash_map, NULL, NULL, NULL, NULL, NULL); From e98e4ed0672077d20cb5905e7bb297b27f01d98d Mon Sep 17 00:00:00 2001 From: Daniel Leung Date: Thu, 30 May 2024 12:51:27 -0700 Subject: [PATCH 2724/2849] serial: convert kconfig source to rsource Simple cosmetic change to convert all the source commands to rsource so that includes are relative to driver/serial. Signed-off-by: Daniel Leung --- drivers/serial/Kconfig | 128 ++++++++++++++++++++--------------------- 1 file changed, 64 insertions(+), 64 deletions(-) diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index 856b3f2eb89f6..81329bfc6a821 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -150,132 +150,132 @@ config UART_ASYNC_TO_INT_DRIVEN_RX_TIMEOUT comment "Serial Drivers" -source "drivers/serial/Kconfig.b91" +rsource "Kconfig.b91" -source "drivers/serial/Kconfig.ns16550" +rsource "Kconfig.ns16550" -source "drivers/serial/Kconfig.mcux" +rsource "Kconfig.mcux" -source "drivers/serial/Kconfig.mcux_flexcomm" +rsource "Kconfig.mcux_flexcomm" -source "drivers/serial/Kconfig.mcux_iuart" +rsource "Kconfig.mcux_iuart" -source "drivers/serial/Kconfig.mcux_lpsci" +rsource "Kconfig.mcux_lpsci" -source "drivers/serial/Kconfig.mcux_lpuart" +rsource "Kconfig.mcux_lpuart" -source "drivers/serial/Kconfig.miv" +rsource "Kconfig.miv" -source "drivers/serial/Kconfig.imx" +rsource "Kconfig.imx" -source "drivers/serial/Kconfig.it8xxx2" +rsource "Kconfig.it8xxx2" -source "drivers/serial/Kconfig.stellaris" +rsource "Kconfig.stellaris" -source "drivers/serial/Kconfig.native_posix" +rsource "Kconfig.native_posix" -source "drivers/serial/Kconfig.usart_sam" +rsource "Kconfig.usart_sam" -source "drivers/serial/Kconfig.uart_sam" +rsource "Kconfig.uart_sam" -source "drivers/serial/Kconfig.stm32" +rsource "Kconfig.stm32" -source "drivers/serial/Kconfig.nrfx" +rsource "Kconfig.nrfx" -source "drivers/serial/Kconfig.altera_jtag" +rsource "Kconfig.altera_jtag" -source "drivers/serial/Kconfig.cc13xx_cc26xx" +rsource "Kconfig.cc13xx_cc26xx" -source "drivers/serial/Kconfig.cc32xx" +rsource "Kconfig.cc32xx" -source "drivers/serial/Kconfig.cmsdk_apb" +rsource "Kconfig.cmsdk_apb" -source "drivers/serial/Kconfig.sifive" +rsource "Kconfig.sifive" -source "drivers/serial/Kconfig.esp32" +rsource "Kconfig.esp32" -source "drivers/serial/Kconfig.gecko" +rsource "Kconfig.gecko" -source "drivers/serial/Kconfig.leuart_gecko" +rsource "Kconfig.leuart_gecko" -source "drivers/serial/Kconfig.msp432p4xx" +rsource "Kconfig.msp432p4xx" -source "drivers/serial/Kconfig.numicro" +rsource "Kconfig.numicro" -source "drivers/serial/Kconfig.sam0" +rsource "Kconfig.sam0" -source "drivers/serial/Kconfig.psoc6" +rsource "Kconfig.psoc6" -source "drivers/serial/Kconfig.pl011" +rsource "Kconfig.pl011" -source "drivers/serial/Kconfig.ql_usbserialport_s3b" +rsource "Kconfig.ql_usbserialport_s3b" -source "drivers/serial/Kconfig.rv32m1_lpuart" +rsource "Kconfig.rv32m1_lpuart" -source "drivers/serial/Kconfig.rpi_pico" +rsource "Kconfig.rpi_pico" -source "drivers/serial/Kconfig.litex" +rsource "Kconfig.litex" -source "drivers/serial/Kconfig.rtt" +rsource "Kconfig.rtt" -source "drivers/serial/Kconfig.bt" +rsource "Kconfig.bt" -source "drivers/serial/Kconfig.xlnx" +rsource "Kconfig.xlnx" -source "drivers/serial/Kconfig.xmc4xxx" +rsource "Kconfig.xmc4xxx" -source "drivers/serial/Kconfig.lpc11u6x" +rsource "Kconfig.lpc11u6x" -source "drivers/serial/Kconfig.npcx" +rsource "Kconfig.npcx" -source "drivers/serial/Kconfig.apbuart" +rsource "Kconfig.apbuart" -source "drivers/serial/Kconfig.rcar" +rsource "Kconfig.rcar" -source "drivers/serial/Kconfig.xec" +rsource "Kconfig.xec" -source "drivers/serial/Kconfig.gd32" +rsource "Kconfig.gd32" -source "drivers/serial/Kconfig.test" +rsource "Kconfig.test" -source "drivers/serial/Kconfig.neorv32" +rsource "Kconfig.neorv32" -source "drivers/serial/Kconfig.xen" +rsource "Kconfig.xen" -source "drivers/serial/Kconfig.ifx_cat1" +rsource "Kconfig.ifx_cat1" -source "drivers/serial/Kconfig.smartbond" +rsource "Kconfig.smartbond" -source "drivers/serial/Kconfig.nxp_s32" +rsource "Kconfig.nxp_s32" -source "drivers/serial/Kconfig.cdns" +rsource "Kconfig.cdns" -source "drivers/serial/Kconfig.opentitan" +rsource "Kconfig.opentitan" -source "drivers/serial/Kconfig.altera" +rsource "Kconfig.altera" -source "drivers/serial/Kconfig.hostlink" +rsource "Kconfig.hostlink" -source "drivers/serial/Kconfig.emul" +rsource "Kconfig.emul" -source "drivers/serial/Kconfig.native_tty" +rsource "Kconfig.native_tty" -source "drivers/serial/Kconfig.numaker" +rsource "Kconfig.numaker" -source "drivers/serial/Kconfig.efinix_sapphire" +rsource "Kconfig.efinix_sapphire" -source "drivers/serial/Kconfig.sedi" +rsource "Kconfig.sedi" -source "drivers/serial/Kconfig.max32" +rsource "Kconfig.max32" -source "drivers/serial/Kconfig.bcm2711" +rsource "Kconfig.bcm2711" -source "drivers/serial/Kconfig.intel_lw" +rsource "Kconfig.intel_lw" -source "drivers/serial/Kconfig.renesas_ra" +rsource "Kconfig.renesas_ra" -source "drivers/serial/Kconfig.ene" +rsource "Kconfig.ene" -source "drivers/serial/Kconfig.rzt2m" +rsource "Kconfig.rzt2m" endif # SERIAL From 6f215526d702cb0544ee75789c2065e2eba15bfc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sigmund=20Kl=C3=A5pbakken?= Date: Wed, 15 May 2024 12:41:09 +0200 Subject: [PATCH 2725/2849] runners: jlink: Add support for big endian device MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sets the endianness of the JLink and the GDB Server based on if `CONFIG_BIG_ENDIAN` is set. Doc on JLink LE/BE option: https://wiki.segger.com/J-Link_Commander#LE Doc on GDB server -endian option: https://wiki.segger.com/J-Link_GDB_Server#-endian Signed-off-by: Sigmund Klåpbakken --- scripts/west_commands/runners/jlink.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/scripts/west_commands/runners/jlink.py b/scripts/west_commands/runners/jlink.py index 17d6078774595..5670cd374c810 100644 --- a/scripts/west_commands/runners/jlink.py +++ b/scripts/west_commands/runners/jlink.py @@ -233,6 +233,7 @@ def do_run(self, command, **kwargs): rtos = self.thread_info_enabled and self.supports_thread_info plugin_dir = os.fspath(Path(self.commander).parent / 'GDBServer' / 'RTOSPlugin_Zephyr') + big_endian = self.build_conf.getboolean('CONFIG_BIG_ENDIAN') server_cmd = ([self.gdbserver] + ['-select', @@ -243,6 +244,7 @@ def do_run(self, command, **kwargs): '-speed', self.speed, '-device', self.device, '-silent', + '-endian', 'big' if big_endian else 'little', '-singlerun'] + (['-nogui'] if self.supports_nogui else []) + (['-rtos', plugin_dir] if rtos else []) + @@ -290,6 +292,7 @@ def flash(self, **kwargs): lines = [ 'ExitOnError 1', # Treat any command-error as fatal 'r', # Reset and halt the target + 'BE' if self.build_conf.getboolean('CONFIG_BIG_ENDIAN') else 'LE' ] if self.erase: From ddef306394fa48fe0f01aa213767d69da7971ac0 Mon Sep 17 00:00:00 2001 From: Thibo Verheyde Date: Wed, 8 May 2024 09:35:08 +0200 Subject: [PATCH 2726/2849] drivers: serial: esp32: Fix next buffer release on rx disable Set event data rx buffer as next buffer instead of current buffer. Signed-off-by: Thibo Verheyde --- drivers/serial/uart_esp32.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/serial/uart_esp32.c b/drivers/serial/uart_esp32.c index 48f213c7394c9..0bbc3fb4d2d1d 100644 --- a/drivers/serial/uart_esp32.c +++ b/drivers/serial/uart_esp32.c @@ -888,7 +888,7 @@ static int uart_esp32_async_rx_disable(const struct device *dev) /*Release next buffer*/ if (data->async.rx_next_len) { evt.type = UART_RX_BUF_RELEASED; - evt.data.rx_buf.buf = data->async.rx_buf; + evt.data.rx_buf.buf = data->async.rx_next_buf; if (data->async.cb) { data->async.cb(dev, &evt, data->async.user_data); } From 86fa756ddeaf0bcb501853ead53a1b8848b597bd Mon Sep 17 00:00:00 2001 From: Jeppe Odgaard Date: Wed, 1 May 2024 09:17:06 +0200 Subject: [PATCH 2727/2849] tests: drivers: dac: use zassert_ok Replace `zassert_equal` with `zassert_ok` where return value contains 0 or errno. Signed-off-by: Jeppe Odgaard --- tests/drivers/dac/dac_api/src/test_dac.c | 5 ++--- tests/drivers/dac/dac_loopback/src/test_dac.c | 10 ++++------ 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/tests/drivers/dac/dac_api/src/test_dac.c b/tests/drivers/dac/dac_api/src/test_dac.c index 8c32f756f44a6..134b9fcc46c77 100644 --- a/tests/drivers/dac/dac_api/src/test_dac.c +++ b/tests/drivers/dac/dac_api/src/test_dac.c @@ -119,8 +119,7 @@ static const struct device *init_dac(void) zassert_true(device_is_ready(dac_dev), "DAC device is not ready"); ret = dac_channel_setup(dac_dev, &dac_ch_cfg); - zassert_equal(ret, 0, - "Setting up of the first channel failed with code %d", ret); + zassert_ok(ret, "Setting up of the first channel failed with code %d", ret); return dac_dev; } @@ -137,7 +136,7 @@ ZTEST(dac, test_task_write_value) /* write a value of half the full scale resolution */ ret = dac_write_value(dac_dev, DAC_CHANNEL_ID, (1U << DAC_RESOLUTION) / 2); - zassert_equal(ret, 0, "dac_write_value() failed with code %d", ret); + zassert_ok(ret, "dac_write_value() failed with code %d", ret); } static void *dac_setup(void) diff --git a/tests/drivers/dac/dac_loopback/src/test_dac.c b/tests/drivers/dac/dac_loopback/src/test_dac.c index 38d71c4b8a1dd..55fb22b44ae4a 100644 --- a/tests/drivers/dac/dac_loopback/src/test_dac.c +++ b/tests/drivers/dac/dac_loopback/src/test_dac.c @@ -198,8 +198,7 @@ static const struct device *init_dac(void) zassert_true(device_is_ready(dac_dev), "DAC device is not ready"); ret = dac_channel_setup(dac_dev, &dac_ch_cfg); - zassert_equal(ret, 0, - "Setting up of the first channel failed with code %d", ret); + zassert_ok(ret, "Setting up of the first channel failed with code %d", ret); return dac_dev; } @@ -213,8 +212,7 @@ static const struct device *init_adc(void) zassert_true(device_is_ready(adc_dev), "ADC device is not ready"); ret = adc_channel_setup(adc_dev, &adc_ch_cfg); - zassert_equal(ret, 0, - "Setting up of the ADC channel failed with code %d", ret); + zassert_ok(ret, "Setting up of the ADC channel failed with code %d", ret); return adc_dev; } @@ -236,7 +234,7 @@ static int test_task_loopback(void) /* write a value of half the full scale resolution */ ret = dac_write_value(dac_dev, DAC_CHANNEL_ID, (1U << DAC_RESOLUTION) / 2); - zassert_equal(ret, 0, "dac_write_value() failed with code %d", ret); + zassert_ok(ret, "dac_write_value() failed with code %d", ret); /* wait to let DAC output settle */ k_sleep(K_MSEC(10)); @@ -250,7 +248,7 @@ static int test_task_loopback(void) }; ret = adc_read(adc_dev, &sequence); - zassert_equal(ret, 0, "adc_read() failed with code %d", ret); + zassert_ok(ret, "adc_read() failed with code %d", ret); zassert_within(m_sample_buffer[0], (1U << ADC_RESOLUTION) / 2, 32, "Value %d read from ADC does not match expected range.", From ec72339d6194620fbadeb85b8219bd2dc2e3a13f Mon Sep 17 00:00:00 2001 From: Evgeniy Paltsev Date: Tue, 11 Jun 2024 21:45:21 +0100 Subject: [PATCH 2728/2849] ARC: enable barriers for HS As we start to use data memory barriers in SMP scheduler code explicitly (not only internaly in the atomics implementation) let's enable barriers for ARC HS. Signed-off-by: Eugeniy Paltsev Signed-off-by: Evgeniy Paltsev --- arch/arc/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arc/Kconfig b/arch/arc/Kconfig index 8a3bd5b1b3c2a..bd1b30517d4eb 100644 --- a/arch/arc/Kconfig +++ b/arch/arc/Kconfig @@ -18,6 +18,7 @@ config CPU_ARCEM config CPU_ARCHS bool select ATOMIC_OPERATIONS_BUILTIN + select BARRIER_OPERATIONS_BUILTIN help This option signifies the use of an ARC HS CPU From a9f7788f9f44e8363d650c345f55a59ce8337258 Mon Sep 17 00:00:00 2001 From: Valerio Setti Date: Tue, 4 Jun 2024 13:44:57 +0200 Subject: [PATCH 2729/2849] trusted-firmware-m: select PSA_CRYPTO_CLIENT when BUILD_WITH_TFM TF-M is a PSA API provider alternative to Mbed TLS one. As a consequence when CONFIG_BUILD_WITH_TFM is set CONFIG_PSA_CRYPTO_CLIENT should be set as well. Signed-off-by: Valerio Setti --- 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 b90390f3d043e..8834256ccbb56 100644 --- a/modules/trusted-firmware-m/Kconfig.tfm +++ b/modules/trusted-firmware-m/Kconfig.tfm @@ -30,6 +30,7 @@ menuconfig BUILD_WITH_TFM depends on TFM_BOARD != "" depends on ARM_TRUSTZONE_M select BUILD_OUTPUT_HEX + select PSA_CRYPTO_CLIENT imply INIT_ARCH_HW_AT_BOOT imply ARM_NONSECURE_PREEMPTIBLE_SECURE_CALLS imply MBEDTLS From 9032f8d791cd3d9d1f14d59390845dc8c760a8c3 Mon Sep 17 00:00:00 2001 From: Valerio Setti Date: Tue, 28 May 2024 07:36:47 +0200 Subject: [PATCH 2730/2849] bt-crypto: add option to use PSA APIs instead of TinyCrypt This commit adds CONFIG_BT_USE_PSA_API to allow the end user to prefer PSA APIs over TinyCrypt for crypto operations in bluetooth. Of course, this is possible only if a PSA provider is available on the system, i.e. CONFIG_PSA_CRYPTO_CLIENT is set. This commit also extends tests/bluetooth/bt_crypto adding a test case for PSA. Signed-off-by: Valerio Setti --- subsys/bluetooth/Kconfig | 7 ++++ subsys/bluetooth/crypto/CMakeLists.txt | 10 +++++ subsys/bluetooth/crypto/Kconfig | 8 ++-- subsys/bluetooth/crypto/bt_crypto.c | 25 ++---------- subsys/bluetooth/crypto/bt_crypto_psa.c | 46 ++++++++++++++++++++++ subsys/bluetooth/crypto/bt_crypto_tc.c | 34 ++++++++++++++++ tests/bluetooth/bt_crypto/testcase.yaml | 16 ++++++++ tests/bluetooth/host/crypto/CMakeLists.txt | 2 +- 8 files changed, 123 insertions(+), 25 deletions(-) create mode 100644 subsys/bluetooth/crypto/bt_crypto_psa.c create mode 100644 subsys/bluetooth/crypto/bt_crypto_tc.c diff --git a/subsys/bluetooth/Kconfig b/subsys/bluetooth/Kconfig index 5e1de57db0802..9a9b91f2b18de 100644 --- a/subsys/bluetooth/Kconfig +++ b/subsys/bluetooth/Kconfig @@ -192,6 +192,13 @@ rsource "crypto/Kconfig" rsource "lib/Kconfig" rsource "Kconfig.logging" +config BT_USE_PSA_API + bool "Use PSA APIs instead of TinyCrypt for crypto operations" + depends on BT_CRYPTO || BT_HOST_CRYPTO + depends on PSA_CRYPTO_CLIENT + help + Use PSA APIs instead of TinyCrypt for crypto operations + endif # BT_HCI config BT_COMPANY_ID diff --git a/subsys/bluetooth/crypto/CMakeLists.txt b/subsys/bluetooth/crypto/CMakeLists.txt index 9228fc9fd0b85..dc0f83b32c271 100644 --- a/subsys/bluetooth/crypto/CMakeLists.txt +++ b/subsys/bluetooth/crypto/CMakeLists.txt @@ -4,6 +4,16 @@ zephyr_library() zephyr_library_sources(bt_crypto.c) +if(CONFIG_BT_USE_PSA_API) + zephyr_library_sources(bt_crypto_psa.c) + zephyr_library_link_libraries_ifdef(CONFIG_MBEDTLS mbedTLS) + zephyr_library_include_directories_ifdef(CONFIG_BUILD_WITH_TFM + $/api_ns/interface/include + ) +else() + zephyr_library_sources(bt_crypto_tc.c) +endif() + if(CONFIG_BT_CRYPTO_LOG_LEVEL_DBG) message(WARNING "CONFIG_BT_CRYPTO_LOG_LEVEL_DBG is enabled. Private security keys such as the Long Term Key will be printed out. diff --git a/subsys/bluetooth/crypto/Kconfig b/subsys/bluetooth/crypto/Kconfig index ccf5a8b641b4b..a59979730f0d5 100644 --- a/subsys/bluetooth/crypto/Kconfig +++ b/subsys/bluetooth/crypto/Kconfig @@ -3,8 +3,10 @@ config BT_CRYPTO bool - select TINYCRYPT - select TINYCRYPT_AES - select TINYCRYPT_AES_CMAC + select TINYCRYPT if !BT_USE_PSA_API + select TINYCRYPT_AES if !BT_USE_PSA_API + select TINYCRYPT_AES_CMAC if !BT_USE_PSA_API + select PSA_WANT_KEY_TYPE_AES if BT_USE_PSA_API + select PSA_WANT_ALG_CMAC if BT_USE_PSA_API help This option enables the Bluetooth Cryptographic Toolbox. diff --git a/subsys/bluetooth/crypto/bt_crypto.c b/subsys/bluetooth/crypto/bt_crypto.c index 8b098d7cc2838..62a475a57d751 100644 --- a/subsys/bluetooth/crypto/bt_crypto.c +++ b/subsys/bluetooth/crypto/bt_crypto.c @@ -7,8 +7,12 @@ #include +#if defined(CONFIG_BT_USE_PSA_API) +#include "psa/crypto.h" +#else #include #include +#endif #include "common/bt_str.h" #include "bt_crypto.h" @@ -17,27 +21,6 @@ #include LOG_MODULE_REGISTER(bt_crypto); - -int bt_crypto_aes_cmac(const uint8_t *key, const uint8_t *in, size_t len, uint8_t *out) -{ - struct tc_aes_key_sched_struct sched; - struct tc_cmac_struct state; - - if (tc_cmac_setup(&state, key, &sched) == TC_CRYPTO_FAIL) { - return -EIO; - } - - if (tc_cmac_update(&state, in, len) == TC_CRYPTO_FAIL) { - return -EIO; - } - - if (tc_cmac_final(out, &state) == TC_CRYPTO_FAIL) { - return -EIO; - } - - return 0; -} - int bt_crypto_f4(const uint8_t *u, const uint8_t *v, const uint8_t *x, uint8_t z, uint8_t res[16]) { uint8_t xs[16]; diff --git a/subsys/bluetooth/crypto/bt_crypto_psa.c b/subsys/bluetooth/crypto/bt_crypto_psa.c new file mode 100644 index 0000000000000..8e92bc9ec6918 --- /dev/null +++ b/subsys/bluetooth/crypto/bt_crypto_psa.c @@ -0,0 +1,46 @@ +/* Copyright (c) 2022 Nordic Semiconductor ASA + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +#include + +#include "psa/crypto.h" + +#include "common/bt_str.h" +#include "bt_crypto.h" + +#define LOG_LEVEL CONFIG_BT_CRYPTO_LOG_LEVEL +#include +LOG_MODULE_DECLARE(bt_crypto); + +int bt_crypto_aes_cmac(const uint8_t *key, const uint8_t *in, size_t len, uint8_t *out) +{ + psa_key_id_t key_id; + psa_key_attributes_t key_attr = PSA_KEY_ATTRIBUTES_INIT; + size_t out_size; + psa_status_t status, destroy_status; + + psa_set_key_type(&key_attr, PSA_KEY_TYPE_AES); + psa_set_key_bits(&key_attr, 128); + psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_SIGN_MESSAGE | + PSA_KEY_USAGE_VERIFY_MESSAGE); + psa_set_key_algorithm(&key_attr, PSA_ALG_CMAC); + + status = psa_import_key(&key_attr, key, 16, &key_id); + if (status != PSA_SUCCESS) { + LOG_ERR("Failed to import AES key %d", status); + return -EIO; + } + + status = psa_mac_compute(key_id, PSA_ALG_CMAC, in, len, out, 16, &out_size); + destroy_status = psa_destroy_key(key_id); + if ((status != PSA_SUCCESS) || (destroy_status != PSA_SUCCESS)) { + LOG_ERR("Failed to compute MAC %d", status); + return -EIO; + } + + return 0; +} diff --git a/subsys/bluetooth/crypto/bt_crypto_tc.c b/subsys/bluetooth/crypto/bt_crypto_tc.c new file mode 100644 index 0000000000000..95160d55dfd9e --- /dev/null +++ b/subsys/bluetooth/crypto/bt_crypto_tc.c @@ -0,0 +1,34 @@ +/* Copyright (c) 2022 Nordic Semiconductor ASA + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +#include + +#include +#include + +#include "common/bt_str.h" +#include "bt_crypto.h" + +int bt_crypto_aes_cmac(const uint8_t *key, const uint8_t *in, size_t len, uint8_t *out) +{ + struct tc_aes_key_sched_struct sched; + struct tc_cmac_struct state; + + if (tc_cmac_setup(&state, key, &sched) == TC_CRYPTO_FAIL) { + return -EIO; + } + + if (tc_cmac_update(&state, in, len) == TC_CRYPTO_FAIL) { + return -EIO; + } + + if (tc_cmac_final(out, &state) == TC_CRYPTO_FAIL) { + return -EIO; + } + + return 0; +} diff --git a/tests/bluetooth/bt_crypto/testcase.yaml b/tests/bluetooth/bt_crypto/testcase.yaml index 430d763d0cb23..ba93346259062 100644 --- a/tests/bluetooth/bt_crypto/testcase.yaml +++ b/tests/bluetooth/bt_crypto/testcase.yaml @@ -12,3 +12,19 @@ tests: integration_platforms: - native_sim tags: bluetooth + bluetooth.bt_crypto.psa: + filter: CONFIG_PSA_CRYPTO_CLIENT + extra_args: + - EXTRA_DTC_OVERLAY_FILE="test.overlay" + platform_allow: + - native_posix + - native_posix/native/64 + - native_sim + - native_sim/native/64 + - qemu_x86 + - qemu_cortex_m3 + - nrf5340dk/nrf5340/cpuapp/ns + - nrf52840dk/nrf52840 + integration_platforms: + - native_sim + tags: bluetooth diff --git a/tests/bluetooth/host/crypto/CMakeLists.txt b/tests/bluetooth/host/crypto/CMakeLists.txt index 1a8ae2f5a5004..856b27562822a 100644 --- a/tests/bluetooth/host/crypto/CMakeLists.txt +++ b/tests/bluetooth/host/crypto/CMakeLists.txt @@ -12,7 +12,7 @@ add_library(mocks STATIC mocks/hmac_prng_expects.c mocks/crypto_help_utils.c - ${ZEPHYR_BASE}/subsys/bluetooth/host/crypto.c + ${ZEPHYR_BASE}/subsys/bluetooth/host/crypto_tc.c ${ZEPHYR_BASE}/subsys/logging/log_minimal.c ${ZEPHYR_BASE}/subsys/bluetooth/common/bt_str.c ${ZEPHYR_BASE}/subsys/bluetooth/host/uuid.c From 814b2ed45704ac974f92e632c3351fccfb067e37 Mon Sep 17 00:00:00 2001 From: Valerio Setti Date: Tue, 4 Jun 2024 13:47:34 +0200 Subject: [PATCH 2731/2849] bt-host: add option to use PSA APIs instead of TinyCrypt By enabling CONFIG_BT_USE_PSA_API the user can specify to use PSA APIs instead of TinyCrypt for crypto operations in bluetooth host module. This commit also extends tests/bluetooth/gatt in order to add a PSA test. Signed-off-by: Valerio Setti --- subsys/bluetooth/host/CMakeLists.txt | 18 ++- subsys/bluetooth/host/Kconfig | 11 +- subsys/bluetooth/host/Kconfig.gatt | 8 +- subsys/bluetooth/host/crypto_psa.c | 151 ++++++++++++++++++ .../bluetooth/host/{crypto.c => crypto_tc.c} | 0 subsys/bluetooth/host/gatt.c | 113 +++++++++++-- tests/bluetooth/gatt/testcase.yaml | 18 +++ 7 files changed, 292 insertions(+), 27 deletions(-) create mode 100644 subsys/bluetooth/host/crypto_psa.c rename subsys/bluetooth/host/{crypto.c => crypto_tc.c} (100%) diff --git a/subsys/bluetooth/host/CMakeLists.txt b/subsys/bluetooth/host/CMakeLists.txt index 56cdfb045750f..ae574e2b5bfa6 100644 --- a/subsys/bluetooth/host/CMakeLists.txt +++ b/subsys/bluetooth/host/CMakeLists.txt @@ -31,10 +31,13 @@ if(CONFIG_BT_HCI_HOST) CONFIG_BT_OBSERVER scan.c ) - zephyr_library_sources_ifdef( - CONFIG_BT_HOST_CRYPTO - crypto.c - ) + + if(CONFIG_BT_USE_PSA_API) + zephyr_library_sources_ifdef(CONFIG_BT_HOST_CRYPTO crypto_psa.c) + else() + zephyr_library_sources_ifdef(CONFIG_BT_HOST_CRYPTO crypto_tc.c) + endif() + zephyr_library_sources_ifdef( CONFIG_BT_ECC ecc.c @@ -108,6 +111,13 @@ if(CONFIG_BT_CONN_DISABLE_SECURITY) ) endif() +if(CONFIG_BT_USE_PSA_API) + zephyr_library_link_libraries_ifdef(CONFIG_MBEDTLS mbedTLS) + zephyr_library_include_directories_ifdef(CONFIG_BUILD_WITH_TFM + $/api_ns/interface/include + ) +endif() + # Bluetooth Mesh has test dependencies in the host. # In order to compile Bsim tests with these test features # and PSA enabled, the libraries must be linked. diff --git a/subsys/bluetooth/host/Kconfig b/subsys/bluetooth/host/Kconfig index f9bbac130ccc8..49277097da966 100644 --- a/subsys/bluetooth/host/Kconfig +++ b/subsys/bluetooth/host/Kconfig @@ -139,8 +139,9 @@ rsource "../audio/Kconfig" config BT_HOST_CRYPTO bool "Use crypto functionality implemented in the Bluetooth host" default y if !BT_CTLR_CRYPTO - select TINYCRYPT - select TINYCRYPT_AES + select TINYCRYPT if !BT_USE_PSA_API + select TINYCRYPT_AES if !BT_USE_PSA_API + select PSA_WANT_KEY_TYPE_AES if BT_USE_PSA_API help The option adds the AES encryption support using TinyCrypt library if this is not provided by the controller implementation. @@ -148,9 +149,9 @@ config BT_HOST_CRYPTO config BT_HOST_CRYPTO_PRNG bool "Use Tinycrypt library for random number generation" default y - select TINYCRYPT_SHA256 - select TINYCRYPT_SHA256_HMAC - select TINYCRYPT_SHA256_HMAC_PRNG + select TINYCRYPT_SHA256 if !BT_USE_PSA_API + select TINYCRYPT_SHA256_HMAC if !BT_USE_PSA_API + select TINYCRYPT_SHA256_HMAC_PRNG if !BT_USE_PSA_API depends on BT_HOST_CRYPTO help When selected, will use tinycrypt library for random number generation. diff --git a/subsys/bluetooth/host/Kconfig.gatt b/subsys/bluetooth/host/Kconfig.gatt index 310442423b9cc..45e3fa8e4fca0 100644 --- a/subsys/bluetooth/host/Kconfig.gatt +++ b/subsys/bluetooth/host/Kconfig.gatt @@ -107,9 +107,11 @@ config BT_GATT_CACHING bool "GATT Caching support" default y depends on BT_GATT_SERVICE_CHANGED - select TINYCRYPT - select TINYCRYPT_AES - select TINYCRYPT_AES_CMAC + select TINYCRYPT if !BT_USE_PSA_API + select TINYCRYPT_AES if !BT_USE_PSA_API + select TINYCRYPT_AES_CMAC if !BT_USE_PSA_API + select PSA_WANT_KEY_TYPE_AES if BT_USE_PSA_API + select PSA_WANT_ALG_CMAC if BT_USE_PSA_API help This option enables support for GATT Caching. When enabled the stack will register Client Supported Features and Database Hash diff --git a/subsys/bluetooth/host/crypto_psa.c b/subsys/bluetooth/host/crypto_psa.c new file mode 100644 index 0000000000000..041a2f9cd047e --- /dev/null +++ b/subsys/bluetooth/host/crypto_psa.c @@ -0,0 +1,151 @@ +/* + * Copyright (c) 2017 Nordic Semiconductor ASA + * Copyright (c) 2015-2016 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +#include +#include +#include + +#include +#include +#include +#include + +#include "psa/crypto.h" + +#include "common/bt_str.h" + +#include "hci_core.h" + +#define LOG_LEVEL CONFIG_BT_HCI_CORE_LOG_LEVEL +#include +LOG_MODULE_REGISTER(bt_host_crypto); + +int prng_init(void) +{ + if (psa_crypto_init() != PSA_SUCCESS) { + return -EIO; + } + return 0; +} + +#if defined(CONFIG_BT_HOST_CRYPTO_PRNG) +int bt_rand(void *buf, size_t len) +{ + if (psa_generate_random(buf, len) == PSA_SUCCESS) { + return 0; + } + + return -EIO; +} +#else /* !CONFIG_BT_HOST_CRYPTO_PRNG */ +int bt_rand(void *buf, size_t len) +{ + CHECKIF(buf == NULL || len == 0) { + return -EINVAL; + } + + return bt_hci_le_rand(buf, len); +} +#endif /* CONFIG_BT_HOST_CRYPTO_PRNG */ + +int bt_encrypt_le(const uint8_t key[16], const uint8_t plaintext[16], + uint8_t enc_data[16]) +{ + psa_key_attributes_t attr = PSA_KEY_ATTRIBUTES_INIT; + psa_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT; + psa_status_t status, destroy_status; + size_t out_len; + uint8_t tmp[16]; + + CHECKIF(key == NULL || plaintext == NULL || enc_data == NULL) { + return -EINVAL; + } + + LOG_DBG("key %s", bt_hex(key, 16)); + LOG_DBG("plaintext %s", bt_hex(plaintext, 16)); + + sys_memcpy_swap(tmp, key, 16); + + psa_set_key_type(&attr, PSA_KEY_TYPE_AES); + psa_set_key_bits(&attr, 128); + psa_set_key_usage_flags(&attr, PSA_KEY_USAGE_ENCRYPT); + psa_set_key_algorithm(&attr, PSA_ALG_ECB_NO_PADDING); + if (psa_import_key(&attr, tmp, 16, &key_id) != PSA_SUCCESS) { + LOG_ERR("Failed to import AES key"); + return -EINVAL; + } + + sys_memcpy_swap(tmp, plaintext, 16); + + status = psa_cipher_encrypt(key_id, PSA_ALG_ECB_NO_PADDING, tmp, 16, + enc_data, 16, &out_len); + if (status != PSA_SUCCESS) { + LOG_ERR("AES encryption failed"); + } + + destroy_status = psa_destroy_key(key_id); + if (destroy_status != PSA_SUCCESS) { + LOG_ERR("Failed to destroy AES key"); + } + + if ((status != PSA_SUCCESS) || (destroy_status != PSA_SUCCESS)) { + return -EIO; + } + + sys_mem_swap(enc_data, 16); + + LOG_DBG("enc_data %s", bt_hex(enc_data, 16)); + + return 0; +} + +int bt_encrypt_be(const uint8_t key[16], const uint8_t plaintext[16], + uint8_t enc_data[16]) +{ + psa_key_attributes_t attr = PSA_KEY_ATTRIBUTES_INIT; + psa_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT; + psa_status_t status, destroy_status; + size_t out_len; + + CHECKIF(key == NULL || plaintext == NULL || enc_data == NULL) { + return -EINVAL; + } + + LOG_DBG("key %s", bt_hex(key, 16)); + LOG_DBG("plaintext %s", bt_hex(plaintext, 16)); + + psa_set_key_type(&attr, PSA_KEY_TYPE_AES); + psa_set_key_bits(&attr, 128); + psa_set_key_usage_flags(&attr, PSA_KEY_USAGE_ENCRYPT); + psa_set_key_algorithm(&attr, PSA_ALG_ECB_NO_PADDING); + if (psa_import_key(&attr, key, 16, &key_id) != PSA_SUCCESS) { + LOG_ERR("Failed to import AES key"); + return -EINVAL; + } + + status = psa_cipher_encrypt(key_id, PSA_ALG_ECB_NO_PADDING, + plaintext, 16, enc_data, 16, &out_len); + if (status != PSA_SUCCESS) { + LOG_ERR("AES encryption failed"); + } + + destroy_status = psa_destroy_key(key_id); + if (destroy_status != PSA_SUCCESS) { + LOG_ERR("Failed to destroy AES key"); + } + + if ((status != PSA_SUCCESS) || (destroy_status != PSA_SUCCESS)) { + return -EIO; + } + + LOG_DBG("enc_data %s", bt_hex(enc_data, 16)); + + return 0; +} diff --git a/subsys/bluetooth/host/crypto.c b/subsys/bluetooth/host/crypto_tc.c similarity index 100% rename from subsys/bluetooth/host/crypto.c rename to subsys/bluetooth/host/crypto_tc.c diff --git a/subsys/bluetooth/host/gatt.c b/subsys/bluetooth/host/gatt.c index 6a967f9672a07..19c71087b42c5 100644 --- a/subsys/bluetooth/host/gatt.c +++ b/subsys/bluetooth/host/gatt.c @@ -21,11 +21,15 @@ #include #if defined(CONFIG_BT_GATT_CACHING) +#if defined(CONFIG_BT_USE_PSA_API) +#include "psa/crypto.h" +#else /* CONFIG_BT_USE_PSA_API */ #include #include #include #include #include +#endif /* CONFIG_BT_USE_PSA_API */ #endif /* CONFIG_BT_GATT_CACHING */ #include @@ -693,11 +697,93 @@ static ssize_t cf_write(struct bt_conn *conn, const struct bt_gatt_attr *attr, return len; } +#if defined(CONFIG_BT_USE_PSA_API) +struct gen_hash_state { + psa_mac_operation_t operation; + psa_key_id_t key; + int err; +}; + +static int db_hash_setup(struct gen_hash_state *state, uint8_t *key) +{ + psa_key_attributes_t key_attr = PSA_KEY_ATTRIBUTES_INIT; + + psa_set_key_type(&key_attr, PSA_KEY_TYPE_AES); + psa_set_key_bits(&key_attr, 128); + psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_SIGN_MESSAGE); + psa_set_key_algorithm(&key_attr, PSA_ALG_CMAC); + + if (psa_import_key(&key_attr, key, 16, &(state->key)) != PSA_SUCCESS) { + LOG_ERR("Unable to import the key for AES CMAC"); + return -EIO; + } + state->operation = psa_mac_operation_init(); + if (psa_mac_sign_setup(&(state->operation), state->key, + PSA_ALG_CMAC) != PSA_SUCCESS) { + LOG_ERR("CMAC operation init failed"); + return -EIO; + } + return 0; +} + +static int db_hash_update(struct gen_hash_state *state, uint8_t *data, size_t len) +{ + if (psa_mac_update(&(state->operation), data, len) != PSA_SUCCESS) { + LOG_ERR("CMAC update failed"); + return -EIO; + } + return 0; +} + +static int db_hash_finish(struct gen_hash_state *state) +{ + size_t mac_length; + + if (psa_mac_sign_finish(&(state->operation), db_hash.hash, 16, + &mac_length) != PSA_SUCCESS) { + LOG_ERR("CMAC finish failed"); + return -EIO; + } + return 0; +} + +#else /* CONFIG_BT_USE_PSA_API */ struct gen_hash_state { struct tc_cmac_struct state; + struct tc_aes_key_sched_struct sched; int err; }; +static int db_hash_setup(struct gen_hash_state *state, uint8_t *key) +{ + if (tc_cmac_setup(&(state->state), key, &(state->sched)) == TC_CRYPTO_FAIL) { + LOG_ERR("CMAC setup failed"); + return -EIO; + } + return 0; +} + +static int db_hash_update(struct gen_hash_state *state, uint8_t *data, size_t len) +{ + if (tc_cmac_update(&state->state, data, len) == TC_CRYPTO_FAIL) { + LOG_ERR("CMAC update failed"); + return -EIO; + } + return 0; +} + +static int db_hash_finish(struct gen_hash_state *state) +{ + if (tc_cmac_final(db_hash.hash, &(state->state)) == TC_CRYPTO_FAIL) { + LOG_ERR("CMAC finish failed"); + return -EIO; + } + return 0; +} + + +#endif /* CONFIG_BT_USE_PSA_API */ + union hash_attr_value { /* Bluetooth Core Specification Version 5.3 | Vol 3, Part G * Table 3.1: Service declaration @@ -755,15 +841,15 @@ static uint8_t gen_hash_m(const struct bt_gatt_attr *attr, uint16_t handle, case BT_UUID_GATT_CHRC_VAL: case BT_UUID_GATT_CEP_VAL: value = sys_cpu_to_le16(handle); - if (tc_cmac_update(&state->state, (uint8_t *)&value, - sizeof(handle)) == TC_CRYPTO_FAIL) { + if (db_hash_update(state, (uint8_t *)&value, + sizeof(handle)) != 0) { state->err = -EINVAL; return BT_GATT_ITER_STOP; } value = sys_cpu_to_le16(u16->val); - if (tc_cmac_update(&state->state, (uint8_t *)&value, - sizeof(u16->val)) == TC_CRYPTO_FAIL) { + if (db_hash_update(state, (uint8_t *)&value, + sizeof(u16->val)) != 0) { state->err = -EINVAL; return BT_GATT_ITER_STOP; } @@ -774,8 +860,7 @@ static uint8_t gen_hash_m(const struct bt_gatt_attr *attr, uint16_t handle, return BT_GATT_ITER_STOP; } - if (tc_cmac_update(&state->state, data, len) == - TC_CRYPTO_FAIL) { + if (db_hash_update(state, data, len) != 0) { state->err = -EINVAL; return BT_GATT_ITER_STOP; } @@ -788,18 +873,19 @@ static uint8_t gen_hash_m(const struct bt_gatt_attr *attr, uint16_t handle, case BT_UUID_GATT_CPF_VAL: case BT_UUID_GATT_CAF_VAL: value = sys_cpu_to_le16(handle); - if (tc_cmac_update(&state->state, (uint8_t *)&value, - sizeof(handle)) == TC_CRYPTO_FAIL) { + if (db_hash_update(state, (uint8_t *)&value, + sizeof(handle)) != 0) { state->err = -EINVAL; return BT_GATT_ITER_STOP; } value = sys_cpu_to_le16(u16->val); - if (tc_cmac_update(&state->state, (uint8_t *)&value, - sizeof(u16->val)) == TC_CRYPTO_FAIL) { + if (db_hash_update(state, (uint8_t *)&value, + sizeof(u16->val)) != 0) { state->err = -EINVAL; return BT_GATT_ITER_STOP; } + break; default: return BT_GATT_ITER_CONTINUE; @@ -825,18 +911,15 @@ static void db_hash_store(void) static void db_hash_gen(void) { uint8_t key[16] = {}; - struct tc_aes_key_sched_struct sched; struct gen_hash_state state; - if (tc_cmac_setup(&state.state, key, &sched) == TC_CRYPTO_FAIL) { - LOG_ERR("Unable to setup AES CMAC"); + if (db_hash_setup(&state, key) != 0) { return; } bt_gatt_foreach_attr(0x0001, 0xffff, gen_hash_m, &state); - if (tc_cmac_final(db_hash.hash, &state.state) == TC_CRYPTO_FAIL) { - LOG_ERR("Unable to calculate hash"); + if (db_hash_finish(&state) != 0) { return; } diff --git a/tests/bluetooth/gatt/testcase.yaml b/tests/bluetooth/gatt/testcase.yaml index 135f6d823ede4..fd349d00f52c9 100644 --- a/tests/bluetooth/gatt/testcase.yaml +++ b/tests/bluetooth/gatt/testcase.yaml @@ -14,3 +14,21 @@ tests: tags: - bluetooth - gatt + bluetooth.gatt.psa: + filter: CONFIG_PSA_CRYPTO_CLIENT + extra_args: + - EXTRA_DTC_OVERLAY_FILE="test.overlay" + platform_allow: + - native_posix + - native_posix/native/64 + - native_sim + - native_sim/native/64 + - qemu_x86 + - qemu_cortex_m3 + - nrf5340dk/nrf5340/cpuapp/ns + - nrf52840dk/nrf52840 + integration_platforms: + - native_sim + tags: + - bluetooth + - gatt From 32b792b21f5eb33495097e440e7a64464f045d27 Mon Sep 17 00:00:00 2001 From: Valerio Setti Date: Wed, 5 Jun 2024 10:25:28 +0200 Subject: [PATCH 2732/2849] bluetooth: remove BT_TINYCRYPT_ECC in bluetooth mesh tests Some bluetooth test were using BT_TINYCRYPT_ECC without also setting BT_ECC. This means that BT_TINYCRYPT_ECC gets disabled as it depends on BT_ECC. This commit fix this by removing BT_TINYCRYPT_ECC in all test for bluetooth mesh. Signed-off-by: Valerio Setti --- tests/bluetooth/mesh/basic/dbg.conf | 1 - tests/bluetooth/mesh/basic/friend.conf | 1 - tests/bluetooth/mesh/basic/gatt.conf | 1 - tests/bluetooth/mesh/basic/lpn.conf | 1 - tests/bluetooth/mesh/basic/multi_ext_adv.conf | 1 - tests/bluetooth/mesh/basic/pb_gatt.conf | 1 - tests/bluetooth/mesh/basic/prj.conf | 1 - tests/bluetooth/mesh/basic/proxy.conf | 1 - tests/bluetooth/mesh_shell/prj.conf | 1 - tests/bluetooth/shell/log.conf | 1 - tests/bluetooth/shell/mesh.conf | 1 - tests/bluetooth/shell/prj.conf | 1 - tests/bluetooth/shell/prj_br.conf | 1 - tests/bluetooth/tester/prj.conf | 1 - 14 files changed, 14 deletions(-) diff --git a/tests/bluetooth/mesh/basic/dbg.conf b/tests/bluetooth/mesh/basic/dbg.conf index 73cd1b361b6d1..6933c402ac6c2 100644 --- a/tests/bluetooth/mesh/basic/dbg.conf +++ b/tests/bluetooth/mesh/basic/dbg.conf @@ -17,7 +17,6 @@ CONFIG_BT_CTLR_PRIVACY=n CONFIG_BT_PERIPHERAL=y CONFIG_BT=y -CONFIG_BT_TINYCRYPT_ECC=y CONFIG_BT_MESH=y CONFIG_BT_MESH_RELAY=y diff --git a/tests/bluetooth/mesh/basic/friend.conf b/tests/bluetooth/mesh/basic/friend.conf index 136bced37db2a..b669d9729125d 100644 --- a/tests/bluetooth/mesh/basic/friend.conf +++ b/tests/bluetooth/mesh/basic/friend.conf @@ -15,7 +15,6 @@ CONFIG_BT_CTLR_MIN_USED_CHAN=n CONFIG_BT_CTLR_PRIVACY=n CONFIG_BT=y -CONFIG_BT_TINYCRYPT_ECC=y CONFIG_BT_MESH=y CONFIG_BT_MESH_RELAY=y diff --git a/tests/bluetooth/mesh/basic/gatt.conf b/tests/bluetooth/mesh/basic/gatt.conf index 75b6a424a4aa5..57caf1ec8436c 100644 --- a/tests/bluetooth/mesh/basic/gatt.conf +++ b/tests/bluetooth/mesh/basic/gatt.conf @@ -17,7 +17,6 @@ CONFIG_BT_CTLR_PRIVACY=n CONFIG_BT_PERIPHERAL=y CONFIG_BT=y -CONFIG_BT_TINYCRYPT_ECC=y CONFIG_BT_MESH=y CONFIG_BT_MESH_RELAY=y diff --git a/tests/bluetooth/mesh/basic/lpn.conf b/tests/bluetooth/mesh/basic/lpn.conf index 441516fbe6efd..6edaa9af8a940 100644 --- a/tests/bluetooth/mesh/basic/lpn.conf +++ b/tests/bluetooth/mesh/basic/lpn.conf @@ -17,7 +17,6 @@ CONFIG_BT_CTLR_PRIVACY=n CONFIG_BT_PERIPHERAL=y CONFIG_BT=y -CONFIG_BT_TINYCRYPT_ECC=y CONFIG_BT_MESH=y CONFIG_BT_MESH_RELAY=n diff --git a/tests/bluetooth/mesh/basic/multi_ext_adv.conf b/tests/bluetooth/mesh/basic/multi_ext_adv.conf index aa93628401b7a..634973154c348 100644 --- a/tests/bluetooth/mesh/basic/multi_ext_adv.conf +++ b/tests/bluetooth/mesh/basic/multi_ext_adv.conf @@ -16,7 +16,6 @@ CONFIG_BT_CTLR_PRIVACY=n CONFIG_BT_PERIPHERAL=y CONFIG_BT=y -CONFIG_BT_TINYCRYPT_ECC=y CONFIG_BT_MESH=y CONFIG_BT_MESH_RELAY=y diff --git a/tests/bluetooth/mesh/basic/pb_gatt.conf b/tests/bluetooth/mesh/basic/pb_gatt.conf index 28ade412c0833..3deb6aebc0713 100644 --- a/tests/bluetooth/mesh/basic/pb_gatt.conf +++ b/tests/bluetooth/mesh/basic/pb_gatt.conf @@ -17,7 +17,6 @@ CONFIG_BT_CTLR_PRIVACY=n CONFIG_BT_PERIPHERAL=y CONFIG_BT=y -CONFIG_BT_TINYCRYPT_ECC=y CONFIG_BT_MESH=y CONFIG_BT_MESH_RELAY=y diff --git a/tests/bluetooth/mesh/basic/prj.conf b/tests/bluetooth/mesh/basic/prj.conf index 126907a8837ef..825d1be6e9ab8 100644 --- a/tests/bluetooth/mesh/basic/prj.conf +++ b/tests/bluetooth/mesh/basic/prj.conf @@ -17,7 +17,6 @@ CONFIG_BT_CTLR_PRIVACY=n CONFIG_BT_PERIPHERAL=y CONFIG_BT=y -CONFIG_BT_TINYCRYPT_ECC=y CONFIG_BT_MESH=y CONFIG_BT_MESH_RELAY=y diff --git a/tests/bluetooth/mesh/basic/proxy.conf b/tests/bluetooth/mesh/basic/proxy.conf index 18d22ae8b9782..068be4973aade 100644 --- a/tests/bluetooth/mesh/basic/proxy.conf +++ b/tests/bluetooth/mesh/basic/proxy.conf @@ -17,7 +17,6 @@ CONFIG_BT_CTLR_PRIVACY=n CONFIG_BT_PERIPHERAL=y CONFIG_BT=y -CONFIG_BT_TINYCRYPT_ECC=y CONFIG_BT_MESH=y CONFIG_BT_MESH_RELAY=n diff --git a/tests/bluetooth/mesh_shell/prj.conf b/tests/bluetooth/mesh_shell/prj.conf index 9ed15616cab52..bb4c878bdfdfb 100644 --- a/tests/bluetooth/mesh_shell/prj.conf +++ b/tests/bluetooth/mesh_shell/prj.conf @@ -18,7 +18,6 @@ CONFIG_SETTINGS=y CONFIG_BT=y CONFIG_BT_OBSERVER=y CONFIG_BT_PERIPHERAL=y -CONFIG_BT_TINYCRYPT_ECC=y CONFIG_BT_DEVICE_NAME="Zephyr Mesh" CONFIG_BT_GATT_CACHING=n diff --git a/tests/bluetooth/shell/log.conf b/tests/bluetooth/shell/log.conf index 69a1d5d5533f7..7a9aa9b8680ff 100644 --- a/tests/bluetooth/shell/log.conf +++ b/tests/bluetooth/shell/log.conf @@ -13,7 +13,6 @@ CONFIG_BT_FIXED_PASSKEY=y CONFIG_BT_ATT_PREPARE_COUNT=2 CONFIG_BT_GATT_CLIENT=y CONFIG_BT_L2CAP_DYNAMIC_CHANNEL=y -CONFIG_BT_TINYCRYPT_ECC=y CONFIG_BT_SHELL=y CONFIG_BT_DEVICE_NAME="log test shell" CONFIG_BT_DEVICE_NAME_DYNAMIC=y diff --git a/tests/bluetooth/shell/mesh.conf b/tests/bluetooth/shell/mesh.conf index a8079eb7b28b8..0336d417fb51d 100644 --- a/tests/bluetooth/shell/mesh.conf +++ b/tests/bluetooth/shell/mesh.conf @@ -13,7 +13,6 @@ CONFIG_BT_SIGNING=y CONFIG_BT_ATT_PREPARE_COUNT=2 CONFIG_BT_GATT_CLIENT=y CONFIG_BT_L2CAP_DYNAMIC_CHANNEL=y -CONFIG_BT_TINYCRYPT_ECC=y CONFIG_SHELL=y CONFIG_BT_SHELL=y CONFIG_BT_DEVICE_NAME="test shell" diff --git a/tests/bluetooth/shell/prj.conf b/tests/bluetooth/shell/prj.conf index 605cbc61c1948..510d0988262c1 100644 --- a/tests/bluetooth/shell/prj.conf +++ b/tests/bluetooth/shell/prj.conf @@ -15,7 +15,6 @@ CONFIG_BT_FIXED_PASSKEY=y CONFIG_BT_ATT_PREPARE_COUNT=2 CONFIG_BT_GATT_CLIENT=y CONFIG_BT_L2CAP_DYNAMIC_CHANNEL=y -CONFIG_BT_TINYCRYPT_ECC=y CONFIG_BT_SHELL=y CONFIG_BT_DEVICE_NAME="test shell" CONFIG_BT_DEVICE_NAME_DYNAMIC=y diff --git a/tests/bluetooth/shell/prj_br.conf b/tests/bluetooth/shell/prj_br.conf index d41ec3053087f..45d3806473fff 100644 --- a/tests/bluetooth/shell/prj_br.conf +++ b/tests/bluetooth/shell/prj_br.conf @@ -16,5 +16,4 @@ CONFIG_BT_ATT_PREPARE_COUNT=2 CONFIG_BT_GATT_CLIENT=y CONFIG_BT_HRS=y CONFIG_BT_L2CAP_DYNAMIC_CHANNEL=y -CONFIG_BT_TINYCRYPT_ECC=y CONFIG_BT_DEVICE_NAME="test shell" diff --git a/tests/bluetooth/tester/prj.conf b/tests/bluetooth/tester/prj.conf index 84ba74652ddc1..3e7f52d4d8375 100644 --- a/tests/bluetooth/tester/prj.conf +++ b/tests/bluetooth/tester/prj.conf @@ -36,7 +36,6 @@ CONFIG_BT_PER_ADV_SYNC=y CONFIG_BT_BUF_ACL_RX_SIZE=100 CONFIG_BT_RX_STACK_SIZE=4096 -CONFIG_BT_TINYCRYPT_ECC=y CONFIG_BT_TESTING=y CONFIG_UTF8=y From 32b43564dfd0ab2a58f4406c6e4289bc88da09be Mon Sep 17 00:00:00 2001 From: Valerio Setti Date: Wed, 5 Jun 2024 14:16:42 +0200 Subject: [PATCH 2733/2849] bt: hci_ecc: add option to use PSA APIs instead of TinyCrypt This commit adds CONFIG_BT_USE_PSA_API to allow the end user to prefer PSA APIs over TinyCrypt for crypto operations in bluetooth. Of course, this is possible only if a PSA provider is available on the system, i.e. CONFIG_PSA_CRYPTO_CLIENT is set. This commit also extends tests/bluetooth/mesh/basic/bluetooth.mesh.gatt adding a specific case using PSA. Signed-off-by: Valerio Setti --- subsys/bluetooth/Kconfig | 2 +- subsys/bluetooth/host/hci_ecc.c | 108 ++++++++++++++++++++--- tests/bluetooth/mesh/basic/testcase.yaml | 14 +++ 3 files changed, 113 insertions(+), 11 deletions(-) diff --git a/subsys/bluetooth/Kconfig b/subsys/bluetooth/Kconfig index 9a9b91f2b18de..0b993db935940 100644 --- a/subsys/bluetooth/Kconfig +++ b/subsys/bluetooth/Kconfig @@ -194,7 +194,7 @@ rsource "Kconfig.logging" config BT_USE_PSA_API bool "Use PSA APIs instead of TinyCrypt for crypto operations" - depends on BT_CRYPTO || BT_HOST_CRYPTO + depends on BT_CRYPTO || BT_HOST_CRYPTO || BT_ECC depends on PSA_CRYPTO_CLIENT help Use PSA APIs instead of TinyCrypt for crypto operations diff --git a/subsys/bluetooth/host/hci_ecc.c b/subsys/bluetooth/host/hci_ecc.c index 718d90176fa7d..7e8e66a90fe6f 100644 --- a/subsys/bluetooth/host/hci_ecc.c +++ b/subsys/bluetooth/host/hci_ecc.c @@ -13,10 +13,15 @@ #include #include #include + +#if defined(CONFIG_BT_USE_PSA_API) +#include +#else /* !CONFIG_BT_USE_PSA_API */ #include #include #include #include +#endif /* CONFIG_BT_USE_PSA_API*/ #include #include @@ -104,6 +109,54 @@ static void send_cmd_status(uint16_t opcode, uint8_t status) #endif } +#if defined(CONFIG_BT_USE_PSA_API) +static void set_key_attributes(psa_key_attributes_t *attr) +{ + psa_set_key_type(attr, PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1)); + psa_set_key_bits(attr, 256); + psa_set_key_usage_flags(attr, PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_DERIVE); + psa_set_key_algorithm(attr, PSA_ALG_ECDH); +} + +static uint8_t generate_keys(void) +{ + psa_key_attributes_t attr = PSA_KEY_ATTRIBUTES_INIT; + psa_key_id_t key_id; + uint8_t tmp_pub_key_buf[BT_PUB_KEY_LEN + 1]; + size_t tmp_len; + + set_key_attributes(&attr); + + if (psa_generate_key(&attr, &key_id) != PSA_SUCCESS) { + LOG_ERR("Failed to generate ECC key"); + return BT_HCI_ERR_UNSPECIFIED; + } + + if (psa_export_public_key(key_id, tmp_pub_key_buf, sizeof(tmp_pub_key_buf), + &tmp_len) != PSA_SUCCESS) { + LOG_ERR("Failed to export ECC public key"); + return BT_HCI_ERR_UNSPECIFIED; + } + /* secp256r1 PSA exported public key has an extra 0x04 predefined byte at + * the beginning of the buffer which is not part of the coordinate so + * we remove that. + */ + memcpy(ecc.public_key_be, &tmp_pub_key_buf[1], BT_PUB_KEY_LEN); + + if (psa_export_key(key_id, ecc.private_key_be, BT_PRIV_KEY_LEN, + &tmp_len) != PSA_SUCCESS) { + LOG_ERR("Failed to export ECC private key"); + return BT_HCI_ERR_UNSPECIFIED; + } + + if (psa_destroy_key(key_id) != PSA_SUCCESS) { + LOG_ERR("Failed to destroy ECC key ID"); + return BT_HCI_ERR_UNSPECIFIED; + } + + return 0; +} +#else static uint8_t generate_keys(void) { do { @@ -125,6 +178,7 @@ static uint8_t generate_keys(void) return 0; } +#endif /* CONFIG_BT_USE_PSA_API */ static void emulate_le_p256_public_key_cmd(void) { @@ -176,21 +230,55 @@ static void emulate_le_generate_dhkey(void) struct bt_hci_evt_le_meta_event *meta; struct bt_hci_evt_hdr *hdr; struct net_buf *buf; - int ret; + int ret = 0; + bool use_debug = atomic_test_bit(flags, USE_DEBUG_KEY); + +#if defined(CONFIG_BT_USE_PSA_API) + psa_key_attributes_t attr = PSA_KEY_ATTRIBUTES_INIT; + psa_key_id_t key_id; + /* PSA expects secp256r1 public key to start with a predefined 0x04 byte + * at the beginning the buffer. + */ + uint8_t tmp_pub_key_buf[BT_PUB_KEY_LEN + 1] = { 0x04 }; + size_t tmp_len; + set_key_attributes(&attr); + + if (psa_import_key(&attr, use_debug ? debug_private_key_be : ecc.private_key_be, + BT_PRIV_KEY_LEN, &key_id) != PSA_SUCCESS) { + ret = -EIO; + LOG_ERR("Failed to import the private key for key agreement"); + goto exit; + } + + memcpy(&tmp_pub_key_buf[1], ecc.public_key_be, BT_PUB_KEY_LEN); + if (psa_raw_key_agreement(PSA_ALG_ECDH, key_id, tmp_pub_key_buf, + sizeof(tmp_pub_key_buf), ecc.dhkey_be, BT_DH_KEY_LEN, + &tmp_len) != PSA_SUCCESS) { + ret = -EIO; + LOG_ERR("Raw key agreement failed"); + goto exit; + } + + if (psa_destroy_key(key_id) != PSA_SUCCESS) { + LOG_ERR("Failed to destroy the key"); + ret = -EIO; + } + +#else /* !CONFIG_BT_USE_PSA_API */ ret = uECC_valid_public_key(ecc.public_key_be, &curve_secp256r1); if (ret < 0) { LOG_ERR("public key is not valid (ret %d)", ret); - ret = TC_CRYPTO_FAIL; - } else { - bool use_debug = atomic_test_bit(flags, USE_DEBUG_KEY); - - ret = uECC_shared_secret(ecc.public_key_be, - use_debug ? debug_private_key_be : - ecc.private_key_be, - ecc.dhkey_be, &curve_secp256r1); + ret = -EIO; + goto exit; } + ret = uECC_shared_secret(ecc.public_key_be, + use_debug ? debug_private_key_be : ecc.private_key_be, + ecc.dhkey_be, &curve_secp256r1); + ret = (ret == TC_CRYPTO_FAIL) ? -EIO : 0; +#endif /* CONFIG_BT_USE_PSA_API */ +exit: buf = bt_buf_get_rx(BT_BUF_EVT, K_FOREVER); hdr = net_buf_add(buf, sizeof(*hdr)); @@ -202,7 +290,7 @@ static void emulate_le_generate_dhkey(void) evt = net_buf_add(buf, sizeof(*evt)); - if (ret == TC_CRYPTO_FAIL) { + if (ret != 0) { evt->status = BT_HCI_ERR_UNSPECIFIED; (void)memset(evt->dhkey, 0xff, sizeof(evt->dhkey)); } else { diff --git a/tests/bluetooth/mesh/basic/testcase.yaml b/tests/bluetooth/mesh/basic/testcase.yaml index 24486e4d75fa4..1eced45437fcd 100644 --- a/tests/bluetooth/mesh/basic/testcase.yaml +++ b/tests/bluetooth/mesh/basic/testcase.yaml @@ -37,6 +37,20 @@ tests: platform_allow: - qemu_x86 - nrf52840dk/nrf52840 + - nrf5340dk/nrf5340/cpuapp/ns + integration_platforms: + - qemu_x86 + tags: + - bluetooth + - mesh + bluetooth.mesh.gatt.psa: + build_only: true + extra_args: CONF_FILE=gatt.conf + extra_configs: + - CONFIG_BT_USE_PSA_API=y + platform_allow: + - qemu_x86 + - nrf5340dk/nrf5340/cpuapp/ns integration_platforms: - qemu_x86 tags: From 035b4af8b4bb25f61d951395acf21cef9d1d41ed Mon Sep 17 00:00:00 2001 From: Valerio Setti Date: Thu, 30 May 2024 13:53:25 +0200 Subject: [PATCH 2734/2849] doc: update migration guide about changes to bt-crypto Update migration guide about the support to PSA functions introduced in bt-crypto. Signed-off-by: Valerio Setti --- 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 c2053fdfa6085..1223fcbc2b71c 100644 --- a/doc/releases/migration-guide-3.7.rst +++ b/doc/releases/migration-guide-3.7.rst @@ -657,6 +657,14 @@ Bluetooth Host longer used in Zephyr 3.4.0 and later. Any references to this field should be removed. No further action is needed. +Bluetooth Crypto +================ + +* :kconfig:option:`CONFIG_BT_USE_PSA_API` was added to explicitly request use + of PSA APIs instead of TinyCrypt for crypto operations. Of course, this is + possible only a PSA crypto provider available in the system, i.e. + :kconfig:option:`CONFIG_PSA_CRYPTO_CLIENT` is set. (:github:`73378`) + Networking ********** From e9687c7e5cccf86a74def432a816fedd23948f05 Mon Sep 17 00:00:00 2001 From: Valerio Setti Date: Wed, 12 Jun 2024 22:11:22 +0200 Subject: [PATCH 2735/2849] bsim: add tests for BT_USE_PSA_API Add a couple PSA overlay configs for the BT tests in order to evaluate PSA API support introduced by CONFIG_BT_USE_PSA_API. These test are performed on nrf52840dk platform. Signed-off-by: Valerio Setti --- tests/bsim/bluetooth/hci_uart/compile.sh | 2 + .../basic_conn_split_hci_uart_psa.sh | 45 +++++++++++++++++++ .../host/gatt/caching/psa_overlay.conf | 7 +++ .../gatt/caching/test_scripts/_run_test.sh | 5 ++- .../gatt_caching_psa_db_hash_read_eatt.sh | 9 ++++ tests/bsim/bluetooth/host/gatt/compile.sh | 1 + tests/bsim/bluetooth/ll/conn/psa_overlay.conf | 7 +++ 7 files changed, 74 insertions(+), 2 deletions(-) create mode 100755 tests/bsim/bluetooth/hci_uart/tests_scripts/basic_conn_split_hci_uart_psa.sh create mode 100644 tests/bsim/bluetooth/host/gatt/caching/psa_overlay.conf create mode 100755 tests/bsim/bluetooth/host/gatt/caching/test_scripts/gatt_caching_psa_db_hash_read_eatt.sh create mode 100644 tests/bsim/bluetooth/ll/conn/psa_overlay.conf diff --git a/tests/bsim/bluetooth/hci_uart/compile.sh b/tests/bsim/bluetooth/hci_uart/compile.sh index ed177513a055e..3546c8c37987d 100755 --- a/tests/bsim/bluetooth/hci_uart/compile.sh +++ b/tests/bsim/bluetooth/hci_uart/compile.sh @@ -12,6 +12,8 @@ source ${ZEPHYR_BASE}/tests/bsim/compile.source app=tests/bsim/bluetooth/ll/conn conf_file=prj_split_hci_uart.conf \ cmake_extra_args=-DEXTRA_DTC_OVERLAY_FILE=hci-uart.overlay compile +app=tests/bsim/bluetooth/ll/conn conf_file=prj_split_hci_uart.conf conf_overlay=psa_overlay.conf \ + cmake_extra_args=-DEXTRA_DTC_OVERLAY_FILE=hci-uart.overlay compile app=samples/bluetooth/hci_uart compile app=samples/bluetooth/hci_uart_async compile diff --git a/tests/bsim/bluetooth/hci_uart/tests_scripts/basic_conn_split_hci_uart_psa.sh b/tests/bsim/bluetooth/hci_uart/tests_scripts/basic_conn_split_hci_uart_psa.sh new file mode 100755 index 0000000000000..6859ad8cbdfb6 --- /dev/null +++ b/tests/bsim/bluetooth/hci_uart/tests_scripts/basic_conn_split_hci_uart_psa.sh @@ -0,0 +1,45 @@ +#!/usr/bin/env bash +# Copyright 2024 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +source ${ZEPHYR_BASE}/tests/bsim/sh_common.source + +# Basic connection test: a central connects to a peripheral and expects a +# notification, using the split controller (ULL LLL) +# Both central and peripheral hosts have their controllers in a separate device +# connected over UART. The controller is the HCI UART sample. +simulation_id="basic_conn_split_hci_uart_psa" +verbosity_level=2 + +cd ${BSIM_OUT_PATH}/bin + +UART_DIR=/tmp/bs_${USER}/${simulation_id}/ +UART_PER=${UART_DIR}/peripheral +UART_CEN=${UART_DIR}/central + +# Note the host+app devices are NOT connected to the phy, only the controllers are. + +# Peripheral app + host : +Execute ./bs_${BOARD_TS}_tests_bsim_bluetooth_ll_conn_prj_split_hci_uart_conf_psa_overlay_conf \ + -v=${verbosity_level} -s=${simulation_id} -d=10 -nosim -RealEncryption=0 \ + -testid=peripheral -rs=23 -uart1_fifob_rxfile=${UART_PER}.rx -uart1_fifob_txfile=${UART_PER}.tx + +# Peripheral controller: +Execute ./bs_${BOARD_TS}_samples_bluetooth_hci_uart_prj_conf \ + -v=${verbosity_level} -s=${simulation_id} -d=0 -RealEncryption=0 \ + -rs=23 -uart1_fifob_rxfile=${UART_PER}.tx -uart1_fifob_txfile=${UART_PER}.rx \ + +# Central app + host +Execute ./bs_${BOARD_TS}_tests_bsim_bluetooth_ll_conn_prj_split_hci_uart_conf_psa_overlay_conf \ + -v=${verbosity_level} -s=${simulation_id} -d=11 -nosim -RealEncryption=0 \ + -testid=central -rs=6 -uart1_fifob_rxfile=${UART_CEN}.rx -uart1_fifob_txfile=${UART_CEN}.tx + +# Central controller: +Execute ./bs_${BOARD_TS}_samples_bluetooth_hci_uart_prj_conf \ + -v=${verbosity_level} -s=${simulation_id} -d=1 -RealEncryption=0 \ + -rs=23 -uart1_fifob_rxfile=${UART_CEN}.tx -uart1_fifob_txfile=${UART_CEN}.rx + +Execute ./bs_2G4_phy_v1 -v=${verbosity_level} -s=${simulation_id} \ + -D=2 -sim_length=20e6 $@ + +wait_for_background_jobs diff --git a/tests/bsim/bluetooth/host/gatt/caching/psa_overlay.conf b/tests/bsim/bluetooth/host/gatt/caching/psa_overlay.conf new file mode 100644 index 0000000000000..7086f66d96d52 --- /dev/null +++ b/tests/bsim/bluetooth/host/gatt/caching/psa_overlay.conf @@ -0,0 +1,7 @@ +CONFIG_BT_USE_PSA_API=y +CONFIG_MBEDTLS=y +CONFIG_MBEDTLS_PSA_CRYPTO_C=y +CONFIG_PSA_CRYPTO_ENABLE_ALL=y + +CONFIG_ENTROPY_GENERATOR=y +CONFIG_MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG=y diff --git a/tests/bsim/bluetooth/host/gatt/caching/test_scripts/_run_test.sh b/tests/bsim/bluetooth/host/gatt/caching/test_scripts/_run_test.sh index a8399b79eb9b9..ed7876abe8b54 100755 --- a/tests/bsim/bluetooth/host/gatt/caching/test_scripts/_run_test.sh +++ b/tests/bsim/bluetooth/host/gatt/caching/test_scripts/_run_test.sh @@ -6,13 +6,14 @@ source ${ZEPHYR_BASE}/tests/bsim/sh_common.source verbosity_level=2 EXECUTE_TIMEOUT=120 +BIN_SUFFIX=${bin_suffix:-} cd ${BSIM_OUT_PATH}/bin -Execute ./bs_${BOARD_TS}_tests_bsim_bluetooth_host_gatt_caching_prj_conf \ +Execute ./bs_${BOARD_TS}_tests_bsim_bluetooth_host_gatt_caching_prj_conf${BIN_SUFFIX} \ -v=${verbosity_level} -s=${simulation_id} -d=0 -testid=${client_id} -Execute ./bs_${BOARD_TS}_tests_bsim_bluetooth_host_gatt_caching_prj_conf \ +Execute ./bs_${BOARD_TS}_tests_bsim_bluetooth_host_gatt_caching_prj_conf${BIN_SUFFIX} \ -v=${verbosity_level} -s=${simulation_id} -d=1 -testid=${server_id} Execute ./bs_2G4_phy_v1 -v=${verbosity_level} -s=${simulation_id} \ diff --git a/tests/bsim/bluetooth/host/gatt/caching/test_scripts/gatt_caching_psa_db_hash_read_eatt.sh b/tests/bsim/bluetooth/host/gatt/caching/test_scripts/gatt_caching_psa_db_hash_read_eatt.sh new file mode 100755 index 0000000000000..281ff23a055db --- /dev/null +++ b/tests/bsim/bluetooth/host/gatt/caching/test_scripts/gatt_caching_psa_db_hash_read_eatt.sh @@ -0,0 +1,9 @@ +#!/usr/bin/env bash +# Copyright 2024 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +simulation_id="gatt_caching_psa_db_hash_read_eatt_psa" \ + client_id="gatt_client_db_hash_read_eatt" \ + server_id="gatt_server_eatt" \ + bin_suffix="_psa_overlay_conf" \ + $(dirname "${BASH_SOURCE[0]}")/_run_test.sh diff --git a/tests/bsim/bluetooth/host/gatt/compile.sh b/tests/bsim/bluetooth/host/gatt/compile.sh index 3fc026e67ccbb..67ebb09be9ecf 100755 --- a/tests/bsim/bluetooth/host/gatt/compile.sh +++ b/tests/bsim/bluetooth/host/gatt/compile.sh @@ -12,6 +12,7 @@ source ${ZEPHYR_BASE}/tests/bsim/compile.source app=tests/bsim/bluetooth/host/gatt/authorization compile app=tests/bsim/bluetooth/host/gatt/caching compile +app=tests/bsim/bluetooth/host/gatt/caching conf_overlay=psa_overlay.conf compile app=tests/bsim/bluetooth/host/gatt/general compile app=tests/bsim/bluetooth/host/gatt/notify compile app=tests/bsim/bluetooth/host/gatt/notify_multiple compile diff --git a/tests/bsim/bluetooth/ll/conn/psa_overlay.conf b/tests/bsim/bluetooth/ll/conn/psa_overlay.conf new file mode 100644 index 0000000000000..7086f66d96d52 --- /dev/null +++ b/tests/bsim/bluetooth/ll/conn/psa_overlay.conf @@ -0,0 +1,7 @@ +CONFIG_BT_USE_PSA_API=y +CONFIG_MBEDTLS=y +CONFIG_MBEDTLS_PSA_CRYPTO_C=y +CONFIG_PSA_CRYPTO_ENABLE_ALL=y + +CONFIG_ENTROPY_GENERATOR=y +CONFIG_MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG=y From 35e313f9e5ff7044ccd9ca2950c10e03c19a0ed0 Mon Sep 17 00:00:00 2001 From: Dmitrii Golovanov Date: Wed, 29 May 2024 16:57:35 +0200 Subject: [PATCH 2736/2849] twister: recording: Allow JSON data fields Extend Twister Harness recording feature to allow selected data fields, extracted from the log by a regular expression, to be parsed into JSON objects and eventually reported in `twister.json` as `recording` list property of the test suite. With this extension, log records can convey layered data structures passed from a test image as summary results, traces, statistics, etc. This extension also allows flexible recording structure: a test image can output different types of data records incapsulated into a fixed set of fields, so `recording.csv` file columns are respected, whereas some of the columns keep strings with json-encoded semi-structured data. Signed-off-by: Dmitrii Golovanov --- doc/develop/test/twister.rst | 45 +++++++++++++++++-- scripts/pylib/twister/twisterlib/harness.py | 20 ++++++++- scripts/schemas/twister/testsuite-schema.yaml | 5 +++ scripts/tests/twister/test_harness.py | 33 ++++++++++---- 4 files changed, 91 insertions(+), 12 deletions(-) diff --git a/doc/develop/test/twister.rst b/doc/develop/test/twister.rst index 4773a3e3466e2..99a4e546e62f9 100644 --- a/doc/develop/test/twister.rst +++ b/doc/develop/test/twister.rst @@ -504,16 +504,55 @@ harness_config: The regular expression with named subgroups to match data fields at the test's output lines where the test provides some custom data for further analysis. These records will be written into the build - directory 'recording.csv' file as well as 'recording' property - of the test suite object in 'twister.json'. + directory ``recording.csv`` file as well as ``recording`` property + of the test suite object in ``twister.json``. - For example, to extract three data fields 'metric', 'cycles', 'nanoseconds': + For example, to extract three data fields ``metric``, ``cycles``, + ``nanoseconds``: .. code-block:: yaml record: regex: "(?P.*):(?P.*) cycles, (?P.*) ns" + as_json: (optional) + Data fields, extracted by the regular expression into named subgroups, + which will be additionally parsed as JSON encoded strings and written + into ``twister.json`` as nested ``recording`` object properties. + The corresponding ``recording.csv`` columns will contain strings as-is. + + Using this option, a test log can convey layered data structures + passed from the test image for further analysis with summary results, + traces, statistics, etc. + + For example, this configuration: + + .. code-block:: yaml + + record: + regex: "RECORD:(?P.*):DATA:(?P.*)" + as_json: [metrics] + + when matched to a test log string: + + .. code-block:: none + + RECORD:jitter_drift:DATA:{"rollovers":0, "mean_us":1000.0} + + will be reported in ``twister.json`` as: + + .. code-block:: json + + "recording":[ + { + "type":"jitter_drift", + "metrics":{ + "rollovers":0, + "mean_us":1000.0 + } + } + ] + fixture: Specify a test case dependency on an external device(e.g., sensor), and identify setups that fulfill this dependency. It depends on diff --git a/scripts/pylib/twister/twisterlib/harness.py b/scripts/pylib/twister/twisterlib/harness.py index 6108703c22f92..1518cdbd79e22 100644 --- a/scripts/pylib/twister/twisterlib/harness.py +++ b/scripts/pylib/twister/twisterlib/harness.py @@ -13,6 +13,7 @@ import threading import time import shutil +import json from twisterlib.error import ConfigurationError from twisterlib.environment import ZEPHYR_BASE, PYTEST_PLUGIN_INSTALLED @@ -57,6 +58,7 @@ def __init__(self): self.next_pattern = 0 self.record = None self.record_pattern = None + self.record_as_json = None self.recording = [] self.ztest = False self.detected_suite_names = [] @@ -82,6 +84,7 @@ def configure(self, instance): self.record = config.get('record', {}) if self.record: self.record_pattern = re.compile(self.record.get("regex", "")) + self.record_as_json = self.record.get("as_json") def build(self): pass @@ -92,12 +95,27 @@ def get_testcase_name(self): """ return self.id + def translate_record(self, record: dict) -> dict: + if self.record_as_json: + for k in self.record_as_json: + if not k in record: + continue + try: + record[k] = json.loads(record[k]) if record[k] else {} + except json.JSONDecodeError as parse_error: + logger.warning(f"HARNESS:{self.__class__.__name__}: recording JSON failed:" + f" {parse_error} for '{k}':'{record[k]}'") + # Don't set the Harness state to failed for recordings. + record[k] = { 'ERROR': { 'msg': str(parse_error), 'doc': record[k] } } + return record + 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() }) + rec = self.translate_record({ k:v.strip() for k,v in match.groupdict(default="").items() }) + self.recording.append(rec) return match # diff --git a/scripts/schemas/twister/testsuite-schema.yaml b/scripts/schemas/twister/testsuite-schema.yaml index 1eae7dcef1b1f..28b7e730edbe5 100644 --- a/scripts/schemas/twister/testsuite-schema.yaml +++ b/scripts/schemas/twister/testsuite-schema.yaml @@ -130,6 +130,11 @@ schema;scenario-schema: "regex": type: str required: true + "as_json": + type: seq + required: false + sequence: + - type: str "bsim_exe_name": type: str required: false diff --git a/scripts/tests/twister/test_harness.py b/scripts/tests/twister/test_harness.py index ddebb2c5b2e9f..2e0028b234a9c 100644 --- a/scripts/tests/twister/test_harness.py +++ b/scripts/tests/twister/test_harness.py @@ -45,23 +45,40 @@ def process_logs(harness, logs): 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:(?P.*):END", [], None), + (['START:bar:STOP'], "^START:(?P.*):END", [], None), + (['START:bar:END'], "^START:(?P.*):END", [{'foo':'bar'}], None), + (['START:bar:baz:END'], "^START:(?P.*):(?P.*):END", [{'foo':'bar', 'boo':'baz'}], None), (['START:bar:baz:END','START:may:jun:END'], "^START:(?P.*):(?P.*):END", - [{'foo':'bar', 'boo':'baz'}, {'foo':'may', 'boo':'jun'}]), + [{'foo':'bar', 'boo':'baz'}, {'foo':'may', 'boo':'jun'}], None), + (['START:bar:END'], "^START:(?P.*):END", [{'foo':'bar'}], []), + (['START:bar:END'], "^START:(?P.*):END", [{'foo':'bar'}], ['boo']), + (['START:bad_json:END'], "^START:(?P.*):END", + [{'foo':{'ERROR':{'msg':'Expecting value: line 1 column 1 (char 0)', 'doc':'bad_json'}}}], ['foo']), + (['START::END'], "^START:(?P.*):END", [{'foo':{}}], ['foo']), + (['START: {"one":1, "two":2} :END'], "^START:(?P.*):END", [{'foo':{'one':1, 'two':2}}], ['foo']), + (['START: {"one":1, "two":2} :STOP:oops:END'], "^START:(?P.*):STOP:(?P.*):END", + [{'foo':{'one':1, 'two':2},'boo':'oops'}], ['foo']), + (['START: {"one":1, "two":2} :STOP:{"oops":0}:END'], "^START:(?P.*):STOP:(?P.*):END", + [{'foo':{'one':1, 'two':2},'boo':{'oops':0}}], ['foo','boo']), ] @pytest.mark.parametrize( - "lines, pattern, expected_records", + "lines, pattern, expected_records, as_json", TEST_DATA_RECORDING, - ids=["empty", "no match", "match 1 field", "match 2 fields", "match 2 records"] + ids=["empty", "no match", "match 1 field", "match 2 fields", "match 2 records", + "as_json empty", "as_json no such field", "error parsing json", "empty json value", "simple json", + "plain field and json field", "two json fields" + ] ) -def test_harness_parse_record(lines, pattern, expected_records): +def test_harness_parse_record(lines, pattern, expected_records, as_json): harness = Harness() harness.record = { 'regex': pattern } harness.record_pattern = re.compile(pattern) + harness.record_as_json = as_json + if as_json is not None: + harness.record['as_json'] = as_json + assert not harness.recording for line in lines: From dd6779185715bbdf4cee340b3c03227f9539fc46 Mon Sep 17 00:00:00 2001 From: Dmitrii Golovanov Date: Fri, 31 May 2024 13:53:28 +0200 Subject: [PATCH 2737/2849] tests: kernel: timer_behavior: Additional stats recording Additional logging of kernel.timer.timer test case statistics for timer drift, variance, etc. as JSON-formatted records to make easier data collection and its further analysis. These log records will be processed by the Twister Harness recording feature which captures and parses timer statistics from the log output, then composes it into twister.json and recording.csv files. Signed-off-by: Dmitrii Golovanov --- .../timer/timer_behavior/src/jitter_drift.c | 51 +++++++++++++++++-- .../timer_behavior/src/tick_timer_train.c | 17 +++++++ .../kernel/timer/timer_behavior/testcase.yaml | 4 ++ 3 files changed, 69 insertions(+), 3 deletions(-) diff --git a/tests/kernel/timer/timer_behavior/src/jitter_drift.c b/tests/kernel/timer/timer_behavior/src/jitter_drift.c index d78adb40eaf2b..28ea47a790ed6 100644 --- a/tests/kernel/timer/timer_behavior/src/jitter_drift.c +++ b/tests/kernel/timer/timer_behavior/src/jitter_drift.c @@ -126,7 +126,7 @@ static double cycles_to_us(uint64_t cycles) /** * @brief Test a timers jitter and drift over time */ -static void do_test_using(void (*sample_collection_fn)(void)) +static void do_test_using(void (*sample_collection_fn)(void), const char *mechanism) { k_timeout_t actual_timeout = K_USEC(CONFIG_TIMER_TEST_PERIOD); uint64_t expected_duration = (uint64_t)actual_timeout.ticks * CONFIG_TIMER_TEST_SAMPLES; @@ -262,6 +262,51 @@ static void do_test_using(void (*sample_collection_fn)(void)) periodic_start, periodic_end, actual_time_us, expected_time_us, expected_time_drift_us, time_diff_us); + /* Record the stats gathered as a JSON object including related CONFIG_* params. */ + TC_PRINT("RECORD: {" + "\"testcase\":\"jitter_drift_timer\", \"mechanism\":\"%s\"" + ", \"stats_count\":%d, \"rollovers\":%d" + ", \"mean_us\":%.6f, \"mean_cycles\":%.0f" + ", \"stddev_us\":%.6f, \"stddev_cycles\":%.0f" + ", \"var_us\":%.6f, \"var_cycles\":%.0f" + ", \"min_us\":%.6f, \"min_cycles\":%llu" + ", \"max_us\":%.6f, \"max_cycles\":%llu" + ", \"timer_start_cycle\": %llu, \"timer_end_cycle\": %llu" + ", \"total_time_us\":%.6f" + ", \"expected_total_time_us\":%.6f" + ", \"expected_total_drift_us\":%.6f" + ", \"total_drift_us\":%.6f" + ", \"expected_period_cycles\":%.0f" + ", \"expected_period_drift_us\":%.6f" + ", \"sys_clock_hw_cycles_per_sec\":%d" + ", \"CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC\":%d" + ", \"CONFIG_SYS_CLOCK_TICKS_PER_SEC\":%d" + ", \"CONFIG_TIMER_TEST_PERIOD\":%d" + ", \"CONFIG_TIMER_TEST_SAMPLES\":%d" + ", \"CONFIG_TIMER_TEST_MAX_STDDEV\":%d" + "}\n", + mechanism, + CONFIG_TIMER_TEST_SAMPLES - periodic_rollovers, periodic_rollovers, + mean_us, mean_cyc, + stddev_us, stddev_cyc, + variance_us, variance_cyc, + min_us, min_cyc, + max_us, max_cyc, + periodic_start, periodic_end, + actual_time_us, + expected_time_us, + expected_time_drift_us, + time_diff_us, + expected_period, + expected_period_drift, + sys_clock_hw_cycles_per_sec(), + CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC, + CONFIG_SYS_CLOCK_TICKS_PER_SEC, + CONFIG_TIMER_TEST_PERIOD, + CONFIG_TIMER_TEST_SAMPLES, + CONFIG_TIMER_TEST_MAX_STDDEV + ); + /* Validate the maximum/minimum timer period is off by no more than 10% */ double test_period = (double)CONFIG_TIMER_TEST_PERIOD; double period_max_drift_percentage = @@ -300,7 +345,7 @@ ZTEST(timer_jitter_drift, test_jitter_drift_timer_period) k_sleep(K_SECONDS(CONFIG_TIMER_EXTERNAL_TEST_SYNC_DELAY)); gpio_pin_configure_dt(&timer_out, GPIO_OUTPUT_LOW); #endif - do_test_using(collect_timer_period_time_samples); + do_test_using(collect_timer_period_time_samples, "builtin"); } ZTEST(timer_jitter_drift, test_jitter_drift_timer_startdelay) @@ -314,7 +359,7 @@ ZTEST(timer_jitter_drift, test_jitter_drift_timer_startdelay) k_sleep(K_SECONDS(CONFIG_TIMER_EXTERNAL_TEST_SYNC_DELAY)); gpio_pin_configure_dt(&timer_out, GPIO_OUTPUT_LOW); #endif - do_test_using(collect_timer_startdelay_time_samples); + do_test_using(collect_timer_startdelay_time_samples, "startdelay"); } ZTEST_SUITE(timer_jitter_drift, NULL, NULL, NULL, NULL, NULL); diff --git a/tests/kernel/timer/timer_behavior/src/tick_timer_train.c b/tests/kernel/timer/timer_behavior/src/tick_timer_train.c index e4532b3f13be2..a1daabb132e7b 100644 --- a/tests/kernel/timer/timer_behavior/src/tick_timer_train.c +++ b/tests/kernel/timer/timer_behavior/src/tick_timer_train.c @@ -136,6 +136,23 @@ ZTEST(timer_tick_train, test_one_tick_timer_train) timers[i].late_callbacks, (1000 * timers[i].late_callbacks + MAX_CALLBACKS/2) / MAX_CALLBACKS / 10, (1000 * timers[i].late_callbacks + MAX_CALLBACKS/2) / MAX_CALLBACKS % 10); + /* Record the stats gathered as a JSON object including related CONFIG_* params. */ + TC_PRINT("RECORD: {" + "\"testcase\":\"one_tick_timer_train\"" + ", \"timer\":%d, \"max_delta_cycles\":%u, \"max_delta_us\":%u" + ", \"late_callbacks\":%u" + ", \"perfect_delta_cycles\":%u, \"perfect_delta_us\":%u" + ", \"train_time_ms\":%u, \"busy_loops\":%u" + ", \"timers\":%u, \"expected_callbacks\":%u, \"expected_time_ms\":%u" + ", \"CONFIG_SYS_CLOCK_TICKS_PER_SEC\":%u" + "}\n", + i, timers[i].max_delta, k_cyc_to_us_near32(timers[i].max_delta), + timers[i].late_callbacks, + k_ticks_to_cyc_floor32(TIMERS), k_ticks_to_us_near32(TIMERS), + delta_time, busy_loops, + TIMERS, MAX_CALLBACKS, max_time, + CONFIG_SYS_CLOCK_TICKS_PER_SEC + ); max_delta = timers[i].max_delta > max_delta ? timers[i].max_delta : max_delta; k_timer_stop(&timers[i].tm); } diff --git a/tests/kernel/timer/timer_behavior/testcase.yaml b/tests/kernel/timer/timer_behavior/testcase.yaml index 11ac75e5597f8..b1417dce98549 100644 --- a/tests/kernel/timer/timer_behavior/testcase.yaml +++ b/tests/kernel/timer/timer_behavior/testcase.yaml @@ -8,6 +8,10 @@ tests: - mcu simulation_exclude: - renode + harness_config: + record: + regex: "RECORD:(?P.*)" + as_json: ['metrics'] kernel.timer.timer_behavior_external: filter: dt_compat_enabled("test-kernel-timer-behavior-external") harness: pytest From 014a0983fb9b238e36a5303fece697be677312f6 Mon Sep 17 00:00:00 2001 From: Dmitrii Golovanov Date: Fri, 31 May 2024 13:59:03 +0200 Subject: [PATCH 2738/2849] tests: kernel: timer_behavior_external: Additional stats recording Additional logging of kernel.timer.timer_behavior_external test case statistics for timer drift, variance, etc. as JSON-formatted records to make easier data collection and its further analysis. These log records will be processed by the Twister Harness recording feature which captures and parses timer statistics from the log output, then composes it into twister.json and recording.csv files. Signed-off-by: Dmitrii Golovanov --- tests/kernel/timer/timer_behavior/README | 8 +++-- .../timer_behavior/pytest/saleae_logic2.py | 4 +-- .../timer/timer_behavior/pytest/test_timer.py | 32 ++++++++++++++++--- .../kernel/timer/timer_behavior/testcase.yaml | 3 ++ 4 files changed, 38 insertions(+), 9 deletions(-) diff --git a/tests/kernel/timer/timer_behavior/README b/tests/kernel/timer/timer_behavior/README index 64fc2d37112e0..d6f6b90eb7853 100644 --- a/tests/kernel/timer/timer_behavior/README +++ b/tests/kernel/timer/timer_behavior/README @@ -28,12 +28,12 @@ External tool interface In order to get data from the external tool, the test expects a Python module, named on testcase.yaml, with the following interface: - run(seconds: float, options: str) -> {} + run(seconds: float, options: str) -> {}, int The `seconds` parameter defines for how long the data collection is expected to run; `options` is a string defined on testcase.yaml with options known to -the external tool helper module. It should return a dictionary with the -following statistics, in seconds: +the external tool helper module. It should return a tuple with a dictionary +for the following time statistics, in seconds: 'mean': Mean time of each period 'stddev': Standard deviation from the mean time @@ -42,6 +42,8 @@ following statistics, in seconds: 'max': Maximum period registered 'total_time': Total time, between first and last period. +and an integer value of how many data values are collected for the statistics. + Note that the collection may need to go a bit after the "seconds" parameter, to account for expected drift in the test and between the DUT and the external tool. diff --git a/tests/kernel/timer/timer_behavior/pytest/saleae_logic2.py b/tests/kernel/timer/timer_behavior/pytest/saleae_logic2.py index 428677a43764c..2a50844db9f57 100644 --- a/tests/kernel/timer/timer_behavior/pytest/saleae_logic2.py +++ b/tests/kernel/timer/timer_behavior/pytest/saleae_logic2.py @@ -1,4 +1,4 @@ -# Copyright (c) 2023 Intel Corporation +# Copyright (c) 2023-2024 Intel Corporation # # SPDX-License-Identifier: Apache-2.0 @@ -62,7 +62,7 @@ def do_analysis(output_dir): total_time = data[-1] return {'mean': mean, 'stddev': std, 'var': var, 'min': minimum, - 'max': maximum, 'total_time': total_time} + 'max': maximum, 'total_time': total_time}, len(diff) # options should be a string of the format: diff --git a/tests/kernel/timer/timer_behavior/pytest/test_timer.py b/tests/kernel/timer/timer_behavior/pytest/test_timer.py index c6dced949c1e6..0fde72579494e 100755 --- a/tests/kernel/timer/timer_behavior/pytest/test_timer.py +++ b/tests/kernel/timer/timer_behavior/pytest/test_timer.py @@ -1,4 +1,4 @@ -# Copyright (c) 2023 Intel Corporation +# Copyright (c) 2023-2024 Intel Corporation # # SPDX-License-Identifier: Apache-2.0 @@ -11,7 +11,7 @@ logger = logging.getLogger(__name__) -def do_analysys(test, stats, config, sys_clock_hw_cycles_per_sec): +def do_analysys(test, stats, stats_count, config, sys_clock_hw_cycles_per_sec): logger.info('====================================================') logger.info(f'periodic timer behaviour using {test} mechanism:') @@ -52,6 +52,29 @@ def do_analysys(test, stats, config, sys_clock_hw_cycles_per_sec): logger.info(f'real drift: {time_diff * 1_000_000:.6f} us') logger.info('====================================================') + logger.info('RECORD: {' + f'"testcase":"jitter_drift_timer"' + f', "mechanism":"{test}_external", "stats_count": {stats_count}, ' + + ', '.join(['"{}_us":{:.6f}'.format(k, v * 1_000_000) for k,v in stats.items()]) + + f', "expected_total_time_us":{seconds * 1_000_000:.6f}' + f', "expected_total_drift_us":{seconds * max_drift_ppm:.6f}' + f', "total_drift_us": {time_diff * 1_000_000:.6f}' + f', "min_bound_us":{min_bound * 1_000_000:.6f}' + f', "max_bound_us":{max_bound * 1_000_000:.6f}' + f', "expected_period_cycles":{expected_period:.0f}' + f', "sys_clock_hw_cycles_per_sec":{sys_clock_hw_cycles_per_sec}, ' + + ', '.join(['"CONFIG_{}":{}'.format(k, str(config[k]).rstrip()) for k in [ + 'SYS_CLOCK_HW_CYCLES_PER_SEC', + 'SYS_CLOCK_TICKS_PER_SEC', + 'TIMER_TEST_PERIOD', + 'TIMER_TEST_SAMPLES', + 'TIMER_TEST_MAX_STDDEV', + 'TIMER_EXTERNAL_TEST_PERIOD_MAX_DRIFT_PPM', + 'TIMER_EXTERNAL_TEST_MAX_DRIFT_PPM' + ] + ]) + '}' + ) + assert stats['stddev'] < max_stddev assert stats['min'] >= min_bound assert stats['max'] <= max_bound @@ -73,5 +96,6 @@ def test_flash(dut: DeviceAdapter, tool, tool_options, config, tests = ["builtin", "startdelay"] for test in tests: wait_sync_point(dut, test) - stats = tool.run(seconds, tool_options) - do_analysys(test, stats, config, sys_clock_hw_cycles_per_sec) + stats, stats_count = tool.run(seconds, tool_options) + assert stats_count + do_analysys(test, stats, stats_count, config, sys_clock_hw_cycles_per_sec) diff --git a/tests/kernel/timer/timer_behavior/testcase.yaml b/tests/kernel/timer/timer_behavior/testcase.yaml index b1417dce98549..7e1b725ffbaa9 100644 --- a/tests/kernel/timer/timer_behavior/testcase.yaml +++ b/tests/kernel/timer/timer_behavior/testcase.yaml @@ -19,6 +19,9 @@ tests: pytest_args: ['--tool', 'saleae_logic2', '--tool-options', 'address=127.0.0.1,port=10430,channel=1,sample-rate=6_250_000,threshold-volts=3.3'] fixture: gpio_timerout + record: + regex: "RECORD:(?P.*)" + as_json: ['metrics'] extra_configs: - CONFIG_TIMER_EXTERNAL_TEST=y - CONFIG_BOOT_DELAY=5000 From d72dd3562ead085cd2f401f462c5112467164b1b Mon Sep 17 00:00:00 2001 From: Dmitrii Golovanov Date: Wed, 29 May 2024 18:49:07 +0200 Subject: [PATCH 2739/2849] tests: kernel: timer: Fix log capture on external tool testing Fix incomplete test log capture when the external tool is used and Twister Pytest Harness script ends without reading output from the last test case running on the device. Signed-off-by: Dmitrii Golovanov --- tests/kernel/timer/timer_behavior/pytest/test_timer.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/kernel/timer/timer_behavior/pytest/test_timer.py b/tests/kernel/timer/timer_behavior/pytest/test_timer.py index 0fde72579494e..865d0c0805066 100755 --- a/tests/kernel/timer/timer_behavior/pytest/test_timer.py +++ b/tests/kernel/timer/timer_behavior/pytest/test_timer.py @@ -99,3 +99,6 @@ def test_flash(dut: DeviceAdapter, tool, tool_options, config, stats, stats_count = tool.run(seconds, tool_options) assert stats_count do_analysys(test, stats, stats_count, config, sys_clock_hw_cycles_per_sec) + + # Let the running test's image output to be fully captured from device. + dut.readlines() From 01dcb942c676236923a47ac3f0071ac7145c29fc Mon Sep 17 00:00:00 2001 From: Dmitrii Golovanov Date: Thu, 13 Jun 2024 21:39:52 +0200 Subject: [PATCH 2740/2849] tests: kernel: timer_behavior_external: Fix a typo Rename `do_analysys()` to `do_analysis()`. Signed-off-by: Dmitrii Golovanov --- tests/kernel/timer/timer_behavior/pytest/test_timer.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/kernel/timer/timer_behavior/pytest/test_timer.py b/tests/kernel/timer/timer_behavior/pytest/test_timer.py index 865d0c0805066..5a72ecd66a799 100755 --- a/tests/kernel/timer/timer_behavior/pytest/test_timer.py +++ b/tests/kernel/timer/timer_behavior/pytest/test_timer.py @@ -11,7 +11,7 @@ logger = logging.getLogger(__name__) -def do_analysys(test, stats, stats_count, config, sys_clock_hw_cycles_per_sec): +def do_analysis(test, stats, stats_count, config, sys_clock_hw_cycles_per_sec): logger.info('====================================================') logger.info(f'periodic timer behaviour using {test} mechanism:') @@ -98,7 +98,7 @@ def test_flash(dut: DeviceAdapter, tool, tool_options, config, wait_sync_point(dut, test) stats, stats_count = tool.run(seconds, tool_options) assert stats_count - do_analysys(test, stats, stats_count, config, sys_clock_hw_cycles_per_sec) + do_analysis(test, stats, stats_count, config, sys_clock_hw_cycles_per_sec) # Let the running test's image output to be fully captured from device. dut.readlines() From 68bb87bd50b8d6831f84e1480d84418e0cef732a Mon Sep 17 00:00:00 2001 From: Dmitrii Golovanov Date: Fri, 14 Jun 2024 11:17:24 +0200 Subject: [PATCH 2741/2849] twister: pytest: Log output passthrough Pass Twister pytest plugin's log output, as well as output from a test image running with pytest, up to Twister log irregardless of the current verbosity level set at Twister. This allows to collect full test output and also ensures that recording data embedded in the test log is passed to the Twister pytest harness for export. Signed-off-by: Dmitrii Golovanov --- scripts/pylib/twister/twisterlib/harness.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/scripts/pylib/twister/twisterlib/harness.py b/scripts/pylib/twister/twisterlib/harness.py index 1518cdbd79e22..7af7867b3e30d 100644 --- a/scripts/pylib/twister/twisterlib/harness.py +++ b/scripts/pylib/twister/twisterlib/harness.py @@ -359,11 +359,11 @@ def generate_command(self): if pytest_dut_scope: command.append(f'--dut-scope={pytest_dut_scope}') - if handler.options.verbose > 1: - command.extend([ - '--log-cli-level=DEBUG', - '--log-cli-format=%(levelname)s: %(message)s' - ]) + # Always pass output from the pytest test and the test image up to Twister log. + command.extend([ + '--log-cli-level=DEBUG', + '--log-cli-format=%(levelname)s: %(message)s' + ]) if handler.type_str == 'device': command.extend( From 3e99dc26f6b8a7d8f2a08ec2d67d06fb9b3adb8d Mon Sep 17 00:00:00 2001 From: Guillaume Gautier Date: Tue, 11 Jun 2024 10:45:38 +0200 Subject: [PATCH 2742/2849] dts: bindings: flash_controller: add ncs line property to stm32 xspi flash Add a property to define the nCS line used by the XSPI driver for the external Flash. Signed-off-by: Guillaume Gautier --- dts/bindings/flash_controller/st,stm32-xspi-nor.yaml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/dts/bindings/flash_controller/st,stm32-xspi-nor.yaml b/dts/bindings/flash_controller/st,stm32-xspi-nor.yaml index f2ade8c7689c8..7aee7040f6b08 100644 --- a/dts/bindings/flash_controller/st,stm32-xspi-nor.yaml +++ b/dts/bindings/flash_controller/st,stm32-xspi-nor.yaml @@ -51,3 +51,12 @@ properties: enum: - 1 - 2 + + ncs-line: + type: int + default: 1 + enum: + - 1 + - 2 + description: | + Specifies which nCS line of the XSPI IO Manager is connected to the Flash. From fe05606630f8b2f61cdfd93569e67334171d6791 Mon Sep 17 00:00:00 2001 From: Guillaume Gautier Date: Tue, 11 Jun 2024 11:04:33 +0200 Subject: [PATCH 2743/2849] drivers: flash: select ncs line for stm32 xspi Add support to select the nCS line for XSPI from the device tree. Disable the nCS override. This setting only works with series that have an XSPIM (so not H5) Signed-off-by: Guillaume Gautier --- drivers/flash/flash_stm32_xspi.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/flash/flash_stm32_xspi.c b/drivers/flash/flash_stm32_xspi.c index ae7cbb6862b3c..c99bf7b279395 100644 --- a/drivers/flash/flash_stm32_xspi.c +++ b/drivers/flash/flash_stm32_xspi.c @@ -1940,12 +1940,11 @@ static int flash_stm32_xspi_init(const struct device *dev) 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; + xspi_mgr_cfg.IOPort = HAL_XSPIM_IOPORT_2; } - ospi_mgr_cfg.Req2AckTime = 1; + xspi_mgr_cfg.nCSOverride = HAL_XSPI_CSSEL_OVR_DISABLED; + xspi_mgr_cfg.Req2AckTime = 1; if (HAL_XSPIM_Config(&dev_data->hxspi, &xspi_mgr_cfg, HAL_XSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { @@ -2221,6 +2220,11 @@ static struct flash_stm32_xspi_data flash_stm32_xspi_dev_data = { .ClockMode = HAL_XSPI_CLOCK_MODE_0, .ChipSelectBoundary = 0, .MemoryMode = HAL_XSPI_SINGLE_MEM, +#if defined(HAL_XSPIM_IOPORT_1) || defined(HAL_XSPIM_IOPORT_2) + .MemorySelect = ((DT_INST_PROP(0, ncs_line) == 1) + ? HAL_XSPI_CSSEL_NCS1 + : HAL_XSPI_CSSEL_NCS2), +#endif .FreeRunningClock = HAL_XSPI_FREERUNCLK_DISABLE, #if defined(OCTOSPI_DCR4_REFRESH) .Refresh = 0, From 0103c56dd6ff45a8bc0b9cdc7832fa86ad2f8342 Mon Sep 17 00:00:00 2001 From: Yong Cong Sin Date: Fri, 14 Jun 2024 20:21:57 +0800 Subject: [PATCH 2744/2849] zephyr: remove deprecated headers These headers have been deprecated for > 2 full releases, let's remove them to keep them out of v3.7.0 LTS. Signed-off-by: Yong Cong Sin --- drivers/serial/uart_ns16550.h | 18 ------------------ include/zephyr/debug/tracing.h | 12 ------------ include/zephyr/zephyr.h | 14 -------------- 3 files changed, 44 deletions(-) delete mode 100644 drivers/serial/uart_ns16550.h delete mode 100644 include/zephyr/debug/tracing.h delete mode 100644 include/zephyr/zephyr.h diff --git a/drivers/serial/uart_ns16550.h b/drivers/serial/uart_ns16550.h deleted file mode 100644 index 97584c49ef179..0000000000000 --- a/drivers/serial/uart_ns16550.h +++ /dev/null @@ -1,18 +0,0 @@ -/* - * Copyright (c) 2015 Intel Corporation. - * - * SPDX-License-Identifier: Apache-2.0 - */ - -/** - * Header file for the NS16550 UART - */ - -#ifndef ZEPHYR_DRIVERS_SERIAL_UART_NS16550_H_ -#define ZEPHYR_DRIVERS_SERIAL_UART_NS16550_H_ - -#include - -#warning this header is deprecated, include instead - -#endif /* ZEPHYR_DRIVERS_SERIAL_UART_NS16550_H_ */ diff --git a/include/zephyr/debug/tracing.h b/include/zephyr/debug/tracing.h deleted file mode 100644 index 28d438daf812e..0000000000000 --- a/include/zephyr/debug/tracing.h +++ /dev/null @@ -1,12 +0,0 @@ - /* - * Copyright (c) 2020 Intel Corporation - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#ifndef ZEPHYR_INCLUDE_DEBUG_TRACING_H -#define ZEPHYR_INCLUDE_DEBUG_TRACING_H -#warning "This header file has moved, include instead." - -#include -#endif diff --git a/include/zephyr/zephyr.h b/include/zephyr/zephyr.h deleted file mode 100644 index 16e7dcfd6461a..0000000000000 --- a/include/zephyr/zephyr.h +++ /dev/null @@ -1,14 +0,0 @@ -/* - * Copyright (c) 2015 Intel Corporation - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#ifndef ZEPHYR_INCLUDE_ZEPHYR_H_ -#define ZEPHYR_INCLUDE_ZEPHYR_H_ - -#include - -#warning " is deprecated, include instead" - -#endif /* ZEPHYR_INCLUDE_ZEPHYR_H_ */ From 8adec6d74972587b40cec598739795be39efb2b4 Mon Sep 17 00:00:00 2001 From: Sylvio Alves Date: Fri, 14 Jun 2024 07:54:17 -0300 Subject: [PATCH 2745/2849] boards: docs: remove extra table line Remove extra table line present in a few esp32-based board to meet default style. Signed-off-by: Sylvio Alves --- boards/espressif/esp32_devkitc_wroom/doc/index.rst | 1 - boards/espressif/esp32_devkitc_wrover/doc/index.rst | 1 - boards/espressif/esp32c3_devkitm/doc/index.rst | 1 - boards/espressif/esp32s2_devkitc/doc/index.rst | 1 - boards/espressif/esp32s2_saola/doc/index.rst | 1 - boards/espressif/esp32s3_devkitc/doc/index.rst | 1 - boards/espressif/esp32s3_devkitm/doc/index.rst | 1 - boards/espressif/esp_wrover_kit/doc/index.rst | 1 - boards/luatos/esp32c3_luatos_core/doc/index.rst | 1 - boards/luatos/esp32s3_luatos_core/doc/index.rst | 1 - boards/seeed/xiao_esp32s3/doc/index.rst | 1 - boards/vcc-gnd/yd_esp32/doc/index.rst | 1 - 12 files changed, 12 deletions(-) diff --git a/boards/espressif/esp32_devkitc_wroom/doc/index.rst b/boards/espressif/esp32_devkitc_wroom/doc/index.rst index ec1248da38e7b..58106b69ab6e0 100644 --- a/boards/espressif/esp32_devkitc_wroom/doc/index.rst +++ b/boards/espressif/esp32_devkitc_wroom/doc/index.rst @@ -61,7 +61,6 @@ Current Zephyr's ESP32-WROOM board supports the following features: +------------+------------+-------------------------------------+ | Interface | Controller | Driver/Component | +============+============+=====================================+ -+------------+------------+-------------------------------------+ | UART | on-chip | serial port | +------------+------------+-------------------------------------+ | GPIO | on-chip | gpio | diff --git a/boards/espressif/esp32_devkitc_wrover/doc/index.rst b/boards/espressif/esp32_devkitc_wrover/doc/index.rst index 1f66f3da8a923..7a29912dfbc9d 100644 --- a/boards/espressif/esp32_devkitc_wrover/doc/index.rst +++ b/boards/espressif/esp32_devkitc_wrover/doc/index.rst @@ -61,7 +61,6 @@ Current Zephyr's ESP32-devkitc board supports the following features: +------------+------------+-------------------------------------+ | Interface | Controller | Driver/Component | +============+============+=====================================+ -+------------+------------+-------------------------------------+ | UART | on-chip | serial port | +------------+------------+-------------------------------------+ | GPIO | on-chip | gpio | diff --git a/boards/espressif/esp32c3_devkitm/doc/index.rst b/boards/espressif/esp32c3_devkitm/doc/index.rst index c2d6551170cfe..9028d0c3cabd2 100644 --- a/boards/espressif/esp32c3_devkitm/doc/index.rst +++ b/boards/espressif/esp32c3_devkitm/doc/index.rst @@ -40,7 +40,6 @@ Current Zephyr's ESP32-C3-Devkitm board supports the following features: +------------+------------+-------------------------------------+ | Interface | Controller | Driver/Component | +============+============+=====================================+ -+------------+------------+-------------------------------------+ | UART | on-chip | serial port | +------------+------------+-------------------------------------+ | GPIO | on-chip | gpio | diff --git a/boards/espressif/esp32s2_devkitc/doc/index.rst b/boards/espressif/esp32s2_devkitc/doc/index.rst index bfe8eb3fc7de1..427596e31473b 100644 --- a/boards/espressif/esp32s2_devkitc/doc/index.rst +++ b/boards/espressif/esp32s2_devkitc/doc/index.rst @@ -38,7 +38,6 @@ Current Zephyr's ESP32-S2-devkitc board supports the following features: +------------+------------+-------------------------------------+ | Interface | Controller | Driver/Component | +============+============+=====================================+ -+------------+------------+-------------------------------------+ | UART | on-chip | serial port | +------------+------------+-------------------------------------+ | GPIO | on-chip | gpio | diff --git a/boards/espressif/esp32s2_saola/doc/index.rst b/boards/espressif/esp32s2_saola/doc/index.rst index 1e7c1627fd132..485614db8e7d8 100644 --- a/boards/espressif/esp32s2_saola/doc/index.rst +++ b/boards/espressif/esp32s2_saola/doc/index.rst @@ -38,7 +38,6 @@ Current Zephyr's ESP32-S2-saola board supports the following features: +------------+------------+-------------------------------------+ | Interface | Controller | Driver/Component | +============+============+=====================================+ -+------------+------------+-------------------------------------+ | UART | on-chip | serial port | +------------+------------+-------------------------------------+ | GPIO | on-chip | gpio | diff --git a/boards/espressif/esp32s3_devkitc/doc/index.rst b/boards/espressif/esp32s3_devkitc/doc/index.rst index 60edc732b5687..a7d6c7d60d5ae 100644 --- a/boards/espressif/esp32s3_devkitc/doc/index.rst +++ b/boards/espressif/esp32s3_devkitc/doc/index.rst @@ -88,7 +88,6 @@ Current Zephyr's ESP32-S3-DevKitC board supports the following features: +------------+------------+-------------------------------------+ | Interface | Controller | Driver/Component | +============+============+=====================================+ -+------------+------------+-------------------------------------+ | UART | on-chip | serial port | +------------+------------+-------------------------------------+ | GPIO | on-chip | gpio | diff --git a/boards/espressif/esp32s3_devkitm/doc/index.rst b/boards/espressif/esp32s3_devkitm/doc/index.rst index abef4294733eb..17af80ed31869 100644 --- a/boards/espressif/esp32s3_devkitm/doc/index.rst +++ b/boards/espressif/esp32s3_devkitm/doc/index.rst @@ -88,7 +88,6 @@ Current Zephyr's ESP32-S3-DevKitM board supports the following features: +------------+------------+-------------------------------------+ | Interface | Controller | Driver/Component | +============+============+=====================================+ -+------------+------------+-------------------------------------+ | UART | on-chip | serial port | +------------+------------+-------------------------------------+ | GPIO | on-chip | gpio | diff --git a/boards/espressif/esp_wrover_kit/doc/index.rst b/boards/espressif/esp_wrover_kit/doc/index.rst index 521307376a054..fdef0efd6c709 100644 --- a/boards/espressif/esp_wrover_kit/doc/index.rst +++ b/boards/espressif/esp_wrover_kit/doc/index.rst @@ -447,7 +447,6 @@ Current Zephyr's ESP32-Wrover-Kit board supports the following features: +------------+------------+-------------------------------------+ | Interface | Controller | Driver/Component | +============+============+=====================================+ -+------------+------------+-------------------------------------+ | UART | on-chip | serial port | +------------+------------+-------------------------------------+ | GPIO | on-chip | gpio | diff --git a/boards/luatos/esp32c3_luatos_core/doc/index.rst b/boards/luatos/esp32c3_luatos_core/doc/index.rst index 7b6bbacf98213..21c9a7bfc5998 100644 --- a/boards/luatos/esp32c3_luatos_core/doc/index.rst +++ b/boards/luatos/esp32c3_luatos_core/doc/index.rst @@ -54,7 +54,6 @@ Current Zephyr's ESP32C3_LUATOS_CORE board supports the following features: +------------+------------+-------------------------------------+ | Interface | Controller | Driver/Component | +============+============+=====================================+ -+------------+------------+-------------------------------------+ | UART | on-chip | serial port | +------------+------------+-------------------------------------+ | GPIO | on-chip | gpio | diff --git a/boards/luatos/esp32s3_luatos_core/doc/index.rst b/boards/luatos/esp32s3_luatos_core/doc/index.rst index 1acb1bb15c59d..687851ea6a441 100644 --- a/boards/luatos/esp32s3_luatos_core/doc/index.rst +++ b/boards/luatos/esp32s3_luatos_core/doc/index.rst @@ -89,7 +89,6 @@ Current Zephyr's ESP32S3-LUATOS-Core board supports the following features: +------------+------------+-------------------------------------+ | Interface | Controller | Driver/Component | +============+============+=====================================+ -+------------+------------+-------------------------------------+ | UART | on-chip | serial port | +------------+------------+-------------------------------------+ | GPIO | on-chip | gpio | diff --git a/boards/seeed/xiao_esp32s3/doc/index.rst b/boards/seeed/xiao_esp32s3/doc/index.rst index bbb1bf528aef5..cca9a3d8a274f 100644 --- a/boards/seeed/xiao_esp32s3/doc/index.rst +++ b/boards/seeed/xiao_esp32s3/doc/index.rst @@ -38,7 +38,6 @@ Current Zephyr's XIAO ESP32S3 board supports the following features: +------------+------------+-------------------------------------+ | Interface | Controller | Driver/Component | +============+============+=====================================+ -+------------+------------+-------------------------------------+ | UART | on-chip | serial port | +------------+------------+-------------------------------------+ | GPIO | on-chip | gpio | diff --git a/boards/vcc-gnd/yd_esp32/doc/index.rst b/boards/vcc-gnd/yd_esp32/doc/index.rst index 433c1ac0c30ba..236d076dfcb3a 100644 --- a/boards/vcc-gnd/yd_esp32/doc/index.rst +++ b/boards/vcc-gnd/yd_esp32/doc/index.rst @@ -61,7 +61,6 @@ Current Zephyr's YD-ESP32 board supports the following features: +------------+------------+-------------------------------------+ | Interface | Controller | Driver/Component | +============+============+=====================================+ -+------------+------------+-------------------------------------+ | UART | on-chip | serial port | +------------+------------+-------------------------------------+ | GPIO | on-chip | gpio | From 3b94af2b5cd460dae1755f6622243cbd44f9ad6f Mon Sep 17 00:00:00 2001 From: Tom Burdick Date: Wed, 12 Jun 2024 10:46:29 -0500 Subject: [PATCH 2746/2849] sensors: Submit call returns void The integer return of sensor_submit should be void as the call is asynchronous and the response is meant to be delivered using RTIO APIs signaling that the submission completed with error or success. Change the function signature to void and fix all uses of the submit API, fixing some bugs in the process. Signed-off-by: Tom Burdick --- .../sensor/asahi_kasei/akm09918c/akm09918c.h | 2 +- .../asahi_kasei/akm09918c/akm09918c_async.c | 8 +++--- drivers/sensor/bosch/bma4xx/bma4xx.c | 26 +++++++++---------- drivers/sensor/bosch/bme280/bme280.h | 2 +- drivers/sensor/bosch/bme280/bme280_async.c | 10 +++---- drivers/sensor/tdk/icm42688/icm42688_rtio.c | 16 +++++------- drivers/sensor/tdk/icm42688/icm42688_rtio.h | 4 +-- include/zephyr/drivers/sensor.h | 2 +- subsys/sensing/sensing_sensor.c | 1 + .../sensing/sensor/hinge_angle/hinge_angle.c | 14 +++++----- .../sensor/phy_3d_sensor/phy_3d_sensor.c | 10 +++---- 11 files changed, 46 insertions(+), 49 deletions(-) diff --git a/drivers/sensor/asahi_kasei/akm09918c/akm09918c.h b/drivers/sensor/asahi_kasei/akm09918c/akm09918c.h index 742c7d3be3867..a4b35c64dd838 100644 --- a/drivers/sensor/asahi_kasei/akm09918c/akm09918c.h +++ b/drivers/sensor/asahi_kasei/akm09918c/akm09918c.h @@ -93,6 +93,6 @@ int akm09918c_sample_fetch_helper(const struct device *dev, enum sensor_channel int akm09918c_get_decoder(const struct device *dev, const struct sensor_decoder_api **decoder); -int akm09918c_submit(const struct device *dev, struct rtio_iodev_sqe *iodev_sqe); +void akm09918c_submit(const struct device *dev, struct rtio_iodev_sqe *iodev_sqe); #endif /* ZEPHYR_DRIVERS_SENSOR_AKM09918C_AKM09918C_H_ */ diff --git a/drivers/sensor/asahi_kasei/akm09918c/akm09918c_async.c b/drivers/sensor/asahi_kasei/akm09918c/akm09918c_async.c index 438ca24780d46..6fb5d901ec4d0 100644 --- a/drivers/sensor/asahi_kasei/akm09918c/akm09918c_async.c +++ b/drivers/sensor/asahi_kasei/akm09918c/akm09918c_async.c @@ -9,7 +9,7 @@ LOG_MODULE_DECLARE(AKM09918C, CONFIG_SENSOR_LOG_LEVEL); -int akm09918c_submit(const struct device *dev, struct rtio_iodev_sqe *iodev_sqe) +void akm09918c_submit(const struct device *dev, struct rtio_iodev_sqe *iodev_sqe) { uint32_t min_buf_len = sizeof(struct akm09918c_encoded_data); int rc; @@ -22,7 +22,7 @@ int akm09918c_submit(const struct device *dev, struct rtio_iodev_sqe *iodev_sqe) if (rc != 0) { LOG_ERR("Failed to get a read buffer of size %u bytes", min_buf_len); rtio_iodev_sqe_err(iodev_sqe, rc); - return rc; + return; } edata = (struct akm09918c_encoded_data *)buf; @@ -33,10 +33,8 @@ int akm09918c_submit(const struct device *dev, struct rtio_iodev_sqe *iodev_sqe) if (rc != 0) { LOG_ERR("Failed to fetch samples"); rtio_iodev_sqe_err(iodev_sqe, rc); - return rc; + return; } rtio_iodev_sqe_ok(iodev_sqe, 0); - - return 0; } diff --git a/drivers/sensor/bosch/bma4xx/bma4xx.c b/drivers/sensor/bosch/bma4xx/bma4xx.c index db717cc0c04e0..1d1609c64b36b 100644 --- a/drivers/sensor/bosch/bma4xx/bma4xx.c +++ b/drivers/sensor/bosch/bma4xx/bma4xx.c @@ -338,7 +338,7 @@ static int bma4xx_temp_fetch(const struct device *dev, int8_t *temp) * RTIO submit and encoding */ -static int bma4xx_submit_one_shot(const struct device *dev, struct rtio_iodev_sqe *iodev_sqe) +static void bma4xx_submit_one_shot(const struct device *dev, struct rtio_iodev_sqe *iodev_sqe) { struct bma4xx_data *bma4xx = dev->data; @@ -357,7 +357,7 @@ static int bma4xx_submit_one_shot(const struct device *dev, struct rtio_iodev_sq if (rc != 0) { LOG_ERR("Failed to get a read buffer of size %u bytes", min_buf_len); rtio_iodev_sqe_err(iodev_sqe, rc); - return rc; + return; } /* Prepare response */ @@ -372,7 +372,8 @@ static int bma4xx_submit_one_shot(const struct device *dev, struct rtio_iodev_sq for (int i = 0; i < num_channels; i++) { if (channels[i].chan_idx != 0) { LOG_ERR("Only channel index 0 supported"); - return -ENOTSUP; + rtio_iodev_sqe_err(iodev_sqe, -ENOTSUP); + return; } switch (channels[i].chan_type) { case SENSOR_CHAN_ALL: @@ -395,7 +396,8 @@ static int bma4xx_submit_one_shot(const struct device *dev, struct rtio_iodev_sq default: LOG_ERR("Requested unsupported channel type %d, idx %d", channels[i].chan_type, channels[i].chan_idx); - return -ENOTSUP; + rtio_iodev_sqe_err(iodev_sqe, -ENOTSUP); + return; } } @@ -405,7 +407,7 @@ static int bma4xx_submit_one_shot(const struct device *dev, struct rtio_iodev_sq if (rc != 0) { LOG_ERR("Failed to fetch accel samples"); rtio_iodev_sqe_err(iodev_sqe, rc); - return rc; + return; } } @@ -415,26 +417,24 @@ static int bma4xx_submit_one_shot(const struct device *dev, struct rtio_iodev_sq if (rc != 0) { LOG_ERR("Failed to fetch temp sample"); rtio_iodev_sqe_err(iodev_sqe, rc); - return rc; + return; } } #endif /* CONFIG_BMA4XX_TEMPERATURE */ rtio_iodev_sqe_ok(iodev_sqe, 0); - - return 0; } -static int bma4xx_submit(const struct device *dev, struct rtio_iodev_sqe *iodev_sqe) +static void bma4xx_submit(const struct device *dev, struct rtio_iodev_sqe *iodev_sqe) { const struct sensor_read_config *cfg = iodev_sqe->sqe.iodev->data; + /* TODO: Add streaming support */ if (!cfg->is_streaming) { - return bma4xx_submit_one_shot(dev, iodev_sqe); + bma4xx_submit_one_shot(dev, iodev_sqe); + } else { + rtio_iodev_sqe_err(iodev_sqe, -ENOTSUP); } - /* TODO: Add streaming support */ - - return -ENOTSUP; } /* diff --git a/drivers/sensor/bosch/bme280/bme280.h b/drivers/sensor/bosch/bme280/bme280.h index 125659cb58616..2499174d5e6d1 100644 --- a/drivers/sensor/bosch/bme280/bme280.h +++ b/drivers/sensor/bosch/bme280/bme280.h @@ -211,7 +211,7 @@ struct bme280_encoded_data { int bme280_get_decoder(const struct device *dev, const struct sensor_decoder_api **decoder); -int bme280_submit(const struct device *dev, struct rtio_iodev_sqe *iodev_sqe); +void bme280_submit(const struct device *dev, struct rtio_iodev_sqe *iodev_sqe); int bme280_sample_fetch(const struct device *dev, enum sensor_channel chan); diff --git a/drivers/sensor/bosch/bme280/bme280_async.c b/drivers/sensor/bosch/bme280/bme280_async.c index 562beb4f09058..780a7a28c1e40 100644 --- a/drivers/sensor/bosch/bme280/bme280_async.c +++ b/drivers/sensor/bosch/bme280/bme280_async.c @@ -9,7 +9,7 @@ LOG_MODULE_DECLARE(BME280, CONFIG_SENSOR_LOG_LEVEL); -int bme280_submit(const struct device *dev, struct rtio_iodev_sqe *iodev_sqe) +void bme280_submit(const struct device *dev, struct rtio_iodev_sqe *iodev_sqe) { uint32_t min_buf_len = sizeof(struct bme280_encoded_data); int rc; @@ -31,7 +31,7 @@ int bme280_submit(const struct device *dev, struct rtio_iodev_sqe *iodev_sqe) default: LOG_ERR("Unsupported channel type %d", channels[i].chan_type); rtio_iodev_sqe_err(iodev_sqe, -ENOTSUP); - return -ENOTSUP; + return; } } @@ -39,7 +39,7 @@ int bme280_submit(const struct device *dev, struct rtio_iodev_sqe *iodev_sqe) if (rc != 0) { LOG_ERR("Failed to get a read buffer of size %u bytes", min_buf_len); rtio_iodev_sqe_err(iodev_sqe, rc); - return rc; + return; } struct bme280_encoded_data *edata; @@ -52,10 +52,8 @@ int bme280_submit(const struct device *dev, struct rtio_iodev_sqe *iodev_sqe) if (rc != 0) { LOG_ERR("Failed to fetch samples"); rtio_iodev_sqe_err(iodev_sqe, rc); - return rc; + return; } rtio_iodev_sqe_ok(iodev_sqe, 0); - - return 0; } diff --git a/drivers/sensor/tdk/icm42688/icm42688_rtio.c b/drivers/sensor/tdk/icm42688/icm42688_rtio.c index ad00fd7abf25a..b9e86c3d9a188 100644 --- a/drivers/sensor/tdk/icm42688/icm42688_rtio.c +++ b/drivers/sensor/tdk/icm42688/icm42688_rtio.c @@ -43,7 +43,7 @@ static int icm42688_rtio_sample_fetch(const struct device *dev, int16_t readings return 0; } -static int icm42688_submit_one_shot(const struct device *dev, struct rtio_iodev_sqe *iodev_sqe) +static void 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 struct sensor_chan_spec *const channels = cfg->channels; @@ -59,7 +59,7 @@ static int icm42688_submit_one_shot(const struct device *dev, struct rtio_iodev_ if (rc != 0) { LOG_ERR("Failed to get a read buffer of size %u bytes", min_buf_len); rtio_iodev_sqe_err(iodev_sqe, rc); - return rc; + return; } edata = (struct icm42688_encoded_data *)buf; @@ -71,24 +71,22 @@ static int icm42688_submit_one_shot(const struct device *dev, struct rtio_iodev_ if (rc != 0) { LOG_ERR("Failed to fetch samples"); rtio_iodev_sqe_err(iodev_sqe, rc); - return rc; + return; } rtio_iodev_sqe_ok(iodev_sqe, 0); - - return 0; } -int icm42688_submit(const struct device *dev, struct rtio_iodev_sqe *iodev_sqe) +void icm42688_submit(const struct device *dev, struct rtio_iodev_sqe *iodev_sqe) { const struct sensor_read_config *cfg = iodev_sqe->sqe.iodev->data; if (!cfg->is_streaming) { - return icm42688_submit_one_shot(dev, iodev_sqe); + icm42688_submit_one_shot(dev, iodev_sqe); } else if (IS_ENABLED(CONFIG_ICM42688_STREAM)) { - return icm42688_submit_stream(dev, iodev_sqe); + icm42688_submit_stream(dev, iodev_sqe); } else { - return -ENOTSUP; + rtio_iodev_sqe_err(iodev_sqe, -ENOTSUP); } } diff --git a/drivers/sensor/tdk/icm42688/icm42688_rtio.h b/drivers/sensor/tdk/icm42688/icm42688_rtio.h index 888e8e95357ae..a4d12b82a1891 100644 --- a/drivers/sensor/tdk/icm42688/icm42688_rtio.h +++ b/drivers/sensor/tdk/icm42688/icm42688_rtio.h @@ -10,9 +10,9 @@ #include #include -int icm42688_submit(const struct device *sensor, struct rtio_iodev_sqe *iodev_sqe); +void icm42688_submit(const struct device *sensor, struct rtio_iodev_sqe *iodev_sqe); -int icm42688_submit_stream(const struct device *sensor, struct rtio_iodev_sqe *iodev_sqe); +void icm42688_submit_stream(const struct device *sensor, struct rtio_iodev_sqe *iodev_sqe); void icm42688_fifo_event(const struct device *dev); diff --git a/include/zephyr/drivers/sensor.h b/include/zephyr/drivers/sensor.h index 4e1a41c4e1d8e..a33a320f90304 100644 --- a/include/zephyr/drivers/sensor.h +++ b/include/zephyr/drivers/sensor.h @@ -687,7 +687,7 @@ struct sensor_read_config { RTIO_IODEV_DEFINE(name, &__sensor_iodev_api, &_CONCAT(__sensor_read_config_, name)) /* Used to submit an RTIO sqe to the sensor's iodev */ -typedef int (*sensor_submit_t)(const struct device *sensor, struct rtio_iodev_sqe *sqe); +typedef void (*sensor_submit_t)(const struct device *sensor, struct rtio_iodev_sqe *sqe); /* The default decoder API */ extern const struct sensor_decoder_api __sensor_default_decoder; diff --git a/subsys/sensing/sensing_sensor.c b/subsys/sensing/sensing_sensor.c index a2ebd9ff7d321..6bd68ce5b2c25 100644 --- a/subsys/sensing/sensing_sensor.c +++ b/subsys/sensing/sensing_sensor.c @@ -22,6 +22,7 @@ static void sensing_iodev_submit(struct rtio_iodev_sqe *iodev_sqe) if (api->submit != NULL) { api->submit(dev, iodev_sqe); } else { + LOG_ERR("submit function not supported for device %p %s!\n", dev, dev->name); rtio_iodev_sqe_err(iodev_sqe, -ENOTSUP); } } diff --git a/subsys/sensing/sensor/hinge_angle/hinge_angle.c b/subsys/sensing/sensor/hinge_angle/hinge_angle.c index 077f7ca37743a..db86f4081a3d6 100644 --- a/subsys/sensing/sensor/hinge_angle/hinge_angle.c +++ b/subsys/sensing/sensor/hinge_angle/hinge_angle.c @@ -79,17 +79,16 @@ static int hinge_attr_set(const struct device *dev, return ret; } -static int hinge_submit(const struct device *dev, +static void hinge_submit(const struct device *dev, struct rtio_iodev_sqe *sqe) { struct hinge_angle_context *data = dev->data; if (data->sqe) { - return -EBUSY; + rtio_iodev_sqe_err(sqe, -EBUSY); + } else { + data->sqe = sqe; } - - data->sqe = sqe; - return 0; } static const struct sensor_driver_api hinge_api = { @@ -146,7 +145,10 @@ static void hinge_reporter_on_data_event(sensing_sensor_handle_t handle, sample->readings[0].v = calc_hinge_angle(data); - rtio_iodev_sqe_ok(data->sqe, 0); + struct rtio_iodev_sqe *sqe = data->sqe; + + data->sqe = NULL; + rtio_iodev_sqe_ok(sqe, 0); } } diff --git a/subsys/sensing/sensor/phy_3d_sensor/phy_3d_sensor.c b/subsys/sensing/sensor/phy_3d_sensor/phy_3d_sensor.c index 3ad2e499fff1c..12f2026636dc9 100644 --- a/subsys/sensing/sensor/phy_3d_sensor/phy_3d_sensor.c +++ b/subsys/sensing/sensor/phy_3d_sensor/phy_3d_sensor.c @@ -159,7 +159,7 @@ static int phy_3d_sensor_attr_set(const struct device *dev, return ret; } -static int phy_3d_sensor_submit(const struct device *dev, +static void phy_3d_sensor_submit(const struct device *dev, struct rtio_iodev_sqe *sqe) { struct sensing_submit_config *config = (struct sensing_submit_config *)sqe->sqe.iodev->data; @@ -175,21 +175,21 @@ static int phy_3d_sensor_submit(const struct device *dev, (uint8_t **)&sample, &buffer_len); if (ret) { rtio_iodev_sqe_err(sqe, ret); - return ret; + return; } ret = sensor_sample_fetch_chan(cfg->hw_dev, custom->chan_all); if (ret) { LOG_ERR("%s: sample fetch failed: %d", dev->name, ret); rtio_iodev_sqe_err(sqe, ret); - return ret; + return; } ret = sensor_channel_get(cfg->hw_dev, custom->chan_all, value); if (ret) { LOG_ERR("%s: channel get failed: %d", dev->name, ret); rtio_iodev_sqe_err(sqe, ret); - return ret; + return; } for (i = 0; i < ARRAY_SIZE(value); ++i) { @@ -206,7 +206,7 @@ static int phy_3d_sensor_submit(const struct device *dev, sample->readings[0].z); rtio_iodev_sqe_ok(sqe, 0); - return 0; + return; } static const struct sensor_driver_api phy_3d_sensor_api = { From d9171df773683939002ef076e6f47b411dacef73 Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Tue, 11 Jun 2024 00:48:45 +0200 Subject: [PATCH 2747/2849] samples: Bluetooth: peripheral_hr restart advertising on disconnect Restart legacy advertising on ACL disconnect similar to when using extended advertising in this sample. Signed-off-by: Vinayak Kariappa Chettimada --- samples/bluetooth/peripheral_hr/src/main.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/samples/bluetooth/peripheral_hr/src/main.c b/samples/bluetooth/peripheral_hr/src/main.c index 7c1ab42ef2452..5081d93a64b32 100644 --- a/samples/bluetooth/peripheral_hr/src/main.c +++ b/samples/bluetooth/peripheral_hr/src/main.c @@ -281,7 +281,16 @@ int main(void) blink_stop(); #endif /* HAS_LED */ } else if (atomic_test_and_clear_bit(state, STATE_DISCONNECTED)) { -#if defined(CONFIG_BT_EXT_ADV) +#if !defined(CONFIG_BT_EXT_ADV) + printk("Starting Legacy Advertising (connectable and scannable)\n"); + err = bt_le_adv_start(BT_LE_ADV_CONN_ONE_TIME, ad, ARRAY_SIZE(ad), sd, + ARRAY_SIZE(sd)); + if (err) { + printk("Advertising failed to start (err %d)\n", err); + return 0; + } + +#else /* CONFIG_BT_EXT_ADV */ printk("Starting Extended Advertising (connectable and non-scannable)\n"); err = bt_le_ext_adv_start(adv, BT_LE_EXT_ADV_START_DEFAULT); if (err) { From 45aca35650a37d53fb045504706784605f0b0908 Mon Sep 17 00:00:00 2001 From: Piotr Kosycarz Date: Wed, 12 Jun 2024 16:36:20 +0200 Subject: [PATCH 2748/2849] samples: subsys: logging: multidomain: check console output on HW Verify host console. Signed-off-by: Piotr Kosycarz --- samples/subsys/logging/multidomain/sample.yaml | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/samples/subsys/logging/multidomain/sample.yaml b/samples/subsys/logging/multidomain/sample.yaml index 5fba4c3785364..10f67b9b2f8e6 100644 --- a/samples/subsys/logging/multidomain/sample.yaml +++ b/samples/subsys/logging/multidomain/sample.yaml @@ -4,28 +4,24 @@ common: sysbuild: true tags: ipc tests: - sample.logging.multidomain.ipc_static_vrings.hw: + sample.logging.multidomain.ipc_static_vrings: platform_allow: - nrf5340dk/nrf5340/cpuapp - integration_platforms: - - nrf5340dk/nrf5340/cpuapp - build_only: true - sample.logging.multidomain.ipc_static_vrings.simu: - platform_allow: - nrf5340bsim/nrf5340/cpuapp integration_platforms: + - nrf5340dk/nrf5340/cpuapp - nrf5340bsim/nrf5340/cpuapp harness: console harness_config: type: multi_line ordered: false regex: - - "IPC-service REMOTE \\[INST 1\\] demo started" + - "Hello World!" + - "app: IPC-service HOST \\[INST 1\\] demo started" - "app: loop: 0" - "app: ipc open" - "app: wait for bound" - "app: bounded" - "app: REMOTE \\[1\\]: 0" - "app: HOST \\[1\\]: 1" - - "IPC-service REMOTE \\[INST 1\\] demo ended." - "app: IPC-service HOST \\[INST 1\\] demo ended." From 3222f378ab11148cc50f5d00bca405be2773f7f8 Mon Sep 17 00:00:00 2001 From: Piotr Kosycarz Date: Wed, 12 Jun 2024 16:02:39 +0200 Subject: [PATCH 2749/2849] samples: subsys: ipc: ipc_service: check console output Verify host console. Signed-off-by: Piotr Kosycarz --- samples/subsys/ipc/ipc_service/icmsg/sample.yaml | 12 +++++++++++- .../ipc/ipc_service/multi_endpoint/sample.yaml | 14 ++++++++++++-- .../ipc/ipc_service/static_vrings/sample.yaml | 12 +++++++++++- 3 files changed, 34 insertions(+), 4 deletions(-) diff --git a/samples/subsys/ipc/ipc_service/icmsg/sample.yaml b/samples/subsys/ipc/ipc_service/icmsg/sample.yaml index af1f172d7097c..ee24fc1aec1b4 100644 --- a/samples/subsys/ipc/ipc_service/icmsg/sample.yaml +++ b/samples/subsys/ipc/ipc_service/icmsg/sample.yaml @@ -7,4 +7,14 @@ tests: - nrf5340dk/nrf5340/cpuapp tags: ipc sysbuild: true - harness: remote + harness: console + harness_config: + type: multi_line + ordered: false + regex: + - "host: IPC-service HOST demo started" + - "host: Ep bounded" + - "host: Perform sends for" + - "host: Sent" + - "host: Received" + - "host: IPC-service HOST demo ended" diff --git a/samples/subsys/ipc/ipc_service/multi_endpoint/sample.yaml b/samples/subsys/ipc/ipc_service/multi_endpoint/sample.yaml index c9ebfbadde1d3..b05c8f001f2c9 100644 --- a/samples/subsys/ipc/ipc_service/multi_endpoint/sample.yaml +++ b/samples/subsys/ipc/ipc_service/multi_endpoint/sample.yaml @@ -1,5 +1,17 @@ sample: name: IPC Service example integration (icmsg multi endpoint backend) +common: + harness: console + harness_config: + type: multi_line + ordered: false + regex: + - "IPC-service HOST \\[INST 0 - ENDP A\\] demo started" + - "IPC-service HOST \\[INST 0 - ENDP B\\] demo started" + - "IPC-service HOST \\[INST 1\\] demo started" + - "IPC-service HOST \\[INST 0 - ENDP A\\] demo ended\\." + - "IPC-service HOST \\[INST 0 - ENDP B\\] demo ended\\." + - "IPC-service HOST \\[INST 1\\] demo ended\\." tests: sample.ipc.multi_endpoint: platform_allow: nrf5340dk/nrf5340/cpuapp @@ -7,14 +19,12 @@ tests: - nrf5340dk/nrf5340/cpuapp tags: ipc sysbuild: true - harness: remote sample.ipc.multi_endpoint.icbmsg: platform_allow: nrf5340dk/nrf5340/cpuapp integration_platforms: - 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 diff --git a/samples/subsys/ipc/ipc_service/static_vrings/sample.yaml b/samples/subsys/ipc/ipc_service/static_vrings/sample.yaml index 0189185c83998..911b3624e44dc 100644 --- a/samples/subsys/ipc/ipc_service/static_vrings/sample.yaml +++ b/samples/subsys/ipc/ipc_service/static_vrings/sample.yaml @@ -12,4 +12,14 @@ tests: - nrf5340dk/nrf5340/cpuapp tags: ipc sysbuild: true - harness: remote + harness: console + harness_config: + type: multi_line + ordered: false + regex: + - "IPC-service HOST \\[INST 0 - ENDP A\\] demo started" + - "IPC-service HOST \\[INST 0 - ENDP B\\] demo started" + - "IPC-service HOST \\[INST 1\\] demo started" + - "IPC-service HOST \\[INST 0 - ENDP A\\] demo ended\\." + - "IPC-service HOST \\[INST 0 - ENDP B\\] demo ended\\." + - "IPC-service HOST \\[INST 1\\] demo ended\\." From b148178bd225e660ab2d741824f7ab49b6f0edad Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Fri, 7 Jun 2024 18:34:52 -0400 Subject: [PATCH 2750/2849] demand_paging: eviction/nru: fix pathological behavior Currently, the NRU algorithm always picks the lowest (and very often the same) clean unaccessed page over and over when e.g. doing large anonymous memory mappings. Spread the eviction selection more uniformly by by starting the search right after the last victim instead of always restarting from 0. Signed-off-by: Nicolas Pitre --- subsys/demand_paging/eviction/nru.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/subsys/demand_paging/eviction/nru.c b/subsys/demand_paging/eviction/nru.c index edf4ea01846b1..515c8ba3174f4 100644 --- a/subsys/demand_paging/eviction/nru.c +++ b/subsys/demand_paging/eviction/nru.c @@ -50,9 +50,17 @@ struct k_mem_page_frame *k_mem_paging_eviction_select(bool *dirty_ptr) bool accessed; bool last_dirty = false; bool dirty = false; - uintptr_t flags, phys; + uintptr_t flags; + uint32_t pf_idx; + static uint32_t last_pf_idx; + + /* similar to K_MEM_PAGE_FRAME_FOREACH except we don't always start at 0 */ + last_pf_idx = (last_pf_idx + 1) % ARRAY_SIZE(k_mem_page_frames); + pf_idx = last_pf_idx; + do { + pf = &k_mem_page_frames[pf_idx]; + pf_idx = (pf_idx + 1) % ARRAY_SIZE(k_mem_page_frames); - K_MEM_PAGE_FRAME_FOREACH(phys, pf) { unsigned int prec; if (!k_mem_page_frame_is_evictable(pf)) { @@ -84,10 +92,12 @@ struct k_mem_page_frame *k_mem_paging_eviction_select(bool *dirty_ptr) last_pf = pf; last_dirty = dirty; } - } + } while (pf_idx != last_pf_idx); + /* Shouldn't ever happen unless every page is pinned */ __ASSERT(last_pf != NULL, "no page to evict"); + last_pf_idx = last_pf - k_mem_page_frames; *dirty_ptr = last_dirty; return last_pf; From f908b411541603ba818b6c0aba152906f747c8ab Mon Sep 17 00:00:00 2001 From: Grzegorz Swiderski Date: Fri, 7 Jun 2024 11:55:31 +0200 Subject: [PATCH 2751/2849] soc: nordic: Resolve z_arm_platform_init in the linker generator Fixes #72673 Follow-up to #70977 and #71590 The CMake linker generator doesn't have an API equivalent to `PROVIDE`, but the existing `zephyr_linker_symbol()` function should do just fine. It still lets us set `z_arm_platform_init = SystemInit` and thus keep the reduced ROM space. Signed-off-by: Grzegorz Swiderski --- soc/nordic/common/CMakeLists.txt | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/soc/nordic/common/CMakeLists.txt b/soc/nordic/common/CMakeLists.txt index abf8b80d3fa18..513a3a968b89f 100644 --- a/soc/nordic/common/CMakeLists.txt +++ b/soc/nordic/common/CMakeLists.txt @@ -3,7 +3,13 @@ add_subdirectory_ifdef(CONFIG_RISCV_CORE_NORDIC_VPR vpr) -zephyr_linker_sources_ifdef(CONFIG_ARM SECTIONS arm_platform_init.ld) +if(CONFIG_ARM) + # Let SystemInit() be called in place of z_arm_platform_init() by default. + zephyr_linker_symbol(SYMBOL z_arm_platform_init EXPR "@SystemInit@") + + # This file is used when the CMake linker script generator is disabled. + zephyr_linker_sources(SECTIONS arm_platform_init.ld) +endif() zephyr_library_sources_ifdef(CONFIG_POWEROFF poweroff.c) From 7f2320ae08db75d1b18feaeb0e80405861228d50 Mon Sep 17 00:00:00 2001 From: Johann Fischer Date: Thu, 6 Jun 2024 18:29:32 +0200 Subject: [PATCH 2752/2849] doc: usb: include new HID device API Include new HID device API. Signed-off-by: Johann Fischer --- doc/connectivity/usb/device_next/api/index.rst | 1 + .../usb/device_next/api/usbd_hid_device.rst | 11 +++++++++++ 2 files changed, 12 insertions(+) create mode 100644 doc/connectivity/usb/device_next/api/usbd_hid_device.rst diff --git a/doc/connectivity/usb/device_next/api/index.rst b/doc/connectivity/usb/device_next/api/index.rst index bbc5bfc47a967..8e98d611134b1 100644 --- a/doc/connectivity/usb/device_next/api/index.rst +++ b/doc/connectivity/usb/device_next/api/index.rst @@ -8,3 +8,4 @@ New USB device support APIs udc.rst usbd.rst + usbd_hid_device.rst diff --git a/doc/connectivity/usb/device_next/api/usbd_hid_device.rst b/doc/connectivity/usb/device_next/api/usbd_hid_device.rst new file mode 100644 index 0000000000000..51a499a20503f --- /dev/null +++ b/doc/connectivity/usb/device_next/api/usbd_hid_device.rst @@ -0,0 +1,11 @@ +.. _usbd_hid_device: + +HID device API +############## + +HID device specific API defined in :zephyr_file:`include/zephyr/usb/class/usbd_hid.h`. + +API Reference +************* + +.. doxygengroup:: usbd_hid_device From 1d0616a33be5a8694f5135fd514a593370291ae7 Mon Sep 17 00:00:00 2001 From: Johann Fischer Date: Tue, 11 Jun 2024 15:53:21 +0200 Subject: [PATCH 2753/2849] doc: usb: include Audio Class 2 device API Include new Audio Class 2 device API. Signed-off-by: Johann Fischer --- doc/connectivity/usb/device_next/api/index.rst | 1 + .../usb/device_next/api/uac2_device.rst | 11 +++++++++++ include/zephyr/usb/class/usbd_uac2.h | 16 ++++++++++++++++ 3 files changed, 28 insertions(+) create mode 100644 doc/connectivity/usb/device_next/api/uac2_device.rst diff --git a/doc/connectivity/usb/device_next/api/index.rst b/doc/connectivity/usb/device_next/api/index.rst index 8e98d611134b1..d0ba69763221d 100644 --- a/doc/connectivity/usb/device_next/api/index.rst +++ b/doc/connectivity/usb/device_next/api/index.rst @@ -9,3 +9,4 @@ New USB device support APIs udc.rst usbd.rst usbd_hid_device.rst + uac2_device.rst diff --git a/doc/connectivity/usb/device_next/api/uac2_device.rst b/doc/connectivity/usb/device_next/api/uac2_device.rst new file mode 100644 index 0000000000000..bbe1fd0758b17 --- /dev/null +++ b/doc/connectivity/usb/device_next/api/uac2_device.rst @@ -0,0 +1,11 @@ +.. _uac2_device: + +Audio Class 2 device API +######################## + +USB Audio Class 2 device specific API defined in :zephyr_file:`include/zephyr/usb/class/usbd_uac2.h`. + +API Reference +************* + +.. doxygengroup:: uac2_device diff --git a/include/zephyr/usb/class/usbd_uac2.h b/include/zephyr/usb/class/usbd_uac2.h index bf76a21ce5338..22b599a2099c4 100644 --- a/include/zephyr/usb/class/usbd_uac2.h +++ b/include/zephyr/usb/class/usbd_uac2.h @@ -19,6 +19,18 @@ #include +/** + * @brief USB Audio Class 2 device API + * @defgroup uac2_device USB Audio Class 2 device API + * @ingroup usb + * @{ + */ + +/** + * @brief Get entity ID + * + * @param node node identifier + */ #define UAC2_ENTITY_ID(node) \ ({ \ BUILD_ASSERT(DT_NODE_HAS_COMPAT(DT_PARENT(node), zephyr_uac2)); \ @@ -139,4 +151,8 @@ void usbd_uac2_set_ops(const struct device *dev, int usbd_uac2_send(const struct device *dev, uint8_t terminal, void *data, uint16_t size); +/** + * @} + */ + #endif /* ZEPHYR_INCLUDE_USB_CLASS_USBD_UAC2_H_ */ From 9e80d4f9761489702ad68d105de8fde15e522a49 Mon Sep 17 00:00:00 2001 From: Johann Fischer Date: Thu, 6 Jun 2024 00:17:18 +0200 Subject: [PATCH 2754/2849] doc: usb: rework new USB device support overview description Rework new USB device support overview description. Signed-off-by: Johann Fischer --- .../usb/device_next/usb_device.rst | 99 +++++++++++-------- 1 file changed, 60 insertions(+), 39 deletions(-) diff --git a/doc/connectivity/usb/device_next/usb_device.rst b/doc/connectivity/usb/device_next/usb_device.rst index a9009d54e2b1f..a21da33fdf8c0 100644 --- a/doc/connectivity/usb/device_next/usb_device.rst +++ b/doc/connectivity/usb/device_next/usb_device.rst @@ -1,57 +1,78 @@ .. _usb_device_stack_next: -New experimental USB device support -################################### +New USB device support +###################### Overview ******** -The new USB device support is experimental. It consists of :ref:`udc_api` -and :ref:`usbd_api`. The new device stack brings support for multiple device -controllers, support for multiple configurations, and dynamic registration of -class instances to a configuration at runtime. The stack also provides a specific -class API that should be used to implement the functions (classes). -It will replace :ref:`usb_device_stack`. +USB device support consists of the USB device controller (UDC) drivers +, :ref:`udc_api`, and USB device stack, :ref:`usbd_api`. +The :ref:`udc_api` provides a generic and vendor independent interface to USB +device controllers, and although, there a is clear separation between these +layers, the purpose of :ref:`udc_api` is to serve new Zephyr's USB device stack +exclusively. -If you would like to play around with the new device support, or the new USB -support in general, please try :zephyr:code-sample:`usb-shell` sample. The sample is mainly to help -test the capabilities of the stack and correct implementation of the USB controller -drivers. +The new device stack supports multiple device controllers, meaning that if a +SoC has multiple controllers, they can be used simultaneously. Full and +high-speed device controllers are supported. It also provides support for +registering multiple function or class instances to a configuration at runtime, +or changing the configuration later. It has built-in support for several USB +classes and provides an API to implement custom USB functions. -Supported USB classes -********************* +The new USB device support is considered experimental and will replace +:ref:`usb_device_stack`. -Bluetooth HCI USB transport layer -================================= +Built-in functions +================== + +The USB device stack has built-in USB functions. Some can be used directly in +the user application through a special API, such as HID or Audio class devices, +while others use a general Zephyr RTOS driver API, such as MSC and CDC class +implementations. The *Identification string* identifies a class or function +instance (n) and is used as an argument to the :c:func:`usbd_register_class`. -See :ref:`bluetooth-hci-usb-sample` sample for reference. -To build the sample for the new device support, set the configuration -``-DCONF_FILE=usbd_next_prj.conf`` either directly or via ``west``. ++-----------------------------------+-------------------------+-------------------------+ +| Class or function | User API (if any) | Identification string | ++===================================+=========================+=========================+ +| USB Audio 2 class | :ref:`uac2_device` | uac2_(n) | ++-----------------------------------+-------------------------+-------------------------+ +| USB CDC ACM class | :ref:`uart_api` | cdc_acm_(n) | ++-----------------------------------+-------------------------+-------------------------+ +| USB CDC ECM class | Ethernet device | cdc_ecm_(n) | ++-----------------------------------+-------------------------+-------------------------+ +| USB Mass Storage Class (MSC) | :ref:`disk_access_api` | msc_(n) | ++-----------------------------------+-------------------------+-------------------------+ +| USB Human Interface Devices (HID) | :ref:`usbd_hid_device` | hid_(n) | ++-----------------------------------+-------------------------+-------------------------+ +| Bluetooth HCI USB transport layer | :ref:`bt_hci_raw` | bt_hci_(n) | ++-----------------------------------+-------------------------+-------------------------+ -CDC ACM +Samples ======= -CDC ACM implementation has support for multiple instances. -Description from :ref:`usb_device_cdc_acm` also applies to the new implementation. -See :zephyr:code-sample:`usb-cdc-acm` sample for reference. -To build the sample for the new device support, set the configuration -``-DCONF_FILE=usbd_next_prj.conf`` either directly or via ``west``. +* :zephyr:code-sample:`usb-hid-keyboard` -Mass Storage Class -================== +* :zephyr:code-sample:`uac2-explicit-feedback` + +Samples ported to new USB device support +---------------------------------------- + +To build a sample that supports both the old and new USB device stack, set the +configuration ``-DCONF_FILE=usbd_next_prj.conf`` either directly or via +``west``. + +* :ref:`bluetooth-hci-usb-sample` + +* :zephyr:code-sample:`usb-cdc-acm` -See :zephyr:code-sample:`usb-mass` sample for reference. -To build the sample for the new device support, set the configuration -``-DCONF_FILE=usbd_next_prj.conf`` either directly or via ``west``. +* :zephyr:code-sample:`usb-cdc-acm-console` -Networking -========== +* :zephyr:code-sample:`usb-mass` -At the moment only CDC ECM class is implemented and has support for multiple instances. -It provides a virtual Ethernet connection between the remote (USB host) and -Zephyr network support. +* :zephyr:code-sample:`usb-hid-mouse` -See :zephyr:code-sample:`zperf` for reference. -To build the sample for the new device support, set the configuration overlay file -``-DDEXTRA_CONF_FILE=overlay-usbd_next_ecm.conf`` and devicetree overlay file -``-DDTC_OVERLAY_FILE="usbd_next_ecm.overlay`` either directly or via ``west``. +* :zephyr:code-sample:`zperf` To build the sample for the new device support, + set the configuration overlay file + ``-DDEXTRA_CONF_FILE=overlay-usbd_next_ecm.conf`` and devicetree overlay file + ``-DDTC_OVERLAY_FILE="usbd_next_ecm.overlay`` either directly or via ``west``. From 4191602f117d2c6f9de9d10615d6ba3c98dcac4c Mon Sep 17 00:00:00 2001 From: Johann Fischer Date: Fri, 7 Jun 2024 14:48:19 +0200 Subject: [PATCH 2755/2849] usb: device_next: add helper to register all available class instances Add helper to register/unregister all available class instances. Signed-off-by: Johann Fischer --- include/zephyr/usb/usbd.h | 38 ++++++++++++- subsys/usb/device_next/usbd_class.c | 72 +++++++++++++++++++++++++ tests/subsys/usb/device_next/src/main.c | 12 +++++ 3 files changed, 120 insertions(+), 2 deletions(-) diff --git a/include/zephyr/usb/usbd.h b/include/zephyr/usb/usbd.h index 7afc27656ee9d..7a643b15db014 100644 --- a/include/zephyr/usb/usbd.h +++ b/include/zephyr/usb/usbd.h @@ -660,7 +660,7 @@ int usbd_add_configuration(struct usbd_context *uds_ctx, * @param[in] uds_ctx Pointer to USB device support context * @param[in] name Class instance name * @param[in] speed Configuration speed - * @param[in] cfg Configuration value (similar to bConfigurationValue) + * @param[in] cfg Configuration value (bConfigurationValue) * * @return 0 on success, other values on fail. */ @@ -668,6 +668,25 @@ int usbd_register_class(struct usbd_context *uds_ctx, const char *name, const enum usbd_speed speed, uint8_t cfg); +/** + * @brief Register all available USB class instances + * + * Register all available instances. Like usbd_register_class, but does not + * take the instance name and instead registers all available instances. + * + * @note This cannot be combined. If your application calls + * usbd_register_class for any device, configuration number, or instance, + * either usbd_register_class or this function will fail. + * + * @param[in] uds_ctx Pointer to USB device support context + * @param[in] speed Configuration speed + * @param[in] cfg Configuration value (bConfigurationValue) + * + * @return 0 on success, other values on fail. + */ +int usbd_register_all_classes(struct usbd_context *uds_ctx, + const enum usbd_speed speed, uint8_t cfg); + /** * @brief Unregister an USB class instance * @@ -678,7 +697,7 @@ int usbd_register_class(struct usbd_context *uds_ctx, * @param[in] uds_ctx Pointer to USB device support context * @param[in] name Class instance name * @param[in] speed Configuration speed - * @param[in] cfg Configuration value (similar to bConfigurationValue) + * @param[in] cfg Configuration value (bConfigurationValue) * * @return 0 on success, other values on fail. */ @@ -686,6 +705,21 @@ int usbd_unregister_class(struct usbd_context *uds_ctx, const char *name, const enum usbd_speed speed, uint8_t cfg); +/** + * @brief Unregister all available USB class instances + * + * Unregister all available instances. Like usbd_unregister_class, but does not + * take the instance name and instead unregisters all available instances. + * + * @param[in] uds_ctx Pointer to USB device support context + * @param[in] speed Configuration speed + * @param[in] cfg Configuration value (bConfigurationValue) + * + * @return 0 on success, other values on fail. + */ +int usbd_unregister_all_classes(struct usbd_context *uds_ctx, + const enum usbd_speed speed, uint8_t cfg); + /** * @brief Register USB notification message callback * diff --git a/subsys/usb/device_next/usbd_class.c b/subsys/usb/device_next/usbd_class.c index 265bffbe947a2..465480bd0e3fe 100644 --- a/subsys/usb/device_next/usbd_class.c +++ b/subsys/usb/device_next/usbd_class.c @@ -340,6 +340,42 @@ int usbd_register_class(struct usbd_context *const uds_ctx, return ret; } +int usbd_register_all_classes(struct usbd_context *const uds_ctx, + const enum usbd_speed speed, const uint8_t cfg) +{ + int ret; + + if (speed == USBD_SPEED_HS) { + STRUCT_SECTION_FOREACH_ALTERNATE(usbd_class_hs, usbd_class_node, c_nd) { + ret = usbd_register_class(uds_ctx, c_nd->c_data->name, + speed, cfg); + if (ret) { + LOG_ERR("Failed to register %s to HS configuration %u", + c_nd->c_data->name, cfg); + return ret; + } + } + + return 0; + } + + if (speed == USBD_SPEED_FS) { + STRUCT_SECTION_FOREACH_ALTERNATE(usbd_class_fs, usbd_class_node, c_nd) { + ret = usbd_register_class(uds_ctx, c_nd->c_data->name, + speed, cfg); + if (ret) { + LOG_ERR("Failed to register %s to FS configuration %u", + c_nd->c_data->name, cfg); + return ret; + } + } + + return 0; + } + + return -ENOTSUP; +} + int usbd_unregister_class(struct usbd_context *const uds_ctx, const char *name, const enum usbd_speed speed, const uint8_t cfg) @@ -407,3 +443,39 @@ int usbd_unregister_class(struct usbd_context *const uds_ctx, usbd_device_unlock(uds_ctx); return ret; } + +int usbd_unregister_all_classes(struct usbd_context *const uds_ctx, + const enum usbd_speed speed, const uint8_t cfg) +{ + int ret; + + if (speed == USBD_SPEED_HS) { + STRUCT_SECTION_FOREACH_ALTERNATE(usbd_class_hs, usbd_class_node, c_nd) { + ret = usbd_unregister_class(uds_ctx, c_nd->c_data->name, + speed, cfg); + if (ret) { + LOG_ERR("Failed to unregister %s to HS configuration %u", + c_nd->c_data->name, cfg); + return ret; + } + } + + return 0; + } + + if (speed == USBD_SPEED_FS) { + STRUCT_SECTION_FOREACH_ALTERNATE(usbd_class_fs, usbd_class_node, c_nd) { + ret = usbd_unregister_class(uds_ctx, c_nd->c_data->name, + speed, cfg); + if (ret) { + LOG_ERR("Failed to unregister %s to FS configuration %u", + c_nd->c_data->name, cfg); + return ret; + } + } + + return 0; + } + + return -ENOTSUP; +} diff --git a/tests/subsys/usb/device_next/src/main.c b/tests/subsys/usb/device_next/src/main.c index 5d6a9da703909..f33b054fcd147 100644 --- a/tests/subsys/usb/device_next/src/main.c +++ b/tests/subsys/usb/device_next/src/main.c @@ -134,10 +134,22 @@ static void *usb_test_enable(void) zassert_equal(err, 0, "Failed to add configuration (%d)"); if (usbd_caps_speed(&test_usbd) == USBD_SPEED_HS) { + err = usbd_register_all_classes(&test_usbd, USBD_SPEED_HS, 1); + zassert_equal(err, 0, "Failed to unregister all instances(%d)"); + + err = usbd_unregister_all_classes(&test_usbd, USBD_SPEED_HS, 1); + zassert_equal(err, 0, "Failed to unregister all instances(%d)"); + err = usbd_register_class(&test_usbd, "loopback_0", USBD_SPEED_HS, 1); zassert_equal(err, 0, "Failed to register loopback_0 class (%d)"); } + err = usbd_register_all_classes(&test_usbd, USBD_SPEED_FS, 1); + zassert_equal(err, 0, "Failed to unregister all instances(%d)"); + + err = usbd_unregister_all_classes(&test_usbd, USBD_SPEED_FS, 1); + zassert_equal(err, 0, "Failed to unregister all instances(%d)"); + err = usbd_register_class(&test_usbd, "loopback_0", USBD_SPEED_FS, 1); zassert_equal(err, 0, "Failed to register loopback_0 class (%d)"); From cf2113e43788ce5e5f55fcf8f8f742a65b35d477 Mon Sep 17 00:00:00 2001 From: Johann Fischer Date: Fri, 7 Jun 2024 15:29:03 +0200 Subject: [PATCH 2756/2849] samples: usb: rework common code to use usbd_register_all_classes() Rework common USB samples code to use usbd_register_all_classes(). Signed-off-by: Johann Fischer --- samples/subsys/usb/common/sample_usbd_init.c | 90 +++++--------------- 1 file changed, 22 insertions(+), 68 deletions(-) diff --git a/samples/subsys/usb/common/sample_usbd_init.c b/samples/subsys/usb/common/sample_usbd_init.c index 14fd43993e664..2c559aa789a42 100644 --- a/samples/subsys/usb/common/sample_usbd_init.c +++ b/samples/subsys/usb/common/sample_usbd_init.c @@ -9,7 +9,6 @@ #include #include #include -#include #include LOG_MODULE_REGISTER(usbd_sample_config); @@ -51,68 +50,9 @@ static const struct usb_bos_capability_lpm bos_cap_lpm = { USBD_DESC_BOS_DEFINE(sample_usbext, sizeof(bos_cap_lpm), &bos_cap_lpm); -static int register_fs_classes(struct usbd_context *uds_ctx) +static void sample_fix_code_triple(struct usbd_context *uds_ctx, + const enum usbd_speed speed) { - int err = 0; - - STRUCT_SECTION_FOREACH_ALTERNATE(usbd_class_fs, usbd_class_node, c_nd) { - /* Pull everything that is enabled in our configuration. */ - err = usbd_register_class(uds_ctx, c_nd->c_data->name, - USBD_SPEED_FS, 1); - if (err) { - LOG_ERR("Failed to register FS %s (%d)", - c_nd->c_data->name, err); - return err; - } - - LOG_DBG("Register FS %s", c_nd->c_data->name); - } - - return err; -} - -static int register_hs_classes(struct usbd_context *uds_ctx) -{ - int err = 0; - - STRUCT_SECTION_FOREACH_ALTERNATE(usbd_class_hs, usbd_class_node, c_nd) { - /* Pull everything that is enabled in our configuration. */ - err = usbd_register_class(uds_ctx, c_nd->c_data->name, - USBD_SPEED_HS, 1); - if (err) { - LOG_ERR("Failed to register HS %s (%d)", - c_nd->c_data->name, err); - return err; - } - - LOG_DBG("Register HS %s", c_nd->c_data->name); - } - - return err; -} - -static int sample_add_configuration(struct usbd_context *uds_ctx, - const enum usbd_speed speed, - struct usbd_config_node *config) -{ - int err; - - err = usbd_add_configuration(uds_ctx, speed, config); - if (err) { - LOG_ERR("Failed to add configuration (%d)", err); - return err; - } - - if (speed == USBD_SPEED_FS) { - err = register_fs_classes(uds_ctx); - } else if (speed == USBD_SPEED_HS) { - err = register_hs_classes(uds_ctx); - } - - if (err) { - return err; - } - /* Always use class code information from Interface Descriptors */ if (IS_ENABLED(CONFIG_USBD_CDC_ACM_CLASS) || IS_ENABLED(CONFIG_USBD_CDC_ECM_CLASS) || @@ -127,8 +67,6 @@ static int sample_add_configuration(struct usbd_context *uds_ctx, } else { usbd_device_set_code_triple(uds_ctx, speed, 0, 0, 0); } - - return 0; } struct usbd_context *sample_usbd_init_device(usbd_msg_cb_t msg_cb) @@ -160,21 +98,37 @@ struct usbd_context *sample_usbd_init_device(usbd_msg_cb_t msg_cb) } if (usbd_caps_speed(&sample_usbd) == USBD_SPEED_HS) { - err = sample_add_configuration(&sample_usbd, USBD_SPEED_HS, - &sample_hs_config); + err = usbd_add_configuration(&sample_usbd, USBD_SPEED_HS, + &sample_hs_config); if (err) { LOG_ERR("Failed to add High-Speed configuration"); return NULL; } + + err = usbd_register_all_classes(&sample_usbd, USBD_SPEED_HS, 1); + if (err) { + LOG_ERR("Failed to add register classes"); + return NULL; + } + + sample_fix_code_triple(&sample_usbd, USBD_SPEED_HS); } - err = sample_add_configuration(&sample_usbd, USBD_SPEED_FS, - &sample_fs_config); + err = usbd_add_configuration(&sample_usbd, USBD_SPEED_FS, + &sample_fs_config); if (err) { LOG_ERR("Failed to add Full-Speed configuration"); return NULL; } + err = usbd_register_all_classes(&sample_usbd, USBD_SPEED_FS, 1); + if (err) { + LOG_ERR("Failed to add register classes"); + return NULL; + } + + sample_fix_code_triple(&sample_usbd, USBD_SPEED_FS); + if (msg_cb != NULL) { err = usbd_msg_register_cb(&sample_usbd, msg_cb); if (err) { From 8739efe0fc603dc8e413c8006f1ecb6044330351 Mon Sep 17 00:00:00 2001 From: Johann Fischer Date: Thu, 6 Jun 2024 18:33:12 +0200 Subject: [PATCH 2757/2849] doc: usb: add initial USB device configuraiton howto Add initial documentation how to configure and enable new USB device support. Use literalinclude to pull code snippets from the samples. Signed-off-by: Johann Fischer --- .../usb/device_next/usb_device.rst | 109 ++++++++++++++++++ samples/subsys/usb/common/sample_usbd_init.c | 23 ++++ samples/subsys/usb/hid-keyboard/src/main.c | 2 + 3 files changed, 134 insertions(+) diff --git a/doc/connectivity/usb/device_next/usb_device.rst b/doc/connectivity/usb/device_next/usb_device.rst index a21da33fdf8c0..852da003cef06 100644 --- a/doc/connectivity/usb/device_next/usb_device.rst +++ b/doc/connectivity/usb/device_next/usb_device.rst @@ -76,3 +76,112 @@ configuration ``-DCONF_FILE=usbd_next_prj.conf`` either directly or via set the configuration overlay file ``-DDEXTRA_CONF_FILE=overlay-usbd_next_ecm.conf`` and devicetree overlay file ``-DDTC_OVERLAY_FILE="usbd_next_ecm.overlay`` either directly or via ``west``. + +How to configure and enable USB device support +********************************************** + +For the USB device support samples in the Zephyr project repository, we have a +common file for instantiation, configuration and initialization, +:zephyr_file:`samples/subsys/usb/common/sample_usbd_init.c`. The following code +snippets from this file are used as examples. USB Samples Kconfig options used +in the USB samples and prefixed with ``SAMPLE_USBD_`` have default values +specific to the Zephyr project and the scope is limited to the project samples. +In the examples below, you will need to replace these Kconfig options and other +defaults with values appropriate for your application or hardware. + +The USB device stack requires a context structure to manage its properties and +runtime data. The preferred way to define a device context is to use the +:c:macro:`USBD_DEVICE_DEFINE` macro. This creates a static +:c:struct:`usbd_context` variable with a given name. Any number of contexts may +be instantiated. A USB controller device can be assigned to multiple contexts, +but only one context can be initialized and used at a time. Context properties +must not be directly accessed or manipulated by the application. + +.. literalinclude:: ../../../../samples/subsys/usb/common/sample_usbd_init.c + :language: c + :start-after: doc device instantiation start + :end-before: doc device instantiation end + +Your USB device may have manufacturer, product, and serial number string +descriptors. To instantiate these string descriptors, the application should +use the appropriate :c:macro:`USBD_DESC_MANUFACTURER_DEFINE`, +:c:macro:`USBD_DESC_PRODUCT_DEFINE`, and +:c:macro:`USBD_DESC_SERIAL_NUMBER_DEFINE` macros. String descriptors also +require a single instantiation of the language descriptor using the +:c:macro:`USBD_DESC_LANG_DEFINE` macro. + +.. literalinclude:: ../../../../samples/subsys/usb/common/sample_usbd_init.c + :language: c + :start-after: doc string instantiation start + :end-before: doc string instantiation end + +String descriptors must be added to the device context at runtime before +initializing the USB device with :c:func:`usbd_add_descriptor`. + +.. literalinclude:: ../../../../samples/subsys/usb/common/sample_usbd_init.c + :language: c + :start-after: doc add string descriptor start + :end-before: doc add string descriptor end + +USB device requires at least one configuration instance per supported speed. +The application should use :c:macro:`USBD_CONFIGURATION_DEFINE` to instantiate +a configuration. Later, USB device functions are assigned to a configuration. + +.. literalinclude:: ../../../../samples/subsys/usb/common/sample_usbd_init.c + :language: c + :start-after: doc configuration instantiation start + :end-before: doc configuration instantiation end + +Each configuration instance for a specific speed must be added to the device +context at runtime before the USB device is initialized using +:c:func:`usbd_add_configuration`. Note :c:enumerator:`USBD_SPEED_FS` and +:c:enumerator:`USBD_SPEED_HS`. The first full-speed or high-speed +configuration will get ``bConfigurationValue`` one, and then further upward. + +.. literalinclude:: ../../../../samples/subsys/usb/common/sample_usbd_init.c + :language: c + :start-after: doc configuration register start + :end-before: doc configuration register end + + +Although we have already done a lot, this USB device has no function. A device +can have multiple configurations with different set of functions at different +speeds. A function or class can be registered on a USB device before +it is initialized using :c:func:`usbd_register_class`. The desired +configuration is specified using :c:enumerator:`USBD_SPEED_FS` or +:c:enumerator:`USBD_SPEED_HS` and the configuration number. For simple cases, +:c:func:`usbd_register_all_classes` can be used to register all available +instances. + +.. literalinclude:: ../../../../samples/subsys/usb/common/sample_usbd_init.c + :language: c + :start-after: doc functions register start + :end-before: doc functions register end + +The last step in the preparation is to initialize the device with +:c:func:`usbd_init`. After this, the configuration of the device cannot be +changed. A device can be deinitialized with :c:func:`usbd_shutdown` and all +instances can be reused, but the previous steps must be repeated. So it is +possible to shutdown a device, register another type of configuration or +function, and initialize it again. At the USB controller level, +:c:func:`usbd_init` does only what is necessary to detect VBUS changes. There +are controller types where the next step is only possible if a VBUS signal is +present. + +A function or class implementation may require its own specific configuration +steps, which should be performed prior to initializing the USB device. + +.. literalinclude:: ../../../../samples/subsys/usb/common/sample_usbd_init.c + :language: c + :start-after: doc device init start + :end-before: doc device init end + +The final step to enable the USB device is :c:func:`usbd_enable`, after that, +if the USB device is connected to a USB host controller, the host can start +enumerating the device. The application can disable the USB device using +:c:func:`usbd_disable`. + +.. literalinclude:: ../../../../samples/subsys/usb/hid-keyboard/src/main.c + :language: c + :start-after: doc device enable start + :end-before: doc device enable end diff --git a/samples/subsys/usb/common/sample_usbd_init.c b/samples/subsys/usb/common/sample_usbd_init.c index 2c559aa789a42..f6b2963b21297 100644 --- a/samples/subsys/usb/common/sample_usbd_init.c +++ b/samples/subsys/usb/common/sample_usbd_init.c @@ -15,27 +15,40 @@ LOG_MODULE_REGISTER(usbd_sample_config); #define ZEPHYR_PROJECT_USB_VID 0x2fe3 +/* doc device instantiation start */ +/* + * Instantiate a context named sample_usbd using the default USB device + * controller, the Zephyr project vendor ID, and the sample product ID. + * Zephyr project vendor ID must not be used outside of Zephyr samples. + */ USBD_DEVICE_DEFINE(sample_usbd, DEVICE_DT_GET(DT_NODELABEL(zephyr_udc0)), ZEPHYR_PROJECT_USB_VID, CONFIG_SAMPLE_USBD_PID); +/* doc device instantiation end */ +/* doc string instantiation start */ 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); +/* doc string instantiation end */ +/* doc configuration instantiation start */ static const uint8_t attributes = (IS_ENABLED(CONFIG_SAMPLE_USBD_SELF_POWERED) ? USB_SCD_SELF_POWERED : 0) | (IS_ENABLED(CONFIG_SAMPLE_USBD_REMOTE_WAKEUP) ? USB_SCD_REMOTE_WAKEUP : 0); +/* Full speed configuration */ USBD_CONFIGURATION_DEFINE(sample_fs_config, attributes, CONFIG_SAMPLE_USBD_MAX_POWER); +/* High speed configuration */ USBD_CONFIGURATION_DEFINE(sample_hs_config, attributes, CONFIG_SAMPLE_USBD_MAX_POWER); +/* doc configuration instantiation end */ /* * This does not yet provide valuable information, but rather serves as an @@ -73,6 +86,7 @@ struct usbd_context *sample_usbd_init_device(usbd_msg_cb_t msg_cb) { int err; + /* doc add string descriptor start */ err = usbd_add_descriptor(&sample_usbd, &sample_lang); if (err) { LOG_ERR("Failed to initialize language descriptor (%d)", err); @@ -96,6 +110,7 @@ struct usbd_context *sample_usbd_init_device(usbd_msg_cb_t msg_cb) LOG_ERR("Failed to initialize SN descriptor (%d)", err); return NULL; } + /* doc add string descriptor end */ if (usbd_caps_speed(&sample_usbd) == USBD_SPEED_HS) { err = usbd_add_configuration(&sample_usbd, USBD_SPEED_HS, @@ -114,21 +129,26 @@ struct usbd_context *sample_usbd_init_device(usbd_msg_cb_t msg_cb) sample_fix_code_triple(&sample_usbd, USBD_SPEED_HS); } + /* doc configuration register start */ err = usbd_add_configuration(&sample_usbd, USBD_SPEED_FS, &sample_fs_config); if (err) { LOG_ERR("Failed to add Full-Speed configuration"); return NULL; } + /* doc configuration register end */ + /* doc functions register start */ err = usbd_register_all_classes(&sample_usbd, USBD_SPEED_FS, 1); if (err) { LOG_ERR("Failed to add register classes"); return NULL; } + /* doc functions register end */ sample_fix_code_triple(&sample_usbd, USBD_SPEED_FS); + /* doc message callback register start */ if (msg_cb != NULL) { err = usbd_msg_register_cb(&sample_usbd, msg_cb); if (err) { @@ -136,6 +156,7 @@ struct usbd_context *sample_usbd_init_device(usbd_msg_cb_t msg_cb) return NULL; } } + /* doc message callback register end */ if (IS_ENABLED(CONFIG_SAMPLE_USBD_20_EXTENSION_DESC)) { (void)usbd_device_set_bcd(&sample_usbd, USBD_SPEED_FS, 0x0201); @@ -148,11 +169,13 @@ struct usbd_context *sample_usbd_init_device(usbd_msg_cb_t msg_cb) } } + /* doc device init start */ err = usbd_init(&sample_usbd); if (err) { LOG_ERR("Failed to initialize device support"); return NULL; } + /* doc device init end */ return &sample_usbd; } diff --git a/samples/subsys/usb/hid-keyboard/src/main.c b/samples/subsys/usb/hid-keyboard/src/main.c index 393edfcf06af3..b56fe26c0c7f9 100644 --- a/samples/subsys/usb/hid-keyboard/src/main.c +++ b/samples/subsys/usb/hid-keyboard/src/main.c @@ -184,11 +184,13 @@ int main(void) return -ENODEV; } + /* doc device enable start */ ret = usbd_enable(sample_usbd); if (ret) { LOG_ERR("Failed to enable device support"); return ret; } + /* doc device enable end */ LOG_INF("HID keyboard sample is initialized"); From bfba19dc41dd69a62d9a59e76dbda2888f392519 Mon Sep 17 00:00:00 2001 From: Rubin Gerritsen Date: Thu, 6 Jun 2024 10:51:44 +0200 Subject: [PATCH 2758/2849] Bluetooth: Host: Add the API bt_hci_err_to_str() This API converts a HCI error code to a string. This can be useful if application developers want to print them in the applications. Later we can also use them in the host to improve debuggability. Signed-off-by: Rubin Gerritsen --- include/zephyr/bluetooth/hci.h | 14 +++++ subsys/bluetooth/common/bt_str.c | 85 ++++++++++++++++++++++++++++++ tests/bluetooth/hci/CMakeLists.txt | 7 +++ tests/bluetooth/hci/prj.conf | 6 +++ tests/bluetooth/hci/src/main.c | 37 +++++++++++++ tests/bluetooth/hci/testcase.yaml | 8 +++ 6 files changed, 157 insertions(+) create mode 100644 tests/bluetooth/hci/CMakeLists.txt create mode 100644 tests/bluetooth/hci/prj.conf create mode 100644 tests/bluetooth/hci/src/main.c create mode 100644 tests/bluetooth/hci/testcase.yaml diff --git a/include/zephyr/bluetooth/hci.h b/include/zephyr/bluetooth/hci.h index c0ea108023c34..7dfcb2275270f 100644 --- a/include/zephyr/bluetooth/hci.h +++ b/include/zephyr/bluetooth/hci.h @@ -20,6 +20,20 @@ extern "C" { #endif +/** Converts a HCI error to string. + * + * The error codes are described in the Bluetooth Core specification, + * Vol 1, Part F, Section 2. + * + * The HCI documentation found in Vol 4, Part E, + * describes when the different error codes are used. + * + * See also the defined BT_HCI_ERR_* macros. + * + * @return The string representation of the HCI error code. + */ +const char *bt_hci_err_to_str(uint8_t hci_err); + /** Allocate a HCI command buffer. * * This function allocates a new buffer for a HCI command. It is given diff --git a/subsys/bluetooth/common/bt_str.c b/subsys/bluetooth/common/bt_str.c index 2e4c3cfa23682..0824793198918 100644 --- a/subsys/bluetooth/common/bt_str.c +++ b/subsys/bluetooth/common/bt_str.c @@ -61,3 +61,88 @@ const char *bt_uuid_str(const struct bt_uuid *uuid) return str; } + +const char *bt_hci_err_to_str(uint8_t hci_err) +{ + #define HCI_ERR(err) [err] = #err + + const char * const mapping_table[] = { + HCI_ERR(BT_HCI_ERR_SUCCESS), + HCI_ERR(BT_HCI_ERR_UNKNOWN_CMD), + HCI_ERR(BT_HCI_ERR_UNKNOWN_CONN_ID), + HCI_ERR(BT_HCI_ERR_HW_FAILURE), + HCI_ERR(BT_HCI_ERR_PAGE_TIMEOUT), + HCI_ERR(BT_HCI_ERR_AUTH_FAIL), + HCI_ERR(BT_HCI_ERR_PIN_OR_KEY_MISSING), + HCI_ERR(BT_HCI_ERR_MEM_CAPACITY_EXCEEDED), + HCI_ERR(BT_HCI_ERR_CONN_TIMEOUT), + HCI_ERR(BT_HCI_ERR_CONN_LIMIT_EXCEEDED), + HCI_ERR(BT_HCI_ERR_SYNC_CONN_LIMIT_EXCEEDED), + HCI_ERR(BT_HCI_ERR_CONN_ALREADY_EXISTS), + HCI_ERR(BT_HCI_ERR_CMD_DISALLOWED), + HCI_ERR(BT_HCI_ERR_INSUFFICIENT_RESOURCES), + HCI_ERR(BT_HCI_ERR_INSUFFICIENT_SECURITY), + HCI_ERR(BT_HCI_ERR_BD_ADDR_UNACCEPTABLE), + HCI_ERR(BT_HCI_ERR_CONN_ACCEPT_TIMEOUT), + HCI_ERR(BT_HCI_ERR_UNSUPP_FEATURE_PARAM_VAL), + HCI_ERR(BT_HCI_ERR_INVALID_PARAM), + HCI_ERR(BT_HCI_ERR_REMOTE_USER_TERM_CONN), + HCI_ERR(BT_HCI_ERR_REMOTE_LOW_RESOURCES), + HCI_ERR(BT_HCI_ERR_REMOTE_POWER_OFF), + HCI_ERR(BT_HCI_ERR_LOCALHOST_TERM_CONN), + HCI_ERR(BT_HCI_ERR_REPEATED_ATTEMPTS), + HCI_ERR(BT_HCI_ERR_PAIRING_NOT_ALLOWED), + HCI_ERR(BT_HCI_ERR_UNKNOWN_LMP_PDU), + HCI_ERR(BT_HCI_ERR_UNSUPP_REMOTE_FEATURE), + HCI_ERR(BT_HCI_ERR_SCO_OFFSET_REJECTED), + HCI_ERR(BT_HCI_ERR_SCO_INTERVAL_REJECTED), + HCI_ERR(BT_HCI_ERR_SCO_AIR_MODE_REJECTED), + HCI_ERR(BT_HCI_ERR_INVALID_LL_PARAM), + HCI_ERR(BT_HCI_ERR_UNSPECIFIED), + HCI_ERR(BT_HCI_ERR_UNSUPP_LL_PARAM_VAL), + HCI_ERR(BT_HCI_ERR_ROLE_CHANGE_NOT_ALLOWED), + HCI_ERR(BT_HCI_ERR_LL_RESP_TIMEOUT), + HCI_ERR(BT_HCI_ERR_LL_PROC_COLLISION), + HCI_ERR(BT_HCI_ERR_LMP_PDU_NOT_ALLOWED), + HCI_ERR(BT_HCI_ERR_ENC_MODE_NOT_ACCEPTABLE), + HCI_ERR(BT_HCI_ERR_LINK_KEY_CANNOT_BE_CHANGED), + HCI_ERR(BT_HCI_ERR_REQUESTED_QOS_NOT_SUPPORTED), + HCI_ERR(BT_HCI_ERR_INSTANT_PASSED), + HCI_ERR(BT_HCI_ERR_PAIRING_NOT_SUPPORTED), + HCI_ERR(BT_HCI_ERR_DIFF_TRANS_COLLISION), + HCI_ERR(BT_HCI_ERR_QOS_UNACCEPTABLE_PARAM), + HCI_ERR(BT_HCI_ERR_QOS_REJECTED), + HCI_ERR(BT_HCI_ERR_CHAN_ASSESS_NOT_SUPPORTED), + HCI_ERR(BT_HCI_ERR_INSUFF_SECURITY), + HCI_ERR(BT_HCI_ERR_PARAM_OUT_OF_MANDATORY_RANGE), + HCI_ERR(BT_HCI_ERR_ROLE_SWITCH_PENDING), + HCI_ERR(BT_HCI_ERR_RESERVED_SLOT_VIOLATION), + HCI_ERR(BT_HCI_ERR_ROLE_SWITCH_FAILED), + HCI_ERR(BT_HCI_ERR_EXT_INQ_RESP_TOO_LARGE), + HCI_ERR(BT_HCI_ERR_SIMPLE_PAIR_NOT_SUPP_BY_HOST), + HCI_ERR(BT_HCI_ERR_HOST_BUSY_PAIRING), + HCI_ERR(BT_HCI_ERR_CONN_REJECTED_DUE_TO_NO_CHAN), + HCI_ERR(BT_HCI_ERR_CONTROLLER_BUSY), + HCI_ERR(BT_HCI_ERR_UNACCEPT_CONN_PARAM), + HCI_ERR(BT_HCI_ERR_ADV_TIMEOUT), + HCI_ERR(BT_HCI_ERR_TERM_DUE_TO_MIC_FAIL), + HCI_ERR(BT_HCI_ERR_CONN_FAIL_TO_ESTAB), + HCI_ERR(BT_HCI_ERR_MAC_CONN_FAILED), + HCI_ERR(BT_HCI_ERR_CLOCK_ADJUST_REJECTED), + HCI_ERR(BT_HCI_ERR_SUBMAP_NOT_DEFINED), + HCI_ERR(BT_HCI_ERR_UNKNOWN_ADV_IDENTIFIER), + HCI_ERR(BT_HCI_ERR_LIMIT_REACHED), + HCI_ERR(BT_HCI_ERR_OP_CANCELLED_BY_HOST), + HCI_ERR(BT_HCI_ERR_PACKET_TOO_LONG), + HCI_ERR(BT_HCI_ERR_TOO_LATE), + HCI_ERR(BT_HCI_ERR_TOO_EARLY), + }; + + if (hci_err < ARRAY_SIZE(mapping_table) && mapping_table[hci_err]) { + return mapping_table[hci_err]; + } else { + return "(unknown)"; + } + + #undef HCI_ERR +} diff --git a/tests/bluetooth/hci/CMakeLists.txt b/tests/bluetooth/hci/CMakeLists.txt new file mode 100644 index 0000000000000..874534128cdbf --- /dev/null +++ b/tests/bluetooth/hci/CMakeLists.txt @@ -0,0 +1,7 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(test_hci) + +target_sources(app PRIVATE src/main.c) diff --git a/tests/bluetooth/hci/prj.conf b/tests/bluetooth/hci/prj.conf new file mode 100644 index 0000000000000..1f86a43c20848 --- /dev/null +++ b/tests/bluetooth/hci/prj.conf @@ -0,0 +1,6 @@ +CONFIG_TEST=y +CONFIG_ZTEST=y + +CONFIG_BT=y +CONFIG_BT_CTLR=n +CONFIG_BT_H4=n diff --git a/tests/bluetooth/hci/src/main.c b/tests/bluetooth/hci/src/main.c new file mode 100644 index 0000000000000..94b3bcfcf9e9b --- /dev/null +++ b/tests/bluetooth/hci/src/main.c @@ -0,0 +1,37 @@ +/* main.c - Application main entry point */ + +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +#include + +ZTEST_SUITE(test_hci, NULL, NULL, NULL, NULL, NULL); + +ZTEST(test_hci, test_bt_hci_err_to_str) +{ + /* Test a couple of entries */ + zassert_mem_equal(bt_hci_err_to_str(BT_HCI_ERR_CONN_TIMEOUT), + "BT_HCI_ERR_CONN_TIMEOUT", strlen("BT_HCI_ERR_CONN_TIMEOUT")); + zassert_mem_equal(bt_hci_err_to_str(BT_HCI_ERR_REMOTE_USER_TERM_CONN), + "BT_HCI_ERR_REMOTE_USER_TERM_CONN", + strlen("BT_HCI_ERR_REMOTE_USER_TERM_CONN")); + zassert_mem_equal(bt_hci_err_to_str(BT_HCI_ERR_TOO_EARLY), + "BT_HCI_ERR_TOO_EARLY", strlen("BT_HCI_ERR_TOO_EARLY")); + + /* Test a entries that is not used */ + zassert_mem_equal(bt_hci_err_to_str(0x2b), + "(unknown)", strlen("(unknown)")); + zassert_mem_equal(bt_hci_err_to_str(0xFF), + "(unknown)", strlen("(unknown)")); + + for (uint16_t i = 0; i <= UINT8_MAX; i++) { + zassert_not_null(bt_hci_err_to_str(i), ": %d", i); + } +} diff --git a/tests/bluetooth/hci/testcase.yaml b/tests/bluetooth/hci/testcase.yaml new file mode 100644 index 0000000000000..1e22485ada128 --- /dev/null +++ b/tests/bluetooth/hci/testcase.yaml @@ -0,0 +1,8 @@ +tests: + bluetooth.hci: + platform_allow: + - native_sim + integration_platforms: + - native_sim + tags: + - bluetooth From a2e97405d0ddf4f1fac20b9c5635d923a12317d6 Mon Sep 17 00:00:00 2001 From: TaiJu Wu Date: Sun, 2 Jun 2024 18:17:54 +0800 Subject: [PATCH 2759/2849] lib: check null pointer before taking lock for bitarray In some function in bitarray.c, we should check the pointer of bitarry before taking bitarray lock. In this patch, we move the null-check assert before the use of the struct to provide better validation than a crash. Signed-off-by: TaiJu Wu --- lib/utils/bitarray.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/lib/utils/bitarray.c b/lib/utils/bitarray.c index 82d4e895bd532..dfd7e6b9453fd 100644 --- a/lib/utils/bitarray.c +++ b/lib/utils/bitarray.c @@ -218,11 +218,11 @@ int sys_bitarray_popcount_region(sys_bitarray_t *bitarray, size_t num_bits, size struct bundle_data bd; int ret; - key = k_spin_lock(&bitarray->lock); - __ASSERT_NO_MSG(bitarray != NULL); __ASSERT_NO_MSG(bitarray->num_bits > 0); + key = k_spin_lock(&bitarray->lock); + if (num_bits == 0 || offset + num_bits > bitarray->num_bits) { ret = -EINVAL; goto out; @@ -266,14 +266,15 @@ int sys_bitarray_xor(sys_bitarray_t *dst, sys_bitarray_t *other, size_t num_bits 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); + key_dst = k_spin_lock(&dst->lock); + key_other = k_spin_lock(&other->lock); + + if (dst->num_bits != other->num_bits) { ret = -EINVAL; goto out; @@ -322,11 +323,11 @@ int sys_bitarray_set_bit(sys_bitarray_t *bitarray, size_t bit) int ret; size_t idx, off; - key = k_spin_lock(&bitarray->lock); - __ASSERT_NO_MSG(bitarray != NULL); __ASSERT_NO_MSG(bitarray->num_bits > 0); + key = k_spin_lock(&bitarray->lock); + if (bit >= bitarray->num_bits) { ret = -EINVAL; goto out; From d8179401b5206130d5afa121dec3867ce8889731 Mon Sep 17 00:00:00 2001 From: frei tycho Date: Tue, 14 May 2024 13:08:17 +0000 Subject: [PATCH 2760/2849] kernel: avoided increments/decrements with side effects - moved ++/-- before or after the value use Signed-off-by: frei tycho --- kernel/include/priority_q.h | 6 ++++-- kernel/mempool.c | 3 ++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/kernel/include/priority_q.h b/kernel/include/priority_q.h index f744e6c5467c3..a2edc26088fa8 100644 --- a/kernel/include/priority_q.h +++ b/kernel/include/priority_q.h @@ -79,7 +79,8 @@ static ALWAYS_INLINE void z_priq_rb_add(struct _priq_rb *pq, struct k_thread *th { struct k_thread *t; - thread->base.order_key = pq->next_order_key++; + thread->base.order_key = pq->next_order_key; + ++pq->next_order_key; /* Renumber at wraparound. This is tiny code, and in practice * will almost never be hit on real systems. BUT on very @@ -89,7 +90,8 @@ static ALWAYS_INLINE void z_priq_rb_add(struct _priq_rb *pq, struct k_thread *th */ if (!pq->next_order_key) { RB_FOR_EACH_CONTAINER(&pq->tree, t, base.qnode_rb) { - t->base.order_key = pq->next_order_key++; + t->base.order_key = pq->next_order_key; + ++pq->next_order_key; } } diff --git a/kernel/mempool.c b/kernel/mempool.c index c8298f0d6fc39..d8926c63ed940 100644 --- a/kernel/mempool.c +++ b/kernel/mempool.c @@ -46,7 +46,8 @@ void k_free(void *ptr) if (ptr != NULL) { heap_ref = ptr; - ptr = --heap_ref; + --heap_ref; + ptr = heap_ref; SYS_PORT_TRACING_OBJ_FUNC_ENTER(k_heap_sys, k_free, *heap_ref, heap_ref); From 96d8330d9b91e24d4045152290ed4437fbf2ce5d Mon Sep 17 00:00:00 2001 From: Phi Bang Nguyen Date: Wed, 12 Jun 2024 15:55:00 +0200 Subject: [PATCH 2761/2849] samples: video: capture: Update documents and tests The mt9m114 camera shield is now added. There are also some changes in the mt9m114 camera driver, e.g. frame rate, default format, capabilities. Update the sample document and test to reflect these changes. Signed-off-by: Phi Bang Nguyen --- samples/subsys/video/capture/README.rst | 42 +++++++++++++++--------- samples/subsys/video/capture/sample.yaml | 7 +++- 2 files changed, 33 insertions(+), 16 deletions(-) diff --git a/samples/subsys/video/capture/README.rst b/samples/subsys/video/capture/README.rst index 29dedf2bdf408..32f95280d19b4 100644 --- a/samples/subsys/video/capture/README.rst +++ b/samples/subsys/video/capture/README.rst @@ -14,7 +14,10 @@ discards the video frame data. Requirements ************ -This sample requires a video capture device (e.g. a camera). +This sample needs a video capture device (e.g. a camera) but it is not mandatory. +Supported camera modules on some i.MX RT boards can be found below. + +- `Camera iMXRT`_ - :ref:`mimxrt1064_evk` - `MT9M114 camera module`_ @@ -22,10 +25,9 @@ This sample requires a video capture device (e.g. a camera). Wiring ****** -On :ref:`mimxrt1064_evk`, The MT9M114 camera module should be plugged in the +On :ref:`mimxrt1064_evk`, the MT9M114 camera module should be plugged in the J35 camera connector. A USB cable should be connected from a host to the micro -USB debug connector (J41) in order to get console output via the freelink -interface. +USB debug connector (J41) in order to get console output via the freelink interface. Building and Running ******************** @@ -35,30 +37,40 @@ For :ref:`mimxrt1064_evk`, build this sample application with the following comm .. zephyr-app-commands:: :zephyr-app: samples/subsys/video/capture :board: mimxrt1064_evk + :shield: dvp_fpc24_mt9m114 :goals: build :compact: +For testing purpose without the need of any real video capture hardware, a video software +pattern generator is supported by the above build command without specifying any shield. + Sample Output ============= .. code-block:: console - Found video device: CSI - width (640,640), height (480,480) - Supported pixelformats (fourcc): - - RGBP - Use default format (640x480) + - Device name: csi@402bc000 + - Capabilities: + RGBP width [480; 480; 0] height [272; 272; 0] + YUYV width [480; 480; 0] height [272; 272; 0] + RGBP width [640; 640; 0] height [480; 480; 0] + YUYV width [640; 640; 0] height [480; 480; 0] + RGBP width [1280; 1280; 0] height [720; 720; 0] + YUYV width [1280; 1280; 0] height [720; 720; 0] + - Default format: RGBP 480x272 Capture started - Got frame 743! size: 614400; timestamp 100740 ms - Got frame 744! size: 614400; timestamp 100875 ms - Got frame 745! size: 614400; timestamp 101010 ms - Got frame 746! size: 614400; timestamp 101146 ms - Got frame 747! size: 614400; timestamp 101281 ms - Got frame 748! size: 614400; timestamp 101416 ms + Got frame 0! size: 261120; timestamp 249 ms + Got frame 1! size: 261120; timestamp 282 ms + Got frame 2! size: 261120; timestamp 316 ms + Got frame 3! size: 261120; timestamp 350 ms + Got frame 4! size: 261120; timestamp 384 ms + Got frame 5! size: 261120; timestamp 418 ms + Got frame 6! size: 261120; timestamp 451 ms References ********** +.. _Camera iMXRT: https://community.nxp.com/t5/i-MX-RT-Knowledge-Base/Connecting-camera-and-LCD-to-i-MX-RT-EVKs/ta-p/1122183 .. _MT9M114 camera module: https://www.onsemi.com/PowerSolutions/product.do?id=MT9M114 diff --git a/samples/subsys/video/capture/sample.yaml b/samples/subsys/video/capture/sample.yaml index 88c57fc74928f..5b6e2cc87feb9 100644 --- a/samples/subsys/video/capture/sample.yaml +++ b/samples/subsys/video/capture/sample.yaml @@ -3,7 +3,12 @@ sample: tests: sample.video.capture: build_only: true - tags: video + tags: + - video + - shield + - samples + extra_args: + - platform:mimxrt1064_evk:SHIELD=dvp_fpc24_mt9m114 platform_allow: - mimxrt1064_evk - mm_swiftio From ee3347a9f3a13b6a680cec4711f956fa19407e38 Mon Sep 17 00:00:00 2001 From: Phi Bang Nguyen Date: Tue, 13 Feb 2024 14:31:17 +0100 Subject: [PATCH 2762/2849] samples: video: capture: Run clang-format Run clang-format on the file before making any changes Signed-off-by: Phi Bang Nguyen --- samples/subsys/video/capture/src/main.c | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/samples/subsys/video/capture/src/main.c b/samples/subsys/video/capture/src/main.c index 5018bdf1ecfd3..6ac75fc9d0b1c 100644 --- a/samples/subsys/video/capture/src/main.c +++ b/samples/subsys/video/capture/src/main.c @@ -57,12 +57,10 @@ int main(void) const struct video_format_cap *fcap = &caps.format_caps[i]; /* fourcc to string */ printk(" %c%c%c%c width [%u; %u; %u] height [%u; %u; %u]\n", - (char)fcap->pixelformat, - (char)(fcap->pixelformat >> 8), - (char)(fcap->pixelformat >> 16), - (char)(fcap->pixelformat >> 24), - fcap->width_min, fcap->width_max, fcap->width_step, - fcap->height_min, fcap->height_max, fcap->height_step); + (char)fcap->pixelformat, (char)(fcap->pixelformat >> 8), + (char)(fcap->pixelformat >> 16), (char)(fcap->pixelformat >> 24), + fcap->width_min, fcap->width_max, fcap->width_step, fcap->height_min, + fcap->height_max, fcap->height_step); i++; } @@ -73,10 +71,8 @@ int main(void) } printk("- Default format: %c%c%c%c %ux%u\n", (char)fmt.pixelformat, - (char)(fmt.pixelformat >> 8), - (char)(fmt.pixelformat >> 16), - (char)(fmt.pixelformat >> 24), - fmt.width, fmt.height); + (char)(fmt.pixelformat >> 8), (char)(fmt.pixelformat >> 16), + (char)(fmt.pixelformat >> 24), fmt.width, fmt.height); /* Size to allocate for each buffer */ bsize = fmt.pitch * fmt.height; @@ -110,8 +106,8 @@ int main(void) return 0; } - printk("\rGot frame %u! size: %u; timestamp %u ms", - frame++, vbuf->bytesused, vbuf->timestamp); + printk("\rGot frame %u! size: %u; timestamp %u ms", frame++, vbuf->bytesused, + vbuf->timestamp); err = video_enqueue(video, VIDEO_EP_OUT, vbuf); if (err) { From 553f527a49fba4c9b28c07946198cba7d70c2220 Mon Sep 17 00:00:00 2001 From: Phi Bang Nguyen Date: Wed, 12 Jun 2024 16:33:53 +0200 Subject: [PATCH 2763/2849] samples: video: capture: Enhance logs readability There are some compatibilty situations where carriage return does not work (e.g. on Serial Monitor in VSCode). Moreover, keeping the timestamps logs on the console would help to have an idea about the frame rate. So, it's better to use line feed instead of carriage return in this case. Signed-off-by: Phi Bang Nguyen --- samples/subsys/video/capture/src/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/subsys/video/capture/src/main.c b/samples/subsys/video/capture/src/main.c index 6ac75fc9d0b1c..fff165e47d4d8 100644 --- a/samples/subsys/video/capture/src/main.c +++ b/samples/subsys/video/capture/src/main.c @@ -106,7 +106,7 @@ int main(void) return 0; } - printk("\rGot frame %u! size: %u; timestamp %u ms", frame++, vbuf->bytesused, + printk("Got frame %u! size: %u; timestamp %u ms\n", frame++, vbuf->bytesused, vbuf->timestamp); err = video_enqueue(video, VIDEO_EP_OUT, vbuf); From 0ecbd0b9c985fba1dd9f17ad5280f5d11956fba9 Mon Sep 17 00:00:00 2001 From: Phi Bang Nguyen Date: Wed, 31 Jan 2024 13:07:42 +0100 Subject: [PATCH 2764/2849] samples: video: capture: Use a chosen node for camera In order to be generic, use a chosen node for camera so that the sample is not specific to NXP SoCs. Also, always favorite a real video device unless it is unavailable. Signed-off-by: Phi Bang Nguyen --- samples/subsys/video/capture/src/main.c | 36 +++++++++++-------------- 1 file changed, 16 insertions(+), 20 deletions(-) diff --git a/samples/subsys/video/capture/src/main.c b/samples/subsys/video/capture/src/main.c index fff165e47d4d8..d2e9ee455269a 100644 --- a/samples/subsys/video/capture/src/main.c +++ b/samples/subsys/video/capture/src/main.c @@ -20,34 +20,30 @@ int main(void) struct video_buffer *buffers[2], *vbuf; struct video_format fmt; struct video_caps caps; - const struct device *video; unsigned int frame = 0; size_t bsize; int i = 0; - /* Default to software video pattern generator */ - video = device_get_binding(VIDEO_DEV_SW); - if (video == NULL) { - LOG_ERR("Video device %s not found", VIDEO_DEV_SW); +#if DT_HAS_CHOSEN(zephyr_camera) + const struct device *const video_dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_camera)); + + if (!device_is_ready(video_dev)) { + LOG_ERR("%s: video device is not ready", video_dev->name); return 0; } +#else + const struct device *const video_dev = device_get_binding(VIDEO_DEV_SW); - /* But would be better to use a real video device if any */ -#if defined(CONFIG_VIDEO_MCUX_CSI) - const struct device *const dev = DEVICE_DT_GET_ONE(nxp_imx_csi); - - if (!device_is_ready(dev)) { - LOG_ERR("%s: device not ready.\n", dev->name); + if (video_dev == NULL) { + LOG_ERR("%s: video device not found or failed to initialized", VIDEO_DEV_SW); return 0; } - - video = dev; #endif - printk("- Device name: %s\n", video->name); + printk("- Device name: %s\n", video_dev->name); /* Get capabilities */ - if (video_get_caps(video, VIDEO_EP_OUT, &caps)) { + if (video_get_caps(video_dev, VIDEO_EP_OUT, &caps)) { LOG_ERR("Unable to retrieve video capabilities"); return 0; } @@ -65,7 +61,7 @@ int main(void) } /* Get default/native format */ - if (video_get_format(video, VIDEO_EP_OUT, &fmt)) { + if (video_get_format(video_dev, VIDEO_EP_OUT, &fmt)) { LOG_ERR("Unable to retrieve video format"); return 0; } @@ -85,11 +81,11 @@ int main(void) return 0; } - video_enqueue(video, VIDEO_EP_OUT, buffers[i]); + video_enqueue(video_dev, VIDEO_EP_OUT, buffers[i]); } /* Start video capture */ - if (video_stream_start(video)) { + if (video_stream_start(video_dev)) { LOG_ERR("Unable to start capture (interface)"); return 0; } @@ -100,7 +96,7 @@ int main(void) while (1) { int err; - err = video_dequeue(video, VIDEO_EP_OUT, &vbuf, K_FOREVER); + err = video_dequeue(video_dev, VIDEO_EP_OUT, &vbuf, K_FOREVER); if (err) { LOG_ERR("Unable to dequeue video buf"); return 0; @@ -109,7 +105,7 @@ int main(void) printk("Got frame %u! size: %u; timestamp %u ms\n", frame++, vbuf->bytesused, vbuf->timestamp); - err = video_enqueue(video, VIDEO_EP_OUT, vbuf); + err = video_enqueue(video_dev, VIDEO_EP_OUT, vbuf); if (err) { LOG_ERR("Unable to requeue video buf"); return 0; From 831f5f6ba611e2b1e2efc50654525cb983545f5b Mon Sep 17 00:00:00 2001 From: Phi Bang Nguyen Date: Fri, 2 Feb 2024 00:35:17 +0100 Subject: [PATCH 2765/2849] samples: video: capture: Display captured frames on screen Improve the sample application by displaying the captured frames instead of just discarding them. Signed-off-by: Phi Bang Nguyen --- samples/subsys/video/capture/README.rst | 15 ++++-- samples/subsys/video/capture/prj.conf | 1 + samples/subsys/video/capture/sample.yaml | 2 +- samples/subsys/video/capture/src/main.c | 64 ++++++++++++++++++++++-- 4 files changed, 73 insertions(+), 9 deletions(-) diff --git a/samples/subsys/video/capture/README.rst b/samples/subsys/video/capture/README.rst index 32f95280d19b4..bfe8a9fa916ad 100644 --- a/samples/subsys/video/capture/README.rst +++ b/samples/subsys/video/capture/README.rst @@ -7,9 +7,8 @@ Description *********** -This sample application uses the :ref:`Video API ` to retrieve video frames from the -video capture device, writes a frame count message to the console, and then -discards the video frame data. +This sample application uses the :ref:`video_api` to capture frames from a video capture +device then uses the :ref:`display_api` to display them onto an LCD screen (if any). Requirements ************ @@ -37,7 +36,7 @@ For :ref:`mimxrt1064_evk`, build this sample application with the following comm .. zephyr-app-commands:: :zephyr-app: samples/subsys/video/capture :board: mimxrt1064_evk - :shield: dvp_fpc24_mt9m114 + :shield: "dvp_fpc24_mt9m114 rk043fn66hs_ctg" :goals: build :compact: @@ -49,7 +48,7 @@ Sample Output .. code-block:: console - - Device name: csi@402bc000 + Video device: csi@402bc000 - Capabilities: RGBP width [480; 480; 0] height [272; 272; 0] YUYV width [480; 480; 0] height [272; 272; 0] @@ -58,6 +57,12 @@ Sample Output RGBP width [1280; 1280; 0] height [720; 720; 0] YUYV width [1280; 1280; 0] height [720; 720; 0] - Default format: RGBP 480x272 + + Display device: display-controller@402b8000 + - Capabilities: + x_resolution = 480, y_resolution = 272, supported_pixel_formats = 40 + current_pixel_format = 32, current_orientation = 0 + Capture started Got frame 0! size: 261120; timestamp 249 ms Got frame 1! size: 261120; timestamp 282 ms diff --git a/samples/subsys/video/capture/prj.conf b/samples/subsys/video/capture/prj.conf index f8d9f2b955376..ce6dcc316d67e 100644 --- a/samples/subsys/video/capture/prj.conf +++ b/samples/subsys/video/capture/prj.conf @@ -4,3 +4,4 @@ CONFIG_SHELL=y CONFIG_DEVICE_SHELL=y CONFIG_PRINTK=y CONFIG_LOG=y +CONFIG_DISPLAY=y diff --git a/samples/subsys/video/capture/sample.yaml b/samples/subsys/video/capture/sample.yaml index 5b6e2cc87feb9..db8a75c526dee 100644 --- a/samples/subsys/video/capture/sample.yaml +++ b/samples/subsys/video/capture/sample.yaml @@ -8,7 +8,7 @@ tests: - shield - samples extra_args: - - platform:mimxrt1064_evk:SHIELD=dvp_fpc24_mt9m114 + - platform:mimxrt1064_evk:SHIELD="dvp_fpc24_mt9m114;rk043fn66hs_ctg" platform_allow: - mimxrt1064_evk - mm_swiftio diff --git a/samples/subsys/video/capture/src/main.c b/samples/subsys/video/capture/src/main.c index d2e9ee455269a..1f82c698ceb7d 100644 --- a/samples/subsys/video/capture/src/main.c +++ b/samples/subsys/video/capture/src/main.c @@ -7,6 +7,7 @@ #include #include +#include #include #define LOG_LEVEL CONFIG_LOG_DEFAULT_LEVEL @@ -15,6 +16,45 @@ LOG_MODULE_REGISTER(main); #define VIDEO_DEV_SW "VIDEO_SW_GENERATOR" +#if DT_HAS_CHOSEN(zephyr_display) +static inline int display_setup(const struct device *const display_dev) +{ + struct display_capabilities capabilities; + + if (!device_is_ready(display_dev)) { + LOG_ERR("Device %s not found", display_dev->name); + return -ENODEV; + } + + printk("\nDisplay device: %s\n", display_dev->name); + + display_get_capabilities(display_dev, &capabilities); + + printk("- Capabilities:\n"); + printk(" x_resolution = %u, y_resolution = %u, supported_pixel_formats = %u\n" + " current_pixel_format = %u, current_orientation = %u\n\n", + capabilities.x_resolution, capabilities.y_resolution, + capabilities.supported_pixel_formats, capabilities.current_pixel_format, + capabilities.current_orientation); + + return display_blanking_off(display_dev); +} + +static inline void video_display_frame(const struct device *const display_dev, + const struct video_buffer *const vbuf, + const struct video_format fmt) +{ + struct display_buffer_descriptor buf_desc; + + buf_desc.buf_size = vbuf->bytesused; + buf_desc.width = fmt.width; + buf_desc.pitch = buf_desc.width; + buf_desc.height = fmt.height; + + display_write(display_dev, 0, 0, &buf_desc, vbuf->buffer); +} +#endif + int main(void) { struct video_buffer *buffers[2], *vbuf; @@ -23,6 +63,7 @@ int main(void) unsigned int frame = 0; size_t bsize; int i = 0; + int err; #if DT_HAS_CHOSEN(zephyr_camera) const struct device *const video_dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_camera)); @@ -40,7 +81,7 @@ int main(void) } #endif - printk("- Device name: %s\n", video_dev->name); + printk("Video device: %s\n", video_dev->name); /* Get capabilities */ if (video_get_caps(video_dev, VIDEO_EP_OUT, &caps)) { @@ -70,6 +111,21 @@ int main(void) (char)(fmt.pixelformat >> 8), (char)(fmt.pixelformat >> 16), (char)(fmt.pixelformat >> 24), fmt.width, fmt.height); +#if DT_HAS_CHOSEN(zephyr_display) + const struct device *const display_dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_display)); + + if (!device_is_ready(display_dev)) { + LOG_ERR("%s: display device not ready.", display_dev->name); + return 0; + } + + err = display_setup(display_dev); + if (err) { + LOG_ERR("Unable to set up display"); + return err; + } +#endif + /* Size to allocate for each buffer */ bsize = fmt.pitch * fmt.height; @@ -94,8 +150,6 @@ int main(void) /* Grab video frames */ while (1) { - int err; - err = video_dequeue(video_dev, VIDEO_EP_OUT, &vbuf, K_FOREVER); if (err) { LOG_ERR("Unable to dequeue video buf"); @@ -105,6 +159,10 @@ int main(void) printk("Got frame %u! size: %u; timestamp %u ms\n", frame++, vbuf->bytesused, vbuf->timestamp); +#if DT_HAS_CHOSEN(zephyr_display) + video_display_frame(display_dev, vbuf, fmt); +#endif + err = video_enqueue(video_dev, VIDEO_EP_OUT, vbuf); if (err) { LOG_ERR("Unable to requeue video buf"); From 727f04b159e70e4f38c455aeee650f5125b1df1c Mon Sep 17 00:00:00 2001 From: Phi Bang Nguyen Date: Wed, 13 Mar 2024 18:13:18 +0100 Subject: [PATCH 2766/2849] samples: video: capture: Add support for i.MX RT1170 EVK Add support for i.MX RT1170 EVK Signed-off-by: Phi Bang Nguyen --- samples/subsys/video/capture/README.rst | 22 +++++++++++++-- .../boards/mimxrt1170_evk_mimxrt1176_cm7.conf | 4 +++ samples/subsys/video/capture/sample.yaml | 3 ++ samples/subsys/video/capture/src/main.c | 28 +++++++++++++++++-- 4 files changed, 52 insertions(+), 5 deletions(-) create mode 100644 samples/subsys/video/capture/boards/mimxrt1170_evk_mimxrt1176_cm7.conf diff --git a/samples/subsys/video/capture/README.rst b/samples/subsys/video/capture/README.rst index bfe8a9fa916ad..67cbcfdacb355 100644 --- a/samples/subsys/video/capture/README.rst +++ b/samples/subsys/video/capture/README.rst @@ -21,6 +21,9 @@ Supported camera modules on some i.MX RT boards can be found below. - :ref:`mimxrt1064_evk` - `MT9M114 camera module`_ +- :ref:`mimxrt1170_evk` +- `OV5640 camera module`_ + Wiring ****** @@ -28,6 +31,10 @@ On :ref:`mimxrt1064_evk`, the MT9M114 camera module should be plugged in the J35 camera connector. A USB cable should be connected from a host to the micro USB debug connector (J41) in order to get console output via the freelink interface. +On :ref:`mimxrt1170_evk`, the OV5640 camera module should be plugged into the +J2 camera connector. A USB cable should be connected from a host to the micro +USB debug connector (J11) in order to get console output via the daplink interface. + Building and Running ******************** @@ -40,8 +47,18 @@ For :ref:`mimxrt1064_evk`, build this sample application with the following comm :goals: build :compact: -For testing purpose without the need of any real video capture hardware, a video software -pattern generator is supported by the above build command without specifying any shield. +For :ref:`mimxrt1170_evk`, build this sample application with the following commands: + +.. zephyr-app-commands:: + :zephyr-app: samples/subsys/video/capture + :board: mimxrt1170_evk/mimxrt1176/cm7 + :shield: "nxp_btb44_ov5640 rk055hdmipi4ma0" + :goals: build + :compact: + +For testing purpose without the need of any real video capture and/or display hardwares, +a video software pattern generator is supported by the above build commands without +specifying the shields. Sample Output ============= @@ -79,3 +96,4 @@ References .. _Camera iMXRT: https://community.nxp.com/t5/i-MX-RT-Knowledge-Base/Connecting-camera-and-LCD-to-i-MX-RT-EVKs/ta-p/1122183 .. _MT9M114 camera module: https://www.onsemi.com/PowerSolutions/product.do?id=MT9M114 +.. _OV5640 camera module: https://cdn.sparkfun.com/datasheets/Sensors/LightImaging/OV5640_datasheet.pdf diff --git a/samples/subsys/video/capture/boards/mimxrt1170_evk_mimxrt1176_cm7.conf b/samples/subsys/video/capture/boards/mimxrt1170_evk_mimxrt1176_cm7.conf new file mode 100644 index 0000000000000..7252f9e67c5cb --- /dev/null +++ b/samples/subsys/video/capture/boards/mimxrt1170_evk_mimxrt1176_cm7.conf @@ -0,0 +1,4 @@ +CONFIG_VIDEO_BUFFER_POOL_SZ_MAX=3686800 +CONFIG_DMA=y +CONFIG_MCUX_ELCDIF_PXP=y +CONFIG_MCUX_ELCDIF_PXP_ROTATE_90=y diff --git a/samples/subsys/video/capture/sample.yaml b/samples/subsys/video/capture/sample.yaml index db8a75c526dee..34eaffdec69c4 100644 --- a/samples/subsys/video/capture/sample.yaml +++ b/samples/subsys/video/capture/sample.yaml @@ -9,9 +9,12 @@ tests: - samples extra_args: - platform:mimxrt1064_evk:SHIELD="dvp_fpc24_mt9m114;rk043fn66hs_ctg" + - platform:mimxrt1170_evk/mimxrt1176/cm7:SHIELD="nxp_btb44_ov5640;rk055hdmipi4ma0" platform_allow: - mimxrt1064_evk + - mimxrt1170_evk/mimxrt1176/cm7 - mm_swiftio depends_on: video integration_platforms: - mimxrt1064_evk + - mimxrt1170_evk/mimxrt1176/cm7 diff --git a/samples/subsys/video/capture/src/main.c b/samples/subsys/video/capture/src/main.c index 1f82c698ceb7d..862dff287f7aa 100644 --- a/samples/subsys/video/capture/src/main.c +++ b/samples/subsys/video/capture/src/main.c @@ -17,9 +17,10 @@ LOG_MODULE_REGISTER(main); #define VIDEO_DEV_SW "VIDEO_SW_GENERATOR" #if DT_HAS_CHOSEN(zephyr_display) -static inline int display_setup(const struct device *const display_dev) +static inline int display_setup(const struct device *const display_dev, const uint32_t pixfmt) { struct display_capabilities capabilities; + int ret = 0; if (!device_is_ready(display_dev)) { LOG_ERR("Device %s not found", display_dev->name); @@ -37,6 +38,23 @@ static inline int display_setup(const struct device *const display_dev) capabilities.supported_pixel_formats, capabilities.current_pixel_format, capabilities.current_orientation); + /* Set display pixel format to match the one in use by the camera */ + switch (pixfmt) { + case VIDEO_PIX_FMT_RGB565: + ret = display_set_pixel_format(display_dev, PIXEL_FORMAT_BGR_565); + break; + case VIDEO_PIX_FMT_XRGB32: + ret = display_set_pixel_format(display_dev, PIXEL_FORMAT_ARGB_8888); + break; + default: + return -ENOTSUP; + } + + if (ret) { + LOG_ERR("Unable to set display format"); + return ret; + } + return display_blanking_off(display_dev); } @@ -119,7 +137,7 @@ int main(void) return 0; } - err = display_setup(display_dev); + err = display_setup(display_dev, fmt.pixelformat); if (err) { LOG_ERR("Unable to set up display"); return err; @@ -131,7 +149,11 @@ int main(void) /* Alloc video buffers and enqueue for capture */ for (i = 0; i < ARRAY_SIZE(buffers); i++) { - buffers[i] = video_buffer_alloc(bsize); + /* + * For some hardwares, such as the PxP used on i.MX RT1170 to do image rotation, + * buffer alignment is needed in order to achieve the best performance + */ + buffers[i] = video_buffer_aligned_alloc(bsize, CONFIG_VIDEO_BUFFER_POOL_ALIGN); if (buffers[i] == NULL) { LOG_ERR("Unable to alloc video buffer"); return 0; From f1aa5d93916b22df5b39ef920cbb4a10152912ad Mon Sep 17 00:00:00 2001 From: Jiafei Pan Date: Tue, 23 Apr 2024 14:23:55 +0800 Subject: [PATCH 2767/2849] drivers: eth_nxp_enet: fix cache maintain Need to disable cache maintain by driver in case of using noncache DMA buffer. Signed-off-by: Jiafei Pan --- drivers/ethernet/nxp_enet/eth_nxp_enet.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/ethernet/nxp_enet/eth_nxp_enet.c b/drivers/ethernet/nxp_enet/eth_nxp_enet.c index 8096185e5bcbb..24e82a0275994 100644 --- a/drivers/ethernet/nxp_enet/eth_nxp_enet.c +++ b/drivers/ethernet/nxp_enet/eth_nxp_enet.c @@ -839,14 +839,17 @@ static const struct ethernet_api api_funcs = { #define _nxp_enet_dma_desc_section __dtcm_bss_section #define _nxp_enet_dma_buffer_section __dtcm_noinit_section #define _nxp_enet_driver_buffer_section __dtcm_noinit_section +#define driver_cache_maintain false #elif defined(CONFIG_NOCACHE_MEMORY) #define _nxp_enet_dma_desc_section __nocache #define _nxp_enet_dma_buffer_section __nocache #define _nxp_enet_driver_buffer_section +#define driver_cache_maintain false #else #define _nxp_enet_dma_desc_section #define _nxp_enet_dma_buffer_section #define _nxp_enet_driver_buffer_section +#define driver_cache_maintain true #endif /* Use ENET_FRAME_MAX_VLANFRAMELEN for VLAN frame size @@ -957,8 +960,8 @@ BUILD_ASSERT(NXP_ENET_PHY_MODE(DT_DRV_INST(n)) != NXP_ENET_RGMII_MODE || \ .txBdStartAddrAlign = nxp_enet_##n##_tx_buffer_desc, \ .rxBufferAlign = nxp_enet_##n##_rx_buffer[0], \ .txBufferAlign = nxp_enet_##n##_tx_buffer[0], \ - .rxMaintainEnable = true, \ - .txMaintainEnable = true, \ + .rxMaintainEnable = driver_cache_maintain, \ + .txMaintainEnable = driver_cache_maintain, \ NXP_ENET_FRAMEINFO(n) \ }, \ .phy_mode = NXP_ENET_PHY_MODE(DT_DRV_INST(n)), \ From 0c958ae2123f87a47893aafdc044e0f262ff4107 Mon Sep 17 00:00:00 2001 From: Jiafei Pan Date: Thu, 25 Apr 2024 17:42:54 +0800 Subject: [PATCH 2768/2849] drivers: ethernet: eth_enet: remove building error Don't block building in case of there is no unique ID provided. Signed-off-by: Jiafei Pan --- drivers/ethernet/nxp_enet/eth_nxp_enet.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/ethernet/nxp_enet/eth_nxp_enet.c b/drivers/ethernet/nxp_enet/eth_nxp_enet.c index 24e82a0275994..afc640ea778ef 100644 --- a/drivers/ethernet/nxp_enet/eth_nxp_enet.c +++ b/drivers/ethernet/nxp_enet/eth_nxp_enet.c @@ -65,7 +65,7 @@ LOG_MODULE_REGISTER(LOG_MODULE_NAME); #elif defined(CONFIG_SOC_SERIES_RW6XX) #define ETH_NXP_ENET_UNIQUE_ID (OCOTP->OTP_SHADOW[46]) #else -#error "Unsupported SOC" +#define ETH_NXP_ENET_UNIQUE_ID 0xFFFFFF #endif #define RING_ID 0 @@ -612,6 +612,9 @@ static inline void nxp_enet_unique_mac(uint8_t *mac_addr) { uint32_t id = ETH_NXP_ENET_UNIQUE_ID; + if (id == 0xFFFFFF) + LOG_ERR("No unique MAC can be provided in this platform"); + /* Setting LAA bit because it is not guaranteed universally unique */ mac_addr[0] = FREESCALE_OUI_B0 | 0x02; mac_addr[1] = FREESCALE_OUI_B1; From 6d48c8ce190180c7deee9c628f6c9b9697bd14ea Mon Sep 17 00:00:00 2001 From: Jiafei Pan Date: Wed, 24 Apr 2024 17:08:19 +0800 Subject: [PATCH 2769/2849] board: imx8mp_evk: enable MMU direct mapping for A-Core Enable MMU direct mapping, so that driver can use it for MMIO mapping as currently hal driver needs direct mapping (physical address and virtual address 1:1 mapping). Signed-off-by: Jiafei Pan --- boards/nxp/imx8mp_evk/imx8mp_evk_mimx8ml8_a53_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/boards/nxp/imx8mp_evk/imx8mp_evk_mimx8ml8_a53_defconfig b/boards/nxp/imx8mp_evk/imx8mp_evk_mimx8ml8_a53_defconfig index 4e31bf4e94605..03f341149702d 100644 --- a/boards/nxp/imx8mp_evk/imx8mp_evk_mimx8ml8_a53_defconfig +++ b/boards/nxp/imx8mp_evk/imx8mp_evk_mimx8ml8_a53_defconfig @@ -13,6 +13,7 @@ CONFIG_ICACHE_LINE_SIZE_DETECT=y # Zephyr Kernel Configuration CONFIG_XIP=n +CONFIG_KERNEL_DIRECT_MAP=y # Serial Drivers CONFIG_SERIAL=y From cca390d24365e80ef274141151c53efe2b2e9af9 Mon Sep 17 00:00:00 2001 From: Jiafei Pan Date: Wed, 24 Apr 2024 12:03:27 +0800 Subject: [PATCH 2770/2849] drivers: ethernet: eth_enet: add MMIO mapping Adding MMIO mapping support in ENET module driver before MDIO, MAC and PTP drivers initialization, so that they can reuse this mapping. Signed-off-by: Jiafei Pan --- drivers/ethernet/nxp_enet/eth_nxp_enet.c | 107 ++++++++++++++++------- 1 file changed, 74 insertions(+), 33 deletions(-) diff --git a/drivers/ethernet/nxp_enet/eth_nxp_enet.c b/drivers/ethernet/nxp_enet/eth_nxp_enet.c index afc640ea778ef..5168879b5b916 100644 --- a/drivers/ethernet/nxp_enet/eth_nxp_enet.c +++ b/drivers/ethernet/nxp_enet/eth_nxp_enet.c @@ -79,7 +79,7 @@ enum mac_address_source { }; struct nxp_enet_mac_config { - ENET_Type *base; + const struct device *module_dev; const struct device *clock_dev; clock_control_subsys_t clock_subsys; enum mac_address_source mac_addr_source; @@ -95,6 +95,7 @@ struct nxp_enet_mac_config { }; struct nxp_enet_mac_data { + ENET_Type *base; struct net_if *iface; uint8_t mac_addr[6]; enet_handle_t enet_handle; @@ -202,7 +203,6 @@ static const struct device *eth_nxp_enet_get_ptp_clock(const struct device *dev) static int eth_nxp_enet_tx(const struct device *dev, struct net_pkt *pkt) { - const struct nxp_enet_mac_config *config = dev->config; struct nxp_enet_mac_data *data = dev->data; uint16_t total_len = net_pkt_get_len(pkt); bool frame_is_timestamped; @@ -222,7 +222,7 @@ static int eth_nxp_enet_tx(const struct device *dev, struct net_pkt *pkt) frame_is_timestamped = eth_get_ptp_data(net_pkt_iface(pkt), pkt); - ret = ENET_SendFrame(config->base, &data->enet_handle, data->tx_frame_buf, + ret = ENET_SendFrame(data->base, &data->enet_handle, data->tx_frame_buf, total_len, RING_ID, frame_is_timestamped, pkt); if (ret == kStatus_Success) { goto exit; @@ -232,7 +232,7 @@ static int eth_nxp_enet_tx(const struct device *dev, struct net_pkt *pkt) eth_wait_for_ptp_ts(dev, pkt); } else { LOG_ERR("ENET_SendFrame error: %d", ret); - ENET_ReclaimTxDescriptor(config->base, &data->enet_handle, RING_ID); + ENET_ReclaimTxDescriptor(data->base, &data->enet_handle, RING_ID); } exit: @@ -305,14 +305,13 @@ static int eth_nxp_enet_set_config(const struct device *dev, const struct ethernet_config *cfg) { struct nxp_enet_mac_data *data = dev->data; - const struct nxp_enet_mac_config *config = dev->config; switch (type) { case ETHERNET_CONFIG_TYPE_MAC_ADDRESS: memcpy(data->mac_addr, cfg->mac_address.addr, sizeof(data->mac_addr)); - ENET_SetMacAddr(config->base, data->mac_addr); + ENET_SetMacAddr(data->base, data->mac_addr); net_if_set_link_addr(data->iface, data->mac_addr, sizeof(data->mac_addr), NET_LINK_ETHERNET); @@ -325,10 +324,10 @@ static int eth_nxp_enet_set_config(const struct device *dev, case ETHERNET_CONFIG_TYPE_FILTER: /* The ENET driver does not modify the address buffer but the API is not const */ if (cfg->filter.set) { - ENET_AddMulticastGroup(config->base, + ENET_AddMulticastGroup(data->base, (uint8_t *)cfg->filter.mac_address.addr); } else { - ENET_LeaveMulticastGroup(config->base, + ENET_LeaveMulticastGroup(data->base, (uint8_t *)cfg->filter.mac_address.addr); } return 0; @@ -341,7 +340,9 @@ static int eth_nxp_enet_set_config(const struct device *dev, static int eth_nxp_enet_rx(const struct device *dev) { +#if defined(CONFIG_PTP_CLOCK_NXP_ENET) const struct nxp_enet_mac_config *config = dev->config; +#endif struct nxp_enet_mac_data *data = dev->data; uint32_t frame_length = 0U; struct net_if *iface; @@ -376,7 +377,7 @@ static int eth_nxp_enet_rx(const struct device *dev) } k_mutex_lock(&data->rx_frame_buf_mutex, K_FOREVER); - status = ENET_ReadFrame(config->base, &data->enet_handle, + status = ENET_ReadFrame(data->base, &data->enet_handle, data->rx_frame_buf, frame_length, RING_ID, &ts); k_mutex_unlock(&data->rx_frame_buf_mutex); @@ -430,7 +431,7 @@ static int eth_nxp_enet_rx(const struct device *dev) * only report failure if there is no frame to flush, * which cannot happen in this context. */ - status = ENET_ReadFrame(config->base, &data->enet_handle, NULL, + status = ENET_ReadFrame(data->base, &data->enet_handle, NULL, 0, RING_ID, NULL); __ASSERT_NO_MSG(status == kStatus_Success); error: @@ -446,7 +447,6 @@ static void eth_nxp_enet_rx_thread(struct k_work *work) struct nxp_enet_mac_data *data = CONTAINER_OF(work, struct nxp_enet_mac_data, rx_work); const struct device *dev = data->dev; - const struct nxp_enet_mac_config *config = dev->config; int ret; if (k_sem_take(&data->rx_thread_sem, K_FOREVER)) { @@ -457,7 +457,7 @@ static void eth_nxp_enet_rx_thread(struct k_work *work) ret = eth_nxp_enet_rx(dev); } while (ret == 1); - ENET_EnableInterrupts(config->base, kENET_RxFrameInterrupt); + ENET_EnableInterrupts(data->base, kENET_RxFrameInterrupt); } static int nxp_enet_phy_configure(const struct device *phy, uint8_t phy_mode) @@ -503,7 +503,7 @@ static void nxp_enet_phy_cb(const struct device *phy, duplex = kENET_MiiHalfDuplex; } - ENET_SetMII(config->base, speed, duplex); + ENET_SetMII(data->base, speed, duplex); } if (!data->iface) { @@ -556,7 +556,6 @@ static void eth_callback(ENET_Type *base, enet_handle_t *handle, enet_event_t event, enet_frame_info_t *frameinfo, void *param) { const struct device *dev = param; - const struct nxp_enet_mac_config *config = dev->config; struct nxp_enet_mac_data *data = dev->data; switch (event) { @@ -569,7 +568,7 @@ static void eth_callback(ENET_Type *base, enet_handle_t *handle, break; case kENET_TimeStampEvent: /* Reset periodic timer to default value. */ - config->base->ATPER = NSEC_PER_SEC; + data->base->ATPER = NSEC_PER_SEC; break; default: break; @@ -588,16 +587,16 @@ static void eth_nxp_enet_isr(const struct device *dev) struct nxp_enet_mac_data *data = dev->data; unsigned int irq_lock_key = irq_lock(); - uint32_t eir = ENET_GetInterruptStatus(config->base); + uint32_t eir = ENET_GetInterruptStatus(data->base); if (eir & (kENET_RxFrameInterrupt)) { - ENET_ReceiveIRQHandler(ENET_IRQ_HANDLER_ARGS(config->base, &data->enet_handle)); - ENET_DisableInterrupts(config->base, kENET_RxFrameInterrupt); + ENET_ReceiveIRQHandler(ENET_IRQ_HANDLER_ARGS(data->base, &data->enet_handle)); + ENET_DisableInterrupts(data->base, kENET_RxFrameInterrupt); k_work_submit_to_queue(&rx_work_queue, &data->rx_work); } if (eir & kENET_TxFrameInterrupt) { - ENET_TransmitIRQHandler(ENET_IRQ_HANDLER_ARGS(config->base, &data->enet_handle)); + ENET_TransmitIRQHandler(ENET_IRQ_HANDLER_ARGS(data->base, &data->enet_handle)); } if (eir & ENET_EIR_MII_MASK) { @@ -660,6 +659,8 @@ static int eth_nxp_enet_init(const struct device *dev) uint32_t enet_module_clock_rate; int err; + data->base = (ENET_Type *)DEVICE_MMIO_GET(config->module_dev); + err = pinctrl_apply_state(config->pincfg, PINCTRL_STATE_DEFAULT); if (err) { return err; @@ -733,7 +734,7 @@ static int eth_nxp_enet_init(const struct device *dev) enet_config.callback = eth_callback; enet_config.userData = (void *)dev; - ENET_Up(config->base, + ENET_Up(data->base, &data->enet_handle, &enet_config, &config->buffer_config, @@ -748,7 +749,7 @@ static int eth_nxp_enet_init(const struct device *dev) ENET_SetTxReclaim(&data->enet_handle, true, 0); #endif - ENET_ActiveRead(config->base); + ENET_ActiveRead(data->base); err = nxp_enet_phy_init(dev); if (err) { @@ -948,8 +949,8 @@ BUILD_ASSERT(NXP_ENET_PHY_MODE(DT_DRV_INST(n)) != NXP_ENET_RGMII_MODE || \ [ETH_NXP_ENET_BUFFER_SIZE]; \ \ const struct nxp_enet_mac_config nxp_enet_##n##_config = { \ - .base = (ENET_Type *)DT_REG_ADDR(DT_INST_PARENT(n)), \ .irq_config_func = nxp_enet_##n##_irq_config_func, \ + .module_dev = DEVICE_DT_GET(DT_INST_PARENT(n)), \ .clock_dev = DEVICE_DT_GET(DT_CLOCKS_CTLR(DT_INST_PARENT(n))), \ .clock_subsys = (void *)DT_CLOCKS_CELL_BY_IDX( \ DT_INST_PARENT(n), 0, name), \ @@ -996,27 +997,67 @@ BUILD_ASSERT(NXP_ENET_PHY_MODE(DT_DRV_INST(n)) != NXP_ENET_RGMII_MODE || \ DT_INST_FOREACH_STATUS_OKAY(NXP_ENET_MAC_INIT) +struct nxp_enet_mod_config { + DEVICE_MMIO_ROM; + const struct device *clock_dev; + clock_control_subsys_t clock_subsys; +}; + +struct nxp_enet_mod_data { + DEVICE_MMIO_RAM; +}; + +static int nxp_enet_mod_init(const struct device *dev) +{ + const struct nxp_enet_mod_config *config = dev->config; + + clock_control_on(config->clock_dev, config->clock_subsys); + + DEVICE_MMIO_MAP(dev, K_MEM_CACHE_NONE | K_MEM_DIRECT_MAP); + + ENET_Reset((ENET_Type *)DEVICE_MMIO_GET(dev)); + + return 0; +} + #define NXP_ENET_INIT(n, compat) \ \ -int compat##_##n##_init(void) \ -{ \ - clock_control_on(DEVICE_DT_GET(DT_INST_CLOCKS_CTLR(n)), \ - (void *)DT_INST_CLOCKS_CELL_BY_IDX(n, 0, name)); \ - \ - ENET_Reset((ENET_Type *)DT_INST_REG_ADDR(n)); \ +static const struct nxp_enet_mod_config nxp_enet_mod_cfg_##n = { \ + DEVICE_MMIO_ROM_INIT(DT_DRV_INST(n)), \ + .clock_dev = DEVICE_DT_GET(DT_CLOCKS_CTLR(DT_DRV_INST(n))), \ + .clock_subsys = (void *) DT_CLOCKS_CELL_BY_IDX( \ + DT_DRV_INST(n), 0, name), \ +}; \ \ - return 0; \ -} \ +static struct nxp_enet_mod_data nxp_enet_mod_data_##n; \ \ - /* Init the module before any of the MAC, MDIO, or PTP clock */ \ - SYS_INIT(compat##_##n##_init, POST_KERNEL, 0); +/* Init the module before any of the MAC, MDIO, or PTP clock */ \ +DEVICE_DT_INST_DEFINE(n, nxp_enet_mod_init, NULL, \ + &nxp_enet_mod_data_##n, &nxp_enet_mod_cfg_##n, \ + POST_KERNEL, 0, NULL); #undef DT_DRV_COMPAT #define DT_DRV_COMPAT nxp_enet DT_INST_FOREACH_STATUS_OKAY_VARGS(NXP_ENET_INIT, DT_DRV_COMPAT) +#define NXP_ENET1G_INIT(n, compat) \ + \ +static const struct nxp_enet_mod_config nxp_enet1g_mod_cfg_##n = { \ + DEVICE_MMIO_ROM_INIT(DT_DRV_INST(n)), \ + .clock_dev = DEVICE_DT_GET(DT_CLOCKS_CTLR(DT_DRV_INST(n))), \ + .clock_subsys = (void *) DT_CLOCKS_CELL_BY_IDX( \ + DT_DRV_INST(n), 0, name), \ +}; \ + \ +static struct nxp_enet_mod_data nxp_enet1g_mod_data_##n; \ + \ +/* Init the module before any of the MAC, MDIO, or PTP clock */ \ +DEVICE_DT_INST_DEFINE(n, nxp_enet_mod_init, NULL, \ + &nxp_enet1g_mod_data_##n, &nxp_enet1g_mod_cfg_##n, \ + POST_KERNEL, 0, NULL); + #undef DT_DRV_COMPAT #define DT_DRV_COMPAT nxp_enet1g -DT_INST_FOREACH_STATUS_OKAY_VARGS(NXP_ENET_INIT, DT_DRV_COMPAT) +DT_INST_FOREACH_STATUS_OKAY_VARGS(NXP_ENET1G_INIT, DT_DRV_COMPAT) From c8d8dce7555bf2995b5a003521b809c985315762 Mon Sep 17 00:00:00 2001 From: Jiafei Pan Date: Thu, 25 Apr 2024 15:15:02 +0800 Subject: [PATCH 2771/2849] drivers: ptp_clock: ptp_enet: use MMIO mapped address Get MMIO mapped address from ENET module driver. Signed-off-by: Jiafei Pan --- drivers/ptp_clock/ptp_clock_nxp_enet.c | 37 +++++++++++++------------- 1 file changed, 18 insertions(+), 19 deletions(-) diff --git a/drivers/ptp_clock/ptp_clock_nxp_enet.c b/drivers/ptp_clock/ptp_clock_nxp_enet.c index 286c6c91d57c5..b5e1cbb9bd32c 100644 --- a/drivers/ptp_clock/ptp_clock_nxp_enet.c +++ b/drivers/ptp_clock/ptp_clock_nxp_enet.c @@ -1,5 +1,5 @@ /* - * Copyright 2023 NXP + * Copyright 2023-2024 NXP * * Based on a commit to drivers/ethernet/eth_mcux.c which was: * Copyright (c) 2018 Intel Coporation @@ -19,8 +19,8 @@ #include struct ptp_clock_nxp_enet_config { - ENET_Type *base; const struct pinctrl_dev_config *pincfg; + const struct device *module_dev; const struct device *port; const struct device *clock_dev; struct device *clock_subsys; @@ -28,6 +28,7 @@ struct ptp_clock_nxp_enet_config { }; struct ptp_clock_nxp_enet_data { + ENET_Type *base; double clock_ratio; enet_handle_t enet_handle; struct k_mutex ptp_mutex; @@ -36,14 +37,13 @@ struct ptp_clock_nxp_enet_data { static int ptp_clock_nxp_enet_set(const struct device *dev, struct net_ptp_time *tm) { - const struct ptp_clock_nxp_enet_config *config = dev->config; struct ptp_clock_nxp_enet_data *data = dev->data; enet_ptp_time_t enet_time; enet_time.second = tm->second; enet_time.nanosecond = tm->nanosecond; - ENET_Ptp1588SetTimer(config->base, &data->enet_handle, &enet_time); + ENET_Ptp1588SetTimer(data->base, &data->enet_handle, &enet_time); return 0; } @@ -51,11 +51,10 @@ static int ptp_clock_nxp_enet_set(const struct device *dev, static int ptp_clock_nxp_enet_get(const struct device *dev, struct net_ptp_time *tm) { - const struct ptp_clock_nxp_enet_config *config = dev->config; struct ptp_clock_nxp_enet_data *data = dev->data; enet_ptp_time_t enet_time; - ENET_Ptp1588GetTimer(config->base, &data->enet_handle, &enet_time); + ENET_Ptp1588GetTimer(data->base, &data->enet_handle, &enet_time); tm->second = enet_time.second; tm->nanosecond = enet_time.nanosecond; @@ -66,7 +65,7 @@ static int ptp_clock_nxp_enet_get(const struct device *dev, static int ptp_clock_nxp_enet_adjust(const struct device *dev, int increment) { - const struct ptp_clock_nxp_enet_config *config = dev->config; + struct ptp_clock_nxp_enet_data *data = dev->data; int ret = 0; int key; @@ -75,13 +74,13 @@ static int ptp_clock_nxp_enet_adjust(const struct device *dev, ret = -EINVAL; } else { key = irq_lock(); - if (config->base->ATPER != NSEC_PER_SEC) { + if (data->base->ATPER != NSEC_PER_SEC) { ret = -EBUSY; } else { /* Seconds counter is handled by software. Change the * period of one software second to adjust the clock. */ - config->base->ATPER = NSEC_PER_SEC - increment; + data->base->ATPER = NSEC_PER_SEC - increment; ret = 0; } irq_unlock(key); @@ -144,7 +143,7 @@ static int ptp_clock_nxp_enet_rate_adjust(const struct device *dev, k_mutex_lock(&data->ptp_mutex, K_FOREVER); - ENET_Ptp1588AdjustTimer(config->base, corr, mul); + ENET_Ptp1588AdjustTimer(data->base, corr, mul); k_mutex_unlock(&data->ptp_mutex); @@ -167,17 +166,17 @@ void nxp_enet_ptp_clock_callback(const struct device *dev, (void) clock_control_get_rate(config->clock_dev, config->clock_subsys, &enet_ref_pll_rate); - ENET_AddMulticastGroup(config->base, ptp_multicast); - ENET_AddMulticastGroup(config->base, ptp_peer_multicast); + ENET_AddMulticastGroup(data->base, ptp_multicast); + ENET_AddMulticastGroup(data->base, ptp_peer_multicast); /* only for ERRATA_2579 */ ptp_config.channel = kENET_PtpTimerChannel3; ptp_config.ptp1588ClockSrc_Hz = enet_ref_pll_rate; data->clock_ratio = 1.0; - ENET_Ptp1588SetChannelMode(config->base, kENET_PtpTimerChannel3, + ENET_Ptp1588SetChannelMode(data->base, kENET_PtpTimerChannel3, kENET_PtpChannelPulseHighonCompare, true); - ENET_Ptp1588Configure(config->base, &data->enet_handle, + ENET_Ptp1588Configure(data->base, &data->enet_handle, &ptp_config); } @@ -193,6 +192,8 @@ static int ptp_clock_nxp_enet_init(const struct device *port) struct ptp_clock_nxp_enet_data *data = port->data; int ret; + data->base = (ENET_Type *)DEVICE_MMIO_GET(config->module_dev); + ret = pinctrl_apply_state(config->pincfg, PINCTRL_STATE_DEFAULT); if (ret) { return ret; @@ -207,7 +208,6 @@ static int ptp_clock_nxp_enet_init(const struct device *port) static void ptp_clock_nxp_enet_isr(const struct device *dev) { - const struct ptp_clock_nxp_enet_config *config = dev->config; struct ptp_clock_nxp_enet_data *data = dev->data; enet_ptp_timer_channel_t channel; @@ -215,12 +215,12 @@ static void ptp_clock_nxp_enet_isr(const struct device *dev) /* clear channel */ for (channel = kENET_PtpTimerChannel1; channel <= kENET_PtpTimerChannel4; channel++) { - if (ENET_Ptp1588GetChannelStatus(config->base, channel)) { - ENET_Ptp1588ClearChannelStatus(config->base, channel); + if (ENET_Ptp1588GetChannelStatus(data->base, channel)) { + ENET_Ptp1588ClearChannelStatus(data->base, channel); } } - ENET_TimeStampIRQHandler(config->base, &data->enet_handle); + ENET_TimeStampIRQHandler(data->base, &data->enet_handle); irq_unlock(irq_lock_key); } @@ -247,7 +247,6 @@ static const struct ptp_clock_driver_api ptp_clock_nxp_enet_api = { \ static const struct ptp_clock_nxp_enet_config \ ptp_clock_nxp_enet_##n##_config = { \ - .base = (ENET_Type *) DT_REG_ADDR(DT_INST_PARENT(n)), \ .pincfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n), \ .port = DEVICE_DT_INST_GET(n), \ .clock_dev = DEVICE_DT_GET(DT_INST_CLOCKS_CTLR(n)), \ From bbf34ad6a0e8e69919b78a2f1cefd013c18506d3 Mon Sep 17 00:00:00 2001 From: Jiafei Pan Date: Thu, 18 Apr 2024 11:00:19 +0800 Subject: [PATCH 2772/2849] drivers: mdio_nxp_enet: remove unused header file soc.h is not used, and some platform has no such header file, so remove it. Signed-off-by: Jiafei Pan --- drivers/mdio/mdio_nxp_enet.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/mdio/mdio_nxp_enet.c b/drivers/mdio/mdio_nxp_enet.c index f91158ed505cc..66793e4639157 100644 --- a/drivers/mdio/mdio_nxp_enet.c +++ b/drivers/mdio/mdio_nxp_enet.c @@ -14,7 +14,6 @@ #include #include #include -#include struct nxp_enet_mdio_config { ENET_Type *base; From 671aaf48b51b8ab069b48908d83f4bc97ca74cb8 Mon Sep 17 00:00:00 2001 From: Jiafei Pan Date: Wed, 24 Apr 2024 17:06:35 +0800 Subject: [PATCH 2773/2849] drivers: mdio_nxp_enet: using MMIO mapped address Use ENET module MMIO mapping address directly. Signed-off-by: Jiafei Pan --- drivers/mdio/mdio_nxp_enet.c | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/drivers/mdio/mdio_nxp_enet.c b/drivers/mdio/mdio_nxp_enet.c index 66793e4639157..896de74790329 100644 --- a/drivers/mdio/mdio_nxp_enet.c +++ b/drivers/mdio/mdio_nxp_enet.c @@ -1,5 +1,5 @@ /* - * Copyright 2023 NXP + * Copyright 2023-2024 NXP * * SPDX-License-Identifier: Apache-2.0 */ @@ -16,8 +16,8 @@ #include struct nxp_enet_mdio_config { - ENET_Type *base; const struct pinctrl_dev_config *pincfg; + const struct device *module_dev; const struct device *clock_dev; clock_control_subsys_t clock_subsys; uint32_t mdc_freq; @@ -26,6 +26,7 @@ struct nxp_enet_mdio_config { }; struct nxp_enet_mdio_data { + ENET_Type *base; struct k_mutex mdio_mutex; struct k_sem mdio_sem; bool interrupt_up; @@ -42,7 +43,7 @@ static int nxp_enet_mdio_wait_xfer(const struct device *dev) { const struct nxp_enet_mdio_config *config = dev->config; struct nxp_enet_mdio_data *data = dev->data; - ENET_Type *base = config->base; + ENET_Type *base = data->base; int ret = 0; /* This function will not make sense from IRQ context */ @@ -82,7 +83,6 @@ static int nxp_enet_mdio_wait_xfer(const struct device *dev) static int nxp_enet_mdio_read(const struct device *dev, uint8_t prtad, uint8_t regad, uint16_t *read_data) { - const struct nxp_enet_mdio_config *config = dev->config; struct nxp_enet_mdio_data *data = dev->data; int ret; @@ -93,7 +93,7 @@ static int nxp_enet_mdio_read(const struct device *dev, * Clear the bit (W1C) that indicates MDIO transfer is ready to * prepare to wait for it to be set once this read is done */ - config->base->EIR |= ENET_EIR_MII_MASK; + data->base->EIR |= ENET_EIR_MII_MASK; /* * Write MDIO frame to MII management register which will @@ -105,7 +105,7 @@ static int nxp_enet_mdio_read(const struct device *dev, * TA = Turnaround, must be 2 to be valid * data = data to be written to the PHY register */ - config->base->MMFR = ENET_MMFR_ST(0x1U) | + data->base->MMFR = ENET_MMFR_ST(0x1U) | ENET_MMFR_OP(MDIO_OP_C22_READ) | ENET_MMFR_PA(prtad) | ENET_MMFR_RA(regad) | @@ -118,10 +118,10 @@ static int nxp_enet_mdio_read(const struct device *dev, } /* The data is received in the same register that we wrote the command to */ - *read_data = (config->base->MMFR & ENET_MMFR_DATA_MASK) >> ENET_MMFR_DATA_SHIFT; + *read_data = (data->base->MMFR & ENET_MMFR_DATA_MASK) >> ENET_MMFR_DATA_SHIFT; /* Clear the same bit as before because the event has been handled */ - config->base->EIR |= ENET_EIR_MII_MASK; + data->base->EIR |= ENET_EIR_MII_MASK; /* This MDIO interaction is finished */ (void)k_mutex_unlock(&data->mdio_mutex); @@ -133,7 +133,6 @@ static int nxp_enet_mdio_read(const struct device *dev, static int nxp_enet_mdio_write(const struct device *dev, uint8_t prtad, uint8_t regad, uint16_t write_data) { - const struct nxp_enet_mdio_config *config = dev->config; struct nxp_enet_mdio_data *data = dev->data; int ret; @@ -144,7 +143,7 @@ static int nxp_enet_mdio_write(const struct device *dev, * Clear the bit (W1C) that indicates MDIO transfer is ready to * prepare to wait for it to be set once this write is done */ - config->base->EIR |= ENET_EIR_MII_MASK; + data->base->EIR |= ENET_EIR_MII_MASK; /* * Write MDIO frame to MII management register which will @@ -156,7 +155,7 @@ static int nxp_enet_mdio_write(const struct device *dev, * TA = Turnaround, must be 2 to be valid * data = data to be written to the PHY register */ - config->base->MMFR = ENET_MMFR_ST(0x1U) | + data->base->MMFR = ENET_MMFR_ST(0x1U) | ENET_MMFR_OP(MDIO_OP_C22_WRITE) | ENET_MMFR_PA(prtad) | ENET_MMFR_RA(regad) | @@ -170,7 +169,7 @@ static int nxp_enet_mdio_write(const struct device *dev, } /* Clear the same bit as before because the event has been handled */ - config->base->EIR |= ENET_EIR_MII_MASK; + data->base->EIR |= ENET_EIR_MII_MASK; /* This MDIO interaction is finished */ (void)k_mutex_unlock(&data->mdio_mutex); @@ -185,19 +184,19 @@ static const struct mdio_driver_api nxp_enet_mdio_api = { static void nxp_enet_mdio_isr_cb(const struct device *dev) { - const struct nxp_enet_mdio_config *config = dev->config; struct nxp_enet_mdio_data *data = dev->data; /* Signal that operation finished */ k_sem_give(&data->mdio_sem); /* Disable the interrupt */ - config->base->EIMR &= ~ENET_EIMR_MII_MASK; + data->base->EIMR &= ~ENET_EIMR_MII_MASK; } static void nxp_enet_mdio_post_module_reset_init(const struct device *dev) { const struct nxp_enet_mdio_config *config = dev->config; + struct nxp_enet_mdio_data *data = dev->data; uint32_t enet_module_clock_rate; /* Set up MSCR register */ @@ -209,7 +208,7 @@ static void nxp_enet_mdio_post_module_reset_init(const struct device *dev) (NSEC_PER_SEC / enet_module_clock_rate) - 1; uint32_t mscr = ENET_MSCR_MII_SPEED(mii_speed) | ENET_MSCR_HOLDTIME(holdtime) | (config->disable_preamble ? ENET_MSCR_DIS_PRE_MASK : 0); - config->base->MSCR = mscr; + data->base->MSCR = mscr; } void nxp_enet_mdio_callback(const struct device *dev, @@ -240,6 +239,8 @@ static int nxp_enet_mdio_init(const struct device *dev) struct nxp_enet_mdio_data *data = dev->data; int ret = 0; + data->base = (ENET_Type *)DEVICE_MMIO_GET(config->module_dev); + ret = pinctrl_apply_state(config->pincfg, PINCTRL_STATE_DEFAULT); if (ret) { return ret; @@ -265,7 +266,7 @@ static int nxp_enet_mdio_init(const struct device *dev) PINCTRL_DT_INST_DEFINE(inst); \ \ static const struct nxp_enet_mdio_config nxp_enet_mdio_cfg_##inst = { \ - .base = (ENET_Type *) DT_REG_ADDR(DT_INST_PARENT(inst)), \ + .module_dev = DEVICE_DT_GET(DT_INST_PARENT(inst)), \ .pincfg = PINCTRL_DT_INST_DEV_CONFIG_GET(inst), \ .timeout = CONFIG_MDIO_NXP_ENET_TIMEOUT, \ .clock_dev = DEVICE_DT_GET(DT_CLOCKS_CTLR(DT_INST_PARENT(inst))), \ From 5c95d04b26631511df0a08d9ac1e756c1bfe6d3c Mon Sep 17 00:00:00 2001 From: Jiafei Pan Date: Thu, 18 Apr 2024 11:02:05 +0800 Subject: [PATCH 2774/2849] clock: mcux_ccm: add enet clock support for imx8m serial Add ENET clock support for imx8m serial platforms. Signed-off-by: Jiafei Pan --- drivers/clock_control/clock_control_mcux_ccm.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/drivers/clock_control/clock_control_mcux_ccm.c b/drivers/clock_control/clock_control_mcux_ccm.c index c9fd6229bab5e..72f1afaae398d 100644 --- a/drivers/clock_control/clock_control_mcux_ccm.c +++ b/drivers/clock_control/clock_control_mcux_ccm.c @@ -108,8 +108,13 @@ static int mcux_ccm_on(const struct device *dev, #endif #if defined(CONFIG_ETH_NXP_ENET) +#ifdef CONFIG_SOC_SERIES_IMX8M +#define ENET_CLOCK kCLOCK_Enet1 +#else +#define ENET_CLOCK kCLOCK_Enet +#endif case IMX_CCM_ENET_CLK: - CLOCK_EnableClock(kCLOCK_Enet); + CLOCK_EnableClock(ENET_CLOCK); return 0; #endif default: @@ -239,9 +244,14 @@ static int mcux_ccm_get_subsys_rate(const struct device *dev, #ifdef CONFIG_ETH_NXP_ENET case IMX_CCM_ENET_CLK: +#ifdef CONFIG_SOC_SERIES_IMX8M + *rate = CLOCK_GetFreq(kCLOCK_EnetIpgClk); +#else *rate = CLOCK_GetIpgFreq(); - break; #endif +#endif + break; + #ifdef CONFIG_PTP_CLOCK_NXP_ENET case IMX_CCM_ENET_PLL: *rate = CLOCK_GetPllFreq(kCLOCK_PllEnet); From 20dae220bd95ec236213f6fd5a113457ea5744cc Mon Sep 17 00:00:00 2001 From: Jiafei Pan Date: Wed, 3 Apr 2024 18:41:37 +0800 Subject: [PATCH 2775/2849] board: imx8mp_evk: add ENET support on Cortex-A Core Add ENET support on Cortex-A Core, enable it in DTS. Update board document for supported features. Signed-off-by: Jiafei Pan --- boards/nxp/imx8mp_evk/doc/index.rst | 8 ++++ boards/nxp/imx8mp_evk/imx8mp_evk-pinctrl.dtsi | 42 ++++++++++++++++++- .../imx8mp_evk/imx8mp_evk_mimx8ml8_a53.dts | 27 +++++++++++- dts/arm64/nxp/nxp_mimx8mp_a53.dtsi | 30 +++++++++++++ 4 files changed, 105 insertions(+), 2 deletions(-) diff --git a/boards/nxp/imx8mp_evk/doc/index.rst b/boards/nxp/imx8mp_evk/doc/index.rst index c36a9065d31e9..684f03d5a5b04 100644 --- a/boards/nxp/imx8mp_evk/doc/index.rst +++ b/boards/nxp/imx8mp_evk/doc/index.rst @@ -55,8 +55,16 @@ features: +-----------+------------+-------------------------------------+ | ARM TIMER | on-chip | system clock | +-----------+------------+-------------------------------------+ +| CLOCK | on-chip | clock_control | ++-----------+------------+-------------------------------------+ +| PINMUX | on-chip | pinmux | ++-----------+------------+-------------------------------------+ +| RDC | on-chip | Resource Domain Controller | ++-----------+------------+-------------------------------------+ | UART | on-chip | serial port | +-----------+------------+-------------------------------------+ +| ENET | on-chip | ethernet port | ++-----------+------------+-------------------------------------+ The Zephyr mimx8mp_evk_m7 board configuration supports the following hardware features: diff --git a/boards/nxp/imx8mp_evk/imx8mp_evk-pinctrl.dtsi b/boards/nxp/imx8mp_evk/imx8mp_evk-pinctrl.dtsi index 949b622affb5d..f88555b13e276 100644 --- a/boards/nxp/imx8mp_evk/imx8mp_evk-pinctrl.dtsi +++ b/boards/nxp/imx8mp_evk/imx8mp_evk-pinctrl.dtsi @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, NXP + * Copyright 2022-2024 NXP * SPDX-License-Identifier: Apache-2.0 * */ @@ -26,4 +26,44 @@ drive-strength = "x1"; }; }; + + pinmux_mdio: pinmux_mdio { + group0 { + pinmux = <&iomuxc_sai1_rxd2_enet_mdc_enet1_mdc>, + <&iomuxc_sai1_rxd3_enet_mdio_enet1_mdio>; + slew-rate = "slow"; + drive-strength = "x4"; + }; + }; + + pinmux_enet: pinmux_enet { + group0 { + pinmux = <&iomuxc_sai1_rxd4_enet_rgmii_rd_enet1_rgmii_rd0>, + <&iomuxc_sai1_rxd5_enet_rgmii_rd_enet1_rgmii_rd1>, + <&iomuxc_sai1_rxd6_enet_rgmii_rd_enet1_rgmii_rd2>, + <&iomuxc_sai1_rxd7_enet_rgmii_rd_enet1_rgmii_rd3>, + <&iomuxc_sai1_txc_enet_rgmii_rxc_enet1_rgmii_rxc>, + <&iomuxc_sai1_txfs_enet_rgmii_rx_ctl_enet1_rgmii_rx_ctl>; + input-schmitt-enable; + slew-rate = "fast"; + drive-strength = "x1"; + }; + + group1 { + pinmux = <&iomuxc_sai1_txd0_enet_rgmii_td_enet1_rgmii_td0>, + <&iomuxc_sai1_txd1_enet_rgmii_td_enet1_rgmii_td1>, + <&iomuxc_sai1_txd2_enet_rgmii_td_enet1_rgmii_td2>, + <&iomuxc_sai1_txd3_enet_rgmii_td_enet1_rgmii_td3>, + <&iomuxc_sai1_txd4_enet_rgmii_tx_ctl_enet1_rgmii_tx_ctl>, + <&iomuxc_sai1_txd5_enet_rgmii_txc_enet1_rgmii_txc>; + slew-rate = "fast"; + drive-strength = "x6"; + }; + + group2 { + pinmux = <&iomuxc_sai1_rxd0_gpio_io_gpio4_io2>; + slew-rate = "fast"; + drive-strength = "x1"; + }; + }; }; diff --git a/boards/nxp/imx8mp_evk/imx8mp_evk_mimx8ml8_a53.dts b/boards/nxp/imx8mp_evk/imx8mp_evk_mimx8ml8_a53.dts index 18cff6569d493..634092adbd4e5 100644 --- a/boards/nxp/imx8mp_evk/imx8mp_evk_mimx8ml8_a53.dts +++ b/boards/nxp/imx8mp_evk/imx8mp_evk_mimx8ml8_a53.dts @@ -1,5 +1,5 @@ /* - * Copyright 2021-2022 NXP + * Copyright 2021-2024 NXP * * SPDX-License-Identifier: Apache-2.0 */ @@ -34,6 +34,31 @@ sram0: memory@c0000000 { reg = <0xc0000000 DT_SIZE_M(1)>; }; + +}; + +&enet { + status = "okay"; +}; + +&enet_mac { + pinctrl-0 = <&pinmux_enet>; + pinctrl-names = "default"; + phy-handle = <&phy>; + zephyr,random-mac-address; + phy-connection-type = "rgmii"; + status = "okay"; +}; + +&enet_mdio { + pinctrl-0 = <&pinmux_mdio>; + pinctrl-names = "default"; + status = "okay"; + phy: phy@0 { + compatible = "realtek,rtl8211f"; + reg = <1>; + status = "okay"; + }; }; &uart4 { diff --git a/dts/arm64/nxp/nxp_mimx8mp_a53.dtsi b/dts/arm64/nxp/nxp_mimx8mp_a53.dtsi index 9fdfa1d27f345..93c85d2c70306 100644 --- a/dts/arm64/nxp/nxp_mimx8mp_a53.dtsi +++ b/dts/arm64/nxp/nxp_mimx8mp_a53.dtsi @@ -124,6 +124,36 @@ status = "disabled"; }; + enet: enet@30be0000 { + compatible = "nxp,enet1g"; + reg = <0x30be0000 DT_SIZE_K(64)>; + clocks = <&ccm IMX_CCM_ENET_CLK 0 0>; + status = "disabled"; + + enet_mac: ethernet { + compatible = "nxp,enet-mac"; + interrupts = ; + interrupt-names = "COMMON"; + interrupt-parent = <&gic>; + nxp,mdio = <&enet_mdio>; + nxp,ptp-clock = <&enet_ptp_clock>; + status = "disabled"; + }; + enet_mdio: mdio { + compatible = "nxp,enet-mdio"; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + enet_ptp_clock: ptp_clock { + compatible = "nxp,enet-ptp-clock"; + interrupts = ; + interrupt-parent = <&gic>; + clocks = <&ccm IMX_CCM_ENET_PLL 0 0>; + status = "disabled"; + }; + }; + iomuxc: iomuxc@30330000 { compatible = "nxp,imx-iomuxc"; reg = <0x30330000 DT_SIZE_K(64)>; From 3f831e30fae3e4868f57fc5b97bd0d6d64c11e9a Mon Sep 17 00:00:00 2001 From: Jiafei Pan Date: Tue, 23 Apr 2024 18:37:37 +0800 Subject: [PATCH 2776/2849] soc: imx8mm/n/p: enable cache driver for Cortex-A Core Enable Cache driver in hal_nxp. Signed-off-by: Jiafei Pan --- soc/nxp/imx/imx8m/Kconfig | 3 +++ west.yml | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/soc/nxp/imx/imx8m/Kconfig b/soc/nxp/imx/imx8m/Kconfig index 562290ddfc825..fe206de15270c 100644 --- a/soc/nxp/imx/imx8m/Kconfig +++ b/soc/nxp/imx/imx8m/Kconfig @@ -9,6 +9,7 @@ config SOC_MIMX8MM6_A53 select HAS_MCUX_CCM if CLOCK_CONTROL select HAS_MCUX_IOMUXC if PINCTRL select HAS_MCUX_RDC + select HAS_MCUX_CACHE config SOC_MIMX8MM6_M4 select ARM @@ -29,6 +30,7 @@ config SOC_MIMX8ML8_A53 select HAS_MCUX_CCM if CLOCK_CONTROL select HAS_MCUX_IOMUXC if PINCTRL select HAS_MCUX_RDC + select HAS_MCUX_CACHE config SOC_MIMX8MN6_A53 select ARM64 @@ -38,6 +40,7 @@ config SOC_MIMX8MN6_A53 select HAS_MCUX_CCM if CLOCK_CONTROL select HAS_MCUX_IOMUXC if PINCTRL select HAS_MCUX_RDC + select HAS_MCUX_CACHE config SOC_MIMX8ML8_ADSP select XTENSA diff --git a/west.yml b/west.yml index 5c85145297cf1..10e7ec2a648a8 100644 --- a/west.yml +++ b/west.yml @@ -198,7 +198,7 @@ manifest: groups: - hal - name: hal_nxp - revision: 5db52e3e3bd6a7ada1f4983e037555d3ff9af028 + revision: bee15c31e19ff1982583d9b750ef844d64320160 path: modules/hal/nxp groups: - hal From 4f034f46b06cbdc13b6b081d4ae2483d4ac893a3 Mon Sep 17 00:00:00 2001 From: Jiafei Pan Date: Wed, 24 Apr 2024 11:00:34 +0800 Subject: [PATCH 2777/2849] soc: imx8mp: enable rdc for enet Add RDC dts node for ENET and configure it in soc.c. Signed-off-by: Jiafei Pan --- dts/arm64/nxp/nxp_mimx8mp_a53.dtsi | 1 + dts/bindings/ethernet/nxp,enet.yaml | 2 +- dts/bindings/ethernet/nxp,enet1g.yaml | 4 ++++ soc/nxp/imx/imx8m/a53/soc.c | 6 ++++++ 4 files changed, 12 insertions(+), 1 deletion(-) diff --git a/dts/arm64/nxp/nxp_mimx8mp_a53.dtsi b/dts/arm64/nxp/nxp_mimx8mp_a53.dtsi index 93c85d2c70306..5913da254486c 100644 --- a/dts/arm64/nxp/nxp_mimx8mp_a53.dtsi +++ b/dts/arm64/nxp/nxp_mimx8mp_a53.dtsi @@ -128,6 +128,7 @@ compatible = "nxp,enet1g"; reg = <0x30be0000 DT_SIZE_K(64)>; clocks = <&ccm IMX_CCM_ENET_CLK 0 0>; + rdc = ; status = "disabled"; enet_mac: ethernet { diff --git a/dts/bindings/ethernet/nxp,enet.yaml b/dts/bindings/ethernet/nxp,enet.yaml index f98af9f002b50..23e234bb7ae7a 100644 --- a/dts/bindings/ethernet/nxp,enet.yaml +++ b/dts/bindings/ethernet/nxp,enet.yaml @@ -1,4 +1,4 @@ -# Copyright 2023 NXP +# Copyright 2023-2024 NXP # SPDX-License-Identifier: Apache-2.0 description: NXP ENET IP Module diff --git a/dts/bindings/ethernet/nxp,enet1g.yaml b/dts/bindings/ethernet/nxp,enet1g.yaml index 3f79a33f060a1..4c7e99ab72d2e 100644 --- a/dts/bindings/ethernet/nxp,enet1g.yaml +++ b/dts/bindings/ethernet/nxp,enet1g.yaml @@ -13,3 +13,7 @@ properties: clocks: required: true + + rdc: + type: int + description: Set the RDC(Resource Domain Controller) domain permission for this peripheral diff --git a/soc/nxp/imx/imx8m/a53/soc.c b/soc/nxp/imx/imx8m/a53/soc.c index 412880e4023f8..002b884daa044 100644 --- a/soc/nxp/imx/imx8m/a53/soc.c +++ b/soc/nxp/imx/imx8m/a53/soc.c @@ -35,6 +35,12 @@ static void soc_rdc_init(void) periphConfig.policy = RDC_DT_VAL(uart4); RDC_SetPeriphAccessConfig(RDC, &periphConfig); #endif + +#if DT_NODE_HAS_STATUS(DT_NODELABEL(enet), okay) && DT_NODE_HAS_PROP(DT_NODELABEL(enet), rdc) + periphConfig.periph = kRDC_Periph_ENET1; + periphConfig.policy = RDC_DT_VAL(enet); + RDC_SetPeriphAccessConfig(RDC, &periphConfig); +#endif } static int soc_init(void) From 12405a64d4def2f3962846b8ed660ca00edf25e5 Mon Sep 17 00:00:00 2001 From: Fabio Baltieri Date: Wed, 10 Jan 2024 22:14:01 +0000 Subject: [PATCH 2778/2849] input: analog_axis: implement power management support Implement suspend and resume, just stop and restart the timer that kicks the main thread update cycles. Signed-off-by: Fabio Baltieri --- drivers/input/input_analog_axis.c | 72 ++++++++++++++++++++++++++++--- 1 file changed, 67 insertions(+), 5 deletions(-) diff --git a/drivers/input/input_analog_axis.c b/drivers/input/input_analog_axis.c index 4217fdc765014..44c0cc34cb6ea 100644 --- a/drivers/input/input_analog_axis.c +++ b/drivers/input/input_analog_axis.c @@ -13,6 +13,9 @@ #include #include #include +#include +#include +#include #include LOG_MODULE_REGISTER(analog_axis, CONFIG_INPUT_LOG_LEVEL); @@ -45,6 +48,11 @@ struct analog_axis_data { K_KERNEL_STACK_MEMBER(thread_stack, CONFIG_INPUT_ANALOG_AXIS_THREAD_STACK_SIZE); + +#ifdef CONFIG_PM_DEVICE + atomic_t suspended; + struct k_sem wakeup; +#endif }; int analog_axis_num_axes(const struct device *dev) @@ -229,11 +237,13 @@ static void analog_axis_thread(void *arg1, void *arg2, void *arg3) } } - k_timer_init(&data->timer, NULL, NULL); - k_timer_start(&data->timer, - K_MSEC(cfg->poll_period_ms), K_MSEC(cfg->poll_period_ms)); - while (true) { +#ifdef CONFIG_PM_DEVICE + if (atomic_get(&data->suspended) == 1) { + k_sem_take(&data->wakeup, K_FOREVER); + } +#endif + analog_axis_loop(dev); k_timer_status_sync(&data->timer); } @@ -245,6 +255,11 @@ static int analog_axis_init(const struct device *dev) k_tid_t tid; k_sem_init(&data->cal_lock, 1, 1); + k_timer_init(&data->timer, NULL, NULL); + +#ifdef CONFIG_PM_DEVICE + k_sem_init(&data->wakeup, 0, 1); +#endif tid = k_thread_create(&data->thread, data->thread_stack, K_KERNEL_STACK_SIZEOF(data->thread_stack), @@ -258,9 +273,54 @@ static int analog_axis_init(const struct device *dev) k_thread_name_set(&data->thread, dev->name); +#ifndef CONFIG_PM_DEVICE_RUNTIME + const struct analog_axis_config *cfg = dev->config; + + k_timer_start(&data->timer, + K_MSEC(cfg->poll_period_ms), K_MSEC(cfg->poll_period_ms)); +#else + int ret; + + atomic_set(&data->suspended, 1); + + pm_device_init_suspended(dev); + ret = pm_device_runtime_enable(dev); + if (ret < 0) { + LOG_ERR("Failed to enable runtime power management"); + return ret; + } +#endif + return 0; } +#ifdef CONFIG_PM_DEVICE +static int analog_axis_pm_action(const struct device *dev, + enum pm_device_action action) +{ + const struct analog_axis_config *cfg = dev->config; + struct analog_axis_data *data = dev->data; + + switch (action) { + case PM_DEVICE_ACTION_SUSPEND: + atomic_set(&data->suspended, 1); + k_timer_stop(&data->timer); + break; + case PM_DEVICE_ACTION_RESUME: + k_timer_start(&data->timer, + K_MSEC(cfg->poll_period_ms), + K_MSEC(cfg->poll_period_ms)); + atomic_set(&data->suspended, 0); + k_sem_give(&data->wakeup); + break; + default: + return -ENOTSUP; + } + + return 0; +} +#endif + #define ANALOG_AXIS_CHANNEL_CFG_DEF(node_id) \ { \ .adc = ADC_DT_SPEC_GET(node_id), \ @@ -301,7 +361,9 @@ static int analog_axis_init(const struct device *dev) \ static struct analog_axis_data analog_axis_data_##inst; \ \ - DEVICE_DT_INST_DEFINE(inst, analog_axis_init, NULL, \ + PM_DEVICE_DT_INST_DEFINE(inst, analog_axis_pm_action); \ + \ + DEVICE_DT_INST_DEFINE(inst, analog_axis_init, PM_DEVICE_DT_INST_GET(inst), \ &analog_axis_data_##inst, &analog_axis_cfg_##inst, \ POST_KERNEL, CONFIG_INPUT_INIT_PRIORITY, NULL); From baa3b6a5ba059a626578b0fb7f148e5b6fb5bb23 Mon Sep 17 00:00:00 2001 From: Luca Burelli Date: Wed, 12 Jun 2024 18:32:49 +0200 Subject: [PATCH 2779/2849] llext: disable LL_EXTENSION_SYMBOL when not building an llext The LL_EXTENSION_SYMBOL macro is used to export a symbol to the base image. When CONFIG_LLEXT is not defined, or the file is being compiled outside of an llext, the macro is not useful and would leave orphan sections in the final image instead. This patch adds the LL_EXTENSION_BUILD definition to the llext build process, and uses it to stub out the symbol-defining macro when not building an llext. Signed-off-by: Luca Burelli --- cmake/modules/extensions.cmake | 1 + include/zephyr/llext/symbol.h | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/cmake/modules/extensions.cmake b/cmake/modules/extensions.cmake index 9fe387e238815..ade63dcded718 100644 --- a/cmake/modules/extensions.cmake +++ b/cmake/modules/extensions.cmake @@ -5394,6 +5394,7 @@ function(add_llext_target target_name) target_compile_definitions(${llext_lib_target} PRIVATE $ + LL_EXTENSION_BUILD ) target_compile_options(${llext_lib_target} PRIVATE ${zephyr_filtered_flags} diff --git a/include/zephyr/llext/symbol.h b/include/zephyr/llext/symbol.h index 62190ed08e586..1eb90cb3f5e65 100644 --- a/include/zephyr/llext/symbol.h +++ b/include/zephyr/llext/symbol.h @@ -114,12 +114,16 @@ struct llext_symtable { * * @param x Extension symbol to export to the base image */ +#if defined(CONFIG_LLEXT) && defined(LL_EXTENSION_BUILD) #define LL_EXTENSION_SYMBOL(x) \ static const struct llext_const_symbol \ Z_GENERIC_SECTION(".exported_sym") __used \ x ## _sym = { \ .name = STRINGIFY(x), .addr = (const void *)&x, \ } +#else +#define LL_EXTENSION_SYMBOL(x) +#endif /** * @} From 57011e4c1a38a8066ea1234b0714f51b47dc3658 Mon Sep 17 00:00:00 2001 From: Luca Burelli Date: Fri, 7 Jun 2024 19:10:55 +0200 Subject: [PATCH 2780/2849] llext: add a "modules" Kconfig tristate example This adds a new sample to demonstrate the use of tristate symbols in Kconfig to build a function as an llext module or as a built-in part of Zephyr. Signed-off-by: Luca Burelli --- samples/subsys/llext/modules/CMakeLists.txt | 39 ++++++++++++ samples/subsys/llext/modules/Kconfig | 18 ++++++ samples/subsys/llext/modules/README.rst | 63 +++++++++++++++++++ samples/subsys/llext/modules/prj.conf | 14 +++++ samples/subsys/llext/modules/sample.yaml | 35 +++++++++++ .../llext/modules/src/hello_world_ext.c | 27 ++++++++ .../subsys/llext/modules/src/main_builtin.c | 20 ++++++ .../subsys/llext/modules/src/main_module.c | 46 ++++++++++++++ 8 files changed, 262 insertions(+) create mode 100644 samples/subsys/llext/modules/CMakeLists.txt create mode 100644 samples/subsys/llext/modules/Kconfig create mode 100644 samples/subsys/llext/modules/README.rst create mode 100644 samples/subsys/llext/modules/prj.conf create mode 100644 samples/subsys/llext/modules/sample.yaml create mode 100644 samples/subsys/llext/modules/src/hello_world_ext.c create mode 100644 samples/subsys/llext/modules/src/main_builtin.c create mode 100644 samples/subsys/llext/modules/src/main_module.c diff --git a/samples/subsys/llext/modules/CMakeLists.txt b/samples/subsys/llext/modules/CMakeLists.txt new file mode 100644 index 0000000000000..9e5f0e427a511 --- /dev/null +++ b/samples/subsys/llext/modules/CMakeLists.txt @@ -0,0 +1,39 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) + +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(fs_shell) + +if(CONFIG_HELLO_WORLD_MODE STREQUAL "m") + + # Build the llext ... + + set(ext_name hello_world) + set(ext_src src/${ext_name}_ext.c) + set(ext_bin ${ZEPHYR_BINARY_DIR}/${ext_name}.llext) + set(ext_inc ${ZEPHYR_BINARY_DIR}/include/generated/${ext_name}_ext.inc) + add_llext_target(${ext_name}_ext + OUTPUT ${ext_bin} + SOURCES ${ext_src} + ) + generate_inc_file_for_target(app ${ext_bin} ${ext_inc}) + + # ...and the code for loading and running it + + target_sources(app PRIVATE + src/main_module.c + ) + +elseif(CONFIG_HELLO_WORLD_MODE STREQUAL "y") + + # Just build the two files together + + target_sources(app PRIVATE + src/main_builtin.c + src/hello_world_ext.c + ) + +else() + message(FATAL_ERROR "Please choose 'y' or 'm' for CONFIG_HELLO_WORLD_MODE") +endif() diff --git a/samples/subsys/llext/modules/Kconfig b/samples/subsys/llext/modules/Kconfig new file mode 100644 index 0000000000000..243d892e1fcad --- /dev/null +++ b/samples/subsys/llext/modules/Kconfig @@ -0,0 +1,18 @@ +# SPDX-License-Identifier: Apache-2.0 +# Copyright (c) 2024 Intel Corporation. + +mainmenu "LLEXT functionality test" + +source "Kconfig.zephyr" + +config HELLO_WORLD_MODE + tristate "Include the hello_world function" + default m + help + This enables building the hello_world function, implemented in + hello_world_ext.c, either as an llext module or as a built-in part of + Zephyr. + + If you select 'm', the hello_world function will be built as an llext + "module". If you select 'y', the hello_world function will be directly + linked in the Zephyr image. diff --git a/samples/subsys/llext/modules/README.rst b/samples/subsys/llext/modules/README.rst new file mode 100644 index 0000000000000..a825d1cc65cef --- /dev/null +++ b/samples/subsys/llext/modules/README.rst @@ -0,0 +1,63 @@ +.. zephyr:code-sample:: llext-modules + :name: Linkable loadable extensions "module" sample + :relevant-api: llext + + Call a function in a loadable extension module, + either built-in or loaded at runtime. + +Overview +******** + +This sample demonstrates the use of the :ref:`llext` subsystem in Zephyr. The +llext subsystem allows for the loading of relocatable ELF files at runtime; +their symbols can be accessed and functions called. + +Specifically, this shows how to call a simple "hello world" function, +implemented in :zephyr_file:`samples/subsys/llext/modules/src/hello_world_ext.c`. +This is achieved in two different ways, depending on the value of the Kconfig +symbol ``CONFIG_HELLO_WORLD_MODE``: + +- if it is ``y``, the function is directly compiled and called by the Zephyr + application. The caller code used in this case is in + :zephyr_file:`samples/subsys/llext/modules/src/main_builtin.c`. + +- if it is ``m``, the function is compiled as an llext and it is included in + the application as a binary blob. At runtime, the llext subsystem is used to + load the extension and call the function. The caller code is in + :zephyr_file:`samples/subsys/llext/modules/src/main_module.c`. + +Requirements +************ + +A board with a supported llext architecture and console. This can also be +executed in QEMU emulation on the :ref:`qemu_xtensa ` or +:ref:`qemu_cortex_r5 ` virtual boards. + +Building and running +******************** + +- The following commands build and run the sample so that the files are linked + together in the same binary: + + .. zephyr-app-commands:: + :zephyr-app: samples/subsys/llext/modules + :board: qemu_xtensa + :goals: build run + :west-args: -T sample.llext.modules.builtin_build + :compact: + +- The following commands build and run the sample so that the extension code is + compiled separately and included in the Zephyr image as a binary blob: + + .. zephyr-app-commands:: + :zephyr-app: samples/subsys/llext/modules + :board: qemu_xtensa + :goals: build run + :west-args: -T sample.llext.modules.module_build + :compact: + + Take a look at :zephyr_file:`samples/subsys/llext/modules/sample.yaml` for the + additional architecture-specific configurations required in this case. + +To build for a different board, replace ``qemu_xtensa`` in the commands above +with the desired board name. diff --git a/samples/subsys/llext/modules/prj.conf b/samples/subsys/llext/modules/prj.conf new file mode 100644 index 0000000000000..b097e9fdb23ca --- /dev/null +++ b/samples/subsys/llext/modules/prj.conf @@ -0,0 +1,14 @@ +CONFIG_LOG=y +CONFIG_LOG_MODE_IMMEDIATE=y + +CONFIG_MODULES=y + +# LLEXT is only required when loading the extension at runtime. Since in this +# basic example there's only one llext, leaving it in when building the +# extension as a built-in is redundant; in a real application, however, there +# could be other uses of the llext subsystem. + +CONFIG_LLEXT=y +CONFIG_LLEXT_LOG_LEVEL_DBG=y +CONFIG_LLEXT_HEAP_SIZE=64 +CONFIG_LLEXT_TYPE_ELF_RELOCATABLE=y diff --git a/samples/subsys/llext/modules/sample.yaml b/samples/subsys/llext/modules/sample.yaml new file mode 100644 index 0000000000000..cdb8aaff64c18 --- /dev/null +++ b/samples/subsys/llext/modules/sample.yaml @@ -0,0 +1,35 @@ +common: + tags: llext + arch_allow: + - arm + - xtensa + platform_exclude: + - apollo4p_evb # See #73443 + - apollo4p_blue_kxr_evb # See #73443 + - numaker_pfm_m487 # See #63167 + integration_platforms: + - qemu_xtensa + - qemu_cortex_r5 + - mps2/an385 + harness: console +sample: + name: CONFIG_MODULES test + description: Call code directly and from extensions +tests: + sample.llext.modules.module_build: + filter: not CONFIG_MPU and not CONFIG_MMU and not CONFIG_SOC_SERIES_S32ZE + extra_configs: + - CONFIG_HELLO_WORLD_MODE=m + - arch:arm:CONFIG_ARM_MPU=n + - arch:xtensa:CONFIG_LLEXT_STORAGE_WRITABLE=y + harness_config: + type: one_line + regex: + - "Hello, world, from an llext!" + sample.llext.modules.builtin_build: + extra_configs: + - CONFIG_HELLO_WORLD_MODE=y + harness_config: + type: one_line + regex: + - "Hello, world, from the main binary!" diff --git a/samples/subsys/llext/modules/src/hello_world_ext.c b/samples/subsys/llext/modules/src/hello_world_ext.c new file mode 100644 index 0000000000000..41220b027255e --- /dev/null +++ b/samples/subsys/llext/modules/src/hello_world_ext.c @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2023 Intel Corporation. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* + * This very simple hello world C code can be used as a test case for building + * probably the simplest loadable extension. It requires a single symbol be + * linked, section relocation support, and the ability to export and call out to + * a function. + */ + +#include +#include + +void hello_world(void) +{ +#if defined(CONFIG_HELLO_WORLD_MODE) + /* HELLO_WORLD_MODE=y: CONFIG_* is defined */ + printk("Hello, world, from the main binary!\n"); +#else + /* HELLO_WORLD_MODE=m: CONFIG_*_MODULE is defined instead */ + printk("Hello, world, from an llext!\n"); +#endif +} +LL_EXTENSION_SYMBOL(hello_world); diff --git a/samples/subsys/llext/modules/src/main_builtin.c b/samples/subsys/llext/modules/src/main_builtin.c new file mode 100644 index 0000000000000..e740c5b80e50c --- /dev/null +++ b/samples/subsys/llext/modules/src/main_builtin.c @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2024 Arduino SA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define LOG_LEVEL CONFIG_LOG_DEFAULT_LEVEL +#include +LOG_MODULE_REGISTER(app); + +extern void hello_world(void); + +int main(void) +{ + LOG_INF("Calling hello world as a builtin"); + + hello_world(); + + return 0; +} diff --git a/samples/subsys/llext/modules/src/main_module.c b/samples/subsys/llext/modules/src/main_module.c new file mode 100644 index 0000000000000..fd7f3dd5bf7f8 --- /dev/null +++ b/samples/subsys/llext/modules/src/main_module.c @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2024 Arduino SA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define LOG_LEVEL CONFIG_LOG_DEFAULT_LEVEL +#include +LOG_MODULE_REGISTER(app); + +#include +#include + +static uint8_t llext_buf[] = { +#include "hello_world_ext.inc" +}; + +int main(void) +{ + LOG_INF("Calling hello world as a module"); + + size_t llext_buf_len = ARRAY_SIZE(llext_buf); + struct llext_buf_loader buf_loader = LLEXT_BUF_LOADER(llext_buf, llext_buf_len); + struct llext_loader *ldr = &buf_loader.loader; + + struct llext_load_param ldr_parm = LLEXT_LOAD_PARAM_DEFAULT; + struct llext *ext; + int res; + + res = llext_load(ldr, "ext", &ext, &ldr_parm); + if (res != 0) { + LOG_ERR("Failed to load extension, return code %d\n", res); + return res; + } + + void (*hello_world_fn)() = llext_find_sym(&ext->exp_tab, "hello_world"); + + if (hello_world_fn == NULL) { + LOG_ERR("Failed to find symbol\n"); + return -1; + } + + hello_world_fn(); + + return llext_unload(&ext); +} From 6db484455d6719ce339ea307ff436076adfc1bab Mon Sep 17 00:00:00 2001 From: Luca Burelli Date: Tue, 11 Jun 2024 10:04:52 +0200 Subject: [PATCH 2781/2849] llext: remove the "modules_enabled" tests These tests are simple copies of the existing tests with the addition of the CONFIG_MODULES=y option. This different Kconfig setting has no practical effect on the code, and the tests are therefore redundant. Remove them to halve the number of tests. Signed-off-by: Luca Burelli --- tests/subsys/llext/simple/Kconfig | 12 ---- tests/subsys/llext/simple/testcase.yaml | 85 ++----------------------- 2 files changed, 5 insertions(+), 92 deletions(-) delete mode 100644 tests/subsys/llext/simple/Kconfig diff --git a/tests/subsys/llext/simple/Kconfig b/tests/subsys/llext/simple/Kconfig deleted file mode 100644 index 047e1a4502603..0000000000000 --- a/tests/subsys/llext/simple/Kconfig +++ /dev/null @@ -1,12 +0,0 @@ -# SPDX-License-Identifier: Apache-2.0 -# Copyright (c) 2024 Intel Corporation. - -mainmenu "LLEXT functionality test" - -source "Kconfig.zephyr" - -config LLEXT_TEST_HELLO - tristate "llext hello test" - default y - help - This enables building the hello_world test case. diff --git a/tests/subsys/llext/simple/testcase.yaml b/tests/subsys/llext/simple/testcase.yaml index 8a3aca97037d7..069d7e6f7feff 100644 --- a/tests/subsys/llext/simple/testcase.yaml +++ b/tests/subsys/llext/simple/testcase.yaml @@ -4,9 +4,9 @@ common: - arm - xtensa platform_exclude: - - apollo4p_evb - - apollo4p_blue_kxr_evb - - numaker_pfm_m487 # See #63167 + - apollo4p_evb # See #73443 + - apollo4p_blue_kxr_evb # See #73443 + - numaker_pfm_m487 # See #63167 tests: # While there is in practice no value in compiling subsys/llext/*.c @@ -36,50 +36,14 @@ tests: extra_configs: - arch:arm:CONFIG_ARM_MPU=n - CONFIG_LLEXT_STORAGE_WRITABLE=y - llext.simple.modules_enabled_writable: - filter: not CONFIG_MPU and not CONFIG_MMU - platform_key: - - simulation - - arch - platform_exclude: - - qemu_cortex_a9 # MMU - extra_configs: - - arch:arm:CONFIG_ARM_MPU=n - - CONFIG_MODULES=y - - CONFIG_LLEXT_STORAGE_WRITABLE=y - - CONFIG_LLEXT_TEST_HELLO=m - llext.simple.modules_enabled_writable_relocatable: + llext.simple.writable_relocatable: arch_exclude: arm arm64 filter: not CONFIG_MPU and not CONFIG_MMU integration_platforms: - qemu_xtensa extra_configs: - - CONFIG_MODULES=y - CONFIG_LLEXT_STORAGE_WRITABLE=y - CONFIG_LLEXT_TYPE_ELF_RELOCATABLE=y - - CONFIG_LLEXT_TEST_HELLO=m - llext.simple.modules_enabled_readonly: - filter: not CONFIG_MPU and not CONFIG_MMU - arch_exclude: xtensa # for now - platform_key: - - simulation - - arch - platform_exclude: - - qemu_cortex_a9 # MMU - extra_configs: - - arch:arm:CONFIG_ARM_MPU=n - - CONFIG_MODULES=y - - CONFIG_LLEXT_TEST_HELLO=m - llext.simple.modules_enabled_readonly_mpu: - filter: CONFIG_ARCH_HAS_USERSPACE - arch_exclude: xtensa # for now - platform_key: - - simulation - - arch - extra_configs: - - CONFIG_USERSPACE=y - - CONFIG_MODULES=y - - CONFIG_LLEXT_TEST_HELLO=m llext.simple.readonly_slid_linking: arch_exclude: xtensa # for now filter: not CONFIG_MPU and not CONFIG_MMU and not CONFIG_SOC_SERIES_S32ZE @@ -100,51 +64,12 @@ tests: extra_configs: - arch:arm:CONFIG_ARM_MPU=n - CONFIG_LLEXT_STORAGE_WRITABLE=y - llext.simple.modules_enabled_writable_slid_linking: - filter: not CONFIG_MPU and not CONFIG_MMU - platform_key: - - simulation - - arch - platform_exclude: - - qemu_cortex_a9 # MMU - extra_configs: - - arch:arm:CONFIG_ARM_MPU=n - - CONFIG_MODULES=y - - CONFIG_LLEXT_STORAGE_WRITABLE=y - - CONFIG_LLEXT_TEST_HELLO=m - - CONFIG_LLEXT_EXPORT_BUILTINS_BY_SLID=y - llext.simple.modules_enabled_writable_relocatable_slid_linking: + llext.simple.writable_relocatable_slid_linking: arch_exclude: arm arm64 filter: not CONFIG_MPU and not CONFIG_MMU integration_platforms: - qemu_xtensa extra_configs: - - CONFIG_MODULES=y - CONFIG_LLEXT_STORAGE_WRITABLE=y - CONFIG_LLEXT_TYPE_ELF_RELOCATABLE=y - - CONFIG_LLEXT_TEST_HELLO=m - - CONFIG_LLEXT_EXPORT_BUILTINS_BY_SLID=y - llext.simple.modules_enabled_readonly_slid_linking: - filter: not CONFIG_MPU and not CONFIG_MMU - arch_exclude: xtensa # for now - platform_key: - - simulation - - arch - platform_exclude: - - qemu_cortex_a9 # MMU - extra_configs: - - arch:arm:CONFIG_ARM_MPU=n - - CONFIG_MODULES=y - - CONFIG_LLEXT_TEST_HELLO=m - - CONFIG_LLEXT_EXPORT_BUILTINS_BY_SLID=y - llext.simple.modules_enabled_readonly_mpu_slid_linking: - filter: CONFIG_ARCH_HAS_USERSPACE - arch_exclude: xtensa # for now - platform_key: - - simulation - - arch - extra_configs: - - CONFIG_USERSPACE=y - - CONFIG_MODULES=y - - CONFIG_LLEXT_TEST_HELLO=m - CONFIG_LLEXT_EXPORT_BUILTINS_BY_SLID=y From fc377363e44ad32d0cc38ef81325f6228974e090 Mon Sep 17 00:00:00 2001 From: Rubin Gerritsen Date: Tue, 11 Jun 2024 14:32:24 +0200 Subject: [PATCH 2782/2849] cocinelle: Parse ztest test functions We want to able to use cocinelle on ztest functions as well when transforming APIs. Provide a simple macro so that test functions are recognized. Signed-off-by: Rubin Gerritsen --- scripts/coccinelle/macros.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/scripts/coccinelle/macros.h b/scripts/coccinelle/macros.h index 2cd5b75cf40c9..b13716689a45b 100644 --- a/scripts/coccinelle/macros.h +++ b/scripts/coccinelle/macros.h @@ -14,6 +14,8 @@ /* Zephyr macros */ +#define ZTEST(suite, fn) static void _##suite##_##fn##_wrapper(void) + /* Attributes */ /* Confirmed problematic */ From 470a0fcaa531e521ce1bd171d2c0864ca8d4f815 Mon Sep 17 00:00:00 2001 From: Rubin Gerritsen Date: Tue, 11 Jun 2024 14:36:17 +0200 Subject: [PATCH 2783/2849] cocinelle: Add a sematic patch file for ztest string assertions ztest now provides functionality to compare strings. These are simpler to use than the strcmp ways. The semantic patch transforms many of the commonly used patterns. It does not handle variable length macros. Signed-off-by: Rubin Gerritsen --- scripts/coccinelle/ztest_strcmp.cocci | 79 +++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 scripts/coccinelle/ztest_strcmp.cocci diff --git a/scripts/coccinelle/ztest_strcmp.cocci b/scripts/coccinelle/ztest_strcmp.cocci new file mode 100644 index 0000000000000..6448bb1ad3ce4 --- /dev/null +++ b/scripts/coccinelle/ztest_strcmp.cocci @@ -0,0 +1,79 @@ +/// Find cases where ztest string comparisons macros can be used +// Copyright: (C) 2024 Nordic Semiconductor ASA +// SPDX-License-Identifier: Apache-2.0 +// Confidence: LOW +// Options: --no-includes --include-headers + +virtual patch +virtual context +virtual org +virtual report + +// Comparing result of strcmp with 0 + +@@ expression E1,E2; @@ +- zassert_equal(strcmp(E1, E2), 0); ++ zassert_str_equal(E1, E2); + +@@ expression E1,E2,E3; @@ +- zassert_equal(strcmp(E1, E2), 0, E3); ++ zassert_str_equal(E1, E2, E3); + +@@ expression E1,E2; @@ +- zassert_equal(0, strcmp(E1, E2)); ++ zassert_str_equal(E1, E2); + +@@ expression E1,E2,E3; @@ +- zassert_equal(0, !strcmp(E1, E2), E3); ++ zassert_str_equal(E1, E2, E3); + + + +// Using assert_true with !strcmp + +@@ expression E1,E2; @@ +- zassert_true(!strcmp(E1, E2)); ++ zassert_str_equal(E1, E2); + +@@ expression E1,E2,E3; @@ +- zassert_true(!strcmp(E1, E2), E3); ++ zassert_str_equal(E1, E2, E3); + + +// using zassert_true with strcmp(E1, E2) == 0 + +@@expression E1,E2; @@ +- zassert_true(strcmp(E1, E2) == 0); ++ zassert_str_equal(E1, E2); + +@@expression E1,E2; @@ +- zassert_true((strcmp(E1, E2) == 0)); ++ zassert_str_equal(E1, E2); + +@@expression E1,E2,E3; @@ +- zassert_true(strcmp(E1, E2) == 0, E3); ++ zassert_str_equal(E1, E2, E3); + +@@expression E1,E2,E3; @@ +- zassert_true((strcmp(E1, E2) == 0), E3); ++ zassert_str_equal(E1, E2, E3); + + + +// using zassert_true with 0 == strcmp(E1, E2) + +@@expression E1,E2; @@ +- zassert_true(0 == strcmp(E1, E2)); ++ zassert_str_equal(E1, E2); + +@@expression E1,E2; @@ +- zassert_true((0 == strcmp(E1, E2))); ++ zassert_str_equal(E1, E2); + +@@expression E1,E2,E3; @@ +- zassert_true(0 == strcmp(E1, E2), E3); ++ zassert_str_equal(E1, E2, E3); + +@@expression E1,E2,E3; @@ +- zassert_true((0 == strcmp(E1, E2)), E3); ++ zassert_str_equal(E1, E2, E3); From 8799ab1ec2fa9b61f3f0d9e40fcc3c3c3ee059d8 Mon Sep 17 00:00:00 2001 From: Rubin Gerritsen Date: Tue, 11 Jun 2024 14:39:44 +0200 Subject: [PATCH 2784/2849] test: Apply semantic patch file ztest_strcmp.cocci This patch file updates the use of assertion macros comparing strings. Command line used: ``` ./scripts/coccicheck --mode=patch \ --cocci=scripts/coccinelle/ztest_strcmp.cocci tests/ ``` Signed-off-by: Rubin Gerritsen --- .../drivers/sensor/generic/src/dummy_sensor.c | 2 +- tests/kernel/common/src/printk.c | 4 +- .../thread_apis/src/test_kthread_for_each.c | 22 ++--- .../src/test_threads_suspend_resume.c | 8 +- tests/kernel/workq/work/src/main.c | 4 +- tests/lib/c_lib/common/src/main.c | 51 +++++------ tests/lib/cbprintf_package/src/main.c | 4 +- tests/lib/json/src/main.c | 87 ++++++++++--------- tests/lib/sprintf/src/main.c | 4 +- tests/modules/nanopb/src/main.c | 2 +- tests/net/conn_mgr_conn/src/main.c | 9 +- .../net/lib/http_server/prototype/src/main.c | 40 ++++----- .../lwm2m/lwm2m_registry/src/lwm2m_registry.c | 6 +- tests/subsys/debug/symtab/src/main.c | 23 ++--- tests/subsys/fs/common/test_fs_basic.c | 9 +- tests/subsys/fs/fs_api/src/test_fs_dir_file.c | 4 +- tests/subsys/fs/littlefs/src/test_util.c | 81 +++++------------ tests/subsys/logging/log_links/src/main.c | 4 +- .../logging/log_output/src/log_output_test.c | 20 ++--- .../log_timestamp/src/log_timestamp_test.c | 2 +- tests/subsys/mem_mgmt/mem_attr/src/main.c | 8 +- tests/subsys/modem/modem_chat/src/main.c | 23 +++-- tests/subsys/pm/device_driver_init/src/main.c | 12 ++- .../cmsis_rtos_v2/src/event_flags.c | 4 +- .../portability/cmsis_rtos_v2/src/kernel.c | 2 +- .../portability/cmsis_rtos_v2/src/mempool.c | 3 +- .../portability/cmsis_rtos_v2/src/mutex.c | 3 +- .../portability/cmsis_rtos_v2/src/semaphore.c | 4 +- .../cmsis_rtos_v2/src/thread_apis.c | 3 +- .../portability/cmsis_rtos_v2/src/timer.c | 3 +- .../fcb/src/settings_test_save_2_fcb.c | 3 +- tests/unit/cbprintf/main.c | 4 +- tests/unit/util/main.c | 37 ++++---- 33 files changed, 227 insertions(+), 268 deletions(-) diff --git a/tests/drivers/sensor/generic/src/dummy_sensor.c b/tests/drivers/sensor/generic/src/dummy_sensor.c index 556ad33c5de0f..a68c90973716f 100644 --- a/tests/drivers/sensor/generic/src/dummy_sensor.c +++ b/tests/drivers/sensor/generic/src/dummy_sensor.c @@ -80,7 +80,7 @@ static int dummy_sensor_init(const struct device *dev) const struct device *i2c = device_get_binding(config->i2c_name); /* Bus and address should be configured. */ - zassert_equal(strcmp(config->i2c_name, "dummy I2C"), 0); + zassert_str_equal(config->i2c_name, "dummy I2C"); zassert_equal(config->i2c_address, 123); if (i2c != NULL) { diff --git a/tests/kernel/common/src/printk.c b/tests/kernel/common/src/printk.c index 85a0ccbb4d35b..ee0dea94b37c2 100644 --- a/tests/kernel/common/src/printk.c +++ b/tests/kernel/common/src/printk.c @@ -220,7 +220,7 @@ ZTEST(printk, test_printk) pk_console[pos] = '\0'; __printk_hook_install(_old_char_out); printk("expected '%s'\n", expected); - zassert_true((strcmp(pk_console, expected) == 0), "printk failed"); + zassert_str_equal(pk_console, expected, "printk failed"); (void)memset(pk_console, 0, sizeof(pk_console)); count = 0; @@ -251,7 +251,7 @@ ZTEST(printk, test_printk) count += snprintk(pk_console + count, sizeof(pk_console) - count, "0x%x %p %-2p\n", hex, ptr, (char *)42); pk_console[count] = '\0'; - zassert_true((strcmp(pk_console, expected) == 0), "snprintk failed"); + zassert_str_equal(pk_console, expected, "snprintk failed"); } extern void *common_setup(void); diff --git a/tests/kernel/threads/thread_apis/src/test_kthread_for_each.c b/tests/kernel/threads/thread_apis/src/test_kthread_for_each.c index 654e2224d57ac..883b6831b742a 100644 --- a/tests/kernel/threads/thread_apis/src/test_kthread_for_each.c +++ b/tests/kernel/threads/thread_apis/src/test_kthread_for_each.c @@ -228,44 +228,44 @@ ZTEST(threads_lifecycle_1cpu, test_k_thread_state_str) tid->base.thread_state = 0; str = k_thread_state_str(tid, state_str, sizeof(state_str)); - zassert_true(strcmp(str, "") == 0); + zassert_str_equal(str, ""); tid->base.thread_state = _THREAD_DUMMY; str = k_thread_state_str(tid, NULL, sizeof(state_str)); - zassert_true(strcmp(str, "") == 0); + zassert_str_equal(str, ""); str = k_thread_state_str(tid, state_str, 0); - zassert_true(strcmp(str, "") == 0); + zassert_str_equal(str, ""); str = k_thread_state_str(tid, state_str, sizeof(state_str)); - zassert_true(strcmp(str, "dummy") == 0); + zassert_str_equal(str, "dummy"); tid->base.thread_state = _THREAD_PENDING; str = k_thread_state_str(tid, state_str, sizeof(state_str)); - zassert_true(strcmp(str, "pending") == 0); + zassert_str_equal(str, "pending"); tid->base.thread_state = _THREAD_PRESTART; str = k_thread_state_str(tid, state_str, sizeof(state_str)); - zassert_true(strcmp(str, "prestart") == 0); + zassert_str_equal(str, "prestart"); tid->base.thread_state = _THREAD_DEAD; str = k_thread_state_str(tid, state_str, sizeof(state_str)); - zassert_true(strcmp(str, "dead") == 0); + zassert_str_equal(str, "dead"); tid->base.thread_state = _THREAD_SUSPENDED; str = k_thread_state_str(tid, state_str, sizeof(state_str)); - zassert_true(strcmp(str, "suspended") == 0); + zassert_str_equal(str, "suspended"); tid->base.thread_state = _THREAD_ABORTING; str = k_thread_state_str(tid, state_str, sizeof(state_str)); - zassert_true(strcmp(str, "aborting") == 0); + zassert_str_equal(str, "aborting"); tid->base.thread_state = _THREAD_QUEUED; str = k_thread_state_str(tid, state_str, sizeof(state_str)); - zassert_true(strcmp(str, "queued") == 0); + zassert_str_equal(str, "queued"); tid->base.thread_state = _THREAD_PENDING | _THREAD_SUSPENDED; str = k_thread_state_str(tid, state_str, sizeof(state_str)); - zassert_true(strcmp(str, "pending+suspended") == 0); + zassert_str_equal(str, "pending+suspended"); } diff --git a/tests/kernel/threads/thread_apis/src/test_threads_suspend_resume.c b/tests/kernel/threads/thread_apis/src/test_threads_suspend_resume.c index 378f82fb7b0dc..bc23b5f677416 100644 --- a/tests/kernel/threads/thread_apis/src/test_threads_suspend_resume.c +++ b/tests/kernel/threads/thread_apis/src/test_threads_suspend_resume.c @@ -165,19 +165,19 @@ ZTEST(threads_lifecycle, test_resume_unsuspend_thread) /* Resume an unsuspend thread will not change the thread state. */ str = k_thread_state_str(tid, buffer, sizeof(buffer)); - zassert_true(strcmp(str, "queued") == 0); + zassert_str_equal(str, "queued"); k_thread_resume(tid); str = k_thread_state_str(tid, buffer, sizeof(buffer)); - zassert_true(strcmp(str, "queued") == 0); + zassert_str_equal(str, "queued"); /* suspend created thread */ k_thread_suspend(tid); str = k_thread_state_str(tid, buffer, sizeof(buffer)); - zassert_true(strcmp(str, "suspended") == 0); + zassert_str_equal(str, "suspended"); /* Resume an suspend thread will make it to be next eligible.*/ k_thread_resume(tid); str = k_thread_state_str(tid, buffer, sizeof(buffer)); - zassert_true(strcmp(str, "queued") == 0); + zassert_str_equal(str, "queued"); k_thread_abort(tid); } diff --git a/tests/kernel/workq/work/src/main.c b/tests/kernel/workq/work/src/main.c index 808c83cb17feb..7776db2a7d5a6 100644 --- a/tests/kernel/workq/work/src/main.c +++ b/tests/kernel/workq/work/src/main.c @@ -237,7 +237,7 @@ static void test_queue_start(void) zassert_true(tn != cfg.name); zassert_true(tn != NULL); - zassert_equal(strcmp(tn, cfg.name), 0); + zassert_str_equal(tn, cfg.name); } cfg.name = NULL; @@ -251,7 +251,7 @@ static void test_queue_start(void) zassert_true(tn != cfg.name); zassert_true(tn != NULL); - zassert_equal(strcmp(tn, ""), 0); + zassert_str_equal(tn, ""); } cfg.name = "wq.coophi"; diff --git a/tests/lib/c_lib/common/src/main.c b/tests/lib/c_lib/common/src/main.c index 716e2e0fd9b03..4380b2cde8f96 100644 --- a/tests/lib/c_lib/common/src/main.c +++ b/tests/lib/c_lib/common/src/main.c @@ -230,7 +230,7 @@ ZTEST(libc_common, test_strcmp) char test = 0; zassert_true((strcmp(buffer, "fffff") < 0), "strcmp less ..."); - zassert_true((strcmp(buffer, "eeeee") == 0), "strcmp equal ..."); + zassert_str_equal(buffer, "eeeee", "strcmp equal ..."); zassert_true((strcmp(buffer, "ddddd") > 0), "strcmp greater ..."); zassert_true((strncasecmp(buffer, "FFFFF", 3) < 0), "strncasecmp less ..."); @@ -277,7 +277,7 @@ ZTEST(libc_common, test_strcpy) (void)memset(buffer, '\0', BUFSIZE); strcpy(buffer, "10 chars!\0"); - zassert_true((strcmp(buffer, "10 chars!\0") == 0), "strcpy"); + zassert_str_equal(buffer, "10 chars!\0", "strcpy"); } /** @@ -467,7 +467,7 @@ ZTEST(libc_common, test_checktype) } } *ptr = '\0'; - zassert_equal(strcmp(buf, exp_alnum), 0, "isalnum error"); + zassert_str_equal(buf, exp_alnum, "isalnum error"); ptr = buf; for (int i = 0; i < 128; i++) { @@ -476,7 +476,7 @@ ZTEST(libc_common, test_checktype) } } *ptr = '\0'; - zassert_equal(strcmp(buf, exp_alpha), 0, "isalpha error"); + zassert_str_equal(buf, exp_alpha, "isalpha error"); ptr = buf; for (int i = 0; i < 128; i++) { @@ -485,7 +485,7 @@ ZTEST(libc_common, test_checktype) } } *ptr = '\0'; - zassert_equal(strcmp(buf, exp_digit), 0, "isdigit error"); + zassert_str_equal(buf, exp_digit, "isdigit error"); ptr = buf; for (int i = 0; i < 128; i++) { @@ -494,7 +494,7 @@ ZTEST(libc_common, test_checktype) } } *ptr = '\0'; - zassert_equal(strcmp(buf, exp_graph), 0, "isgraph error"); + zassert_str_equal(buf, exp_graph, "isgraph error"); ptr = buf; for (int i = 0; i < 128; i++) { @@ -503,7 +503,7 @@ ZTEST(libc_common, test_checktype) } } *ptr = '\0'; - zassert_equal(strcmp(buf, exp_print), 0, "isprint error"); + zassert_str_equal(buf, exp_print, "isprint error"); ptr = buf; for (int i = 0; i < 128; i++) { @@ -512,7 +512,7 @@ ZTEST(libc_common, test_checktype) } } *ptr = '\0'; - zassert_equal(strcmp(buf, exp_upper), 0, "isupper error"); + zassert_str_equal(buf, exp_upper, "isupper error"); ptr = buf; for (int i = 0; i < 128; i++) { @@ -521,7 +521,7 @@ ZTEST(libc_common, test_checktype) } } *ptr = '\0'; - zassert_equal(strcmp(buf, exp_space), 0, "isspace error"); + zassert_str_equal(buf, exp_space, "isspace error"); ptr = buf; for (int i = 0; i < 128; i++) { @@ -530,7 +530,7 @@ ZTEST(libc_common, test_checktype) } } *ptr = '\0'; - zassert_equal(strcmp(buf, exp_xdigit), 0, "isxdigit error"); + zassert_str_equal(buf, exp_xdigit, "isxdigit error"); } /** @@ -642,7 +642,7 @@ ZTEST(libc_common, test_str_operate) char *ptr; zassert_not_null(strcat(str1, str3), "strcat false"); - zassert_equal(strcmp(str1, "aabbccd"), 0, "test strcat failed"); + zassert_str_equal(str1, "aabbccd", "test strcat failed"); ret = strcspn(str1, str2); zassert_equal(ret, 2, "strcspn failed"); @@ -659,12 +659,12 @@ ZTEST(libc_common, test_str_operate) #if defined(__GNUC__) && __GNUC__ >= 7 #pragma GCC diagnostic pop #endif - zassert_equal(strcmp(ncat, "ddeeaa"), 0, "strncat failed"); + zassert_str_equal(ncat, "ddeeaa", "strncat failed"); zassert_is_null(strrchr(ncat, 'z'), "strrchr not found this word. failed"); ptr = strrchr(ncat, 'e'); - zassert_equal(strcmp(ptr, "eaa"), 0, "strrchr failed"); + zassert_str_equal(ptr, "eaa", "strrchr failed"); zassert_is_null(strstr(str1, "ayz"), "strstr aabbccd with ayz failed"); zassert_not_null(strstr(str1, str2), "strstr aabbccd with b succeed"); @@ -728,13 +728,11 @@ ZTEST(libc_common, test_strtol) ret = strtol(str_normal, &stop, 10); zassert_equal(ret, -1011, "strtol base = 10 failed"); - zassert_true((strcmp(stop, " This stopped it") == 0), - "strtol get stop failed"); + zassert_str_equal(stop, " This stopped it", "strtol get stop failed"); ret = strtol(str_abnormal, &stop, 0); zassert_equal(ret, 0, "strtol base = 0 failed"); - zassert_true((strcmp(stop, "ABCDEFGH") == 0), - "strtol get stop failed"); + zassert_str_equal(stop, "ABCDEFGH", "strtol get stop failed"); #if LONG_MAX > 2147483647 char border1[] = "-9223372036854775809"; @@ -817,13 +815,11 @@ ZTEST(libc_common, test_strtoul) ret = strtoul(str_normal, &stop, 10); zassert_equal(ret, -1011, "strtol base = 10 failed"); - zassert_true((strcmp(stop, " This stopped it") == 0), - "strtol get stop failed"); + zassert_str_equal(stop, " This stopped it", "strtol get stop failed"); ret = strtoul(str_abnormal, &stop, 0); zassert_equal(ret, 0, "strtol base = 0 failed"); - zassert_true((strcmp(stop, "ABCDEFGH") == 0), - "strtol get stop failed"); + zassert_str_equal(stop, "ABCDEFGH", "strtol get stop failed"); #if LONG_MAX > 2147483647 char border1[] = "18446744073709551615"; @@ -901,11 +897,11 @@ void test_strtoll(void) ret = strtoll(str_normal, &stop, 10); zassert_equal(ret, -1011, "strtoll base = 10 failed"); - zassert_true((strcmp(stop, " This stopped it") == 0), "strtoll get stop failed"); + zassert_str_equal(stop, " This stopped it", "strtoll get stop failed"); ret = strtoll(str_abnormal, &stop, 0); zassert_equal(ret, 0, "strtoll base = 0 failed"); - zassert_true((strcmp(stop, "ABCDEFGH") == 0), "strtoll get stop failed"); + zassert_str_equal(stop, "ABCDEFGH", "strtoll get stop failed"); char border1[] = "-9223372036854775808"; char border2[] = "+9223372036854775807"; @@ -981,11 +977,12 @@ void test_strtoull(void) ret = strtoull(str_normal, &stop, 10); zassert_equal(ret, -1011, "strtoull base = 10 failed"); - zassert_true((strcmp(stop, " This stopped it") == 0), "strtoull get stop failed"); + zassert_str_equal(stop, " This stopped it", + "strtoull get stop failed"); ret = strtoull(str_abnormal, &stop, 0); zassert_equal(ret, 0, "strtoull base = 0 failed"); - zassert_true((strcmp(stop, "ABCDEFGH") == 0), "strtoull get stop failed"); + zassert_str_equal(stop, "ABCDEFGH", "strtoull get stop failed"); char border1[] = "+18446744073709551615"; char border2[] = "-18446744073709551615000"; @@ -1028,8 +1025,8 @@ ZTEST(libc_common, test_tolower_toupper) } lw[i] = up[i] = '\0'; - zassert_equal(strcmp(up, toup), 0, "toupper error"); - zassert_equal(strcmp(lw, tolw), 0, "tolower error"); + zassert_str_equal(up, toup, "toupper error"); + zassert_str_equal(lw, tolw, "tolower error"); } void test_strtok_r_do(char *str, char *sep, int tlen, diff --git a/tests/lib/cbprintf_package/src/main.c b/tests/lib/cbprintf_package/src/main.c index 7451d8012b801..b29d976408f96 100644 --- a/tests/lib/cbprintf_package/src/main.c +++ b/tests/lib/cbprintf_package/src/main.c @@ -289,11 +289,11 @@ ZTEST(cbprintf_package, test_cbprintf_fsc_package) /* Get pointer to the first string in the package. */ addr = (char *)&fsc_package[desc->desc.len * sizeof(int) + 1]; - zassert_equal(strcmp(test_str, addr), 0); + zassert_str_equal(test_str, addr); /* Get address of the second string. */ addr += strlen(addr) + 2; - zassert_equal(strcmp(test_str1, addr), 0); + zassert_str_equal(test_str1, addr); } static void check_package(void *package, size_t len, const char *exp_str) diff --git a/tests/lib/json/src/main.c b/tests/lib/json/src/main.c index 6c9c76772f855..095952351d3ca 100644 --- a/tests/lib/json/src/main.c +++ b/tests/lib/json/src/main.c @@ -255,17 +255,17 @@ ZTEST(lib_json_test, test_json_decoding) zassert_equal(ret, (1 << ARRAY_SIZE(test_descr)) - 1, "Not all fields decoded correctly"); - zassert_true(!strcmp(ts.some_string, "zephyr 123\\uABCD456"), - "String not decoded correctly"); + zassert_str_equal(ts.some_string, "zephyr 123\\uABCD456", + "String not decoded correctly"); zassert_equal(ts.some_int, 42, "Positive integer not decoded correctly"); zassert_equal(ts.some_bool, true, "Boolean not decoded correctly"); zassert_equal(ts.some_nested_struct.nested_int, -1234, "Nested negative integer not decoded correctly"); zassert_equal(ts.some_nested_struct.nested_bool, false, "Nested boolean value not decoded correctly"); - zassert_true(!strcmp(ts.some_nested_struct.nested_string, - "this should be escaped: \\t"), - "Nested string not decoded correctly"); + zassert_str_equal(ts.some_nested_struct.nested_string, + "this should be escaped: \\t", + "Nested string not decoded correctly"); zassert_equal(ts.some_array_len, 5, "Array doesn't have correct number of items"); zassert_true(!memcmp(ts.some_array, expected_array, @@ -284,23 +284,23 @@ ZTEST(lib_json_test, test_json_decoding) "Named nested integer not decoded correctly"); zassert_equal(ts.xnother_nexx.nested_bool, true, "Named nested boolean not decoded correctly"); - zassert_true(!strcmp(ts.xnother_nexx.nested_string, - "no escape necessary"), - "Named nested string not decoded correctly"); + zassert_str_equal(ts.xnother_nexx.nested_string, + "no escape necessary", + "Named nested string not decoded correctly"); zassert_equal(ts.obj_array_len, 2, "Array of objects does not have correct number of items"); zassert_equal(ts.nested_obj_array[0].nested_int, 1, "Integer in first object array element not decoded correctly"); zassert_equal(ts.nested_obj_array[0].nested_bool, true, "Boolean value in first object array element not decoded correctly"); - zassert_true(!strcmp(ts.nested_obj_array[0].nested_string, "true"), - "String in first object array element not decoded correctly"); + zassert_str_equal(ts.nested_obj_array[0].nested_string, "true", + "String in first object array element not decoded correctly"); zassert_equal(ts.nested_obj_array[1].nested_int, 0, "Integer in second object array element not decoded correctly"); zassert_equal(ts.nested_obj_array[1].nested_bool, false, "Boolean value in second object array element not decoded correctly"); - zassert_true(!strcmp(ts.nested_obj_array[1].nested_string, "false"), - "String in second object array element not decoded correctly"); + zassert_str_equal(ts.nested_obj_array[1].nested_string, "false", + "String in second object array element not decoded correctly"); } ZTEST(lib_json_test, test_json_limits) @@ -325,7 +325,8 @@ ZTEST(lib_json_test, test_json_limits) ret = json_obj_parse(encoded, sizeof(encoded) - 1, obj_limits_descr, ARRAY_SIZE(obj_limits_descr), &limits_decoded); - zassert_true(!strcmp(encoded, buffer), "Integer limits not encoded correctly"); + zassert_str_equal(encoded, buffer, + "Integer limits not encoded correctly"); zassert_true(!memcmp(&limits, &limits_decoded, sizeof(limits)), "Integer limits not decoded correctly"); } @@ -351,8 +352,8 @@ ZTEST(lib_json_test, test_json_encoding_array_array) ret = json_obj_encode_buf(array_array_descr, ARRAY_SIZE(array_array_descr), &obj_array_array_ts, buffer, sizeof(buffer)); zassert_equal(ret, 0, "Encoding array returned error"); - zassert_true(!strcmp(buffer, encoded), - "Encoded array of objects is not consistent"); + zassert_str_equal(buffer, encoded, + "Encoded array of objects is not consistent"); } ZTEST(lib_json_test, test_json_decoding_array_array) @@ -374,18 +375,19 @@ ZTEST(lib_json_test, test_json_decoding_array_array) zassert_equal(obj_array_array_ts.objects_array_len, 3, "Array doesn't have correct number of items"); - zassert_true(!strcmp(obj_array_array_ts.objects_array[0].objects.name, - "Sim\303\263n Bol\303\255var"), "String not decoded correctly"); + zassert_str_equal(obj_array_array_ts.objects_array[0].objects.name, + "Sim\303\263n Bol\303\255var", + "String not decoded correctly"); zassert_equal(obj_array_array_ts.objects_array[0].objects.height, 168, "Sim\303\263n Bol\303\255var height not decoded correctly"); - zassert_true(!strcmp(obj_array_array_ts.objects_array[1].objects.name, - "Pel\303\251"), "String not decoded correctly"); + zassert_str_equal(obj_array_array_ts.objects_array[1].objects.name, + "Pel\303\251", "String not decoded correctly"); zassert_equal(obj_array_array_ts.objects_array[1].objects.height, 173, "Pel\303\251 height not decoded correctly"); - zassert_true(!strcmp(obj_array_array_ts.objects_array[2].objects.name, - "Usain Bolt"), "String not decoded correctly"); + zassert_str_equal(obj_array_array_ts.objects_array[2].objects.name, + "Usain Bolt", "String not decoded correctly"); zassert_equal(obj_array_array_ts.objects_array[2].objects.height, 195, "Usain Bolt height not decoded correctly"); } @@ -425,8 +427,8 @@ ZTEST(lib_json_test, test_json_obj_arr_encoding) ret = json_obj_encode_buf(obj_array_descr, ARRAY_SIZE(obj_array_descr), &oa, buffer, sizeof(buffer)); zassert_equal(ret, 0, "Encoding array of object returned error"); - zassert_true(!strcmp(buffer, encoded), - "Encoded array of objects is not consistent"); + zassert_str_equal(buffer, encoded, + "Encoded array of objects is not consistent"); } ZTEST(lib_json_test, test_json_arr_obj_decoding) @@ -446,18 +448,19 @@ ZTEST(lib_json_test, test_json_arr_obj_decoding) zassert_equal(obj_array_array_ts.num_elements, 3, "Array doesn't have correct number of items"); - zassert_true(!strcmp(obj_array_array_ts.elements[0].name, - "Sim\303\263n Bol\303\255var"), "String not decoded correctly"); + zassert_str_equal(obj_array_array_ts.elements[0].name, + "Sim\303\263n Bol\303\255var", + "String not decoded correctly"); zassert_equal(obj_array_array_ts.elements[0].height, 168, "Sim\303\263n Bol\303\255var height not decoded correctly"); - zassert_true(!strcmp(obj_array_array_ts.elements[1].name, - "Pel\303\251"), "String not decoded correctly"); + zassert_str_equal(obj_array_array_ts.elements[1].name, "Pel\303\251", + "String not decoded correctly"); zassert_equal(obj_array_array_ts.elements[1].height, 173, "Pel\303\251 height not decoded correctly"); - zassert_true(!strcmp(obj_array_array_ts.elements[2].name, - "Usain Bolt"), "String not decoded correctly"); + zassert_str_equal(obj_array_array_ts.elements[2].name, "Usain Bolt", + "String not decoded correctly"); zassert_equal(obj_array_array_ts.elements[2].height, 195, "Usain Bolt height not decoded correctly"); } @@ -500,8 +503,8 @@ ZTEST(lib_json_test, test_json_arr_obj_encoding) ret = json_arr_encode_buf(obj_array_descr, &oa, buffer, sizeof(buffer)); zassert_equal(ret, 0, "Encoding array of object returned error %d", ret); - zassert_true(!strcmp(buffer, encoded), - "Encoded array of objects is not consistent"); + zassert_str_equal(buffer, encoded, + "Encoded array of objects is not consistent"); } ZTEST(lib_json_test, test_json_obj_arr_decoding) @@ -629,8 +632,8 @@ ZTEST(lib_json_test, test_json_2dim_arr_obj_encoding) ret = json_obj_encode_buf(array_2dim_descr, ARRAY_SIZE(array_2dim_descr), &obj_array_array_ts, buffer, sizeof(buffer)); zassert_equal(ret, 0, "Encoding two-dimensional array returned error"); - zassert_true(!strcmp(buffer, encoded), - "Encoded two-dimensional array is not consistent"); + zassert_str_equal(buffer, encoded, + "Encoded two-dimensional array is not consistent"); } ZTEST(lib_json_test, test_json_2dim_arr_extra_obj_encoding) @@ -712,8 +715,8 @@ ZTEST(lib_json_test, test_json_2dim_arr_extra_obj_encoding) ret = json_obj_encode_buf(array_2dim_extra_descr, ARRAY_SIZE(array_2dim_extra_descr), &obj_array_2dim_extra_ts, buffer, sizeof(buffer)); zassert_equal(ret, 0, "Encoding two-dimensional extra array returned error"); - zassert_true(!strcmp(buffer, encoded), - "Encoded two-dimensional extra array is not consistent"); + zassert_str_equal(buffer, encoded, + "Encoded two-dimensional extra array is not consistent"); } ZTEST(lib_json_test, test_json_2dim_arr_extra_named_obj_encoding) @@ -796,8 +799,8 @@ ZTEST(lib_json_test, test_json_2dim_arr_extra_named_obj_encoding) ARRAY_SIZE(array_2dim_extra_named_descr), &obj_array_2dim_extra_ts, buffer, sizeof(buffer)); zassert_equal(ret, 0, "Encoding two-dimensional extra named array returned error"); - zassert_true(!strcmp(buffer, encoded), - "Encoded two-dimensional extra named array is not consistent"); + zassert_str_equal(buffer, encoded, + "Encoded two-dimensional extra named array is not consistent"); } ZTEST(lib_json_test, test_json_2dim_obj_arr_decoding) @@ -1033,8 +1036,7 @@ ZTEST(lib_json_test, test_json_escape) zassert_equal(ret, 0, "Escape did not succeed"); zassert_equal(len, sizeof(buf) - 1, "Escaped length not computed correctly"); - zassert_true(!strcmp(buf, expected), - "Escaped value is not correct"); + zassert_str_equal(buf, expected, "Escaped value is not correct"); } /* Edge case: only one character, which must be escaped. */ @@ -1050,8 +1052,7 @@ ZTEST(lib_json_test, test_json_escape_one) "Escaping one character did not succeed"); zassert_equal(len, sizeof(buf) - 1, "Escaping one character length is not correct"); - zassert_true(!strcmp(buf, expected), - "Escaped value is not correct"); + zassert_str_equal(buf, expected, "Escaped value is not correct"); } ZTEST(lib_json_test, test_json_escape_empty) @@ -1077,8 +1078,8 @@ ZTEST(lib_json_test, test_json_escape_no_op) zassert_equal(ret, 0, "Escape no-op not handled correctly"); zassert_equal(len, sizeof(nothing_to_escape) - 1, "Changed length of already escaped string"); - zassert_true(!strcmp(nothing_to_escape, expected), - "Altered string with nothing to escape"); + zassert_str_equal(nothing_to_escape, expected, + "Altered string with nothing to escape"); } ZTEST(lib_json_test, test_json_escape_bounds_check) diff --git a/tests/lib/sprintf/src/main.c b/tests/lib/sprintf/src/main.c index af22d97fadd8c..8395be690ffb7 100644 --- a/tests/lib/sprintf/src/main.c +++ b/tests/lib/sprintf/src/main.c @@ -754,8 +754,8 @@ ZTEST(sprintf, test_sprintf_string) "Expected 'short string', got '%s'\n", buffer); sprintf(buffer, "%s", REALLY_LONG_STRING); - zassert_true((strcmp(buffer, REALLY_LONG_STRING) == 0), - "sprintf(%%s) of REALLY_LONG_STRING doesn't match!\n"); + zassert_str_equal(buffer, REALLY_LONG_STRING, + "sprintf(%%s) of REALLY_LONG_STRING doesn't match!\n"); } diff --git a/tests/modules/nanopb/src/main.c b/tests/modules/nanopb/src/main.c index 798b11e6f1689..74c775f260fa8 100644 --- a/tests/modules/nanopb/src/main.c +++ b/tests/modules/nanopb/src/main.c @@ -67,7 +67,7 @@ ZTEST(nanopb_tests, test_nanopb_nested) zassert_equal(42, msg.nested.id); zassert_true(msg.has_nested); - zassert_equal(0, strcmp(msg.nested.name, "Test name")); + zassert_str_equal(msg.nested.name, "Test name"); } ZTEST(nanopb_tests, test_nanopb_lib) diff --git a/tests/net/conn_mgr_conn/src/main.c b/tests/net/conn_mgr_conn/src/main.c index 79f19ee9712ae..b66e246b12de8 100644 --- a/tests/net/conn_mgr_conn/src/main.c +++ b/tests/net/conn_mgr_conn/src/main.c @@ -639,7 +639,8 @@ ZTEST(conn_mgr_conn, test_conn_opt) 0, "conn_mgr_if_get_opt should succeed for valid parameters"); printk("%d, %d", buf_len, strlen(buf) + 1); zassert_equal(buf_len, strlen(buf) + 1, "conn_mgr_if_get_opt should return valid optlen"); - zassert_equal(strcmp(buf, "A"), 0, "conn_mgr_if_get_opt should retrieve \"A\""); + zassert_str_equal(buf, "A", + "conn_mgr_if_get_opt should retrieve \"A\""); /* Verify that ifa1->Y was not affected */ memset(buf, 0, sizeof(buf)); @@ -668,7 +669,8 @@ ZTEST(conn_mgr_conn, test_conn_opt) zassert_equal(conn_mgr_if_get_opt(ifa1, TEST_CONN_OPT_Y, &buf, &buf_len), 0, "conn_mgr_if_get_opt should succeed for valid parameters"); zassert_equal(buf_len, strlen(buf) + 1, "conn_mgr_if_get_opt should return valid optlen"); - zassert_equal(strcmp(buf, "ABC"), 0, "conn_mgr_if_get_opt should retrieve \"ABC\""); + zassert_str_equal(buf, "ABC", + "conn_mgr_if_get_opt should retrieve \"ABC\""); /* Verify that ifa1->X was not affected */ memset(buf, 0, sizeof(buf)); @@ -676,7 +678,8 @@ ZTEST(conn_mgr_conn, test_conn_opt) zassert_equal(conn_mgr_if_get_opt(ifa1, TEST_CONN_OPT_X, &buf, &buf_len), 0, "conn_mgr_if_get_opt should succeed for valid parameters"); zassert_equal(buf_len, strlen(buf) + 1, "conn_mgr_if_get_opt should return valid optlen"); - zassert_equal(strcmp(buf, "A"), 0, "conn_mgr_if_get_opt should retrieve \"A\""); + zassert_str_equal(buf, "A", + "conn_mgr_if_get_opt should retrieve \"A\""); /* Next, we pass some buffers that are too large or too small. * This is an indirect way of verifying that buf_len is passed correctly. diff --git a/tests/net/lib/http_server/prototype/src/main.c b/tests/net/lib/http_server/prototype/src/main.c index 99db7f81f7c52..0e6b4171a3555 100644 --- a/tests/net/lib/http_server/prototype/src/main.c +++ b/tests/net/lib/http_server/prototype/src/main.c @@ -319,26 +319,26 @@ ZTEST(server_function_tests, test_http_server_start_stop) ZTEST(server_function_tests, test_get_frame_type_name) { - zassert_equal(strcmp(get_frame_type_name(HTTP_SERVER_DATA_FRAME), "DATA"), 0, - "Unexpected frame type"); - zassert_equal(strcmp(get_frame_type_name(HTTP_SERVER_HEADERS_FRAME), "HEADERS"), 0, - "Unexpected frame type"); - zassert_equal(strcmp(get_frame_type_name(HTTP_SERVER_PRIORITY_FRAME), "PRIORITY"), 0, - "Unexpected frame type"); - zassert_equal(strcmp(get_frame_type_name(HTTP_SERVER_RST_STREAM_FRAME), "RST_STREAM"), 0, - "Unexpected frame type"); - zassert_equal(strcmp(get_frame_type_name(HTTP_SERVER_SETTINGS_FRAME), "SETTINGS"), 0, - "Unexpected frame type"); - zassert_equal(strcmp(get_frame_type_name(HTTP_SERVER_PUSH_PROMISE_FRAME), "PUSH_PROMISE"), - 0, "Unexpected frame type"); - zassert_equal(strcmp(get_frame_type_name(HTTP_SERVER_PING_FRAME), "PING"), 0, - "Unexpected frame type"); - zassert_equal(strcmp(get_frame_type_name(HTTP_SERVER_GOAWAY_FRAME), "GOAWAY"), 0, - "Unexpected frame type"); - zassert_equal(strcmp(get_frame_type_name(HTTP_SERVER_WINDOW_UPDATE_FRAME), "WINDOW_UPDATE"), - 0, "Unexpected frame type"); - zassert_equal(strcmp(get_frame_type_name(HTTP_SERVER_CONTINUATION_FRAME), "CONTINUATION"), - 0, "Unexpected frame type"); + zassert_str_equal(get_frame_type_name(HTTP_SERVER_DATA_FRAME), "DATA", + "Unexpected frame type"); + zassert_str_equal(get_frame_type_name(HTTP_SERVER_HEADERS_FRAME), + "HEADERS", "Unexpected frame type"); + zassert_str_equal(get_frame_type_name(HTTP_SERVER_PRIORITY_FRAME), + "PRIORITY", "Unexpected frame type"); + zassert_str_equal(get_frame_type_name(HTTP_SERVER_RST_STREAM_FRAME), + "RST_STREAM", "Unexpected frame type"); + zassert_str_equal(get_frame_type_name(HTTP_SERVER_SETTINGS_FRAME), + "SETTINGS", "Unexpected frame type"); + zassert_str_equal(get_frame_type_name(HTTP_SERVER_PUSH_PROMISE_FRAME), + "PUSH_PROMISE", "Unexpected frame type"); + zassert_str_equal(get_frame_type_name(HTTP_SERVER_PING_FRAME), "PING", + "Unexpected frame type"); + zassert_str_equal(get_frame_type_name(HTTP_SERVER_GOAWAY_FRAME), + "GOAWAY", "Unexpected frame type"); + zassert_str_equal(get_frame_type_name(HTTP_SERVER_WINDOW_UPDATE_FRAME), + "WINDOW_UPDATE", "Unexpected frame type"); + zassert_str_equal(get_frame_type_name(HTTP_SERVER_CONTINUATION_FRAME), + "CONTINUATION", "Unexpected frame type"); } ZTEST(server_function_tests, test_parse_http_frames) 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 b6178abb17f1d..d5b0c1190a829 100644 --- a/tests/net/lib/lwm2m/lwm2m_registry/src/lwm2m_registry.c +++ b/tests/net/lib/lwm2m/lwm2m_registry/src/lwm2m_registry.c @@ -181,7 +181,7 @@ ZTEST(lwm2m_registry, test_get_set) zassert_equal(b, true); zassert_equal(memcmp(opaque, &(uint8_t[6]) {0xde, 0xad, 0xbe, 0xff, 0, 0}, l), 0); - zassert_equal(strcmp(string, "Hello"), 0); + zassert_str_equal(string, "Hello"); zassert_equal(u8, 8); zassert_equal(s8, -8); zassert_equal(u16, 16); @@ -465,7 +465,7 @@ ZTEST(lwm2m_registry, test_deprecated_functions) zassert_equal(b, true); zassert_equal(memcmp(opaque, &(uint8_t[6]) {0xde, 0xad, 0xbe, 0xff, 0, 0}, l), 0); - zassert_equal(strcmp(string, "Hello"), 0); + zassert_str_equal(string, "Hello"); zassert_equal(u8, 8); zassert_equal(s8, -8); zassert_equal(u16, 16); @@ -681,7 +681,7 @@ ZTEST(lwm2m_registry, test_set_bulk) zassert_equal(b, true); zassert_equal(memcmp(opaque, &(uint8_t[6]) {0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff}, sizeof(opaque)), 0); - zassert_equal(strcmp(string, "Hello world"), 0); + zassert_str_equal(string, "Hello world"); zassert_equal(u8, 80); zassert_equal(s8, -80); zassert_equal(u16, 160); diff --git a/tests/subsys/debug/symtab/src/main.c b/tests/subsys/debug/symtab/src/main.c index 8fa2018fa786e..39297dbc1640b 100644 --- a/tests/subsys/debug/symtab/src/main.c +++ b/tests/subsys/debug/symtab/src/main.c @@ -37,21 +37,21 @@ ZTEST(test_symtab, test_symtab_find_symbol_name) /* Find the name of functions with `symtab_find_symbol_name()` */ offset = -1; symbol_name = symtab_find_symbol_name((uintptr_t)main, &offset); - zassert_equal(strcmp(symbol_name, "main"), 0); + zassert_str_equal(symbol_name, "main"); zassert_equal(offset, 0); /* Do a few more just for fun */ symbol_name = symtab_find_symbol_name((uintptr_t)strcmp, NULL); - zassert_equal(strcmp(symbol_name, "strcmp"), 0); + zassert_str_equal(symbol_name, "strcmp"); symbol_name = symtab_find_symbol_name((uintptr_t)symtab_find_symbol_name, NULL); - zassert_equal(strcmp(symbol_name, "symtab_find_symbol_name"), 0); + zassert_str_equal(symbol_name, "symtab_find_symbol_name"); symbol_name = symtab_find_symbol_name((uintptr_t)test_main, NULL); - zassert_equal(strcmp(symbol_name, "test_main"), 0); + zassert_str_equal(symbol_name, "test_main"); symbol_name = symtab_find_symbol_name((uintptr_t)setup, NULL); - zassert_equal(strcmp(symbol_name, "setup"), 0); + zassert_str_equal(symbol_name, "setup"); } /** @@ -83,7 +83,7 @@ ZTEST(test_symtab, test_before_first) if (first_addr > 0) { offset = -1; symbol_name = symtab_find_symbol_name(first_addr - 1, &offset); - zassert_equal(strcmp(symbol_name, "?"), 0); + zassert_str_equal(symbol_name, "?"); zassert_equal(offset, 0); } else { ztest_test_skip(); @@ -98,13 +98,13 @@ ZTEST(test_symtab, test_first) offset = -1; symbol_name = symtab_find_symbol_name(first_addr, &offset); - zassert_equal(strcmp(symbol_name, symtab->entries[0].name), 0); + zassert_str_equal(symbol_name, symtab->entries[0].name); zassert_equal(offset, 0); if ((symtab->entries[0].offset + 1) != symtab->entries[1].offset) { offset = -1; symbol_name = symtab_find_symbol_name(first_addr + 1, &offset); - zassert_equal(strcmp(symbol_name, symtab->entries[0].name), 0); + zassert_str_equal(symbol_name, symtab->entries[0].name); zassert_equal(offset, 1); } } @@ -119,7 +119,7 @@ ZTEST(test_symtab, test_last) offset = -1; symbol_name = symtab_find_symbol_name(last_addr, &offset); - zassert_equal(strcmp(symbol_name, symtab->entries[last_idx].name), 0); + zassert_str_equal(symbol_name, symtab->entries[last_idx].name); zassert_equal(offset, 0); } @@ -135,7 +135,8 @@ ZTEST(test_symtab, test_after_last) if (last_offset + 0x1 != symtab->entries[symtab->length].offset) { offset = -1; symbol_name = symtab_find_symbol_name(last_addr + 0x1, &offset); - zassert_equal(strcmp(symbol_name, symtab->entries[symtab->length - 1].name), 0); + zassert_str_equal(symbol_name, + symtab->entries[symtab->length - 1].name); zassert_equal(offset, 0x1); } else { ztest_test_skip(); @@ -153,6 +154,6 @@ ZTEST(test_symtab, test_after_dummy) /* Test `offset` output with dummy symbol (after last dymbol) */ offset = -1; symbol_name = symtab_find_symbol_name(last_dummy_addr + 0x42, &offset); - zassert_equal(strcmp(symbol_name, "?"), 0); + zassert_str_equal(symbol_name, "?"); zassert_equal(offset, 0); } diff --git a/tests/subsys/fs/common/test_fs_basic.c b/tests/subsys/fs/common/test_fs_basic.c index 60b51ac48ac8a..8c3b2128ddda3 100644 --- a/tests/subsys/fs/common/test_fs_basic.c +++ b/tests/subsys/fs/common/test_fs_basic.c @@ -43,8 +43,7 @@ static int create_write_hello(const struct fs_mount_t *mp) zassert_equal(stat.type, FS_DIR_ENTRY_FILE, "stat new hello not file"); - zassert_equal(strcmp(stat.name, HELLO), 0, - "stat new hello not hello"); + zassert_str_equal(stat.name, HELLO, "stat new hello not hello"); zassert_equal(stat.size, 0, "stat new hello not empty"); @@ -58,8 +57,7 @@ static int create_write_hello(const struct fs_mount_t *mp) zassert_equal(stat.type, FS_DIR_ENTRY_FILE, "stat written hello not file"); - zassert_equal(strcmp(stat.name, HELLO), 0, - "stat written hello not hello"); + zassert_str_equal(stat.name, HELLO, "stat written hello not hello"); /* Anomalous behavior requiring upstream response */ if (mp->type == FS_LITTLEFS) { @@ -79,8 +77,7 @@ static int create_write_hello(const struct fs_mount_t *mp) zassert_equal(stat.type, FS_DIR_ENTRY_FILE, "stat closed hello not file"); - zassert_equal(strcmp(stat.name, HELLO), 0, - "stat closed hello not hello"); + zassert_str_equal(stat.name, HELLO, "stat closed hello not hello"); zassert_equal(stat.size, TESTFS_BUFFER_SIZE, "stat closed hello badsize"); diff --git a/tests/subsys/fs/fs_api/src/test_fs_dir_file.c b/tests/subsys/fs/fs_api/src/test_fs_dir_file.c index 3b8232714a156..7547cffae972f 100644 --- a/tests/subsys/fs/fs_api/src/test_fs_dir_file.c +++ b/tests/subsys/fs/fs_api/src/test_fs_dir_file.c @@ -700,8 +700,8 @@ void test_file_read(void) read_buff[brw] = 0; TC_PRINT("Data read:\"%s\"\n\n", read_buff); - zassert_true(strcmp(test_str, read_buff) == 0, - "Error - Data read does not match data written"); + zassert_str_equal(test_str, read_buff, + "Error - Data read does not match data written"); TC_PRINT("Data read matches data written\n"); } diff --git a/tests/subsys/fs/littlefs/src/test_util.c b/tests/subsys/fs/littlefs/src/test_util.c index 491ad3ff87317..3c8695c6f23a4 100644 --- a/tests/subsys/fs/littlefs/src/test_util.c +++ b/tests/subsys/fs/littlefs/src/test_util.c @@ -31,12 +31,12 @@ ZTEST(littlefs, test_util_path_init_base) zassert_equal(testfs_path_init(&path, NULL, TESTFS_PATH_END), path.path, "bad root init return"); - zassert_equal(strcmp(path.path, "/"), 0, "bad root init path"); + zassert_str_equal(path.path, "/", "bad root init path"); zassert_equal(testfs_path_init(&path, &mnt, TESTFS_PATH_END), path.path, "bad mnt init return"); - zassert_equal(strcmp(path.path, mnt.mnt_point), 0, "bad mnt init path"); + zassert_str_equal(path.path, mnt.mnt_point, "bad mnt init path"); if (IS_ENABLED(CONFIG_DEBUG)) { struct fs_mount_t invalid = { @@ -76,71 +76,35 @@ ZTEST(littlefs, test_util_path_init_overrun) ZTEST(littlefs, test_util_path_init_extended) { - zassert_equal(strcmp(testfs_path_init(&path, &mnt, - ELT1, - TESTFS_PATH_END), - MNT "/" ELT1), - 0, - "bad mnt init elt1"); + zassert_str_equal(testfs_path_init(&path, &mnt, ELT1, TESTFS_PATH_END), + MNT "/" ELT1, "bad mnt init elt1"); - zassert_equal(strcmp(testfs_path_init(&path, &mnt, - ELT1, - ELT2, - TESTFS_PATH_END), - MNT "/" ELT1 "/" ELT2), - 0, - "bad mnt init elt1 elt2"); + zassert_str_equal(testfs_path_init(&path, &mnt, ELT1, ELT2, TESTFS_PATH_END), + MNT "/" ELT1 "/" ELT2, "bad mnt init elt1 elt2"); } ZTEST(littlefs, test_util_path_extend) { - zassert_equal(strcmp(testfs_path_extend(reset_path(), - TESTFS_PATH_END), - MNT), - 0, - "empty extend failed"); + zassert_str_equal(testfs_path_extend(reset_path(), TESTFS_PATH_END), + MNT, "empty extend failed"); - zassert_equal(strcmp(testfs_path_extend(reset_path(), - ELT2, - TESTFS_PATH_END), - MNT "/" ELT2), - 0, - "elt extend failed"); + zassert_str_equal(testfs_path_extend(reset_path(), ELT2, TESTFS_PATH_END), + MNT "/" ELT2, "elt extend failed"); - zassert_equal(strcmp(testfs_path_extend(reset_path(), - ELT1, - ELT2, - TESTFS_PATH_END), - MNT "/" ELT1 "/" ELT2), - 0, - "elt1 elt2 extend failed"); + zassert_str_equal(testfs_path_extend(reset_path(), ELT1, ELT2, TESTFS_PATH_END), + MNT "/" ELT1 "/" ELT2, "elt1 elt2 extend failed"); } ZTEST(littlefs, test_util_path_extend_up) { - zassert_equal(strcmp(testfs_path_extend(reset_path(), - ELT2, - "..", - ELT1, - TESTFS_PATH_END), - MNT "/" ELT1), - 0, - "elt elt2, up, elt1 failed"); + zassert_str_equal(testfs_path_extend(reset_path(), ELT2, "..", ELT1, TESTFS_PATH_END), + MNT "/" ELT1, "elt elt2, up, elt1 failed"); - zassert_equal(strcmp(testfs_path_extend(reset_path(), - "..", - TESTFS_PATH_END), - "/"), - 0, - "up strip mnt failed"); + zassert_str_equal(testfs_path_extend(reset_path(), "..", TESTFS_PATH_END), + "/", "up strip mnt failed"); - zassert_equal(strcmp(testfs_path_extend(reset_path(), - "..", - "..", - TESTFS_PATH_END), - "/"), - 0, - "up from root failed"); + zassert_str_equal(testfs_path_extend(reset_path(), "..", "..", TESTFS_PATH_END), + "/", "up from root failed"); } ZTEST(littlefs, test_util_path_extend_overrun) @@ -150,11 +114,6 @@ ZTEST(littlefs, test_util_path_extend_overrun) memset(long_elt, 'a', sizeof(long_elt) - 1); long_elt[sizeof(long_elt) - 1] = '\0'; - zassert_equal(strcmp(testfs_path_extend(reset_path(), - long_elt, - ELT1, - TESTFS_PATH_END), - MNT), - 0, - "stop at overrun failed"); + zassert_str_equal(testfs_path_extend(reset_path(), long_elt, ELT1, TESTFS_PATH_END), + MNT, "stop at overrun failed"); } diff --git a/tests/subsys/logging/log_links/src/main.c b/tests/subsys/logging/log_links/src/main.c index 84aa6eb2a3824..76a11bd2a1955 100644 --- a/tests/subsys/logging/log_links/src/main.c +++ b/tests/subsys/logging/log_links/src/main.c @@ -211,8 +211,8 @@ ZTEST(log_links, test_log_runtime_level_set) ZTEST(log_links, test_log_domain_name_get) { - zassert_equal(strcmp(log_domain_name_get(0), ""), 0, - "Unexpected domain name"); + zassert_str_equal(log_domain_name_get(0), "", + "Unexpected domain name"); zassert_equal(strcmp(log_domain_name_get(1), "domain1"), 0, "Unexpected domain name (%s)", log_domain_name_get(1)); zassert_equal(strcmp(log_domain_name_get(2), "domain2"), 0, diff --git a/tests/subsys/logging/log_output/src/log_output_test.c b/tests/subsys/logging/log_output/src/log_output_test.c index e13c18f1a1174..21ee039f6e297 100644 --- a/tests/subsys/logging/log_output/src/log_output_test.c +++ b/tests/subsys/logging/log_output/src/log_output_test.c @@ -57,7 +57,7 @@ ZTEST(test_log_output, test_no_flags) log_output_process(&log_output, 0, NULL, SNAME, NULL, LOG_LEVEL_INF, package, NULL, 0, 0); mock_buffer[mock_len] = '\0'; - zassert_equal(strcmp(exp_str, mock_buffer), 0); + zassert_str_equal(exp_str, mock_buffer); } ZTEST(test_log_output, test_raw) @@ -73,7 +73,7 @@ ZTEST(test_log_output, test_raw) package, NULL, 0, 0); mock_buffer[mock_len] = '\0'; - zassert_equal(strcmp(exp_str, mock_buffer), 0); + zassert_str_equal(exp_str, mock_buffer); } ZTEST(test_log_output, test_no_flags_dname) @@ -88,7 +88,7 @@ ZTEST(test_log_output, test_no_flags_dname) log_output_process(&log_output, 0, DNAME, SNAME, NULL, LOG_LEVEL_INF, package, NULL, 0, 0); mock_buffer[mock_len] = '\0'; - zassert_equal(strcmp(exp_str, mock_buffer), 0); + zassert_str_equal(exp_str, mock_buffer); } ZTEST(test_log_output, test_level_flag) @@ -105,7 +105,7 @@ ZTEST(test_log_output, test_level_flag) package, NULL, 0, flags); mock_buffer[mock_len] = '\0'; - zassert_equal(strcmp(exp_str, mock_buffer), 0); + zassert_str_equal(exp_str, mock_buffer); } ZTEST(test_log_output, test_ts_flag) @@ -124,7 +124,7 @@ ZTEST(test_log_output, test_ts_flag) package, NULL, 0, flags); mock_buffer[mock_len] = '\0'; - zassert_equal(strcmp(exp_str, mock_buffer), 0); + zassert_str_equal(exp_str, mock_buffer); } ZTEST(test_log_output, test_format_ts) @@ -145,7 +145,7 @@ ZTEST(test_log_output, test_format_ts) mock_buffer[mock_len] = '\0'; printk("%s", mock_buffer); - zassert_equal(strcmp(exp_str, mock_buffer), 0); + zassert_str_equal(exp_str, mock_buffer); } ZTEST(test_log_output, test_ts_to_us) @@ -182,7 +182,7 @@ ZTEST(test_log_output, test_levels) package, NULL, 0, flags); mock_buffer[mock_len] = '\0'; - zassert_equal(strcmp(exp_strs[i], mock_buffer), 0); + zassert_str_equal(exp_strs[i], mock_buffer); } } @@ -214,7 +214,7 @@ ZTEST(test_log_output, test_colors) package, NULL, 0, flags); mock_buffer[mock_len] = '\0'; - zassert_equal(strcmp(exp_strs[i], mock_buffer), 0); + zassert_str_equal(exp_strs[i], mock_buffer); } } @@ -244,7 +244,7 @@ ZTEST(test_log_output, test_thread_id) mock_buffer[mock_len] = '\0'; printk("%s", mock_buffer); - zassert_equal(strcmp(exp_str, mock_buffer), 0); + zassert_str_equal(exp_str, mock_buffer); } ZTEST(test_log_output, test_skip_src) @@ -262,7 +262,7 @@ ZTEST(test_log_output, test_skip_src) package, NULL, 0, flags); mock_buffer[mock_len] = '\0'; - zassert_equal(strcmp(exp_str, mock_buffer), 0); + zassert_str_equal(exp_str, mock_buffer); } static void before(void *notused) diff --git a/tests/subsys/logging/log_timestamp/src/log_timestamp_test.c b/tests/subsys/logging/log_timestamp/src/log_timestamp_test.c index f6b65042d050f..17f04e83c1f22 100644 --- a/tests/subsys/logging/log_timestamp/src/log_timestamp_test.c +++ b/tests/subsys/logging/log_timestamp/src/log_timestamp_test.c @@ -75,7 +75,7 @@ ZTEST(test_timestamp, test_custom_timestamp) package, NULL, 0, flags); mock_buffer[mock_len] = '\0'; - zassert_equal(strcmp(exp_str, mock_buffer), 0); + zassert_str_equal(exp_str, mock_buffer); } static void before(void *notused) diff --git a/tests/subsys/mem_mgmt/mem_attr/src/main.c b/tests/subsys/mem_mgmt/mem_attr/src/main.c index a05ea6dab20a3..160c3d51801c8 100644 --- a/tests/subsys/mem_mgmt/mem_attr/src/main.c +++ b/tests/subsys/mem_mgmt/mem_attr/src/main.c @@ -26,15 +26,15 @@ ZTEST(mem_attr, test_mem_attr) zassert_equal(region[idx].dt_attr, DT_MEM_ARM_MPU_FLASH | DT_MEM_NON_VOLATILE, "Wrong region address"); - zassert_true((strcmp(region[idx].dt_name, "memory@10000000") == 0), - "Wrong name"); + zassert_str_equal(region[idx].dt_name, + "memory@10000000", "Wrong name"); } else { zassert_equal(region[idx].dt_addr, 0x20000000, "Wrong region address"); zassert_equal(region[idx].dt_size, 0x2000, "Wrong region size"); zassert_equal(region[idx].dt_attr, DT_MEM_ARM_MPU_RAM_NOCACHE, "Wrong region address"); - zassert_true((strcmp(region[idx].dt_name, "memory@20000000") == 0), - "Wrong name"); + zassert_str_equal(region[idx].dt_name, + "memory@20000000", "Wrong name"); } } diff --git a/tests/subsys/modem/modem_chat/src/main.c b/tests/subsys/modem/modem_chat/src/main.c index f988342899330..730b35da00b36 100644 --- a/tests/subsys/modem/modem_chat/src/main.c +++ b/tests/subsys/modem/modem_chat/src/main.c @@ -521,11 +521,16 @@ ZTEST(modem_chat, test_script_with_partial_matches) MODEM_CHAT_UTEST_ON_CMGL_PARTIAL_CALLED_BIT); zassert_equal(called, true, "Match callback not called"); zassert_equal(argc_buffers, 5, "Incorrect number of args"); - zassert_equal(strcmp(argv_buffers[0], "+CMGL: "), 0, "Incorrect argv received"); - zassert_equal(strcmp(argv_buffers[1], "1"), 0, "Incorrect argv received"); - zassert_equal(strcmp(argv_buffers[2], "1"), 0, "Incorrect argv received"); - zassert_equal(strcmp(argv_buffers[3], ""), 0, "Incorrect argv received"); - zassert_equal(strcmp(argv_buffers[4], "50"), 0, "Incorrect argv received"); + zassert_str_equal(argv_buffers[0], "+CMGL: ", + "Incorrect argv received"); + zassert_str_equal(argv_buffers[1], "1", + "Incorrect argv received"); + zassert_str_equal(argv_buffers[2], "1", + "Incorrect argv received"); + zassert_str_equal(argv_buffers[3], "", + "Incorrect argv received"); + zassert_str_equal(argv_buffers[4], "50", + "Incorrect argv received"); atomic_set(&callback_called, 0); modem_backend_mock_put(&mock, cmgl_response_1, sizeof(cmgl_response_1) - 1); @@ -535,9 +540,11 @@ ZTEST(modem_chat, test_script_with_partial_matches) MODEM_CHAT_UTEST_ON_CMGL_PARTIAL_ANY_CALLED_BIT); zassert_equal(called, true, "Match callback not called"); zassert_equal(argc_buffers, 2, "Incorrect number of args"); - zassert_equal(strcmp(argv_buffers[0], ""), 0, "Incorrect argv received"); - zassert_equal(strcmp(argv_buffers[1], "07911326060032F064A9542954"), 0, - "Incorrect argv received"); + zassert_str_equal(argv_buffers[0], "", + "Incorrect argv received"); + zassert_str_equal(argv_buffers[1], + "07911326060032F064A9542954", + "Incorrect argv received"); } atomic_set(&callback_called, 0); diff --git a/tests/subsys/pm/device_driver_init/src/main.c b/tests/subsys/pm/device_driver_init/src/main.c index d2f9f78fd3aaa..d01a83d3ca68d 100644 --- a/tests/subsys/pm/device_driver_init/src/main.c +++ b/tests/subsys/pm/device_driver_init/src/main.c @@ -33,25 +33,29 @@ ZTEST(device_driver_init, test_device_driver_init) enum pm_device_state state; int rc; state = -1; - zassert_equal(strcmp("", pm_device_state_str(state)), 0, "Invalid device state"); + zassert_str_equal("", pm_device_state_str(state), + "Invalid device state"); /* No device runtime PM, starts on */ DEVICE_STATE_IS(DT_NODELABEL(test_reg), PM_DEVICE_STATE_ACTIVE); DEVICE_STATE_IS(DT_NODELABEL(test_reg_chained), PM_DEVICE_STATE_ACTIVE); POWER_GPIO_CONFIG_IS(DT_NODELABEL(test_reg), GPIO_OUTPUT_HIGH); POWER_GPIO_CONFIG_IS(DT_NODELABEL(test_reg_chained), GPIO_OUTPUT_HIGH); - zassert_equal(strcmp("active", pm_device_state_str(state)), 0, "Invalid device state"); + zassert_str_equal("active", pm_device_state_str(state), + "Invalid device state"); /* Device powered, zephyr,pm-device-runtime-auto, starts suspended */ DEVICE_STATE_IS(DT_NODELABEL(test_reg_chained_auto), PM_DEVICE_STATE_SUSPENDED); DEVICE_STATE_IS(DT_NODELABEL(test_reg_auto), PM_DEVICE_STATE_SUSPENDED); POWER_GPIO_CONFIG_IS(DT_NODELABEL(test_reg_chained_auto), GPIO_OUTPUT_LOW); POWER_GPIO_CONFIG_IS(DT_NODELABEL(test_reg_auto), GPIO_OUTPUT_LOW); - zassert_equal(strcmp("suspended", pm_device_state_str(state)), 0, "Invalid device state"); + zassert_str_equal("suspended", pm_device_state_str(state), + "Invalid device state"); /* Device not powered, starts off */ DEVICE_STATE_IS(DT_NODELABEL(test_reg_auto_chained), PM_DEVICE_STATE_OFF); DEVICE_STATE_IS(DT_NODELABEL(test_reg_auto_chained_auto), PM_DEVICE_STATE_OFF); POWER_GPIO_CONFIG_IS(DT_NODELABEL(test_reg_auto_chained), GPIO_DISCONNECTED); POWER_GPIO_CONFIG_IS(DT_NODELABEL(test_reg_auto_chained_auto), GPIO_DISCONNECTED); - zassert_equal(strcmp("off", pm_device_state_str(state)), 0, "Invalid device state"); + zassert_str_equal("off", pm_device_state_str(state), + "Invalid device state"); #else /* Every regulator should be in "active" mode automatically. * State checking via GPIO as PM API is disabled. diff --git a/tests/subsys/portability/cmsis_rtos_v2/src/event_flags.c b/tests/subsys/portability/cmsis_rtos_v2/src/event_flags.c index 34c06578912de..c4906eb5e9686 100644 --- a/tests/subsys/portability/cmsis_rtos_v2/src/event_flags.c +++ b/tests/subsys/portability/cmsis_rtos_v2/src/event_flags.c @@ -81,8 +81,8 @@ void test_event_flags_no_wait_timeout(void) "Invalid event Flags ID is unexpectedly working!"); name = osEventFlagsGetName(evt_id); - zassert_true(strcmp(event_flags_attrs.name, name) == 0, - "Error getting event_flags object name"); + zassert_str_equal(event_flags_attrs.name, name, + "Error getting event_flags object name"); id1 = osThreadNew(thread1, evt_id, &thread1_attr); zassert_true(id1 != NULL, "Failed creating thread1"); diff --git a/tests/subsys/portability/cmsis_rtos_v2/src/kernel.c b/tests/subsys/portability/cmsis_rtos_v2/src/kernel.c index b47d4e77d2248..96071d0f1fc90 100644 --- a/tests/subsys/portability/cmsis_rtos_v2/src/kernel.c +++ b/tests/subsys/portability/cmsis_rtos_v2/src/kernel.c @@ -78,7 +78,7 @@ ZTEST(cmsis_kernel, test_kernel_apis) irq_offload(get_version_check, (const void *)&version_irq); /* Check if the version value retrieved in ISR and thread is same */ - zassert_equal(strcmp(version.info, version_irq.info), 0); + zassert_str_equal(version.info, version_irq.info); zassert_equal(version.os_info.api, version_irq.os_info.api); zassert_equal(version.os_info.kernel, version_irq.os_info.kernel); diff --git a/tests/subsys/portability/cmsis_rtos_v2/src/mempool.c b/tests/subsys/portability/cmsis_rtos_v2/src/mempool.c index 1af17988e7eea..c0e4530f8648d 100644 --- a/tests/subsys/portability/cmsis_rtos_v2/src/mempool.c +++ b/tests/subsys/portability/cmsis_rtos_v2/src/mempool.c @@ -39,8 +39,7 @@ static void mempool_common_tests(osMemoryPoolId_t mp_id, "Something's wrong with osMemoryPoolGetName!"); name = osMemoryPoolGetName(mp_id); - zassert_true(strcmp(expected_name, name) == 0, - "Error getting mempool name"); + zassert_str_equal(expected_name, name, "Error getting mempool name"); zassert_equal(osMemoryPoolGetCapacity(dummy_id), 0, "Something's wrong with osMemoryPoolGetCapacity!"); diff --git a/tests/subsys/portability/cmsis_rtos_v2/src/mutex.c b/tests/subsys/portability/cmsis_rtos_v2/src/mutex.c index e56dc3720f7d4..bfb1b0735d5e9 100644 --- a/tests/subsys/portability/cmsis_rtos_v2/src/mutex.c +++ b/tests/subsys/portability/cmsis_rtos_v2/src/mutex.c @@ -66,8 +66,7 @@ ZTEST(cmsis_mutex, test_mutex) zassert_true(mutex_id != NULL, "Mutex1 creation failed"); name = osMutexGetName(mutex_id); - zassert_true(strcmp(mutex_attr.name, name) == 0, - "Error getting Mutex name"); + zassert_str_equal(mutex_attr.name, name, "Error getting Mutex name"); /* Try to release mutex without obtaining it */ status = osMutexRelease(mutex_id); diff --git a/tests/subsys/portability/cmsis_rtos_v2/src/semaphore.c b/tests/subsys/portability/cmsis_rtos_v2/src/semaphore.c index 50feb6efd4419..9259cf69b47de 100644 --- a/tests/subsys/portability/cmsis_rtos_v2/src/semaphore.c +++ b/tests/subsys/portability/cmsis_rtos_v2/src/semaphore.c @@ -78,8 +78,8 @@ ZTEST(cmsis_semaphore, test_semaphore) zassert_true(semaphore_id != NULL, "semaphore creation failed"); name = osSemaphoreGetName(semaphore_id); - zassert_true(strcmp(sema_attr.name, name) == 0, - "Error getting Semaphore name"); + zassert_str_equal(sema_attr.name, name, + "Error getting Semaphore name"); id = osThreadNew(thread_sema, semaphore_id, &thread_attr); zassert_true(id != NULL, "Thread creation failed"); diff --git a/tests/subsys/portability/cmsis_rtos_v2/src/thread_apis.c b/tests/subsys/portability/cmsis_rtos_v2/src/thread_apis.c index a777e1cbd6f21..ea73756a6631d 100644 --- a/tests/subsys/portability/cmsis_rtos_v2/src/thread_apis.c +++ b/tests/subsys/portability/cmsis_rtos_v2/src/thread_apis.c @@ -46,8 +46,7 @@ static void thread1(void *argument) zassert_true(thread_id != NULL, "Failed getting Thread ID"); name = osThreadGetName(thread_id); - zassert_true(strcmp(args->name, name) == 0, - "Failed getting Thread name"); + zassert_str_equal(args->name, name, "Failed getting Thread name"); /* This thread starts off at a high priority (same as thread2) */ (*args->yield_check)++; diff --git a/tests/subsys/portability/cmsis_rtos_v2/src/timer.c b/tests/subsys/portability/cmsis_rtos_v2/src/timer.c index 6e0e3a0ee9387..35ab88ed17417 100644 --- a/tests/subsys/portability/cmsis_rtos_v2/src/timer.c +++ b/tests/subsys/portability/cmsis_rtos_v2/src/timer.c @@ -55,8 +55,7 @@ ZTEST(cmsis_timer, test_timer) zassert_true(id1 != NULL, "error creating one-shot timer"); name = osTimerGetName(id1); - zassert_true(strcmp(timer_attr.name, name) == 0, - "Error getting Timer name"); + zassert_str_equal(timer_attr.name, name, "Error getting Timer name"); /* Stop the timer before start */ status = osTimerStop(id1); diff --git a/tests/subsys/settings/fcb/src/settings_test_save_2_fcb.c b/tests/subsys/settings/fcb/src/settings_test_save_2_fcb.c index 74fb9288c82a0..a75f4ffd8a769 100644 --- a/tests/subsys/settings/fcb/src/settings_test_save_2_fcb.c +++ b/tests/subsys/settings/fcb/src/settings_test_save_2_fcb.c @@ -56,8 +56,7 @@ ZTEST(settings_config_fcb, test_config_save_2_fcb) rc = settings_load(); zassert_true(rc == 0, "fcb read error"); zassert_true(val8 == 42U, "bad value read"); - zassert_true(!strcmp(val_string[0], test_ref_value[0]), - "bad value read"); + zassert_str_equal(val_string[0], test_ref_value[0], "bad value read"); test_export_block = 1; /* diff --git a/tests/unit/cbprintf/main.c b/tests/unit/cbprintf/main.c index ace6aa6ff254b..1fabf19bfa066 100644 --- a/tests/unit/cbprintf/main.c +++ b/tests/unit/cbprintf/main.c @@ -1306,14 +1306,14 @@ ZTEST(prf, test_cbprintf_fsc_package) cbpprintf(fsc_package_cb, &pout, package); *pout = '\0'; - zassert_equal(strcmp(out_str, exp_str1), 0); + zassert_str_equal(out_str, exp_str1); zassert_true(strcmp(exp_str0, exp_str1) != 0); /* FSC package contains original content. */ pout = out_str; cbpprintf(fsc_package_cb, &pout, fsc_package); *pout = '\0'; - zassert_equal(strcmp(out_str, exp_str0), 0); + zassert_str_equal(out_str, exp_str0); } ZTEST(prf, test_cbpprintf) diff --git a/tests/unit/util/main.c b/tests/unit/util/main.c index f386ba0f7894e..dad28a9ec4892 100644 --- a/tests/unit/util/main.c +++ b/tests/unit/util/main.c @@ -14,49 +14,44 @@ ZTEST(util, test_u8_to_dec) { len = u8_to_dec(text, sizeof(text), 0); zassert_equal(len, 1, "Length of 0 is not 1"); - zassert_equal(strcmp(text, "0"), 0, - "Value=0 is not converted to \"0\""); + zassert_str_equal(text, "0", "Value=0 is not converted to \"0\""); len = u8_to_dec(text, sizeof(text), 1); zassert_equal(len, 1, "Length of 1 is not 1"); - zassert_equal(strcmp(text, "1"), 0, - "Value=1 is not converted to \"1\""); + zassert_str_equal(text, "1", "Value=1 is not converted to \"1\""); len = u8_to_dec(text, sizeof(text), 11); zassert_equal(len, 2, "Length of 11 is not 2"); - zassert_equal(strcmp(text, "11"), 0, - "Value=10 is not converted to \"11\""); + zassert_str_equal(text, "11", "Value=10 is not converted to \"11\""); len = u8_to_dec(text, sizeof(text), 100); zassert_equal(len, 3, "Length of 100 is not 3"); - zassert_equal(strcmp(text, "100"), 0, - "Value=100 is not converted to \"100\""); + zassert_str_equal(text, "100", + "Value=100 is not converted to \"100\""); len = u8_to_dec(text, sizeof(text), 101); zassert_equal(len, 3, "Length of 101 is not 3"); - zassert_equal(strcmp(text, "101"), 0, - "Value=101 is not converted to \"101\""); + zassert_str_equal(text, "101", + "Value=101 is not converted to \"101\""); len = u8_to_dec(text, sizeof(text), 255); zassert_equal(len, 3, "Length of 255 is not 3"); - zassert_equal(strcmp(text, "255"), 0, - "Value=255 is not converted to \"255\""); + zassert_str_equal(text, "255", + "Value=255 is not converted to \"255\""); memset(text, 0, sizeof(text)); len = u8_to_dec(text, 2, 123); zassert_equal(len, 2, "Length of converted value using 2 byte buffer isn't 2"); - zassert_equal( - strcmp(text, "12"), 0, - "Value=123 is not converted to \"12\" using 2-byte buffer"); + zassert_str_equal(text, "12", + "Value=123 is not converted to \"12\" using 2-byte buffer"); memset(text, 0, sizeof(text)); len = u8_to_dec(text, 1, 123); zassert_equal(len, 1, "Length of converted value using 1 byte buffer isn't 1"); - zassert_equal( - strcmp(text, "1"), 0, - "Value=123 is not converted to \"1\" using 1-byte buffer"); + zassert_str_equal(text, "1", + "Value=123 is not converted to \"1\" using 1-byte buffer"); memset(text, 0, sizeof(text)); len = u8_to_dec(text, 0, 123); @@ -419,9 +414,9 @@ ZTEST(util, test_LIST_DROP_EMPTY) { }; zassert_equal(ARRAY_SIZE(arr), 3, "Failed to cleanup list"); - zassert_equal(strcmp(arr[0], "Henry"), 0, "Failed at 0"); - zassert_equal(strcmp(arr[1], "Dorsett"), 0, "Failed at 1"); - zassert_equal(strcmp(arr[2], "Case"), 0, "Failed at 0"); + zassert_str_equal(arr[0], "Henry", "Failed at 0"); + zassert_str_equal(arr[1], "Dorsett", "Failed at 1"); + zassert_str_equal(arr[2], "Case", "Failed at 0"); } ZTEST(util, test_nested_FOR_EACH) { From 25cdda10e1efad2eb3afbc70e55e6c9eafb3a8a4 Mon Sep 17 00:00:00 2001 From: Lars-Ove Karlsson Date: Wed, 12 Jun 2024 12:51:21 +0200 Subject: [PATCH 2785/2849] kernel: Unified type of stack protection canary __stack_chk_guard. Extern declaration of __stack_chk_guard added volatile to the type while the declaration was non-volatile. This cause type check errors with compilers that declares the __stack_chk_guard variable in an internal pre-include header file (IAR). While I think the volatile keyword is unnecessary, I decided on keep it and add it to the declaration in kernel/compiler_stack_protect.c Tested with IAR ICCARM and the Zephyr SDK GCC. Signed-off-by: Lars-Ove Karlsson --- kernel/compiler_stack_protect.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/kernel/compiler_stack_protect.c b/kernel/compiler_stack_protect.c index 2ee2d81c7a320..928fdc6ec9ad8 100644 --- a/kernel/compiler_stack_protect.c +++ b/kernel/compiler_stack_protect.c @@ -47,11 +47,11 @@ void _StackCheckHandler(void) * The canary value gets initialized in z_cstart(). */ #ifdef CONFIG_STACK_CANARIES_TLS -__thread uintptr_t __stack_chk_guard; +__thread volatile uintptr_t __stack_chk_guard; #elif CONFIG_USERSPACE -K_APP_DMEM(z_libc_partition) uintptr_t __stack_chk_guard; +K_APP_DMEM(z_libc_partition) volatile uintptr_t __stack_chk_guard; #else -__noinit uintptr_t __stack_chk_guard; +__noinit volatile uintptr_t __stack_chk_guard; #endif /** From 9fdaf43e79331f87b4f1a8bcea21613c9969389b Mon Sep 17 00:00:00 2001 From: Daniel DeGrasse Date: Wed, 5 Jun 2024 11:52:28 -0500 Subject: [PATCH 2786/2849] drivers: display: uc81xx: convert to MIPI DBI API Convert UC81XX display to use MIPI DBI API, as this display uses a SPI 3/4 wire bus. In tree shields using this driver have also had their devicetrees updated to use the new MIPI DBI SPI driver Signed-off-by: Daniel DeGrasse --- .../waveshare_epaper_gdew042t2-p.overlay | 146 +++++++++--------- .../waveshare_epaper_gdew042t2.overlay | 36 +++-- .../waveshare_epaper_gdew075t7.overlay | 36 +++-- drivers/display/Kconfig.uc81xx | 2 +- drivers/display/uc81xx.c | 114 +++++--------- .../display/ultrachip,uc81xx-common.yaml | 21 +-- 6 files changed, 157 insertions(+), 198 deletions(-) diff --git a/boards/shields/waveshare_epaper/waveshare_epaper_gdew042t2-p.overlay b/boards/shields/waveshare_epaper/waveshare_epaper_gdew042t2-p.overlay index 35f96d940e2ad..2a1024ece0d82 100644 --- a/boards/shields/waveshare_epaper/waveshare_epaper_gdew042t2-p.overlay +++ b/boards/shields/waveshare_epaper/waveshare_epaper_gdew042t2-p.overlay @@ -8,87 +8,93 @@ / { chosen { - zephyr,display = &uc8176_waveshare_epaper_gdew042t2-p; + zephyr,display = &uc8176_waveshare_epaper_gdew042t2_p; }; -}; -&arduino_spi { - /* - * GoodDisplay GDEW042T2 with fast partial refresh. Based on - * configuration from GoodDisplay's Arduino example. - */ - uc8176_waveshare_epaper_gdew042t2-p: uc8176@0 { - compatible = "gooddisplay,gdew042t2", "ultrachip,uc8176"; - spi-max-frequency = <4000000>; - reg = <0>; - width = <400>; - height = <300>; - dc-gpios = <&arduino_header 15 GPIO_ACTIVE_LOW>; /* D9 */ + mipi_dbi_waveshare_epaper_gdew042t2-p { + 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 */ - busy-gpios = <&arduino_header 13 GPIO_ACTIVE_LOW>; /* D7 */ + write-only; + #address-cells = <1>; + #size-cells = <0>; - softstart = [ 17 17 17 ]; + /* + * GoodDisplay GDEW042T2 with fast partial refresh. Based on + * configuration from GoodDisplay's Arduino example. + */ + uc8176_waveshare_epaper_gdew042t2_p: uc8176@0 { + compatible = "gooddisplay,gdew042t2", "ultrachip,uc8176"; + mipi-max-frequency = <4000000>; + reg = <0>; + width = <400>; + height = <300>; + busy-gpios = <&arduino_header 13 GPIO_ACTIVE_LOW>; /* D7 */ - full { - cdi = <0x07>; - }; + softstart = [ 17 17 17 ]; + + full { + cdi = <0x07>; + }; - partial { - pwr = [ 03 02 2b 2b ]; - cdi = <0x07>; - pll = <0x3c>; - vdcs = <0x08>; + partial { + pwr = [ 03 02 2b 2b ]; + cdi = <0x07>; + pll = <0x3c>; + vdcs = <0x08>; - lutc = [ - 00 01 0E 00 00 01 - 00 00 00 00 00 00 - 00 00 00 00 00 00 - 00 00 00 00 00 00 - 00 00 00 00 00 00 - 00 00 00 00 00 00 - 00 00 00 00 00 00 - 00 00 - ]; + lutc = [ + 00 01 0E 00 00 01 + 00 00 00 00 00 00 + 00 00 00 00 00 00 + 00 00 00 00 00 00 + 00 00 00 00 00 00 + 00 00 00 00 00 00 + 00 00 00 00 00 00 + 00 00 + ]; - lutww = [ - 00 01 0E 00 00 01 - 00 00 00 00 00 00 - 00 00 00 00 00 00 - 00 00 00 00 00 00 - 00 00 00 00 00 00 - 00 00 00 00 00 00 - 00 00 00 00 00 00 - ]; + lutww = [ + 00 01 0E 00 00 01 + 00 00 00 00 00 00 + 00 00 00 00 00 00 + 00 00 00 00 00 00 + 00 00 00 00 00 00 + 00 00 00 00 00 00 + 00 00 00 00 00 00 + ]; - lutkw = [ - 20 01 0E 00 00 01 - 00 00 00 00 00 00 - 00 00 00 00 00 00 - 00 00 00 00 00 00 - 00 00 00 00 00 00 - 00 00 00 00 00 00 - 00 00 00 00 00 00 - ]; + lutkw = [ + 20 01 0E 00 00 01 + 00 00 00 00 00 00 + 00 00 00 00 00 00 + 00 00 00 00 00 00 + 00 00 00 00 00 00 + 00 00 00 00 00 00 + 00 00 00 00 00 00 + ]; - lutwk = [ - 10 01 0E 00 00 01 - 00 00 00 00 00 00 - 00 00 00 00 00 00 - 00 00 00 00 00 00 - 00 00 00 00 00 00 - 00 00 00 00 00 00 - 00 00 00 00 00 00 - ]; + lutwk = [ + 10 01 0E 00 00 01 + 00 00 00 00 00 00 + 00 00 00 00 00 00 + 00 00 00 00 00 00 + 00 00 00 00 00 00 + 00 00 00 00 00 00 + 00 00 00 00 00 00 + ]; - lutkk = [ - 00 01 0E 00 00 01 - 00 00 00 00 00 00 - 00 00 00 00 00 00 - 00 00 00 00 00 00 - 00 00 00 00 00 00 - 00 00 00 00 00 00 - 00 00 00 00 00 00 - ]; + lutkk = [ + 00 01 0E 00 00 01 + 00 00 00 00 00 00 + 00 00 00 00 00 00 + 00 00 00 00 00 00 + 00 00 00 00 00 00 + 00 00 00 00 00 00 + 00 00 00 00 00 00 + ]; + }; }; }; }; diff --git a/boards/shields/waveshare_epaper/waveshare_epaper_gdew042t2.overlay b/boards/shields/waveshare_epaper/waveshare_epaper_gdew042t2.overlay index 0b8f994c97b19..035110ea5dcd9 100644 --- a/boards/shields/waveshare_epaper/waveshare_epaper_gdew042t2.overlay +++ b/boards/shields/waveshare_epaper/waveshare_epaper_gdew042t2.overlay @@ -9,25 +9,31 @@ chosen { zephyr,display = &uc8176_waveshare_epaper_gdew042t2; }; -}; -&arduino_spi { - uc8176_waveshare_epaper_gdew042t2: uc8176@0 { - compatible = "gooddisplay,gdew042t2", "ultrachip,uc8176"; - spi-max-frequency = <4000000>; - reg = <0>; - width = <400>; - height = <300>; - dc-gpios = <&arduino_header 15 GPIO_ACTIVE_LOW>; /* D9 */ + mipi_dbi_waveshare_epaper_gdew042t2 { + 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 */ - busy-gpios = <&arduino_header 13 GPIO_ACTIVE_LOW>; /* D7 */ + write-only; + #address-cells = <1>; + #size-cells = <0>; + + uc8176_waveshare_epaper_gdew042t2: uc8176@0 { + compatible = "gooddisplay,gdew042t2", "ultrachip,uc8176"; + mipi-max-frequency = <4000000>; + reg = <0>; + width = <400>; + height = <300>; + busy-gpios = <&arduino_header 13 GPIO_ACTIVE_LOW>; /* D7 */ - softstart = [17 17 17]; + softstart = [17 17 17]; - full { - pwr = [03 00 26 26 09]; - cdi = <0xd7>; - tcon = <0x22>; + full { + pwr = [03 00 26 26 09]; + cdi = <0xd7>; + tcon = <0x22>; + }; }; }; }; diff --git a/boards/shields/waveshare_epaper/waveshare_epaper_gdew075t7.overlay b/boards/shields/waveshare_epaper/waveshare_epaper_gdew075t7.overlay index cccee41faaa28..8c8cbd9d636ed 100644 --- a/boards/shields/waveshare_epaper/waveshare_epaper_gdew075t7.overlay +++ b/boards/shields/waveshare_epaper/waveshare_epaper_gdew075t7.overlay @@ -10,25 +10,31 @@ chosen { zephyr,display = &uc8179_waveshare_epaper_gdew075t7; }; -}; -&arduino_spi { - uc8179_waveshare_epaper_gdew075t7: uc8179@0 { - compatible = "gooddisplay,gdew075t7", "ultrachip,uc8179"; - spi-max-frequency = <4000000>; - reg = <0>; - width = <800>; - height = <480>; - dc-gpios = <&arduino_header 15 GPIO_ACTIVE_LOW>; /* D9 */ + mipi_dbi_waveshare_epaper_gdew075t7 { + 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 */ - busy-gpios = <&arduino_header 13 GPIO_ACTIVE_LOW>; /* D7 */ + write-only; + #address-cells = <1>; + #size-cells = <0>; + + uc8179_waveshare_epaper_gdew075t7: uc8179@0 { + compatible = "gooddisplay,gdew075t7", "ultrachip,uc8179"; + mipi-max-frequency = <4000000>; + reg = <0>; + width = <800>; + height = <480>; + busy-gpios = <&arduino_header 13 GPIO_ACTIVE_LOW>; /* D7 */ - softstart = [17 17 17 17]; + softstart = [17 17 17 17]; - full { - pwr = [07 07 3f 3f]; - cdi = <07>; - tcon = <0x22>; + full { + pwr = [07 07 3f 3f]; + cdi = <07>; + tcon = <0x22>; + }; }; }; }; diff --git a/drivers/display/Kconfig.uc81xx b/drivers/display/Kconfig.uc81xx index 75678d2f66310..123b5b3ed6fda 100644 --- a/drivers/display/Kconfig.uc81xx +++ b/drivers/display/Kconfig.uc81xx @@ -7,6 +7,6 @@ config UC81XX bool "UltraChip UC81xx compatible display controller driver" default y depends on DT_HAS_ULTRACHIP_UC8175_ENABLED || DT_HAS_ULTRACHIP_UC8176_ENABLED || DT_HAS_ULTRACHIP_UC8179_ENABLED - select SPI + select MIPI_DBI help Enable driver for UC81xx compatible controller. diff --git a/drivers/display/uc81xx.c b/drivers/display/uc81xx.c index ae0a3bf667c77..cac7d1d20c67c 100644 --- a/drivers/display/uc81xx.c +++ b/drivers/display/uc81xx.c @@ -1,6 +1,7 @@ /* * Copyright (c) 2022 Andreas Sandberg * Copyright (c) 2020 PHYTEC Messtechnik GmbH + * Copyright 2024 NXP * * SPDX-License-Identifier: Apache-2.0 */ @@ -10,7 +11,7 @@ #include #include #include -#include +#include #include #include "uc81xx_regs.h" @@ -75,10 +76,9 @@ struct uc81xx_quirks { struct uc81xx_config { const struct uc81xx_quirks *quirks; - struct spi_dt_spec bus; - struct gpio_dt_spec dc_gpio; + const struct device *mipi_dev; + const struct mipi_dbi_config dbi_config; struct gpio_dt_spec busy_gpio; - struct gpio_dt_spec reset_gpio; uint16_t height; uint16_t width; @@ -110,39 +110,13 @@ static inline int uc81xx_write_cmd(const struct device *dev, uint8_t cmd, const uint8_t *data, size_t len) { const struct uc81xx_config *config = dev->config; - struct spi_buf buf = {.buf = &cmd, .len = sizeof(cmd)}; - struct spi_buf_set buf_set = {.buffers = &buf, .count = 1}; int err; uc81xx_busy_wait(dev); - err = gpio_pin_set_dt(&config->dc_gpio, 1); - if (err < 0) { - return err; - } - - err = spi_write_dt(&config->bus, &buf_set); - if (err < 0) { - goto spi_out; - } - - if (data != NULL) { - buf.buf = (void *)data; - buf.len = len; - - err = gpio_pin_set_dt(&config->dc_gpio, 0); - if (err < 0) { - goto spi_out; - } - - err = spi_write_dt(&config->bus, &buf_set); - if (err < 0) { - goto spi_out; - } - } - -spi_out: - spi_release_dt(&config->bus); + err = mipi_dbi_command_write(config->mipi_dev, &config->dbi_config, + cmd, data, len); + mipi_dbi_release(config->mipi_dev, &config->dbi_config); return err; } @@ -151,43 +125,42 @@ static inline int uc81xx_write_cmd_pattern(const struct device *dev, uint8_t pattern, size_t len) { const struct uc81xx_config *config = dev->config; - struct spi_buf buf = {.buf = &cmd, .len = sizeof(cmd)}; - struct spi_buf_set buf_set = {.buffers = &buf, .count = 1}; + struct display_buffer_descriptor mipi_desc; int err; uint8_t data[64]; uc81xx_busy_wait(dev); - err = gpio_pin_set_dt(&config->dc_gpio, 1); + err = mipi_dbi_command_write(config->mipi_dev, &config->dbi_config, + cmd, NULL, 0); if (err < 0) { return err; } - err = spi_write_dt(&config->bus, &buf_set); - if (err < 0) { - goto spi_out; - } - - err = gpio_pin_set_dt(&config->dc_gpio, 0); - if (err < 0) { - goto spi_out; - } + /* + * MIPI display write API requires a display buffer descriptor. + * Create one that describes the buffer we are writing + */ + mipi_desc.height = 1; memset(data, pattern, sizeof(data)); while (len) { - buf.buf = data; - buf.len = MIN(len, sizeof(data)); + mipi_desc.buf_size = mipi_desc.width = mipi_desc.pitch = + MIN(len, sizeof(data)); - err = spi_write_dt(&config->bus, &buf_set); + err = mipi_dbi_write_display(config->mipi_dev, + &config->dbi_config, + data, &mipi_desc, + PIXEL_FORMAT_MONO10); if (err < 0) { - goto spi_out; + goto out; } - len -= buf.len; + len -= mipi_desc.buf_size; } -spi_out: - spi_release_dt(&config->bus); +out: + mipi_dbi_release(config->mipi_dev, &config->dbi_config); return err; } @@ -544,9 +517,7 @@ static int uc81xx_controller_init(const struct device *dev) const struct uc81xx_config *config = dev->config; struct uc81xx_data *data = dev->data; - gpio_pin_set_dt(&config->reset_gpio, 1); - k_sleep(K_MSEC(UC81XX_RESET_DELAY)); - gpio_pin_set_dt(&config->reset_gpio, 0); + mipi_dbi_reset(config->mipi_dev, UC81XX_RESET_DELAY); k_sleep(K_MSEC(UC81XX_RESET_DELAY)); uc81xx_busy_wait(dev); @@ -570,26 +541,11 @@ static int uc81xx_init(const struct device *dev) LOG_DBG(""); - if (!spi_is_ready_dt(&config->bus)) { - LOG_ERR("SPI bus %s not ready", config->bus.bus->name); - return -ENODEV; - } - - if (!gpio_is_ready_dt(&config->reset_gpio)) { - LOG_ERR("Reset GPIO device not ready"); - return -ENODEV; - } - - gpio_pin_configure_dt(&config->reset_gpio, GPIO_OUTPUT_INACTIVE); - - if (!gpio_is_ready_dt(&config->dc_gpio)) { - LOG_ERR("DC GPIO device not ready"); + if (!device_is_ready(config->mipi_dev)) { + LOG_ERR("MIPI device not ready"); return -ENODEV; } - gpio_pin_configure_dt(&config->dc_gpio, GPIO_OUTPUT_INACTIVE); - - if (!gpio_is_ready_dt(&config->busy_gpio)) { LOG_ERR("Busy GPIO device not ready"); return -ENODEV; @@ -816,12 +772,14 @@ static const struct display_driver_api uc81xx_driver_api = { \ static const struct uc81xx_config uc81xx_cfg_ ## n = { \ .quirks = quirks_ptr, \ - .bus = SPI_DT_SPEC_GET(n, \ - SPI_OP_MODE_MASTER | SPI_WORD_SET(8) | \ - SPI_LOCK_ON, \ - 0), \ - .reset_gpio = GPIO_DT_SPEC_GET(n, reset_gpios), \ - .dc_gpio = GPIO_DT_SPEC_GET(n, dc_gpios), \ + .mipi_dev = DEVICE_DT_GET(DT_PARENT(n)), \ + .dbi_config = { \ + .mode = MIPI_DBI_MODE_SPI_4WIRE, \ + .config = MIPI_DBI_SPI_CONFIG_DT(n, \ + SPI_OP_MODE_MASTER | \ + SPI_LOCK_ON | SPI_WORD_SET(8), \ + 0), \ + }, \ .busy_gpio = GPIO_DT_SPEC_GET(n, busy_gpios), \ \ .height = DT_PROP(n, height), \ diff --git a/dts/bindings/display/ultrachip,uc81xx-common.yaml b/dts/bindings/display/ultrachip,uc81xx-common.yaml index b2c8a4de35c13..20819d8c9fb01 100644 --- a/dts/bindings/display/ultrachip,uc81xx-common.yaml +++ b/dts/bindings/display/ultrachip,uc81xx-common.yaml @@ -1,30 +1,13 @@ # Copyright (c) 2022 Andreas Sandberg # Copyright (c) 2020, Phytec Messtechnik GmbH +# Copyright 2024 NXP # SPDX-License-Identifier: Apache-2.0 description: UltraChip UC81xx EPD display controller common properties -include: [spi-device.yaml, display-controller.yaml] +include: [mipi-dbi-spi-device.yaml, display-controller.yaml] properties: - reset-gpios: - type: phandle-array - required: true - description: RESET pin. - - The RESET pin of UC81xx is active low. - If connected directly the MCU pin should be configured - as active low. - - dc-gpios: - type: phandle-array - required: true - description: DC pin. - - The DC pin of UC81xx is active low (transmission command byte). - If connected directly the MCU pin should be configured - as active low. - busy-gpios: type: phandle-array required: true From 7714f8f87b063ab6f1d0ae3b33fad31106b5265a Mon Sep 17 00:00:00 2001 From: Daniel DeGrasse Date: Wed, 5 Jun 2024 14:18:18 -0500 Subject: [PATCH 2787/2849] tests: drivers: display: build_all: add uc81xx Add uc81xx to display build test Signed-off-by: Daniel DeGrasse --- tests/drivers/build_all/display/app.overlay | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/tests/drivers/build_all/display/app.overlay b/tests/drivers/build_all/display/app.overlay index 0ba2cb33f2c01..a30348fcf0dcf 100644 --- a/tests/drivers/build_all/display/app.overlay +++ b/tests/drivers/build_all/display/app.overlay @@ -107,6 +107,24 @@ height = <122>; busy-gpios = <&test_gpio 0 0>; }; + + uc8176_waveshare_epaper_gdew042t2: uc8176@5 { + compatible = "ultrachip,uc8176"; + mipi-max-frequency = <4000000>; + reg = <5>; + width = <400>; + height = <300>; + busy-gpios = <&test_gpio 0 0>; + + /* Arbirary settings */ + softstart = [17 17 17]; + + full { + pwr = [03 00 26 26 09]; + cdi = <0xd7>; + tcon = <0x22>; + }; + }; }; @@ -120,7 +138,7 @@ /* one entry for every devices at spi.dtsi */ cs-gpios = <&test_gpio 0 0 &test_gpio 0 1 &test_gpio 0 2 - &test_gpio 0 3 &test_gpio 0 4>; + &test_gpio 0 3 &test_gpio 0 4 &test_gpio 0 5>; test_spi_gc9x01x: gc9x01x@1 { compatible = "galaxycore,gc9x01x"; From 2c7cd3dc1e51603a49bae2d64c3df940d24f2f96 Mon Sep 17 00:00:00 2001 From: Daniel DeGrasse Date: Wed, 5 Jun 2024 14:58:10 -0500 Subject: [PATCH 2788/2849] doc: releases: migration-guide-3.7: add note for UC81xx displays Add note for UC81xx displays, which have been migrated to the MIPI DBI API. This note describes how to define the MIPI DBI wrapper device needed for the UC81xx display Signed-off-by: Daniel DeGrasse --- doc/releases/migration-guide-3.7.rst | 39 ++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/doc/releases/migration-guide-3.7.rst b/doc/releases/migration-guide-3.7.rst index 1223fcbc2b71c..4e9140c8f670d 100644 --- a/doc/releases/migration-guide-3.7.rst +++ b/doc/releases/migration-guide-3.7.rst @@ -355,6 +355,45 @@ Display }; }; +* UC81XX 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. (:github:`73812`) Note that the ``dc-gpios`` + pin has changed polarity with this update, for an example, see below: + + .. code-block:: devicetree + + /* Legacy UC81XX display definition */ + &spi0 { + uc8179: uc8179@0 { + compatible = "ultrachip,uc8179"; + reg = <0>; + spi-max-frequency = <4000000>; + reset-gpios = <&gpio0 6 GPIO_ACTIVE_LOW>; + dc-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>; + uc8179: uc8179@0 { + compatible = "ultrachip,uc8179"; + reg = <0>; + mipi-max-frequency = <4000000>; + ... + }; + }; * ST7789V based displays now use the MIPI DBI driver class. These displays must now be declared within a MIPI DBI driver wrapper device, which will From 2d171efcec3225e05a72e11e8f62728160c66ec2 Mon Sep 17 00:00:00 2001 From: Robert Hancock Date: Wed, 31 Jan 2024 15:12:39 -0600 Subject: [PATCH 2789/2849] drivers: sensors: Add driver for LM95234 temperature sensor Add a driver for the National/TI LM95234 Quad Remote Diode and Local Temperature Sensor with SMBus Interface and TruTherm Technology. Signed-off-by: Robert Hancock --- drivers/sensor/ti/CMakeLists.txt | 1 + drivers/sensor/ti/Kconfig | 1 + drivers/sensor/ti/lm95234/CMakeLists.txt | 5 + drivers/sensor/ti/lm95234/Kconfig | 13 + drivers/sensor/ti/lm95234/lm95234.c | 322 ++++++++++++++++++++++ dts/bindings/sensor/national,lm95234.yaml | 8 + include/zephyr/drivers/sensor/lm95234.h | 20 ++ tests/drivers/build_all/sensor/i2c.dtsi | 6 + 8 files changed, 376 insertions(+) create mode 100644 drivers/sensor/ti/lm95234/CMakeLists.txt create mode 100644 drivers/sensor/ti/lm95234/Kconfig create mode 100644 drivers/sensor/ti/lm95234/lm95234.c create mode 100644 dts/bindings/sensor/national,lm95234.yaml create mode 100644 include/zephyr/drivers/sensor/lm95234.h diff --git a/drivers/sensor/ti/CMakeLists.txt b/drivers/sensor/ti/CMakeLists.txt index 4af7aa8996d06..3ea219ad0bcb3 100644 --- a/drivers/sensor/ti/CMakeLists.txt +++ b/drivers/sensor/ti/CMakeLists.txt @@ -8,6 +8,7 @@ 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_LM95234 lm95234) add_subdirectory_ifdef(CONFIG_OPT3001 opt3001) add_subdirectory_ifdef(CONFIG_TI_HDC ti_hdc) add_subdirectory_ifdef(CONFIG_TI_HDC20XX ti_hdc20xx) diff --git a/drivers/sensor/ti/Kconfig b/drivers/sensor/ti/Kconfig index 02c5a6e9780fe..00f6de6a94a46 100644 --- a/drivers/sensor/ti/Kconfig +++ b/drivers/sensor/ti/Kconfig @@ -8,6 +8,7 @@ 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/lm95234/Kconfig" source "drivers/sensor/ti/opt3001/Kconfig" source "drivers/sensor/ti/ti_hdc/Kconfig" source "drivers/sensor/ti/ti_hdc20xx/Kconfig" diff --git a/drivers/sensor/ti/lm95234/CMakeLists.txt b/drivers/sensor/ti/lm95234/CMakeLists.txt new file mode 100644 index 0000000000000..1eeeec6132b4d --- /dev/null +++ b/drivers/sensor/ti/lm95234/CMakeLists.txt @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: Apache-2.0 + +zephyr_library() + +zephyr_library_sources(lm95234.c) diff --git a/drivers/sensor/ti/lm95234/Kconfig b/drivers/sensor/ti/lm95234/Kconfig new file mode 100644 index 0000000000000..e7e8528405d03 --- /dev/null +++ b/drivers/sensor/ti/lm95234/Kconfig @@ -0,0 +1,13 @@ +# LM95234 temperature sensor config + +# Copyright (c) 2024 Calian Advanced Technologies +# SPDX-License-Identifier: Apache-2.0 + +config LM95234 + bool "LM95234 Temperature Sensor" + default y + depends on DT_HAS_NATIONAL_LM95234_ENABLED + select I2C + help + Enable the driver for the LM95234 Quad Remote Diode and Local + Temperature Sensor with SMBus Interface. diff --git a/drivers/sensor/ti/lm95234/lm95234.c b/drivers/sensor/ti/lm95234/lm95234.c new file mode 100644 index 0000000000000..9beabc6da28d5 --- /dev/null +++ b/drivers/sensor/ti/lm95234/lm95234.c @@ -0,0 +1,322 @@ +/* + * Copyright (c) 2024 Calian Advanced Technologies + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT national_lm95234 + +#include +#include +#include +#include +#include +#include +#include +#include + +LOG_MODULE_REGISTER(LM95234, CONFIG_SENSOR_LOG_LEVEL); + +#define LM95234_REG_LOCAL_TEMP_SIGNED_MSB 0x10 +#define LM95234_REG_LOCAL_TEMP_SIGNED_LSB 0x20 +#define LM95234_REG_REMOTE_TEMP_1_SIGNED_MSB 0x11 +#define LM95234_REG_REMOTE_TEMP_1_SIGNED_LSB 0x21 +#define LM95234_REG_REMOTE_TEMP_2_SIGNED_MSB 0x12 +#define LM95234_REG_REMOTE_TEMP_2_SIGNED_LSB 0x22 +#define LM95234_REG_REMOTE_TEMP_3_SIGNED_MSB 0x13 +#define LM95234_REG_REMOTE_TEMP_3_SIGNED_LSB 0x23 +#define LM95234_REG_REMOTE_TEMP_4_SIGNED_MSB 0x14 +#define LM95234_REG_REMOTE_TEMP_4_SIGNED_LSB 0x24 +#define LM95234_REG_REMOTE_TEMP_1_UNSIGNED_MSB 0x19 +#define LM95234_REG_REMOTE_TEMP_1_UNSIGNED_LSB 0x29 +#define LM95234_REG_REMOTE_TEMP_2_UNSIGNED_MSB 0x1a +#define LM95234_REG_REMOTE_TEMP_2_UNSIGNED_LSB 0x2a +#define LM95234_REG_REMOTE_TEMP_3_UNSIGNED_MSB 0x1b +#define LM95234_REG_REMOTE_TEMP_3_UNSIGNED_LSB 0x2b +#define LM95234_REG_REMOTE_TEMP_4_UNSIGNED_MSB 0x1c +#define LM95234_REG_REMOTE_TEMP_4_UNSIGNED_LSB 0x2c +#define LM95234_REG_DIODE_MODEL_SELECT 0x30 +#define LM95234_REG_REMOTE_1_OFFSET 0x31 +#define LM95234_REG_REMOTE_2_OFFSET 0x32 +#define LM95234_REG_REMOTE_3_OFFSET 0x33 +#define LM95234_REG_REMOTE_4_OFFSET 0x34 +#define LM95234_REG_CONFIG 0x03 +#define LM95234_REG_CONV_RATE 0x04 +#define LM95234_REG_CHANNEL_CONV_ENABLE 0x05 +#define LM95234_REG_FILTER_SETTING 0x06 +#define LM95234_REG_ONESHOT 0x0f +#define LM95234_REG_COMMON_STATUS 0x02 +#define LM95234_REG_STATUS_1 0x07 +#define LM95234_REG_STATUS_2 0x08 +#define LM95234_REG_STATUS_3 0x09 +#define LM95234_REG_STATUS_4 0x0a +#define LM95234_REG_DIODE_MODEL_STATUS 0x38 +#define LM95234_REG_TCRIT1_MASK 0x0c +#define LM95234_REG_TCRIT2_MASK 0x0d +#define LM95234_REG_TCRIT3_MASK 0x0e +#define LM95234_REG_LOCAL_TCRIT_LIMIT 0x40 +#define LM95234_REG_REMOTE1_TCRIT1_LIMIT 0x41 +#define LM95234_REG_REMOTE2_TCRIT1_LIMIT 0x42 +#define LM95234_REG_REMOTE3_TCRIT_LIMIT 0x43 +#define LM95234_REG_REMOTE4_TCRIT_LIMIT 0x44 +#define LM95234_REG_REMOTE1_TCRIT23_LIMIT 0x49 +#define LM95234_REG_REMOTE2_TCRIT23_LIMIT 0x4a +#define LM95234_REG_COMMON_TCRIT_HYSTERESIS 0x5a +#define LM95234_REG_MANUF_ID 0xfe +#define LM95234_REG_REV_ID 0xff + +#define LM95234_MAN_ID 0x01 +#define LM95234_CHIP_ID 0x79 + +#define LM95234_CONFIG_STANDBY BIT(6) + +struct lm95234_data { + /** Temperatures in raw format read from sensor */ + int32_t local; + int32_t remote[4]; +}; + +struct lm95234_config { + struct i2c_dt_spec i2c; +}; + +static inline int lm95234_fetch_temp(const struct lm95234_config *cfg, struct lm95234_data *data, + enum sensor_channel chan, int32_t *output) +{ + int ret; + uint8_t val; + int32_t result = 0; + + if (chan != SENSOR_CHAN_AMBIENT_TEMP) { + uint16_t temp; + int offset = (chan - SENSOR_CHAN_LM95234_REMOTE_TEMP_1); + + ret = i2c_reg_read_byte_dt(&cfg->i2c, + LM95234_REG_REMOTE_TEMP_1_UNSIGNED_MSB + offset, &val); + if (ret) { + return ret; + } + temp = val << 8; + ret = i2c_reg_read_byte_dt(&cfg->i2c, + LM95234_REG_REMOTE_TEMP_1_UNSIGNED_LSB + offset, &val); + if (ret) { + return ret; + } + temp |= val; + result = temp; + } + + /* Read signed temperature if unsigned temperature is 0, or for local sensor */ + if (chan == SENSOR_CHAN_AMBIENT_TEMP || result == 0) { + int offset = chan == SENSOR_CHAN_AMBIENT_TEMP ? 0 : + (chan - SENSOR_CHAN_LM95234_REMOTE_TEMP_1 + 1); + int16_t temp; + + ret = i2c_reg_read_byte_dt(&cfg->i2c, + LM95234_REG_LOCAL_TEMP_SIGNED_MSB + offset, &val); + if (ret) { + return ret; + } + temp = val << 8; + ret = i2c_reg_read_byte_dt(&cfg->i2c, + LM95234_REG_LOCAL_TEMP_SIGNED_LSB + offset, &val); + if (ret) { + return ret; + } + temp |= val; + result = temp; + } + *output = result; + return 0; +} + +static int lm95234_sample_fetch(const struct device *dev, + enum sensor_channel chan) +{ + struct lm95234_data *data = dev->data; + const struct lm95234_config *cfg = dev->config; + enum pm_device_state pm_state; + int ret; + + (void)pm_device_state_get(dev, &pm_state); + if (pm_state != PM_DEVICE_STATE_ACTIVE) { + ret = -EIO; + return ret; + } + + switch ((uint32_t)chan) { + case SENSOR_CHAN_ALL: + ret = lm95234_fetch_temp(cfg, data, SENSOR_CHAN_AMBIENT_TEMP, &data->local); + if (ret) + return ret; + for (int i = 0; i < ARRAY_SIZE(data->remote); i++) { + ret = lm95234_fetch_temp(cfg, data, + SENSOR_CHAN_LM95234_REMOTE_TEMP_1 + i, + &data->remote[i]); + if (ret) + return ret; + } + break; + case SENSOR_CHAN_AMBIENT_TEMP: + ret = lm95234_fetch_temp(cfg, data, chan, &data->local); + break; + case SENSOR_CHAN_LM95234_REMOTE_TEMP_1: + case SENSOR_CHAN_LM95234_REMOTE_TEMP_2: + case SENSOR_CHAN_LM95234_REMOTE_TEMP_3: + case SENSOR_CHAN_LM95234_REMOTE_TEMP_4: + ret = lm95234_fetch_temp(cfg, data, chan, + &data->remote[chan - SENSOR_CHAN_LM95234_REMOTE_TEMP_1]); + break; + default: + ret = -ENOTSUP; + break; + } + + return ret; +} + +static int lm95234_channel_get(const struct device *dev, + enum sensor_channel chan, + struct sensor_value *val) +{ + struct lm95234_data *data = dev->data; + int32_t raw_temp; + + switch ((uint32_t)chan) { + case SENSOR_CHAN_AMBIENT_TEMP: + raw_temp = data->local; + break; + case SENSOR_CHAN_LM95234_REMOTE_TEMP_1: + case SENSOR_CHAN_LM95234_REMOTE_TEMP_2: + case SENSOR_CHAN_LM95234_REMOTE_TEMP_3: + case SENSOR_CHAN_LM95234_REMOTE_TEMP_4: + raw_temp = data->remote[chan - SENSOR_CHAN_LM95234_REMOTE_TEMP_1]; + break; + default: + return -ENOTSUP; + } + + /* Raw data format is 8 bits integer, 5 bits fractional, 3 bits zero */ + val->val1 = raw_temp / 256; + val->val2 = (raw_temp % 256) * 1000000 / 256; + return 0; +} + +static const struct sensor_driver_api lm95234_driver_api = { + .sample_fetch = lm95234_sample_fetch, + .channel_get = lm95234_channel_get, +}; + +static int lm95234_init(const struct device *dev) +{ + const struct lm95234_config *cfg = dev->config; + int ret = 0; + uint8_t value, model_select, model_status; + + if (!i2c_is_ready_dt(&cfg->i2c)) { + LOG_ERR("I2C dev not ready"); + return -ENODEV; + } + + ret = i2c_reg_read_byte_dt(&cfg->i2c, LM95234_REG_MANUF_ID, &value); + if (ret) { + LOG_ERR("Could not read manufacturer ID: %d", ret); + return ret; + } + if (value != LM95234_MAN_ID) { + LOG_ERR("Invalid manufacturer ID: %02x", value); + return -ENODEV; + } + ret = i2c_reg_read_byte_dt(&cfg->i2c, LM95234_REG_REV_ID, &value); + if (ret) { + LOG_ERR("Could not read revision ID: %d", ret); + return ret; + } + if (value != LM95234_CHIP_ID) { + LOG_ERR("Invalid chip ID: %02x", value); + return -ENODEV; + } + ret = i2c_reg_read_byte_dt(&cfg->i2c, LM95234_REG_CONFIG, &value); + if (ret) { + LOG_ERR("Could not read config: %d", ret); + return ret; + } + if (value & LM95234_CONFIG_STANDBY) { + value &= ~LM95234_CONFIG_STANDBY; + ret = i2c_reg_write_byte_dt(&cfg->i2c, LM95234_REG_CONFIG, value); + if (ret) { + LOG_ERR("Could not write config: %d", ret); + return ret; + } + } + ret = i2c_reg_read_byte_dt(&cfg->i2c, LM95234_REG_DIODE_MODEL_SELECT, &model_select); + if (ret) { + LOG_ERR("Could not read diode model select: %d", ret); + return ret; + } + ret = i2c_reg_read_byte_dt(&cfg->i2c, LM95234_REG_DIODE_MODEL_STATUS, &model_status); + if (ret) { + LOG_ERR("Could not read diode model status: %d", ret); + return ret; + } + /** + * Check if any remote inputs have a 3904 transistor detected but are not configured + * as such. If so, configure them as 3904 transistors. + */ + if (model_select & model_status) { + model_select &= ~model_status; + ret = i2c_reg_write_byte_dt(&cfg->i2c, LM95234_REG_DIODE_MODEL_SELECT, + model_select); + if (ret) { + LOG_ERR("Could not write diode model select: %d", ret); + return ret; + } + } + +#ifdef CONFIG_PM_DEVICE_RUNTIME + pm_device_init_suspended(dev); + + ret = pm_device_runtime_enable(dev); + if (ret < 0 && ret != -ENOTSUP) { + LOG_ERR("Failed to enable runtime power management"); + return ret; + } +#endif + + return 0; +} + +#ifdef CONFIG_PM_DEVICE + +static int lm95234_pm_action(const struct device *dev, enum pm_device_action action) +{ + switch (action) { + case PM_DEVICE_ACTION_TURN_ON: + case PM_DEVICE_ACTION_RESUME: + case PM_DEVICE_ACTION_TURN_OFF: + case PM_DEVICE_ACTION_SUSPEND: + break; + default: + return -ENOTSUP; + } + + return 0; +} + +#endif + +#define LM95234_INST(inst) \ +static struct lm95234_data lm95234_data_##inst; \ +static const struct lm95234_config lm95234_config_##inst = { \ + .i2c = I2C_DT_SPEC_INST_GET(inst), \ +}; \ +PM_DEVICE_DT_INST_DEFINE(inst, lm95234_pm_action); \ +SENSOR_DEVICE_DT_INST_DEFINE(inst, lm95234_init, \ + PM_DEVICE_DT_INST_GET(inst), \ + &lm95234_data_##inst, \ + &lm95234_config_##inst, \ + POST_KERNEL, \ + CONFIG_SENSOR_INIT_PRIORITY, \ + &lm95234_driver_api); + +DT_INST_FOREACH_STATUS_OKAY(LM95234_INST) diff --git a/dts/bindings/sensor/national,lm95234.yaml b/dts/bindings/sensor/national,lm95234.yaml new file mode 100644 index 0000000000000..a13577aca8f06 --- /dev/null +++ b/dts/bindings/sensor/national,lm95234.yaml @@ -0,0 +1,8 @@ +# Copyright (c) 2024 Calian Advanced Technologies +# SPDX-License-Identifier: Apache-2.0 + +description: LM95234 Quad Remote Diode and Local Temperature Sensor with SMBus Interface + +compatible: "national,lm95234" + +include: [sensor-device.yaml, i2c-device.yaml] diff --git a/include/zephyr/drivers/sensor/lm95234.h b/include/zephyr/drivers/sensor/lm95234.h new file mode 100644 index 0000000000000..6d25ceee70489 --- /dev/null +++ b/include/zephyr/drivers/sensor/lm95234.h @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2024, Calian Advanced Technologies + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_DRIVERS_SENSOR_LM95234_H_ +#define ZEPHYR_INCLUDE_DRIVERS_SENSOR_LM95234_H_ + +#include + +enum sensor_channel_lm95234 { + /* External temperature inputs */ + SENSOR_CHAN_LM95234_REMOTE_TEMP_1 = SENSOR_CHAN_PRIV_START, + SENSOR_CHAN_LM95234_REMOTE_TEMP_2, + SENSOR_CHAN_LM95234_REMOTE_TEMP_3, + SENSOR_CHAN_LM95234_REMOTE_TEMP_4 +}; + +#endif /* ZEPHYR_INCLUDE_DRIVERS_SENSOR_LM95234_H_ */ diff --git a/tests/drivers/build_all/sensor/i2c.dtsi b/tests/drivers/build_all/sensor/i2c.dtsi index c1689a21ca9c2..08b5d8b72e199 100644 --- a/tests/drivers/build_all/sensor/i2c.dtsi +++ b/tests/drivers/build_all/sensor/i2c.dtsi @@ -1055,3 +1055,9 @@ test_i2c_shtc1: shtc1@8e { measure-mode = "low-power"; clock-stretching; }; + +test_i2c_lm95234: lm95234@8f { + compatible = "national,lm95234"; + reg = <0x8f>; + status = "okay"; +}; From 0b83a9b18c50876d5826634a2f702b627e0318c6 Mon Sep 17 00:00:00 2001 From: Francois Ramu Date: Fri, 29 Mar 2024 11:15:02 +0100 Subject: [PATCH 2790/2849] samples: subsys: task_wdt on the IWDG of the stm32f4 Run the sample on the IWDG of stm32f4 nucleo boards instead of WWDG because the APB1 prescaler cannot set the WWDG input clock source to match the wd timeout. Signed-off-by: Francois Ramu --- .../task_wdt/boards/nucleo_f401re.overlay | 19 +++++++++++++++++++ .../task_wdt/boards/nucleo_f411re.overlay | 19 +++++++++++++++++++ 2 files changed, 38 insertions(+) create mode 100644 samples/subsys/task_wdt/boards/nucleo_f401re.overlay create mode 100644 samples/subsys/task_wdt/boards/nucleo_f411re.overlay diff --git a/samples/subsys/task_wdt/boards/nucleo_f401re.overlay b/samples/subsys/task_wdt/boards/nucleo_f401re.overlay new file mode 100644 index 0000000000000..c1f68c375f65a --- /dev/null +++ b/samples/subsys/task_wdt/boards/nucleo_f401re.overlay @@ -0,0 +1,19 @@ +/* + * Copyright 2024 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* + * stm32F4 has a WWDG clock by APB1 where the APB1 prescaler is 1..16 + * this is too low to configure the WWDG clock for this sample. + * Thus, use the IWDG instead for running this sample. + */ + +&wwdg { + status = "disabled"; +}; + +&iwdg { + status = "okay"; +}; diff --git a/samples/subsys/task_wdt/boards/nucleo_f411re.overlay b/samples/subsys/task_wdt/boards/nucleo_f411re.overlay new file mode 100644 index 0000000000000..c1f68c375f65a --- /dev/null +++ b/samples/subsys/task_wdt/boards/nucleo_f411re.overlay @@ -0,0 +1,19 @@ +/* + * Copyright 2024 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* + * stm32F4 has a WWDG clock by APB1 where the APB1 prescaler is 1..16 + * this is too low to configure the WWDG clock for this sample. + * Thus, use the IWDG instead for running this sample. + */ + +&wwdg { + status = "disabled"; +}; + +&iwdg { + status = "okay"; +}; From 3edd5a9070d2067fdcc37c12ed0555374c038c38 Mon Sep 17 00:00:00 2001 From: Dawid Niedzwiecki Date: Fri, 14 Jun 2024 13:20:40 +0200 Subject: [PATCH 2791/2849] board: google_dragonclaw: add supported features Add the list of supported features to the google_dragonclaw board definition. It allows running more tests. Signed-off-by: Dawid Niedzwiecki --- boards/google/dragonclaw/google_dragonclaw.yaml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/boards/google/dragonclaw/google_dragonclaw.yaml b/boards/google/dragonclaw/google_dragonclaw.yaml index ddb4f3a77133a..bf535af2c1e63 100644 --- a/boards/google/dragonclaw/google_dragonclaw.yaml +++ b/boards/google/dragonclaw/google_dragonclaw.yaml @@ -9,3 +9,11 @@ toolchain: ram: 256 flash: 1024 vendor: google +supported: + - counter + - dma + - gpio + - i2c + - spi + - pwm + - rtc From 252ca99d0cfcbc5682c8c6dc70b839956a47d19d Mon Sep 17 00:00:00 2001 From: Anas Nashif Date: Fri, 14 Jun 2024 10:27:45 -0400 Subject: [PATCH 2792/2849] ci: testplan: do not run tests on all platforms when a test changes With many tests having 10s or scenarios and variants, anytime we make a change to a test right now, we end up building all scenarios on all platforms which ends up in multiple 10s of the thousands of instances that need to run on 30 or 40 runners blocking CI for hours. We do not really need that, a test needs to be smart about its coverage and not rely on boiling the ocean to catch, mostly build errors that are platform specific. Change this to do the normal coverage we get on push events. Signed-off-by: Anas Nashif --- scripts/ci/test_plan.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/scripts/ci/test_plan.py b/scripts/ci/test_plan.py index 54ead52819594..fba031e574f63 100755 --- a/scripts/ci/test_plan.py +++ b/scripts/ci/test_plan.py @@ -313,8 +313,6 @@ def find_tests(self): if self.platforms: for platform in self.platforms: _options.extend(["-p", platform]) - else: - _options.append("--all") self.get_plan(_options, use_testsuite_root=False) def find_tags(self): From 1a95246f61285357dfa2458e5470814b0ab5803e Mon Sep 17 00:00:00 2001 From: Chris Friedt Date: Wed, 5 Jun 2024 11:23:41 -0400 Subject: [PATCH 2793/2849] posix: features: correct typo _POSIX_XOPEN_STREAMS An invalid feature test macro was found in in sysconf.h . It should be corrected from _POSIX_XOPEN_STREAMS to _XOPEN_STREAMS. Signed-off-by: Chris Friedt --- include/zephyr/posix/sys/sysconf.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/zephyr/posix/sys/sysconf.h b/include/zephyr/posix/sys/sysconf.h index f53d598ac0ba6..201db45e4008e 100644 --- a/include/zephyr/posix/sys/sysconf.h +++ b/include/zephyr/posix/sys/sysconf.h @@ -252,7 +252,7 @@ enum { #define __z_posix_sysconf_SC_XOPEN_REALTIME_THREADS (-1L) #define __z_posix_sysconf_SC_XOPEN_SHM (-1L) #define __z_posix_sysconf_SC_XOPEN_STREAMS \ - COND_CODE_1(CONFIG_XOPEN_STREAMS, (_POSIX_XOPEN_STREAMS), (-1)) + COND_CODE_1(CONFIG_XOPEN_STREAMS, (_XOPEN_STREAMS), (-1)) #define __z_posix_sysconf_SC_XOPEN_UNIX (-1L) #define __z_posix_sysconf_SC_XOPEN_UUCP (-1L) #define __z_posix_sysconf_SC_XOPEN_VERSION _XOPEN_VERSION From 1f9ca63b936964f44f58137e47a9580027f634df Mon Sep 17 00:00:00 2001 From: Chris Friedt Date: Sat, 8 Jun 2024 08:39:56 -0400 Subject: [PATCH 2794/2849] posix: fs: implement fstat() via zvfs_fstat() Route the fstat() call (part of POSIX_FILE_SYSTEM) to zvfs_fstat() so that other types of file descriptors can also supply file status information. Signed-off-by: Chris Friedt --- include/zephyr/sys/fdtable.h | 1 + lib/os/fdtable.c | 13 ++++++++++++- lib/posix/options/fs.c | 8 +++----- 3 files changed, 16 insertions(+), 6 deletions(-) diff --git a/include/zephyr/sys/fdtable.h b/include/zephyr/sys/fdtable.h index bd5e70813d5e4..1e9a91181a904 100644 --- a/include/zephyr/sys/fdtable.h +++ b/include/zephyr/sys/fdtable.h @@ -166,6 +166,7 @@ enum { ZFD_IOCTL_POLL_UPDATE, ZFD_IOCTL_POLL_OFFLOAD, ZFD_IOCTL_SET_LOCK, + ZFD_IOCTL_STAT, /* Codes above 0x5400 and below 0x5500 are reserved for termios, FIO, etc */ ZFD_IOCTL_FIONREAD = 0x541B, diff --git a/lib/os/fdtable.c b/lib/os/fdtable.c index 9343936e6deaf..fd7f59d30f0dd 100644 --- a/lib/os/fdtable.c +++ b/lib/os/fdtable.c @@ -16,13 +16,15 @@ #include #include -#include #include +#include #include #include #include #include +struct stat; + struct fd_entry { void *obj; const struct fd_op_vtable *vtable; @@ -349,6 +351,15 @@ int zvfs_close(int fd) return res; } +int zvfs_fstat(int fd, struct stat *buf) +{ + if (_check_fd(fd) < 0) { + return -1; + } + + return z_fdtable_call_ioctl(fdtable[fd].vtable, fdtable[fd].obj, ZFD_IOCTL_STAT, buf); +} + int zvfs_fsync(int fd) { if (_check_fd(fd) < 0) { diff --git a/lib/posix/options/fs.c b/lib/posix/options/fs.c index 6a572c278f4dd..e8a0f83605c34 100644 --- a/lib/posix/options/fs.c +++ b/lib/posix/options/fs.c @@ -15,6 +15,8 @@ #include #include +int zvfs_fstat(int fd, struct stat *buf); + BUILD_ASSERT(PATH_MAX >= MAX_FILE_NAME, "PATH_MAX is less than MAX_FILE_NAME"); struct posix_fs_desc { @@ -432,11 +434,7 @@ int zvfs_ftruncate(int fd, off_t length) int fstat(int fildes, struct stat *buf) { - ARG_UNUSED(fildes); - ARG_UNUSED(buf); - - errno = ENOTSUP; - return -1; + return zvfs_fstat(fildes, buf); } #ifdef CONFIG_POSIX_FILE_SYSTEM_ALIAS_FSTAT FUNC_ALIAS(fstat, _fstat, int); From 65020f5b1f6f9e78e6c357e57b179a9afbfd6933 Mon Sep 17 00:00:00 2001 From: Chris Friedt Date: Sat, 8 Jun 2024 16:15:56 -0400 Subject: [PATCH 2795/2849] doc: posix: mark fstat() as implemented The fstat() function is implemented as part of the POSIX_FILE_SYSTEM Option Group, but it is implemented through zvfs, as an ioctl, which allows other file descriptor types to support queries of file descriptor status. Signed-off-by: Chris Friedt --- doc/services/portability/posix/option_groups/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/services/portability/posix/option_groups/index.rst b/doc/services/portability/posix/option_groups/index.rst index 980732c4612b3..b1b588956f621 100644 --- a/doc/services/portability/posix/option_groups/index.rst +++ b/doc/services/portability/posix/option_groups/index.rst @@ -368,7 +368,7 @@ POSIX_FILE_SYSTEM creat(), fchdir(), fpathconf(), - fstat(), + fstat(), yes fstatvfs(), getcwd(), link(), From 50fc010f0f9082c3bc376c80c796b0d582201d8f Mon Sep 17 00:00:00 2001 From: Chris Friedt Date: Wed, 5 Jun 2024 12:33:06 -0400 Subject: [PATCH 2796/2849] posix + fdtable: move zvfs_ftruncate() to fdtable.c Move the zvfs_ftruncate() call from fs.c to fdtable.c, as file types other than regular files can also be truncated. Instead of hard-wiring zvfs_ftruncate() to fs_truncate(), add a new ZVFS_IOCTL_TRUNCATE so that the operation can be handled with other ioctl() operations. Signed-off-by: Chris Friedt --- include/zephyr/sys/fdtable.h | 1 + lib/os/fdtable.c | 27 ++++++++++++++++++++++++++- lib/posix/options/fs.c | 33 +++++++++++---------------------- 3 files changed, 38 insertions(+), 23 deletions(-) diff --git a/include/zephyr/sys/fdtable.h b/include/zephyr/sys/fdtable.h index 1e9a91181a904..f8d65e5487bd6 100644 --- a/include/zephyr/sys/fdtable.h +++ b/include/zephyr/sys/fdtable.h @@ -167,6 +167,7 @@ enum { ZFD_IOCTL_POLL_OFFLOAD, ZFD_IOCTL_SET_LOCK, ZFD_IOCTL_STAT, + ZFD_IOCTL_TRUNCATE, /* Codes above 0x5400 and below 0x5500 are reserved for termios, FIO, etc */ ZFD_IOCTL_FIONREAD = 0x541B, diff --git a/lib/os/fdtable.c b/lib/os/fdtable.c index fd7f59d30f0dd..6d1f87bbc6f33 100644 --- a/lib/os/fdtable.c +++ b/lib/os/fdtable.c @@ -16,8 +16,8 @@ #include #include -#include #include +#include #include #include #include @@ -409,6 +409,31 @@ int zvfs_fcntl(int fd, int cmd, va_list args) return res; } +static inline int zvfs_ftruncate_wrap(int fd, int cmd, ...) +{ + int res; + va_list args; + + __ASSERT_NO_MSG(fd < ARRAY_SIZE(fdtable)); + + (void)k_mutex_lock(&fdtable[fd].lock, K_FOREVER); + va_start(args, cmd); + res = fdtable[fd].vtable->ioctl(fdtable[fd].obj, cmd, args); + va_end(args); + k_mutex_unlock(&fdtable[fd].lock); + + return res; +} + +int zvfs_ftruncate(int fd, off_t length) +{ + if (_check_fd(fd) < 0) { + return -1; + } + + return zvfs_ftruncate_wrap(fd, ZFD_IOCTL_TRUNCATE, length); +} + #if defined(CONFIG_POSIX_DEVICE_IO) /* * fd operations for stdio/stdout/stderr diff --git a/lib/posix/options/fs.c b/lib/posix/options/fs.c index e8a0f83605c34..4d7f6d8301283 100644 --- a/lib/posix/options/fs.c +++ b/lib/posix/options/fs.c @@ -154,7 +154,18 @@ static int fs_ioctl_vmeth(void *obj, unsigned int request, va_list args) } break; } + case ZFD_IOCTL_TRUNCATE: { + off_t length; + length = va_arg(args, off_t); + + rc = fs_truncate(&ptr->file, length); + if (rc < 0) { + errno = -rc; + return -1; + } + break; + } default: errno = EOPNOTSUPP; return -1; @@ -410,28 +421,6 @@ int mkdir(const char *path, mode_t mode) return 0; } -/** - * @brief Truncate file to specified length. - * - */ -int zvfs_ftruncate(int fd, off_t length) -{ - int rc; - struct posix_fs_desc *ptr = NULL; - - ptr = z_get_fd_obj(fd, NULL, EBADF); - if (!ptr) - return -1; - - rc = fs_truncate(&ptr->file, length); - if (rc < 0) { - errno = -rc; - return -1; - } - - return 0; -} - int fstat(int fildes, struct stat *buf) { return zvfs_fstat(fildes, buf); From 156eaab70e648238fcc1974cdea89cf45ebd3f77 Mon Sep 17 00:00:00 2001 From: Chris Friedt Date: Wed, 5 Jun 2024 13:12:11 -0400 Subject: [PATCH 2797/2849] posix: move ioctl() from fdtable to posix The ioctl() call should be a part of the _XOPEN_STREAMS Option in posix, so move it there. Create a zephyr-native zvfs_ioctl() in the layer below. Signed-off-by: Chris Friedt --- lib/os/fdtable.c | 26 ++++++++------------ lib/posix/options/stropts.c | 18 +++++++++++++- samples/modules/thrift/hello/client/prj.conf | 1 + samples/modules/thrift/hello/server/prj.conf | 1 + tests/modules/thrift/ThriftTest/prj.conf | 1 + tests/posix/eventfd/prj.conf | 1 + 6 files changed, 31 insertions(+), 17 deletions(-) diff --git a/lib/os/fdtable.c b/lib/os/fdtable.c index 6d1f87bbc6f33..6adb57696cdb5 100644 --- a/lib/os/fdtable.c +++ b/lib/os/fdtable.c @@ -379,22 +379,6 @@ off_t zvfs_lseek(int fd, off_t offset, int whence) whence); } -int ioctl(int fd, unsigned long request, ...) -{ - va_list args; - int res; - - if (_check_fd(fd) < 0) { - return -1; - } - - va_start(args, request); - res = fdtable[fd].vtable->ioctl(fdtable[fd].obj, request, args); - va_end(args); - - return res; -} - int zvfs_fcntl(int fd, int cmd, va_list args) { int res; @@ -434,6 +418,16 @@ int zvfs_ftruncate(int fd, off_t length) return zvfs_ftruncate_wrap(fd, ZFD_IOCTL_TRUNCATE, length); } +int zvfs_ioctl(int fd, unsigned long request, va_list args) +{ + if (_check_fd(fd) < 0) { + return -1; + } + + return fdtable[fd].vtable->ioctl(fdtable[fd].obj, request, args); +} + + #if defined(CONFIG_POSIX_DEVICE_IO) /* * fd operations for stdio/stdout/stderr diff --git a/lib/posix/options/stropts.c b/lib/posix/options/stropts.c index dab6ea976855c..61d5e6abf5d68 100644 --- a/lib/posix/options/stropts.c +++ b/lib/posix/options/stropts.c @@ -4,9 +4,11 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include #include +#include + #include +#include int putmsg(int fildes, const struct strbuf *ctlptr, const struct strbuf *dataptr, int flags) { @@ -79,3 +81,17 @@ int isastream(int fildes) errno = ENOSYS; return -1; } + +extern int zvfs_ioctl(int fd, unsigned long request, va_list args); + +int ioctl(int fd, unsigned long request, ...) +{ + int ret; + va_list args; + + va_start(args, request); + ret = zvfs_ioctl(fd, request, args); + va_end(args); + + return ret; +} diff --git a/samples/modules/thrift/hello/client/prj.conf b/samples/modules/thrift/hello/client/prj.conf index 0f094d14d6c2e..c8ac179680b18 100644 --- a/samples/modules/thrift/hello/client/prj.conf +++ b/samples/modules/thrift/hello/client/prj.conf @@ -6,6 +6,7 @@ CONFIG_CPP=y CONFIG_STD_CPP17=y CONFIG_CPP_EXCEPTIONS=y CONFIG_POSIX_API=y +CONFIG_XOPEN_STREAMS=y CONFIG_COMMON_LIBC_THRD=y CONFIG_DYNAMIC_THREAD=y CONFIG_THREAD_STACK_INFO=y diff --git a/samples/modules/thrift/hello/server/prj.conf b/samples/modules/thrift/hello/server/prj.conf index fe78b9a2803a5..78b009fb3e285 100644 --- a/samples/modules/thrift/hello/server/prj.conf +++ b/samples/modules/thrift/hello/server/prj.conf @@ -6,6 +6,7 @@ CONFIG_CPP=y CONFIG_STD_CPP17=y CONFIG_CPP_EXCEPTIONS=y CONFIG_POSIX_API=y +CONFIG_XOPEN_STREAMS=y CONFIG_NET_SOCKETPAIR=y CONFIG_HEAP_MEM_POOL_SIZE=16384 CONFIG_EVENTFD=y diff --git a/tests/modules/thrift/ThriftTest/prj.conf b/tests/modules/thrift/ThriftTest/prj.conf index 80872a61085f0..4bc7153026a10 100755 --- a/tests/modules/thrift/ThriftTest/prj.conf +++ b/tests/modules/thrift/ThriftTest/prj.conf @@ -7,6 +7,7 @@ CONFIG_STD_CPP17=y CONFIG_CPP_EXCEPTIONS=y CONFIG_GLIBCXX_LIBCPP=y CONFIG_POSIX_API=y +CONFIG_XOPEN_STREAMS=y CONFIG_NETWORKING=y CONFIG_NET_TCP=y CONFIG_NET_SOCKETS=y diff --git a/tests/posix/eventfd/prj.conf b/tests/posix/eventfd/prj.conf index 4fcab370408b9..a5839a7a447a7 100644 --- a/tests/posix/eventfd/prj.conf +++ b/tests/posix/eventfd/prj.conf @@ -9,4 +9,5 @@ CONFIG_TEST_RANDOM_GENERATOR=y CONFIG_ZTEST=y CONFIG_POSIX_API=y +CONFIG_XOPEN_STREAMS=y CONFIG_EVENTFD=y From 73394a83905ab135c527d9424a6c43926d86ba21 Mon Sep 17 00:00:00 2001 From: Chris Friedt Date: Fri, 31 May 2024 23:30:42 -0400 Subject: [PATCH 2798/2849] posix: add implementation of mmap(), msync(), and munmap() Add stubs for mmap(), msync(), and munmap() as required by the _POSIX_MAPPED_FILES Option and POSIX_MAPPED_FILES and Option Group of IEEE 1003.1-2017. Signed-off-by: Chris Friedt --- include/zephyr/posix/posix_features.h | 6 +- include/zephyr/posix/sys/mman.h | 43 +++++++++ include/zephyr/posix/sys/sysconf.h | 3 +- include/zephyr/sys/fdtable.h | 1 + lib/posix/options/CMakeLists.txt | 1 + lib/posix/options/Kconfig.mem | 15 +++ lib/posix/options/mmap.c | 128 ++++++++++++++++++++++++++ 7 files changed, 195 insertions(+), 2 deletions(-) create mode 100644 include/zephyr/posix/sys/mman.h create mode 100644 lib/posix/options/mmap.c diff --git a/include/zephyr/posix/posix_features.h b/include/zephyr/posix/posix_features.h index 5faadb66c05db..c4e122e9f7596 100644 --- a/include/zephyr/posix/posix_features.h +++ b/include/zephyr/posix/posix_features.h @@ -64,7 +64,11 @@ #endif /* #define _POSIX_JOB_CONTROL (-1L) */ -/* #define _POSIX_MAPPED_FILES (-1L) */ + +#ifdef CONFIG_POSIX_MAPPED_FILES +#define _POSIX_MAPPED_FILES _POSIX_VERSION +#endif + /* #define _POSIX_MEMLOCK (-1L) */ /* #define _POSIX_MEMLOCK_RANGE (-1L) */ /* #define _POSIX_MEMORY_PROTECTION (-1L) */ diff --git a/include/zephyr/posix/sys/mman.h b/include/zephyr/posix/sys/mman.h new file mode 100644 index 0000000000000..320d9d46cd235 --- /dev/null +++ b/include/zephyr/posix/sys/mman.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2024, Tenstorrent AI ULC + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_ZEPHYR_POSIX_SYS_MMAN_H_ +#define ZEPHYR_INCLUDE_ZEPHYR_POSIX_SYS_MMAN_H_ + +#include +#include + +#define PROT_NONE 0x0 +#define PROT_READ 0x1 +#define PROT_WRITE 0x2 +#define PROT_EXEC 0x4 + +#define MAP_SHARED 0x1 +#define MAP_PRIVATE 0x2 +#define MAP_FIXED 0x4 + +/* for Linux compatibility */ +#define MAP_ANONYMOUS 0x20 + +#define MS_SYNC 0x0 +#define MS_ASYNC 0x1 +#define MS_INVALIDATE 0x2 + +#define MAP_FAILED ((void *)-1) + +#ifdef __cplusplus +extern "C" { +#endif + +void *mmap(void *addr, size_t len, int prot, int flags, int fildes, off_t off); +int msync(void *addr, size_t length, int flags); +int munmap(void *addr, size_t len); + +#ifdef __cplusplus +} +#endif + +#endif /* ZEPHYR_INCLUDE_ZEPHYR_POSIX_SYS_MMAN_H_ */ diff --git a/include/zephyr/posix/sys/sysconf.h b/include/zephyr/posix/sys/sysconf.h index 201db45e4008e..43c2c2943a0a4 100644 --- a/include/zephyr/posix/sys/sysconf.h +++ b/include/zephyr/posix/sys/sysconf.h @@ -153,7 +153,8 @@ enum { COND_CODE_1(CONFIG_POSIX_FSYNC, (_POSIX_FSYNC), (-1L)) #define __z_posix_sysconf_SC_IPV6 COND_CODE_1(CONFIG_NET_IPV6, (_POSIX_IPV6), (-1L)) #define __z_posix_sysconf_SC_JOB_CONTROL (-1L) -#define __z_posix_sysconf_SC_MAPPED_FILES (-1L) +#define __z_posix_sysconf_SC_MAPPED_FILES \ + COND_CODE_1(CONFIG_POSIX_MAPPED_FILES, (_POSIX_MAPPED_FILES), (-1L)) #define __z_posix_sysconf_SC_MEMLOCK (-1L) #define __z_posix_sysconf_SC_MEMLOCK_RANGE (-1L) #define __z_posix_sysconf_SC_MEMORY_PROTECTION (-1L) diff --git a/include/zephyr/sys/fdtable.h b/include/zephyr/sys/fdtable.h index f8d65e5487bd6..4f68d7598ce65 100644 --- a/include/zephyr/sys/fdtable.h +++ b/include/zephyr/sys/fdtable.h @@ -168,6 +168,7 @@ enum { ZFD_IOCTL_SET_LOCK, ZFD_IOCTL_STAT, ZFD_IOCTL_TRUNCATE, + ZFD_IOCTL_MMAP, /* Codes above 0x5400 and below 0x5500 are reserved for termios, FIO, etc */ ZFD_IOCTL_FIONREAD = 0x541B, diff --git a/lib/posix/options/CMakeLists.txt b/lib/posix/options/CMakeLists.txt index b4981a62eace1..a11e440b3e71c 100644 --- a/lib/posix/options/CMakeLists.txt +++ b/lib/posix/options/CMakeLists.txt @@ -51,6 +51,7 @@ zephyr_library_sources_ifdef(CONFIG_POSIX_FD_MGMT ) zephyr_library_sources_ifdef(CONFIG_POSIX_FILE_SYSTEM fs.c) zephyr_library_sources_ifdef(CONFIG_POSIX_FSYNC fsync.c) +zephyr_library_sources_ifdef(CONFIG_POSIX_MAPPED_FILES mmap.c) zephyr_library_sources_ifdef(CONFIG_POSIX_MESSAGE_PASSING mqueue.c) zephyr_library_sources_ifdef(CONFIG_POSIX_MULTI_PROCESS sleep.c diff --git a/lib/posix/options/Kconfig.mem b/lib/posix/options/Kconfig.mem index 5a5783340919d..7f0140fd1b1e3 100644 --- a/lib/posix/options/Kconfig.mem +++ b/lib/posix/options/Kconfig.mem @@ -2,6 +2,8 @@ # # SPDX-License-Identifier: Apache-2.0 +menu "POSIX memory" + config POSIX_PAGE_SIZE_BITS int "Number of bits to use for PAGE_SIZE" range 6 16 @@ -11,3 +13,16 @@ config POSIX_PAGE_SIZE_BITS Define PAGE_SIZE as BIT(n), where n is the value configured here. PAGE_SIZE is supported in the range [64, 65536] If CONFIG_POSIX_API=y, PAGE_SIZE defaults to 4096, otherwise, it is 64 bytes. + +config POSIX_MAPPED_FILES + bool "POSIX memory-mapped files [EXPERIMENTAL]" + select EXPERIMENTAL + imply MMU + help + Select 'y' here and Zephyr will provide support for mmap(), msync(), and munmap(). + + For more information, please see + https://pubs.opengroup.org/onlinepubs/9699919799.orig/functions/V2_chap02.html + https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_port.html#tag_24_03_04 + +endmenu diff --git a/lib/posix/options/mmap.c b/lib/posix/options/mmap.c new file mode 100644 index 0000000000000..dae56a960e860 --- /dev/null +++ b/lib/posix/options/mmap.c @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2024, Tenstorrent AI ULC + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#define _page_size COND_CODE_1(CONFIG_MMU, (CONFIG_MMU_PAGE_SIZE), (PAGE_SIZE)) + +int zvfs_ioctl(int fd, int cmd, va_list args); + +static int p2z(int prot, int pflags) +{ + bool rw = (prot & PROT_WRITE) != 0; + bool ex = (prot & PROT_EXEC) != 0; + bool fixed = (pflags & MAP_FIXED) != 0; + bool shared = (pflags & MAP_SHARED) != 0; + bool private = (pflags & MAP_PRIVATE) != 0; + + if (!(shared ^ private)) { + return -1; + } + + return (rw * K_MEM_PERM_RW) | (ex * K_MEM_PERM_EXEC) | (fixed * K_MEM_DIRECT_MAP); +} + +static inline int zvfs_ioctl_wrap(int fd, int cmd, ...) +{ + int ret; + va_list args; + + va_start(args, cmd); + ret = zvfs_ioctl(fd, cmd, args); + va_end(args); + + return ret; +} + +void *mmap(void *addr, size_t len, int prot, int flags, int fd, off_t off) +{ + void *virt; + uintptr_t phys; + int zflags = p2z(prot, flags); + + if ((len == 0) || (zflags == -1)) { + errno = EINVAL; + return MAP_FAILED; + } + + if ((flags & MAP_ANONYMOUS) != 0) { + /* force behaviour to be in-line with Linux, fd is ignored */ + fd = -1; + } + + if (fd > 0) { + /* non-anonymous mapping */ + virt = NULL; + if (zvfs_ioctl_wrap(fd, ZFD_IOCTL_MMAP, addr, len, prot, flags, off, &virt) < 0) { + return MAP_FAILED; + } + + return virt; + } + + if (!IS_ENABLED(CONFIG_MMU)) { + errno = ENOTSUP; + return MAP_FAILED; + } + + if ((flags & MAP_FIXED) == 0) { + /* anonymous mapping */ + virt = k_mem_map(len, zflags); + } else { + /* a physical mapping. Care should be taken not to map the same page twice */ + virt = NULL; + phys = POINTER_TO_UINT(addr); + k_mem_map_phys_bare((uint8_t **)&virt, phys, (size_t)ROUND_UP(len, _page_size), + zflags); + } + + if (virt == NULL) { + errno = ENOMEM; + return MAP_FAILED; + } + + return virt; +} + +int msync(void *addr, size_t length, int flags) +{ + ARG_UNUSED(addr); + ARG_UNUSED(length); + ARG_UNUSED(flags); + + return 0; +} + +int munmap(void *addr, size_t len) +{ + if (len == 0) { + errno = EINVAL; + return -1; + } + + if (!IS_ENABLED(CONFIG_MMU)) { + /* cannot munmap without an MPU */ + errno = ENOTSUP; + return -1; + } + + uintptr_t phys = 0; + + if (arch_page_phys_get(addr, &phys) == 0) { + k_mem_unmap(addr, ROUND_UP(len, _page_size)); + } + + return 0; +} From 510be57d7fb24e917c65cfa47ed89713ebca3c93 Mon Sep 17 00:00:00 2001 From: Chris Friedt Date: Fri, 31 May 2024 23:44:26 -0400 Subject: [PATCH 2799/2849] doc: posix: mark mapped files as supported Mark POSIX_MAPPED_FILES as supported. Signed-off-by: Chris Friedt --- .../portability/posix/conformance/index.rst | 2 +- .../portability/posix/option_groups/index.rst | 17 +++++++++++++++-- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/doc/services/portability/posix/conformance/index.rst b/doc/services/portability/posix/conformance/index.rst index 302bf4f6e71f3..93b11c7ae7bb5 100644 --- a/doc/services/portability/posix/conformance/index.rst +++ b/doc/services/portability/posix/conformance/index.rst @@ -36,7 +36,7 @@ POSIX System Interfaces :ref:`_POSIX_ASYNCHRONOUS_IO`, 200809L, :kconfig:option:`CONFIG_POSIX_ASYNCHRONOUS_IO`:ref:`†` :ref:`_POSIX_BARRIERS`, 200809L, :kconfig:option:`CONFIG_POSIX_BARRIERS` :ref:`_POSIX_CLOCK_SELECTION`, 200809L, :kconfig:option:`CONFIG_POSIX_CLOCK_SELECTION` - _POSIX_MAPPED_FILES, -1, :ref:`†` + :ref:`_POSIX_MAPPED_FILES`, 200809L, :kconfig:option:`CONFIG_POSIX_MAPPED_FILES` _POSIX_MEMORY_PROTECTION, -1, :ref:`†` :ref:`_POSIX_READER_WRITER_LOCKS`, 200809L, :kconfig:option:`CONFIG_POSIX_READER_WRITER_LOCKS` :ref:`_POSIX_REALTIME_SIGNALS`, -1, :kconfig:option:`CONFIG_POSIX_REALTIME_SIGNALS` diff --git a/doc/services/portability/posix/option_groups/index.rst b/doc/services/portability/posix/option_groups/index.rst index b1b588956f621..fd037d1d2fa68 100644 --- a/doc/services/portability/posix/option_groups/index.rst +++ b/doc/services/portability/posix/option_groups/index.rst @@ -389,6 +389,19 @@ POSIX_FILE_SYSTEM unlink(), yes utime(), +.. _posix_option_mapped_files: + +POSIX_MAPPED_FILES +================== + +.. csv-table:: POSIX_MAPPED_FILES + :header: API, Supported + :widths: 50,10 + + mmap(),yes + msync(),yes + munmap(),yes + .. _posix_option_group_networking: POSIX_NETWORKING @@ -757,8 +770,8 @@ _POSIX_SHARED_MEMORY_OBJECTS :header: API, Supported :widths: 50,10 - mmap(), - munmap(), + mmap(), yes + munmap(), yes shm_open(), shm_unlink(), From d949c9c8b8f892603486a7e983a30864ae2c3ece Mon Sep 17 00:00:00 2001 From: Chris Friedt Date: Sat, 1 Jun 2024 07:43:50 -0400 Subject: [PATCH 2800/2849] posix: add support for mlock() and munlock() Add support for mlock() and munlock(). These two functions comprise the _POSIX_MEMLOCK_RANGE Option which is required by PSE51, PSE52, PSE53, and PSE54. Signed-off-by: Chris Friedt --- include/zephyr/posix/posix_features.h | 6 +++++- include/zephyr/posix/sys/mman.h | 2 ++ include/zephyr/posix/sys/sysconf.h | 3 ++- lib/posix/options/CMakeLists.txt | 1 + lib/posix/options/Kconfig.mem | 16 ++++++++++++++++ lib/posix/options/mlock.c | 24 ++++++++++++++++++++++++ 6 files changed, 50 insertions(+), 2 deletions(-) create mode 100644 lib/posix/options/mlock.c diff --git a/include/zephyr/posix/posix_features.h b/include/zephyr/posix/posix_features.h index c4e122e9f7596..2c07173218151 100644 --- a/include/zephyr/posix/posix_features.h +++ b/include/zephyr/posix/posix_features.h @@ -70,7 +70,11 @@ #endif /* #define _POSIX_MEMLOCK (-1L) */ -/* #define _POSIX_MEMLOCK_RANGE (-1L) */ + +#ifdef CONFIG_POSIX_MEMLOCK_RANGE +#define _POSIX_MEMLOCK_RANGE _POSIX_VERSION +#endif + /* #define _POSIX_MEMORY_PROTECTION (-1L) */ #ifdef CONFIG_POSIX_MESSAGE_PASSING diff --git a/include/zephyr/posix/sys/mman.h b/include/zephyr/posix/sys/mman.h index 320d9d46cd235..20880749c0d68 100644 --- a/include/zephyr/posix/sys/mman.h +++ b/include/zephyr/posix/sys/mman.h @@ -32,8 +32,10 @@ extern "C" { #endif +int mlock(const void *addr, size_t len); void *mmap(void *addr, size_t len, int prot, int flags, int fildes, off_t off); int msync(void *addr, size_t length, int flags); +int munlock(const void *addr, size_t len); int munmap(void *addr, size_t len); #ifdef __cplusplus diff --git a/include/zephyr/posix/sys/sysconf.h b/include/zephyr/posix/sys/sysconf.h index 43c2c2943a0a4..d1ffac5f8d23e 100644 --- a/include/zephyr/posix/sys/sysconf.h +++ b/include/zephyr/posix/sys/sysconf.h @@ -156,7 +156,8 @@ enum { #define __z_posix_sysconf_SC_MAPPED_FILES \ COND_CODE_1(CONFIG_POSIX_MAPPED_FILES, (_POSIX_MAPPED_FILES), (-1L)) #define __z_posix_sysconf_SC_MEMLOCK (-1L) -#define __z_posix_sysconf_SC_MEMLOCK_RANGE (-1L) +#define __z_posix_sysconf_SC_MEMLOCK_RANGE \ + COND_CODE_1(CONFIG_POSIX_MEMLOCK_RANGE, (_POSIX_MEMLOCK_RANGE), (-1L)) #define __z_posix_sysconf_SC_MEMORY_PROTECTION (-1L) #define __z_posix_sysconf_SC_MESSAGE_PASSING \ COND_CODE_1(CONFIG_POSIX_MESSAGE_PASSING, (_POSIX_MESSAGE_PASSING), (-1L)) diff --git a/lib/posix/options/CMakeLists.txt b/lib/posix/options/CMakeLists.txt index a11e440b3e71c..fd8d4198e1a47 100644 --- a/lib/posix/options/CMakeLists.txt +++ b/lib/posix/options/CMakeLists.txt @@ -51,6 +51,7 @@ zephyr_library_sources_ifdef(CONFIG_POSIX_FD_MGMT ) zephyr_library_sources_ifdef(CONFIG_POSIX_FILE_SYSTEM fs.c) zephyr_library_sources_ifdef(CONFIG_POSIX_FSYNC fsync.c) +zephyr_library_sources_ifdef(CONFIG_POSIX_MEMLOCK_RANGE mlock.c) zephyr_library_sources_ifdef(CONFIG_POSIX_MAPPED_FILES mmap.c) zephyr_library_sources_ifdef(CONFIG_POSIX_MESSAGE_PASSING mqueue.c) zephyr_library_sources_ifdef(CONFIG_POSIX_MULTI_PROCESS diff --git a/lib/posix/options/Kconfig.mem b/lib/posix/options/Kconfig.mem index 7f0140fd1b1e3..d26c5dcc4c8b7 100644 --- a/lib/posix/options/Kconfig.mem +++ b/lib/posix/options/Kconfig.mem @@ -25,4 +25,20 @@ config POSIX_MAPPED_FILES https://pubs.opengroup.org/onlinepubs/9699919799.orig/functions/V2_chap02.html https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_port.html#tag_24_03_04 +if POSIX_MAPPED_FILES + +config POSIX_MEMLOCK_RANGE + bool "POSIX range memory locking [EXPERIMENTAL]" + select EXPERIMENTAL + imply MMU + imply DEMAND_PAGING + help + Select 'y' here and Zephyr will provide support for mlock() and munlock(). + + For more information, please see + https://pubs.opengroup.org/onlinepubs/9699919799.orig/functions/V2_chap02.html + https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_port.html#tag_24_03_04 + +endif + endmenu diff --git a/lib/posix/options/mlock.c b/lib/posix/options/mlock.c new file mode 100644 index 0000000000000..b81773c3a5711 --- /dev/null +++ b/lib/posix/options/mlock.c @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2024, Tenstorrent AI ULC + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +#include +#include + +int mlock(const void *addr, size_t len) +{ + k_mem_pin(addr, len); + + return 0; +} + +int munlock(const void *addr, size_t len) +{ + k_mem_unpin(addr, len); + + return 0; +} From d44047120baf13fac02a17413dea01dc34cd9e95 Mon Sep 17 00:00:00 2001 From: Chris Friedt Date: Sat, 1 Jun 2024 07:47:33 -0400 Subject: [PATCH 2801/2849] doc: posix: mark mlock() and munlock() as supported. Mark mlock() and munlock() as supported, as well as the _POSIX_MEMLOCK_RANGE Option. These functions are currently expected to fail, but are required so that conformant applications can still link successfully. Signed-off-by: Chris Friedt --- doc/services/portability/posix/aep/index.rst | 2 +- doc/services/portability/posix/conformance/index.rst | 2 +- doc/services/portability/posix/option_groups/index.rst | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/doc/services/portability/posix/aep/index.rst b/doc/services/portability/posix/aep/index.rst index 3896d052184ff..5a1a3f3fd8092 100644 --- a/doc/services/portability/posix/aep/index.rst +++ b/doc/services/portability/posix/aep/index.rst @@ -61,7 +61,7 @@ The *Minimal Realtime System Profile* (PSE51) includes all of the :ref:`_POSIX_FSYNC `, 200809L, :kconfig:option:`CONFIG_POSIX_FSYNC` :ref:`_POSIX_MEMLOCK `, -1, - :ref:`_POSIX_MEMLOCK_RANGE `, -1, + :ref:`_POSIX_MEMLOCK_RANGE `, 200809L, :kconfig:option:`CONFIG_POSIX_MEMLOCK_RANGE` :ref:`_POSIX_MONOTONIC_CLOCK `, 200809L, :kconfig:option:`CONFIG_POSIX_MONOTONIC_CLOCK` :ref:`_POSIX_SHARED_MEMORY_OBJECTS `, -1, :ref:`_POSIX_SYNCHRONIZED_IO `, -1, :kconfig:option:`CONFIG_POSIX_SYNCHRONIZED_IO` diff --git a/doc/services/portability/posix/conformance/index.rst b/doc/services/portability/posix/conformance/index.rst index 93b11c7ae7bb5..bdb5a574f1f1f 100644 --- a/doc/services/portability/posix/conformance/index.rst +++ b/doc/services/portability/posix/conformance/index.rst @@ -69,7 +69,7 @@ POSIX System Interfaces :ref:`_POSIX_FSYNC`, 200809L, :kconfig:option:`CONFIG_POSIX_FSYNC` :ref:`_POSIX_IPV6`, 200809L, :kconfig:option:`CONFIG_POSIX_IPV6` :ref:`_POSIX_MEMLOCK `, -1, - :ref:`_POSIX_MEMLOCK_RANGE `, -1, + :ref:`_POSIX_MEMLOCK_RANGE `, 200809L, :kconfig:option:`CONFIG_POSIX_MEMLOCK_RANGE` :ref:`_POSIX_MESSAGE_PASSING`, 200809L, :kconfig:option:`CONFIG_POSIX_MESSAGE_PASSING` :ref:`_POSIX_MONOTONIC_CLOCK`, 200809L, :kconfig:option:`CONFIG_POSIX_MONOTONIC_CLOCK` _POSIX_PRIORITIZED_IO, -1, diff --git a/doc/services/portability/posix/option_groups/index.rst b/doc/services/portability/posix/option_groups/index.rst index fd037d1d2fa68..edfce646a59de 100644 --- a/doc/services/portability/posix/option_groups/index.rst +++ b/doc/services/portability/posix/option_groups/index.rst @@ -681,8 +681,8 @@ _POSIX_MEMLOCK_RANGE :header: API, Supported :widths: 50,10 - mlock(), - munlock(), + mlock(), yes + munlock(), yes .. _posix_option_message_passing: From 5e99e13b4c2e4ec65e5495e74804e79f73baefea Mon Sep 17 00:00:00 2001 From: Chris Friedt Date: Sat, 1 Jun 2024 08:19:51 -0400 Subject: [PATCH 2802/2849] posix: add support for mlockall() and munlockall() Add support for mlockall() and munlockall(). These two functions comprise the _POSIX_MEMLOCK Option which is required by PSE51, PSE52, PSE53, and PSE54. Zephyr's on-demand paging API does not yet support pinning and unpinning *all* virtual memory regions, so these functions are expected to fail, setting errno to ENOSYS. Any other usage is currently categorized as undefined behaviour. Signed-off-by: Chris Friedt --- include/zephyr/posix/posix_features.h | 4 +++- include/zephyr/posix/sys/mman.h | 5 +++++ include/zephyr/posix/sys/sysconf.h | 3 ++- lib/posix/options/CMakeLists.txt | 1 + lib/posix/options/Kconfig.mem | 10 ++++++++++ lib/posix/options/mlockall.c | 25 +++++++++++++++++++++++++ 6 files changed, 46 insertions(+), 2 deletions(-) create mode 100644 lib/posix/options/mlockall.c diff --git a/include/zephyr/posix/posix_features.h b/include/zephyr/posix/posix_features.h index 2c07173218151..49b6368b32440 100644 --- a/include/zephyr/posix/posix_features.h +++ b/include/zephyr/posix/posix_features.h @@ -69,7 +69,9 @@ #define _POSIX_MAPPED_FILES _POSIX_VERSION #endif -/* #define _POSIX_MEMLOCK (-1L) */ +#ifdef CONFIG_POSIX_MEMLOCK +#define _POSIX_MEMLOCK _POSIX_VERSION +#endif #ifdef CONFIG_POSIX_MEMLOCK_RANGE #define _POSIX_MEMLOCK_RANGE _POSIX_VERSION diff --git a/include/zephyr/posix/sys/mman.h b/include/zephyr/posix/sys/mman.h index 20880749c0d68..0c9946e33b541 100644 --- a/include/zephyr/posix/sys/mman.h +++ b/include/zephyr/posix/sys/mman.h @@ -28,14 +28,19 @@ #define MAP_FAILED ((void *)-1) +#define MCL_CURRENT 0 +#define MCL_FUTURE 1 + #ifdef __cplusplus extern "C" { #endif int mlock(const void *addr, size_t len); +int mlockall(int flags); void *mmap(void *addr, size_t len, int prot, int flags, int fildes, off_t off); int msync(void *addr, size_t length, int flags); int munlock(const void *addr, size_t len); +int munlockall(void); int munmap(void *addr, size_t len); #ifdef __cplusplus diff --git a/include/zephyr/posix/sys/sysconf.h b/include/zephyr/posix/sys/sysconf.h index d1ffac5f8d23e..5a1d3c0dc2acc 100644 --- a/include/zephyr/posix/sys/sysconf.h +++ b/include/zephyr/posix/sys/sysconf.h @@ -155,7 +155,8 @@ enum { #define __z_posix_sysconf_SC_JOB_CONTROL (-1L) #define __z_posix_sysconf_SC_MAPPED_FILES \ COND_CODE_1(CONFIG_POSIX_MAPPED_FILES, (_POSIX_MAPPED_FILES), (-1L)) -#define __z_posix_sysconf_SC_MEMLOCK (-1L) +#define __z_posix_sysconf_SC_MEMLOCK \ + COND_CODE_1(CONFIG_POSIX_MEMLOCK, (_POSIX_MEMLOCK), (-1L)) #define __z_posix_sysconf_SC_MEMLOCK_RANGE \ COND_CODE_1(CONFIG_POSIX_MEMLOCK_RANGE, (_POSIX_MEMLOCK_RANGE), (-1L)) #define __z_posix_sysconf_SC_MEMORY_PROTECTION (-1L) diff --git a/lib/posix/options/CMakeLists.txt b/lib/posix/options/CMakeLists.txt index fd8d4198e1a47..0c8f3a460b577 100644 --- a/lib/posix/options/CMakeLists.txt +++ b/lib/posix/options/CMakeLists.txt @@ -51,6 +51,7 @@ zephyr_library_sources_ifdef(CONFIG_POSIX_FD_MGMT ) zephyr_library_sources_ifdef(CONFIG_POSIX_FILE_SYSTEM fs.c) zephyr_library_sources_ifdef(CONFIG_POSIX_FSYNC fsync.c) +zephyr_library_sources_ifdef(CONFIG_POSIX_MEMLOCK mlockall.c) zephyr_library_sources_ifdef(CONFIG_POSIX_MEMLOCK_RANGE mlock.c) zephyr_library_sources_ifdef(CONFIG_POSIX_MAPPED_FILES mmap.c) zephyr_library_sources_ifdef(CONFIG_POSIX_MESSAGE_PASSING mqueue.c) diff --git a/lib/posix/options/Kconfig.mem b/lib/posix/options/Kconfig.mem index d26c5dcc4c8b7..5726038510e4c 100644 --- a/lib/posix/options/Kconfig.mem +++ b/lib/posix/options/Kconfig.mem @@ -27,6 +27,16 @@ config POSIX_MAPPED_FILES if POSIX_MAPPED_FILES +config POSIX_MEMLOCK + bool "POSIX memory locking [EXPERIMENTAL]" + select EXPERIMENTAL + help + Select 'y' here and Zephyr will provide support for mlockall() and munlockall(). + + For more information, please see + https://pubs.opengroup.org/onlinepubs/9699919799.orig/functions/V2_chap02.html + https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_port.html#tag_24_03_04 + config POSIX_MEMLOCK_RANGE bool "POSIX range memory locking [EXPERIMENTAL]" select EXPERIMENTAL diff --git a/lib/posix/options/mlockall.c b/lib/posix/options/mlockall.c new file mode 100644 index 0000000000000..e921b9325352b --- /dev/null +++ b/lib/posix/options/mlockall.c @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2024, Tenstorrent AI ULC + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +#include + +int mlockall(int flags) +{ + ARG_UNUSED(flags); + + errno = ENOSYS; + return -1; +} + +int munlockall(void) +{ + errno = ENOSYS; + return -1; +} From 2fd7297aed727d4cbbf0f29330ee838068427da0 Mon Sep 17 00:00:00 2001 From: Chris Friedt Date: Sat, 1 Jun 2024 08:20:56 -0400 Subject: [PATCH 2803/2849] doc: posix: mark mlockall() and munlockall() as supported Mark mlockall() and munlockall() as supported, as well as the _POSIX_MEMLOCK Option. These functions are currently expected to fail, but are required so that conformant applications can still link successfully. Signed-off-by: Chris Friedt --- doc/services/portability/posix/aep/index.rst | 2 +- doc/services/portability/posix/conformance/index.rst | 2 +- doc/services/portability/posix/option_groups/index.rst | 8 ++++++-- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/doc/services/portability/posix/aep/index.rst b/doc/services/portability/posix/aep/index.rst index 5a1a3f3fd8092..e9e31492285b2 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 :widths: 50, 10, 50 :ref:`_POSIX_FSYNC `, 200809L, :kconfig:option:`CONFIG_POSIX_FSYNC` - :ref:`_POSIX_MEMLOCK `, -1, + :ref:`_POSIX_MEMLOCK `, 200809L, :kconfig:option:`CONFIG_POSIX_MEMLOCK` :ref:`†` :ref:`_POSIX_MEMLOCK_RANGE `, 200809L, :kconfig:option:`CONFIG_POSIX_MEMLOCK_RANGE` :ref:`_POSIX_MONOTONIC_CLOCK `, 200809L, :kconfig:option:`CONFIG_POSIX_MONOTONIC_CLOCK` :ref:`_POSIX_SHARED_MEMORY_OBJECTS `, -1, diff --git a/doc/services/portability/posix/conformance/index.rst b/doc/services/portability/posix/conformance/index.rst index bdb5a574f1f1f..c976ccaee05c5 100644 --- a/doc/services/portability/posix/conformance/index.rst +++ b/doc/services/portability/posix/conformance/index.rst @@ -68,7 +68,7 @@ POSIX System Interfaces :ref:`_POSIX_CPUTIME`, 200809L, :kconfig:option:`CONFIG_POSIX_CPUTIME` :ref:`_POSIX_FSYNC`, 200809L, :kconfig:option:`CONFIG_POSIX_FSYNC` :ref:`_POSIX_IPV6`, 200809L, :kconfig:option:`CONFIG_POSIX_IPV6` - :ref:`_POSIX_MEMLOCK `, -1, + :ref:`_POSIX_MEMLOCK `, 200809L, :kconfig:option:`CONFIG_POSIX_MEMLOCK` :ref:`†` :ref:`_POSIX_MEMLOCK_RANGE `, 200809L, :kconfig:option:`CONFIG_POSIX_MEMLOCK_RANGE` :ref:`_POSIX_MESSAGE_PASSING`, 200809L, :kconfig:option:`CONFIG_POSIX_MESSAGE_PASSING` :ref:`_POSIX_MONOTONIC_CLOCK`, 200809L, :kconfig:option:`CONFIG_POSIX_MONOTONIC_CLOCK` diff --git a/doc/services/portability/posix/option_groups/index.rst b/doc/services/portability/posix/option_groups/index.rst index edfce646a59de..cd9befa785bf6 100644 --- a/doc/services/portability/posix/option_groups/index.rst +++ b/doc/services/portability/posix/option_groups/index.rst @@ -665,12 +665,16 @@ For more information, please refer to :ref:`Networking `. _POSIX_MEMLOCK ++++++++++++++ +Zephyr's :ref:`Demand Paging API ` does not yet support +pinning or unpinning all virtual memory regions. The functions below are expected to fail and +set ``errno`` to ``ENOSYS`` :ref:`†`. + .. csv-table:: _POSIX_MEMLOCK :header: API, Supported :widths: 50,10 - mlockall(), - munlockall(), + mlockall(), yes + munlockall(), yes .. _posix_option_memlock_range: From 271090301492cb8786e96d8877519c7d6ef92be3 Mon Sep 17 00:00:00 2001 From: Chris Friedt Date: Wed, 5 Jun 2024 12:06:50 -0400 Subject: [PATCH 2804/2849] os: fdtable: add mode field for fd_entry Add a mode field for struct fd_entry, as well as a new initializer, z_finalize_typed_fd(). The constants ZVFS_MODE_* may be used to differentiate between fifo, character device, message queues, directories, semaphores, block devices, shared memory objects, regular files, symbolic links, and sockets. Signed-off-by: Chris Friedt --- include/zephyr/sys/fdtable.h | 37 +++++++++++++++++++++++++++++++++++- lib/os/fdtable.c | 4 +++- 2 files changed, 39 insertions(+), 2 deletions(-) diff --git a/include/zephyr/sys/fdtable.h b/include/zephyr/sys/fdtable.h index 4f68d7598ce65..a899e1eb2d51a 100644 --- a/include/zephyr/sys/fdtable.h +++ b/include/zephyr/sys/fdtable.h @@ -12,6 +12,20 @@ #include #include +/* File mode bits */ +#define ZVFS_MODE_IFMT 0170000 +#define ZVFS_MODE_UNSPEC 0000000 +#define ZVFS_MODE_IFIFO 0010000 +#define ZVFS_MODE_IFCHR 0020000 +#define ZVFS_MODE_IMSGQ 0030000 +#define ZVFS_MODE_IFDIR 0040000 +#define ZVFS_MODE_IFSEM 0050000 +#define ZVFS_MODE_IFBLK 0060000 +#define ZVFS_MODE_IFSHM 0070000 +#define ZVFS_MODE_IFREG 0100000 +#define ZVFS_MODE_IFLNK 0120000 +#define ZVFS_MODE_IFSOCK 0140000 + #ifdef __cplusplus extern "C" { #endif @@ -39,6 +53,24 @@ struct fd_op_vtable { */ int z_reserve_fd(void); +/** + * @brief Finalize creation of file descriptor, with type. + * + * This function should be called exactly once after z_reserve_fd(), and + * should not be called in any other case. + * + * The difference between this function and @ref z_finalize_fd is that the + * latter does not relay type information of the created file descriptor. + * + * Values permitted for @a mode are one of `ZVFS_MODE_..`. + * + * @param fd File descriptor previously returned by z_reserve_fd() + * @param obj pointer to I/O object structure + * @param vtable pointer to I/O operation implementations for the object + * @param mode File type as specified above. + */ +void z_finalize_typed_fd(int fd, void *obj, const struct fd_op_vtable *vtable, uint32_t mode); + /** * @brief Finalize creation of file descriptor. * @@ -49,7 +81,10 @@ int z_reserve_fd(void); * @param obj pointer to I/O object structure * @param vtable pointer to I/O operation implementations for the object */ -void z_finalize_fd(int fd, void *obj, const struct fd_op_vtable *vtable); +static inline void z_finalize_fd(int fd, void *obj, const struct fd_op_vtable *vtable) +{ + z_finalize_typed_fd(fd, obj, vtable, ZVFS_MODE_UNSPEC); +} /** * @brief Allocate file descriptor for underlying I/O object. diff --git a/lib/os/fdtable.c b/lib/os/fdtable.c index 6adb57696cdb5..803d31a5c2e2a 100644 --- a/lib/os/fdtable.c +++ b/lib/os/fdtable.c @@ -31,6 +31,7 @@ struct fd_entry { atomic_t refcount; struct k_mutex lock; struct k_condvar cond; + uint32_t mode; }; #if defined(CONFIG_POSIX_DEVICE_IO) @@ -254,7 +255,7 @@ int z_reserve_fd(void) return fd; } -void z_finalize_fd(int fd, void *obj, const struct fd_op_vtable *vtable) +void z_finalize_typed_fd(int fd, void *obj, const struct fd_op_vtable *vtable, uint32_t mode) { /* Assumes fd was already bounds-checked. */ #ifdef CONFIG_USERSPACE @@ -269,6 +270,7 @@ void z_finalize_fd(int fd, void *obj, const struct fd_op_vtable *vtable) #endif fdtable[fd].obj = obj; fdtable[fd].vtable = vtable; + fdtable[fd].mode = mode; /* Let the object know about the lock just in case it needs it * for something. For BSD sockets, the lock is used with condition From 58c1c48df074532cd51654d47fdaea352e2acec7 Mon Sep 17 00:00:00 2001 From: Chris Friedt Date: Wed, 5 Jun 2024 13:36:32 -0400 Subject: [PATCH 2805/2849] fdtable: per-fd offset support, add read/write_offs() methods File offset actually varies on a per-file-descriptor basis, and not with the resource that is abstracted behind the file descriptor. This is consistent with both the POSIX model and also the ISO C/C++ model, so Zephyr should follow suit. This is very work-around-y, but it's necessary to ensure that shared memory objects, block devices, files and directories all behave consistently. Signed-off-by: Chris Friedt --- include/zephyr/sys/fdtable.h | 10 ++++-- lib/os/fdtable.c | 64 +++++++++++++++++++++++++++++++----- 2 files changed, 64 insertions(+), 10 deletions(-) diff --git a/include/zephyr/sys/fdtable.h b/include/zephyr/sys/fdtable.h index a899e1eb2d51a..2c49d24210b1e 100644 --- a/include/zephyr/sys/fdtable.h +++ b/include/zephyr/sys/fdtable.h @@ -35,8 +35,14 @@ extern "C" { * Currently all operations beyond read/write/close go thru ioctl method. */ struct fd_op_vtable { - ssize_t (*read)(void *obj, void *buf, size_t sz); - ssize_t (*write)(void *obj, const void *buf, size_t sz); + union { + ssize_t (*read)(void *obj, void *buf, size_t sz); + ssize_t (*read_offs)(void *obj, void *buf, size_t sz, size_t offset); + }; + union { + ssize_t (*write)(void *obj, const void *buf, size_t sz); + ssize_t (*write_offs)(void *obj, const void *buf, size_t sz, size_t offset); + }; int (*close)(void *obj); int (*ioctl)(void *obj, unsigned int request, va_list args); }; diff --git a/lib/os/fdtable.c b/lib/os/fdtable.c index 803d31a5c2e2a..8e192eeb106b0 100644 --- a/lib/os/fdtable.c +++ b/lib/os/fdtable.c @@ -31,6 +31,7 @@ struct fd_entry { atomic_t refcount; struct k_mutex lock; struct k_condvar cond; + size_t offset; uint32_t mode; }; @@ -309,9 +310,19 @@ ssize_t zvfs_read(int fd, void *buf, size_t sz) } (void)k_mutex_lock(&fdtable[fd].lock, K_FOREVER); - - res = fdtable[fd].vtable->read(fdtable[fd].obj, buf, sz); - + res = fdtable[fd].vtable->read_offs(fdtable[fd].obj, buf, sz, fdtable[fd].offset); + if (res > 0) { + switch (fdtable[fd].mode & ZVFS_MODE_IFMT) { + case ZVFS_MODE_IFDIR: + case ZVFS_MODE_IFBLK: + case ZVFS_MODE_IFSHM: + case ZVFS_MODE_IFREG: + fdtable[fd].offset += res; + break; + default: + break; + } + } k_mutex_unlock(&fdtable[fd].lock); return res; @@ -326,9 +337,19 @@ ssize_t zvfs_write(int fd, const void *buf, size_t sz) } (void)k_mutex_lock(&fdtable[fd].lock, K_FOREVER); - - res = fdtable[fd].vtable->write(fdtable[fd].obj, buf, sz); - + res = fdtable[fd].vtable->write_offs(fdtable[fd].obj, buf, sz, fdtable[fd].offset); + if (res > 0) { + switch (fdtable[fd].mode & ZVFS_MODE_IFMT) { + case ZVFS_MODE_IFDIR: + case ZVFS_MODE_IFBLK: + case ZVFS_MODE_IFSHM: + case ZVFS_MODE_IFREG: + fdtable[fd].offset += res; + break; + default: + break; + } + } k_mutex_unlock(&fdtable[fd].lock); return res; @@ -371,14 +392,41 @@ int zvfs_fsync(int fd) return z_fdtable_call_ioctl(fdtable[fd].vtable, fdtable[fd].obj, ZFD_IOCTL_FSYNC); } +static inline off_t zvfs_lseek_wrap(int fd, int cmd, ...) +{ + off_t res; + va_list args; + + __ASSERT_NO_MSG(fd < ARRAY_SIZE(fdtable)); + + (void)k_mutex_lock(&fdtable[fd].lock, K_FOREVER); + va_start(args, cmd); + res = fdtable[fd].vtable->ioctl(fdtable[fd].obj, cmd, args); + va_end(args); + if (res > 0) { + switch (fdtable[fd].mode & ZVFS_MODE_IFMT) { + case ZVFS_MODE_IFDIR: + case ZVFS_MODE_IFBLK: + case ZVFS_MODE_IFSHM: + case ZVFS_MODE_IFREG: + fdtable[fd].offset = res; + break; + default: + break; + } + } + k_mutex_unlock(&fdtable[fd].lock); + + return res; +} + off_t zvfs_lseek(int fd, off_t offset, int whence) { if (_check_fd(fd) < 0) { return -1; } - return z_fdtable_call_ioctl(fdtable[fd].vtable, fdtable[fd].obj, ZFD_IOCTL_LSEEK, offset, - whence); + return zvfs_lseek_wrap(fd, ZFD_IOCTL_LSEEK, offset, whence, fdtable[fd].offset); } int zvfs_fcntl(int fd, int cmd, va_list args) From 5346306261c4764a884f9b277fdee1aae458a542 Mon Sep 17 00:00:00 2001 From: Chris Friedt Date: Wed, 5 Jun 2024 12:41:26 -0400 Subject: [PATCH 2806/2849] posix: add support for shared memory objects Implement shm_open() and shm_unlink() to complete support for the _POSIX_SHARED_MEMORY_OBJECTS Option. Since mmap() support is not yet implemented in Zephyr, I/O is limited to read(), write(), ftruncate(), lseek(), close(), for now. Signed-off-by: Chris Friedt --- include/zephyr/posix/posix_features.h | 5 +- include/zephyr/posix/sys/mman.h | 2 + include/zephyr/posix/sys/sysconf.h | 3 +- lib/posix/options/CMakeLists.txt | 1 + lib/posix/options/Kconfig.mem | 14 + lib/posix/options/shm.c | 395 ++++++++++++++++++++++++++ 6 files changed, 418 insertions(+), 2 deletions(-) create mode 100644 lib/posix/options/shm.c diff --git a/include/zephyr/posix/posix_features.h b/include/zephyr/posix/posix_features.h index 49b6368b32440..1a8a921e2f91d 100644 --- a/include/zephyr/posix/posix_features.h +++ b/include/zephyr/posix/posix_features.h @@ -109,7 +109,10 @@ #define _POSIX_SEMAPHORES _POSIX_VERSION #endif -/* #define _POSIX_SHARED_MEMORY_OBJECTS (-1L) */ +#ifdef CONFIG_POSIX_SHARED_MEMORY_OBJECTS +#define _POSIX_SHARED_MEMORY_OBJECTS _POSIX_VERSION +#endif + /* #define _POSIX_SHELL (-1L) */ /* #define _POSIX_SPAWN (-1L) */ diff --git a/include/zephyr/posix/sys/mman.h b/include/zephyr/posix/sys/mman.h index 0c9946e33b541..8cbf5fd838077 100644 --- a/include/zephyr/posix/sys/mman.h +++ b/include/zephyr/posix/sys/mman.h @@ -42,6 +42,8 @@ int msync(void *addr, size_t length, int flags); int munlock(const void *addr, size_t len); int munlockall(void); int munmap(void *addr, size_t len); +int shm_open(const char *name, int oflag, mode_t mode); +int shm_unlink(const char *name); #ifdef __cplusplus } diff --git a/include/zephyr/posix/sys/sysconf.h b/include/zephyr/posix/sys/sysconf.h index 5a1d3c0dc2acc..4241dabd0696d 100644 --- a/include/zephyr/posix/sys/sysconf.h +++ b/include/zephyr/posix/sys/sysconf.h @@ -177,7 +177,8 @@ enum { #define __z_posix_sysconf_SC_SAVED_IDS (-1L) #define __z_posix_sysconf_SC_SEMAPHORES \ COND_CODE_1(CONFIG_POSIX_SEMAPHORES, (_POSIX_SEMAPHORES), (-1L)) -#define __z_posix_sysconf_SC_SHARED_MEMORY_OBJECTS (-1L) +#define __z_posix_sysconf_SC_SHARED_MEMORY_OBJECTS \ + COND_CODE_1(CONFIG_POSIX_SHARED_MEMORY_OBJECTS, (_POSIX_SHARED_MEMORY_OBJECTS), (-1L)) #define __z_posix_sysconf_SC_SHELL (-1L) #define __z_posix_sysconf_SC_SPAWN (-1L) #define __z_posix_sysconf_SC_SPIN_LOCKS \ diff --git a/lib/posix/options/CMakeLists.txt b/lib/posix/options/CMakeLists.txt index 0c8f3a460b577..f25af7f427dae 100644 --- a/lib/posix/options/CMakeLists.txt +++ b/lib/posix/options/CMakeLists.txt @@ -60,6 +60,7 @@ zephyr_library_sources_ifdef(CONFIG_POSIX_MULTI_PROCESS multi_process.c ) zephyr_library_sources_ifdef(CONFIG_POSIX_NETWORKING net.c) +zephyr_library_sources_ifdef(CONFIG_POSIX_SHARED_MEMORY_OBJECTS shm.c) zephyr_library_sources_ifdef(CONFIG_POSIX_SIGNALS signal.c ${STRSIGNAL_TABLE_H}) zephyr_library_sources_ifdef(CONFIG_POSIX_SINGLE_PROCESS confstr.c diff --git a/lib/posix/options/Kconfig.mem b/lib/posix/options/Kconfig.mem index 5726038510e4c..160a57e80772a 100644 --- a/lib/posix/options/Kconfig.mem +++ b/lib/posix/options/Kconfig.mem @@ -14,6 +14,20 @@ config POSIX_PAGE_SIZE_BITS PAGE_SIZE is supported in the range [64, 65536] If CONFIG_POSIX_API=y, PAGE_SIZE defaults to 4096, otherwise, it is 64 bytes. +config POSIX_SHARED_MEMORY_OBJECTS + bool "POSIX shared memory objects [EXPERIMENTAL]" + select EXPERIMENTAL + select SYS_HASH_FUNC32 + select SYS_HASH_FUNC32_DJB2 + select FDTABLE + select POSIX_MAPPED_FILES + help + Select 'y' here and Zephyr will provide implementations of shm_open() and shm_unlink(). + + For more information, please see + https://pubs.opengroup.org/onlinepubs/9699919799.orig/functions/V2_chap02.html + https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_port.html#tag_24_03_04 + config POSIX_MAPPED_FILES bool "POSIX memory-mapped files [EXPERIMENTAL]" select EXPERIMENTAL diff --git a/lib/posix/options/shm.c b/lib/posix/options/shm.c new file mode 100644 index 0000000000000..d1eca540fe683 --- /dev/null +++ b/lib/posix/options/shm.c @@ -0,0 +1,395 @@ +/* + * Copyright (c) 2024, Tenstorrent AI ULC + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define _page_size COND_CODE_1(CONFIG_MMU, (CONFIG_MMU_PAGE_SIZE), (PAGE_SIZE)) + +static const struct fd_op_vtable shm_vtable; + +static sys_dlist_t shm_list = SYS_DLIST_STATIC_INIT(&shm_list); + +struct shm_obj { + uint8_t *mem; + sys_dnode_t node; + size_t refs; + size_t size; + uint32_t hash; + bool unlinked: 1; + bool mapped: 1; +}; + +static inline uint32_t hash32(const char *str, size_t n) +{ + /* we need a hasher that is not sensitive to input alignment */ + return sys_hash32_djb2(str, n); +} + +static bool shm_obj_name_valid(const char *name, size_t len) +{ + if (name == NULL) { + return false; + } + + if (name[0] != '/') { + return false; + } + + if (len < 2) { + return false; + } + + return true; +} + +static struct shm_obj *shm_obj_find(uint32_t key) +{ + struct shm_obj *shm; + + SYS_DLIST_FOR_EACH_CONTAINER(&shm_list, shm, node) { + if (shm->hash == key) { + return shm; + } + } + + return NULL; +} + +static void shm_obj_add(struct shm_obj *shm) +{ + sys_dlist_init(&shm->node); + sys_dlist_append(&shm_list, &shm->node); +} + +static void shm_obj_remove(struct shm_obj *shm) +{ + sys_dlist_remove(&shm->node); + if (shm->size > 0) { + if (IS_ENABLED(CONFIG_MMU)) { + uintptr_t phys = 0; + + if (arch_page_phys_get(shm->mem, &phys) == 0) { + k_mem_unmap(shm->mem, ROUND_UP(shm->size, _page_size)); + } + } else { + k_free(shm->mem); + } + } + k_free(shm); +} + +static int shm_fstat(struct shm_obj *shm, struct stat *st) +{ + *st = (struct stat){0}; + st->st_mode = ZVFS_MODE_IFSHM; + st->st_size = shm->size; + + return 0; +} + +static int shm_ftruncate(struct shm_obj *shm, off_t length) +{ + void *virt; + + if (length < 0) { + errno = EINVAL; + return -1; + } + + if (length == 0) { + if (shm->size != 0) { + /* only allow resizing this once, for consistence */ + errno = EBUSY; + return -1; + } + + return 0; + } + + if (IS_ENABLED(CONFIG_MMU)) { + virt = k_mem_map(ROUND_UP(length, _page_size), K_MEM_PERM_RW); + } else { + virt = k_calloc(1, length); + } + + if (virt == NULL) { + errno = ENOMEM; + return -1; + } + + shm->mem = virt; + shm->size = length; + + return 0; +} + +static off_t shm_lseek(struct shm_obj *shm, off_t offset, int whence, size_t cur) +{ + size_t addend; + + switch (whence) { + case SEEK_SET: + addend = 0; + break; + case SEEK_CUR: + addend = cur; + break; + case SEEK_END: + addend = shm->size; + break; + default: + errno = EINVAL; + return -1; + } + + if ((INTPTR_MAX - addend) < offset) { + errno = EOVERFLOW; + return -1; + } + + offset += addend; + if (offset < 0) { + errno = EINVAL; + return -1; + } + + return offset; +} + +static int shm_mmap(struct shm_obj *shm, void *addr, size_t len, int prot, int flags, off_t off, + void **virt) +{ + ARG_UNUSED(addr); + ARG_UNUSED(prot); + __ASSERT_NO_MSG(virt != NULL); + + if ((len == 0) || (off < 0) || ((flags & MAP_FIXED) != 0) || + ((off & (_page_size - 1)) != 0) || ((len + off) > shm->size)) { + errno = EINVAL; + return -1; + } + + if (!IS_ENABLED(CONFIG_MMU)) { + errno = ENOTSUP; + return -1; + } + + if (shm->mem == NULL) { + errno = ENOMEM; + return -1; + } + + /* + * Note: due to Zephyr's page mapping algorithm, physical pages can only have 1 + * mapping, so different file handles will have the same virtual memory address + * underneath. + */ + *virt = shm->mem + off; + + return 0; +} + +static ssize_t shm_rw(struct shm_obj *shm, void *buf, size_t size, bool is_write, size_t offset) +{ + if (offset >= size) { + size = 0; + } else { + size = MIN(size, shm->size - offset); + } + + if (size > 0) { + if (is_write) { + memcpy(&shm->mem[offset], buf, size); + } else { + memcpy(buf, &shm->mem[offset], size); + } + } + + return size; +} + +static ssize_t shm_read(void *obj, void *buf, size_t sz, size_t offset) +{ + return shm_rw((struct shm_obj *)obj, buf, sz, false, offset); +} + +static ssize_t shm_write(void *obj, const void *buf, size_t sz, size_t offset) +{ + return shm_rw((struct shm_obj *)obj, (void *)buf, sz, true, offset); +} + +static int shm_close(void *obj) +{ + struct shm_obj *shm = obj; + + shm->refs -= (shm->refs > 0) ? 1 : 0; + if (shm->unlinked && (shm->refs == 0)) { + shm_obj_remove(shm); + } + + return 0; +} + +static int shm_ioctl(void *obj, unsigned int request, va_list args) +{ + struct shm_obj *shm = obj; + + switch (request) { + case ZFD_IOCTL_LSEEK: { + off_t offset = va_arg(args, off_t); + int whence = va_arg(args, int); + size_t cur = va_arg(args, size_t); + + return shm_lseek(shm, offset, whence, cur); + } break; + case ZFD_IOCTL_MMAP: { + void *addr = va_arg(args, void *); + size_t len = va_arg(args, size_t); + int prot = va_arg(args, int); + int flags = va_arg(args, int); + off_t off = va_arg(args, off_t); + void **maddr = va_arg(args, void **); + + return shm_mmap(shm, addr, len, prot, flags, off, maddr); + } break; + case ZFD_IOCTL_SET_LOCK: + break; + case ZFD_IOCTL_STAT: { + struct stat *st = va_arg(args, struct stat *); + + return shm_fstat(shm, st); + } break; + case ZFD_IOCTL_TRUNCATE: { + off_t length = va_arg(args, off_t); + + return shm_ftruncate(shm, length); + } break; + default: + errno = ENOTSUP; + return -1; + } + + return 0; +} + +static const struct fd_op_vtable shm_vtable = { + .read_offs = shm_read, + .write_offs = shm_write, + .close = shm_close, + .ioctl = shm_ioctl, +}; + +int shm_open(const char *name, int oflag, mode_t mode) +{ + int fd; + uint32_t key; + struct shm_obj *shm; + bool rd = (oflag & O_RDONLY) != 0; + bool rw = (oflag & O_RDWR) != 0; + bool creat = (oflag & O_CREAT) != 0; + bool excl = (oflag & O_EXCL) != 0; + bool trunc = false; /* (oflag & O_TRUNC) != 0 */ + size_t name_len = (name == NULL) ? 0 : strnlen(name, PATH_MAX); + + /* revisit when file-based permissions are available */ + if ((mode & 0777) == 0) { + errno = EINVAL; + return -1; + } + + if (!(rd ^ rw)) { + errno = EINVAL; + return -1; + } + + if (rd && trunc) { + errno = EINVAL; + return -1; + } + + if (!shm_obj_name_valid(name, name_len)) { + errno = EINVAL; + return -1; + } + + fd = z_reserve_fd(); + if (fd < 0) { + errno = EMFILE; + return -1; + } + + key = hash32(name, name_len); + shm = shm_obj_find(key); + if ((shm != NULL) && shm->unlinked) { + /* we cannot open a shm object that has already been unlinked */ + errno = EACCES; + return -1; + } + + if (creat) { + if ((shm != NULL) && excl) { + z_free_fd(fd); + errno = EEXIST; + return -1; + } + + if (shm == NULL) { + shm = k_calloc(1, sizeof(*shm)); + if (shm == NULL) { + z_free_fd(fd); + errno = ENOSPC; + return -1; + } + + shm->hash = key; + shm_obj_add(shm); + } + } else if (shm == NULL) { + errno = ENOENT; + return -1; + } + + ++shm->refs; + z_finalize_typed_fd(fd, shm, &shm_vtable, ZVFS_MODE_IFSHM); + + return fd; +} + +int shm_unlink(const char *name) +{ + uint32_t key; + struct shm_obj *shm; + size_t name_len = (name == NULL) ? 0 : strnlen(name, PATH_MAX); + + if (!shm_obj_name_valid(name, name_len)) { + errno = EINVAL; + return -1; + } + + key = hash32(name, name_len); + shm = shm_obj_find(key); + if ((shm == NULL) || shm->unlinked) { + errno = ENOENT; + return -1; + } + + shm->unlinked = true; + if (shm->refs == 0) { + shm_obj_remove(shm); + } + + return 0; +} From f4cb16139333e921b3987f6a4b76a0a7ab09b1bf Mon Sep 17 00:00:00 2001 From: Chris Friedt Date: Wed, 5 Jun 2024 12:58:21 -0400 Subject: [PATCH 2807/2849] tests: posix: add tests for shared memory objects Add tests for shared memory objects. Signed-off-by: Chris Friedt --- tests/posix/shm/CMakeLists.txt | 8 ++ tests/posix/shm/prj.conf | 4 + tests/posix/shm/src/main.c | 200 +++++++++++++++++++++++++++++++++ tests/posix/shm/testcase.yaml | 19 ++++ 4 files changed, 231 insertions(+) create mode 100644 tests/posix/shm/CMakeLists.txt create mode 100644 tests/posix/shm/prj.conf create mode 100644 tests/posix/shm/src/main.c create mode 100644 tests/posix/shm/testcase.yaml diff --git a/tests/posix/shm/CMakeLists.txt b/tests/posix/shm/CMakeLists.txt new file mode 100644 index 0000000000000..65e1ac9b27f37 --- /dev/null +++ b/tests/posix/shm/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(shm) + +FILE(GLOB app_sources src/*.c) +target_sources(app PRIVATE ${app_sources}) diff --git a/tests/posix/shm/prj.conf b/tests/posix/shm/prj.conf new file mode 100644 index 0000000000000..04734c10d7c7c --- /dev/null +++ b/tests/posix/shm/prj.conf @@ -0,0 +1,4 @@ +CONFIG_ZTEST=y + +CONFIG_POSIX_API=y +CONFIG_POSIX_SHARED_MEMORY_OBJECTS=y diff --git a/tests/posix/shm/src/main.c b/tests/posix/shm/src/main.c new file mode 100644 index 0000000000000..625398e24aa8b --- /dev/null +++ b/tests/posix/shm/src/main.c @@ -0,0 +1,200 @@ +/* + * Copyright (c) 2024, Tenstorrent AI ULC + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +#include +#include +#include +#include + +#include + +#define SHM_SIZE 8 + +#define VALID_SHM_PATH "/foo" +#define INVALID_SHM_PATH "foo" +#define EMPTY_SHM_PATH "" +#define TOO_SHORT_SHM_PATH "/" + +#define INVALID_MODE 0 +#define VALID_MODE 0666 + +#define INVALID_FLAGS 0 +#define VALID_FLAGS (O_RDWR | O_CREAT) +#define CREATE_FLAGS VALID_FLAGS +#define OPEN_FLAGS (VALID_FLAGS & ~O_CREAT) + +/* account for stdin, stdout, stderr */ +#define N (CONFIG_ZVFS_OPEN_MAX - 3) + +/* we need to have at least 2 shared memory objects */ +BUILD_ASSERT(N >= 2, "CONFIG_ZVFS_OPEN_MAX must be > 4"); + +#define S_TYPEISSHM(st) (((st)->st_mode & ZVFS_MODE_IFMT) == ZVFS_MODE_IFSHM) + +ZTEST(shm, test_shm_open) +{ + int ret; + int fd[N]; + struct stat st; + + { + /* degenerate error cases */ + zassert_not_ok(shm_open(NULL, INVALID_FLAGS, INVALID_MODE)); + zassert_not_ok(shm_open(NULL, INVALID_FLAGS, VALID_MODE)); + zassert_not_ok(shm_open(NULL, VALID_FLAGS, INVALID_MODE)); + zassert_not_ok(shm_open(NULL, VALID_FLAGS, VALID_MODE)); + zassert_not_ok(shm_open(INVALID_SHM_PATH, VALID_FLAGS, VALID_MODE)); + zassert_not_ok(shm_open(EMPTY_SHM_PATH, VALID_FLAGS, VALID_MODE)); + zassert_not_ok(shm_open(TOO_SHORT_SHM_PATH, VALID_FLAGS, VALID_MODE)); + zassert_not_ok(shm_open(VALID_SHM_PATH, INVALID_FLAGS, INVALID_MODE)); + zassert_not_ok(shm_open(VALID_SHM_PATH, INVALID_FLAGS, VALID_MODE)); + zassert_not_ok(shm_open(VALID_SHM_PATH, VALID_FLAGS, INVALID_MODE)); + } + + /* open / close 1 file descriptor referring to VALID_SHM_PATH */ + fd[0] = shm_open(VALID_SHM_PATH, VALID_FLAGS, VALID_MODE); + zassert_true(fd[0] >= 0, "shm_open(%s, %x, %04o) failed: %d", VALID_SHM_PATH, VALID_FLAGS, + VALID_MODE, errno); + + /* should have size 0 and be a shared memory object */ + zassert_ok(fstat(fd[0], &st)); + zassert_equal(st.st_size, 0); + zassert_true(S_TYPEISSHM(&st)); + + /* technically, the order of close / shm_unlink can be reversed too */ + zassert_ok(close(fd[0])); + ret = shm_unlink(VALID_SHM_PATH); + zassert_true(ret == 0 || (ret == -1 && errno == ENOENT), + "unexpected return / errno from shm_unlink: %d / %d", ret, errno); + + /* open / close N file descriptors referring to VALID_SHM_PATH */ + for (size_t i = 0; i < N; ++i) { + fd[i] = shm_open(VALID_SHM_PATH, i == 0 ? CREATE_FLAGS : OPEN_FLAGS, VALID_MODE); + zassert_true(fd[i] >= 0, "shm_open(%s, %x, %04o) failed: %d", VALID_SHM_PATH, + VALID_FLAGS, VALID_MODE, errno); + } + zassert_ok(shm_unlink(VALID_SHM_PATH)); + for (size_t i = N; i > 0; --i) { + zassert_ok(close(fd[i - 1])); + } +} + +ZTEST(shm, test_shm_unlink) +{ + int fd; + + { + /* degenerate error cases */ + zassert_not_ok(shm_unlink(NULL)); + zassert_not_ok(shm_unlink(INVALID_SHM_PATH)); + zassert_not_ok(shm_unlink(EMPTY_SHM_PATH)); + zassert_not_ok(shm_unlink(TOO_SHORT_SHM_PATH)); + } + + /* open / close 1 file descriptor referring to VALID_SHM_PATH */ + fd = shm_open(VALID_SHM_PATH, VALID_FLAGS, VALID_MODE); + zassert_true(fd >= 0, "shm_open(%s, %x, %04o) failed: %d", VALID_SHM_PATH, VALID_FLAGS, + VALID_MODE, errno); + /* technically, the order of close / shm_unlink can be reversed too */ + zassert_ok(close(fd)); + zassert_ok(shm_unlink(VALID_SHM_PATH)); + /* should not be able to re-open the same path without O_CREAT */ + zassert_not_ok(shm_open(VALID_SHM_PATH, OPEN_FLAGS, VALID_MODE)); +} + +ZTEST(shm, test_shm_read_write) +{ + int fd[N]; + + for (size_t i = 0; i < N; ++i) { + char cbuf = 0xff; + + fd[i] = shm_open(VALID_SHM_PATH, i == 0 ? CREATE_FLAGS : OPEN_FLAGS, VALID_MODE); + zassert_true(fd[i] >= 0, "shm_open(%s, %x, %04o) failed: %d", VALID_SHM_PATH, + VALID_FLAGS, VALID_MODE, errno); + if (i == 0) { + /* size 0 on create / zero characters written */ + zassert_equal(write(fd[0], "", 1), 0, + "write() should fail on newly create shm fd with size 0"); + /* size 0 on create / zero characters read */ + zassert_equal(read(fd[0], &cbuf, 1), 0, + "read() should fail on newly create shm fd with size 0"); + + BUILD_ASSERT(SHM_SIZE >= 1); + zassert_ok(ftruncate(fd[0], SHM_SIZE)); + + zassert_equal(write(fd[0], "\x42", 1), 1, "write() failed on fd %d: %d\n", + fd[0], errno); + + continue; + } + + zassert_equal(read(fd[i], &cbuf, 1), 1, "read() failed on fd %d: %d\n", fd[i], + errno); + zassert_equal(cbuf, 0x42, + "Failed to read byte over fd %d: expected: 0x%02x actual: 0x%02x", + fd[i], 0x42, cbuf); + } + + for (size_t i = N; i > 0; --i) { + zassert_ok(close(fd[i - 1])); + } + + zassert_ok(shm_unlink(VALID_SHM_PATH)); +} + +ZTEST(shm, test_shm_mmap) +{ + int fd[N]; + void *addr[N]; + + if (!IS_ENABLED(CONFIG_MMU)) { + ztest_test_skip(); + } + + for (size_t i = 0; i < N; ++i) { + fd[i] = shm_open(VALID_SHM_PATH, i == 0 ? CREATE_FLAGS : OPEN_FLAGS, VALID_MODE); + zassert_true(fd[i] >= 0, "shm_open(%s, %x, %04o) failed: %d", VALID_SHM_PATH, + VALID_FLAGS, VALID_MODE, errno); + + if (i == 0) { + /* cannot map shm of size zero */ + zassert_not_ok(mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, + fd[0], 0)); + + zassert_ok(ftruncate(fd[0], PAGE_SIZE)); + } + + addr[i] = mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd[i], 0); + zassert_not_equal(MAP_FAILED, addr[i], "mmap() failed: %d", errno); + + if ((i & 1) == 0) { + memset(addr[0], i & 0xff, PAGE_SIZE); + } else { + zassert_mem_equal(addr[i], addr[i - 1], PAGE_SIZE); + } + } + + for (size_t i = N; i > 0; --i) { + zassert_ok(close(fd[i - 1])); + } + + for (size_t i = N; i > 0; --i) { + zassert_ok(munmap(addr[i - 1], PAGE_SIZE)); + /* + * Note: for some reason, in Zephyr, unmapping a physical page once, removes all + * virtual mappings. When that behaviour changes, remove the break below and adjust + * shm.c accordingly. + */ + break; + } + + zassert_ok(shm_unlink(VALID_SHM_PATH)); +} + +ZTEST_SUITE(shm, NULL, NULL, NULL, NULL, NULL); diff --git a/tests/posix/shm/testcase.yaml b/tests/posix/shm/testcase.yaml new file mode 100644 index 0000000000000..31a490c01536a --- /dev/null +++ b/tests/posix/shm/testcase.yaml @@ -0,0 +1,19 @@ +common: + filter: not CONFIG_NATIVE_LIBC + tags: + - posix + - shm + integration_platforms: + - qemu_x86 + - qemu_x86_64 + - qemu_cortex_a53 + - qemu_riscv64 + platform_exclude: + # linker_zephyr_pre0.cmd:140: syntax error (??) + - qemu_xtensa + # CONFIG_MMU=y but no arch_mem_map() or arch_mem_unmap() + - intel_ish_5_4_1 + - intel_ish_5_6_0 + - intel_ish_5_8_0 +tests: + portability.posix.shm: {} From 24378ed08a1c82f6ae4b7605f6b94123fb8f309b Mon Sep 17 00:00:00 2001 From: Chris Friedt Date: Wed, 5 Jun 2024 22:52:05 -0400 Subject: [PATCH 2808/2849] doc: posix: mark shared memory objects as supported Mark _POSIX_SHARED_MEMORY_OBJECTS as supported. Signed-off-by: Chris Friedt --- doc/services/portability/posix/aep/index.rst | 2 +- doc/services/portability/posix/conformance/index.rst | 2 +- doc/services/portability/posix/option_groups/index.rst | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/doc/services/portability/posix/aep/index.rst b/doc/services/portability/posix/aep/index.rst index e9e31492285b2..aeb591f2ab0a4 100644 --- a/doc/services/portability/posix/aep/index.rst +++ b/doc/services/portability/posix/aep/index.rst @@ -63,7 +63,7 @@ The *Minimal Realtime System Profile* (PSE51) includes all of the :ref:`_POSIX_MEMLOCK `, 200809L, :kconfig:option:`CONFIG_POSIX_MEMLOCK` :ref:`†` :ref:`_POSIX_MEMLOCK_RANGE `, 200809L, :kconfig:option:`CONFIG_POSIX_MEMLOCK_RANGE` :ref:`_POSIX_MONOTONIC_CLOCK `, 200809L, :kconfig:option:`CONFIG_POSIX_MONOTONIC_CLOCK` - :ref:`_POSIX_SHARED_MEMORY_OBJECTS `, -1, + :ref:`_POSIX_SHARED_MEMORY_OBJECTS `, 200809L, :kconfig:option:`CONFIG_POSIX_SHARED_MEMORY_OBJECTS` :ref:`_POSIX_SYNCHRONIZED_IO `, -1, :kconfig:option:`CONFIG_POSIX_SYNCHRONIZED_IO` :ref:`_POSIX_THREAD_ATTR_STACKADDR`, 200809L, :kconfig:option:`CONFIG_POSIX_THREAD_ATTR_STACKADDR` :ref:`_POSIX_THREAD_ATTR_STACKSIZE`, 200809L, :kconfig:option:`CONFIG_POSIX_THREAD_ATTR_STACKSIZE` diff --git a/doc/services/portability/posix/conformance/index.rst b/doc/services/portability/posix/conformance/index.rst index c976ccaee05c5..0aa86e0feb490 100644 --- a/doc/services/portability/posix/conformance/index.rst +++ b/doc/services/portability/posix/conformance/index.rst @@ -75,7 +75,7 @@ POSIX System Interfaces _POSIX_PRIORITIZED_IO, -1, :ref:`_POSIX_PRIORITY_SCHEDULING`, 200809L, :kconfig:option:`CONFIG_POSIX_PRIORITY_SCHEDULING` :ref:`_POSIX_RAW_SOCKETS`, 200809L, :kconfig:option:`CONFIG_POSIX_RAW_SOCKETS` - :ref:`_POSIX_SHARED_MEMORY_OBJECTS `, -1, + :ref:`_POSIX_SHARED_MEMORY_OBJECTS `, 200809L, :kconfig:option:`CONFIG_POSIX_SHARED_MEMORY_OBJECTS` _POSIX_SPAWN, -1, :ref:`†` _POSIX_SPORADIC_SERVER, -1, :ref:`†` :ref:`_POSIX_SYNCHRONIZED_IO `, -1, :kconfig:option:`CONFIG_POSIX_SYNCHRONIZED_IO` diff --git a/doc/services/portability/posix/option_groups/index.rst b/doc/services/portability/posix/option_groups/index.rst index cd9befa785bf6..1633494bbc4e1 100644 --- a/doc/services/portability/posix/option_groups/index.rst +++ b/doc/services/portability/posix/option_groups/index.rst @@ -389,7 +389,7 @@ POSIX_FILE_SYSTEM unlink(), yes utime(), -.. _posix_option_mapped_files: +.. _posix_option_group_mapped_files: POSIX_MAPPED_FILES ================== @@ -776,8 +776,8 @@ _POSIX_SHARED_MEMORY_OBJECTS mmap(), yes munmap(), yes - shm_open(), - shm_unlink(), + shm_open(), yes + shm_unlink(), yes .. _posix_option_synchronized_io: From 64f336c2519b74a9367823e33b0db15a0d1c423d Mon Sep 17 00:00:00 2001 From: Chris Friedt Date: Thu, 6 Jun 2024 09:46:42 -0400 Subject: [PATCH 2809/2849] posix: tie page size to mmu page size Make POSIX_PAGE_SIZE_BITS not user-configurable and tie it to CONFIG_MMU_PAGE_SIZE if there is an MMU. Otherwise, simply default it to something small. Signed-off-by: Chris Friedt --- include/zephyr/posix/posix_features.h | 2 +- lib/posix/options/Kconfig.mem | 14 ++++++-------- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/include/zephyr/posix/posix_features.h b/include/zephyr/posix/posix_features.h index 1a8a921e2f91d..8476e634d5c8a 100644 --- a/include/zephyr/posix/posix_features.h +++ b/include/zephyr/posix/posix_features.h @@ -313,7 +313,7 @@ #endif #ifndef PAGE_SIZE -#define PAGE_SIZE BIT(CONFIG_POSIX_PAGE_SIZE_BITS) +#define PAGE_SIZE CONFIG_POSIX_PAGE_SIZE #endif #ifndef PAGESIZE diff --git a/lib/posix/options/Kconfig.mem b/lib/posix/options/Kconfig.mem index 160a57e80772a..213049870e7de 100644 --- a/lib/posix/options/Kconfig.mem +++ b/lib/posix/options/Kconfig.mem @@ -4,15 +4,13 @@ menu "POSIX memory" -config POSIX_PAGE_SIZE_BITS - int "Number of bits to use for PAGE_SIZE" - range 6 16 - default 12 if POSIX_BASE_DEFINITIONS - default 6 +config POSIX_PAGE_SIZE + hex + # TODO: something similar and arch-independent for MPUs + default MMU_PAGE_SIZE if MMU + default 0x40 help - Define PAGE_SIZE as BIT(n), where n is the value configured here. - PAGE_SIZE is supported in the range [64, 65536] - If CONFIG_POSIX_API=y, PAGE_SIZE defaults to 4096, otherwise, it is 64 bytes. + This option is not user-configurable. config POSIX_SHARED_MEMORY_OBJECTS bool "POSIX shared memory objects [EXPERIMENTAL]" From 2d4346ba53fb84f0ceaf6f5a8febc5f150b82cad Mon Sep 17 00:00:00 2001 From: Chris Friedt Date: Sat, 8 Jun 2024 09:01:07 -0400 Subject: [PATCH 2810/2849] posix: implement mprotect() Provide a stub for mprotect() to satisfy the requirement for the base definitions / system interfaces and subsequently PSE51, PSE52, PSE52, etc. Currently, Zephyr's virtual memory-management API does not seem to support modifying memory protection bits after pages have already been mapped. Signed-off-by: Chris Friedt --- include/zephyr/posix/posix_features.h | 4 +++- include/zephyr/posix/sys/sysconf.h | 3 ++- lib/posix/options/CMakeLists.txt | 1 + lib/posix/options/Kconfig.mem | 10 ++++++++++ lib/posix/options/mprotect.c | 21 +++++++++++++++++++++ 5 files changed, 37 insertions(+), 2 deletions(-) create mode 100644 lib/posix/options/mprotect.c diff --git a/include/zephyr/posix/posix_features.h b/include/zephyr/posix/posix_features.h index 8476e634d5c8a..4e15fbd695019 100644 --- a/include/zephyr/posix/posix_features.h +++ b/include/zephyr/posix/posix_features.h @@ -77,7 +77,9 @@ #define _POSIX_MEMLOCK_RANGE _POSIX_VERSION #endif -/* #define _POSIX_MEMORY_PROTECTION (-1L) */ +#ifdef CONFIG_POSIX_MEMORY_PROTECTION +#define _POSIX_MEMORY_PROTECTION _POSIX_VERSION +#endif #ifdef CONFIG_POSIX_MESSAGE_PASSING #define _POSIX_MESSAGE_PASSING _POSIX_VERSION diff --git a/include/zephyr/posix/sys/sysconf.h b/include/zephyr/posix/sys/sysconf.h index 4241dabd0696d..c7d8228a8cddb 100644 --- a/include/zephyr/posix/sys/sysconf.h +++ b/include/zephyr/posix/sys/sysconf.h @@ -159,7 +159,8 @@ enum { COND_CODE_1(CONFIG_POSIX_MEMLOCK, (_POSIX_MEMLOCK), (-1L)) #define __z_posix_sysconf_SC_MEMLOCK_RANGE \ COND_CODE_1(CONFIG_POSIX_MEMLOCK_RANGE, (_POSIX_MEMLOCK_RANGE), (-1L)) -#define __z_posix_sysconf_SC_MEMORY_PROTECTION (-1L) +#define __z_posix_sysconf_SC_MEMORY_PROTECTION \ + COND_CODE_1(CONFIG_POSIX_MEMORY_PROTECTION, (_POSIX_MEMORY_PROTECTION), (-1L)) #define __z_posix_sysconf_SC_MESSAGE_PASSING \ COND_CODE_1(CONFIG_POSIX_MESSAGE_PASSING, (_POSIX_MESSAGE_PASSING), (-1L)) #define __z_posix_sysconf_SC_MONOTONIC_CLOCK \ diff --git a/lib/posix/options/CMakeLists.txt b/lib/posix/options/CMakeLists.txt index f25af7f427dae..f7da027223d4d 100644 --- a/lib/posix/options/CMakeLists.txt +++ b/lib/posix/options/CMakeLists.txt @@ -53,6 +53,7 @@ zephyr_library_sources_ifdef(CONFIG_POSIX_FILE_SYSTEM fs.c) zephyr_library_sources_ifdef(CONFIG_POSIX_FSYNC fsync.c) zephyr_library_sources_ifdef(CONFIG_POSIX_MEMLOCK mlockall.c) zephyr_library_sources_ifdef(CONFIG_POSIX_MEMLOCK_RANGE mlock.c) +zephyr_library_sources_ifdef(CONFIG_POSIX_MEMORY_PROTECTION mprotect.c) zephyr_library_sources_ifdef(CONFIG_POSIX_MAPPED_FILES mmap.c) zephyr_library_sources_ifdef(CONFIG_POSIX_MESSAGE_PASSING mqueue.c) zephyr_library_sources_ifdef(CONFIG_POSIX_MULTI_PROCESS diff --git a/lib/posix/options/Kconfig.mem b/lib/posix/options/Kconfig.mem index 213049870e7de..57b9ad9670e41 100644 --- a/lib/posix/options/Kconfig.mem +++ b/lib/posix/options/Kconfig.mem @@ -63,4 +63,14 @@ config POSIX_MEMLOCK_RANGE endif +config POSIX_MEMORY_PROTECTION + bool "POSIX memory protection [EXPERIMENTAL]" + select EXPERIMENTAL + help + Select 'y' here and Zephyr will provide support for mprotect(). + + For more information, please see + https://pubs.opengroup.org/onlinepubs/9699919799.orig/functions/V2_chap02.html + https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_port.html#tag_24_03_04 + endmenu diff --git a/lib/posix/options/mprotect.c b/lib/posix/options/mprotect.c new file mode 100644 index 0000000000000..3bd2762763af3 --- /dev/null +++ b/lib/posix/options/mprotect.c @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2024, Tenstorrent AI ULC + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +#include + +int mprotect(void *addr, size_t len, int prot) +{ + ARG_UNUSED(addr); + ARG_UNUSED(len); + ARG_UNUSED(prot); + + errno = ENOSYS; + return -1; +} From 0af0187095c7b4a6d7bcd9d72d44ce85baa36adf Mon Sep 17 00:00:00 2001 From: Chris Friedt Date: Sat, 8 Jun 2024 09:05:39 -0400 Subject: [PATCH 2811/2849] doc: posix: mark memory protection as supported Mark _POSIX_MEMORY_PROTECTION as supported (i.e. a conformant application will link). Zephyr's mm API does not currently support modifying memory protection bits after pages have been mapped, so use of this function may result in undefined behaviour. Signed-off-by: Chris Friedt --- doc/services/portability/posix/conformance/index.rst | 2 +- .../portability/posix/option_groups/index.rst | 11 +++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/doc/services/portability/posix/conformance/index.rst b/doc/services/portability/posix/conformance/index.rst index 0aa86e0feb490..4cd8687ebf4fa 100644 --- a/doc/services/portability/posix/conformance/index.rst +++ b/doc/services/portability/posix/conformance/index.rst @@ -37,7 +37,7 @@ POSIX System Interfaces :ref:`_POSIX_BARRIERS`, 200809L, :kconfig:option:`CONFIG_POSIX_BARRIERS` :ref:`_POSIX_CLOCK_SELECTION`, 200809L, :kconfig:option:`CONFIG_POSIX_CLOCK_SELECTION` :ref:`_POSIX_MAPPED_FILES`, 200809L, :kconfig:option:`CONFIG_POSIX_MAPPED_FILES` - _POSIX_MEMORY_PROTECTION, -1, :ref:`†` + :ref:`_POSIX_MEMORY_PROTECTION`, 200809L, :kconfig:option:`CONFIG_POSIX_MEMORY_PROTECTION` :ref:`†` :ref:`_POSIX_READER_WRITER_LOCKS`, 200809L, :kconfig:option:`CONFIG_POSIX_READER_WRITER_LOCKS` :ref:`_POSIX_REALTIME_SIGNALS`, -1, :kconfig:option:`CONFIG_POSIX_REALTIME_SIGNALS` :ref:`_POSIX_SEMAPHORES`, 200809L, :kconfig:option:`CONFIG_POSIX_SEMAPHORES` diff --git a/doc/services/portability/posix/option_groups/index.rst b/doc/services/portability/posix/option_groups/index.rst index 1633494bbc4e1..8339e200e05c1 100644 --- a/doc/services/portability/posix/option_groups/index.rst +++ b/doc/services/portability/posix/option_groups/index.rst @@ -572,6 +572,17 @@ This table lists service support status in Zephyr for `POSIX_FD_MGMT`: putc_unlocked(), putchar_unlocked(), +.. _posix_option_group_memory_protection: + +POSIX_MEMORY_PROTECTION +======================= + +.. csv-table:: POSIX_MEMORY_PROTECTION + :header: API, Supported + :widths: 50,10 + + mprotect(), yes :ref:`†` + .. _posix_option_group_multi_process: POSIX_MULTI_PROCESS From 298bf49048ffc03a5b9ee233bbde98aaf1671835 Mon Sep 17 00:00:00 2001 From: Francois Ramu Date: Tue, 2 Apr 2024 10:41:04 +0200 Subject: [PATCH 2812/2849] samples: sensor: dht_polling run sample on sensor present Add a fixture to run the sample only when the DHT sensor HX330x is present (shield) on the nucleo_f40re board 'fixture_i2c_hs300x' The stm32f401 Nucleo board itself has no sensor mounted Signed-off-by: Francois Ramu --- samples/sensor/dht_polling/README.rst | 12 +++++++++++- samples/sensor/dht_polling/sample.yaml | 1 + 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/samples/sensor/dht_polling/README.rst b/samples/sensor/dht_polling/README.rst index 09550b255d00b..b985c9e0a082e 100644 --- a/samples/sensor/dht_polling/README.rst +++ b/samples/sensor/dht_polling/README.rst @@ -23,7 +23,17 @@ be aliased as ``dhtN`` where ``N`` goes from ``0`` to ``9``. For example: }; }; -Make sure the aliases are in devicetree, then build and run with: + +Make sure the aliases are in devicetree. + +It also requires a correct fixture setup when the sensor is present. +For the correct execution of that sample in twister, add into boards's +map-file next fixture settings:: + + - fixture: fixture_i2c_hs300x + + +Then build and run with: .. zephyr-app-commands:: :zephyr-app: samples/sensor/dht_polling diff --git a/samples/sensor/dht_polling/sample.yaml b/samples/sensor/dht_polling/sample.yaml index 8177e636d2167..50cf2ef6d7ce6 100644 --- a/samples/sensor/dht_polling/sample.yaml +++ b/samples/sensor/dht_polling/sample.yaml @@ -15,6 +15,7 @@ tests: - nucleo_f401re harness: console harness_config: + fixture: fixture_i2c_hs300x type: one_line regex: - "[0-9A-Za-z_,+-.]*@[0-9A-Fa-f]*: temp is (.*) °C humidity is (.*) %RH" From 703e5258eb8f5133cc73c4d6bffa966556ce52c1 Mon Sep 17 00:00:00 2001 From: Tomi Fontanilles Date: Thu, 30 May 2024 13:20:56 +0300 Subject: [PATCH 2813/2849] mgmt: updatehub: replace TinyCrypt by PSA As part of ongoing work to move away from TinyCrypt and towards PSA (#43712), introduce a PSA option and remove the TinyCrypt one for the SHA-256 implementation. The Mbed TLS implementation is modified to use `mbedtls_sha256` directly for smaller code size. The reliance of mgmt/updatehub on storage/flash_map's configuration (`FLASH_AREA_CHECK_INTEGRITY_BACKEND`) is removed. The choice of which implementation to use is made automatically, based on whether a PSA API provider is present (`PSA_CRYPTO_CLIENT`). This commit also add a test case with PSA (based on Mbed TLS) in samples/subsys/mgmt/updatehub/sample.yaml. Signed-off-by: Tomi Fontanilles Signed-off-by: Valerio Setti --- doc/releases/migration-guide-3.7.rst | 9 ++ .../subsys/mgmt/updatehub/overlay-psa.conf | 3 + samples/subsys/mgmt/updatehub/sample.yaml | 7 ++ subsys/mgmt/updatehub/Kconfig | 10 +- subsys/mgmt/updatehub/updatehub.c | 4 +- subsys/mgmt/updatehub/updatehub_integrity.c | 100 ++++++++---------- subsys/mgmt/updatehub/updatehub_integrity.h | 26 ++--- 7 files changed, 79 insertions(+), 80 deletions(-) create mode 100644 samples/subsys/mgmt/updatehub/overlay-psa.conf diff --git a/doc/releases/migration-guide-3.7.rst b/doc/releases/migration-guide-3.7.rst index 4e9140c8f670d..126cc45b9f395 100644 --- a/doc/releases/migration-guide-3.7.rst +++ b/doc/releases/migration-guide-3.7.rst @@ -838,6 +838,15 @@ State Machine Framework 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. +UpdateHub +========= + +* The SHA-256 implementation used to perform integrity checks is not chosen with + :kconfig:option:`CONFIG_FLASH_AREA_CHECK_INTEGRITY_BACKEND` anymore. Instead, the implementation + used (now either Mbed TLS or PSA) is chosen based on :kconfig:option:`CONFIG_PSA_CRYPTO_CLIENT`. + It still defaults to using Mbed TLS (with a smaller footprint than previously) unless the + board is built with TF-M or :kconfig:option:`CONFIG_MBEDTLS_PSA_CRYPTO_C` is enabled. (:github:`73511`) + ZBus ==== diff --git a/samples/subsys/mgmt/updatehub/overlay-psa.conf b/samples/subsys/mgmt/updatehub/overlay-psa.conf new file mode 100644 index 0000000000000..4b5dcfd9af67d --- /dev/null +++ b/samples/subsys/mgmt/updatehub/overlay-psa.conf @@ -0,0 +1,3 @@ +CONFIG_FLASH_AREA_CHECK_INTEGRITY_PSA=y +CONFIG_MBEDTLS=y +CONFIG_MBEDTLS_PSA_CRYPTO_C=y diff --git a/samples/subsys/mgmt/updatehub/sample.yaml b/samples/subsys/mgmt/updatehub/sample.yaml index 7f664bb2dfeae..de8192d957e0a 100644 --- a/samples/subsys/mgmt/updatehub/sample.yaml +++ b/samples/subsys/mgmt/updatehub/sample.yaml @@ -19,6 +19,13 @@ tests: - CONFIG_UPDATEHUB_POLL_INTERVAL=1 - CONFIG_UPDATEHUB_CE=y - CONFIG_UPDATEHUB_SERVER="updatehub.io" + sample.net.updatehub.psa: + extra_args: OVERLAY_CONFIG="overlay-psa.conf" + extra_configs: + - CONFIG_UPDATEHUB_PRODUCT_UID="e4d37cfe6ec48a2d069cc0bbb8b078677e9a0d8df3a027c4d8ea131130c4265f" + - CONFIG_UPDATEHUB_POLL_INTERVAL=1 + - CONFIG_UPDATEHUB_CE=y + - CONFIG_UPDATEHUB_SERVER="updatehub.io" sample.net.updatehub.userspace: extra_configs: - CONFIG_UPDATEHUB_PRODUCT_UID="e4d37cfe6ec48a2d069cc0bbb8b078677e9a0d8df3a027c4d8ea131130c4265f" diff --git a/subsys/mgmt/updatehub/Kconfig b/subsys/mgmt/updatehub/Kconfig index 93859499e5977..eb19b6442edc3 100644 --- a/subsys/mgmt/updatehub/Kconfig +++ b/subsys/mgmt/updatehub/Kconfig @@ -2,7 +2,7 @@ # SPDX-License-Identifier: Apache-2.0 menuconfig UPDATEHUB - bool"UpdateHub Firmware Over-the-Air support" + bool "UpdateHub Firmware Over-the-Air support" depends on FLASH depends on REBOOT depends on IMG_MANAGER @@ -17,6 +17,8 @@ menuconfig UPDATEHUB select REQUIRES_FULL_LIBC select IMG_ENABLE_IMAGE_CHECK select MPU_ALLOW_FLASH_WRITE + select MBEDTLS if !BUILD_WITH_TFM + select MBEDTLS_SHA256 if !PSA_CRYPTO_CLIENT help UpdateHub is an enterprise-grade solution which makes simple to remotely update all your embedded devices in the field. It @@ -69,7 +71,7 @@ config UPDATEHUB_SHELL Activate shell module that provides UpdateHub commands like config UPDATEHUB_DTLS - bool"Activate communication CoAPS/DTLS" + bool "Activate communication CoAPS/DTLS" select MBEDTLS select MBEDTLS_ENABLE_HEAP select NET_SOCKETS_SOCKOPT_TLS @@ -146,10 +148,6 @@ config UPDATEHUB_DOWNLOAD_STORAGE_SHA256_VERIFICATION endchoice -choice FLASH_AREA_CHECK_INTEGRITY_BACKEND - default FLASH_AREA_CHECK_INTEGRITY_MBEDTLS -endchoice - module = UPDATEHUB module-str = Log level for UpdateHub module-help = Enables logging for UpdateHub code. diff --git a/subsys/mgmt/updatehub/updatehub.c b/subsys/mgmt/updatehub/updatehub.c index 1886b634a765e..95f3b67e1ca8f 100644 --- a/subsys/mgmt/updatehub/updatehub.c +++ b/subsys/mgmt/updatehub/updatehub.c @@ -61,7 +61,7 @@ static struct updatehub_context { struct coap_block_context block; struct k_sem semaphore; struct updatehub_storage_context storage_ctx; - struct updatehub_crypto_context crypto_ctx; + updatehub_crypto_context_t crypto_ctx; enum updatehub_response code_status; uint8_t hash[SHA256_BIN_DIGEST_SIZE]; uint8_t uri_path[MAX_PATH_SIZE]; @@ -113,7 +113,7 @@ static void prepare_fds(void) static int metadata_hash_get(char *metadata) { - struct updatehub_crypto_context local_crypto_ctx; + updatehub_crypto_context_t local_crypto_ctx; if (updatehub_integrity_init(&local_crypto_ctx)) { return -1; diff --git a/subsys/mgmt/updatehub/updatehub_integrity.c b/subsys/mgmt/updatehub/updatehub_integrity.c index d9f0c8e1a3582..dcebcf6d39d61 100644 --- a/subsys/mgmt/updatehub/updatehub_integrity.c +++ b/subsys/mgmt/updatehub/updatehub_integrity.c @@ -9,7 +9,13 @@ LOG_MODULE_DECLARE(updatehub, CONFIG_UPDATEHUB_LOG_LEVEL); #include "updatehub_integrity.h" -int updatehub_integrity_init(struct updatehub_crypto_context *ctx) +#if defined(CONFIG_PSA_CRYPTO_CLIENT) +#define SUCCESS_VALUE PSA_SUCCESS +#else +#define SUCCESS_VALUE 0 +#endif + +int updatehub_integrity_init(updatehub_crypto_context_t *ctx) { int ret; @@ -18,43 +24,22 @@ int updatehub_integrity_init(struct updatehub_crypto_context *ctx) return -EINVAL; } - memset(ctx, 0, sizeof(struct updatehub_crypto_context)); - -#if defined(CONFIG_FLASH_AREA_CHECK_INTEGRITY_MBEDTLS) - ctx->md_info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA256); - if (ctx->md_info == NULL) { - LOG_DBG("Message Digest not found or not enabled"); - return -ENOENT; - } - - mbedtls_md_init(&ctx->md_ctx); - ret = mbedtls_md_setup(&ctx->md_ctx, ctx->md_info, 0); - if (ret == MBEDTLS_ERR_MD_BAD_INPUT_DATA) { - LOG_DBG("Bad Message Digest selected"); - return -EFAULT; - } - if (ret == MBEDTLS_ERR_MD_ALLOC_FAILED) { - LOG_DBG("Failed to allocate memory"); - return -ENOMEM; - } - - ret = mbedtls_md_starts(&ctx->md_ctx); - if (ret == MBEDTLS_ERR_MD_BAD_INPUT_DATA) { - LOG_DBG("Bad Message Digest selected"); - return -EFAULT; - } -#elif defined(CONFIG_FLASH_AREA_CHECK_INTEGRITY_TC) - ret = tc_sha256_init(&ctx->sha256sum); - if (ret != TC_CRYPTO_SUCCESS) { - LOG_DBG("Invalid integrity context"); +#if defined(CONFIG_PSA_CRYPTO_CLIENT) + *ctx = psa_hash_operation_init(); + ret = psa_hash_setup(ctx, PSA_ALG_SHA_256); +#else + mbedtls_sha256_init(ctx); + ret = mbedtls_sha256_starts(ctx, false); +#endif + if (ret != SUCCESS_VALUE) { + LOG_DBG("Failed to %s SHA-256 operation. (%d)", "set up", ret); return -EFAULT; } -#endif return 0; } -int updatehub_integrity_update(struct updatehub_crypto_context *ctx, +int updatehub_integrity_update(updatehub_crypto_context_t *ctx, const uint8_t *buffer, const uint32_t len) { int ret; @@ -68,24 +53,27 @@ int updatehub_integrity_update(struct updatehub_crypto_context *ctx, return 0; } -#if defined(CONFIG_FLASH_AREA_CHECK_INTEGRITY_MBEDTLS) - ret = mbedtls_md_update(&ctx->md_ctx, buffer, len); - if (ret == MBEDTLS_ERR_MD_BAD_INPUT_DATA) { - LOG_DBG("Bad Message Digest selected"); - return -EFAULT; +#if defined(CONFIG_PSA_CRYPTO_CLIENT) + ret = psa_hash_update(ctx, buffer, len); + if (ret != PSA_SUCCESS) { + psa_hash_abort(ctx); } -#elif defined(CONFIG_FLASH_AREA_CHECK_INTEGRITY_TC) - ret = tc_sha256_update(&ctx->sha256sum, buffer, len); - if (ret != TC_CRYPTO_SUCCESS) { - LOG_DBG("Invalid integrity context or invalid buffer"); - return -EFAULT; +#else + ret = mbedtls_sha256_update(ctx, buffer, len); + if (ret != 0) { + mbedtls_sha256_free(ctx); } #endif + if (ret != SUCCESS_VALUE) { + LOG_DBG("Failed to %s SHA-256 operation. (%d)", "update", ret); + return -EFAULT; + } + return 0; } -int updatehub_integrity_finish(struct updatehub_crypto_context *ctx, +int updatehub_integrity_finish(updatehub_crypto_context_t *ctx, uint8_t *hash, const uint32_t size) { int ret; @@ -94,26 +82,26 @@ int updatehub_integrity_finish(struct updatehub_crypto_context *ctx, return -EINVAL; } -#if defined(CONFIG_FLASH_AREA_CHECK_INTEGRITY_MBEDTLS) - if (size < mbedtls_md_get_size(ctx->md_info)) { + if (size < SHA256_BIN_DIGEST_SIZE) { LOG_DBG("HASH input buffer is to small to store the message digest"); return -EINVAL; } - ret = mbedtls_md_finish(&ctx->md_ctx, hash); - if (ret == MBEDTLS_ERR_MD_BAD_INPUT_DATA) { - LOG_DBG("Bad Message Digest selected"); - return -EFAULT; - } +#if defined(CONFIG_PSA_CRYPTO_CLIENT) + size_t hash_len; - mbedtls_md_free(&ctx->md_ctx); -#elif defined(CONFIG_FLASH_AREA_CHECK_INTEGRITY_TC) - ret = tc_sha256_final(hash, &ctx->sha256sum); - if (ret != TC_CRYPTO_SUCCESS) { - LOG_DBG("Invalid integrity context or invalid hash pointer"); - return -EFAULT; + ret = psa_hash_finish(ctx, hash, size, &hash_len); + if (ret != PSA_SUCCESS) { + psa_hash_abort(ctx); } +#else + ret = mbedtls_sha256_finish(ctx, hash); + mbedtls_sha256_free(ctx); #endif + if (ret != SUCCESS_VALUE) { + LOG_DBG("Failed to %s SHA-256 operation. (%d)", "finish", ret); + return -EFAULT; + } return 0; } diff --git a/subsys/mgmt/updatehub/updatehub_integrity.h b/subsys/mgmt/updatehub/updatehub_integrity.h index d960c8f8ef8a4..dcec7ecdb286c 100644 --- a/subsys/mgmt/updatehub/updatehub_integrity.h +++ b/subsys/mgmt/updatehub/updatehub_integrity.h @@ -7,13 +7,10 @@ #ifndef __UPDATEHUB_INTEGRITY_H__ #define __UPDATEHUB_INTEGRITY_H__ -#if defined(CONFIG_FLASH_AREA_CHECK_INTEGRITY_MBEDTLS) -#include -#elif defined(CONFIG_FLASH_AREA_CHECK_INTEGRITY_TC) -#include -#include +#if defined(CONFIG_PSA_CRYPTO_CLIENT) +#include #else -#error "Integrity check method not defined" +#include #endif #ifdef __cplusplus @@ -23,19 +20,16 @@ extern "C" { #define SHA256_BIN_DIGEST_SIZE (32) #define SHA256_HEX_DIGEST_SIZE ((SHA256_BIN_DIGEST_SIZE * 2) + 1) -struct updatehub_crypto_context { -#if defined(CONFIG_FLASH_AREA_CHECK_INTEGRITY_MBEDTLS) - mbedtls_md_context_t md_ctx; - const mbedtls_md_info_t *md_info; -#elif defined(CONFIG_FLASH_AREA_CHECK_INTEGRITY_TC) - struct tc_sha256_state_struct sha256sum; +#if defined(CONFIG_PSA_CRYPTO_CLIENT) +typedef psa_hash_operation_t updatehub_crypto_context_t; +#else +typedef mbedtls_sha256_context updatehub_crypto_context_t; #endif -}; -int updatehub_integrity_init(struct updatehub_crypto_context *ctx); -int updatehub_integrity_update(struct updatehub_crypto_context *ctx, +int updatehub_integrity_init(updatehub_crypto_context_t *ctx); +int updatehub_integrity_update(updatehub_crypto_context_t *ctx, const uint8_t *buffer, const uint32_t len); -int updatehub_integrity_finish(struct updatehub_crypto_context *ctx, +int updatehub_integrity_finish(updatehub_crypto_context_t *ctx, uint8_t *hash, const uint32_t size); #ifdef __cplusplus From f2c643ba0205c00dccea56af5294c60d1e92aea3 Mon Sep 17 00:00:00 2001 From: Tomi Fontanilles Date: Thu, 30 May 2024 13:31:08 +0300 Subject: [PATCH 2814/2849] storage: flash_map: replace TinyCrypt by PSA As part of ongoing work to move away from TinyCrypt and towards PSA (#43712), introduce a PSA option and remove the TinyCrypt one for the SHA-256 implementation. The Mbed TLS implementation is modified to use `mbedtls_sha256` directly for smaller code size. As of now the implementation defaults to PSA only if TF-M is enabled because a dependency loop happens if using `PSA_CRYPTO_CLIENT` as a condition in `FLASH_AREA_CHECK_INTEGRITY_BACKEND`. A test case is added for the PSA implementation, and an NS platform is added to the base test case to verify the compilation on a TF-M-enabled platform. Signed-off-by: Tomi Fontanilles --- doc/releases/migration-guide-3.7.rst | 11 +++ subsys/storage/flash_map/CMakeLists.txt | 4 +- subsys/storage/flash_map/Kconfig | 22 ++--- .../storage/flash_map/flash_map_integrity.c | 81 ++++++++----------- .../subsys/storage/flash_map/overlay-psa.conf | 3 + tests/subsys/storage/flash_map/testcase.yaml | 13 +++ 6 files changed, 73 insertions(+), 61 deletions(-) create mode 100644 tests/subsys/storage/flash_map/overlay-psa.conf diff --git a/doc/releases/migration-guide-3.7.rst b/doc/releases/migration-guide-3.7.rst index 126cc45b9f395..bdd4e884d23c9 100644 --- a/doc/releases/migration-guide-3.7.rst +++ b/doc/releases/migration-guide-3.7.rst @@ -781,6 +781,17 @@ Networking Other Subsystems **************** +Flash map +========= + +* The crypto backend for the flash check functions (:kconfig:option:`CONFIG_FLASH_AREA_CHECK_INTEGRITY_BACKEND`), + previously provided through either TinyCrypt or Mbed TLS, is now provided through either PSA or Mbed TLS. + The updated Mbed TLS implementation has a slightly smaller footprint than the previous TinyCrypt one, + and the PSA implementation offers an even greater footprint reduction for devices built with TF-M. + PSA is the supported way forward, however as of now you may still use Mbed TLS if you cannot afford the + one-time cost of enabling the PSA API (:kconfig:option:`CONFIG_MBEDTLS_PSA_CRYPTO_C` for devices without TF-M). + :github:`73511` + hawkBit ======= diff --git a/subsys/storage/flash_map/CMakeLists.txt b/subsys/storage/flash_map/CMakeLists.txt index 906762f6b177c..b0ee70768d74c 100644 --- a/subsys/storage/flash_map/CMakeLists.txt +++ b/subsys/storage/flash_map/CMakeLists.txt @@ -6,6 +6,4 @@ zephyr_sources_ifdef(CONFIG_FLASH_MAP_SHELL flash_map_shell.c) zephyr_sources_ifdef(CONFIG_FLASH_PAGE_LAYOUT flash_map_layout.c) zephyr_sources_ifdef(CONFIG_FLASH_AREA_CHECK_INTEGRITY flash_map_integrity.c) -if(CONFIG_FLASH_AREA_CHECK_INTEGRITY_MBEDTLS) - zephyr_library_link_libraries_ifdef(CONFIG_MBEDTLS mbedTLS) -endif() +zephyr_library_link_libraries_ifdef(CONFIG_MBEDTLS mbedTLS) diff --git a/subsys/storage/flash_map/Kconfig b/subsys/storage/flash_map/Kconfig index cbe5c1599b329..b29da6da971da 100644 --- a/subsys/storage/flash_map/Kconfig +++ b/subsys/storage/flash_map/Kconfig @@ -43,27 +43,27 @@ config FLASH_MAP_LABELS flash_map list shell command. if FLASH_AREA_CHECK_INTEGRITY + choice FLASH_AREA_CHECK_INTEGRITY_BACKEND prompt "Crypto backend for the flash check functions" - default FLASH_AREA_CHECK_INTEGRITY_TC + default FLASH_AREA_CHECK_INTEGRITY_PSA if BUILD_WITH_TFM + default FLASH_AREA_CHECK_INTEGRITY_MBEDTLS if !BUILD_WITH_TFM -config FLASH_AREA_CHECK_INTEGRITY_TC - bool "Use TinyCrypt" - select TINYCRYPT - select TINYCRYPT_SHA256 +config FLASH_AREA_CHECK_INTEGRITY_PSA + bool "Use PSA" + select PSA_WANT_ALG_SHA_256 help - Use TinyCrypt library to perform the integrity check. + Use the PSA API to perform the integrity check. config FLASH_AREA_CHECK_INTEGRITY_MBEDTLS - bool "Use MBEDTLS" + bool "Use Mbed TLS" select MBEDTLS - select MBEDTLS_MD select MBEDTLS_SHA256 - select MBEDTLS_ENABLE_HEAP help - Use MBEDTLS library to perform the integrity check. + Use the Mbed TLS library to perform the integrity check. endchoice -endif + +endif # FLASH_AREA_CHECK_INTEGRITY endif diff --git a/subsys/storage/flash_map/flash_map_integrity.c b/subsys/storage/flash_map/flash_map_integrity.c index e9556abef6356..7e512e759db26 100644 --- a/subsys/storage/flash_map/flash_map_integrity.c +++ b/subsys/storage/flash_map/flash_map_integrity.c @@ -11,6 +11,7 @@ #include #include +#include #include #include #include @@ -18,26 +19,23 @@ #include #include -#if defined(CONFIG_FLASH_AREA_CHECK_INTEGRITY) #define SHA256_DIGEST_SIZE 32 -#if defined(CONFIG_FLASH_AREA_CHECK_INTEGRITY_TC) -#include -#include +#if defined(CONFIG_FLASH_AREA_CHECK_INTEGRITY_PSA) +#include +#define SUCCESS_VALUE PSA_SUCCESS #else -#include +#include +#define SUCCESS_VALUE 0 #endif -#include -#endif /* CONFIG_FLASH_AREA_CHECK_INTEGRITY */ int flash_area_check_int_sha256(const struct flash_area *fa, const struct flash_area_check *fac) { unsigned char hash[SHA256_DIGEST_SIZE]; -#if defined(CONFIG_FLASH_AREA_CHECK_INTEGRITY_TC) - struct tc_sha256_state_struct sha; +#if defined(CONFIG_FLASH_AREA_CHECK_INTEGRITY_PSA) + psa_hash_operation_t hash_ctx; #else /* CONFIG_FLASH_AREA_CHECK_INTEGRITY_MBEDTLS */ - mbedtls_md_context_t mbed_hash_ctx; - const mbedtls_md_info_t *mbed_hash_info; + mbedtls_sha256_context hash_ctx; #endif int to_read; int pos; @@ -52,25 +50,17 @@ int flash_area_check_int_sha256(const struct flash_area *fa, return -EINVAL; } -#if defined(CONFIG_FLASH_AREA_CHECK_INTEGRITY_TC) - if (tc_sha256_init(&sha) != TC_CRYPTO_SUCCESS) { - return -ESRCH; - } +#if defined(CONFIG_FLASH_AREA_CHECK_INTEGRITY_PSA) + hash_ctx = psa_hash_operation_init(); + rc = psa_hash_setup(&hash_ctx, PSA_ALG_SHA_256); #else /* CONFIG_FLASH_AREA_CHECK_INTEGRITY_MBEDTLS */ - 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) { + mbedtls_sha256_init(&hash_ctx); + rc = mbedtls_sha256_starts(&hash_ctx, false); +#endif + if (rc != SUCCESS_VALUE) { return -ESRCH; } - if (mbedtls_md_starts(&mbed_hash_ctx)) { - rc = -ESRCH; - goto error; - } -#endif - to_read = fac->rblen; for (pos = 0; pos < fac->clen; pos += to_read) { @@ -81,40 +71,35 @@ int flash_area_check_int_sha256(const struct flash_area *fa, rc = flash_read(fa->fa_dev, (fa->fa_off + fac->off + pos), fac->rbuf, to_read); if (rc != 0) { -#if defined(CONFIG_FLASH_AREA_CHECK_INTEGRITY_TC) - return rc; -#else /* CONFIG_FLASH_AREA_CHECK_INTEGRITY_MBEDTLS */ goto error; -#endif } -#if defined(CONFIG_FLASH_AREA_CHECK_INTEGRITY_TC) - if (tc_sha256_update(&sha, - fac->rbuf, - to_read) != TC_CRYPTO_SUCCESS) { - return -ESRCH; - } +#if defined(CONFIG_FLASH_AREA_CHECK_INTEGRITY_PSA) + rc = psa_hash_update(&hash_ctx, fac->rbuf, to_read); #else /* CONFIG_FLASH_AREA_CHECK_INTEGRITY_MBEDTLS */ - if (mbedtls_md_update(&mbed_hash_ctx, fac->rbuf, to_read) != 0) { + rc = mbedtls_sha256_update(&hash_ctx, fac->rbuf, to_read); +#endif + if (rc != SUCCESS_VALUE) { rc = -ESRCH; goto error; } -#endif } -#if defined(CONFIG_FLASH_AREA_CHECK_INTEGRITY_TC) - if (tc_sha256_final(hash, &sha) != TC_CRYPTO_SUCCESS) { - return -ESRCH; - } +#if defined(CONFIG_FLASH_AREA_CHECK_INTEGRITY_PSA) + size_t hash_len; + + rc = psa_hash_finish(&hash_ctx, hash, sizeof(hash), &hash_len); #else /* CONFIG_FLASH_AREA_CHECK_INTEGRITY_MBEDTLS */ - if (mbedtls_md_finish(&mbed_hash_ctx, hash) != 0) { + rc = mbedtls_sha256_finish(&hash_ctx, hash); +#endif + if (rc != SUCCESS_VALUE) { rc = -ESRCH; goto error; } -#endif if (memcmp(hash, fac->match, SHA256_DIGEST_SIZE)) { -#if defined(CONFIG_FLASH_AREA_CHECK_INTEGRITY_TC) +#if defined(CONFIG_FLASH_AREA_CHECK_INTEGRITY_PSA) + /* The operation has already been terminated. */ return -EILSEQ; #else /* CONFIG_FLASH_AREA_CHECK_INTEGRITY_MBEDTLS */ rc = -EILSEQ; @@ -122,9 +107,11 @@ int flash_area_check_int_sha256(const struct flash_area *fa, #endif } -#if defined(CONFIG_FLASH_AREA_CHECK_INTEGRITY_MBEDTLS) error: - mbedtls_md_free(&mbed_hash_ctx); +#if defined(CONFIG_FLASH_AREA_CHECK_INTEGRITY_PSA) + psa_hash_abort(&hash_ctx); +#else /* CONFIG_FLASH_AREA_CHECK_INTEGRITY_MBEDTLS */ + mbedtls_sha256_free(&hash_ctx); #endif return rc; } diff --git a/tests/subsys/storage/flash_map/overlay-psa.conf b/tests/subsys/storage/flash_map/overlay-psa.conf new file mode 100644 index 0000000000000..4b5dcfd9af67d --- /dev/null +++ b/tests/subsys/storage/flash_map/overlay-psa.conf @@ -0,0 +1,3 @@ +CONFIG_FLASH_AREA_CHECK_INTEGRITY_PSA=y +CONFIG_MBEDTLS=y +CONFIG_MBEDTLS_PSA_CRYPTO_C=y diff --git a/tests/subsys/storage/flash_map/testcase.yaml b/tests/subsys/storage/flash_map/testcase.yaml index 3ed44f28e07e3..43934a1589a16 100644 --- a/tests/subsys/storage/flash_map/testcase.yaml +++ b/tests/subsys/storage/flash_map/testcase.yaml @@ -2,6 +2,7 @@ tests: storage.flash_map: platform_allow: - nrf51dk/nrf51822 + - nrf9160dk/nrf9160/ns - qemu_x86 - native_posix - native_posix/native/64 @@ -35,3 +36,15 @@ tests: tags: flash_map integration_platforms: - native_sim + storage.flash_map.psa: + extra_args: OVERLAY_CONFIG=overlay-psa.conf + platform_allow: + - nrf51dk/nrf51822 + - native_posix + - native_posix/native/64 + - native_sim + - native_sim/native/64 + - mr_canhubk3 + tags: flash_map + integration_platforms: + - native_sim From 2e04cfd88728a501b9565e5d9fe8c4fd9d04c21d Mon Sep 17 00:00:00 2001 From: Daniel Mangum Date: Mon, 10 Jun 2024 09:08:48 -0400 Subject: [PATCH 2815/2849] boards: esp32s3_devkitm: remove conflicting usb_serial reference The usb_serial node is referenced twice in the procpu dts file. The first time the status is set to "okay", while the second it is set to "disabled". Only the second status is honored, so the first is removed to eliminate confusion. Signed-off-by: Daniel Mangum --- boards/espressif/esp32s3_devkitm/esp32s3_devkitm_procpu.dts | 4 ---- 1 file changed, 4 deletions(-) diff --git a/boards/espressif/esp32s3_devkitm/esp32s3_devkitm_procpu.dts b/boards/espressif/esp32s3_devkitm/esp32s3_devkitm_procpu.dts index c88bf0d01012e..95390a0324bf0 100644 --- a/boards/espressif/esp32s3_devkitm/esp32s3_devkitm_procpu.dts +++ b/boards/espressif/esp32s3_devkitm/esp32s3_devkitm_procpu.dts @@ -43,10 +43,6 @@ }; }; -&usb_serial { - status = "okay"; -}; - &uart0 { status = "okay"; current-speed = <115200>; From 9faf111744ae4e50b917d6bd9ae4f823e22b5b37 Mon Sep 17 00:00:00 2001 From: Dong Wang Date: Thu, 13 Jun 2024 20:19:07 +0800 Subject: [PATCH 2816/2849] dts: bindings: dma: correct compatible name of Intel SEDI dma controller Replace an underscore with a hyphen in the name to align with the general naming convention. Signed-off-by: Dong Wang --- dts/bindings/dma/{intel,sedi_dma.yaml => intel,sedi-dma.yaml} | 2 +- dts/x86/intel/intel_ish5.dtsi | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) rename dts/bindings/dma/{intel,sedi_dma.yaml => intel,sedi-dma.yaml} (91%) diff --git a/dts/bindings/dma/intel,sedi_dma.yaml b/dts/bindings/dma/intel,sedi-dma.yaml similarity index 91% rename from dts/bindings/dma/intel,sedi_dma.yaml rename to dts/bindings/dma/intel,sedi-dma.yaml index 3fe1036c00c9f..8e708cc232f73 100644 --- a/dts/bindings/dma/intel,sedi_dma.yaml +++ b/dts/bindings/dma/intel,sedi-dma.yaml @@ -4,7 +4,7 @@ description: Intel SEDI DMA controller. -compatible: "intel,sedi_dma" +compatible: "intel,sedi-dma" include: dma-controller.yaml diff --git a/dts/x86/intel/intel_ish5.dtsi b/dts/x86/intel/intel_ish5.dtsi index 5f2ef6a1960c3..81abf748b9342 100644 --- a/dts/x86/intel/intel_ish5.dtsi +++ b/dts/x86/intel/intel_ish5.dtsi @@ -189,7 +189,7 @@ }; dma0: dma@10100000 { - compatible = "intel,sedi_dma"; + compatible = "intel,sedi-dma"; #dma-cells = <2>; dma-channels = <8>; peripheral-id = <0>; From a2386efbce1866613f7c714b958a159364dc5f37 Mon Sep 17 00:00:00 2001 From: Damian Nikodem Date: Mon, 10 Jun 2024 20:12:39 +0200 Subject: [PATCH 2817/2849] drivers: ssp: update SSP driver to support Intel ACE30 PTL This commit refactors the SSP driver to support the Intel ACE30 PTL platform. The changes include: - Adding new structures ssp_rx_dir and ssp_tx_dir to hold the TDM slot configuration for RX and TX directions - Adjusting the dai_ssp_set_config_blob functions to work with the new TDM slot configuration. Signed-off-by: Damian Nikodem --- drivers/dai/intel/ssp/dai-params-intel-ipc4.h | 9 + drivers/dai/intel/ssp/ssp.c | 226 +++++++++++++----- drivers/dai/intel/ssp/ssp.h | 1 + drivers/dai/intel/ssp/ssp_regs_v3.h | 4 +- dts/xtensa/intel/intel_adsp_ace30_ptl.dtsi | 126 ++++++++++ include/zephyr/drivers/dai.h | 2 + 6 files changed, 302 insertions(+), 66 deletions(-) diff --git a/drivers/dai/intel/ssp/dai-params-intel-ipc4.h b/drivers/dai/intel/ssp/dai-params-intel-ipc4.h index 057a45d2a1242..a92f06d6620ca 100644 --- a/drivers/dai/intel/ssp/dai-params-intel-ipc4.h +++ b/drivers/dai/intel/ssp/dai-params-intel-ipc4.h @@ -11,6 +11,9 @@ #define DAI_INTEL_I2S_TDM_MAX_SLOT_MAP_COUNT 8 +#define I2SIPCMC 8 +#define I2SOPCMC 8 + /**< Type of the gateway. */ enum dai_intel_ipc4_connector_node_id_type { /**< HD/A host output (-> DSP). */ @@ -228,12 +231,18 @@ struct dai_intel_ipc4_ssp_config { uint32_t ssc1; uint32_t sscto; uint32_t sspsp; +#ifndef CONFIG_SOC_INTEL_ACE30_PTL uint32_t sstsa; uint32_t ssrsa; +#endif uint32_t ssc2; uint32_t sspsp2; uint32_t ssc3; uint32_t ssioc; +#ifdef CONFIG_SOC_INTEL_ACE30_PTL + uint64_t ssmidytsa[I2SIPCMC]; + uint64_t ssmodytsa[I2SOPCMC]; +#endif } __packed; struct dai_intel_ipc4_ssp_mclk_config { diff --git a/drivers/dai/intel/ssp/ssp.c b/drivers/dai/intel/ssp/ssp.c index a7e83f7a07f9e..1c9488d3f0a54 100644 --- a/drivers/dai/intel/ssp/ssp.c +++ b/drivers/dai/intel/ssp/ssp.c @@ -873,9 +873,10 @@ static void dai_ssp_pm_runtime_dis_ssp_power(struct dai_intel_ssp *dp, uint32_t } static void dai_ssp_program_channel_map(struct dai_intel_ssp *dp, - const struct dai_config *cfg, uint32_t ssp_index) + const struct dai_config *cfg, uint32_t ssp_index, const void *spec_config) { -#if defined(CONFIG_SOC_INTEL_ACE20_LNL) || defined(CONFIG_SOC_INTEL_ACE30_PTL) +#if defined(CONFIG_SOC_INTEL_ACE20_LNL) + ARG_UNUSED(spec_config); uint16_t pcmsycm = cfg->link_config; /* Set upper slot number from configuration */ pcmsycm = pcmsycm | (dp->ssp_plat_data->params.tdm_slots - 1) << 4; @@ -889,10 +890,39 @@ static void dai_ssp_program_channel_map(struct dai_intel_ssp *dp, /* Program HDA input stream parameters */ sys_write16((pcmsycm & 0xffff), reg_add); } +#elif defined(CONFIG_SOC_INTEL_ACE30_PTL) + const struct dai_intel_ipc4_ssp_configuration_blob *blob = spec_config; + uint64_t time_slot_map = 0; + uint16_t pcmsycm = cfg->link_config; + uint8_t slot_count = 0; + + if (DAI_INTEL_SSP_IS_BIT_SET(cfg->link_config, 15)) { + time_slot_map = + blob->i2s_driver_config.i2s_config.ssmidytsa[cfg->tdm_slot_group]; + slot_count = POPCOUNT(time_slot_map >> 32) + POPCOUNT(time_slot_map & 0xFFFFFFFF); + pcmsycm = cfg->link_config | (slot_count - 1) << 4; + uint32_t reg_add = dai_ip_base(dp) + 0x1000 * ssp_index + + PCMSyCM_OFFSET(cfg->tdm_slot_group); + + /* Program HDA output stream parameters */ + sys_write16((pcmsycm & 0xffff), reg_add); + + } else { + time_slot_map = + blob->i2s_driver_config.i2s_config.ssmodytsa[cfg->tdm_slot_group]; + slot_count = POPCOUNT(time_slot_map >> 32) + POPCOUNT(time_slot_map & 0xFFFFFFFF); + pcmsycm = cfg->link_config | (slot_count - 1) << 4; + uint32_t reg_add = dai_ip_base(dp) + 0x1000 * ssp_index + + PCMSyCM_OFFSET(cfg->tdm_slot_group + I2SOPCMC); + + /* Program HDA input stream parameters */ + sys_write16((pcmsycm & 0xffff), reg_add); + } #else ARG_UNUSED(dp); ARG_UNUSED(cfg); ARG_UNUSED(ssp_index); + ARG_UNUSED(spec_config); #endif /* CONFIG_SOC_INTEL_ACE20_LNL */ } @@ -907,11 +937,12 @@ static void dai_ssp_empty_tx_fifo(struct dai_intel_ssp *dp) * so wait for set TNF then for TFL zero - order matter. */ #ifdef CONFIG_SOC_INTEL_ACE30_PTL - ret = dai_ssp_poll_for_register_delay(dai_base(dp) + SSMODyCS(0), + ret = dai_ssp_poll_for_register_delay(dai_base(dp) + SSMODyCS(dp->tdm_slot_group), SSMODyCS_TNF, SSMODyCS_TNF, DAI_INTEL_SSP_MAX_SEND_TIME_PER_SAMPLE); - ret |= dai_ssp_poll_for_register_delay(dai_base(dp) + SSMODyCS(0), SSMODyCS_TFL, 0, + ret |= dai_ssp_poll_for_register_delay(dai_base(dp) + SSMODyCS(dp->tdm_slot_group), + SSMODyCS_TFL, 0, DAI_INTEL_SSP_MAX_SEND_TIME_PER_SAMPLE * (DAI_INTEL_SSP_FIFO_DEPTH - 1) / 2); #else @@ -944,8 +975,10 @@ static void ssp_empty_rx_fifo_on_start(struct dai_intel_ssp *dp) if (sssr & SSSR_ROR) { /* The RX FIFO is in overflow condition, empty it */ - for (i = 0; i < DAI_INTEL_SSP_FIFO_DEPTH; i++) - sys_read32(dai_base(dp) + SSMIDyD(0)); + for (uint32_t idx = 0; idx < I2SIPCMC; ++idx) { + for (i = 0; i < DAI_INTEL_SSP_FIFO_DEPTH; i++) + sys_read32(dai_base(dp) + SSMIDyD(idx)); + } /* Clear the overflow status */ dai_ssp_update_bits(dp, SSSR, SSSR_ROR, SSSR_ROR); @@ -953,14 +986,17 @@ static void ssp_empty_rx_fifo_on_start(struct dai_intel_ssp *dp) sssr = sys_read32(dai_base(dp) + SSSR); } - while ((sys_read32(dai_base(dp) + SSMIDyCS(0)) & SSMIDyCS_RNE) && retry--) { - uint32_t entries = SSMIDyCS_RFL_VAL(sys_read32(dai_base(dp) + SSMIDyCS(0))); + for (uint32_t idx = 0; idx < I2SIPCMC; ++idx) { + while ((sys_read32(dai_base(dp) + SSMIDyCS(idx)) & SSMIDyCS_RNE) && retry--) { + uint32_t entries = SSMIDyCS_RFL_VAL(sys_read32(dai_base(dp) + + SSMIDyCS(idx))); - /* Empty the RX FIFO (the DMA is not running at this point) */ - for (i = 0; i < entries + 1; i++) - sys_read32(dai_base(dp) + SSMIDyD(0)); + /* Empty the RX FIFO (the DMA is not running at this point) */ + for (i = 0; i < entries + 1; i++) + sys_read32(dai_base(dp) + SSMIDyD(idx)); - sssr = sys_read32(dai_base(dp) + SSSR); + sssr = sys_read32(dai_base(dp) + SSSR); + } } } @@ -969,41 +1005,47 @@ static void ssp_empty_rx_fifo_on_stop(struct dai_intel_ssp *dp) struct dai_intel_ssp_plat_data *ssp_plat_data = dai_get_plat_data(dp); uint64_t sample_ticks = ssp_plat_data->params.fsync_rate ? 1000000 / ssp_plat_data->params.fsync_rate : 0; - uint32_t retry = DAI_INTEL_SSP_RX_FLUSH_RETRY_MAX; uint32_t i, sssr, ssmidycs; uint32_t entries[2]; - sssr = sys_read32(dai_base(dp) + SSSR); - entries[0] = SSMIDyCS_RFL_VAL(sys_read32(dai_base(dp) + SSMIDyCS(0))); + if (ssp_is_acquired(dp->ssp_plat_data)) { + return; + } - while ((sys_read32(dai_base(dp) + SSMIDyCS(0)) & SSMIDyCS_RNE) && retry--) { - /* Wait one sample time */ - k_busy_wait(sample_ticks); + sssr = sys_read32(dai_base(dp) + SSSR); - entries[1] = SSMIDyCS_RFL_VAL(sys_read32(dai_base(dp) + SSMIDyCS(0))); - sssr = sys_read32(dai_base(dp) + SSSR); - ssmidycs = sys_read32(dai_base(dp) + SSMIDyCS(0)); + for (uint32_t idx = 0; idx < I2SIPCMC; ++idx) { + entries[0] = SSMIDyCS_RFL_VAL(sys_read32(dai_base(dp) + SSMIDyCS(idx))); + + while ((sys_read32(dai_base(dp) + SSMIDyCS(idx)) & SSMIDyCS_RNE) && retry--) { + /* Wait one sample time */ + k_busy_wait(sample_ticks); + + entries[1] = SSMIDyCS_RFL_VAL(sys_read32(dai_base(dp) + SSMIDyCS(idx))); + sssr = sys_read32(dai_base(dp) + SSSR); + ssmidycs = sys_read32(dai_base(dp) + SSMIDyCS(idx)); + + if (entries[0] > entries[1]) { + /* + * The DMA is reading the FIFO, check the status in the + * next loop + */ + entries[0] = entries[1]; + } else if (!(ssmidycs & SSMIDyCS_RFS)) { + /* + * The DMA request is not asserted, read the FIFO + * directly, otherwise let the next loop iteration to + * check the status + */ + for (i = 0; i < entries[1] + 1; i++) + sys_read32(dai_base(dp) + SSMIDyD(idx)); + } - if (entries[0] > entries[1]) { - /* - * The DMA is reading the FIFO, check the status in the - * next loop - */ - entries[0] = entries[1]; - } else if (!(ssmidycs & SSMIDyCS_RFS)) { - /* - * The DMA request is not asserted, read the FIFO - * directly, otherwise let the next loop iteration to - * check the status - */ - for (i = 0; i < entries[1] + 1; i++) - sys_read32(dai_base(dp) + SSMIDyD(0)); + sssr = sys_read32(dai_base(dp) + SSSR); } - sssr = sys_read32(dai_base(dp) + SSSR); } - /* Just in case clear the overflow status */ dai_ssp_update_bits(dp, SSSR, SSSR_ROR, SSSR_ROR); } @@ -1688,8 +1730,13 @@ static int dai_ssp_set_config_tplg(struct dai_intel_ssp *dp, const struct dai_co sys_write32(ssioc, dai_base(dp) + SSIOC); sys_write32(ssto, dai_base(dp) + SSTO); #ifdef CONFIG_SOC_INTEL_ACE30_PTL - sys_write64((uint64_t)sstsa, dai_base(dp) + SSMODyTSA(0)); - sys_write64((uint64_t)ssrsa, dai_base(dp) + SSMIDyTSA(0)); + for (uint32_t idx = 0; idx < I2SIPCMC; ++idx) { + sys_write64(sstsa, dai_base(dp) + SSMODyTSA(idx)); + } + + for (uint32_t idx = 0; idx < I2SOPCMC; ++idx) { + sys_write64(ssrsa, dai_base(dp) + SSMIDyTSA(idx)); + } #else sys_write32(sstsa, dai_base(dp) + SSTSA); sys_write32(ssrsa, dai_base(dp) + SSRSA); @@ -1735,6 +1782,16 @@ static int dai_ssp_set_config_tplg(struct dai_intel_ssp *dp, const struct dai_co ssp_plat_data->clk_active |= SSP_CLK_BCLK_ES_REQ; if (enable_sse) { +#ifdef CONFIG_SOC_INTEL_ACE30_PTL + dai_ssp_update_bits(dp, SSMIDyCS(dp->tdm_slot_group), + SSMIDyCS_RSRE, SSMIDyCS_RSRE); + dai_ssp_update_bits(dp, SSMODyCS(dp->tdm_slot_group), + SSMODyCS_TSRE, SSMODyCS_TSRE); +#else + dai_ssp_update_bits(dp, SSCR1, + SSCR1_TSRE | SSCR1_RSRE, + SSCR1_TSRE | SSCR1_RSRE); +#endif /* enable port */ dai_ssp_update_bits(dp, SSCR0, SSCR0_SSE, SSCR0_SSE); @@ -1758,6 +1815,19 @@ static int dai_ssp_set_config_tplg(struct dai_intel_ssp *dp, const struct dai_co LOG_INF("hw_free stage: releasing BCLK clocks for SSP%d...", dp->dai_index); if (ssp_plat_data->clk_active & SSP_CLK_BCLK_ACTIVE) { +#ifdef CONFIG_SOC_INTEL_ACE30_PTL + for (uint32_t idx = 0; idx < I2SOPCMC; ++idx) { + dai_ssp_update_bits(dp, SSMODyCS(idx), SSMODyCS_TSRE, 0); + } + + for (uint32_t idx = 0; idx < I2SIPCMC; ++idx) { + dai_ssp_update_bits(dp, SSMIDyCS(idx), SSMIDyCS_RSRE, 0); + } +#else + dai_ssp_update_bits(dp, SSCR1, + SSCR1_TSRE | SSCR1_RSRE, + 0); +#endif dai_ssp_update_bits(dp, SSCR0, SSCR0_SSE, 0); LOG_INF("SSE clear for SSP%d", dp->dai_index); } @@ -1957,17 +2027,19 @@ static int dai_ssp_set_clock_control_ver_1(struct dai_intel_ssp *dp, static void dai_ssp_set_reg_config(struct dai_intel_ssp *dp, const struct dai_config *cfg, const struct dai_intel_ipc4_ssp_config *regs) { - uint32_t ssc0, sstsa, ssrsa; - uint32_t sscr1 = regs->ssc1; + struct dai_intel_ssp_plat_data *ssp_plat_data = dai_get_plat_data(dp); + uint32_t sscr1 = 0; + uint32_t sstsa = 0; + uint32_t ssrsa = 0; + uint32_t ssc0 = regs->ssc0; + #ifdef CONFIG_SOC_INTEL_ACE30_PTL sscr1 = regs->ssc1 & ~(SSCR1_RSVD21); #else sscr1 = regs->ssc1 & ~(SSCR1_RSRE | SSCR1_TSRE); -#endif - - ssc0 = regs->ssc0; sstsa = SSTSA_GET(regs->sstsa); ssrsa = SSRSA_GET(regs->ssrsa); +#endif LOG_INF("SSP%d configuration:", dp->dai_index); #ifndef CONFIG_SOC_INTEL_ACE30_PTL @@ -1986,14 +2058,21 @@ static void dai_ssp_set_reg_config(struct dai_intel_ssp *dp, const struct dai_co sys_write32(sscr1, dai_base(dp) + SSCR1); sys_write32(regs->ssc2 | SSCR2_SFRMEN, dai_base(dp) + SSCR2); /* hardware specific flow */ sys_write32(regs->ssc2, dai_base(dp) + SSCR2); +#ifndef CONFIG_SOC_INTEL_ACE30_PTL sys_write32(regs->ssc3, dai_base(dp) + SSCR3); +#endif sys_write32(regs->sspsp, dai_base(dp) + SSPSP); sys_write32(regs->sspsp2, dai_base(dp) + SSPSP2); sys_write32(regs->ssioc, dai_base(dp) + SSIOC); sys_write32(regs->sscto, dai_base(dp) + SSTO); #ifdef CONFIG_SOC_INTEL_ACE30_PTL - sys_write64((uint64_t)sstsa, dai_base(dp) + SSMODyTSA(0)); - sys_write64((uint64_t)ssrsa, dai_base(dp) + SSMIDyTSA(0)); + for (uint32_t idx = 0; idx < I2SIPCMC; ++idx) { + sys_write64(regs->ssmidytsa[idx], dai_base(dp) + SSMIDyTSA(idx)); + } + + for (uint32_t idx = 0; idx < I2SOPCMC; ++idx) { + sys_write64(regs->ssmodytsa[idx], dai_base(dp) + SSMODyTSA(idx)); + } #else sys_write32(sstsa, dai_base(dp) + SSTSA); sys_write32(ssrsa, dai_base(dp) + SSRSA); @@ -2006,16 +2085,19 @@ static void dai_ssp_set_reg_config(struct dai_intel_ssp *dp, const struct dai_co LOG_INF(" ssioc = 0x%08x, ssrsa = 0x%08x, sstsa = 0x%08x", regs->ssioc, ssrsa, sstsa); - dp->ssp_plat_data->params.sample_valid_bits = SSCR0_DSIZE_GET(ssc0); + ssp_plat_data->params.sample_valid_bits = SSCR0_DSIZE_GET(ssc0); if (ssc0 & SSCR0_EDSS) { - dp->ssp_plat_data->params.sample_valid_bits += 16; + ssp_plat_data->params.sample_valid_bits += 16; } - - dp->ssp_plat_data->params.tdm_slots = SSCR0_FRDC_GET(ssc0); - dp->ssp_plat_data->params.tx_slots = SSTSA_GET(sstsa); - dp->ssp_plat_data->params.rx_slots = SSRSA_GET(ssrsa); - dp->ssp_plat_data->params.fsync_rate = cfg->rate; - +#ifdef CONFIG_SOC_INTEL_ACE30_PTL + ssp_plat_data->params.tx_slots = regs->ssmodytsa[dp->tdm_slot_group]; + ssp_plat_data->params.rx_slots = regs->ssmidytsa[dp->tdm_slot_group]; +#else + ssp_plat_data->params.tdm_slots = SSCR0_FRDC_GET(ssc0); + ssp_plat_data->params.tx_slots = SSTSA_GET(sstsa); + ssp_plat_data->params.rx_slots = SSRSA_GET(ssrsa); +#endif + ssp_plat_data->params.fsync_rate = cfg->rate; dp->state[DAI_DIR_PLAYBACK] = DAI_STATE_PRE_RUNNING; dp->state[DAI_DIR_CAPTURE] = DAI_STATE_PRE_RUNNING; } @@ -2028,6 +2110,10 @@ static int dai_ssp_set_config_blob(struct dai_intel_ssp *dp, const struct dai_co struct dai_intel_ssp_plat_data *ssp_plat_data = dai_get_plat_data(dp); int err; +#ifdef CONFIG_SOC_INTEL_ACE30_PTL + dp->tdm_slot_group = cfg->tdm_slot_group; +#endif + /* set config only once for playback or capture */ if (ssp_plat_data->is_initialized) { dp->state[DAI_DIR_PLAYBACK] = DAI_STATE_PRE_RUNNING; @@ -2151,11 +2237,15 @@ static void dai_ssp_start(struct dai_intel_ssp *dp, int direction) /* enable DMA */ #if CONFIG_SOC_INTEL_ACE30_PTL if (direction == DAI_DIR_PLAYBACK) { - dai_ssp_update_bits(dp, SSMODyCS(0), SSMODyCS_TSRE, SSMODyCS_TSRE); - dai_ssp_update_bits(dp, SSMODyCS(0), SSMODyCS_TXEN, SSMODyCS_TXEN); + dai_ssp_update_bits(dp, SSMODyCS(dp->tdm_slot_group), + SSMODyCS_TSRE, SSMODyCS_TSRE); + dai_ssp_update_bits(dp, SSMODyCS(dp->tdm_slot_group), + SSMODyCS_TXEN, SSMODyCS_TXEN); } else { - dai_ssp_update_bits(dp, SSMIDyCS(0), SSMIDyCS_RSRE, SSMIDyCS_RSRE); - dai_ssp_update_bits(dp, SSMIDyCS(0), SSMIDyCS_RXEN, SSMIDyCS_RXEN); + dai_ssp_update_bits(dp, SSMIDyCS(dp->tdm_slot_group), + SSMIDyCS_RSRE, SSMIDyCS_RSRE); + dai_ssp_update_bits(dp, SSMIDyCS(dp->tdm_slot_group), + SSMIDyCS_RXEN, SSMIDyCS_RXEN); } #else if (direction == DAI_DIR_PLAYBACK) { @@ -2218,8 +2308,8 @@ static void dai_ssp_stop(struct dai_intel_ssp *dp, int direction) dp->state[DAI_DIR_CAPTURE] != DAI_STATE_PRE_RUNNING) { LOG_INF("SSP%d RX", dp->dai_index); #if CONFIG_SOC_INTEL_ACE30_PTL - dai_ssp_update_bits(dp, SSMIDyCS(0), SSMIDyCS_RXEN, 0); - dai_ssp_update_bits(dp, SSMIDyCS(0), SSMIDyCS_RSRE, 0); + dai_ssp_update_bits(dp, SSMIDyCS(dp->tdm_slot_group), SSMIDyCS_RXEN, 0); + dai_ssp_update_bits(dp, SSMIDyCS(dp->tdm_slot_group), SSMIDyCS_RSRE, 0); #else dai_ssp_update_bits(dp, SSRSA, SSRSA_RXEN, 0); dai_ssp_update_bits(dp, SSCR1, SSCR1_RSRE, 0); @@ -2234,9 +2324,9 @@ static void dai_ssp_stop(struct dai_intel_ssp *dp, int direction) dp->state[DAI_DIR_PLAYBACK] != DAI_STATE_PRE_RUNNING) { LOG_INF("SSP%d TX", dp->dai_index); #if CONFIG_SOC_INTEL_ACE30_PTL - dai_ssp_update_bits(dp, SSMODyCS(0), SSMODyCS_TSRE, 0); + dai_ssp_update_bits(dp, SSMODyCS(dp->tdm_slot_group), SSMODyCS_TSRE, 0); dai_ssp_empty_tx_fifo(dp); - dai_ssp_update_bits(dp, SSMODyCS(0), SSMODyCS_TXEN, 0); + dai_ssp_update_bits(dp, SSMODyCS(dp->tdm_slot_group), SSMODyCS_TXEN, 0); #else dai_ssp_update_bits(dp, SSCR1, SSCR1_TSRE, 0); dai_ssp_empty_tx_fifo(dp); @@ -2251,7 +2341,6 @@ static void dai_ssp_stop(struct dai_intel_ssp *dp, int direction) dp->state[DAI_DIR_PLAYBACK] == DAI_STATE_PRE_RUNNING && COND_CODE_1(CONFIG_INTEL_ADSP_CAVS, (!(ssp_plat_data->clk_active & SSP_CLK_BCLK_ES_REQ)), (true))) { - if (!ssp_is_acquired(ssp_plat_data)) { dai_ssp_update_bits(dp, SSCR0, SSCR0_SSE, 0); LOG_INF("%s SSE clear SSP%d", __func__, ssp_plat_data->ssp_index); @@ -2342,6 +2431,7 @@ static int dai_ssp_config_set(const struct device *dev, const struct dai_config const void *bespoke_cfg) { struct dai_intel_ssp *dp = (struct dai_intel_ssp *)dev->data; + struct dai_intel_ssp_plat_data *ssp_plat_data = dai_get_plat_data(dp); int ret; if (cfg->type == DAI_INTEL_SSP) { @@ -2349,7 +2439,8 @@ static int dai_ssp_config_set(const struct device *dev, const struct dai_config } else { ret = dai_ssp_set_config_blob(dp, cfg, bespoke_cfg); } - dai_ssp_program_channel_map(dp, cfg, dp->ssp_index); + dai_ssp_program_channel_map(dp, cfg, ssp_plat_data->ssp_index, bespoke_cfg); + return ret; } @@ -2421,6 +2512,12 @@ static int dai_ssp_remove(struct dai_intel_ssp *dp) { struct dai_intel_ssp_plat_data *ssp_plat_data = dai_get_plat_data(dp); + if (ssp_is_acquired(ssp_plat_data)) { + k_free(dai_get_drvdata(dp)); + dai_set_drvdata(dp, NULL); + return 0; + } + dai_ssp_pm_runtime_en_ssp_clk_gating(dp, ssp_plat_data->ssp_index); dai_ssp_mclk_disable_unprepare(dp); @@ -2502,6 +2599,7 @@ static struct dai_driver_api dai_intel_ssp_api_funcs = { static struct dai_intel_ssp dai_intel_ssp_data_##n = { \ .dai_index = DT_INST_REG_ADDR(n), \ .ssp_index = DT_PROP(DT_INST_PARENT(n), ssp_index), \ + .tdm_slot_group = 0, \ }; \ \ PM_DEVICE_DT_INST_DEFINE(n, ssp_pm_action); \ diff --git a/drivers/dai/intel/ssp/ssp.h b/drivers/dai/intel/ssp/ssp.h index 877ff75e53240..560b5d3df5f6e 100644 --- a/drivers/dai/intel/ssp/ssp.h +++ b/drivers/dai/intel/ssp/ssp.h @@ -142,6 +142,7 @@ struct dai_intel_ssp_pdata { struct dai_intel_ssp { uint32_t dai_index; uint32_t ssp_index; + uint32_t tdm_slot_group; uint32_t state[2]; struct k_spinlock lock; /**< locking mechanism */ int sref; /**< simple ref counter, guarded by lock */ diff --git a/drivers/dai/intel/ssp/ssp_regs_v3.h b/drivers/dai/intel/ssp/ssp_regs_v3.h index 958c3919c6051..2141dc39d85b6 100644 --- a/drivers/dai/intel/ssp/ssp_regs_v3.h +++ b/drivers/dai/intel/ssp/ssp_regs_v3.h @@ -29,6 +29,8 @@ #define SSMODyD(y) 0x64 + 0x10*I2SIPCMC + 0x10*y #define SSMODyTSA(y) 0x68 + 0x10*I2SIPCMC + 0x10*y +#define PCMSyCM_OFFSET(x) 0x16 + 0x4*(x) + #define OUT_FIFO SSMODyD(0) #define IN_FIFO SSMIDyD(0) @@ -211,8 +213,6 @@ #define I2SLCTL_OFLEN BIT(4) #define I2SLCTL_SPA(x) BIT(16 + x) #define I2SLCTL_CPA(x) BIT(23 + x) -#define PCMS0CM_OFFSET 0x16 -#define PCMS1CM_OFFSET PCMS0CM_OFFSET + 4 * I2SIPCMC #define I2CLCTL_MLCS(x) DAI_INTEL_SSP_SET_BITS(30, 27, x) #define SHIM_CLKCTL 0x78 diff --git a/dts/xtensa/intel/intel_adsp_ace30_ptl.dtsi b/dts/xtensa/intel/intel_adsp_ace30_ptl.dtsi index 5923d385291f7..11930481baad7 100644 --- a/dts/xtensa/intel/intel_adsp_ace30_ptl.dtsi +++ b/dts/xtensa/intel/intel_adsp_ace30_ptl.dtsi @@ -238,6 +238,48 @@ reg = <0x0>; status = "okay"; }; + + ssp01: ssp@1 { + compatible = "intel,ssp-dai"; + reg = <0x1>; + status = "okay"; + }; + + ssp02: ssp@2 { + compatible = "intel,ssp-dai"; + reg = <0x2>; + status = "okay"; + }; + + ssp03: ssp@3 { + compatible = "intel,ssp-dai"; + reg = <0x3>; + status = "okay"; + }; + + ssp04: ssp@4 { + compatible = "intel,ssp-dai"; + reg = <0x4>; + status = "okay"; + }; + + ssp05: ssp@5 { + compatible = "intel,ssp-dai"; + reg = <0x5>; + status = "okay"; + }; + + ssp06: ssp@6 { + compatible = "intel,ssp-dai"; + reg = <0x6>; + status = "okay"; + }; + + ssp07: ssp@7 { + compatible = "intel,ssp-dai"; + reg = <0x7>; + status = "okay"; + }; }; ssp1: ssp@29100 { @@ -260,6 +302,48 @@ reg = <0x10>; status = "okay"; }; + + ssp11: ssp@11 { + compatible = "intel,ssp-dai"; + reg = <0x11>; + status = "okay"; + }; + + ssp12: ssp@12 { + compatible = "intel,ssp-dai"; + reg = <0x12>; + status = "okay"; + }; + + ssp13: ssp@13 { + compatible = "intel,ssp-dai"; + reg = <0x13>; + status = "okay"; + }; + + ssp14: ssp@14 { + compatible = "intel,ssp-dai"; + reg = <0x14>; + status = "okay"; + }; + + ssp15: ssp@15 { + compatible = "intel,ssp-dai"; + reg = <0x15>; + status = "okay"; + }; + + ssp16: ssp@16 { + compatible = "intel,ssp-dai"; + reg = <0x16>; + status = "okay"; + }; + + ssp17: ssp@17 { + compatible = "intel,ssp-dai"; + reg = <0x17>; + status = "okay"; + }; }; ssp2: ssp@2a100 { @@ -282,6 +366,48 @@ reg = <0x20>; status = "okay"; }; + + ssp21: ssp@21 { + compatible = "intel,ssp-dai"; + reg = <0x21>; + status = "okay"; + }; + + ssp22: ssp@22 { + compatible = "intel,ssp-dai"; + reg = <0x22>; + status = "okay"; + }; + + ssp23: ssp@23 { + compatible = "intel,ssp-dai"; + reg = <0x23>; + status = "okay"; + }; + + ssp24: ssp@24 { + compatible = "intel,ssp-dai"; + reg = <0x24>; + status = "okay"; + }; + + ssp25: ssp@25 { + compatible = "intel,ssp-dai"; + reg = <0x25>; + status = "okay"; + }; + + ssp26: ssp@26 { + compatible = "intel,ssp-dai"; + reg = <0x26>; + status = "okay"; + }; + + ssp27: ssp@27 { + compatible = "intel,ssp-dai"; + reg = <0x27>; + status = "okay"; + }; }; mem_window0: mem_window@70200 { diff --git a/include/zephyr/drivers/dai.h b/include/zephyr/drivers/dai.h index 2e6f570454006..fa78f3efb15e4 100644 --- a/include/zephyr/drivers/dai.h +++ b/include/zephyr/drivers/dai.h @@ -268,6 +268,8 @@ struct dai_config { size_t block_size; /** DAI specific link configuration. */ uint16_t link_config; + /**< tdm slot goup number*/ + uint32_t tdm_slot_group; }; /** From 809c0923c6154f55fad5d6dd7528c47768928234 Mon Sep 17 00:00:00 2001 From: "Giardina, Anthony" Date: Thu, 2 May 2024 04:02:24 +0000 Subject: [PATCH 2818/2849] xtensa: userspace: fix uninitialized return values in mpu_map_region_add Ensure that *first_idx is populated for the case of adding entries to an empty table Signed-off-by: Anthony Giardina --- arch/xtensa/core/mpu.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/arch/xtensa/core/mpu.c b/arch/xtensa/core/mpu.c index 76036b32c705f..2b16ff912411f 100644 --- a/arch/xtensa/core/mpu.c +++ b/arch/xtensa/core/mpu.c @@ -443,6 +443,8 @@ static int mpu_map_region_add(struct xtensa_mpu_map *map, xtensa_mpu_entry_set(entry_slot_s, start_addr, true, access_rights, memory_type); + first_enabled_idx = XTENSA_MPU_NUM_ENTRIES - 1; + goto end; } else { /* * Populate the last two entries to indicate @@ -459,6 +461,8 @@ static int mpu_map_region_add(struct xtensa_mpu_map *map, xtensa_mpu_entry_set(entry_slot_e, end_addr, false, XTENSA_MPU_ACCESS_P_NA_U_NA, CONFIG_XTENSA_MPU_DEFAULT_MEM_TYPE); + first_enabled_idx = XTENSA_MPU_NUM_ENTRIES - 2; + goto end; } ret = 0; @@ -595,6 +599,7 @@ static int mpu_map_region_add(struct xtensa_mpu_map *map, xtensa_mpu_entry_attributes_set(&entries[idx], access_rights, memory_type); } +end: if (first_idx != NULL) { *first_idx = first_enabled_idx; } From 79f4f2ac31cbba648ae4bc6066e7da77a1688fd7 Mon Sep 17 00:00:00 2001 From: Bartlomiej Buczek Date: Thu, 13 Jun 2024 08:55:49 +0200 Subject: [PATCH 2819/2849] samples: drivers: adc: Allow coverage calculation. Sample must end to dump coverage data. Signed-off-by: Bartlomiej Buczek --- samples/drivers/adc/adc_dt/src/main.c | 4 ++++ samples/drivers/adc/adc_sequence/src/main.c | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/samples/drivers/adc/adc_dt/src/main.c b/samples/drivers/adc/adc_dt/src/main.c index 0f781eac7000e..cb607a0ff0d17 100644 --- a/samples/drivers/adc/adc_dt/src/main.c +++ b/samples/drivers/adc/adc_dt/src/main.c @@ -54,7 +54,11 @@ int main(void) } } +#ifndef CONFIG_COVERAGE while (1) { +#else + for (int k = 0; k < 10; k++) { +#endif printk("ADC reading[%u]:\n", count++); for (size_t i = 0U; i < ARRAY_SIZE(adc_channels); i++) { int32_t val_mv; diff --git a/samples/drivers/adc/adc_sequence/src/main.c b/samples/drivers/adc/adc_sequence/src/main.c index 9dda1acfb4672..0e401f9cc340e 100644 --- a/samples/drivers/adc/adc_sequence/src/main.c +++ b/samples/drivers/adc/adc_sequence/src/main.c @@ -56,7 +56,11 @@ int main(void) } } +#ifndef CONFIG_COVERAGE while (1) { +#else + for (int k = 0; k < 10; k++) { +#endif printf("ADC sequence reading [%u]:\n", count++); k_msleep(1000); From f6fdfd4ee1be0e089798a40ae400d53617df2e1c Mon Sep 17 00:00:00 2001 From: Sylvio Alves Date: Wed, 12 Jun 2024 17:40:26 -0300 Subject: [PATCH 2820/2849] soc: esp32c3: add systimer clock disable option When both MCUBoot and application run, systimer is initialized twice. As a consequence, application freezes as systimer new initialization conflicts with previous. This PR adds the systimer clock disable function, that shall be called before mcuboot jump to application, making sure it will work as expected. Fixes #74189 Signed-off-by: Sylvio Alves --- drivers/timer/Kconfig.esp32 | 1 + drivers/timer/esp32_sys_timer.c | 7 +++++++ west.yml | 2 +- 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/timer/Kconfig.esp32 b/drivers/timer/Kconfig.esp32 index 0d45987c726db..0634c3f0cb229 100644 --- a/drivers/timer/Kconfig.esp32 +++ b/drivers/timer/Kconfig.esp32 @@ -9,6 +9,7 @@ config ESP32_SYS_TIMER default y select TICKLESS_CAPABLE select TIMER_HAS_64BIT_CYCLE_COUNTER + select SYSTEM_TIMER_HAS_DISABLE_SUPPORT help This option enables the system timer driver for the Espressif ESP32Cx and provides the standard "system clock driver" interface. diff --git a/drivers/timer/esp32_sys_timer.c b/drivers/timer/esp32_sys_timer.c index 0fa888f674580..770a89edbdf30 100644 --- a/drivers/timer/esp32_sys_timer.c +++ b/drivers/timer/esp32_sys_timer.c @@ -136,6 +136,13 @@ uint64_t sys_clock_cycle_get_64(void) return get_systimer_alarm(); } +void sys_clock_disable(void) +{ + systimer_ll_enable_alarm(systimer_hal.dev, SYSTIMER_ALARM_OS_TICK_CORE0, false); + systimer_ll_enable_alarm_int(systimer_hal.dev, SYSTIMER_ALARM_OS_TICK_CORE0, false); + systimer_hal_deinit(&systimer_hal); +} + static int sys_clock_driver_init(void) { diff --git a/west.yml b/west.yml index 10e7ec2a648a8..a5e7a78ff0bdf 100644 --- a/west.yml +++ b/west.yml @@ -157,7 +157,7 @@ manifest: groups: - hal - name: hal_espressif - revision: 0690c03f1540e8a5082da4c2b997e64bde8f4765 + revision: 4e38d8d9fe16d4d41736c1ffae6566001a624fca path: modules/hal/espressif west-commands: west/west-commands.yml groups: From 4f72df466cc52434209cad9a206cf22e013fd45e Mon Sep 17 00:00:00 2001 From: Eric Ackermann Date: Mon, 10 Jun 2024 09:52:57 +0200 Subject: [PATCH 2821/2849] net: Support partial checksum offloading The Xilinx AXI Ethernet subsystem is capable of RX/Tx checksum offloading. While it supports computing IP and UDP/TCP checksums, it does not support computing ICMP checksums and only computes IP checksums for ICMP messages. Thus, this patch adds an additional configuration for ethernet drivers that indicates for which protocols checksum offloading is (to be) supported. This flag is then considered by the IP subsystem in determining when flags need to be computed in software. Signed-off-by: Eric Ackermann --- include/zephyr/net/ethernet.h | 46 +++++++++++++++++++++++++++++++ include/zephyr/net/net_if.h | 51 +++++++++++++++++++++++++++++++++-- subsys/net/ip/icmpv4.c | 5 ++-- subsys/net/ip/icmpv6.c | 5 ++-- subsys/net/ip/ipv4.c | 4 +-- subsys/net/ip/net_if.c | 31 ++++++++++++++++----- subsys/net/ip/tcp.c | 8 ++++-- subsys/net/ip/udp.c | 8 ++++-- 8 files changed, 140 insertions(+), 18 deletions(-) diff --git a/include/zephyr/net/ethernet.h b/include/zephyr/net/ethernet.h index 6376a36ee3c41..5918f5ddf826b 100644 --- a/include/zephyr/net/ethernet.h +++ b/include/zephyr/net/ethernet.h @@ -218,6 +218,8 @@ enum ethernet_config_type { ETHERNET_CONFIG_TYPE_PORTS_NUM, ETHERNET_CONFIG_TYPE_T1S_PARAM, ETHERNET_CONFIG_TYPE_TXINJECTION_MODE, + ETHERNET_CONFIG_TYPE_RX_CHECKSUM_SUPPORT, + ETHERNET_CONFIG_TYPE_TX_CHECKSUM_SUPPORT }; enum ethernet_qav_param_type { @@ -465,6 +467,24 @@ struct ethernet_txtime_param { bool enable_txtime; }; +/** Protocols that are supported by checksum offloading */ +enum ethernet_checksum_support { + /** Device does not support any L3/L4 checksum offloading */ + ETHERNET_CHECKSUM_SUPPORT_NONE = NET_IF_CHECKSUM_NONE_BIT, + /** Device supports checksum offloading for the IPv4 header */ + ETHERNET_CHECKSUM_SUPPORT_IPV4_HEADER = NET_IF_CHECKSUM_IPV4_HEADER_BIT, + /** Device supports checksum offloading for ICMPv4 payload (implies IPv4 header) */ + ETHERNET_CHECKSUM_SUPPORT_IPV4_ICMP = NET_IF_CHECKSUM_IPV4_ICMP_BIT, + /** Device supports checksum offloading for the IPv6 header */ + ETHERNET_CHECKSUM_SUPPORT_IPV6_HEADER = NET_IF_CHECKSUM_IPV6_HEADER_BIT, + /** Device supports checksum offloading for ICMPv6 payload (implies IPv6 header) */ + ETHERNET_CHECKSUM_SUPPORT_IPV6_ICMP = NET_IF_CHECKSUM_IPV6_ICMP_BIT, + /** Device supports TCP checksum offloading for all supported IP protocols */ + ETHERNET_CHECKSUM_SUPPORT_TCP = NET_IF_CHECKSUM_TCP_BIT, + /** Device supports UDP checksum offloading for all supported IP protocols */ + ETHERNET_CHECKSUM_SUPPORT_UDP = NET_IF_CHECKSUM_UDP_BIT, +}; + /** @cond INTERNAL_HIDDEN */ struct ethernet_config { @@ -491,6 +511,8 @@ struct ethernet_config { int priority_queues_num; int ports_num; + enum ethernet_checksum_support chksum_support; + struct ethernet_filter filter; }; }; @@ -913,6 +935,30 @@ enum ethernet_hw_caps net_eth_get_hw_capabilities(struct net_if *iface) return eth->get_capabilities(net_if_get_device(iface)); } +/** + * @brief Return ethernet device hardware configuration information. + * + * @param iface Network interface + * @param type configuration type + * @param config Ethernet configuration + * + * @return 0 if ok, <0 if error + */ +static inline +int net_eth_get_hw_config(struct net_if *iface, enum ethernet_config_type type, + struct ethernet_config *config) +{ + const struct ethernet_api *eth = + (struct ethernet_api *)net_if_get_device(iface)->api; + + if (!eth->get_config) { + return -ENOTSUP; + } + + return eth->get_config(net_if_get_device(iface), type, config); +} + + /** * @brief Add VLAN tag to the interface. * diff --git a/include/zephyr/net/net_if.h b/include/zephyr/net/net_if.h index 05cdc7155f4a1..bcadd814f394b 100644 --- a/include/zephyr/net/net_if.h +++ b/include/zephyr/net/net_if.h @@ -2646,16 +2646,61 @@ void net_if_unregister_link_cb(struct net_if_link_cb *link); void net_if_call_link_cb(struct net_if *iface, struct net_linkaddr *lladdr, int status); +/** @cond INTERNAL_HIDDEN */ + +/* used to ensure encoding of checksum support in net_if.h and + * ethernet.h is the same + */ +#define NET_IF_CHECKSUM_NONE_BIT 0 +#define NET_IF_CHECKSUM_IPV4_HEADER_BIT BIT(0) +#define NET_IF_CHECKSUM_IPV4_ICMP_BIT BIT(1) +/* Space for future protocols and restrictions for IPV4 */ +#define NET_IF_CHECKSUM_IPV6_HEADER_BIT BIT(10) +#define NET_IF_CHECKSUM_IPV6_ICMP_BIT BIT(11) +/* Space for future protocols and restrictions for IPV6 */ +#define NET_IF_CHECKSUM_TCP_BIT BIT(21) +#define NET_IF_CHECKSUM_UDP_BIT BIT(22) + +/** @endcond */ + +/** + * @brief Type of checksum for which support in the interface will be queried. + */ +enum net_if_checksum_type { + /** Interface supports IP version 4 header checksum calculation */ + NET_IF_CHECKSUM_IPV4_HEADER = NET_IF_CHECKSUM_IPV4_HEADER_BIT, + /** Interface supports checksum calculation for TCP payload in IPv4 */ + NET_IF_CHECKSUM_IPV4_TCP = NET_IF_CHECKSUM_IPV4_HEADER_BIT | + NET_IF_CHECKSUM_TCP_BIT, + /** Interface supports checksum calculation for UDP payload in IPv4 */ + NET_IF_CHECKSUM_IPV4_UDP = NET_IF_CHECKSUM_IPV4_HEADER_BIT | + NET_IF_CHECKSUM_UDP_BIT, + /** Interface supports checksum calculation for ICMP4 payload in IPv4 */ + NET_IF_CHECKSUM_IPV4_ICMP = NET_IF_CHECKSUM_IPV4_ICMP_BIT, + /** Interface supports IP version 6 header checksum calculation */ + NET_IF_CHECKSUM_IPV6_HEADER = NET_IF_CHECKSUM_IPV6_HEADER_BIT, + /** Interface supports checksum calculation for TCP payload in IPv6 */ + NET_IF_CHECKSUM_IPV6_TCP = NET_IF_CHECKSUM_IPV6_HEADER_BIT | + NET_IF_CHECKSUM_TCP_BIT, + /** Interface supports checksum calculation for UDP payload in IPv6 */ + NET_IF_CHECKSUM_IPV6_UDP = NET_IF_CHECKSUM_IPV6_HEADER_BIT | + NET_IF_CHECKSUM_UDP_BIT, + /** Interface supports checksum calculation for ICMP6 payload in IPv6 */ + NET_IF_CHECKSUM_IPV6_ICMP = NET_IF_CHECKSUM_IPV6_ICMP_BIT +}; + /** * @brief Check if received network packet checksum calculation can be avoided * or not. For example many ethernet devices support network packet offloading * in which case the IP stack does not need to calculate the checksum. * * @param iface Network interface + * @param chksum_type L3 and/or L4 protocol for which to compute checksum * * @return True if checksum needs to be calculated, false otherwise. */ -bool net_if_need_calc_rx_checksum(struct net_if *iface); +bool net_if_need_calc_rx_checksum(struct net_if *iface, + enum net_if_checksum_type chksum_type); /** * @brief Check if network packet checksum calculation can be avoided or not @@ -2664,10 +2709,12 @@ bool net_if_need_calc_rx_checksum(struct net_if *iface); * checksum. * * @param iface Network interface + * @param chksum_type L3 and/or L4 protocol for which to compute checksum * * @return True if checksum needs to be calculated, false otherwise. */ -bool net_if_need_calc_tx_checksum(struct net_if *iface); +bool net_if_need_calc_tx_checksum(struct net_if *iface, + enum net_if_checksum_type chksum_type); /** * @brief Get interface according to index diff --git a/subsys/net/ip/icmpv4.c b/subsys/net/ip/icmpv4.c index 456242d1eec86..5e1cb35566c57 100644 --- a/subsys/net/ip/icmpv4.c +++ b/subsys/net/ip/icmpv4.c @@ -65,7 +65,8 @@ int net_icmpv4_finalize(struct net_pkt *pkt, bool force_chksum) } icmp_hdr->chksum = 0U; - if (net_if_need_calc_tx_checksum(net_pkt_iface(pkt)) || force_chksum) { + if (net_if_need_calc_tx_checksum(net_pkt_iface(pkt), NET_IF_CHECKSUM_IPV4_ICMP) || + force_chksum) { icmp_hdr->chksum = net_calc_chksum_icmpv4(pkt); net_pkt_set_chksum_done(pkt, true); } @@ -615,7 +616,7 @@ enum net_verdict net_icmpv4_input(struct net_pkt *pkt, return NET_DROP; } - if (net_if_need_calc_rx_checksum(net_pkt_iface(pkt)) || + if (net_if_need_calc_rx_checksum(net_pkt_iface(pkt), NET_IF_CHECKSUM_IPV4_ICMP) || net_pkt_is_ip_reassembled(pkt)) { if (net_calc_chksum_icmpv4(pkt) != 0U) { NET_DBG("DROP: Invalid checksum"); diff --git a/subsys/net/ip/icmpv6.c b/subsys/net/ip/icmpv6.c index e60589da764c9..048521e1c12be 100644 --- a/subsys/net/ip/icmpv6.c +++ b/subsys/net/ip/icmpv6.c @@ -69,7 +69,8 @@ int net_icmpv6_finalize(struct net_pkt *pkt, bool force_chksum) } icmp_hdr->chksum = 0U; - if (net_if_need_calc_tx_checksum(net_pkt_iface(pkt)) || force_chksum) { + if (net_if_need_calc_tx_checksum(net_pkt_iface(pkt), NET_IF_CHECKSUM_IPV6_ICMP) || + force_chksum) { icmp_hdr->chksum = net_calc_chksum_icmpv6(pkt); net_pkt_set_chksum_done(pkt, true); } @@ -347,7 +348,7 @@ enum net_verdict net_icmpv6_input(struct net_pkt *pkt, } - if (net_if_need_calc_rx_checksum(net_pkt_iface(pkt)) || + if (net_if_need_calc_rx_checksum(net_pkt_iface(pkt), NET_IF_CHECKSUM_IPV6_ICMP) || net_pkt_is_ip_reassembled(pkt)) { if (net_calc_chksum_icmpv6(pkt) != 0U) { NET_DBG("DROP: invalid checksum"); diff --git a/subsys/net/ip/ipv4.c b/subsys/net/ip/ipv4.c index 35872988edd76..abc2cfd09cda2 100644 --- a/subsys/net/ip/ipv4.c +++ b/subsys/net/ip/ipv4.c @@ -122,7 +122,7 @@ int net_ipv4_finalize(struct net_pkt *pkt, uint8_t next_header_proto) ipv4_hdr->len = htons(net_pkt_get_len(pkt)); ipv4_hdr->proto = next_header_proto; - if (net_if_need_calc_tx_checksum(net_pkt_iface(pkt))) { + if (net_if_need_calc_tx_checksum(net_pkt_iface(pkt), NET_IF_CHECKSUM_IPV4_HEADER)) { ipv4_hdr->chksum = net_calc_chksum_ipv4(pkt); } @@ -323,7 +323,7 @@ enum net_verdict net_ipv4_input(struct net_pkt *pkt, bool is_loopback) goto drop; } - if (net_if_need_calc_rx_checksum(net_pkt_iface(pkt)) && + if (net_if_need_calc_rx_checksum(net_pkt_iface(pkt), NET_IF_CHECKSUM_IPV4_HEADER) && net_calc_chksum_ipv4(pkt) != 0U) { NET_DBG("DROP: invalid chksum"); goto drop; diff --git a/subsys/net/ip/net_if.c b/subsys/net/ip/net_if.c index b100cad9fb31f..127e860aed1d0 100644 --- a/subsys/net/ip/net_if.c +++ b/subsys/net/ip/net_if.c @@ -5067,14 +5067,33 @@ void net_if_call_link_cb(struct net_if *iface, struct net_linkaddr *lladdr, k_mutex_unlock(&lock); } -static bool need_calc_checksum(struct net_if *iface, enum ethernet_hw_caps caps) +static bool need_calc_checksum(struct net_if *iface, enum ethernet_hw_caps caps, + enum net_if_checksum_type chksum_type) { #if defined(CONFIG_NET_L2_ETHERNET) + struct ethernet_config config; + enum ethernet_config_type config_type; + if (net_if_l2(iface) != &NET_L2_GET_NAME(ETHERNET)) { return true; } - return !(net_eth_get_hw_capabilities(iface) & caps); + if (!(net_eth_get_hw_capabilities(iface) & caps)) { + return true; /* No checksum offload*/ + } + + if (caps == ETHERNET_HW_RX_CHKSUM_OFFLOAD) { + config_type = ETHERNET_CONFIG_TYPE_RX_CHECKSUM_SUPPORT; + } else { + config_type = ETHERNET_CONFIG_TYPE_TX_CHECKSUM_SUPPORT; + } + + if (net_eth_get_hw_config(iface, config_type, &config) != 0) { + return false; /* No extra info, assume all offloaded. */ + } + + /* bitmaps are encoded such that this works */ + return !((config.chksum_support & chksum_type) == chksum_type); #else ARG_UNUSED(iface); ARG_UNUSED(caps); @@ -5083,14 +5102,14 @@ static bool need_calc_checksum(struct net_if *iface, enum ethernet_hw_caps caps) #endif } -bool net_if_need_calc_tx_checksum(struct net_if *iface) +bool net_if_need_calc_tx_checksum(struct net_if *iface, enum net_if_checksum_type chksum_type) { - return need_calc_checksum(iface, ETHERNET_HW_TX_CHKSUM_OFFLOAD); + return need_calc_checksum(iface, ETHERNET_HW_TX_CHKSUM_OFFLOAD, chksum_type); } -bool net_if_need_calc_rx_checksum(struct net_if *iface) +bool net_if_need_calc_rx_checksum(struct net_if *iface, enum net_if_checksum_type chksum_type) { - return need_calc_checksum(iface, ETHERNET_HW_RX_CHKSUM_OFFLOAD); + return need_calc_checksum(iface, ETHERNET_HW_RX_CHKSUM_OFFLOAD, chksum_type); } int net_if_get_by_iface(struct net_if *iface) diff --git a/subsys/net/ip/tcp.c b/subsys/net/ip/tcp.c index b891dca05385d..5dca5506f001d 100644 --- a/subsys/net/ip/tcp.c +++ b/subsys/net/ip/tcp.c @@ -4051,6 +4051,8 @@ int net_tcp_finalize(struct net_pkt *pkt, bool force_chksum) { NET_PKT_DATA_ACCESS_DEFINE(tcp_access, struct net_tcp_hdr); struct net_tcp_hdr *tcp_hdr; + enum net_if_checksum_type type = net_pkt_family(pkt) == AF_INET6 ? + NET_IF_CHECKSUM_IPV6_TCP : NET_IF_CHECKSUM_IPV4_TCP; tcp_hdr = (struct net_tcp_hdr *)net_pkt_get_data(pkt, &tcp_access); if (!tcp_hdr) { @@ -4059,7 +4061,7 @@ int net_tcp_finalize(struct net_pkt *pkt, bool force_chksum) tcp_hdr->chksum = 0U; - if (net_if_need_calc_tx_checksum(net_pkt_iface(pkt)) || force_chksum) { + if (net_if_need_calc_tx_checksum(net_pkt_iface(pkt), type) || force_chksum) { tcp_hdr->chksum = net_calc_chksum_tcp(pkt); net_pkt_set_chksum_done(pkt, true); } @@ -4071,9 +4073,11 @@ struct net_tcp_hdr *net_tcp_input(struct net_pkt *pkt, struct net_pkt_data_access *tcp_access) { struct net_tcp_hdr *tcp_hdr; + enum net_if_checksum_type type = net_pkt_family(pkt) == AF_INET6 ? + NET_IF_CHECKSUM_IPV6_TCP : NET_IF_CHECKSUM_IPV4_TCP; if (IS_ENABLED(CONFIG_NET_TCP_CHECKSUM) && - (net_if_need_calc_rx_checksum(net_pkt_iface(pkt)) || + (net_if_need_calc_rx_checksum(net_pkt_iface(pkt), type) || net_pkt_is_ip_reassembled(pkt)) && net_calc_chksum_tcp(pkt) != 0U) { NET_DBG("DROP: checksum mismatch"); diff --git a/subsys/net/ip/udp.c b/subsys/net/ip/udp.c index e3f45b3db38a9..3ff428cd8a44a 100644 --- a/subsys/net/ip/udp.c +++ b/subsys/net/ip/udp.c @@ -40,6 +40,8 @@ int net_udp_finalize(struct net_pkt *pkt, bool force_chksum) NET_PKT_DATA_ACCESS_DEFINE(udp_access, struct net_udp_hdr); struct net_udp_hdr *udp_hdr; uint16_t length = 0; + enum net_if_checksum_type type = net_pkt_family(pkt) == AF_INET6 ? + NET_IF_CHECKSUM_IPV6_UDP : NET_IF_CHECKSUM_IPV4_UDP; udp_hdr = (struct net_udp_hdr *)net_pkt_get_data(pkt, &udp_access); if (!udp_hdr) { @@ -51,7 +53,7 @@ int net_udp_finalize(struct net_pkt *pkt, bool force_chksum) udp_hdr->len = htons(length); - if (net_if_need_calc_tx_checksum(net_pkt_iface(pkt)) || force_chksum) { + if (net_if_need_calc_tx_checksum(net_pkt_iface(pkt), type) || force_chksum) { udp_hdr->chksum = net_calc_chksum_udp(pkt); net_pkt_set_chksum_done(pkt, true); } @@ -149,6 +151,8 @@ struct net_udp_hdr *net_udp_input(struct net_pkt *pkt, struct net_pkt_data_access *udp_access) { struct net_udp_hdr *udp_hdr; + enum net_if_checksum_type type = net_pkt_family(pkt) == AF_INET6 ? + NET_IF_CHECKSUM_IPV6_UDP : NET_IF_CHECKSUM_IPV4_UDP; udp_hdr = (struct net_udp_hdr *)net_pkt_get_data(pkt, udp_access); if (!udp_hdr || net_pkt_set_data(pkt, udp_access)) { @@ -164,7 +168,7 @@ struct net_udp_hdr *net_udp_input(struct net_pkt *pkt, } if (IS_ENABLED(CONFIG_NET_UDP_CHECKSUM) && - (net_if_need_calc_rx_checksum(net_pkt_iface(pkt)) || + (net_if_need_calc_rx_checksum(net_pkt_iface(pkt), type) || net_pkt_is_ip_reassembled(pkt))) { if (!udp_hdr->chksum) { if (IS_ENABLED(CONFIG_NET_UDP_MISSING_CHECKSUM) && From 7b9a0e7e952d5e1fdb89c9446b73911b1b93153e Mon Sep 17 00:00:00 2001 From: Babak Arisian Date: Wed, 5 Jun 2024 16:35:44 +0200 Subject: [PATCH 2822/2849] Bluetooth: Audio: add add_by_broadcast_name for the assistant shell Add add_by_broadcast_name command that scan for broadcast sources has BT_DATA_BROADCAST_NAME that matches with whatever name is given to the shell command. Fixes #70836 Signed-off-by: Babak Arisian --- include/zephyr/bluetooth/audio/audio.h | 5 + .../audio/shell/bap_broadcast_assistant.c | 273 ++++++++++++------ subsys/bluetooth/shell/bt.c | 10 +- subsys/bluetooth/shell/bt.h | 10 + 4 files changed, 202 insertions(+), 96 deletions(-) diff --git a/include/zephyr/bluetooth/audio/audio.h b/include/zephyr/bluetooth/audio/audio.h index 21af8e5d38577..f847ef35bc397 100644 --- a/include/zephyr/bluetooth/audio/audio.h +++ b/include/zephyr/bluetooth/audio/audio.h @@ -48,6 +48,11 @@ extern "C" { #define BT_AUDIO_BROADCAST_CODE_SIZE 16 +/** The minimum size of a Broadcast Name as defined by Bluetooth Assigned Numbers */ +#define BT_AUDIO_BROADCAST_NAME_LEN_MIN 4 +/** The maximum size of a Broadcast Name as defined by Bluetooth Assigned Numbers */ +#define BT_AUDIO_BROADCAST_NAME_LEN_MAX 128 + /** Size of the stream language value, e.g. "eng" */ #define BT_AUDIO_LANG_SIZE 3 diff --git a/subsys/bluetooth/audio/shell/bap_broadcast_assistant.c b/subsys/bluetooth/audio/shell/bap_broadcast_assistant.c index d0b4dd6410a54..0f64c903e3ca7 100644 --- a/subsys/bluetooth/audio/shell/bap_broadcast_assistant.c +++ b/subsys/bluetooth/audio/shell/bap_broadcast_assistant.c @@ -43,12 +43,18 @@ static size_t received_base_size; static struct bt_auto_scan { uint32_t broadcast_id; + char broadcast_name[BT_AUDIO_BROADCAST_NAME_LEN_MAX + 1]; bool pa_sync; struct bt_bap_bass_subgroup subgroup; } auto_scan = { .broadcast_id = INVALID_BROADCAST_ID, }; +struct bt_scan_recv_info { + uint32_t broadcast_id; + char broadcast_name[BT_AUDIO_BROADCAST_NAME_LEN_MAX + 1]; +}; + static bool pa_decode_base(struct bt_data *data, void *user_data) { const struct bt_bap_base *base = bt_bap_base_get_base_from_ad(data); @@ -304,32 +310,6 @@ static struct bt_bap_broadcast_assistant_cb cbs = { .rem_src = bap_broadcast_assistant_rem_src_cb, }; -static int cmd_bap_broadcast_assistant_discover(const struct shell *sh, - size_t argc, char **argv) -{ - static bool registered; - int result; - - if (!registered) { - static struct bt_le_per_adv_sync_cb cb = { - .recv = pa_recv, - }; - - bt_le_per_adv_sync_cb_register(&cb); - - bt_bap_broadcast_assistant_register_cb(&cbs); - - registered = true; - } - - result = bt_bap_broadcast_assistant_discover(default_conn); - if (result) { - shell_print(sh, "Fail: %d", result); - } - - return result; -} - static int cmd_bap_broadcast_assistant_scan_start(const struct shell *sh, size_t argc, char **argv) { @@ -499,70 +479,49 @@ static int cmd_bap_broadcast_assistant_add_src(const struct shell *sh, static bool broadcast_source_found(struct bt_data *data, void *user_data) { - struct bt_bap_broadcast_assistant_add_src_param param = { 0 }; - const struct bt_le_scan_recv_info *info = user_data; - char addr_str[BT_ADDR_LE_STR_LEN]; + struct bt_scan_recv_info *sr_info = (struct bt_scan_recv_info *)user_data; struct bt_uuid_16 adv_uuid; - uint32_t broadcast_id; - int err; - /* Verify that it is a BAP broadcaster*/ + switch (data->type) { + case BT_DATA_SVC_DATA16: + if (data->data_len < BT_UUID_SIZE_16 + BT_AUDIO_BROADCAST_ID_SIZE) { + return true; + } - if (data->type != BT_DATA_SVC_DATA16) { - return true; - } + if (!bt_uuid_create(&adv_uuid.uuid, data->data, BT_UUID_SIZE_16)) { + return true; + } - if (data->data_len < BT_UUID_SIZE_16 + BT_AUDIO_BROADCAST_ID_SIZE) { - return true; - } + if (bt_uuid_cmp(&adv_uuid.uuid, BT_UUID_BROADCAST_AUDIO) != 0) { + return true; + } - if (!bt_uuid_create(&adv_uuid.uuid, data->data, BT_UUID_SIZE_16)) { + sr_info->broadcast_id = sys_get_le24(data->data + BT_UUID_SIZE_16); return true; - } + case BT_DATA_BROADCAST_NAME: + if (!IN_RANGE(data->data_len, BT_AUDIO_BROADCAST_NAME_LEN_MIN, + BT_AUDIO_BROADCAST_NAME_LEN_MAX)) { + return true; + } - if (bt_uuid_cmp(&adv_uuid.uuid, BT_UUID_BROADCAST_AUDIO) != 0) { + utf8_lcpy(sr_info->broadcast_name, data->data, (data->data_len) + 1); + return true; + default: return true; } - - broadcast_id = sys_get_le24(data->data + BT_UUID_SIZE_16); - - if (broadcast_id != auto_scan.broadcast_id) { - /* Not the one we want */ - return false; - } - - bt_addr_le_to_str(info->addr, addr_str, sizeof(addr_str)); - shell_print(ctx_shell, "Found BAP broadcast source with address %s and ID 0x%06X\n", - addr_str, broadcast_id); - - err = bt_le_scan_stop(); - if (err) { - shell_error(ctx_shell, "Failed to stop scan: %d", err); - } - - bt_addr_le_copy(¶m.addr, info->addr); - param.adv_sid = info->sid; - param.pa_interval = info->interval; - param.broadcast_id = broadcast_id; - param.pa_sync = auto_scan.pa_sync; - param.num_subgroups = 1; - param.subgroups = &auto_scan.subgroup; - - err = bt_bap_broadcast_assistant_add_src(default_conn, ¶m); - if (err) { - shell_print(ctx_shell, "Failed to add source: %d", err); - } - - memset(&auto_scan, 0, sizeof(auto_scan)); - auto_scan.broadcast_id = INVALID_BROADCAST_ID; - - return false; } static void scan_recv_cb(const struct bt_le_scan_recv_info *info, struct net_buf_simple *ad) { - if (auto_scan.broadcast_id == INVALID_BROADCAST_ID) { + struct bt_scan_recv_info sr_info = { 0 }; + struct bt_bap_broadcast_assistant_add_src_param param = { 0 }; + int err; + + sr_info.broadcast_id = INVALID_BROADCAST_ID; + + if ((auto_scan.broadcast_id == INVALID_BROADCAST_ID) && + (strlen(auto_scan.broadcast_name) == 0U)) { /* no op */ return; } @@ -577,17 +536,62 @@ static void scan_recv_cb(const struct bt_le_scan_recv_info *info, return; } - bt_data_parse(ad, broadcast_source_found, (void *)info); + bt_data_parse(ad, broadcast_source_found, (void *)&sr_info); + + /* Verify that it is a BAP broadcaster*/ + if (sr_info.broadcast_id != INVALID_BROADCAST_ID) { + char addr_str[BT_ADDR_LE_STR_LEN]; + bool identified_broadcast = false; + + bt_addr_le_to_str(info->addr, addr_str, sizeof(addr_str)); + + if (sr_info.broadcast_id == auto_scan.broadcast_id) { + identified_broadcast = true; + } + + if ((strlen(auto_scan.broadcast_name) != 0U) && + is_substring(auto_scan.broadcast_name, sr_info.broadcast_name)) { + identified_broadcast = true; + + shell_print(ctx_shell, "Found matched broadcast name '%s' with address %s", + sr_info.broadcast_name, addr_str); + } + + if (identified_broadcast) { + shell_print(ctx_shell, + "Found BAP broadcast source with address %s and ID 0x%06X\n", + addr_str, sr_info.broadcast_id); + + err = bt_le_scan_stop(); + if (err) { + shell_error(ctx_shell, "Failed to stop scan: %d", err); + } + + bt_addr_le_copy(¶m.addr, info->addr); + param.adv_sid = info->sid; + param.pa_interval = info->interval; + param.broadcast_id = sr_info.broadcast_id; + param.pa_sync = auto_scan.pa_sync; + param.num_subgroups = 1; + param.subgroups = &auto_scan.subgroup; + + err = bt_bap_broadcast_assistant_add_src(default_conn, ¶m); + if (err) { + shell_print(ctx_shell, "Failed to add source: %d", err); + } + + memset(&auto_scan, 0, sizeof(auto_scan)); + auto_scan.broadcast_id = INVALID_BROADCAST_ID; + } + } } static void scan_timeout_cb(void) { shell_print(ctx_shell, "Scan timeout"); - if (auto_scan.broadcast_id != INVALID_BROADCAST_ID) { - memset(&auto_scan, 0, sizeof(auto_scan)); - auto_scan.broadcast_id = INVALID_BROADCAST_ID; - } + memset(&auto_scan, 0, sizeof(auto_scan)); + auto_scan.broadcast_id = INVALID_BROADCAST_ID; } static struct bt_le_scan_cb scan_callbacks = { @@ -595,20 +599,42 @@ static struct bt_le_scan_cb scan_callbacks = { .timeout = scan_timeout_cb, }; +static int cmd_bap_broadcast_assistant_discover(const struct shell *sh, + size_t argc, char **argv) +{ + static bool registered; + int result; + + if (!registered) { + static struct bt_le_per_adv_sync_cb cb = { + .recv = pa_recv, + }; + + bt_le_per_adv_sync_cb_register(&cb); + + bt_bap_broadcast_assistant_register_cb(&cbs); + + bt_le_scan_cb_register(&scan_callbacks); + + registered = true; + } + + result = bt_bap_broadcast_assistant_discover(default_conn); + if (result) { + shell_print(sh, "Fail: %d", result); + } + + return result; +} + static int cmd_bap_broadcast_assistant_add_broadcast_id(const struct shell *sh, size_t argc, char **argv) { struct bt_bap_bass_subgroup subgroup = { 0 }; - static bool scan_cbs_registered; unsigned long broadcast_id; int err = 0; - if (!scan_cbs_registered) { - bt_le_scan_cb_register(&scan_callbacks); - scan_cbs_registered = true; - } - if (auto_scan.broadcast_id != INVALID_BROADCAST_ID) { shell_info(sh, "Already scanning, wait for sync or timeout"); @@ -671,6 +697,75 @@ static int cmd_bap_broadcast_assistant_add_broadcast_id(const struct shell *sh, /* Store results in the `auto_scan` struct */ auto_scan.broadcast_id = broadcast_id; memcpy(&auto_scan.subgroup, &subgroup, sizeof(subgroup)); + memset(auto_scan.broadcast_name, 0, sizeof(auto_scan.broadcast_name)); + + return 0; +} + +static int cmd_bap_broadcast_assistant_add_broadcast_name(const struct shell *sh, + size_t argc, char **argv) +{ + struct bt_bap_bass_subgroup subgroup = { 0 }; + char *broadcast_name; + int err = 0; + + broadcast_name = argv[1]; + if (!IN_RANGE(strlen(broadcast_name), BT_AUDIO_BROADCAST_NAME_LEN_MIN, + BT_AUDIO_BROADCAST_NAME_LEN_MAX)) { + + shell_error(sh, "Broadcast name should be minimum %d " + "and maximum %d characters", BT_AUDIO_BROADCAST_NAME_LEN_MIN, + BT_AUDIO_BROADCAST_NAME_LEN_MAX); + + return -ENOEXEC; + } + + auto_scan.pa_sync = shell_strtobool(argv[2], 0, &err); + if (err != 0) { + shell_error(sh, "Could not parse pa_sync: %d", err); + + return -ENOEXEC; + } + + /* TODO: Support multiple subgroups */ + if (argc > 3) { + const unsigned long bis_sync = shell_strtoul(argv[3], 0, &err); + + if (err != 0) { + shell_error(sh, "failed to parse bis_sync: %d", err); + + return -ENOEXEC; + } else if (!VALID_BIS_SYNC(bis_sync)) { + shell_error(sh, "Invalid bis_sync: %lu", bis_sync); + + return -ENOEXEC; + } + + subgroup.bis_sync = bis_sync; + } + + if (argc > 4) { + subgroup.metadata_len = hex2bin(argv[4], strlen(argv[4]), subgroup.metadata, + sizeof(subgroup.metadata)); + + if (subgroup.metadata_len == 0U) { + shell_error(sh, "Could not parse metadata"); + + return -ENOEXEC; + } + } + + err = bt_le_scan_start(BT_LE_SCAN_PASSIVE, NULL); + if (err) { + shell_print(sh, "Fail to start scanning: %d", err); + + return -ENOEXEC; + } + + /* Store results in the `auto_scan` struct */ + utf8_lcpy(auto_scan.broadcast_name, broadcast_name, strlen(broadcast_name) + 1); + auto_scan.broadcast_id = INVALID_BROADCAST_ID; + memcpy(&auto_scan.subgroup, &subgroup, sizeof(subgroup)); return 0; } @@ -1073,6 +1168,10 @@ SHELL_STATIC_SUBCMD_SET_CREATE( "Add a source by broadcast ID " "[] []", cmd_bap_broadcast_assistant_add_broadcast_id, 3, 2), + SHELL_CMD_ARG(add_broadcast_name, NULL, + "Add a source by broadcast name " + "[] []", + cmd_bap_broadcast_assistant_add_broadcast_name, 3, 2), SHELL_CMD_ARG(add_pa_sync, NULL, "Add a PA sync as a source " "[bis_index [bis_index [bix_index [...]]]]>", diff --git a/subsys/bluetooth/shell/bt.c b/subsys/bluetooth/shell/bt.c index 95766335bee51..b36286764ef13 100644 --- a/subsys/bluetooth/shell/bt.c +++ b/subsys/bluetooth/shell/bt.c @@ -259,15 +259,7 @@ int ead_update_ad(void); static bool bt_shell_ead_decrypt_scan; -/** - * @brief Compares two strings without case sensitivy - * - * @param substr The substring - * @param str The string to find the substring in - * - * @return true if @substr is a substring of @p, else false - */ -static bool is_substring(const char *substr, const char *str) +bool is_substring(const char *substr, const char *str) { const size_t str_len = strlen(str); const size_t sub_str_len = strlen(substr); diff --git a/subsys/bluetooth/shell/bt.h b/subsys/bluetooth/shell/bt.h index 5bc1448ae85db..a22ae9d43a2c6 100644 --- a/subsys/bluetooth/shell/bt.h +++ b/subsys/bluetooth/shell/bt.h @@ -36,4 +36,14 @@ extern struct bt_le_per_adv_sync *per_adv_syncs[CONFIG_BT_PER_ADV_SYNC_MAX]; void conn_addr_str(struct bt_conn *conn, char *addr, size_t len); +/** + * @brief Compares two strings without case sensitivy + * + * @param substr The substring + * @param str The string to find the substring in + * + * @return true if @substr is a substring of @p, else false + */ +bool is_substring(const char *substr, const char *str); + #endif /* __BT_H */ From be23e70fffac332df2ad8bd9e458701ef86cf3f8 Mon Sep 17 00:00:00 2001 From: Daniel DeGrasse Date: Wed, 5 Jun 2024 10:34:30 -0500 Subject: [PATCH 2823/2849] drivers: display: gc9x01: convert to MIPI DBI API Convert galaxycore GC9X01 to MIPI DBI API. In tree boards and tests using this display have also had their devicetrees updated to use the new MIPI DBI SPI emulated device. Signed-off-by: Daniel DeGrasse --- .../seeed_xiao_round_display.overlay | 32 +++-- .../esp32s3_touch_lcd_1_28_esp32s3_procpu.dts | 35 +++-- drivers/display/Kconfig.gc9x01x | 2 +- drivers/display/display_gc9x01x.c | 129 +++++------------- dts/bindings/display/galaxycore,gc9x01x.yaml | 16 +-- tests/drivers/build_all/display/app.overlay | 29 ++-- 6 files changed, 96 insertions(+), 147 deletions(-) diff --git a/boards/shields/seeed_xiao_round_display/seeed_xiao_round_display.overlay b/boards/shields/seeed_xiao_round_display/seeed_xiao_round_display.overlay index dab060bb60404..d4a3ad1329e73 100644 --- a/boards/shields/seeed_xiao_round_display/seeed_xiao_round_display.overlay +++ b/boards/shields/seeed_xiao_round_display/seeed_xiao_round_display.overlay @@ -27,6 +27,26 @@ aliases { rtc = &pcf8563_xiao_round_display; }; + + xiao_round_display_mipi_dbi { + compatible = "zephyr,mipi-dbi-spi"; + spi-dev = <&xiao_spi>; + dc-gpios = <&xiao_d 3 GPIO_ACTIVE_HIGH>; + write-only; + #address-cells = <1>; + #size-cells = <0>; + + gc9a01_xiao_round_display: gc9a01@0 { + status = "okay"; + compatible = "galaxycore,gc9x01x"; + reg = <0>; + mipi-max-frequency = ; + pixel-format = ; + width = <240>; + height = <240>; + display-inversion; + }; + }; }; &xiao_adc { @@ -62,18 +82,6 @@ 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>; diff --git a/boards/waveshare/esp32s3_touch_lcd_1_28/esp32s3_touch_lcd_1_28_esp32s3_procpu.dts b/boards/waveshare/esp32s3_touch_lcd_1_28/esp32s3_touch_lcd_1_28_esp32s3_procpu.dts index f6a62874fe50a..cb4bd891f611f 100644 --- a/boards/waveshare/esp32s3_touch_lcd_1_28/esp32s3_touch_lcd_1_28_esp32s3_procpu.dts +++ b/boards/waveshare/esp32s3_touch_lcd_1_28/esp32s3_touch_lcd_1_28_esp32s3_procpu.dts @@ -56,6 +56,28 @@ pwms = <&ledc0 0 PWM_HZ(250) PWM_POLARITY_NORMAL>; }; }; + + /* MIPI DBI */ + mipi_dbi { + compatible = "zephyr,mipi-dbi-spi"; + spi-dev = <&spi2>; + dc-gpios = <&gpio0 8 GPIO_ACTIVE_HIGH>; + reset-gpios = <&gpio0 14 GPIO_ACTIVE_LOW>; + write-only; + #address-cells = <1>; + #size-cells = <0>; + + gc9a01: gc9a01@0 { + status = "okay"; + compatible = "galaxycore,gc9x01x"; + reg = <0>; + mipi-max-frequency = <100000000>; + pixel-format = ; + display-inversion; + width = <240>; + height = <240>; + }; + }; }; &flash0 { @@ -146,19 +168,6 @@ pinctrl-0 = <&spim2_default>; pinctrl-names = "default"; cs-gpios = <&gpio0 9 GPIO_ACTIVE_LOW>; - - gc9a01: gc9a01@0 { - status = "okay"; - compatible = "galaxycore,gc9x01x"; - reg = <0>; - spi-max-frequency = <100000000>; - cmd-data-gpios = <&gpio0 8 GPIO_ACTIVE_HIGH>; - reset-gpios = <&gpio0 14 GPIO_ACTIVE_LOW>; - pixel-format = ; - display-inversion; - width = <240>; - height = <240>; - }; }; &trng0 { diff --git a/drivers/display/Kconfig.gc9x01x b/drivers/display/Kconfig.gc9x01x index aba24c445f1ae..650b0de919155 100644 --- a/drivers/display/Kconfig.gc9x01x +++ b/drivers/display/Kconfig.gc9x01x @@ -5,6 +5,6 @@ config GC9X01X bool "GC9X01X display driver" default y depends on DT_HAS_GALAXYCORE_GC9X01X_ENABLED - select SPI + select MIPI_DBI help Enable driver for GC9X01X display driver. diff --git a/drivers/display/display_gc9x01x.c b/drivers/display/display_gc9x01x.c index 1d432d3f3556b..963e0dbe7a69a 100644 --- a/drivers/display/display_gc9x01x.c +++ b/drivers/display/display_gc9x01x.c @@ -10,8 +10,7 @@ #include #include -#include -#include +#include #include #include #include @@ -19,12 +18,6 @@ #include LOG_MODULE_REGISTER(display_gc9x01x, CONFIG_DISPLAY_LOG_LEVEL); -/* Command/data GPIO level for commands. */ -#define GC9X01X_GPIO_LEVEL_CMD 0U - -/* Command/data GPIO level for data. */ -#define GC9X01X_GPIO_LEVEL_DATA 1U - /* Maximum number of default init registers */ #define GC9X01X_NUM_DEFAULT_INIT_REGS 12U @@ -37,9 +30,8 @@ struct gc9x01x_data { /* Configuration data struct.*/ struct gc9x01x_config { - struct spi_dt_spec spi; - struct gpio_dt_spec cmd_data; - struct gpio_dt_spec reset; + const struct device *mipi_dev; + struct mipi_dbi_config dbi_config; uint8_t pixel_format; uint16_t orientation; uint16_t x_resolution; @@ -229,35 +221,9 @@ static int gc9x01x_transmit(const struct device *dev, uint8_t cmd, const void *t size_t tx_len) { const struct gc9x01x_config *config = dev->config; - int ret; - struct spi_buf tx_buf = {.buf = &cmd, .len = 1U}; - struct spi_buf_set tx_bufs = {.buffers = &tx_buf, .count = 1U}; - - ret = gpio_pin_set_dt(&config->cmd_data, GC9X01X_GPIO_LEVEL_CMD); - if (ret < 0) { - return ret; - } - ret = spi_write_dt(&config->spi, &tx_bufs); - if (ret < 0) { - return ret; - } - - /* send data (if any) */ - if (tx_data != NULL) { - tx_buf.buf = (void *)tx_data; - tx_buf.len = tx_len; - - ret = gpio_pin_set_dt(&config->cmd_data, GC9X01X_GPIO_LEVEL_DATA); - if (ret < 0) { - return ret; - } - ret = spi_write_dt(&config->spi, &tx_bufs); - if (ret < 0) { - return ret; - } - } - return 0; + return mipi_dbi_command_write(config->mipi_dev, &config->dbi_config, + cmd, tx_data, tx_len); } static int gc9x01x_regs_init(const struct device *dev) @@ -266,6 +232,10 @@ static int gc9x01x_regs_init(const struct device *dev) const struct gc9x01x_regs *regs = config->regs; int ret; + if (!device_is_ready(config->mipi_dev)) { + return -ENODEV; + } + /* Enable inter-command mode */ ret = gc9x01x_transmit(dev, GC9X01X_CMD_INREGEN1, NULL, 0); if (ret < 0) { @@ -371,17 +341,15 @@ static int gc9x01x_enter_sleep(const struct device *dev) static int gc9x01x_hw_reset(const struct device *dev) { const struct gc9x01x_config *config = dev->config; + int ret; - if (config->reset.port == NULL) { - return -ENODEV; + ret = mipi_dbi_reset(config->mipi_dev, 100); + if (ret < 0) { + return ret; } - - gpio_pin_set_dt(&config->reset, 1U); - k_msleep(100); - gpio_pin_set_dt(&config->reset, 0U); k_msleep(10); - return 0; + return ret; } static int gc9x01x_display_blanking_off(const struct device *dev) @@ -492,38 +460,8 @@ static int gc9x01x_configure(const struct device *dev) static int gc9x01x_init(const struct device *dev) { - const struct gc9x01x_config *config = dev->config; int ret; - if (!spi_is_ready_dt(&config->spi)) { - LOG_ERR("SPI device is not ready"); - return -ENODEV; - } - - if (!gpio_is_ready_dt(&config->cmd_data)) { - LOG_ERR("Command/Data GPIO device not ready"); - return -ENODEV; - } - - ret = gpio_pin_configure_dt(&config->cmd_data, GPIO_OUTPUT); - if (ret < 0) { - LOG_ERR("Could not configure command/data GPIO (%d)", ret); - return ret; - } - - if (config->reset.port != NULL) { - if (!device_is_ready(config->reset.port)) { - LOG_ERR("Reset GPIO device not ready"); - return -ENODEV; - } - - ret = gpio_pin_configure_dt(&config->reset, GPIO_OUTPUT_INACTIVE); - if (ret < 0) { - LOG_ERR("Could not configure reset GPIO (%d)", ret); - return ret; - } - } - gc9x01x_hw_reset(dev); gc9x01x_display_blanking_on(dev); @@ -573,8 +511,7 @@ static int gc9x01x_write(const struct device *dev, const uint16_t x, const uint1 struct gc9x01x_data *data = dev->data; int ret; const uint8_t *write_data_start = (const uint8_t *)buf; - struct spi_buf tx_buf; - struct spi_buf_set tx_bufs; + struct display_buffer_descriptor mipi_desc; uint16_t write_cnt; uint16_t nbr_of_writes; uint16_t write_h; @@ -592,26 +529,30 @@ static int gc9x01x_write(const struct device *dev, const uint16_t x, const uint1 if (desc->pitch > desc->width) { write_h = 1U; nbr_of_writes = desc->height; + mipi_desc.height = 1; + mipi_desc.buf_size = desc->pitch * data->bytes_per_pixel; } else { write_h = desc->height; + mipi_desc.height = desc->height; + mipi_desc.buf_size = desc->width * data->bytes_per_pixel * write_h; nbr_of_writes = 1U; } - ret = gc9x01x_transmit(dev, GC9X01X_CMD_MEMWR, write_data_start, - desc->width * data->bytes_per_pixel * write_h); + mipi_desc.width = desc->width; + /* Per MIPI API, pitch must always match width */ + mipi_desc.pitch = desc->width; + + ret = gc9x01x_transmit(dev, GC9X01X_CMD_MEMWR, NULL, 0); if (ret < 0) { return ret; } - tx_bufs.buffers = &tx_buf; - tx_bufs.count = 1U; - - write_data_start += desc->pitch * data->bytes_per_pixel; - for (write_cnt = 1U; write_cnt < nbr_of_writes; ++write_cnt) { - tx_buf.buf = (void *)write_data_start; - tx_buf.len = desc->width * data->bytes_per_pixel * write_h; - - ret = spi_write_dt(&config->spi, &tx_bufs); + for (write_cnt = 0U; write_cnt < nbr_of_writes; ++write_cnt) { + ret = mipi_dbi_write_display(config->mipi_dev, + &config->dbi_config, + write_data_start, + &mipi_desc, + data->pixel_format); if (ret < 0) { return ret; } @@ -679,9 +620,13 @@ static const struct display_driver_api gc9x01x_api = { #define GC9X01X_INIT(inst) \ GC9X01X_REGS_INIT(inst); \ static const struct gc9x01x_config gc9x01x_config_##inst = { \ - .spi = SPI_DT_SPEC_INST_GET(inst, SPI_OP_MODE_MASTER | SPI_WORD_SET(8), 0), \ - .cmd_data = GPIO_DT_SPEC_INST_GET(inst, cmd_data_gpios), \ - .reset = GPIO_DT_SPEC_INST_GET_OR(inst, reset_gpios, {0}), \ + .mipi_dev = DEVICE_DT_GET(DT_INST_PARENT(inst)), \ + .dbi_config = { \ + .mode = MIPI_DBI_MODE_SPI_4WIRE, \ + .config = MIPI_DBI_SPI_CONFIG_DT_INST(inst, \ + SPI_OP_MODE_MASTER | \ + SPI_WORD_SET(8), 0), \ + }, \ .pixel_format = DT_INST_PROP(inst, pixel_format), \ .orientation = DT_INST_ENUM_IDX(inst, orientation), \ .x_resolution = DT_INST_PROP(inst, width), \ diff --git a/dts/bindings/display/galaxycore,gc9x01x.yaml b/dts/bindings/display/galaxycore,gc9x01x.yaml index bc85c652b0635..7867de55a0dea 100644 --- a/dts/bindings/display/galaxycore,gc9x01x.yaml +++ b/dts/bindings/display/galaxycore,gc9x01x.yaml @@ -29,23 +29,9 @@ description: | compatible: "galaxycore,gc9x01x" -include: [spi-device.yaml, display-controller.yaml, lcd-controller.yaml] +include: [mipi-dbi-spi-device.yaml, display-controller.yaml, lcd-controller.yaml] properties: - reset-gpios: - type: phandle-array - description: | - RESET pin of the GC9X01X. - If connected directly the MCU pin should be configured - as active low. - - cmd-data-gpios: - type: phandle-array - required: true - description: | - Data/Command pin of the GC9X01X is to be configured - high(1) for data, low(0) for command. - orientation: type: string default: "normal" diff --git a/tests/drivers/build_all/display/app.overlay b/tests/drivers/build_all/display/app.overlay index a30348fcf0dcf..b17b02e8d7b03 100644 --- a/tests/drivers/build_all/display/app.overlay +++ b/tests/drivers/build_all/display/app.overlay @@ -125,6 +125,16 @@ tcon = <0x22>; }; }; + + test_spi_gc9x01x: gc9x01x@6 { + compatible = "galaxycore,gc9x01x"; + reg = <6>; + mipi-max-frequency = <100000000>; + pixel-format = <16>; + + width = <240>; + height = <240>; + }; }; @@ -136,21 +146,12 @@ status = "okay"; clock-frequency = <2000000>; - /* one entry for every devices at spi.dtsi */ + /* one entry for every device. Note that this must + * include MIPI DBI devices as well. + */ cs-gpios = <&test_gpio 0 0 &test_gpio 0 1 &test_gpio 0 2 - &test_gpio 0 3 &test_gpio 0 4 &test_gpio 0 5>; - - test_spi_gc9x01x: gc9x01x@1 { - compatible = "galaxycore,gc9x01x"; - reg = <1>; - spi-max-frequency = <100000000>; - cmd-data-gpios = <&test_gpio 1 0>; - reset-gpios = <&test_gpio 2 0>; - pixel-format = <16>; - - width = <240>; - height = <240>; - }; + &test_gpio 0 3 &test_gpio 0 4 &test_gpio 0 5 + &test_gpio 0 6>; test_led_strip_0: lpd8806@2 { compatible = "greeled,lpd8806"; From 1893928d94d5e29d14d0589ec5015e37e12babfe Mon Sep 17 00:00:00 2001 From: Daniel DeGrasse Date: Wed, 5 Jun 2024 10:34:45 -0500 Subject: [PATCH 2824/2849] tests: drivers: build_all: display: clean up reg addresses Clean up register addresses for devices defined as children of the dummy SPI bus, so that they start from zero. This ensures all SPI chip select gpio indices will be used Signed-off-by: Daniel DeGrasse --- tests/drivers/build_all/display/app.overlay | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/drivers/build_all/display/app.overlay b/tests/drivers/build_all/display/app.overlay index b17b02e8d7b03..1709db0291223 100644 --- a/tests/drivers/build_all/display/app.overlay +++ b/tests/drivers/build_all/display/app.overlay @@ -153,9 +153,9 @@ &test_gpio 0 3 &test_gpio 0 4 &test_gpio 0 5 &test_gpio 0 6>; - test_led_strip_0: lpd8806@2 { + test_led_strip_0: lpd8806@0 { compatible = "greeled,lpd8806"; - reg = <2>; + reg = <0>; spi-max-frequency = <2000000>; chain-length = <1>; color-mapping = ; }; - test_led_strip_1: ws2812_spi@3 { + test_led_strip_1: ws2812_spi@1 { compatible = "worldsemi,ws2812-spi"; - reg = <3>; + reg = <1>; spi-max-frequency = <2000000>; spi-one-frame = <1>; spi-zero-frame = <1>; From 94ade2578cba8768b17bcd16802550d1743cacc4 Mon Sep 17 00:00:00 2001 From: Daniel DeGrasse Date: Mon, 3 Jun 2024 17:49:13 -0500 Subject: [PATCH 2825/2849] doc: releases: migration-guide: add migration note for GC9X01 display Add migration note to GC9X01 display, which has been converted to the MIPI DBI API. Signed-off-by: Daniel DeGrasse --- doc/releases/migration-guide-3.7.rst | 44 ++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/doc/releases/migration-guide-3.7.rst b/doc/releases/migration-guide-3.7.rst index bdd4e884d23c9..835ad1afa1de4 100644 --- a/doc/releases/migration-guide-3.7.rst +++ b/doc/releases/migration-guide-3.7.rst @@ -312,6 +312,50 @@ Controller Area Network (CAN) Display ======= +* GC9X01 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. (:github:`73686`) + For an example, see below: + + .. code-block:: devicetree + + /* Legacy GC9X01 display definition */ + &spi0 { + gc9a01: gc9a01@0 { + status = "okay"; + compatible = "galaxycore,gc9x01x"; + reg = <0>; + spi-max-frequency = <100000000>; + cmd-data-gpios = <&gpio0 8 GPIO_ACTIVE_HIGH>; + reset-gpios = <&gpio0 14 GPIO_ACTIVE_LOW>; + ... + }; + }; + + /* New display definition with MIPI DBI device */ + + #include + + ... + + mipi_dbi { + compatible = "zephyr,mipi-dbi-spi"; + dc-gpios = <&gpio0 8 GPIO_ACTIVE_HIGH>; + reset-gpios = <&gpio0 14 GPIO_ACTIVE_LOW>; + spi-dev = <&spi0>; + #address-cells = <1>; + #size-cells = <0>; + + gc9a01: gc9a01@0 { + status = "okay"; + compatible = "galaxycore,gc9x01x"; + reg = <0>; + mipi-max-frequency = <100000000>; + ... + }; + }; + + * 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 From 64855973c0dfdc73452bfebb30e1d0f95f5765e8 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Fri, 31 May 2024 15:43:39 -0400 Subject: [PATCH 2826/2849] arm64: speed up simple memcpy/memset alternatives We need those simple alternatives to be used during early boot when the MMU is not yet enabled. However they don't have to be the slowest they can be. Those functions are mainly used to clear .bss sections and copy .data to final destination when doing XIP, etc. Therefore it is very likely for provided pointers to be 64-bit aligned. Let's optimize for that case. Signed-off-by: Nicolas Pitre --- arch/arm64/core/prep_c.c | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/arch/arm64/core/prep_c.c b/arch/arm64/core/prep_c.c index bfd3b7c1eaa90..10649eb8fde82 100644 --- a/arch/arm64/core/prep_c.c +++ b/arch/arm64/core/prep_c.c @@ -27,6 +27,22 @@ __weak void z_arm64_mm_init(bool is_primary_core) { } */ void z_early_memset(void *dst, int c, size_t n) { + if (((uintptr_t)dst & (sizeof(uint64_t) - 1)) == 0) { + /* speed-up if 64-bit aligned which should be the default */ + uint64_t *d8 = dst; + uint64_t c8 = (uint8_t)c; + + c8 |= c8 << 8; + c8 |= c8 << 16; + c8 |= c8 << 32; + + while (n >= 8) { + *d8++ = c8; + n -= 8; + } + dst = d8; + } + uint8_t *d = dst; while (n--) { @@ -36,6 +52,19 @@ void z_early_memset(void *dst, int c, size_t n) void z_early_memcpy(void *dst, const void *src, size_t n) { + if ((((uintptr_t)dst | (uintptr_t)src) & (sizeof(uint64_t) - 1)) == 0) { + /* speed-up if 64-bit aligned which should be the default */ + uint64_t *d8 = dst; + const uint64_t *s8 = src; + + while (n >= 8) { + *d8++ = *s8++; + n -= 8; + } + dst = d8; + src = s8; + } + uint8_t *d = dst; const uint8_t *s = src; From 696edbe841aa04a384e86a5a850c2c69ab1eaa2f Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Fri, 31 May 2024 18:20:44 -0400 Subject: [PATCH 2827/2849] arm64: move simple memcpy/memset alternatives to assembly Assembly implementation for z_early_memset() and z_early_memcpy(). Otherwise the compiler will happily replace our C code with a direct call to memset/memcpy which kind of defeats the purpose. Signed-off-by: Nicolas Pitre --- arch/arm64/core/CMakeLists.txt | 1 + arch/arm64/core/early_mem_funcs.S | 83 +++++++++++++++++++++++++++++++ arch/arm64/core/prep_c.c | 52 ------------------- 3 files changed, 84 insertions(+), 52 deletions(-) create mode 100644 arch/arm64/core/early_mem_funcs.S diff --git a/arch/arm64/core/CMakeLists.txt b/arch/arm64/core/CMakeLists.txt index 09822dfae4789..03a34e439bb21 100644 --- a/arch/arm64/core/CMakeLists.txt +++ b/arch/arm64/core/CMakeLists.txt @@ -4,6 +4,7 @@ zephyr_library() zephyr_library_sources( cpu_idle.S + early_mem_funcs.S fatal.c irq_init.c irq_manage.c diff --git a/arch/arm64/core/early_mem_funcs.S b/arch/arm64/core/early_mem_funcs.S new file mode 100644 index 0000000000000..383cdec790195 --- /dev/null +++ b/arch/arm64/core/early_mem_funcs.S @@ -0,0 +1,83 @@ +/* + * Copyright (c) BayLibre SAS + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +_ASM_FILE_PROLOGUE + +/* + * These simple memset and memcpy alternatives are necessary as the optimized + * ones depend on the MMU to be active (see commit c5b898743a20). + * + * Furthermore, we can't implement those in C as the compiler is just too + * smart for its own good and replaces our simple loops into direct calls + * to memset or memcpy on its own. + */ + +/* void z_early_memset(void *dst, int c, size_t n) */ +GTEXT(z_early_memset) +SECTION_FUNC(TEXT, z_early_memset) + + /* is dst pointer 8-bytes aligned? */ + tst x0, #0x7 + b.ne 2f + + /* at least 8 bytes to set? */ + cmp x2, #8 + b.lo 2f + + /* spread the byte value across whole 64 bits */ + and x8, x1, #0xff + mov x9, #0x0101010101010101 + mul x8, x8, x9 + +1: /* 8 bytes at a time */ + sub x2, x2, #8 + cmp x2, #7 + str x8, [x0], #8 + b.hi 1b + +2: /* at least one byte to set? */ + cbz x2, 4f + +3: /* one byte at a time */ + subs x2, x2, #1 + strb w8, [x0], #1 + b.ne 3b + +4: ret + +/* void z_early_memcpy(void *dst, const void *src, size_t n) */ +GTEXT(z_early_memcpy) +SECTION_FUNC(TEXT, z_early_memcpy) + + /* are dst and src pointers 8-bytes aligned? */ + orr x8, x1, x0 + tst x8, #0x7 + b.ne 2f + + /* at least 8 bytes to copy? */ + cmp x2, #8 + b.lo 2f + +1: /* 8 bytes at a time */ + ldr x8, [x1], #8 + sub x2, x2, #8 + cmp x2, #7 + str x8, [x0], #8 + b.hi 1b + +2: /* at least one byte to copy? */ + cbz x2, 4f + +3: /* one byte at a time */ + ldrb w8, [x1], #1 + subs x2, x2, #1 + strb w8, [x0], #1 + b.ne 3b + +4: ret diff --git a/arch/arm64/core/prep_c.c b/arch/arm64/core/prep_c.c index 10649eb8fde82..1aca46f23767e 100644 --- a/arch/arm64/core/prep_c.c +++ b/arch/arm64/core/prep_c.c @@ -21,58 +21,6 @@ extern void z_arm64_mm_init(bool is_primary_core); __weak void z_arm64_mm_init(bool is_primary_core) { } -/* - * These simple memset/memcpy alternatives are necessary as the optimized - * ones depend on the MMU to be active (see commit c5b898743a20). - */ -void z_early_memset(void *dst, int c, size_t n) -{ - if (((uintptr_t)dst & (sizeof(uint64_t) - 1)) == 0) { - /* speed-up if 64-bit aligned which should be the default */ - uint64_t *d8 = dst; - uint64_t c8 = (uint8_t)c; - - c8 |= c8 << 8; - c8 |= c8 << 16; - c8 |= c8 << 32; - - while (n >= 8) { - *d8++ = c8; - n -= 8; - } - dst = d8; - } - - uint8_t *d = dst; - - while (n--) { - *d++ = c; - } -} - -void z_early_memcpy(void *dst, const void *src, size_t n) -{ - if ((((uintptr_t)dst | (uintptr_t)src) & (sizeof(uint64_t) - 1)) == 0) { - /* speed-up if 64-bit aligned which should be the default */ - uint64_t *d8 = dst; - const uint64_t *s8 = src; - - while (n >= 8) { - *d8++ = *s8++; - n -= 8; - } - dst = d8; - src = s8; - } - - uint8_t *d = dst; - const uint8_t *s = src; - - while (n--) { - *d++ = *s++; - } -} - /** * * @brief Prepare to and run C code From 15ddfa8b80e2f21fdb4732f6a3e274fdbd67d0c6 Mon Sep 17 00:00:00 2001 From: Hess Nathan Date: Fri, 26 Apr 2024 10:20:16 +0200 Subject: [PATCH 2828/2849] 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 --- include/zephyr/app_memory/app_memdomain.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/include/zephyr/app_memory/app_memdomain.h b/include/zephyr/app_memory/app_memdomain.h index 08e28982ad632..d53a3d2266a27 100644 --- a/include/zephyr/app_memory/app_memdomain.h +++ b/include/zephyr/app_memory/app_memdomain.h @@ -128,16 +128,16 @@ struct z_app_region { extern char Z_APP_START(name)[]; \ extern char Z_APP_SIZE(name)[]; \ struct k_mem_partition name = { \ - .start = (uintptr_t) &Z_APP_START(name), \ - .size = (size_t) &Z_APP_SIZE(name), \ + .start = (uintptr_t) &Z_APP_START(name)[0], \ + .size = (size_t) &Z_APP_SIZE(name)[0], \ .attr = K_MEM_PARTITION_P_RW_U_RW \ }; \ extern char Z_APP_BSS_START(name)[]; \ extern char Z_APP_BSS_SIZE(name)[]; \ Z_GENERIC_SECTION(.app_regions.name) \ const struct z_app_region name##_region = { \ - .bss_start = &Z_APP_BSS_START(name), \ - .bss_size = (size_t) &Z_APP_BSS_SIZE(name) \ + .bss_start = &Z_APP_BSS_START(name)[0], \ + .bss_size = (size_t) &Z_APP_BSS_SIZE(name)[0] \ }; \ Z_APPMEM_PLACEHOLDER(name) #else From 3db614fe3b66c55713de9d6cb9f2e938e8543852 Mon Sep 17 00:00:00 2001 From: David Ullmann Date: Mon, 11 Mar 2024 13:21:05 -0400 Subject: [PATCH 2829/2849] dts: bindings: Add reyax adding vendor prefix to prepare for adding lora module Signed-off-by: David Ullmann --- 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 4580131de931c..f6152d693646c 100644 --- a/dts/bindings/vendor-prefixes.txt +++ b/dts/bindings/vendor-prefixes.txt @@ -554,6 +554,7 @@ renode Antmicro's open source simulation and virtual development framework rervision Shenzhen Rervision Technology Co., Ltd. revotics Revolution Robotics, Inc. (Revotics) rex iMX6 Rex Project +reyax Reyax Technology Co., Ltd. richtek Richtek Technology Corporation ricoh Ricoh Co. Ltd. rikomagic Rikomagic Tech Corp. Ltd From de6274f302733de03b1df1d829fd9b6567363ce7 Mon Sep 17 00:00:00 2001 From: David Ullmann Date: Mon, 11 Mar 2024 13:38:02 -0400 Subject: [PATCH 2830/2849] lora: add config for reyax lora module adding the Kconfig for reyax lora module Signed-off-by: David Ullmann --- drivers/lora/Kconfig | 2 ++ drivers/lora/Kconfig.rylrxxx | 44 ++++++++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+) create mode 100644 drivers/lora/Kconfig.rylrxxx diff --git a/drivers/lora/Kconfig b/drivers/lora/Kconfig index 585f122c3d6fd..6319ccf6be9e2 100644 --- a/drivers/lora/Kconfig +++ b/drivers/lora/Kconfig @@ -33,4 +33,6 @@ config LORA_INIT_PRIORITY source "drivers/lora/Kconfig.sx12xx" +source "drivers/lora/Kconfig.rylrxxx" + endif # LORA diff --git a/drivers/lora/Kconfig.rylrxxx b/drivers/lora/Kconfig.rylrxxx new file mode 100644 index 0000000000000..8daf137338d37 --- /dev/null +++ b/drivers/lora/Kconfig.rylrxxx @@ -0,0 +1,44 @@ +# +# Copyright (c) 2024 David Ullmann +# +# SPDX-License-Identifier: Apache-2.0 +# + +config LORA_RYLRXXX + bool "Reyax LYLR driver" + depends on DT_HAS_REYAX_RYLRXXX_ENABLED + select MODEM_MODULES + select MODEM_CHAT + select MODEM_PIPE + select MODEM_BACKEND_UART + select GPIO + help + Enable the Reyax LYLR driver + +if LORA_RYLRXXX + +config LORA_RYLRXX_CMD_BUF_SIZE + int "cmd buffer size" + default 256 + help + Configure the cmd buffer size + +config RYLRXXX_UNSOLICITED_RX_MSGQ_SIZE + int "number of message to store in message queue" + default 1 + help + Configure the size of message queue + +config RYLRXXX_RADIO_CMD_RESPONSE_TIMEOUT_MS + int "timeout when waiting for response from radio serial interface after send cmd" + default 500 + help + Configure the number of milliseconds before timing out when waiting for acknowledgment from radio after sending cmd + +config RYLRXXX_MODEM_BUFFERS_SIZE + int "size of buffers for modem library" + default 512 + help + Configure the size of buffers for modem library + +endif # LORA_RYLRXXX From 421e5988251550931c4fb6093f8ab90f00e5e6a2 Mon Sep 17 00:00:00 2001 From: David Ullmann Date: Mon, 11 Mar 2024 13:40:41 -0400 Subject: [PATCH 2831/2849] dts: lora: add board support for reyax lora module adding board support for reyax module as a shield on psoc62s4 board Signed-off-by: David Ullmann --- .../infineon/cy8ckit_062s4/cy8ckit_062s4.dts | 34 ++++++++++++++++++- boards/shields/reyax_lora/Kconfig.shield | 5 +++ .../reyax_lora/boards/cy8ckit_062s4.conf | 6 ++++ .../reyax_lora/boards/cy8ckit_062s4.overlay | 26 ++++++++++++++ boards/shields/reyax_lora/doc/index.rst | 29 ++++++++++++++++ boards/shields/reyax_lora/reyax_lora.overlay | 23 +++++++++++++ dts/bindings/lora/reyax,rylrxxx.yaml | 13 +++++++ 7 files changed, 135 insertions(+), 1 deletion(-) create mode 100644 boards/shields/reyax_lora/Kconfig.shield create mode 100644 boards/shields/reyax_lora/boards/cy8ckit_062s4.conf create mode 100644 boards/shields/reyax_lora/boards/cy8ckit_062s4.overlay create mode 100644 boards/shields/reyax_lora/doc/index.rst create mode 100644 boards/shields/reyax_lora/reyax_lora.overlay create mode 100644 dts/bindings/lora/reyax,rylrxxx.yaml diff --git a/boards/infineon/cy8ckit_062s4/cy8ckit_062s4.dts b/boards/infineon/cy8ckit_062s4/cy8ckit_062s4.dts index 457878a62b7a7..9328a0cf60dcf 100644 --- a/boards/infineon/cy8ckit_062s4/cy8ckit_062s4.dts +++ b/boards/infineon/cy8ckit_062s4/cy8ckit_062s4.dts @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 David Ullmann + * Copyright (c) 2024 David Ullmann * SPDX-License-Identifier: Apache-2.0 */ @@ -29,6 +29,32 @@ }; + arduino_header: connector { + compatible = "arduino-header-r3"; + #gpio-cells = <2>; + gpio-map-mask = <0xffffffff 0xffffffc0>; + gpio-map-pass-thru = <0 0x3f>; /* shared */ + gpio-map = <0 0 &gpio_prt10 0 0>, /* A0 */ + <1 0 &gpio_prt10 1 0>, /* A1 */ + <2 0 &gpio_prt10 2 0>, /* A2 */ + <3 0 &gpio_prt10 3 0>, /* A3 */ + <4 0 &gpio_prt10 4 0>, /* A4 */ + <5 0 &gpio_prt10 5 0>, /* A5 */ + <6 0 &gpio_prt0 2 0>, /* D0-RX-5 */ + <7 0 &gpio_prt0 3 0>, /* D1-TX-5 */ + <8 0 &gpio_prt5 0 0>, /* D2-RTS-5 */ + <9 0 &gpio_prt5 1 0>, /* D3-CTS-5 */ + <10 0 &gpio_prt5 6 0>, /* D4 */ + <11 0 &gpio_prt5 7 0>, /* D5 */ + <12 0 &gpio_prt6 2 0>, /* D6 */ + <13 0 &gpio_prt6 3 0>, /* D7 */ + <14 0 &gpio_prt2 4 0>, /* D8-RX-6 */ + <15 0 &gpio_prt2 6 0>, /* D9-TX-6 */ + <16 0 &gpio_prt2 3 0>, /* D10 */ + <17 0 &gpio_prt2 0 0>, /* D11 */ + <18 0 &gpio_prt2 1 0>, /* D12 */ + <19 0 &gpio_prt2 2 0>; /* D13 */ + }; }; &p3_1_scb2_uart_tx { @@ -55,3 +81,9 @@ uart2: &scb2 { &gpio_prt2 { status = "okay"; }; + +uart0: &scb0 { + compatible = "infineon,cat1-uart"; +}; + +arduino_serial: &uart0 {}; diff --git a/boards/shields/reyax_lora/Kconfig.shield b/boards/shields/reyax_lora/Kconfig.shield new file mode 100644 index 0000000000000..c82a3eacc27b4 --- /dev/null +++ b/boards/shields/reyax_lora/Kconfig.shield @@ -0,0 +1,5 @@ +# Copyright (c) 2024 David Ullmann +# SPDX-License-Identifier: Apache-2.0 + +config SHIELD_REYAX_LORA + def_bool $(shields_list_contains,reyax_lora) diff --git a/boards/shields/reyax_lora/boards/cy8ckit_062s4.conf b/boards/shields/reyax_lora/boards/cy8ckit_062s4.conf new file mode 100644 index 0000000000000..30752249749fa --- /dev/null +++ b/boards/shields/reyax_lora/boards/cy8ckit_062s4.conf @@ -0,0 +1,6 @@ +# Copyright (c) 2024 David Ullmann +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_LORA=y +CONFIG_LORA_RYLRXXX=y +CONFIG_UART_INTERRUPT_DRIVEN=y diff --git a/boards/shields/reyax_lora/boards/cy8ckit_062s4.overlay b/boards/shields/reyax_lora/boards/cy8ckit_062s4.overlay new file mode 100644 index 0000000000000..d45be1daa4107 --- /dev/null +++ b/boards/shields/reyax_lora/boards/cy8ckit_062s4.overlay @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2024 David Ullmann + * SPDX-License-Identifier: Apache-2.0 + */ + + +&p0_2_scb0_uart_rx { + input-enable; +}; + +&p0_3_scb0_uart_tx { + drive-push-pull; +}; + +&arduino_serial { + pinctrl-0 = <&p0_2_scb0_uart_rx &p0_3_scb0_uart_tx>; + pinctrl-names = "default"; +}; + +&gpio_prt0 { + status = "okay"; +}; + +&gpio_prt2 { + status = "okay"; +}; diff --git a/boards/shields/reyax_lora/doc/index.rst b/boards/shields/reyax_lora/doc/index.rst new file mode 100644 index 0000000000000..aa5cc1a781dfc --- /dev/null +++ b/boards/shields/reyax_lora/doc/index.rst @@ -0,0 +1,29 @@ +.. lora_reyax: + +Reyax LoRa RYLR896 and RYLR915 Modules +###################################### + +Overview +******** + +These modules expose a simple uart interface for the Semtech SX1276 chip,which implements the LoRa PHY. + +More information about the board can be found at the +`Reyax RYLR page`_. + +Hardware Description +******************** +The Module contains 4 pins + +- VDD: Power Supply +- NRST: Active low reset +- RXD: Serial data input +- TXD: Serial data output +- GND: Ground + +References +********** + +.. target-notes:: +.. _Reyax RYLR page: + https://reyax.com/products/RYLR896 diff --git a/boards/shields/reyax_lora/reyax_lora.overlay b/boards/shields/reyax_lora/reyax_lora.overlay new file mode 100644 index 0000000000000..080d78d92d0dd --- /dev/null +++ b/boards/shields/reyax_lora/reyax_lora.overlay @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2024 David Ullmann + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +/{ + aliases { + lora0 = &rylr_lora_modem; + }; +}; + + +&arduino_serial { + current-speed = <115200>; + status = "okay"; + rylr_lora_modem: rylr_lora_modem { + compatible = "reyax,rylrxxx"; + status = "okay"; + reset-gpios = <&arduino_header 16 GPIO_ACTIVE_LOW>; + }; +}; diff --git a/dts/bindings/lora/reyax,rylrxxx.yaml b/dts/bindings/lora/reyax,rylrxxx.yaml new file mode 100644 index 0000000000000..e04a78f7ac491 --- /dev/null +++ b/dts/bindings/lora/reyax,rylrxxx.yaml @@ -0,0 +1,13 @@ +# Copyright (c) 2024 David Ullmann +# SPDX-License-Identifier: Apache-2.0 + +description: Reyax lora module with AT-command serial interface + +compatible: "reyax,rylrxxx" + +include: uart-device.yaml + +properties: + reset-gpios: + type: phandle-array + required: true From 35740a83224c833deea492b3ae95c40c64e906ce Mon Sep 17 00:00:00 2001 From: David Ullmann Date: Mon, 11 Mar 2024 13:42:12 -0400 Subject: [PATCH 2832/2849] drivers: lora: implement reyax lora driver implementation of reyax lora module Signed-off-by: David Ullmann --- drivers/lora/CMakeLists.txt | 1 + drivers/lora/rylrxxx.c | 684 ++++++++++++++++++++++++++++++++++++ 2 files changed, 685 insertions(+) create mode 100644 drivers/lora/rylrxxx.c diff --git a/drivers/lora/CMakeLists.txt b/drivers/lora/CMakeLists.txt index 81cb1468ed09a..85a37f0d55948 100644 --- a/drivers/lora/CMakeLists.txt +++ b/drivers/lora/CMakeLists.txt @@ -20,3 +20,4 @@ endif() zephyr_library_sources_ifdef(CONFIG_LORA_SX126X sx126x_standalone.c) zephyr_library_sources_ifdef(CONFIG_LORA_STM32WL_SUBGHZ_RADIO sx126x_stm32wl.c) +zephyr_library_sources_ifdef(CONFIG_LORA_RYLRXXX rylrxxx.c) diff --git a/drivers/lora/rylrxxx.c b/drivers/lora/rylrxxx.c new file mode 100644 index 0000000000000..57e4e6ff0142c --- /dev/null +++ b/drivers/lora/rylrxxx.c @@ -0,0 +1,684 @@ +/* + * Copyright (C) 2024 David Ullmann + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#define DT_DRV_COMPAT reyax_rylrxxx + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +LOG_MODULE_REGISTER(rylr, CONFIG_LORA_LOG_LEVEL); + +#define RYLR_CMD_BAND_FORMAT "AT+BAND=%u\r\n" +#define RYLR_CMD_BAND_PARM_CHARS 9U +#define RYLR_CMD_BAND_FORMAT_NUM_WILDCARDS 1U +#define RYLR_CMD_BAND_FORMAT_WILDCARD_CHARS (RYLR_CMD_BAND_FORMAT_NUM_WILDCARDS * 2) +#define RYLR_CMD_BAND_FORMAT_LEN_WITHOUT_WILDCARDS \ + (sizeof(RYLR_CMD_BAND_FORMAT) - RYLR_CMD_BAND_FORMAT_WILDCARD_CHARS - 1) +#define RYLR_CMD_BAND_LENGTH (RYLR_CMD_BAND_FORMAT_LEN_WITHOUT_WILDCARDS + RYLR_CMD_BAND_PARM_CHARS) + +#define RYLR_CMD_SEND_FORMAT "AT+SEND=0,%u,%s\r\n" +#define RYLR_CMD_SEND_FORMAT_NUM_WILDCARDS 2U +#define RYLR_CMD_SEND_FORMAT_WILDCARD_CHARS (RYLR_CMD_SEND_FORMAT_NUM_WILDCARDS * 2) +#define RYLR_CMD_SEND_FORMAT_LEN_WITHOUT_WILDCARDS \ + (sizeof(RYLR_CMD_SEND_FORMAT) - RYLR_CMD_SEND_FORMAT_WILDCARD_CHARS - 1) +#define RYLR_PAYLOAD_LENGTH_FIELD_CHARS(payload_len) \ + (payload_len >= 100 ? 3 : (payload_len >= 10 ? 2 : 1)) +#define RYLR_CMD_SEND_LENGTH(payload_len) \ + (RYLR_CMD_SEND_FORMAT_LEN_WITHOUT_WILDCARDS + \ + RYLR_PAYLOAD_LENGTH_FIELD_CHARS(payload_len) + payload_len) + +#define RYLR_CMD_RF_SETTINGS_FORMAT "AT+PARAMETER=%u,%u,%u,%u\r\n" +#define RYLR_CMD_RF_SETTINGS_FORMAT_NUM_WILDCARDS 4U +#define RYLR_CMD_RF_SETTINGS_FORMAT_WILDCARD_CHARS (RYLR_CMD_RF_SETTINGS_FORMAT_NUM_WILDCARDS * 2U) +#define RYLR_CMD_RF_SETTINGS_FORMAT_LEN_WITHOUT_WILDCARDS \ + (sizeof(RYLR_CMD_RF_SETTINGS_FORMAT) - RYLR_CMD_RF_SETTINGS_FORMAT_WILDCARD_CHARS - 1) +#define RYLR_CMD_RF_SETTINGS_FORMAT_PARAM_CHARS(spread_factor) \ + (RYLR_CMD_RF_SETTINGS_FORMAT_NUM_WILDCARDS - 1) + (spread_factor >= 10U ? 2U : 1U) +#define RYLR_CMD_RF_SETTINGS_LEN(spread_factor) \ + (RYLR_CMD_RF_SETTINGS_FORMAT_LEN_WITHOUT_WILDCARDS + \ + RYLR_CMD_RF_SETTINGS_FORMAT_PARAM_CHARS(spread_factor)) + +#define RYLR_CMD_POWER_FORMAT "AT+CRFOP=%u\r\n" +#define RYLR_CMD_POWER_FORMAT_NUM_WILDCARDS 1U +#define RYLR_CMD_POWER_FORMAT_WILDCARD_CHARS (RYLR_CMD_POWER_FORMAT_NUM_WILDCARDS * 2U) +#define RYLR_CMD_POWER_FORMAT_LEN_WITHOUT_WILDCARDS \ + (sizeof(RYLR_CMD_POWER_FORMAT) - RYLR_CMD_POWER_FORMAT_WILDCARD_CHARS - 1) +#define RYLR_CMD_POWER_FORMAT_PARAM_CHARS(power) (power >= 10U ? 2U : 1U) +#define RYLR_CMD_POWER_LEN(power) \ + (RYLR_CMD_POWER_FORMAT_LEN_WITHOUT_WILDCARDS + RYLR_CMD_POWER_FORMAT_PARAM_CHARS(power)) + +#define RYLR_MAX_RESPONSE 256 +#define RYLR_MAX_MSG_BYTES 256 + +#define RYLR_ALLOC_TIMEOUT K_SECONDS(1) + +#define RYLR_TX_PENDING_FLAG_POS (0U) +#define RYLR_RX_PENDING_FLAG_POS (1U) + +#define RYLR_IS_TX_PENDING(flags) (flags & (0x01 << RYLR_TX_PENDING_FLAG_POS)) +#define RYLR_IS_RX_PENDING(flags) (flags & (0x01 << RYLR_RX_PENDING_FLAG_POS)) + +#define RYLR_SET_TX_PENDING(flags) (flags |= (0x01 << RYLR_TX_PENDING_FLAG_POS)) +#define RYLR_SET_RX_PENDING(flags) (flags |= (0x01 << RYLR_RX_PENDING_FLAG_POS)) + +#define RYLR_CLEAR_TX_PENDING(flags) (flags &= ~(0x01 << RYLR_TX_PENDING_FLAG_POS)) +#define RYLR_CLEAR_RX_PENDING(flags) (flags &= ~(0x01 << RYLR_RX_PENDING_FLAG_POS)) + +#define RYLR_IS_ASYNC_OP_PENDING(flags) (RYLR_IS_RX_PENDING(flags) || RYLR_IS_TX_PENDING(flags)) + +#define RYLR_MAX_RESPONSE_ARGS 6U + +#define RYLR_MIN_RESET_MSECS (100U) +#define RYLR_RESET_WAIT_MSECS (RYLR_MIN_RESET_MSECS + 10U) + +struct rylr_config { + const struct device *uart; + const struct gpio_dt_spec reset; +}; + +struct rylr_data { + uint8_t cmd_buffer[CONFIG_LORA_RYLRXX_CMD_BUF_SIZE]; + size_t curr_cmd_len; + bool is_tx; + int handler_error; + struct k_msgq rx_msgq; + struct k_sem script_sem; + struct k_sem operation_sem; + uint8_t pending_async_flags; + struct k_poll_signal *async_tx_signal; + lora_recv_cb async_rx_cb; + const struct device *dev; + uint8_t msgq_buffer[CONFIG_RYLRXXX_UNSOLICITED_RX_MSGQ_SIZE]; + struct modem_pipe *modem_pipe; + uint8_t uart_backend_rx_buff[CONFIG_RYLRXXX_MODEM_BUFFERS_SIZE]; + uint8_t uart_backend_tx_buff[CONFIG_RYLRXXX_MODEM_BUFFERS_SIZE]; + struct modem_pipe *uart_pipe; + struct modem_backend_uart uart_backend; + uint8_t chat_rx_buf[CONFIG_RYLRXXX_MODEM_BUFFERS_SIZE]; + uint8_t chat_tx_buf[CONFIG_RYLRXXX_MODEM_BUFFERS_SIZE]; + uint8_t *chat_argv[RYLR_MAX_RESPONSE_ARGS]; + struct modem_chat chat; + struct modem_chat_script dynamic_script; + struct modem_chat_script_chat dynamic_chat; +}; + +struct rylr_recv_msg { + uint16_t addr; + uint8_t length; + uint8_t *data; + uint8_t rssi; + uint8_t snr; +}; + +static void on_ok(struct modem_chat *chat, char **argv, uint16_t argc, void *user_data) +{ + int err = 0; + struct rylr_data *driver_data = user_data; + + driver_data->handler_error = err; +} + +static void on_err(struct modem_chat *chat, char **argv, uint16_t argc, void *user_data) +{ + int radio_err = 0; + struct rylr_data *driver_data = user_data; + + driver_data->handler_error = -EIO; + + if (argc != 2) { + driver_data->handler_error = -EBADMSG; + LOG_ERR("malformed error message from radio"); + return; + } + + radio_err = atoi(argv[1]); + LOG_ERR("error from rylr: %d", radio_err); +} + +static void on_rx(struct modem_chat *chat, char **argv, uint16_t argc, void *user_data) +{ + struct rylr_data *driver_data = user_data; + struct rylr_recv_msg msg; + int err = 0; + + driver_data->handler_error = 0; + + if (argc != 6) { + driver_data->handler_error = -EBADMSG; + return; + } + + msg.addr = atoi(argv[1]); + msg.length = atoi(argv[2]); + msg.data = argv[3]; + msg.rssi = atoi(argv[4]); + msg.snr = atoi(argv[5]); + + if (RYLR_IS_RX_PENDING(driver_data->pending_async_flags)) { + driver_data->async_rx_cb(driver_data->dev, msg.data, msg.length, msg.rssi, msg.snr); + } else { + err = k_msgq_put(&driver_data->rx_msgq, &msg, K_NO_WAIT); + if (err != 0) { + LOG_ERR("error adding messgae to queue: %d", err); + driver_data->handler_error = err; + } + } +} + +static void on_script_finished(struct modem_chat *chat, enum modem_chat_script_result result, + void *user_data) +{ + struct rylr_data *driver_data = user_data; + + if (RYLR_IS_TX_PENDING(driver_data->pending_async_flags)) { + RYLR_CLEAR_TX_PENDING(driver_data->pending_async_flags); + k_poll_signal_raise(driver_data->async_tx_signal, driver_data->handler_error); + k_sem_give(&driver_data->operation_sem); + } + + k_sem_give(&driver_data->script_sem); +} + +MODEM_CHAT_MATCH_DEFINE(ok_match, "+OK", "", on_ok); + +MODEM_CHAT_MATCHES_DEFINE(abort_matches, MODEM_CHAT_MATCH("+ERR=", "", on_err)); + +MODEM_CHAT_MATCHES_DEFINE(unsol_matches, MODEM_CHAT_MATCH("+RCV=", ",", on_rx)); + +MODEM_CHAT_SCRIPT_CMDS_DEFINE(ping_cmd, MODEM_CHAT_SCRIPT_CMD_RESP("AT\r\n", ok_match)); + +MODEM_CHAT_SCRIPT_DEFINE(ping_script, ping_cmd, abort_matches, on_script_finished, + CONFIG_RYLRXXX_RADIO_CMD_RESPONSE_TIMEOUT_MS); + +static void rylr_reset_dynamic_script(struct rylr_data *data) +{ + data->dynamic_chat.response_matches = &ok_match; + data->dynamic_chat.response_matches_size = 1; + data->dynamic_chat.timeout = 0; + + data->dynamic_script.script_chats = &data->dynamic_chat; + data->dynamic_script.script_chats_size = 1; + data->dynamic_script.abort_matches = abort_matches; + data->dynamic_script.abort_matches_size = 1; + data->dynamic_script.callback = on_script_finished; + data->dynamic_script.timeout = CONFIG_RYLRXXX_RADIO_CMD_RESPONSE_TIMEOUT_MS; +} + +static uint32_t rylr_get_bandwidth_index(enum lora_signal_bandwidth bw) +{ + switch (bw) { + case BW_125_KHZ: + return 7; + case BW_250_KHZ: + return 8; + case BW_500_KHZ: + return 9; + default: + return 7; + } +} + +static int rylr_send_cmd_buffer(const struct device *dev) +{ + int err = 0; + struct rylr_data *data = dev->data; + + rylr_reset_dynamic_script(data); + + data->dynamic_chat.request = data->cmd_buffer; + data->dynamic_chat.request_size = data->curr_cmd_len; + + err = modem_chat_run_script(&data->chat, &data->dynamic_script); + if (err != 0) { + LOG_ERR("could not send cmd: %s. err: %d", data->cmd_buffer, err); + return err; + } + err = k_sem_take(&data->script_sem, K_MSEC(CONFIG_RYLRXXX_RADIO_CMD_RESPONSE_TIMEOUT_MS)); + if (err) { + LOG_ERR("error waiting for response: %d", err); + return err; + } + return data->handler_error; +} + +static int rylr_set_rf_band(const struct device *dev, uint32_t frequency) +{ + struct rylr_data *data = dev->data; + + if (sprintf(data->cmd_buffer, RYLR_CMD_BAND_FORMAT, frequency) != RYLR_CMD_BAND_LENGTH) { + LOG_ERR("could not create frequency string"); + return -EINVAL; + } + + data->curr_cmd_len = RYLR_CMD_BAND_LENGTH; + return rylr_send_cmd_buffer(dev); +} + +static int rylr_set_rf_parameters(const struct device *dev, uint32_t datarate, uint32_t bandwidth, + uint32_t coding_rate, uint32_t preamble_length) +{ + struct rylr_data *data = dev->data; + size_t cmd_len; + + if (datarate < 7 || datarate > 12) { + LOG_ERR("datarate/spread factor must be between 7 and 12 inclusive"); + return -EINVAL; + } + + if (coding_rate < 1 || coding_rate > 4) { + LOG_ERR("coding rate must be between 1 and 4 inclusive"); + return -EINVAL; + } + + if (preamble_length < 4 || preamble_length > 7) { + LOG_ERR("preamble length must be between 4 and 7 inclusive"); + return -EINVAL; + } + + cmd_len = sprintf(data->cmd_buffer, RYLR_CMD_RF_SETTINGS_FORMAT, datarate, + rylr_get_bandwidth_index(bandwidth), coding_rate, preamble_length); + if (cmd_len != RYLR_CMD_RF_SETTINGS_LEN(datarate)) { + LOG_ERR("could not create rf settings string"); + return -EINVAL; + } + + data->curr_cmd_len = cmd_len; + return rylr_send_cmd_buffer(dev); +} + +static int rylr_set_power(const struct device *dev, uint32_t power) +{ + struct rylr_data *data = dev->data; + size_t cmd_len; + + if (power > 15) { + LOG_ERR("power cannot be greater than 15"); + return -EINVAL; + } + + cmd_len = RYLR_CMD_POWER_LEN(power); + if (sprintf(data->cmd_buffer, RYLR_CMD_POWER_FORMAT, power) != cmd_len) { + LOG_ERR("could not create power string"); + return -EINVAL; + } + + data->curr_cmd_len = cmd_len; + return rylr_send_cmd_buffer(dev); +} + +static int rylr_config(const struct device *dev, struct lora_modem_config *config) +{ + int err = 0; + struct rylr_data *data = dev->data; + + err = k_sem_take(&data->operation_sem, K_NO_WAIT); + if (err != 0) { + LOG_ERR("error taking operation semaphore: %d", err); + return err; + } + + if (RYLR_IS_ASYNC_OP_PENDING(data->pending_async_flags)) { + LOG_ERR("pending async opperation"); + err = -EBUSY; + goto exit; + } + + err = rylr_set_rf_band(dev, config->frequency); + if (err != 0) { + LOG_ERR("could not send frequency cmd: %d", err); + goto exit; + } + + err = rylr_set_rf_parameters(dev, config->datarate, config->bandwidth, config->coding_rate, + config->preamble_len); + if (err != 0) { + LOG_ERR("could not send rf params cmd: %d", err); + goto exit; + } + + err = rylr_set_power(dev, config->tx_power); + if (err != 0) { + LOG_ERR("could not send power cmd: %d", err); + goto exit; + } + + data->is_tx = config->tx; + +exit: + k_sem_give(&data->operation_sem); + return err; +} + +int rylr_send(const struct device *dev, uint8_t *payload, uint32_t payload_len) +{ + int err = 0; + struct rylr_data *data = dev->data; + int cmd_len = RYLR_CMD_SEND_LENGTH(payload_len); + + err = k_sem_take(&data->operation_sem, K_NO_WAIT); + if (err != 0) { + LOG_ERR("error taking operation semaphore: %d", err); + return err; + } + + if (RYLR_IS_ASYNC_OP_PENDING(data->pending_async_flags)) { + LOG_ERR("pending async opperation"); + err = -EBUSY; + goto exit; + } + + if (!data->is_tx) { + LOG_ERR("radio not configured in tx mode"); + err = -EOPNOTSUPP; + goto exit; + } + + if (cmd_len > CONFIG_LORA_RYLRXX_CMD_BUF_SIZE) { + LOG_ERR("payload too long"); + err = -EINVAL; + goto exit; + } + + snprintf(data->cmd_buffer, cmd_len + 1, RYLR_CMD_SEND_FORMAT, payload_len, payload); + data->curr_cmd_len = cmd_len; + err = rylr_send_cmd_buffer(dev); + if (err != 0) { + LOG_ERR("error sending data: %d", err); + goto exit; + } + +exit: + k_sem_give(&data->operation_sem); + return err; +} + +int rylr_send_async(const struct device *dev, uint8_t *payload, uint32_t payload_len, + struct k_poll_signal *async) +{ + int err = 0; + struct rylr_data *data = dev->data; + int cmd_len; + + err = k_sem_take(&data->operation_sem, K_NO_WAIT); + if (err != 0) { + LOG_ERR("error taking operation sem: %d", err); + return err; + } + + if (RYLR_IS_ASYNC_OP_PENDING(data->pending_async_flags)) { + LOG_ERR("pending async opperation"); + err = -EBUSY; + goto bail; + } + + RYLR_SET_TX_PENDING(data->pending_async_flags); + + if (!data->is_tx) { + LOG_ERR("radio not configured in tx mode"); + err = -EOPNOTSUPP; + goto bail; + } + + cmd_len = RYLR_CMD_SEND_LENGTH(payload_len); + if (cmd_len > CONFIG_LORA_RYLRXX_CMD_BUF_SIZE) { + LOG_ERR("payload too long"); + err = -EINVAL; + goto bail; + } + + if (async == NULL) { + LOG_ERR("async signal cannot be null"); + err = -EINVAL; + goto bail; + } + + data->async_tx_signal = async; + data->curr_cmd_len = + snprintf(data->cmd_buffer, cmd_len + 1, RYLR_CMD_SEND_FORMAT, payload_len, payload); + rylr_reset_dynamic_script(data); + data->dynamic_chat.request = data->cmd_buffer; + data->dynamic_chat.request_size = data->curr_cmd_len; + + return modem_chat_run_script_async(&data->chat, &data->dynamic_script); +bail: + RYLR_CLEAR_TX_PENDING(data->pending_async_flags); + k_sem_give(&data->operation_sem); + return err; +} + +int rylr_recv(const struct device *dev, uint8_t *ret_msg, uint8_t size, k_timeout_t timeout, + int16_t *rssi, int8_t *snr) +{ + + int ret = 0; + struct rylr_data *data = dev->data; + struct rylr_recv_msg msg; + + ret = k_sem_take(&data->operation_sem, K_NO_WAIT); + if (ret != 0) { + LOG_ERR("error taking operation semaphore: %d", ret); + return ret; + } + + if (data->is_tx) { + LOG_ERR("radio is configured for tx"); + ret = -EOPNOTSUPP; + goto exit; + } + + if (RYLR_IS_ASYNC_OP_PENDING(data->pending_async_flags)) { + LOG_ERR("pending async opperation"); + ret = -EBUSY; + goto exit; + } + + ret = k_msgq_get(&data->rx_msgq, &msg, timeout); + if (ret != 0) { + LOG_ERR("error getting msg from queue: %d", ret); + goto exit; + } + + ret = data->handler_error; + if (ret != 0) { + LOG_ERR("error in recv cb: %d", ret); + goto exit; + } + + if (msg.length > size) { + LOG_ERR("buf len of %u too small for message len of %u", size, msg.length); + ret = -ENOBUFS; + goto exit; + } + + *rssi = msg.rssi; + *snr = msg.snr; + memcpy(ret_msg, msg.data, msg.length); + ret = msg.length; + +exit: + k_sem_give(&data->operation_sem); + return ret; +} + +int rylr_recv_async(const struct device *dev, lora_recv_cb cb) +{ + int err = 0; + struct rylr_data *data = dev->data; + + err = k_sem_take(&data->operation_sem, K_NO_WAIT); + if (err != 0) { + LOG_ERR("error taking operation semaphore: %d", err); + return err; + } + + /* This is not a user error but the documeted way to cancel async reception in lora api*/ + if (cb == NULL) { + goto bail; + } + + if (data->is_tx) { + LOG_ERR("radio is configured for tx"); + err = -EOPNOTSUPP; + goto bail; + } + + data->async_rx_cb = cb; + if (RYLR_IS_ASYNC_OP_PENDING(data->pending_async_flags)) { + LOG_ERR("pending async opperation"); + err = -EBUSY; + goto bail; + } + RYLR_SET_RX_PENDING(data->pending_async_flags); + + return err; +bail: + RYLR_CLEAR_RX_PENDING(data->pending_async_flags); + k_sem_give(&data->operation_sem); + return err; +} + +int rylr_test_cw(const struct device *dev, uint32_t frequency, int8_t tx_power, uint16_t duration) +{ + return -ENOSYS; +} + +static int rylr_init(const struct device *dev) +{ + int err = 0; + struct rylr_data *data = dev->data; + const struct rylr_config *config = dev->config; + + if (!gpio_is_ready_dt(&config->reset)) { + return -ENODEV; + } + + if (!device_is_ready(config->uart)) { + return -ENODEV; + } + + err = gpio_pin_configure_dt(&config->reset, config->reset.dt_flags); + if (err != 0) { + LOG_ERR("error configuring reset gpio: %d", err); + return err; + } + + k_msgq_init(&data->rx_msgq, data->msgq_buffer, sizeof(struct rylr_recv_msg), + ARRAY_SIZE(data->msgq_buffer)); + + err = k_sem_init(&data->script_sem, 0, 1); + if (err != 0) { + LOG_ERR("error initializing response semaphore. err=%d", err); + } + + err = k_sem_init(&data->operation_sem, 1, 1); + if (err != 0) { + LOG_ERR("error initializing operation semaphore. err=%d", err); + } + + const struct modem_backend_uart_config uart_backend_config = { + .uart = config->uart, + .receive_buf = data->uart_backend_rx_buff, + .receive_buf_size = ARRAY_SIZE(data->uart_backend_rx_buff), + .transmit_buf = data->uart_backend_tx_buff, + .transmit_buf_size = ARRAY_SIZE(data->uart_backend_tx_buff), + }; + + data->uart_pipe = modem_backend_uart_init(&data->uart_backend, &uart_backend_config); + + const struct modem_chat_config chat_config = { + .user_data = data, + .receive_buf = data->chat_rx_buf, + .receive_buf_size = ARRAY_SIZE(data->chat_rx_buf), + .delimiter = "\r\n", + .delimiter_size = sizeof("\r\n") - 1, + .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), + }; + + err = modem_chat_init(&data->chat, &chat_config); + if (err != 0) { + LOG_ERR("error initializing chat %d", err); + return err; + } + + err = modem_chat_attach(&data->chat, data->uart_pipe); + if (err != 0) { + LOG_ERR("error attaching chat %d", err); + return err; + } + + err = modem_pipe_open(data->uart_pipe); + if (err != 0) { + LOG_ERR("error opening uart pipe %d", err); + return err; + } + + err = gpio_pin_set_dt(&config->reset, 1); + if (err != 0) { + LOG_ERR("error setting reset line: %d", err); + return err; + } + + k_sleep(K_MSEC(RYLR_RESET_WAIT_MSECS)); + + err = gpio_pin_set_dt(&config->reset, 0); + if (err != 0) { + LOG_ERR("error unsetting reset line: %d", err); + return err; + } + + k_sleep(K_MSEC(RYLR_RESET_WAIT_MSECS)); /* wait a bit more for module to boot up*/ + + err = modem_chat_run_script(&data->chat, &ping_script); + if (err != 0) { + LOG_ERR("error pinging radio: %d", err); + return err; + } + + err = k_sem_take(&data->script_sem, K_MSEC(CONFIG_RYLRXXX_RADIO_CMD_RESPONSE_TIMEOUT_MS)); + if (err != 0) { + LOG_ERR("error waiting for ping response from radio %d", err); + return err; + } + + LOG_INF("successfully initialized rylr"); + return err; +} + +static const struct lora_driver_api rylr_lora_api = { + .config = rylr_config, + .send = rylr_send, + .send_async = rylr_send_async, + .recv = rylr_recv, + .recv_async = rylr_recv_async, + .test_cw = rylr_test_cw, +}; + +#define RYLR_DEVICE_INIT(n) \ + static struct rylr_data dev_data_##n; \ + static const struct rylr_config dev_config_##n = { \ + .uart = DEVICE_DT_GET(DT_INST_BUS(n)), \ + .reset = GPIO_DT_SPEC_INST_GET(n, reset_gpios), \ + }; \ + DEVICE_DT_INST_DEFINE(n, &rylr_init, NULL, &dev_data_##n, &dev_config_##n, POST_KERNEL, \ + CONFIG_LORA_INIT_PRIORITY, &rylr_lora_api); + +DT_INST_FOREACH_STATUS_OKAY(RYLR_DEVICE_INIT) From ba75fe482a24e31e7e1f1def391f173b0e2e245c Mon Sep 17 00:00:00 2001 From: David Ullmann Date: Fri, 29 Mar 2024 12:00:30 -0400 Subject: [PATCH 2833/2849] tests: add build test for reyax lora driver adding test to build the reyax lora driver Signed-off-by: David Ullmann --- tests/drivers/build_all/lora/CMakeLists.txt | 8 ++++++++ tests/drivers/build_all/lora/prj.conf | 1 + tests/drivers/build_all/lora/src/main.c | 10 ++++++++++ tests/drivers/build_all/lora/testcase.yaml | 4 ++++ 4 files changed, 23 insertions(+) create mode 100644 tests/drivers/build_all/lora/CMakeLists.txt create mode 100644 tests/drivers/build_all/lora/prj.conf create mode 100644 tests/drivers/build_all/lora/src/main.c create mode 100644 tests/drivers/build_all/lora/testcase.yaml diff --git a/tests/drivers/build_all/lora/CMakeLists.txt b/tests/drivers/build_all/lora/CMakeLists.txt new file mode 100644 index 0000000000000..518596a02f780 --- /dev/null +++ b/tests/drivers/build_all/lora/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(build_all) + +FILE(GLOB app_sources src/*.c) +target_sources(app PRIVATE ${app_sources}) diff --git a/tests/drivers/build_all/lora/prj.conf b/tests/drivers/build_all/lora/prj.conf new file mode 100644 index 0000000000000..e1faee53e19d2 --- /dev/null +++ b/tests/drivers/build_all/lora/prj.conf @@ -0,0 +1 @@ +CONFIG_TEST=y diff --git a/tests/drivers/build_all/lora/src/main.c b/tests/drivers/build_all/lora/src/main.c new file mode 100644 index 0000000000000..a4c870ab2c836 --- /dev/null +++ b/tests/drivers/build_all/lora/src/main.c @@ -0,0 +1,10 @@ +/* + * Copyright (c) 2024 David Ullmann + * + * SPDX-License-Identifier: Apache-2.0 + */ + +int main(void) +{ + return 0; +} diff --git a/tests/drivers/build_all/lora/testcase.yaml b/tests/drivers/build_all/lora/testcase.yaml new file mode 100644 index 0000000000000..c6c4656e69c6d --- /dev/null +++ b/tests/drivers/build_all/lora/testcase.yaml @@ -0,0 +1,4 @@ +tests: + sample.driver.lora.rylr.send: + extra_args: SHIELD=reyax_lora + platform_allow: cy8ckit_062s4 From eb2fc22967d21c8f04b15fb3339f181dcd79bd31 Mon Sep 17 00:00:00 2001 From: David Ullmann Date: Wed, 1 May 2024 17:41:14 -0400 Subject: [PATCH 2834/2849] doc: add release note about Reyax LoRa module updated release notes for 3.7 Signed-off-by: David Ullmann --- 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 0bd55cee3d8d6..84c783055d543 100644 --- a/doc/releases/release-notes-3.7.rst +++ b/doc/releases/release-notes-3.7.rst @@ -345,6 +345,11 @@ Drivers and Sensors * The ``chain-length`` and ``color-mapping`` properties have been added to all LED strip bindings. + +* LoRa + + * Added driver for Reyax LoRa module + * MDIO * MFD From db6d04fefdad8eae1e2cb09c7daa9f5fd3f5d181 Mon Sep 17 00:00:00 2001 From: Raffael Rostagno Date: Tue, 7 May 2024 11:37:09 -0300 Subject: [PATCH 2835/2849] west.yml: update for esp32c6 support hal_espressif update for C6 support Signed-off-by: Raffael Rostagno --- west.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/west.yml b/west.yml index a5e7a78ff0bdf..22d1ad7d1c7c3 100644 --- a/west.yml +++ b/west.yml @@ -157,7 +157,7 @@ manifest: groups: - hal - name: hal_espressif - revision: 4e38d8d9fe16d4d41736c1ffae6566001a624fca + revision: 99dce9490ef4a84ddffe75c9d8853b30008c64bc path: modules/hal/espressif west-commands: west/west-commands.yml groups: From c6bd9c516adbbe27821ea4e6486696c54e8cc982 Mon Sep 17 00:00:00 2001 From: Lucas Tamborrino Date: Mon, 5 Jun 2023 20:15:39 -0300 Subject: [PATCH 2836/2849] dt-bindings: add esp32c6 signals Add clock, interrupt controller and pinctrl related macros for esp32c6 Signed-off-by: Lucas Tamborrino --- .../zephyr/dt-bindings/clock/esp32c6_clock.h | 80 ++ .../interrupt-controller/esp-esp32c6-intmux.h | 89 ++ .../dt-bindings/pinctrl/esp32c6-gpio-sigmap.h | 261 +++++ .../dt-bindings/pinctrl/esp32c6-pinctrl.h | 889 ++++++++++++++++++ 4 files changed, 1319 insertions(+) create mode 100644 include/zephyr/dt-bindings/clock/esp32c6_clock.h create mode 100644 include/zephyr/dt-bindings/interrupt-controller/esp-esp32c6-intmux.h create mode 100644 include/zephyr/dt-bindings/pinctrl/esp32c6-gpio-sigmap.h create mode 100644 include/zephyr/dt-bindings/pinctrl/esp32c6-pinctrl.h diff --git a/include/zephyr/dt-bindings/clock/esp32c6_clock.h b/include/zephyr/dt-bindings/clock/esp32c6_clock.h new file mode 100644 index 0000000000000..c1ccc604986f3 --- /dev/null +++ b/include/zephyr/dt-bindings/clock/esp32c6_clock.h @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_ESP32C6_H_ +#define ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_ESP32C6_H_ + +/* System Clock Source */ +#define ESP32_CLK_SRC_XTAL 0U +#define ESP32_CLK_SRC_PLL 1U +#define ESP32_CLK_SRC_RC_FAST 2U + +/* Supported CPU Frequencies */ +#define ESP32_CLK_CPU_80M 80000000 +#define ESP32_CLK_CPU_160M 160000000 + +/* Supported XTAL Frequencies */ +#define ESP32_CLK_XTAL_32M 32 +#define ESP32_CLK_XTAL_40M 40 + +/* Supported RTC fast clock frequencies */ +#define ESP32_RTC_FAST_CLK_FREQ_8M 8500000U +#define ESP32_RTC_FAST_CLK_FREQ_APPROX ESP32_RTC_FAST_CLK_FREQ_8M + +/* Supported RTC slow clock frequencies */ +#define ESP32_RTC_SLOW_CLK_FREQ_90K 90000U +#define ESP32_RTC_SLOW_CLK_FREQ_8MD256 (ESP32_RTC_FAST_CLK_FREQ_APPROX / 256) +#define ESP32_RTC_SLOW_CLK_FREQ_32K 32768U + +/* Modules IDs + * These IDs are actually offsets in CLK and RST Control registers. + * These IDs shouldn't be changed unless there is a Hardware change + * from Espressif. + * + * Basic Modules + * Registers: DPORT_PERIP_CLK_EN_REG, DPORT_PERIP_RST_EN_REG + */ +#define ESP32_LEDC_MODULE 0 +#define ESP32_UART0_MODULE 1 +#define ESP32_UART1_MODULE 2 +#define ESP32_USB_MODULE 3 +#define ESP32_I2C0_MODULE 4 +#define ESP32_I2S1_MODULE 5 +#define ESP32_TIMG0_MODULE 6 +#define ESP32_TIMG1_MODULE 7 +#define ESP32_UHCI0_MODULE 8 +#define ESP32_RMT_MODULE 9 +#define ESP32_PCNT_MODULE 10 +#define ESP32_SPI_MODULE 11 +#define ESP32_SPI2_MODULE 12 +#define ESP32_TWAI0_MODULE 13 +#define ESP32_TWAI1_MODULE 14 +#define ESP32_RNG_MODULE 15 +#define ESP32_RSA_MODULE 16 +#define ESP32_AES_MODULE 17 +#define ESP32_SHA_MODULE 18 +#define ESP32_ECC_MODULE 19 +#define ESP32_HMAC_MODULE 20 +#define ESP32_DS_MODULE 21 +#define ESP32_SDIO_SLAVE_MODULE 22 +#define ESP32_GDMA_MODULE 23 +#define ESP32_MCPWM0_MODULE 24 +#define ESP32_ETM_MODULE 25 +#define ESP32_PARLIO_MODULE 26 +#define ESP32_SYSTIMER_MODULE 27 +#define ESP32_SARADC_MODULE 28 +#define ESP32_TEMPSENSOR_MODULE 29 +#define ESP32_REGDMA_MODULE 30 +#define ESP32_LP_I2C0_MODULE 31 +/* Peripherals clock managed by the modem_clock driver must be listed last */ +#define ESP32_WIFI_MODULE 32 +#define ESP32_BT_MODULE 33 +#define ESP32_IEEE802154_MODULE 34 +#define ESP32_COEX_MODULE 35 +#define ESP32_PHY_MODULE 36 +#define ESP32_MODULE_MAX 37 + +#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_ESP32C6_H_ */ diff --git a/include/zephyr/dt-bindings/interrupt-controller/esp-esp32c6-intmux.h b/include/zephyr/dt-bindings/interrupt-controller/esp-esp32c6-intmux.h new file mode 100644 index 0000000000000..644d8cfb54f20 --- /dev/null +++ b/include/zephyr/dt-bindings/interrupt-controller/esp-esp32c6-intmux.h @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_INTERRUPT_CONTROLLER_ESP32C6_INTMUX_H_ +#define ZEPHYR_INCLUDE_DT_BINDINGS_INTERRUPT_CONTROLLER_ESP32C6_INTMUX_H_ + +#define WIFI_MAC_INTR_SOURCE 0 /* interrupt of WiFi MAC, level*/ +#define WIFI_MAC_NMI_SOURCE 1 /* interrupt of WiFi MAC, NMI*/ +#define WIFI_PWR_INTR_SOURCE 2 +#define WIFI_BB_INTR_SOURCE 3 /* interrupt of WiFi BB, level*/ +#define BT_MAC_INTR_SOURCE 4 /* will be cancelled*/ +#define BT_BB_INTR_SOURCE 5 /* interrupt of BT BB, level*/ +#define BT_BB_NMI_SOURCE 6 /* interrupt of BT BB, NMI*/ +#define LP_TIMER_INTR_SOURCE 7 +#define COEX_INTR_SOURCE 8 +#define BLE_TIMER_INTR_SOURCE 9 +#define BLE_SEC_INTR_SOURCE 10 +#define I2C_MASTER_SOURCE 11 /* interrupt of I2C Master, level*/ +#define ZB_MAC_SOURCE 12 +#define PMU_INTR_SOURCE 13 +#define EFUSE_INTR_SOURCE 14 /* interrupt of efuse, level, not likely to use*/ +#define LP_RTC_TIMER_INTR_SOURCE 15 +#define LP_UART_INTR_SOURCE 16 +#define LP_I2C_INTR_SOURCE 17 +#define LP_WDT_INTR_SOURCE 18 +#define LP_PERI_TIMEOUT_INTR_SOURCE 19 +#define LP_APM_M0_INTR_SOURCE 20 +#define LP_APM_M1_INTR_SOURCE 21 +#define FROM_CPU_INTR0_SOURCE 22 /* interrupt0 generated from a CPU, level*/ +#define FROM_CPU_INTR1_SOURCE 23 /* interrupt1 generated from a CPU, level*/ +#define FROM_CPU_INTR2_SOURCE 24 /* interrupt2 generated from a CPU, level*/ +#define FROM_CPU_INTR3_SOURCE 25 /* interrupt3 generated from a CPU, level*/ +#define ASSIST_DEBUG_INTR_SOURCE 26 /* interrupt of Assist debug module, LEVEL*/ +#define TRACE_INTR_SOURCE 27 +#define CACHE_INTR_SOURCE 28 +#define CPU_PERI_TIMEOUT_INTR_SOURCE 29 +#define GPIO_INTR_SOURCE 30 /* interrupt of GPIO, level*/ +#define GPIO_NMI_SOURCE 31 /* interrupt of GPIO, NMI*/ +#define PAU_INTR_SOURCE 32 +#define HP_PERI_TIMEOUT_INTR_SOURCE 33 +#define MODEM_PERI_TIMEOUT_INTR_SOURCE 34 +#define HP_APM_M0_INTR_SOURCE 35 +#define HP_APM_M1_INTR_SOURCE 36 +#define HP_APM_M2_INTR_SOURCE 37 +#define HP_APM_M3_INTR_SOURCE 38 +#define LP_APM0_INTR_SOURCE 39 +#define MSPI_INTR_SOURCE 40 +#define I2S1_INTR_SOURCE 41 /* interrupt of I2S1, level*/ +#define UHCI0_INTR_SOURCE 42 /* interrupt of UHCI0, level*/ +#define UART0_INTR_SOURCE 43 /* interrupt of UART0, level*/ +#define UART1_INTR_SOURCE 44 /* interrupt of UART1, level*/ +#define LEDC_INTR_SOURCE 45 /* interrupt of LED PWM, level*/ +#define TWAI0_INTR_SOURCE 46 /* interrupt of can0, level*/ +#define TWAI1_INTR_SOURCE 47 /* interrupt of can1, level*/ +#define USB_SERIAL_JTAG_INTR_SOURCE 48 /* interrupt of USB, level*/ +#define RMT_INTR_SOURCE 49 /* interrupt of remote controller, level*/ +#define I2C_EXT0_INTR_SOURCE 50 /* interrupt of I2C controller1, level*/ +#define TG0_T0_LEVEL_INTR_SOURCE 51 /* interrupt of TIMER_GROUP0, TIMER0, level*/ +#define TG0_T1_LEVEL_INTR_SOURCE 52 /* interrupt of TIMER_GROUP0, TIMER1, level*/ +#define TG0_WDT_LEVEL_INTR_SOURCE 53 /* interrupt of TIMER_GROUP0, WATCH DOG, level*/ +#define TG1_T0_LEVEL_INTR_SOURCE 54 /* interrupt of TIMER_GROUP1, TIMER0, level*/ +#define TG1_T1_LEVEL_INTR_SOURCE 55 /* interrupt of TIMER_GROUP1, TIMER1, level*/ +#define TG1_WDT_LEVEL_INTR_SOURCE 56 /* interrupt of TIMER_GROUP1, WATCHDOG, level*/ +#define SYSTIMER_TARGET0_EDGE_INTR_SOURCE 57 /* interrupt of system timer 0, EDGE*/ +#define SYSTIMER_TARGET1_EDGE_INTR_SOURCE 58 /* interrupt of system timer 1, EDGE*/ +#define SYSTIMER_TARGET2_EDGE_INTR_SOURCE 59 /* interrupt of system timer 2, EDGE*/ +#define APB_ADC_INTR_SOURCE 60 /* interrupt of APB ADC, LEVEL*/ +#define MCPWM0_INTR_SOURCE 61 /* interrupt of MCPWM0, LEVEL*/ +#define PCNT_INTR_SOURCE 62 +#define PARL_IO_INTR_SOURCE 63 +#define SLC0_INTR_SOURCE 64 +#define SLC_INTR_SOURCE 65 +#define DMA_IN_CH0_INTR_SOURCE 66 /* interrupt of general DMA IN channel 0, LEVEL*/ +#define DMA_IN_CH1_INTR_SOURCE 67 /* interrupt of general DMA IN channel 1, LEVEL*/ +#define DMA_IN_CH2_INTR_SOURCE 68 /* interrupt of general DMA IN channel 2, LEVEL*/ +#define DMA_OUT_CH0_INTR_SOURCE 69 /* interrupt of general DMA OUT channel 0, LEVEL*/ +#define DMA_OUT_CH1_INTR_SOURCE 70 /* interrupt of general DMA OUT channel 1, LEVEL*/ +#define DMA_OUT_CH2_INTR_SOURCE 71 /* interrupt of general DMA OUT channel 2, LEVEL*/ +#define GSPI2_INTR_SOURCE 72 +#define AES_INTR_SOURCE 73 /* interrupt of AES accelerator, level*/ +#define SHA_INTR_SOURCE 74 /* interrupt of SHA accelerator, level*/ +#define RSA_INTR_SOURCE 75 /* interrupt of RSA accelerator, level*/ +#define ECC_INTR_SOURCE 76 /* interrupt of ECC accelerator, level*/ +#define MAX_INTR_SOURCE 77 + +#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_INTERRUPT_CONTROLLER_ESP32C6_INTMUX_H_ */ diff --git a/include/zephyr/dt-bindings/pinctrl/esp32c6-gpio-sigmap.h b/include/zephyr/dt-bindings/pinctrl/esp32c6-gpio-sigmap.h new file mode 100644 index 0000000000000..bba370d247d73 --- /dev/null +++ b/include/zephyr/dt-bindings/pinctrl/esp32c6-gpio-sigmap.h @@ -0,0 +1,261 @@ +/* + * Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_PINCTRL_ESP32C6_GPIO_SIGMAP_H_ +#define ZEPHYR_INCLUDE_DT_BINDINGS_PINCTRL_ESP32C6_GPIO_SIGMAP_H_ + +#define ESP_NOSIG ESP_SIG_INVAL + +#define ESP_EXT_ADC_START 0 +#define ESP_LEDC_LS_SIG_OUT0 0 +#define ESP_LEDC_LS_SIG_OUT1 1 +#define ESP_LEDC_LS_SIG_OUT2 2 +#define ESP_LEDC_LS_SIG_OUT3 3 +#define ESP_LEDC_LS_SIG_OUT4 4 +#define ESP_LEDC_LS_SIG_OUT5 5 +#define ESP_U0RXD_IN 6 +#define ESP_U0TXD_OUT 6 +#define ESP_U0CTS_IN 7 +#define ESP_U0RTS_OUT 7 +#define ESP_U0DSR_IN 8 +#define ESP_U0DTR_OUT 8 +#define ESP_U1RXD_IN 9 +#define ESP_U1TXD_OUT 9 +#define ESP_U1CTS_IN 10 +#define ESP_U1RTS_OUT 10 +#define ESP_U1DSR_IN 11 +#define ESP_U1DTR_OUT 11 +#define ESP_I2S_MCLK_IN 12 +#define ESP_I2S_MCLK_OUT 12 +#define ESP_I2SO_BCK_IN 13 +#define ESP_I2SO_BCK_OUT 13 +#define ESP_I2SO_WS_IN 14 +#define ESP_I2SO_WS_OUT 14 +#define ESP_I2SI_SD_IN 15 +#define ESP_I2SO_SD_OUT 15 +#define ESP_I2SI_BCK_IN 16 +#define ESP_I2SI_BCK_OUT 16 +#define ESP_I2SI_WS_IN 17 +#define ESP_I2SI_WS_OUT 17 +#define ESP_I2SO_SD1_OUT 18 +#define ESP_USB_JTAG_TDO_BRIDGE 19 +#define ESP_USB_JTAG_TRST 19 +#define ESP_CPU_TESTBUS0 20 +#define ESP_CPU_TESTBUS1 21 +#define ESP_CPU_TESTBUS2 22 +#define ESP_CPU_TESTBUS3 23 +#define ESP_CPU_TESTBUS4 24 +#define ESP_CPU_TESTBUS5 25 +#define ESP_CPU_TESTBUS6 26 +#define ESP_CPU_TESTBUS7 27 +#define ESP_CPU_GPIO_IN0 28 +#define ESP_CPU_GPIO_OUT0 28 +#define ESP_CPU_GPIO_IN1 29 +#define ESP_CPU_GPIO_OUT1 29 +#define ESP_CPU_GPIO_IN2 30 +#define ESP_CPU_GPIO_OUT2 30 +#define ESP_CPU_GPIO_IN3 31 +#define ESP_CPU_GPIO_OUT3 31 +#define ESP_CPU_GPIO_IN4 32 +#define ESP_CPU_GPIO_OUT4 32 +#define ESP_CPU_GPIO_IN5 33 +#define ESP_CPU_GPIO_OUT5 33 +#define ESP_CPU_GPIO_IN6 34 +#define ESP_CPU_GPIO_OUT6 34 +#define ESP_CPU_GPIO_IN7 35 +#define ESP_CPU_GPIO_OUT7 35 +#define ESP_USB_JTAG_TCK 36 +#define ESP_USB_JTAG_TMS 37 +#define ESP_USB_JTAG_TDI 38 +#define ESP_USB_JTAG_TDO 39 +#define ESP_USB_EXTPHY_VP 40 +#define ESP_USB_EXTPHY_OEN 40 +#define ESP_USB_EXTPHY_VM 41 +#define ESP_USB_EXTPHY_SPEED 41 +#define ESP_USB_EXTPHY_RCV 42 +#define ESP_USB_EXTPHY_VPO 42 +#define ESP_USB_EXTPHY_VMO 43 +#define ESP_USB_EXTPHY_SUSPND 44 +#define ESP_I2CEXT0_SCL_IN 45 +#define ESP_I2CEXT0_SCL_OUT 45 +#define ESP_I2CEXT0_SDA_IN 46 +#define ESP_I2CEXT0_SDA_OUT 46 +#define ESP_PARL_RX_DATA0 47 +#define ESP_PARL_TX_DATA0 47 +#define ESP_PARL_RX_DATA1 48 +#define ESP_PARL_TX_DATA1 48 +#define ESP_PARL_RX_DATA2 49 +#define ESP_PARL_TX_DATA2 49 +#define ESP_PARL_RX_DATA3 50 +#define ESP_PARL_TX_DATA3 50 +#define ESP_PARL_RX_DATA4 51 +#define ESP_PARL_TX_DATA4 51 +#define ESP_PARL_RX_DATA5 52 +#define ESP_PARL_TX_DATA5 52 +#define ESP_PARL_RX_DATA6 53 +#define ESP_PARL_TX_DATA6 53 +#define ESP_PARL_RX_DATA7 54 +#define ESP_PARL_TX_DATA7 54 +#define ESP_PARL_RX_DATA8 55 +#define ESP_PARL_TX_DATA8 55 +#define ESP_PARL_RX_DATA9 56 +#define ESP_PARL_TX_DATA9 56 +#define ESP_PARL_RX_DATA10 57 +#define ESP_PARL_TX_DATA10 57 +#define ESP_PARL_RX_DATA11 58 +#define ESP_PARL_TX_DATA11 58 +#define ESP_PARL_RX_DATA12 59 +#define ESP_PARL_TX_DATA12 59 +#define ESP_PARL_RX_DATA13 60 +#define ESP_PARL_TX_DATA13 60 +#define ESP_PARL_RX_DATA14 61 +#define ESP_PARL_TX_DATA14 61 +#define ESP_PARL_RX_DATA15 62 +#define ESP_PARL_TX_DATA15 62 +#define ESP_FSPICLK_IN 63 +#define ESP_FSPICLK_OUT 63 +#define ESP_FSPIQ_IN 64 +#define ESP_FSPIQ_OUT 64 +#define ESP_FSPID_IN 65 +#define ESP_FSPID_OUT 65 +#define ESP_FSPIHD_IN 66 +#define ESP_FSPIHD_OUT 66 +#define ESP_FSPIWP_IN 67 +#define ESP_FSPIWP_OUT 67 +#define ESP_FSPICS0_IN 68 +#define ESP_FSPICS0_OUT 68 +#define ESP_PARL_RX_CLK_IN 69 +#define ESP_SDIO_TOHOST_INT_OUT 69 +#define ESP_PARL_TX_CLK_IN 70 +#define ESP_PARL_TX_CLK_OUT 70 +#define ESP_RMT_SIG_IN0 71 +#define ESP_RMT_SIG_OUT0 71 +#define ESP_MODEM_DIAG0 71 +#define ESP_RMT_SIG_IN1 72 +#define ESP_RMT_SIG_OUT1 72 +#define ESP_MODEM_DIAG1 72 +#define ESP_TWAI0_RX 73 +#define ESP_TWAI0_TX 73 +#define ESP_MODEM_DIAG2 73 +#define ESP_TWAI0_BUS_OFF_ON 74 +#define ESP_MODEM_DIAG3 74 +#define ESP_TWAI0_CLKOUT 75 +#define ESP_MODEM_DIAG4 75 +#define ESP_TWAI0_STANDBY 76 +#define ESP_MODEM_DIAG5 76 +#define ESP_TWAI1_RX 77 +#define ESP_TWAI1_TX 77 +#define ESP_MODEM_DIAG6 77 +#define ESP_TWAI1_BUS_OFF_ON 78 +#define ESP_MODEM_DIAG7 78 +#define ESP_TWAI1_CLKOUT 79 +#define ESP_MODEM_DIAG8 79 +#define ESP_TWAI1_STANDBY 80 +#define ESP_MODEM_DIAG9 80 +#define ESP_EXTERN_PRIORITY_I 81 +#define ESP_EXTERN_PRIORITY_O 81 +#define ESP_EXTERN_ACTIVE_I 82 +#define ESP_EXTERN_ACTIVE_O 82 +#define ESP_GPIO_SD0_OUT 83 +#define ESP_GPIO_SD1_OUT 84 +#define ESP_GPIO_SD2_OUT 85 +#define ESP_GPIO_SD3_OUT 86 +#define ESP_PWM0_SYNC0_IN 87 +#define ESP_PWM0_OUT0A 87 +#define ESP_MODEM_DIAG10 87 +#define ESP_PWM0_SYNC1_IN 88 +#define ESP_PWM0_OUT0B 88 +#define ESP_MODEM_DIAG11 88 +#define ESP_PWM0_SYNC2_IN 89 +#define ESP_PWM0_OUT1A 89 +#define ESP_MODEM_DIAG12 89 +#define ESP_PWM0_F0_IN 90 +#define ESP_PWM0_OUT1B 90 +#define ESP_MODEM_DIAG13 90 +#define ESP_PWM0_F1_IN 91 +#define ESP_PWM0_OUT2A 91 +#define ESP_MODEM_DIAG14 91 +#define ESP_PWM0_F2_IN 92 +#define ESP_PWM0_OUT2B 92 +#define ESP_MODEM_DIAG15 92 +#define ESP_PWM0_CAP0_IN 93 +#define ESP_ANT_SEL0 93 +#define ESP_PWM0_CAP1_IN 94 +#define ESP_ANT_SEL1 94 +#define ESP_PWM0_CAP2_IN 95 +#define ESP_ANT_SEL2 95 +#define ESP_ANT_SEL3 96 +#define ESP_SIG_IN_FUNC_97 97 +#define ESP_SIG_IN_FUNC97 97 +#define ESP_SIG_IN_FUNC_98 98 +#define ESP_SIG_IN_FUNC98 98 +#define ESP_SIG_IN_FUNC_99 99 +#define ESP_SIG_IN_FUNC99 99 +#define ESP_SIG_IN_FUNC_100 100 +#define ESP_SIG_IN_FUNC100 100 +#define ESP_PCNT_SIG_CH0_IN0 101 +#define ESP_FSPICS1_OUT 101 +#define ESP_MODEM_DIAG16 101 +#define ESP_PCNT_SIG_CH1_IN0 102 +#define ESP_FSPICS2_OUT 102 +#define ESP_MODEM_DIAG17 102 +#define ESP_PCNT_CTRL_CH0_IN0 103 +#define ESP_FSPICS3_OUT 103 +#define ESP_MODEM_DIAG18 103 +#define ESP_PCNT_CTRL_CH1_IN0 104 +#define ESP_FSPICS4_OUT 104 +#define ESP_MODEM_DIAG19 104 +#define ESP_PCNT_SIG_CH0_IN1 105 +#define ESP_FSPICS5_OUT 105 +#define ESP_MODEM_DIAG20 105 +#define ESP_PCNT_SIG_CH1_IN1 106 +#define ESP_MODEM_DIAG21 106 +#define ESP_PCNT_CTRL_CH0_IN1 107 +#define ESP_MODEM_DIAG22 107 +#define ESP_PCNT_CTRL_CH1_IN1 108 +#define ESP_MODEM_DIAG23 108 +#define ESP_PCNT_SIG_CH0_IN2 109 +#define ESP_MODEM_DIAG24 109 +#define ESP_PCNT_SIG_CH1_IN2 110 +#define ESP_MODEM_DIAG25 110 +#define ESP_PCNT_CTRL_CH0_IN2 111 +#define ESP_MODEM_DIAG26 111 +#define ESP_PCNT_CTRL_CH1_IN2 112 +#define ESP_MODEM_DIAG27 112 +#define ESP_PCNT_SIG_CH0_IN3 113 +#define ESP_MODEM_DIAG28 113 +#define ESP_PCNT_SIG_CH1_IN3 114 +#define ESP_SPICLK_OUT 114 +#define ESP_MODEM_DIAG29 114 +#define ESP_PCNT_CTRL_CH0_IN3 115 +#define ESP_SPICS0_OUT 115 +#define ESP_MODEM_DIAG30 115 +#define ESP_PCNT_CTRL_CH1_IN3 116 +#define ESP_SPICS1_OUT 116 +#define ESP_MODEM_DIAG31 116 +#define ESP_GPIO_EVENT_MATRIX_IN0 117 +#define ESP_GPIO_TASK_MATRIX_OUT0 117 +#define ESP_GPIO_EVENT_MATRIX_IN1 118 +#define ESP_GPIO_TASK_MATRIX_OUT1 118 +#define ESP_GPIO_EVENT_MATRIX_IN2 119 +#define ESP_GPIO_TASK_MATRIX_OUT2 119 +#define ESP_GPIO_EVENT_MATRIX_IN3 120 +#define ESP_GPIO_TASK_MATRIX_OUT3 120 +#define ESP_SPIQ_IN 121 +#define ESP_SPIQ_OUT 121 +#define ESP_SPID_IN 122 +#define ESP_SPID_OUT 122 +#define ESP_SPIHD_IN 123 +#define ESP_SPIHD_OUT 123 +#define ESP_SPIWP_IN 124 +#define ESP_SPIWP_OUT 124 +#define ESP_CLK_OUT_OUT1 125 +#define ESP_CLK_OUT_OUT2 126 +#define ESP_CLK_OUT_OUT3 127 +#define ESP_SIG_GPIO_OUT 128 +#define ESP_GPIO_MAP_DATE 0x2201120 + +#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_PINCTRL_ESP32C6_GPIO_SIGMAP_H_ */ diff --git a/include/zephyr/dt-bindings/pinctrl/esp32c6-pinctrl.h b/include/zephyr/dt-bindings/pinctrl/esp32c6-pinctrl.h new file mode 100644 index 0000000000000..3c138c85f4391 --- /dev/null +++ b/include/zephyr/dt-bindings/pinctrl/esp32c6-pinctrl.h @@ -0,0 +1,889 @@ +/* + * Copyright (c) 2022 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + * + * NOTE: Autogenerated file using esp_genpinctrl.py + */ + +#ifndef INC_DT_BINDS_PINCTRL_ESP32C6_PINCTRL_HAL_H_ +#define INC_DT_BINDS_PINCTRL_ESP32C6_PINCTRL_HAL_H_ + +/* UART0_CTS */ +#define UART0_CTS_GPIO0 \ + ESP32_PINMUX(0, ESP_U0CTS_IN, ESP_NOSIG) + +#define UART0_CTS_GPIO1 \ + ESP32_PINMUX(1, ESP_U0CTS_IN, ESP_NOSIG) + +#define UART0_CTS_GPIO2 \ + ESP32_PINMUX(2, ESP_U0CTS_IN, ESP_NOSIG) + +#define UART0_CTS_GPIO3 \ + ESP32_PINMUX(3, ESP_U0CTS_IN, ESP_NOSIG) + +#define UART0_CTS_GPIO4 \ + ESP32_PINMUX(4, ESP_U0CTS_IN, ESP_NOSIG) + +#define UART0_CTS_GPIO5 \ + ESP32_PINMUX(5, ESP_U0CTS_IN, ESP_NOSIG) + +#define UART0_CTS_GPIO6 \ + ESP32_PINMUX(6, ESP_U0CTS_IN, ESP_NOSIG) + +#define UART0_CTS_GPIO7 \ + ESP32_PINMUX(7, ESP_U0CTS_IN, ESP_NOSIG) + +#define UART0_CTS_GPIO8 \ + ESP32_PINMUX(8, ESP_U0CTS_IN, ESP_NOSIG) + +#define UART0_CTS_GPIO9 \ + ESP32_PINMUX(9, ESP_U0CTS_IN, ESP_NOSIG) + +#define UART0_CTS_GPIO10 \ + ESP32_PINMUX(10, ESP_U0CTS_IN, ESP_NOSIG) + +#define UART0_CTS_GPIO11 \ + ESP32_PINMUX(11, ESP_U0CTS_IN, ESP_NOSIG) + +#define UART0_CTS_GPIO12 \ + ESP32_PINMUX(12, ESP_U0CTS_IN, ESP_NOSIG) + +#define UART0_CTS_GPIO13 \ + ESP32_PINMUX(13, ESP_U0CTS_IN, ESP_NOSIG) + +#define UART0_CTS_GPIO14 \ + ESP32_PINMUX(14, ESP_U0CTS_IN, ESP_NOSIG) + +#define UART0_CTS_GPIO15 \ + ESP32_PINMUX(15, ESP_U0CTS_IN, ESP_NOSIG) + +#define UART0_CTS_GPIO16 \ + ESP32_PINMUX(16, ESP_U0CTS_IN, ESP_NOSIG) + +#define UART0_CTS_GPIO17 \ + ESP32_PINMUX(17, ESP_U0CTS_IN, ESP_NOSIG) + +#define UART0_CTS_GPIO18 \ + ESP32_PINMUX(18, ESP_U0CTS_IN, ESP_NOSIG) + +#define UART0_CTS_GPIO19 \ + ESP32_PINMUX(19, ESP_U0CTS_IN, ESP_NOSIG) + +#define UART0_CTS_GPIO20 \ + ESP32_PINMUX(20, ESP_U0CTS_IN, ESP_NOSIG) + +#define UART0_CTS_GPIO21 \ + ESP32_PINMUX(21, ESP_U0CTS_IN, ESP_NOSIG) + +#define UART0_CTS_GPIO22 \ + ESP32_PINMUX(22, ESP_U0CTS_IN, ESP_NOSIG) + +#define UART0_CTS_GPIO23 \ + ESP32_PINMUX(23, ESP_U0CTS_IN, ESP_NOSIG) + +/* UART0_DSR */ +#define UART0_DSR_GPIO0 \ + ESP32_PINMUX(0, ESP_U0DSR_IN, ESP_NOSIG) + +#define UART0_DSR_GPIO1 \ + ESP32_PINMUX(1, ESP_U0DSR_IN, ESP_NOSIG) + +#define UART0_DSR_GPIO2 \ + ESP32_PINMUX(2, ESP_U0DSR_IN, ESP_NOSIG) + +#define UART0_DSR_GPIO3 \ + ESP32_PINMUX(3, ESP_U0DSR_IN, ESP_NOSIG) + +#define UART0_DSR_GPIO4 \ + ESP32_PINMUX(4, ESP_U0DSR_IN, ESP_NOSIG) + +#define UART0_DSR_GPIO5 \ + ESP32_PINMUX(5, ESP_U0DSR_IN, ESP_NOSIG) + +#define UART0_DSR_GPIO6 \ + ESP32_PINMUX(6, ESP_U0DSR_IN, ESP_NOSIG) + +#define UART0_DSR_GPIO7 \ + ESP32_PINMUX(7, ESP_U0DSR_IN, ESP_NOSIG) + +#define UART0_DSR_GPIO8 \ + ESP32_PINMUX(8, ESP_U0DSR_IN, ESP_NOSIG) + +#define UART0_DSR_GPIO9 \ + ESP32_PINMUX(9, ESP_U0DSR_IN, ESP_NOSIG) + +#define UART0_DSR_GPIO10 \ + ESP32_PINMUX(10, ESP_U0DSR_IN, ESP_NOSIG) + +#define UART0_DSR_GPIO11 \ + ESP32_PINMUX(11, ESP_U0DSR_IN, ESP_NOSIG) + +#define UART0_DSR_GPIO12 \ + ESP32_PINMUX(12, ESP_U0DSR_IN, ESP_NOSIG) + +#define UART0_DSR_GPIO13 \ + ESP32_PINMUX(13, ESP_U0DSR_IN, ESP_NOSIG) + +#define UART0_DSR_GPIO14 \ + ESP32_PINMUX(14, ESP_U0DSR_IN, ESP_NOSIG) + +#define UART0_DSR_GPIO15 \ + ESP32_PINMUX(15, ESP_U0DSR_IN, ESP_NOSIG) + +#define UART0_DSR_GPIO16 \ + ESP32_PINMUX(16, ESP_U0DSR_IN, ESP_NOSIG) + +#define UART0_DSR_GPIO17 \ + ESP32_PINMUX(17, ESP_U0DSR_IN, ESP_NOSIG) + +#define UART0_DSR_GPIO18 \ + ESP32_PINMUX(18, ESP_U0DSR_IN, ESP_NOSIG) + +#define UART0_DSR_GPIO19 \ + ESP32_PINMUX(19, ESP_U0DSR_IN, ESP_NOSIG) + +#define UART0_DSR_GPIO20 \ + ESP32_PINMUX(20, ESP_U0DSR_IN, ESP_NOSIG) + +#define UART0_DSR_GPIO21 \ + ESP32_PINMUX(21, ESP_U0DSR_IN, ESP_NOSIG) + +#define UART0_DSR_GPIO22 \ + ESP32_PINMUX(22, ESP_U0DSR_IN, ESP_NOSIG) + +#define UART0_DSR_GPIO23 \ + ESP32_PINMUX(23, ESP_U0DSR_IN, ESP_NOSIG) + +/* UART0_DTR */ +#define UART0_DTR_GPIO0 \ + ESP32_PINMUX(0, ESP_NOSIG, ESP_U0DTR_OUT) + +#define UART0_DTR_GPIO1 \ + ESP32_PINMUX(1, ESP_NOSIG, ESP_U0DTR_OUT) + +#define UART0_DTR_GPIO2 \ + ESP32_PINMUX(2, ESP_NOSIG, ESP_U0DTR_OUT) + +#define UART0_DTR_GPIO3 \ + ESP32_PINMUX(3, ESP_NOSIG, ESP_U0DTR_OUT) + +#define UART0_DTR_GPIO4 \ + ESP32_PINMUX(4, ESP_NOSIG, ESP_U0DTR_OUT) + +#define UART0_DTR_GPIO5 \ + ESP32_PINMUX(5, ESP_NOSIG, ESP_U0DTR_OUT) + +#define UART0_DTR_GPIO6 \ + ESP32_PINMUX(6, ESP_NOSIG, ESP_U0DTR_OUT) + +#define UART0_DTR_GPIO7 \ + ESP32_PINMUX(7, ESP_NOSIG, ESP_U0DTR_OUT) + +#define UART0_DTR_GPIO8 \ + ESP32_PINMUX(8, ESP_NOSIG, ESP_U0DTR_OUT) + +#define UART0_DTR_GPIO9 \ + ESP32_PINMUX(9, ESP_NOSIG, ESP_U0DTR_OUT) + +#define UART0_DTR_GPIO10 \ + ESP32_PINMUX(10, ESP_NOSIG, ESP_U0DTR_OUT) + +#define UART0_DTR_GPIO11 \ + ESP32_PINMUX(11, ESP_NOSIG, ESP_U0DTR_OUT) + +#define UART0_DTR_GPIO12 \ + ESP32_PINMUX(12, ESP_NOSIG, ESP_U0DTR_OUT) + +#define UART0_DTR_GPIO13 \ + ESP32_PINMUX(13, ESP_NOSIG, ESP_U0DTR_OUT) + +#define UART0_DTR_GPIO14 \ + ESP32_PINMUX(14, ESP_NOSIG, ESP_U0DTR_OUT) + +#define UART0_DTR_GPIO15 \ + ESP32_PINMUX(15, ESP_NOSIG, ESP_U0DTR_OUT) + +#define UART0_DTR_GPIO16 \ + ESP32_PINMUX(16, ESP_NOSIG, ESP_U0DTR_OUT) + +#define UART0_DTR_GPIO17 \ + ESP32_PINMUX(17, ESP_NOSIG, ESP_U0DTR_OUT) + +#define UART0_DTR_GPIO18 \ + ESP32_PINMUX(18, ESP_NOSIG, ESP_U0DTR_OUT) + +#define UART0_DTR_GPIO19 \ + ESP32_PINMUX(19, ESP_NOSIG, ESP_U0DTR_OUT) + +#define UART0_DTR_GPIO20 \ + ESP32_PINMUX(20, ESP_NOSIG, ESP_U0DTR_OUT) + +#define UART0_DTR_GPIO21 \ + ESP32_PINMUX(21, ESP_NOSIG, ESP_U0DTR_OUT) + +#define UART0_DTR_GPIO22 \ + ESP32_PINMUX(22, ESP_NOSIG, ESP_U0DTR_OUT) + +#define UART0_DTR_GPIO23 \ + ESP32_PINMUX(23, ESP_NOSIG, ESP_U0DTR_OUT) + +/* UART0_RTS */ +#define UART0_RTS_GPIO0 \ + ESP32_PINMUX(0, ESP_NOSIG, ESP_U0RTS_OUT) + +#define UART0_RTS_GPIO1 \ + ESP32_PINMUX(1, ESP_NOSIG, ESP_U0RTS_OUT) + +#define UART0_RTS_GPIO2 \ + ESP32_PINMUX(2, ESP_NOSIG, ESP_U0RTS_OUT) + +#define UART0_RTS_GPIO3 \ + ESP32_PINMUX(3, ESP_NOSIG, ESP_U0RTS_OUT) + +#define UART0_RTS_GPIO4 \ + ESP32_PINMUX(4, ESP_NOSIG, ESP_U0RTS_OUT) + +#define UART0_RTS_GPIO5 \ + ESP32_PINMUX(5, ESP_NOSIG, ESP_U0RTS_OUT) + +#define UART0_RTS_GPIO6 \ + ESP32_PINMUX(6, ESP_NOSIG, ESP_U0RTS_OUT) + +#define UART0_RTS_GPIO7 \ + ESP32_PINMUX(7, ESP_NOSIG, ESP_U0RTS_OUT) + +#define UART0_RTS_GPIO8 \ + ESP32_PINMUX(8, ESP_NOSIG, ESP_U0RTS_OUT) + +#define UART0_RTS_GPIO9 \ + ESP32_PINMUX(9, ESP_NOSIG, ESP_U0RTS_OUT) + +#define UART0_RTS_GPIO10 \ + ESP32_PINMUX(10, ESP_NOSIG, ESP_U0RTS_OUT) + +#define UART0_RTS_GPIO11 \ + ESP32_PINMUX(11, ESP_NOSIG, ESP_U0RTS_OUT) + +#define UART0_RTS_GPIO12 \ + ESP32_PINMUX(12, ESP_NOSIG, ESP_U0RTS_OUT) + +#define UART0_RTS_GPIO13 \ + ESP32_PINMUX(13, ESP_NOSIG, ESP_U0RTS_OUT) + +#define UART0_RTS_GPIO14 \ + ESP32_PINMUX(14, ESP_NOSIG, ESP_U0RTS_OUT) + +#define UART0_RTS_GPIO15 \ + ESP32_PINMUX(15, ESP_NOSIG, ESP_U0RTS_OUT) + +#define UART0_RTS_GPIO16 \ + ESP32_PINMUX(16, ESP_NOSIG, ESP_U0RTS_OUT) + +#define UART0_RTS_GPIO17 \ + ESP32_PINMUX(17, ESP_NOSIG, ESP_U0RTS_OUT) + +#define UART0_RTS_GPIO18 \ + ESP32_PINMUX(18, ESP_NOSIG, ESP_U0RTS_OUT) + +#define UART0_RTS_GPIO19 \ + ESP32_PINMUX(19, ESP_NOSIG, ESP_U0RTS_OUT) + +#define UART0_RTS_GPIO20 \ + ESP32_PINMUX(20, ESP_NOSIG, ESP_U0RTS_OUT) + +#define UART0_RTS_GPIO21 \ + ESP32_PINMUX(21, ESP_NOSIG, ESP_U0RTS_OUT) + +#define UART0_RTS_GPIO22 \ + ESP32_PINMUX(22, ESP_NOSIG, ESP_U0RTS_OUT) + +#define UART0_RTS_GPIO23 \ + ESP32_PINMUX(23, ESP_NOSIG, ESP_U0RTS_OUT) + +/* UART0_RX */ +#define UART0_RX_GPIO0 \ + ESP32_PINMUX(0, ESP_U0RXD_IN, ESP_NOSIG) + +#define UART0_RX_GPIO1 \ + ESP32_PINMUX(1, ESP_U0RXD_IN, ESP_NOSIG) + +#define UART0_RX_GPIO2 \ + ESP32_PINMUX(2, ESP_U0RXD_IN, ESP_NOSIG) + +#define UART0_RX_GPIO3 \ + ESP32_PINMUX(3, ESP_U0RXD_IN, ESP_NOSIG) + +#define UART0_RX_GPIO4 \ + ESP32_PINMUX(4, ESP_U0RXD_IN, ESP_NOSIG) + +#define UART0_RX_GPIO5 \ + ESP32_PINMUX(5, ESP_U0RXD_IN, ESP_NOSIG) + +#define UART0_RX_GPIO6 \ + ESP32_PINMUX(6, ESP_U0RXD_IN, ESP_NOSIG) + +#define UART0_RX_GPIO7 \ + ESP32_PINMUX(7, ESP_U0RXD_IN, ESP_NOSIG) + +#define UART0_RX_GPIO8 \ + ESP32_PINMUX(8, ESP_U0RXD_IN, ESP_NOSIG) + +#define UART0_RX_GPIO9 \ + ESP32_PINMUX(9, ESP_U0RXD_IN, ESP_NOSIG) + +#define UART0_RX_GPIO10 \ + ESP32_PINMUX(10, ESP_U0RXD_IN, ESP_NOSIG) + +#define UART0_RX_GPIO11 \ + ESP32_PINMUX(11, ESP_U0RXD_IN, ESP_NOSIG) + +#define UART0_RX_GPIO12 \ + ESP32_PINMUX(12, ESP_U0RXD_IN, ESP_NOSIG) + +#define UART0_RX_GPIO13 \ + ESP32_PINMUX(13, ESP_U0RXD_IN, ESP_NOSIG) + +#define UART0_RX_GPIO14 \ + ESP32_PINMUX(14, ESP_U0RXD_IN, ESP_NOSIG) + +#define UART0_RX_GPIO15 \ + ESP32_PINMUX(15, ESP_U0RXD_IN, ESP_NOSIG) + +#define UART0_RX_GPIO16 \ + ESP32_PINMUX(16, ESP_U0RXD_IN, ESP_NOSIG) + +#define UART0_RX_GPIO17 \ + ESP32_PINMUX(17, ESP_U0RXD_IN, ESP_NOSIG) + +#define UART0_RX_GPIO18 \ + ESP32_PINMUX(18, ESP_U0RXD_IN, ESP_NOSIG) + +#define UART0_RX_GPIO19 \ + ESP32_PINMUX(19, ESP_U0RXD_IN, ESP_NOSIG) + +#define UART0_RX_GPIO20 \ + ESP32_PINMUX(20, ESP_U0RXD_IN, ESP_NOSIG) + +#define UART0_RX_GPIO21 \ + ESP32_PINMUX(21, ESP_U0RXD_IN, ESP_NOSIG) + +#define UART0_RX_GPIO22 \ + ESP32_PINMUX(22, ESP_U0RXD_IN, ESP_NOSIG) + +#define UART0_RX_GPIO23 \ + ESP32_PINMUX(23, ESP_U0RXD_IN, ESP_NOSIG) + +/* UART0_TX */ +#define UART0_TX_GPIO0 \ + ESP32_PINMUX(0, ESP_NOSIG, ESP_U0TXD_OUT) + +#define UART0_TX_GPIO1 \ + ESP32_PINMUX(1, ESP_NOSIG, ESP_U0TXD_OUT) + +#define UART0_TX_GPIO2 \ + ESP32_PINMUX(2, ESP_NOSIG, ESP_U0TXD_OUT) + +#define UART0_TX_GPIO3 \ + ESP32_PINMUX(3, ESP_NOSIG, ESP_U0TXD_OUT) + +#define UART0_TX_GPIO4 \ + ESP32_PINMUX(4, ESP_NOSIG, ESP_U0TXD_OUT) + +#define UART0_TX_GPIO5 \ + ESP32_PINMUX(5, ESP_NOSIG, ESP_U0TXD_OUT) + +#define UART0_TX_GPIO6 \ + ESP32_PINMUX(6, ESP_NOSIG, ESP_U0TXD_OUT) + +#define UART0_TX_GPIO7 \ + ESP32_PINMUX(7, ESP_NOSIG, ESP_U0TXD_OUT) + +#define UART0_TX_GPIO8 \ + ESP32_PINMUX(8, ESP_NOSIG, ESP_U0TXD_OUT) + +#define UART0_TX_GPIO9 \ + ESP32_PINMUX(9, ESP_NOSIG, ESP_U0TXD_OUT) + +#define UART0_TX_GPIO10 \ + ESP32_PINMUX(10, ESP_NOSIG, ESP_U0TXD_OUT) + +#define UART0_TX_GPIO11 \ + ESP32_PINMUX(11, ESP_NOSIG, ESP_U0TXD_OUT) + +#define UART0_TX_GPIO12 \ + ESP32_PINMUX(12, ESP_NOSIG, ESP_U0TXD_OUT) + +#define UART0_TX_GPIO13 \ + ESP32_PINMUX(13, ESP_NOSIG, ESP_U0TXD_OUT) + +#define UART0_TX_GPIO14 \ + ESP32_PINMUX(14, ESP_NOSIG, ESP_U0TXD_OUT) + +#define UART0_TX_GPIO15 \ + ESP32_PINMUX(15, ESP_NOSIG, ESP_U0TXD_OUT) + +#define UART0_TX_GPIO16 \ + ESP32_PINMUX(16, ESP_NOSIG, ESP_U0TXD_OUT) + +#define UART0_TX_GPIO17 \ + ESP32_PINMUX(17, ESP_NOSIG, ESP_U0TXD_OUT) + +#define UART0_TX_GPIO18 \ + ESP32_PINMUX(18, ESP_NOSIG, ESP_U0TXD_OUT) + +#define UART0_TX_GPIO19 \ + ESP32_PINMUX(19, ESP_NOSIG, ESP_U0TXD_OUT) + +#define UART0_TX_GPIO20 \ + ESP32_PINMUX(20, ESP_NOSIG, ESP_U0TXD_OUT) + +#define UART0_TX_GPIO21 \ + ESP32_PINMUX(21, ESP_NOSIG, ESP_U0TXD_OUT) + +#define UART0_TX_GPIO22 \ + ESP32_PINMUX(22, ESP_NOSIG, ESP_U0TXD_OUT) + +#define UART0_TX_GPIO23 \ + ESP32_PINMUX(23, ESP_NOSIG, ESP_U0TXD_OUT) + +/* UART1_CTS */ +#define UART1_CTS_GPIO0 \ + ESP32_PINMUX(0, ESP_U1CTS_IN, ESP_NOSIG) + +#define UART1_CTS_GPIO1 \ + ESP32_PINMUX(1, ESP_U1CTS_IN, ESP_NOSIG) + +#define UART1_CTS_GPIO2 \ + ESP32_PINMUX(2, ESP_U1CTS_IN, ESP_NOSIG) + +#define UART1_CTS_GPIO3 \ + ESP32_PINMUX(3, ESP_U1CTS_IN, ESP_NOSIG) + +#define UART1_CTS_GPIO4 \ + ESP32_PINMUX(4, ESP_U1CTS_IN, ESP_NOSIG) + +#define UART1_CTS_GPIO5 \ + ESP32_PINMUX(5, ESP_U1CTS_IN, ESP_NOSIG) + +#define UART1_CTS_GPIO6 \ + ESP32_PINMUX(6, ESP_U1CTS_IN, ESP_NOSIG) + +#define UART1_CTS_GPIO7 \ + ESP32_PINMUX(7, ESP_U1CTS_IN, ESP_NOSIG) + +#define UART1_CTS_GPIO8 \ + ESP32_PINMUX(8, ESP_U1CTS_IN, ESP_NOSIG) + +#define UART1_CTS_GPIO9 \ + ESP32_PINMUX(9, ESP_U1CTS_IN, ESP_NOSIG) + +#define UART1_CTS_GPIO10 \ + ESP32_PINMUX(10, ESP_U1CTS_IN, ESP_NOSIG) + +#define UART1_CTS_GPIO11 \ + ESP32_PINMUX(11, ESP_U1CTS_IN, ESP_NOSIG) + +#define UART1_CTS_GPIO12 \ + ESP32_PINMUX(12, ESP_U1CTS_IN, ESP_NOSIG) + +#define UART1_CTS_GPIO13 \ + ESP32_PINMUX(13, ESP_U1CTS_IN, ESP_NOSIG) + +#define UART1_CTS_GPIO14 \ + ESP32_PINMUX(14, ESP_U1CTS_IN, ESP_NOSIG) + +#define UART1_CTS_GPIO15 \ + ESP32_PINMUX(15, ESP_U1CTS_IN, ESP_NOSIG) + +#define UART1_CTS_GPIO16 \ + ESP32_PINMUX(16, ESP_U1CTS_IN, ESP_NOSIG) + +#define UART1_CTS_GPIO17 \ + ESP32_PINMUX(17, ESP_U1CTS_IN, ESP_NOSIG) + +#define UART1_CTS_GPIO18 \ + ESP32_PINMUX(18, ESP_U1CTS_IN, ESP_NOSIG) + +#define UART1_CTS_GPIO19 \ + ESP32_PINMUX(19, ESP_U1CTS_IN, ESP_NOSIG) + +#define UART1_CTS_GPIO20 \ + ESP32_PINMUX(20, ESP_U1CTS_IN, ESP_NOSIG) + +#define UART1_CTS_GPIO21 \ + ESP32_PINMUX(21, ESP_U1CTS_IN, ESP_NOSIG) + +#define UART1_CTS_GPIO22 \ + ESP32_PINMUX(22, ESP_U1CTS_IN, ESP_NOSIG) + +#define UART1_CTS_GPIO23 \ + ESP32_PINMUX(23, ESP_U1CTS_IN, ESP_NOSIG) + +/* UART1_DSR */ +#define UART1_DSR_GPIO0 \ + ESP32_PINMUX(0, ESP_U1DSR_IN, ESP_NOSIG) + +#define UART1_DSR_GPIO1 \ + ESP32_PINMUX(1, ESP_U1DSR_IN, ESP_NOSIG) + +#define UART1_DSR_GPIO2 \ + ESP32_PINMUX(2, ESP_U1DSR_IN, ESP_NOSIG) + +#define UART1_DSR_GPIO3 \ + ESP32_PINMUX(3, ESP_U1DSR_IN, ESP_NOSIG) + +#define UART1_DSR_GPIO4 \ + ESP32_PINMUX(4, ESP_U1DSR_IN, ESP_NOSIG) + +#define UART1_DSR_GPIO5 \ + ESP32_PINMUX(5, ESP_U1DSR_IN, ESP_NOSIG) + +#define UART1_DSR_GPIO6 \ + ESP32_PINMUX(6, ESP_U1DSR_IN, ESP_NOSIG) + +#define UART1_DSR_GPIO7 \ + ESP32_PINMUX(7, ESP_U1DSR_IN, ESP_NOSIG) + +#define UART1_DSR_GPIO8 \ + ESP32_PINMUX(8, ESP_U1DSR_IN, ESP_NOSIG) + +#define UART1_DSR_GPIO9 \ + ESP32_PINMUX(9, ESP_U1DSR_IN, ESP_NOSIG) + +#define UART1_DSR_GPIO10 \ + ESP32_PINMUX(10, ESP_U1DSR_IN, ESP_NOSIG) + +#define UART1_DSR_GPIO11 \ + ESP32_PINMUX(11, ESP_U1DSR_IN, ESP_NOSIG) + +#define UART1_DSR_GPIO12 \ + ESP32_PINMUX(12, ESP_U1DSR_IN, ESP_NOSIG) + +#define UART1_DSR_GPIO13 \ + ESP32_PINMUX(13, ESP_U1DSR_IN, ESP_NOSIG) + +#define UART1_DSR_GPIO14 \ + ESP32_PINMUX(14, ESP_U1DSR_IN, ESP_NOSIG) + +#define UART1_DSR_GPIO15 \ + ESP32_PINMUX(15, ESP_U1DSR_IN, ESP_NOSIG) + +#define UART1_DSR_GPIO16 \ + ESP32_PINMUX(16, ESP_U1DSR_IN, ESP_NOSIG) + +#define UART1_DSR_GPIO17 \ + ESP32_PINMUX(17, ESP_U1DSR_IN, ESP_NOSIG) + +#define UART1_DSR_GPIO18 \ + ESP32_PINMUX(18, ESP_U1DSR_IN, ESP_NOSIG) + +#define UART1_DSR_GPIO19 \ + ESP32_PINMUX(19, ESP_U1DSR_IN, ESP_NOSIG) + +#define UART1_DSR_GPIO20 \ + ESP32_PINMUX(20, ESP_U1DSR_IN, ESP_NOSIG) + +#define UART1_DSR_GPIO21 \ + ESP32_PINMUX(21, ESP_U1DSR_IN, ESP_NOSIG) + +#define UART1_DSR_GPIO22 \ + ESP32_PINMUX(22, ESP_U1DSR_IN, ESP_NOSIG) + +#define UART1_DSR_GPIO23 \ + ESP32_PINMUX(23, ESP_U1DSR_IN, ESP_NOSIG) + +/* UART1_DTR */ +#define UART1_DTR_GPIO0 \ + ESP32_PINMUX(0, ESP_NOSIG, ESP_U1DTR_OUT) + +#define UART1_DTR_GPIO1 \ + ESP32_PINMUX(1, ESP_NOSIG, ESP_U1DTR_OUT) + +#define UART1_DTR_GPIO2 \ + ESP32_PINMUX(2, ESP_NOSIG, ESP_U1DTR_OUT) + +#define UART1_DTR_GPIO3 \ + ESP32_PINMUX(3, ESP_NOSIG, ESP_U1DTR_OUT) + +#define UART1_DTR_GPIO4 \ + ESP32_PINMUX(4, ESP_NOSIG, ESP_U1DTR_OUT) + +#define UART1_DTR_GPIO5 \ + ESP32_PINMUX(5, ESP_NOSIG, ESP_U1DTR_OUT) + +#define UART1_DTR_GPIO6 \ + ESP32_PINMUX(6, ESP_NOSIG, ESP_U1DTR_OUT) + +#define UART1_DTR_GPIO7 \ + ESP32_PINMUX(7, ESP_NOSIG, ESP_U1DTR_OUT) + +#define UART1_DTR_GPIO8 \ + ESP32_PINMUX(8, ESP_NOSIG, ESP_U1DTR_OUT) + +#define UART1_DTR_GPIO9 \ + ESP32_PINMUX(9, ESP_NOSIG, ESP_U1DTR_OUT) + +#define UART1_DTR_GPIO10 \ + ESP32_PINMUX(10, ESP_NOSIG, ESP_U1DTR_OUT) + +#define UART1_DTR_GPIO11 \ + ESP32_PINMUX(11, ESP_NOSIG, ESP_U1DTR_OUT) + +#define UART1_DTR_GPIO12 \ + ESP32_PINMUX(12, ESP_NOSIG, ESP_U1DTR_OUT) + +#define UART1_DTR_GPIO13 \ + ESP32_PINMUX(13, ESP_NOSIG, ESP_U1DTR_OUT) + +#define UART1_DTR_GPIO14 \ + ESP32_PINMUX(14, ESP_NOSIG, ESP_U1DTR_OUT) + +#define UART1_DTR_GPIO15 \ + ESP32_PINMUX(15, ESP_NOSIG, ESP_U1DTR_OUT) + +#define UART1_DTR_GPIO16 \ + ESP32_PINMUX(16, ESP_NOSIG, ESP_U1DTR_OUT) + +#define UART1_DTR_GPIO17 \ + ESP32_PINMUX(17, ESP_NOSIG, ESP_U1DTR_OUT) + +#define UART1_DTR_GPIO18 \ + ESP32_PINMUX(18, ESP_NOSIG, ESP_U1DTR_OUT) + +#define UART1_DTR_GPIO19 \ + ESP32_PINMUX(19, ESP_NOSIG, ESP_U1DTR_OUT) + +#define UART1_DTR_GPIO20 \ + ESP32_PINMUX(20, ESP_NOSIG, ESP_U1DTR_OUT) + +#define UART1_DTR_GPIO21 \ + ESP32_PINMUX(21, ESP_NOSIG, ESP_U1DTR_OUT) + +#define UART1_DTR_GPIO22 \ + ESP32_PINMUX(22, ESP_NOSIG, ESP_U1DTR_OUT) + +#define UART1_DTR_GPIO23 \ + ESP32_PINMUX(23, ESP_NOSIG, ESP_U1DTR_OUT) + +/* UART1_RTS */ +#define UART1_RTS_GPIO0 \ + ESP32_PINMUX(0, ESP_NOSIG, ESP_U1RTS_OUT) + +#define UART1_RTS_GPIO1 \ + ESP32_PINMUX(1, ESP_NOSIG, ESP_U1RTS_OUT) + +#define UART1_RTS_GPIO2 \ + ESP32_PINMUX(2, ESP_NOSIG, ESP_U1RTS_OUT) + +#define UART1_RTS_GPIO3 \ + ESP32_PINMUX(3, ESP_NOSIG, ESP_U1RTS_OUT) + +#define UART1_RTS_GPIO4 \ + ESP32_PINMUX(4, ESP_NOSIG, ESP_U1RTS_OUT) + +#define UART1_RTS_GPIO5 \ + ESP32_PINMUX(5, ESP_NOSIG, ESP_U1RTS_OUT) + +#define UART1_RTS_GPIO6 \ + ESP32_PINMUX(6, ESP_NOSIG, ESP_U1RTS_OUT) + +#define UART1_RTS_GPIO7 \ + ESP32_PINMUX(7, ESP_NOSIG, ESP_U1RTS_OUT) + +#define UART1_RTS_GPIO8 \ + ESP32_PINMUX(8, ESP_NOSIG, ESP_U1RTS_OUT) + +#define UART1_RTS_GPIO9 \ + ESP32_PINMUX(9, ESP_NOSIG, ESP_U1RTS_OUT) + +#define UART1_RTS_GPIO10 \ + ESP32_PINMUX(10, ESP_NOSIG, ESP_U1RTS_OUT) + +#define UART1_RTS_GPIO11 \ + ESP32_PINMUX(11, ESP_NOSIG, ESP_U1RTS_OUT) + +#define UART1_RTS_GPIO12 \ + ESP32_PINMUX(12, ESP_NOSIG, ESP_U1RTS_OUT) + +#define UART1_RTS_GPIO13 \ + ESP32_PINMUX(13, ESP_NOSIG, ESP_U1RTS_OUT) + +#define UART1_RTS_GPIO14 \ + ESP32_PINMUX(14, ESP_NOSIG, ESP_U1RTS_OUT) + +#define UART1_RTS_GPIO15 \ + ESP32_PINMUX(15, ESP_NOSIG, ESP_U1RTS_OUT) + +#define UART1_RTS_GPIO16 \ + ESP32_PINMUX(16, ESP_NOSIG, ESP_U1RTS_OUT) + +#define UART1_RTS_GPIO17 \ + ESP32_PINMUX(17, ESP_NOSIG, ESP_U1RTS_OUT) + +#define UART1_RTS_GPIO18 \ + ESP32_PINMUX(18, ESP_NOSIG, ESP_U1RTS_OUT) + +#define UART1_RTS_GPIO19 \ + ESP32_PINMUX(19, ESP_NOSIG, ESP_U1RTS_OUT) + +#define UART1_RTS_GPIO20 \ + ESP32_PINMUX(20, ESP_NOSIG, ESP_U1RTS_OUT) + +#define UART1_RTS_GPIO21 \ + ESP32_PINMUX(21, ESP_NOSIG, ESP_U1RTS_OUT) + +#define UART1_RTS_GPIO22 \ + ESP32_PINMUX(22, ESP_NOSIG, ESP_U1RTS_OUT) + +#define UART1_RTS_GPIO23 \ + ESP32_PINMUX(23, ESP_NOSIG, ESP_U1RTS_OUT) + +/* UART1_RX */ +#define UART1_RX_GPIO0 \ + ESP32_PINMUX(0, ESP_U1RXD_IN, ESP_NOSIG) + +#define UART1_RX_GPIO1 \ + ESP32_PINMUX(1, ESP_U1RXD_IN, ESP_NOSIG) + +#define UART1_RX_GPIO2 \ + ESP32_PINMUX(2, ESP_U1RXD_IN, ESP_NOSIG) + +#define UART1_RX_GPIO3 \ + ESP32_PINMUX(3, ESP_U1RXD_IN, ESP_NOSIG) + +#define UART1_RX_GPIO4 \ + ESP32_PINMUX(4, ESP_U1RXD_IN, ESP_NOSIG) + +#define UART1_RX_GPIO5 \ + ESP32_PINMUX(5, ESP_U1RXD_IN, ESP_NOSIG) + +#define UART1_RX_GPIO6 \ + ESP32_PINMUX(6, ESP_U1RXD_IN, ESP_NOSIG) + +#define UART1_RX_GPIO7 \ + ESP32_PINMUX(7, ESP_U1RXD_IN, ESP_NOSIG) + +#define UART1_RX_GPIO8 \ + ESP32_PINMUX(8, ESP_U1RXD_IN, ESP_NOSIG) + +#define UART1_RX_GPIO9 \ + ESP32_PINMUX(9, ESP_U1RXD_IN, ESP_NOSIG) + +#define UART1_RX_GPIO10 \ + ESP32_PINMUX(10, ESP_U1RXD_IN, ESP_NOSIG) + +#define UART1_RX_GPIO11 \ + ESP32_PINMUX(11, ESP_U1RXD_IN, ESP_NOSIG) + +#define UART1_RX_GPIO12 \ + ESP32_PINMUX(12, ESP_U1RXD_IN, ESP_NOSIG) + +#define UART1_RX_GPIO13 \ + ESP32_PINMUX(13, ESP_U1RXD_IN, ESP_NOSIG) + +#define UART1_RX_GPIO14 \ + ESP32_PINMUX(14, ESP_U1RXD_IN, ESP_NOSIG) + +#define UART1_RX_GPIO15 \ + ESP32_PINMUX(15, ESP_U1RXD_IN, ESP_NOSIG) + +#define UART1_RX_GPIO16 \ + ESP32_PINMUX(16, ESP_U1RXD_IN, ESP_NOSIG) + +#define UART1_RX_GPIO17 \ + ESP32_PINMUX(17, ESP_U1RXD_IN, ESP_NOSIG) + +#define UART1_RX_GPIO18 \ + ESP32_PINMUX(18, ESP_U1RXD_IN, ESP_NOSIG) + +#define UART1_RX_GPIO19 \ + ESP32_PINMUX(19, ESP_U1RXD_IN, ESP_NOSIG) + +#define UART1_RX_GPIO20 \ + ESP32_PINMUX(20, ESP_U1RXD_IN, ESP_NOSIG) + +#define UART1_RX_GPIO21 \ + ESP32_PINMUX(21, ESP_U1RXD_IN, ESP_NOSIG) + +#define UART1_RX_GPIO22 \ + ESP32_PINMUX(22, ESP_U1RXD_IN, ESP_NOSIG) + +#define UART1_RX_GPIO23 \ + ESP32_PINMUX(23, ESP_U1RXD_IN, ESP_NOSIG) + +/* UART1_TX */ +#define UART1_TX_GPIO0 \ + ESP32_PINMUX(0, ESP_NOSIG, ESP_U1TXD_OUT) + +#define UART1_TX_GPIO1 \ + ESP32_PINMUX(1, ESP_NOSIG, ESP_U1TXD_OUT) + +#define UART1_TX_GPIO2 \ + ESP32_PINMUX(2, ESP_NOSIG, ESP_U1TXD_OUT) + +#define UART1_TX_GPIO3 \ + ESP32_PINMUX(3, ESP_NOSIG, ESP_U1TXD_OUT) + +#define UART1_TX_GPIO4 \ + ESP32_PINMUX(4, ESP_NOSIG, ESP_U1TXD_OUT) + +#define UART1_TX_GPIO5 \ + ESP32_PINMUX(5, ESP_NOSIG, ESP_U1TXD_OUT) + +#define UART1_TX_GPIO6 \ + ESP32_PINMUX(6, ESP_NOSIG, ESP_U1TXD_OUT) + +#define UART1_TX_GPIO7 \ + ESP32_PINMUX(7, ESP_NOSIG, ESP_U1TXD_OUT) + +#define UART1_TX_GPIO8 \ + ESP32_PINMUX(8, ESP_NOSIG, ESP_U1TXD_OUT) + +#define UART1_TX_GPIO9 \ + ESP32_PINMUX(9, ESP_NOSIG, ESP_U1TXD_OUT) + +#define UART1_TX_GPIO10 \ + ESP32_PINMUX(10, ESP_NOSIG, ESP_U1TXD_OUT) + +#define UART1_TX_GPIO11 \ + ESP32_PINMUX(11, ESP_NOSIG, ESP_U1TXD_OUT) + +#define UART1_TX_GPIO12 \ + ESP32_PINMUX(12, ESP_NOSIG, ESP_U1TXD_OUT) + +#define UART1_TX_GPIO13 \ + ESP32_PINMUX(13, ESP_NOSIG, ESP_U1TXD_OUT) + +#define UART1_TX_GPIO14 \ + ESP32_PINMUX(14, ESP_NOSIG, ESP_U1TXD_OUT) + +#define UART1_TX_GPIO15 \ + ESP32_PINMUX(15, ESP_NOSIG, ESP_U1TXD_OUT) + +#define UART1_TX_GPIO16 \ + ESP32_PINMUX(16, ESP_NOSIG, ESP_U1TXD_OUT) + +#define UART1_TX_GPIO17 \ + ESP32_PINMUX(17, ESP_NOSIG, ESP_U1TXD_OUT) + +#define UART1_TX_GPIO18 \ + ESP32_PINMUX(18, ESP_NOSIG, ESP_U1TXD_OUT) + +#define UART1_TX_GPIO19 \ + ESP32_PINMUX(19, ESP_NOSIG, ESP_U1TXD_OUT) + +#define UART1_TX_GPIO20 \ + ESP32_PINMUX(20, ESP_NOSIG, ESP_U1TXD_OUT) + +#define UART1_TX_GPIO21 \ + ESP32_PINMUX(21, ESP_NOSIG, ESP_U1TXD_OUT) + +#define UART1_TX_GPIO22 \ + ESP32_PINMUX(22, ESP_NOSIG, ESP_U1TXD_OUT) + +#define UART1_TX_GPIO23 \ + ESP32_PINMUX(23, ESP_NOSIG, ESP_U1TXD_OUT) + + +#endif /* INC_DT_BINDS_PINCTRL_ESP32C6_PINCTRL_HAL_H_ */ From acdb468ad10e44033d6985d479d9e83581be0211 Mon Sep 17 00:00:00 2001 From: Marek Matej Date: Mon, 20 May 2024 21:27:02 +0200 Subject: [PATCH 2837/2849] soc: espressif: add esp32-c6 support Add basic support for esp32c6 SoC. Signed-off-by: Marek Matej --- soc/espressif/common/Kconfig.defconfig | 2 +- soc/espressif/common/Kconfig.flash | 2 +- soc/espressif/esp32c6/CMakeLists.txt | 74 +++ soc/espressif/esp32c6/Kconfig | 47 ++ soc/espressif/esp32c6/Kconfig.defconfig | 17 + soc/espressif/esp32c6/Kconfig.mac | 48 ++ soc/espressif/esp32c6/Kconfig.rtc | 50 ++ soc/espressif/esp32c6/Kconfig.soc | 29 + soc/espressif/esp32c6/default.ld | 807 ++++++++++++++++++++++++ soc/espressif/esp32c6/idle.c | 27 + soc/espressif/esp32c6/mcuboot.ld | 285 +++++++++ soc/espressif/esp32c6/memory.h | 62 ++ soc/espressif/esp32c6/pinctrl_soc.h | 76 +++ soc/espressif/esp32c6/soc.c | 96 +++ soc/espressif/esp32c6/soc.h | 62 ++ soc/espressif/esp32c6/soc_irq.S | 26 + soc/espressif/esp32c6/soc_irq.c | 67 ++ soc/espressif/esp32c6/vectors.S | 35 + soc/espressif/soc.yml | 3 + 19 files changed, 1813 insertions(+), 2 deletions(-) create mode 100644 soc/espressif/esp32c6/CMakeLists.txt create mode 100644 soc/espressif/esp32c6/Kconfig create mode 100644 soc/espressif/esp32c6/Kconfig.defconfig create mode 100644 soc/espressif/esp32c6/Kconfig.mac create mode 100644 soc/espressif/esp32c6/Kconfig.rtc create mode 100644 soc/espressif/esp32c6/Kconfig.soc create mode 100644 soc/espressif/esp32c6/default.ld create mode 100644 soc/espressif/esp32c6/idle.c create mode 100644 soc/espressif/esp32c6/mcuboot.ld create mode 100644 soc/espressif/esp32c6/memory.h create mode 100644 soc/espressif/esp32c6/pinctrl_soc.h create mode 100644 soc/espressif/esp32c6/soc.c create mode 100644 soc/espressif/esp32c6/soc.h create mode 100644 soc/espressif/esp32c6/soc_irq.S create mode 100644 soc/espressif/esp32c6/soc_irq.c create mode 100644 soc/espressif/esp32c6/vectors.S diff --git a/soc/espressif/common/Kconfig.defconfig b/soc/espressif/common/Kconfig.defconfig index e451dfaae64ce..381a7e357d40a 100644 --- a/soc/espressif/common/Kconfig.defconfig +++ b/soc/espressif/common/Kconfig.defconfig @@ -1,7 +1,7 @@ # Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. # SPDX-License-Identifier: Apache-2.0 -if SOC_SERIES_ESP32C3 +if SOC_SERIES_ESP32C3 || SOC_SERIES_ESP32C6 config GEN_ISR_TABLES default y diff --git a/soc/espressif/common/Kconfig.flash b/soc/espressif/common/Kconfig.flash index 2ed5d3f1b65a6..71eb970a2a95c 100644 --- a/soc/espressif/common/Kconfig.flash +++ b/soc/espressif/common/Kconfig.flash @@ -94,7 +94,7 @@ config BOOTLOADER_FLASH_XMC_SUPPORT choice BOOTLOADER_VDDSDIO_BOOST bool "VDDSDIO LDO voltage" default BOOTLOADER_VDDSDIO_BOOST_1_9V - depends on !SOC_SERIES_ESP32C3 + depends on !SOC_SERIES_ESP32C3 && !SOC_SERIES_ESP32C6 help If this option is enabled, and VDDSDIO LDO is set to 1.8V (using eFuse or MTDI bootstrapping pin), bootloader will change LDO settings to diff --git a/soc/espressif/esp32c6/CMakeLists.txt b/soc/espressif/esp32c6/CMakeLists.txt new file mode 100644 index 0000000000000..279a373adc17a --- /dev/null +++ b/soc/espressif/esp32c6/CMakeLists.txt @@ -0,0 +1,74 @@ +# SPDX-License-Identifier: Apache-2.0 + +zephyr_sources( + vectors.S + soc_irq.S + soc_irq.c + soc.c + ../common/loader.c + ) + +zephyr_include_directories(.) + +zephyr_library_sources_ifdef(CONFIG_PM power.c) +zephyr_library_sources_ifdef(CONFIG_POWEROFF poweroff.c) + +# get flash size to use in esptool as string +math(EXPR esptoolpy_flashsize "${CONFIG_FLASH_SIZE} / 0x100000") + +if(NOT CONFIG_BOOTLOADER_MCUBOOT) + + if(CONFIG_BUILD_OUTPUT_BIN) + # make ESP ROM loader compatible image + message("ESP-IDF path: ${ESP_IDF_PATH}") + + set(ESPTOOL_PY ${ESP_IDF_PATH}/tools/esptool_py/esptool.py) + message("esptool path: ${ESPTOOL_PY}") + + set(ELF2IMAGE_ARG "") + if(NOT CONFIG_MCUBOOT) + set(ELF2IMAGE_ARG "--ram-only-header") + endif() + + set_property(GLOBAL APPEND PROPERTY extra_post_build_commands + COMMAND ${PYTHON_EXECUTABLE} ${ESPTOOL_PY} + ARGS --chip esp32c6 elf2image ${ELF2IMAGE_ARG} + --flash_mode dio --flash_freq 40m --flash_size ${esptoolpy_flashsize}MB + -o ${CMAKE_BINARY_DIR}/zephyr/${CONFIG_KERNEL_BIN_NAME}.bin + ${CMAKE_BINARY_DIR}/zephyr/${CONFIG_KERNEL_BIN_NAME}.elf) + endif() + +endif() + +# get code-partition slot0 address +dt_nodelabel(dts_partition_path NODELABEL "slot0_partition") +dt_reg_addr(img_0_off PATH ${dts_partition_path}) + +# get code-partition boot address +dt_nodelabel(dts_partition_path NODELABEL "boot_partition") +dt_reg_addr(boot_off PATH ${dts_partition_path}) + +if(CONFIG_ESP_SIMPLE_BOOT) + board_finalize_runner_args(esp32 "--esp-app-address=${boot_off}") +else() + board_finalize_runner_args(esp32 "--esp-app-address=${img_0_off}") +endif() + +if(CONFIG_MCUBOOT) + # search from cross references between bootloader sections + message("check_callgraph using: ${ESP_IDF_PATH}/tools/ci/check_callgraph.py") + set_property(GLOBAL APPEND PROPERTY extra_post_build_commands + COMMAND + ${PYTHON_EXECUTABLE} ${ESP_IDF_PATH}/tools/ci/check_callgraph.py + ARGS + --rtl-dirs ${CMAKE_BINARY_DIR}/zephyr + --elf-file ${CMAKE_BINARY_DIR}/zephyr/${CONFIG_KERNEL_BIN_NAME}.elf + find-refs --from-section=.iram0.iram_loader --to-section=.iram0.text + --exit-code) +endif() + +if(CONFIG_MCUBOOT) + set(SOC_LINKER_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/mcuboot.ld CACHE INTERNAL "") +else() + set(SOC_LINKER_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/default.ld CACHE INTERNAL "") +endif() diff --git a/soc/espressif/esp32c6/Kconfig b/soc/espressif/esp32c6/Kconfig new file mode 100644 index 0000000000000..48aad9c0a4baf --- /dev/null +++ b/soc/espressif/esp32c6/Kconfig @@ -0,0 +1,47 @@ +# Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. +# SPDX-License-Identifier: Apache-2.0 + +config SOC_SERIES_ESP32C6 + select RISCV + select RISCV_GP + select DYNAMIC_INTERRUPTS + select CLOCK_CONTROL + select PINCTRL + select RISCV_ISA_RV32I + select RISCV_ISA_EXT_M + select RISCV_ISA_EXT_C + select RISCV_ISA_EXT_ZICSR + select HAS_ESPRESSIF_HAL + select XIP if !MCUBOOT + select HAS_PM + select HAS_POWEROFF + +if SOC_SERIES_ESP32C6 + +config IDF_TARGET_ESP32C6 + bool "ESP32C6 as target board" + default y + +config ESP32_PHY_MAX_WIFI_TX_POWER + int "Max WiFi TX power (dBm)" + range 10 20 + default 20 + help + Set maximum transmit power for WiFi radio. Actual transmit power for high + data rates may be lower than this setting. + +config ESP32_PHY_MAX_TX_POWER + int + default ESP32_PHY_MAX_WIFI_TX_POWER + +config MAC_BB_PD + bool "Power down MAC and baseband of Wi-Fi and Bluetooth when PHY is disabled" + depends on SOC_SERIES_ESP32C6 && TICKLESS_KERNEL + default n + help + If enabled, the MAC and baseband of Wi-Fi and Bluetooth will be powered + down when PHY is disabled. Enabling this setting reduces power consumption + by a small amount but increases RAM use by approximately 4 KB(Wi-Fi only), + 2 KB(Bluetooth only) or 5.3 KB(Wi-Fi + Bluetooth). + +endif # SOC_SERIES_ESP32C6 diff --git a/soc/espressif/esp32c6/Kconfig.defconfig b/soc/espressif/esp32c6/Kconfig.defconfig new file mode 100644 index 0000000000000..498f486b75c26 --- /dev/null +++ b/soc/espressif/esp32c6/Kconfig.defconfig @@ -0,0 +1,17 @@ +# ESP32C3 board configuration + +# Copyright (c) 2021 Espressif Systems (Shanghai) Co., Ltd. +# SPDX-License-Identifier: Apache-2.0 + +if SOC_SERIES_ESP32C6 + +config NUM_IRQS + default 77 + +config FLASH_SIZE + default $(dt_node_reg_size_int,/soc/flash-controller@60002000/flash@0,0) + +config FLASH_BASE_ADDRESS + default $(dt_node_reg_addr_hex,/soc/flash-controller@60002000/flash@0) + +endif # SOC_SERIES_ESP32C6 diff --git a/soc/espressif/esp32c6/Kconfig.mac b/soc/espressif/esp32c6/Kconfig.mac new file mode 100644 index 0000000000000..5078bef83520d --- /dev/null +++ b/soc/espressif/esp32c6/Kconfig.mac @@ -0,0 +1,48 @@ +# Copyright (c) 2024 Espressif Systems (Shanghai) Co., Ltd. +# SPDX-License-Identifier: Apache-2.0 + +if SOC_SERIES_ESP32C6 + +choice ESP32C6_UNIVERSAL_MAC_ADDRESSES + bool "Number of universally administered (by IEEE) MAC address" + default ESP32C6_UNIVERSAL_MAC_ADDRESSES_FOUR + help + Configure the number of universally administered (by IEEE) MAC addresses. + During initialization, MAC addresses for each network interface are generated or derived from a + single base MAC address. + If the number of universal MAC addresses is four, all four interfaces (WiFi station, WiFi softap, + Bluetooth and Ethernet) receive a universally administered MAC address. These are generated + sequentially by adding 0, 1, 2 and 3 (respectively) to the final octet of the base MAC address. + If the number of universal MAC addresses is two, only two interfaces (WiFi station and Bluetooth) + receive a universally administered MAC address. These are generated sequentially by adding 0 + and 1 (respectively) to the base MAC address. The remaining two interfaces (WiFi softap and Ethernet) + receive local MAC addresses. These are derived from the universal WiFi station and Bluetooth MAC + addresses, respectively. + When using the default (Espressif-assigned) base MAC address, either setting can be used. When using + a custom universal MAC address range, the correct setting will depend on the allocation of MAC + addresses in this range (either 2 or 4 per device.) + Note that ESP32-C6 has no integrated Ethernet MAC. Although it's possible to use the esp_read_mac() + API to return a MAC for Ethernet, this can only be used with an external MAC peripheral. + +config ESP32C6_UNIVERSAL_MAC_ADDRESSES_TWO + bool "Two" + select ESP_MAC_UNIVERSAL_MAC_ADDRESSES_TWO + select ESP_MAC_ADDR_UNIVERSE_WIFI_STA + select ESP_MAC_ADDR_UNIVERSE_BT + +config ESP32C6_UNIVERSAL_MAC_ADDRESSES_FOUR + bool "Four" + select ESP_MAC_UNIVERSAL_MAC_ADDRESSES_FOUR + select ESP_MAC_ADDR_UNIVERSE_WIFI_STA + select ESP_MAC_ADDR_UNIVERSE_WIFI_AP + select ESP_MAC_ADDR_UNIVERSE_BT + select ESP_MAC_ADDR_UNIVERSE_ETH + +endchoice # ESP32C6_UNIVERSAL_MAC_ADDRESSES + +config ESP32C6_UNIVERSAL_MAC_ADDRESSES + int + default 2 if ESP32C6_UNIVERSAL_MAC_ADDRESSES_TWO + default 4 if ESP32C6_UNIVERSAL_MAC_ADDRESSES_FOUR + +endif # SOC_SERIES_ESP32C6 diff --git a/soc/espressif/esp32c6/Kconfig.rtc b/soc/espressif/esp32c6/Kconfig.rtc new file mode 100644 index 0000000000000..2a9a864d01bd4 --- /dev/null +++ b/soc/espressif/esp32c6/Kconfig.rtc @@ -0,0 +1,50 @@ +# Copyright (c) 2024 Espressif Systems (Shanghai) Co., Ltd. +# SPDX-License-Identifier: Apache-2.0 + +if SOC_SERIES_ESP32C6 + +choice RTC_CLK_SRC + prompt "RTC clock source" + default RTC_CLK_SRC_INT_RC + help + Choose which clock is used as RTC clock source. + +config RTC_CLK_SRC_INT_RC + bool "Internal 136kHz RC oscillator" + +config RTC_CLK_SRC_EXT_CRYS + bool "External 32kHz crystal" + select ESP_SYSTEM_RTC_EXT_XTAL + +config RTC_CLK_SRC_EXT_OSC + bool "External 32kHz oscillator at 32K_XP pin" + select ESP_SYSTEM_RTC_EXT_OSC + +config RTC_CLK_SRC_INT_8MD256 + bool "Internal 17.5MHz oscillator, divided by 256" + +endchoice # ESP32C6_RTC_CLK_SRC + +config RTC_CLK_CAL_CYCLES + int "Number of cycles for RTC_SLOW_CLK calibration" + default 3000 if RTC_CLK_SRC_EXT_CRYS || RTC_CLK_SRC_EXT_OSC || RTC_CLK_SRC_INT_8MD256 + default 1024 if RTC_CLK_SRC_INT_RC + range 0 27000 if RTC_CLK_SRC_EXT_CRYS || RTC_CLK_SRC_EXT_OSC || RTC_CLK_SRC_INT_8MD256 + range 0 32766 if RTC_CLK_SRC_INT_RC + help + When the startup code initializes RTC_SLOW_CLK, it can perform + calibration by comparing the RTC_SLOW_CLK frequency with main XTAL + frequency. This option sets the number of RTC_SLOW_CLK cycles measured + by the calibration routine. Higher numbers increase calibration + precision, which may be important for applications which spend a lot of + time in deep sleep. Lower numbers reduce startup time. + + When this option is set to 0, clock calibration will not be performed at + startup, and approximate clock frequencies will be assumed: + + - 150000 Hz if internal RC oscillator is used as clock source. For this use value 1024. + - 32768 Hz if the 32k crystal oscillator is used. For this use value 3000 or more. + 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. + +endif # SOC_SERIES_ESP32C6 diff --git a/soc/espressif/esp32c6/Kconfig.soc b/soc/espressif/esp32c6/Kconfig.soc new file mode 100644 index 0000000000000..7e2e3295ebc3d --- /dev/null +++ b/soc/espressif/esp32c6/Kconfig.soc @@ -0,0 +1,29 @@ +# Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. +# SPDX-License-Identifier: Apache-2.0 + +config SOC_SERIES_ESP32C6 + bool + select SOC_FAMILY_ESPRESSIF_ESP32 + +config SOC_ESP32_C6_WROOM_1U_N4 + bool + select SOC_ESP32C6 + +config SOC_ESP32_C6_WROOM_1U_N8 + bool + select SOC_ESP32C6 + +config SOC_ESP32C6 + bool + select SOC_SERIES_ESP32C6 + +config SOC_SERIES + default "esp32c6" if SOC_SERIES_ESP32C6 + +config SOC + default "esp32c6" if SOC_SERIES_ESP32C6 + +config SOC_PART_NUMBER + default "ESP32_C6_WROOM_1U_N4" if SOC_ESP32_C6_WROOM_1U_N4 + default "ESP32_C6_WROOM_1U_N8" if SOC_ESP32_C6_WROOM_1U_N8 + default "ESP32C6" if SOC_ESP32C6 diff --git a/soc/espressif/esp32c6/default.ld b/soc/espressif/esp32c6/default.ld new file mode 100644 index 0000000000000..eda1381888409 --- /dev/null +++ b/soc/espressif/esp32c6/default.ld @@ -0,0 +1,807 @@ +/* + * Copyright (c) 2024 Espressif Systems (Shanghai) Co., Ltd. + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include + +#include "memory.h" + +/* The "user_sram_end" represents the 2nd stage bootloader + * "iram_loader_seg" start address (that should not be overlapped). + * If no bootloader is used, we can extend it to gain more user ram. + */ +#ifdef CONFIG_ESP_SIMPLE_BOOT +user_sram_end = DRAM_BUFFERS_START; +#else +user_sram_end = BOOTLOADER_IRAM_LOADER_SEG_START; +#endif + +/* User available memory segments */ +user_sram_org = HPSRAM_START; +user_sram_size = (user_sram_end - user_sram_org); + +/* Aliases */ +#define CACHED_REGION mmap0_0_seg +#define RAMABLE_REGION sram0_0_seg +#define ROMABLE_REGION FLASH + +/* Flash segments (rodata and text) should be mapped in the virtual address spaces. + * Executing directly from LMA is not possible. */ +#undef GROUP_ROM_LINK_IN +#define GROUP_ROM_LINK_IN(vregion, lregion) > CACHED_REGION AT > lregion + +/* TODO: add RTC support */ +#define RESERVE_RTC_MEM 0 + +/* Global symbols required for espressif hal build */ +MEMORY +{ +#ifdef CONFIG_BOOTLOADER_MCUBOOT + mcuboot_hdr (R): org = 0x0, len = 0x20 + metadata (R): org = 0x20, len = 0x20 + FLASH (R): org = 0x40, len = FLASH_SIZE - 0x40 +#else + /* Make safety margin in the FLASH memory size so the + * (esp_img_header + (n*esp_seg_headers)) would fit */ + FLASH (R): org = 0x0, len = FLASH_SIZE - 0x100 +#endif + + sram0_0_seg(RW): org = user_sram_org, len = user_sram_size + + mmap0_0_seg (R): org = CACHED_ORG, len = CACHED_SIZE + + lp_ram_seg(RW): org = LPSRAM_IRAM_START, + len = 0x4000 - RESERVE_RTC_MEM + + lp_reserved_seg(RW) : org = LPSRAM_IRAM_START + 0x4000 - RESERVE_RTC_MEM, + len = RESERVE_RTC_MEM + +#ifdef CONFIG_GEN_ISR_TABLES + IDT_LIST(RW): org = 0x3ebfe010, len = 0x2000 +#endif +} + +/* The lines below define location alias for .rtc.data section + * C6 has no distinguished LP(RTC) fast and slow memory sections, + * instead, there is a unified LP_RAM section + * Thus, the following region segments are + * not configurable like on other targets + */ +REGION_ALIAS("rtc_iram_seg", lp_ram_seg ); +REGION_ALIAS("rtc_data_seg", rtc_iram_seg ); +REGION_ALIAS("rtc_slow_seg", rtc_iram_seg ); +REGION_ALIAS("rtc_data_location", rtc_iram_seg ); +REGION_ALIAS("rtc_reserved_seg", lp_reserved_seg ); + +/* Default entry point: */ +ENTRY(CONFIG_KERNEL_ENTRY) + +SECTIONS +{ +#ifdef CONFIG_BOOTLOADER_MCUBOOT + /* Reserve space for MCUboot header in the binary */ + .mcuboot_header : + { + QUAD(0x0) + QUAD(0x0) + QUAD(0x0) + QUAD(0x0) + } > mcuboot_hdr + .metadata : + { + /* 0. Magic byte for load header */ + LONG(0xace637d3) + + /* 1. Application entry point address */ + KEEP(*(.entry_addr)) + + /* IRAM metadata: + * 2. Destination address (VMA) for IRAM region + * 3. Flash offset (LMA) for start of IRAM region + * 4. Size of IRAM region + */ + LONG(ADDR(.iram0.text)) + LONG(LOADADDR(.iram0.text)) + LONG(LOADADDR(.iram0.data) - LOADADDR(.iram0.text)) + + /* DRAM metadata: + * 5. Destination address (VMA) for DRAM region + * 6. Flash offset (LMA) for start of DRAM region + * 7. Size of DRAM region + */ + LONG(ADDR(.dram0.data)) + LONG(LOADADDR(.dram0.data)) + LONG(LOADADDR(.dram0.end) - LOADADDR(.dram0.data)) + } > metadata +#endif /* CONFIG_BOOTLOADER_MCUBOOT */ + + #include + + /* --- START OF RTC --- */ + + .rtc.text : + { + . = ALIGN(4); + *(.rtc.literal .rtc.text) + *rtc_wake_stub*.o(.literal .text .literal.* .text.*) + } GROUP_DATA_LINK_IN(rtc_iram_seg, ROMABLE_REGION) + + /* This section is required to skip rtc.text area because the text and + * data segments reflect the same address space on different buses. + */ + .rtc.dummy (NOLOAD): + { + . = SIZEOF(.rtc.text); + } GROUP_LINK_IN(rtc_iram_seg) + + .rtc.data : + { + _rtc_data_start = ABSOLUTE(.); + *(.rtc.data) + *(.rtc.rodata) + *rtc_wake_stub*.o(.data .rodata .data.* .rodata.* .bss .bss.*) + _rtc_data_end = ABSOLUTE(.); + } GROUP_DATA_LINK_IN(rtc_iram_seg, ROMABLE_REGION) + + .rtc.bss (NOLOAD) : + { + _rtc_bss_start = ABSOLUTE(.); + *rtc_wake_stub*.o(.bss .bss.*) + *rtc_wake_stub*.o(COMMON) + _rtc_bss_end = ABSOLUTE(.); + } GROUP_LINK_IN(rtc_iram_seg) + + /* This section located in RTC SLOW Memory area. + * It holds data marked with RTC_SLOW_ATTR attribute. + * See the file "esp_attr.h" for more information. + */ + .rtc.force_slow : + { + . = ALIGN(4); + _rtc_force_slow_start = ABSOLUTE(.); + *(.rtc.force_slow .rtc.force_slow.*) + . = ALIGN(4) ; + _rtc_force_slow_end = ABSOLUTE(.); + } > rtc_slow_seg + + /* Get size of rtc slow data */ + _rtc_slow_length = (_rtc_force_slow_end - _rtc_data_start); + + /* --- END OF RTC --- */ + + /* --- START OF IRAM --- */ + + .iram0.text : ALIGN(4) + { + /* Vectors go to IRAM */ + _iram_start = ABSOLUTE(.); + _init_start = ABSOLUTE(.); + + KEEP(*(.exception_vectors.text)); + . = ALIGN(256); + + _invalid_pc_placeholder = ABSOLUTE(.); + + KEEP(*(.exception.entry*)); /* contains _isr_wrapper */ + *(.exception.other*) + . = ALIGN(4); + + *(.entry.text) + *(.init.literal) + *(.init) + . = ALIGN(4); + + _init_end = ABSOLUTE(.); + _iram_text_start = ABSOLUTE(.); + + *(.iram1 .iram1.*) + *(.iram0.literal .iram.literal .iram.text.literal .iram0.text .iram.text) + *libzephyr.a:panic.*(.literal .text .literal.* .text.*) + *libzephyr.a:loader.*(.literal .text .literal.* .text.*) + *libarch__riscv__core.a:(.literal .text .literal.* .text.*) + *libsubsys__net__l2__ethernet.a:(.literal .text .literal.* .text.*) + *libsubsys__net__lib__config.a:(.literal .text .literal.* .text.*) + *libsubsys__net__ip.a:(.literal .text .literal.* .text.*) + *libsubsys__net.a:(.literal .text .literal.* .text.*) + *libkernel.a:(.literal .text .literal.* .text.*) + *libgcc.a:lib2funcs.*(.literal .text .literal.* .text.*) + *libdrivers__flash.a:flash_esp32.*(.literal .text .literal.* .text.*) + *libzephyr.a:spi_flash_rom_patch.*(.literal .text .literal.* .text.*) + *libzephyr.a:log_noos.*(.literal .text .literal.* .text.*) + *libdrivers__timer.a:esp32c6_sys_timer.*(.literal .text .literal.* .text.*) + *libzephyr.a:log_core.*(.literal .text .literal.* .text.*) + *libzephyr.a:cbprintf_complete.*(.literal .text .literal.* .text.*) + *libzephyr.a:printk.*(.literal.printk .literal.vprintk .literal.char_out .text.printk .text.vprintk .text.char_out) + *libzephyr.a:log_msg.*(.literal .text .literal.* .text.*) + *libzephyr.a:log_list.*(.literal .text .literal.* .text.*) + *libdrivers__console.a:uart_console.*(.literal.console_out .text.console_out) + *libzephyr.a:log_output.*(.literal .text .literal.* .text.*) + *libzephyr.a:log_backend_uart.*(.literal .text .literal.* .text.*) + *libzephyr.a:rtc_*.*(.literal .text .literal.* .text.*) + *liblib__libc__newlib.a:string.*(.literal .text .literal.* .text.*) + *liblib__libc__minimal.a:string.*(.literal .text .literal.* .text.*) + *liblib__libc__picolib.a:string.*(.literal .text .literal.* .text.*) + *libzephyr.a:periph_ctrl.*(.literal .text .literal.* .text.*) + *libgcov.a:(.literal .text .literal.* .text.*) + *libphy.a:( .phyiram .phyiram.*) + *libc.a:*(.literal .text .literal.* .text.*) + + /* [mapping:hal] */ + *libzephyr.a:mmu_hal.*(.literal .text .literal.* .text.*) + *libzephyr.a:spi_flash_hal_iram.*(.literal .literal.* .text .text.*) + *libzephyr.a:spi_flash_encrypt_hal_iram.*(.literal .text .literal.* .text.*) + *libzephyr.a:cache_hal.*(.literal .text .literal.* .text.*) + *libzephyr.a:ledc_hal_iram.*(.literal .text .literal.* .text.*) + *libzephyr.a:i2c_hal_iram.*(.literal .text .literal.* .text.*) + *libzephyr.a:wdt_hal_iram.*(.literal .text .literal.* .text.*) + *libzephyr.a:systimer_hal.*(.literal .text .literal.* .text.*) + *libzephyr.a:spi_flash_hal_gpspi.*(.literal .literal.* .text .text.*) + + /* [mapping:soc] */ + *libzephyr.a:lldesc.*(.literal .literal.* .text .text.*) + + /* [mapping:log] */ + *(.literal.esp_log_write .text.esp_log_write) + *(.literal.esp_log_timestamp .text.esp_log_timestamp) + *(.literal.esp_log_early_timestamp .text.esp_log_early_timestamp) + *(.literal.esp_log_impl_lock .text.esp_log_impl_lock) + *(.literal.esp_log_impl_lock_timeout .text.esp_log_impl_lock_timeout) + *(.literal.esp_log_impl_unlock .text.esp_log_impl_unlock) + + /* [mapping:spi_flash] */ + *libzephyr.a:spi_flash_chip_boya.*(.literal .literal.* .text .text.*) + *libzephyr.a:spi_flash_chip_gd.*(.literal .literal.* .text .text.*) + *libzephyr.a:spi_flash_chip_generic.*(.literal .literal.* .text .text.*) + *libzephyr.a:spi_flash_chip_issi.*(.literal .literal.* .text .text.*) + *libzephyr.a:spi_flash_chip_mxic.*(.literal .literal.* .text .text.*) + *libzephyr.a:spi_flash_chip_mxic_opi.*(.literal .literal.* .text .text.*) + *libzephyr.a:spi_flash_chip_th.*(.literal .literal.* .text .text.*) + *libzephyr.a:spi_flash_chip_winbond.*(.literal .literal.* .text .text.*) + *libzephyr.a:memspi_host_driver.*(.literal .literal.* .text .text.*) + *libzephyr.a:flash_brownout_hook.*(.literal .literal.* .text .text.*) + *libzephyr.a:spi_flash_wrap.*(.literal .literal.* .text .text.*) + *libzephyr.a:spi_flash_hpm_enable.*(.literal .literal.* .text .text.*) + *libzephyr.a:spi_flash_oct_flash_init*(.literal .literal.* .text .text.*) + + /* [mapping:esp_system] */ + *libzephyr.a:reset_reason.*(.literal .literal.* .text .text.*) + *libzephyr.a:esp_err.*(.literal .literal.* .text .text.*) + *(.literal.esp_system_abort .text.esp_system_abort) + + /* [mapping:esp_hw_support] */ + *(.literal.esp_cpu_stall .text.esp_cpu_stall) + *(.literal.esp_cpu_unstall .text.esp_cpu_unstall) + *(.literal.esp_cpu_reset .text.esp_cpu_reset) + *(.literal.esp_cpu_wait_for_intr .text.esp_cpu_wait_for_intr) + *(.literal.esp_cpu_compare_and_set .text.esp_cpu_compare_and_set) + *(.literal.esp_gpio_reserve_pins .text.esp_gpio_reserve_pins) + *(.literal.esp_gpio_is_pin_reserved .text.esp_gpio_is_pin_reserved) + *(.literal.rtc_vddsdio_get_config .text.rtc_vddsdio_get_config) + *(.literal.rtc_vddsdio_set_config .text.rtc_vddsdio_set_config) + *libzephyr.a:esp_memory_utils.*(.literal .literal.* .text .text.*) + *libzephyr.a:pmu_init.*(.literal .literal.* .text .text.*) + *libzephyr.a:rtc_clk.*(.literal .literal.* .text .text.*) + *libzephyr.a:rtc_clk_init.*(.literal .literal.* .text .text.*) + *libzephyr.a:rtc_time.*(.literal .literal.* .text .text.*) + *libzephyr.a:rtc_sleep.*(.literal .literal.* .text .text.*) + *libzephyr.a:systimer.*(.literal .literal.* .text .text.*) + *libzephyr.a:mspi_timing_config.*(.literal .literal.* .text .text.*) + *libzephyr.a:mspi_timing_tuning.*(.literal .literal.* .text .text.*) + *(.literal.sar_periph_ctrl_power_enable .text.sar_periph_ctrl_power_enable) + + /* [mapping:soc_pm] */ + *(.literal.GPIO_HOLD_MASK .text.GPIO_HOLD_MASK) + + /* [mapping:esp_rom] */ + *libzephyr.a:esp_rom_spiflash.*(.literal .literal.* .text .text.*) + *libzephyr.a:esp_rom_systimer.*(.literal .literal.* .text .text.*) + *libzephyr.a:esp_rom_wdt.*(.literal .literal.* .text .text.*) + + *libzephyr.a:esp_rom_crc.*(.literal .literal.* .text .text.*) + *libzephyr.a:esp_rom_sys.*(.literal .literal.* .text .text.*) + *libzephyr.a:esp_rom_uart.*(.literal .literal.* .text .text.*) + *libzephyr.a:esp_rom_spiflash.*(.literal .literal.* .text .text.*) + *libzephyr.a:esp_rom_efuse.*(.literal .literal.* .text .text.*) + *libzephyr.a:esp_rom_systimer.*(.literal .literal.* .text .text.*) + *libzephyr.a:esp_rom_regi2c_esp32c6.*(.literal .literal.* .text .text.*) + *libzephyr.a:efuse_hal.*(.literal .literal.* .text .text.*) + + /* [mapping:esp_mm] */ + *libzephyr.a:esp_cache.*(.literal .literal.* .text .text.*) + *libzephyr.a:cache_utils.*(.literal .text .literal.* .text.*) + +#if defined(CONFIG_ESP32_WIFI_IRAM_OPT) + *libnet80211.a:( .wifi0iram .wifi0iram.* .wifislpiram .wifislpiram.*) + *libpp.a:( .wifi0iram .wifi0iram.* .wifislpiram .wifislpiram.*) + *libcoexist.a:(.wifi_slp_iram .wifi_slp_iram.*) + + /* [mapping:esp_wifi] */ + *(.literal.wifi_clock_enable_wrapper .text.wifi_clock_enable_wrapper) + *(.literal.wifi_clock_disable_wrapper .text.wifi_clock_disable_wrapper) + + /* [mapping:esp_phy] */ + *(.literal.esp_phy_enable .text.esp_phy_enable) + *(.literal.esp_phy_disable .text.esp_phy_disable) + *(.literal.esp_wifi_bt_power_domain_off .text.esp_wifi_bt_power_domain_off) +#endif /* CONFIG_ESP32_WIFI_IRAM_OPT */ + +#if defined(CONFIG_ESP32_WIFI_RX_IRAM_OPT) + *libnet80211.a:( .wifirxiram .wifirxiram.* .wifislprxiram .wifislprxiram.*) + *libpp.a:( .wifirxiram .wifirxiram.* .wifislprxiram .wifislprxiram.*) +#endif /* CONFIG_ESP32_WIFI_RX_IRAM_OPT */ + + . = ALIGN(4) + 16; + } GROUP_DATA_LINK_IN(RAMABLE_REGION, ROMABLE_REGION) + +#ifdef CONFIG_ESP_SIMPLE_BOOT + .loader.text : + { + . = ALIGN(4); + _loader_text_start = ABSOLUTE(.); + *libzephyr.a:bootloader_soc.*(.literal .text .literal.* .text.*) + *libzephyr.a:bootloader_init.*(.literal .text .literal.* .text.*) + *libzephyr.a:bootloader_esp32c6.*(.literal .text .literal.* .text.*) + *libzephyr.a:bootloader_clock_init.*(.literal .text .literal.* .text.*) + *libzephyr.a:bootloader_wdt.*(.literal .text .literal.* .text.*) + *libzephyr.a:bootloader_flash.*(.literal .text .literal.* .text.*) + *libzephyr.a:bootloader_flash_config_esp32c6.*(.literal .text .literal.* .text.*) + *libzephyr.a:bootloader_clock_loader.*(.literal .text .literal.* .text.*) + *libzephyr.a:bootloader_common_loader.*(.literal .text .literal.* .text.*) + *libzephyr.a:bootloader_panic.*(.literal .text .literal.* .text.*) + *libzephyr.a:bootloader_mem.*(.literal .text .literal.* .text.*) + *libzephyr.a:bootloader_random.*(.literal .text .literal.* .text.*) + *libzephyr.a:bootloader_random*.*(.literal.bootloader_random_disable .text.bootloader_random_disable) + *libzephyr.a:bootloader_random*.*(.literal.bootloader_random_enable .text.bootloader_random_enable) + *libzephyr.a:bootloader_efuse.*(.literal .text .literal.* .text.*) + *libzephyr.a:bootloader_utility.*(.literal .text .literal.* .text.*) + *libzephyr.a:bootloader_sha.*(.literal .text .literal.* .text.*) + *libzephyr.a:bootloader_console.*(.literal .text .literal.* .text.*) + + *libzephyr.a:esp_image_format.*(.literal .text .literal.* .text.*) + *libzephyr.a:flash_ops.*(.literal .text .literal.* .text.*) + *libzephyr.a:flash_ops_esp32c6.*(.literal .text .literal.* .text.*) + *libzephyr.a:flash_encrypt.*(.literal .text .literal.* .text.*) + *libzephyr.a:flash_encryption_secure_features.*(.literal .text .literal.* .text.*) + *libzephyr.a:flash_partitions.*(.literal .text .literal.* .text.*) + *libzephyr.a:spi_flash_hal.*(.literal .literal.* .text .text.*) + *libzephyr.a:spi_flash_hal_common.*(.literal .literal.* .text .text.*) + *libzephyr.a:esp_flash_api.*(.literal .text .literal.* .text.*) + *libzephyr.a:esp_flash_spi_init.*(.literal .text .literal.* .text.*) + + *libzephyr.a:esp_efuse_table.*(.literal .text .literal.* .text.*) + *libzephyr.a:esp_efuse_fields.*(.literal .text .literal.* .text.*) + *libzephyr.a:esp_efuse_api.*(.literal .text .literal.* .text.*) + *libzephyr.a:esp_efuse_utility.*(.literal .text .literal.* .text.*) + *libzephyr.a:esp_efuse_api_key_esp32xx.*(.literal .text .literal.* .text.*) + *libzephyr.a:secure_boot.*(.literal .text .literal.* .text.*) + *libzephyr.a:secure_boot_secure_features.*(.literal .text .literal.* .text.*) + *libzephyr.a:secure_boot_signatures_bootloader.*(.literal .text .literal.* .text.*) + + *libzephyr.a:cpu_region_protect.*(.literal .text .literal.* .text.*) + + /* TODO: optimise */ + *libzephyr.a:esp_gpio_reserve.*(.literal .text .literal.* .text.*) + + . = ALIGN(4) + 16; + _loader_text_end = ABSOLUTE(.); + } GROUP_DATA_LINK_IN(RAMABLE_REGION, ROMABLE_REGION) +#endif /* CONFIG_ESP_SIMPLE_BOOT */ + + .iram0.text_end (NOLOAD) : + { + /* C3 memprot requires 512 B alignment for split lines */ + . = ALIGN(16); + _iram_text_end = ABSOLUTE(.); + } GROUP_LINK_IN(RAMABLE_REGION) + + .iram0.data : + { + . = ALIGN(16); + *(.iram.data) + *(.iram.data*) + } GROUP_DATA_LINK_IN(RAMABLE_REGION, ROMABLE_REGION) + + .iram0.bss (NOLOAD) : + { + . = ALIGN(16); + *(.iram.bss) + *(.iram.bss*) + + . = ALIGN(16); + _iram_end = ABSOLUTE(.); + . = ALIGN(16) + 16; + } GROUP_LINK_IN(RAMABLE_REGION) + + /* --- END OF IRAM --- */ + + /* --- START OF DRAM --- */ + + .dram0.data : + { + . = ALIGN(4); + _data_start = ABSOLUTE(.); + __data_start = ABSOLUTE(.); + + *(.data) + *(.data.*) + *(.gnu.linkonce.d.*) + *(.data1) + +#ifdef CONFIG_RISCV_GP + . = ALIGN(8); + __global_pointer$ = . + 0x800; +#endif /* CONFIG_RISCV_GP */ + + *(.sdata) + *(.sdata.*) + *(.gnu.linkonce.s.*) + *(.sdata2) + *(.sdata2.*) + *(.gnu.linkonce.s2.*) + + /* All dependent functions should be placed in DRAM to avoid issue + * when flash cache is disabled */ + *libkernel.a:fatal.*(.rodata .rodata.* .srodata .srodata.*) + *libkernel.a:init.*(.rodata .rodata.* .srodata .srodata.*) + *libzephyr.a:cbprintf_complete*(.rodata .rodata.* .srodata .srodata.*) + *libzephyr.a:log_core.*(.rodata .rodata.* .srodata .srodata.*) + *libzephyr.a:log_backend_uart.*(.rodata .rodata.* .srodata .srodata.*) + *libzephyr.a:log_output.*(.rodata .rodata.* .srodata .srodata.*) + *libdrivers__flash.a:flash_esp32.*(.rodata .rodata.* .srodata .srodata.*) + *libdrivers__serial.a:uart_esp32.*(.rodata .rodata.* .srodata .srodata.*) + *libzephyr.a:spi_flash_rom_patch.*(.rodata .rodata.* .srodata .srodata.*) + *libzephyr.a:periph_ctrl.*(.rodata .rodata.* .srodata .srodata.*) + *libzephyr.a:loader.*(.rodata .rodata.* .srodata .srodata.*) + *libzephyr.a:cache_utils.*(.rodata .rodata.* .srodata .srodata.*) + + /* [mapping:hal] */ + *libzephyr.a:mmu_hal.*(.rodata .rodata.* .srodata .srodata.*) + *libzephyr.a:spi_flash_hal_iram.*(.rodata .rodata.* .srodata .srodata.*) + *libzephyr.a:spi_flash_encrypt_hal_iram.*(.rodata .rodata.* .srodata .srodata.*) + *libzephyr.a:cache_hal.*(.rodata .rodata.* .srodata .srodata.*) + *libzephyr.a:ledc_hal_iram.*(.rodata .rodata.* .srodata .srodata.*) + *libzephyr.a:i2c_hal_iram.*(.rodata .rodata.* .srodata .srodata.*) + *libzephyr.a:wdt_hal_iram.*(.rodata .rodata.* .srodata .srodata.*) + *libzephyr.a:systimer_hal.*(.rodata .rodata.* .srodata .srodata.*) + *libzephyr.a:spi_flash_hal_gpspi.*(.rodata .rodata.* .srodata .srodata.*) + + /* [mapping:soc] */ + *libzephyr.a:lldesc.*(.rodata .rodata.* .srodata .srodata.*) + + /* [mapping:log] */ + *(.rodata.esp_log_write) + *(.rodata.esp_log_timestamp) + *(.rodata.esp_log_early_timestamp) + *(.rodata.esp_log_impl_lock) + *(.rodata.esp_log_impl_lock_timeout) + *(.rodata.esp_log_impl_unlock) + + /* [mapping:spi_flash] */ + *libzephyr.a:spi_flash_chip_boya.*(.rodata .rodata.* .srodata .srodata.*) + *libzephyr.a:spi_flash_chip_gd.*(.rodata .rodata.* .srodata .srodata.*) + *libzephyr.a:spi_flash_chip_generic.*(.rodata .rodata.* .srodata .srodata.*) + *libzephyr.a:spi_flash_chip_issi.*(.rodata .rodata.* .srodata .srodata.*) + *libzephyr.a:spi_flash_chip_mxic.*(.rodata .rodata.* .srodata .srodata.*) + *libzephyr.a:spi_flash_chip_mxic_opi.*(.rodata .rodata.* .srodata .srodata.*) + *libzephyr.a:spi_flash_chip_th.*(.rodata .rodata.* .srodata .srodata.*) + *libzephyr.a:spi_flash_chip_winbond.*(.rodata .rodata.* .srodata .srodata.*) + *libzephyr.a:memspi_host_driver.*(.rodata .rodata.* .srodata .srodata.*) + *libzephyr.a:flash_brownout_hook.*(.rodata .rodata.* .srodata .srodata.*) + *libzephyr.a:spi_flash_wrap.*(.rodata .rodata.* .srodata .srodata.*) + *libzephyr.a:spi_flash_hpm_enable.*(.rodata .rodata.* .srodata .srodata.*) + *libzephyr.a:spi_flash_oct_flash_init.*(.rodata .rodata.* .srodata .srodata.*) + + /* [mapping:esp_mm] */ + *libzephyr.a:esp_cache.*(.rodata .rodata.* .srodata .srodata.*) + + /* [mapping:esp_hw_support] */ + *(.rodata.esp_cpu_stall) + *(.rodata.esp_cpu_unstall) + *(.rodata.esp_cpu_reset) + *(.rodata.esp_cpu_wait_for_intr) + *(.rodata.esp_cpu_compare_and_set) + *(.rodata.esp_gpio_reserve_pins) + *(.rodata.esp_gpio_is_pin_reserved) + *(.rodata.rtc_vddsdio_get_config) + *(.rodata.rtc_vddsdio_set_config) + *libzephyr.a:esp_memory_utils.*(.rodata .rodata.* .srodata .srodata.*) + *libzephyr.a:rtc_clk.*(.rodata .rodata.* .srodata .srodata.*) + *libzephyr.a:rtc_clk_init.*(.rodata .rodata.* .srodata .srodata.*) + *libzephyr.a:systimer.*(.rodata .rodata.* .srodata .srodata.*) + *libzephyr.a:mspi_timing_config.*(.rodata .rodata.* .srodata .srodata.*) + *libzephyr.a:mspi_timing_tuning.*(.rodata .rodata.* .srodata .srodata.*) + *(.rodata.sar_periph_ctrl_power_enable) + *libzephyr.a:pmu_init.*(.rodata .rodata.* .srodata .srodata.*) + + /* [mapping:esp_system] */ + *libzephyr.a:reset_reason.*(.rodata .rodata.*) + *libzephyr.a:esp_err.*(.rodata .rodata.*) + *(.rodata.esp_system_abort) + + /* [mapping:esp_rom] */ + *libzephyr.a:esp_rom_crc.*(.rodata .rodata.* .srodata .srodata.*) + *libzephyr.a:esp_rom_sys.*(.rodata .rodata.* .srodata .srodata.*) + *libzephyr.a:esp_rom_uart.*(.rodata .rodata.* .srodata .srodata.*) + *libzephyr.a:esp_rom_spiflash.*(.rodata .rodata.* .srodata .srodata.*) + *libzephyr.a:esp_rom_efuse.*(.rodata .rodata.* .srodata .srodata.*) + *libzephyr.a:esp_rom_systimer.*(.rodata .rodata.* .srodata .srodata.*) + *libzephyr.a:esp_rom_regi2c_esp32c6.*(.rodata .rodata.* .srodata .srodata.*) + *libzephyr.a:efuse_hal.*(.rodata .rodata.* .srodata .srodata.*) + + . = ALIGN(4); + #include + . = ALIGN(4); + + KEEP(*(.jcr)) + *(.dram1 .dram1.*) + . = ALIGN(4); + } GROUP_DATA_LINK_IN(RAMABLE_REGION, ROMABLE_REGION) + +#ifdef CONFIG_ESP_SIMPLE_BOOT + /* Secondary loader sections */ + .loader.data : + { + . = ALIGN(4); + _loader_data_start = ABSOLUTE(.); + *libzephyr.a:bootloader_soc.*(.rodata .rodata.* .srodata .srodata.*) + *libzephyr.a:bootloader_init.*(.rodata .rodata.* .srodata .srodata.*) + *libzephyr.a:bootloader_esp32c6.*(.rodata .rodata.* .srodata .srodata.*) + *libzephyr.a:bootloader_clock_init.*(.rodata .rodata.* .srodata .srodata.*) + *libzephyr.a:bootloader_wdt.*(.rodata .rodata.* .srodata .srodata.*) + *libzephyr.a:bootloader_flash.*(.srodata .srodata.* .rodata .rodata.*) + *libzephyr.a:bootloader_flash_config_esp32c6.*(.rodata .rodata.* .srodata .srodata.*) + *libzephyr.a:bootloader_clock_loader.*(.rodata .rodata.* .srodata .srodata.*) + *libzephyr.a:bootloader_common_loader.*(.rodata .rodata.* .srodata .srodata.*) + *libzephyr.a:bootloader_panic.*(.rodata .rodata.* .srodata .srodata.*) + + *libzephyr.a:cpu_region_protect.*(.rodata .rodata.* .srodata .srodata.*) + *libzephyr.a:clk.*(.rodata .rodata.* .srodata .srodata.*) + *libzephyr.a:esp_clk.*(.rodata .rodata.* .srodata .srodata.*) + *libzephyr.a:flash_mmap.*(.rodata .rodata.* .srodata .srodata.*) + *libzephyr.a:flash_ops.*(.rodata .rodata.* .srodata .srodata.*) + *libzephyr.a:flash_ops_esp32c6.*(.rodata .rodata.* .srodata .srodata.*) + + *libzephyr.a:esp_gpio_reserve.*(.rodata .rodata.* .srodata .srodata.*) + *libzephyr.a:spi_flash_hal.*(.rodata .rodata.* .srodata .srodata.*) + *libzephyr.a:spi_flash_hal_common.*(.rodata .rodata.* .srodata .srodata.*) + *libzephyr.a:esp_flash_api.*(.rodata .rodata.* .srodata .srodata.*) + *libzephyr.a:esp_flash_spi_init.*(.rodata .rodata.* .srodata .srodata.*) + + . = ALIGN(16); + _loader_data_end = ABSOLUTE(.); + } GROUP_DATA_LINK_IN(RAMABLE_REGION, ROMABLE_REGION) +#endif /* CONFIG_ESP_SIMPLE_BOOT */ + + #include + #include + #include + #include + + /* logging sections should be placed in RAM area to avoid flash cache disabled issues */ + #pragma push_macro("GROUP_ROM_LINK_IN") + #undef GROUP_ROM_LINK_IN + #define GROUP_ROM_LINK_IN GROUP_DATA_LINK_IN + #include + #pragma pop_macro("GROUP_ROM_LINK_IN") + + .dram0.end : + { + . = ALIGN(4); + _data_end = ABSOLUTE(.); + __data_end = ABSOLUTE(.); + } GROUP_DATA_LINK_IN(RAMABLE_REGION, ROMABLE_REGION) + + .dram0.noinit (NOLOAD): + { + . = ALIGN(4); + *(.noinit) + *(.noinit.*) + . = ALIGN(4); + } GROUP_LINK_IN(RAMABLE_REGION) + + /* Shared RAM */ + .dram0.bss (NOLOAD) : + { + . = ALIGN (8); + __bss_start = ABSOLUTE(.); + _bss_start = ABSOLUTE(.); + + /* bluetooth library requires this symbol to be defined */ + _btdm_bss_start = ABSOLUTE(.); + *libbtdm_app.a:(.bss .bss.* COMMON) + . = ALIGN (4); + _btdm_bss_end = ABSOLUTE(.); + + *(.dynsbss) + *(.sbss) + *(.sbss.*) + *(.gnu.linkonce.sb.*) + *(.scommon) + *(.sbss2) + *(.sbss2.*) + *(.gnu.linkonce.sb2.*) + *(.dynbss) + *(.bss) + *(.bss.*) + *(.share.mem) + *(.gnu.linkonce.b.*) + *(COMMON) + . = ALIGN (16); + __bss_end = ABSOLUTE(.); + _bss_end = ABSOLUTE(.); + } GROUP_LINK_IN(RAMABLE_REGION) + + /* Provide total SRAM usage, including IRAM and DRAM */ + _image_ram_start = _iram_start; + #include + + ASSERT(((__bss_end - ORIGIN(sram0_0_seg)) <= LENGTH(sram0_0_seg)), "DRAM segment data does not fit.") + + /* --- END OF DRAM --- */ + + /* --- START OF .flash.text --- */ + + .flash.align_text (NOLOAD): + { + /* Subsequent segment lma align */ + . = ALIGN(CACHE_ALIGN); + } GROUP_LINK_IN(ROMABLE_REGION) + + /* Symbols used during the application memory mapping */ + _image_irom_start = LOADADDR(.flash.text); + _image_irom_size = SIZEOF(.flash.text); + _image_irom_vaddr = ADDR(.flash.text); + + .flash.text : ALIGN(0x10) + { + _stext = .; + _instruction_reserved_start = ABSOLUTE(.); + _text_start = ABSOLUTE(.); + _instruction_reserved_start = ABSOLUTE(.); + +#if !defined(CONFIG_ESP32_WIFI_IRAM_OPT) + *libnet80211.a:( .wifi0iram .wifi0iram.* .wifislpiram .wifislpiram.*) + *libpp.a:( .wifi0iram .wifi0iram.* .wifislpiram .wifislpiram.*) +#endif /* CONFIG_ESP32_WIFI_IRAM_OPT */ + +#if !defined(CONFIG_ESP32_WIFI_RX_IRAM_OPT) + *libnet80211.a:( .wifirxiram .wifirxiram.* .wifislprxiram .wifislprxiram.*) + *libpp.a:( .wifirxiram .wifirxiram.* .wifislprxiram .wifislprxiram.*) +#endif /* CONFIG_ESP32_WIFI_RX_IRAM_OPT */ + + *(.literal .text .literal.* .text.*) + *(.stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*) + *(.irom0.text) /* catch stray ICACHE_RODATA_ATTR */ + + *(.fini.literal) + *(.fini) + + *(.gnu.version) + + /** CPU will try to prefetch up to 16 bytes of + * of instructions. This means that any configuration (e.g. MMU, PMS) must allow + * safe access to up to 16 bytes after the last real instruction, add + * dummy bytes to ensure this + */ + . += 16; + + _instruction_reserved_end = ABSOLUTE(.); + _text_end = ABSOLUTE(.); + _instruction_reserved_end = ABSOLUTE(.); + _etext = .; + + } GROUP_DATA_LINK_IN(CACHED_REGION, ROMABLE_REGION) + + /* --- END OF .flash.text --- */ + + /* --- START OF .rodata --- */ + + /* Align next section to 64k to allow mapping */ + .flash.align_rodata (NOLOAD) : + { + /* Subsequent segment lma and vma align */ + . = ALIGN(CACHE_ALIGN); + } GROUP_DATA_LINK_IN(CACHED_REGION, ROMABLE_REGION) + + .flash.align_rom (NOLOAD) : + { + . = ALIGN(CACHE_ALIGN); + } GROUP_LINK_IN(ROMABLE_REGION) + + /* Symbols used during the application memory mapping */ + _image_drom_start = LOADADDR(.flash.rodata); + _image_drom_size = _image_rodata_end - _image_rodata_start; + _image_drom_vaddr = ADDR(.flash.rodata); + + .flash.rodata : ALIGN(0x10) + { + _rodata_reserved_start = ABSOLUTE(.); + _image_rodata_start = ABSOLUTE(.); + _rodata_start = ABSOLUTE(.); + + *(.rodata_desc .rodata_desc.*) + *(.rodata_custom_desc .rodata_custom_desc.*) + + __rodata_region_start = ABSOLUTE(.); + + . = ALIGN(4); + #include + + *(.irom1.text) /* catch stray ICACHE_RODATA_ATTR */ + *(.gnu.linkonce.r.*) + *(.rodata1) + __XT_EXCEPTION_TABLE_ = ABSOLUTE(.); + *(.xt_except_table) + *(.gcc_except_table .gcc_except_table.*) + *(.gnu.linkonce.e.*) + *(.gnu.version_r) + . = (. + 3) & ~ 3; + __eh_frame = ABSOLUTE(.); + KEEP(*(.eh_frame)) + . = (. + 7) & ~ 3; + + /* C++ exception handlers table: */ + __XT_EXCEPTION_DESCS_ = ABSOLUTE(.); + *(.xt_except_desc) + *(.gnu.linkonce.h.*) + __XT_EXCEPTION_DESCS_END__ = ABSOLUTE(.); + *(.xt_except_desc_end) + *(.dynamic) + *(.gnu.version_d) + __rodata_region_end = .; + _rodata_end = ABSOLUTE(.); + /* Literals are also RO data. */ + _lit4_start = ABSOLUTE(.); + *(*.lit4) + *(.lit4.*) + *(.gnu.linkonce.lit4.*) + _lit4_end = ABSOLUTE(.); + . = ALIGN(4); + *(.srodata) + *(.srodata.*) + *(.rodata) + *(.rodata.*) + *(.rodata_wlog) + *(.rodata_wlog*) + . = ALIGN(4); + } GROUP_DATA_LINK_IN(CACHED_REGION, ROMABLE_REGION) + + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + + /* Create an explicit section at the end of all the data that shall be mapped into drom. + * This is used to calculate the size of the _image_drom_size variable */ + .flash.rodata_end : ALIGN(0x10) + { + . = ALIGN(4); + _rodata_reserved_end = ABSOLUTE(.); + _image_rodata_end = ABSOLUTE(.); + } GROUP_DATA_LINK_IN(CACHED_REGION, ROMABLE_REGION) + + /* --- END OF .rodata --- */ + +#ifdef CONFIG_GEN_ISR_TABLES + #include +#endif + + #include + /DISCARD/ : { *(.note.GNU-stack) } + + SECTION_PROLOGUE(.riscv.attributes, 0,) + { + KEEP(*(.riscv.attributes)) + KEEP(*(.gnu.attributes)) + } +} diff --git a/soc/espressif/esp32c6/idle.c b/soc/espressif/esp32c6/idle.c new file mode 100644 index 0000000000000..a42691c540fba --- /dev/null +++ b/soc/espressif/esp32c6/idle.c @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +/** + * @brief Power save idle routine + * + * This function will be called by the kernel idle loop or possibly within + * an implementation of _pm_save_idle in the kernel when the + * '_pm_save_flag' variable is non-zero. + */ +void arch_cpu_idle(void) +{ + /* curiously it arrives here with the interrupts masked + * so umask it before wait for an event + */ + arch_irq_unlock(MSTATUS_IEN); + + /* Wait for interrupt */ + __asm__ volatile("wfi"); +} diff --git a/soc/espressif/esp32c6/mcuboot.ld b/soc/espressif/esp32c6/mcuboot.ld new file mode 100644 index 0000000000000..ac87f871847fd --- /dev/null +++ b/soc/espressif/esp32c6/mcuboot.ld @@ -0,0 +1,285 @@ +/* + * Copyright (c) 2024 Espressif Systems (Shanghai) Co., Ltd. + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include + +#include "memory.h" + +/* Disable all romable LMA */ +#undef GROUP_DATA_LINK_IN +#define GROUP_DATA_LINK_IN(vregion, lregion) > vregion + +#define RAMABLE_REGION dram_seg +#define RODATA_REGION dram_seg +#define ROMABLE_REGION dram_seg + +/* Global symbols required for espressif hal build */ +MEMORY +{ + iram_seg (RX) : org = BOOTLOADER_IRAM_SEG_START, + len = BOOTLOADER_IRAM_SEG_LEN + iram_loader_seg (RX) : org = BOOTLOADER_IRAM_LOADER_SEG_START, + len = BOOTLOADER_IRAM_LOADER_SEG_LEN + dram_seg (RW) : org = BOOTLOADER_DRAM_SEG_START, + len = BOOTLOADER_DRAM_SEG_LEN + +#ifdef CONFIG_GEN_ISR_TABLES + IDT_LIST(RW): org = 0x3ebfe010, len = 0x2000 +#endif +} + +/* Default entry point: */ +ENTRY(CONFIG_KERNEL_ENTRY) + +SECTIONS +{ + .iram0.loader_text : + { + . = ALIGN (16); + _loader_text_start = ABSOLUTE(.); + *(.stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*) + + *libapp.a:flash_map_extended.*(.literal .text .literal.* .text.*) + *libzephyr.a:cbprintf_nano.*(.literal .text .literal.* .text.*) + *libzephyr.a:cpu.*(.literal .text .literal.* .text.*) + *libzephyr.a:mmu_hal.*(.literal .text .literal.* .text.*) + *libzephyr.a:cache_hal.*(.literal .text .literal.* .text.*) + *libzephyr.a:flash_map.*(.literal .text .literal.* .text.*) + *libzephyr.a:esp_rom_spiflash.*(.literal .text .literal.* .text.*) + + *libzephyr.a:heap.*(.literal .text .literal.* .text.*) + + *libkernel.a:kheap.*(.literal .text .literal.* .text.*) + *libkernel.a:mempool.*(.literal .text .literal.* .text.*) + + *(.literal.bootloader_mmap .text.bootloader_mmap) + *(.literal.bootloader_munmap .text.bootloader_munmap) + + *libzephyr.a:esp_loader.*(.literal .text .literal.* .text.*) + *libzephyr.a:mmu_hal.*(.literal .text .literal.* .text.*) + + *(.literal.esp_intr_disable .literal.esp_intr_disable.* .text.esp_intr_disable .text.esp_intr_disable.*) + *(.literal.default_intr_handler .text.default_intr_handler .iram1.*.default_intr_handler) + *(.literal.esp_log_timestamp .text.esp_log_timestamp) + *(.literal.esp_log_early_timestamp .text.esp_log_early_timestamp) + *(.literal.esp_system_abort .text.esp_system_abort) + + *(.fini.literal) + *(.fini) + *(.gnu.version) + _loader_text_end = ABSOLUTE(.); + _iram_end = ABSOLUTE(.); + } > iram_loader_seg + + .iram0.text : + { + /* Vectors go to IRAM */ + _iram_start = ABSOLUTE(.); + _init_start = ABSOLUTE(.); + __text_region_start = ABSOLUTE(.); + + KEEP(*(.exception_vectors.text)); + . = ALIGN(256); + + _invalid_pc_placeholder = ABSOLUTE(.); + + _iram_text_start = ABSOLUTE(.); + + KEEP(*(.exception.entry*)); /* contains _isr_wrapper */ + *(.exception.other*) + . = ALIGN(4); + + *(.entry.text) + *(.init.literal) + *(.init) + . = ALIGN(4); + *(.iram1 .iram1.*) + *(.iram0.literal .iram.literal .iram.text.literal .iram0.text .iram.text) + + /* C3 memprot requires 512 B alignment for split lines */ + . = ALIGN (16); + _init_end = ABSOLUTE(.); + . = ALIGN(16); + *(.iram.data) + *(.iram.data*) + . = ALIGN(16); + *(.iram.bss) + *(.iram.bss*) + + . = ALIGN(16); + + *(.literal .text .literal.* .text.*) + *(.stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*) + *(.irom0.text) /* catch stray ICACHE_RODATA_ATTR */ + *(.fini.literal) + *(.fini) + *(.gnu.version) + + /* CPU will try to prefetch up to 16 bytes of + * of instructions. This means that any configuration (e.g. MMU, PMS) must allow + * safe access to up to 16 bytes after the last real instruction, add + * dummy bytes to ensure this + */ + . += 16; + + _text_end = ABSOLUTE(.); + __text_region_end = ABSOLUTE(.); + _etext = .; + + /* Similar to _iram_start, this symbol goes here so it is + * resolved by addr2line in preference to the first symbol in + * the flash.text segment. + */ + _flash_cache_start = ABSOLUTE(0); + } > iram_seg + + .dram0.data : + { + . = ALIGN(4); + __data_start = ABSOLUTE(.); + *(.data) + *(.data.*) + *(.gnu.linkonce.d.*) + *(.data1) +#ifdef CONFIG_RISCV_GP + __global_pointer$ = . + 0x800; +#endif /* CONFIG_RISCV_GP */ + *(.sdata) + *(.sdata.*) + *(.gnu.linkonce.s.*) + *(.sdata2) + *(.sdata2.*) + *(.gnu.linkonce.s2.*) + *libzephyr.a:mmu_hal.*(.rodata .rodata.*) + *libzephyr.a:rtc_clk.*(.rodata .rodata.*) + KEEP(*(.jcr)) + *(.dram1 .dram1.*) + . = ALIGN(4); + + #include + . = ALIGN(4); + + *(.rodata_desc .rodata_desc.*) + *(.rodata_custom_desc .rodata_custom_desc.*) + + . = ALIGN(4); + #include + . = ALIGN(4); + + *(.rodata) + *(.rodata.*) + *(.irom1.text) /* catch stray ICACHE_RODATA_ATTR */ + *(.gnu.linkonce.r.*) + *(.rodata1) + __XT_EXCEPTION_TABLE_ = ABSOLUTE(.); + *(.xt_except_table) + *(.gcc_except_table .gcc_except_table.*) + *(.gnu.linkonce.e.*) + *(.gnu.version_r) + . = (. + 3) & ~ 3; + __eh_frame = ABSOLUTE(.); + KEEP(*(.eh_frame)) + . = (. + 7) & ~ 3; + + /* C++ exception handlers table: */ + __XT_EXCEPTION_DESCS_ = ABSOLUTE(.); + *(.xt_except_desc) + *(.gnu.linkonce.h.*) + __XT_EXCEPTION_DESCS_END__ = ABSOLUTE(.); + *(.xt_except_desc_end) + *(.dynamic) + *(.gnu.version_d) + __rodata_region_end = .; + _rodata_end = ABSOLUTE(.); + /* Literals are also RO data. */ + _lit4_start = ABSOLUTE(.); + *(*.lit4) + *(.lit4.*) + *(.gnu.linkonce.lit4.*) + _lit4_end = ABSOLUTE(.); + . = ALIGN(4); + _thread_local_start = ABSOLUTE(.); + *(.tdata) + *(.tdata.*) + *(.tbss) + *(.tbss.*) + *(.srodata) + *(.srodata.*) + *(.rodata) + *(.rodata.*) + *(.rodata_wlog) + *(.rodata_wlog*) + _thread_local_end = ABSOLUTE(.); + /* _rodata_reserved_end = ABSOLUTE(.); */ + . = ALIGN(4); + } > dram_seg + + #include + #include + #include + #include + #include + + #include + #include + #include + #include + #include + #include + + #include + + .noinit (NOLOAD): + { + . = ALIGN(4); + *(.noinit) + *(.noinit.*) + . = ALIGN(4); + } > dram_seg + + /* Shared RAM */ + .bss (NOLOAD): + { + . = ALIGN (8); + _bss_start = ABSOLUTE(.); + __bss_start = ABSOLUTE(.); + *(.dynsbss) + *(.sbss) + *(.sbss.*) + *(.gnu.linkonce.sb.*) + *(.scommon) + *(.sbss2) + *(.sbss2.*) + *(.gnu.linkonce.sb2.*) + *(.dynbss) + *(.bss) + *(.bss.*) + *(.share.mem) + *(.gnu.linkonce.b.*) + *(COMMON) + . = ALIGN (8); + __bss_end = ABSOLUTE(.); + _bss_end = ABSOLUTE(.); + } > dram_seg + + /* linker rel sections*/ + #include + +#ifdef CONFIG_GEN_ISR_TABLES + #include +#endif + +#include + /DISCARD/ : { *(.note.GNU-stack) } + + SECTION_PROLOGUE(.riscv.attributes, 0,) + { + KEEP(*(.riscv.attributes)) + KEEP(*(.gnu.attributes)) + } +} diff --git a/soc/espressif/esp32c6/memory.h b/soc/espressif/esp32c6/memory.h new file mode 100644 index 0000000000000..500325545f09a --- /dev/null +++ b/soc/espressif/esp32c6/memory.h @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2024 Espressif Systems (Shanghai) Co., Ltd. + * SPDX-License-Identifier: Apache-2.0 + */ +#pragma once + +/* LP-SRAM (16kB) memory */ +#define LPSRAM_IRAM_START 0x50000000 +#define LPSRAM_SIZE 0x4000 +/* HP-SRAM (512kB) memory */ +#define HPSRAM_START 0x40800000 +#define HPSRAM_SIZE 0x80000 +#define HPSRAM_DRAM_START 0x40800000 +#define HPSRAM_IRAM_START 0x40800000 +/* ICache size is fixed to 32KB on ESP32-C6 */ +#define ICACHE_SIZE 0x8000 + +/** Simplified memory map for the bootloader. + * Make sure the bootloader can load into main memory without overwriting itself. + * + * ESP32-C6 ROM static data usage is as follows: + * - 0x4086ad08 - 0x4087c610: Shared buffers, used in UART/USB/SPI download mode only + * - 0x4087c610 - 0x4087e610: PRO CPU stack, can be reclaimed as heap after RTOS startup + * - 0x4087e610 - 0x40880000: ROM .bss and .data (not easily reclaimable) + * + * The 2nd stage bootloader can take space up to the end of ROM shared + * buffers area (0x4087c610). + */ + +#define DRAM_BUFFERS_START 0x4086ad08 +#define DRAM_STACK_START 0x4087c610 +#define DRAM_ROM_BSS_DATA_START 0x4087e610 + +/* For safety margin between bootloader data section and startup stacks */ +#define BOOTLOADER_STACK_OVERHEAD 0x0 +/* These lengths can be adjusted, if necessary: FIXME: optimize ram usage */ +#define BOOTLOADER_DRAM_SEG_LEN 0xA000 +#define BOOTLOADER_IRAM_LOADER_SEG_LEN 0x3000 +#define BOOTLOADER_IRAM_SEG_LEN 0xC000 + +/* Base address used for calculating memory layout + * counted from Dbus backwards and back to the Ibus + */ +#define BOOTLOADER_USER_SRAM_END (DRAM_BUFFERS_START - BOOTLOADER_STACK_OVERHEAD) + +/* Start of the lower region is determined by region size and the end of the higher region */ +#define BOOTLOADER_IRAM_LOADER_SEG_START \ + (BOOTLOADER_USER_SRAM_END - BOOTLOADER_IRAM_LOADER_SEG_LEN) +#define BOOTLOADER_IRAM_SEG_START (BOOTLOADER_IRAM_LOADER_SEG_START - BOOTLOADER_IRAM_SEG_LEN) +#define BOOTLOADER_DRAM_SEG_START (BOOTLOADER_IRAM_SEG_START - BOOTLOADER_DRAM_SEG_LEN) + +/* Flash */ +#ifdef CONFIG_FLASH_SIZE +#define FLASH_SIZE CONFIG_FLASH_SIZE +#else +#define FLASH_SIZE 0x400000 +#endif + +/* Cached memory */ +#define CACHE_ALIGN CONFIG_MMU_PAGE_SIZE +#define CACHED_ORG 0x42000000 +#define CACHED_SIZE FLASH_SIZE diff --git a/soc/espressif/esp32c6/pinctrl_soc.h b/soc/espressif/esp32c6/pinctrl_soc.h new file mode 100644 index 0000000000000..2a92315fc9e56 --- /dev/null +++ b/soc/espressif/esp32c6/pinctrl_soc.h @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2022 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * ESP32C6 SoC specific helpers for pinctrl driver + */ + +#ifndef ZEPHYR_SOC_RISCV_ESP32C6_PINCTRL_SOC_H_ +#define ZEPHYR_SOC_RISCV_ESP32C6_PINCTRL_SOC_H_ + +#include +#include + +#include + +/** @cond INTERNAL_HIDDEN */ + +/** Type for ESP32 pin. */ +typedef struct pinctrl_soc_pin { + /** Pinmux settings (pin, direction and signal). */ + uint32_t pinmux; + /** Pincfg settings (bias). */ + uint32_t pincfg; +} pinctrl_soc_pin_t; + +/** + * @brief Utility macro to initialize pinmux field in #pinctrl_pin_t. + * + * @param node_id Node identifier. + */ +#define Z_PINCTRL_ESP32_PINMUX_INIT(node_id, prop, idx) \ + DT_PROP_BY_IDX(node_id, prop, idx) + +/** + * @brief Utility macro to initialize pincfg field in #pinctrl_pin_t. + * + * @param node_id Node identifier. + */ +#define Z_PINCTRL_ESP32_PINCFG_INIT(node_id) \ + (((ESP32_NO_PULL * DT_PROP(node_id, bias_disable)) << ESP32_PIN_BIAS_SHIFT) | \ + ((ESP32_PULL_UP * DT_PROP(node_id, bias_pull_up)) << ESP32_PIN_BIAS_SHIFT) | \ + ((ESP32_PULL_DOWN * DT_PROP(node_id, bias_pull_down)) << ESP32_PIN_BIAS_SHIFT) | \ + ((ESP32_PUSH_PULL * DT_PROP(node_id, drive_push_pull)) << ESP32_PIN_DRV_SHIFT) | \ + ((ESP32_OPEN_DRAIN * DT_PROP(node_id, drive_open_drain)) << ESP32_PIN_DRV_SHIFT) | \ + ((ESP32_PIN_OUT_HIGH * DT_PROP(node_id, output_high)) << ESP32_PIN_OUT_SHIFT) | \ + ((ESP32_PIN_OUT_LOW * DT_PROP(node_id, output_low)) << ESP32_PIN_OUT_SHIFT)) + +/** + * @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) \ + { .pinmux = Z_PINCTRL_ESP32_PINMUX_INIT(node_id, prop, idx), \ + .pincfg = Z_PINCTRL_ESP32_PINCFG_INIT(node_id) }, + +/** + * @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)} + +/** @endcond */ + +#endif /* ZEPHYR_SOC_RISCV_ESP32C6_PINCTRL_SOC_H_ */ diff --git a/soc/espressif/esp32c6/soc.c b/soc/espressif/esp32c6/soc.c new file mode 100644 index 0000000000000..4bdfacbc0570e --- /dev/null +++ b/soc/espressif/esp32c6/soc.c @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* Include esp-idf headers first to avoid redefining BIT() macro */ +#include +#include +#include +#include +#include "hal/wdt_hal.h" +#include "esp_cpu.h" +#include "hal/soc_hal.h" +#include "hal/cpu_hal.h" +#include "esp_timer.h" +#include "esp_private/system_internal.h" +#include "esp_clk_internal.h" +#include +#include +#include "esp_private/esp_mmu_map_private.h" + +#include + +#include +#include +#include +#include +#include + +/* + * This is written in C rather than assembly since, during the port bring up, + * Zephyr is being booted by the Espressif bootloader. With it, the C stack + * is already set up. + */ +void IRAM_ATTR __esp_platform_start(void) +{ + __asm__ __volatile__("la t0, _esp32c6_vector_table\n" + "csrw mtvec, t0\n"); + + z_bss_zero(); + + /* Disable normal interrupts. */ + csr_read_clear(mstatus, MSTATUS_MIE); + + esp_reset_reason_init(); + +#ifndef CONFIG_MCUBOOT + /* ESP-IDF 2nd stage bootloader enables RTC WDT to check on startup sequence + * related issues in application. Hence disable that as we are about to start + * Zephyr environment. + */ + wdt_hal_context_t rtc_wdt_ctx = {.inst = WDT_RWDT, .rwdt_dev = &LP_WDT}; + + wdt_hal_write_protect_disable(&rtc_wdt_ctx); + wdt_hal_disable(&rtc_wdt_ctx); + wdt_hal_write_protect_enable(&rtc_wdt_ctx); + + /* Configures the CPU clock, RTC slow and fast clocks, and performs + * RTC slow clock calibration. + */ + esp_clk_init(); + + esp_timer_early_init(); + +#if CONFIG_SOC_FLASH_ESP32 + spi_flash_guard_set(&g_flash_guard_default_ops); +#endif + + esp_mmu_map_init(); + +#endif /* !CONFIG_MCUBOOT */ + + /*Initialize the esp32c6 interrupt controller */ + esp_intr_initialize(); + + /* Start Zephyr */ + z_cstart(); + + CODE_UNREACHABLE; +} + +/* Boot-time static default printk handler, possibly to be overridden later. */ +int IRAM_ATTR arch_printk_char_out(int c) +{ + if (c == '\n') { + esp_rom_uart_tx_one_char('\r'); + } + esp_rom_uart_tx_one_char(c); + return 0; +} + +void sys_arch_reboot(int type) +{ + esp_restart_noos(); +} diff --git a/soc/espressif/esp32c6/soc.h b/soc/espressif/esp32c6/soc.h new file mode 100644 index 0000000000000..bfa5644977751 --- /dev/null +++ b/soc/espressif/esp32c6/soc.h @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2024 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef __SOC_H__ +#define __SOC_H__ + +#ifndef _ASMLANGUAGE +#include +#include +#include +#include +#include +#include +#endif + +/* ECALL Exception numbers */ +#define SOC_MCAUSE_ECALL_EXP 11 /* Machine ECALL instruction */ +#define SOC_MCAUSE_USER_ECALL_EXP 8 /* User ECALL instruction */ + +/* Interrupt Mask */ +#define SOC_MCAUSE_IRQ_MASK (1 << 31) +/* Exception code Mask */ +#define SOC_MCAUSE_EXP_MASK 0x7FFFFFFF + +#ifndef _ASMLANGUAGE + +void __esp_platform_start(void); + +static inline uint32_t esp_core_id(void) +{ + return 0; +} + +extern void esp_reset_reason_init(void); +extern void esp_rom_route_intr_matrix(int cpu_no, uint32_t model_num, uint32_t intr_num); +extern void esp_rom_intr_matrix_set(int cpu_no, uint32_t model_num, uint32_t intr_num); +extern void esp_rom_uart_attach(void); +extern void esp_rom_uart_tx_wait_idle(uint8_t uart_no); +extern int esp_rom_uart_tx_one_char(uint8_t chr); +extern int esp_rom_gpio_matrix_in(uint32_t gpio, uint32_t signal_index, + bool inverted); +extern int esp_rom_gpio_matrix_out(uint32_t gpio, uint32_t signal_index, + bool out_inverted, + bool out_enabled_inverted); +extern void esp_rom_ets_set_user_start(uint32_t start); +extern void esprv_intc_int_set_threshold(int priority_threshold); +uint32_t soc_intr_get_next_source(void); +extern void esp_rom_Cache_Resume_ICache(uint32_t autoload); +extern int esp_rom_Cache_Invalidate_Addr(uint32_t addr, uint32_t size); +extern uint32_t esp_rom_Cache_Suspend_ICache(void); +extern void esp_rom_Cache_Invalidate_ICache_All(void); +extern int esp_rom_Cache_Dbus_MMU_Set(uint32_t ext_ram, uint32_t vaddr, uint32_t paddr, + uint32_t psize, uint32_t num, uint32_t fixed); +extern int esp_rom_Cache_Ibus_MMU_Set(uint32_t ext_ram, uint32_t vaddr, uint32_t paddr, + uint32_t psize, uint32_t num, uint32_t fixed); + +#endif /* _ASMLANGUAGE */ + +#endif /* __SOC_H__ */ diff --git a/soc/espressif/esp32c6/soc_irq.S b/soc/espressif/esp32c6/soc_irq.S new file mode 100644 index 0000000000000..c1ad164c1536b --- /dev/null +++ b/soc/espressif/esp32c6/soc_irq.S @@ -0,0 +1,26 @@ +/* Copyright 2021 Espressif Systems (Shanghai) PTE LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +/* Exports */ +GTEXT(__soc_is_irq) +GTEXT(__soc_handle_irq) +GTEXT(soc_intr_get_next_source) + +SECTION_FUNC(exception.other, __soc_is_irq) + csrr a0, mcause + srli a0, a0, 31 + ret + +SECTION_FUNC(exception.other, __soc_handle_irq) + addi sp, sp,-4 + sw ra, 0x00(sp) + la t1, soc_intr_get_next_source + jalr ra, t1, 0 + lw ra, 0x00(sp) + addi sp, sp, 4 + ret diff --git a/soc/espressif/esp32c6/soc_irq.c b/soc/espressif/esp32c6/soc_irq.c new file mode 100644 index 0000000000000..42e5e47eaf2f2 --- /dev/null +++ b/soc/espressif/esp32c6/soc_irq.c @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#define ESP32C6_INTSTATUS_SLOT1_THRESHOLD 32 + +void arch_irq_enable(unsigned int irq) +{ + esp_intr_enable(irq); +} + +void arch_irq_disable(unsigned int irq) +{ + esp_intr_disable(irq); +} + +int arch_irq_is_enabled(unsigned int irq) +{ + bool res = false; + uint32_t key = irq_lock(); + + if (irq < 32) { + res = esp_intr_get_enabled_intmask(0) & BIT(irq); + } else { + res = esp_intr_get_enabled_intmask(1) & BIT(irq - 32); + } + + irq_unlock(key); + + return res; +} + +uint32_t soc_intr_get_next_source(void) +{ + uint32_t status; + uint32_t source; + + status = REG_READ(INTMTX_CORE0_INT_STATUS_REG_0_REG) & + esp_intr_get_enabled_intmask(0); + + if (status) { + source = __builtin_ffs(status) - 1; + } else { + status = REG_READ(INTMTX_CORE0_INT_STATUS_REG_1_REG) & + esp_intr_get_enabled_intmask(1); + source = (__builtin_ffs(status) - 1 + ESP32C6_INTSTATUS_SLOT1_THRESHOLD); + } + + return source; +} diff --git a/soc/espressif/esp32c6/vectors.S b/soc/espressif/esp32c6/vectors.S new file mode 100644 index 0000000000000..d248c0b49b51c --- /dev/null +++ b/soc/espressif/esp32c6/vectors.S @@ -0,0 +1,35 @@ +/* Copyright 2023 Espressif Systems (Shanghai) PTE LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "soc/soc.h" +#include "soc/interrupt_reg.h" +#include "riscv/rvruntime-frames.h" +#include "soc/soc_caps.h" +#include + +/* Imports */ +GTEXT(_isr_wrapper) + + /* This is the vector table. MTVEC points here. + * + * Use 4-byte intructions here. 1 instruction = 1 entry of the table. + * The CPU jumps to MTVEC (i.e. the first entry) in case of an exception, + * and (MTVEC & 0xfffffffc) + (mcause & 0x7fffffff) * 4, in case of an interrupt. + * + * Note: for our CPU, we need to place this on a 256-byte boundary, as CPU + * only uses the 24 MSBs of the MTVEC, i.e. (MTVEC & 0xffffff00). + */ + + .global _esp32c6_vector_table + .section .exception_vectors.text + .balign 0x100 + .type _esp32c6_vector_table, @function + +_esp32c6_vector_table: + .option push + .option norvc + .rept (32) + j _isr_wrapper /* 32 identical entries, all pointing to the interrupt handler */ + .endr diff --git a/soc/espressif/soc.yml b/soc/espressif/soc.yml index 13f6092e311a8..c553b3e9aed39 100644 --- a/soc/espressif/soc.yml +++ b/soc/espressif/soc.yml @@ -19,3 +19,6 @@ family: - name: esp32c3 socs: - name: esp32c3 + - name: esp32c6 + socs: + - name: esp32c6 From 3e61050612b4745b4fb45fd6f7f7449f8b93202b Mon Sep 17 00:00:00 2001 From: Lucas Tamborrino Date: Wed, 7 Jun 2023 08:42:57 -0300 Subject: [PATCH 2838/2849] dts: riscv: espressif: add esp32c6 Add esp32c6 basic device tree. Signed-off-by: Lucas Tamborrino --- .../espressif/esp32c6/esp32c6_common.dtsi | 125 ++++++++++++++++++ .../espressif/esp32c6/esp32c6_wroom_n4.dtsi | 12 ++ .../espressif/esp32c6/esp32c6_wroom_n8.dtsi | 12 ++ 3 files changed, 149 insertions(+) create mode 100644 dts/riscv/espressif/esp32c6/esp32c6_common.dtsi create mode 100644 dts/riscv/espressif/esp32c6/esp32c6_wroom_n4.dtsi create mode 100644 dts/riscv/espressif/esp32c6/esp32c6_wroom_n8.dtsi diff --git a/dts/riscv/espressif/esp32c6/esp32c6_common.dtsi b/dts/riscv/espressif/esp32c6/esp32c6_common.dtsi new file mode 100644 index 0000000000000..175921df6bcdd --- /dev/null +++ b/dts/riscv/espressif/esp32c6/esp32c6_common.dtsi @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#include +#include +#include +#include + +/ { + #address-cells = <1>; + #size-cells = <1>; + + chosen { + zephyr,flash-controller = &flash; + }; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu0: cpu@0 { + device_type = "cpu"; + compatible = "espressif,riscv"; + riscv,isa = "rv32imc_zicsr"; + reg = <0>; + }; + }; + + pinctrl: pin-controller { + compatible = "espressif,esp32-pinctrl"; + status = "okay"; + }; + + soc { + #address-cells = <1>; + #size-cells = <1>; + compatible = "simple-bus"; + ranges; + + sram0: memory@40800000 { + compatible = "mmio-sram"; + reg = <0x40800000 0x50000>; + }; + + intc: interrupt-controller@60010000 { + compatible = "espressif,esp32-intc"; + #address-cells = <0>; + #interrupt-cells = <1>; + interrupt-controller; + reg = <0x60010000 DT_SIZE_K(4)>; + status = "okay"; + }; + + systimer0: systimer@6000a000 { + compatible = "espressif,esp32-systimer"; + reg = <0x6000A000 DT_SIZE_K(4)>; + interrupts = ; + interrupt-parent = <&intc>; + status = "okay"; + }; + + rtc: rtc@600b000 { + compatible = "espressif,esp32-rtc"; + reg = <0x600B000 DT_SIZE_K(1)>; + xtal-freq = ; + #clock-cells = <1>; + status = "okay"; + + rtc_timer: rtc_timer { + compatible = "espressif,esp32-rtc-timer"; + slow-clk-freq = ; + interrupts = ; + interrupt-parent = <&intc>; + status = "okay"; + }; + }; + + flash: flash-controller@60002000 { + compatible = "espressif,esp32-flash-controller"; + reg = <0x60002000 0x1000>; + + #address-cells = <1>; + #size-cells = <1>; + + flash0: flash@0 { + compatible = "soc-nv-flash"; + erase-block-size = <4096>; + write-block-size = <4>; + }; + }; + + gpio0: gpio@60091000 { + compatible = "espressif,esp32-gpio"; + gpio-controller; + #gpio-cells = <2>; + reg = <0x60091000 DT_SIZE_K(4)>; + interrupts = ; + interrupt-parent = <&intc>; + ngpios = <30>; /* 0..29 */ + }; + + uart0: uart@60000000 { + compatible = "espressif,esp32-uart"; + reg = <0x60000000 DT_SIZE_K(4)>; + status = "disabled"; + interrupts = ; + interrupt-parent = <&intc>; + clocks = <&rtc ESP32_UART0_MODULE>; + }; + + uart1: uart@60010000 { + compatible = "espressif,esp32-uart"; + reg = <0x60010000 DT_SIZE_K(4)>; + status = "disabled"; + interrupts = ; + interrupt-parent = <&intc>; + clocks = <&rtc ESP32_UART1_MODULE>; + current-speed = <115200>; + }; + }; + +}; diff --git a/dts/riscv/espressif/esp32c6/esp32c6_wroom_n4.dtsi b/dts/riscv/espressif/esp32c6/esp32c6_wroom_n4.dtsi new file mode 100644 index 0000000000000..062bb06621ca8 --- /dev/null +++ b/dts/riscv/espressif/esp32c6/esp32c6_wroom_n4.dtsi @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + + #include "esp32c6_common.dtsi" + +/* 4MB flash */ +&flash0 { + reg = <0x0 DT_SIZE_M(4)>; +}; diff --git a/dts/riscv/espressif/esp32c6/esp32c6_wroom_n8.dtsi b/dts/riscv/espressif/esp32c6/esp32c6_wroom_n8.dtsi new file mode 100644 index 0000000000000..71af7e15320ed --- /dev/null +++ b/dts/riscv/espressif/esp32c6/esp32c6_wroom_n8.dtsi @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + + #include "esp32c6_common.dtsi" + +/* 8MB flash */ +&flash0 { + reg = <0x0 DT_SIZE_M(8)>; +}; From aa1f06be146b9c1292033be99feadd744fca8237 Mon Sep 17 00:00:00 2001 From: Lucas Tamborrino Date: Wed, 7 Jun 2023 08:57:32 -0300 Subject: [PATCH 2839/2849] boards: espressif: esp32c6: add esp32c6_devkitc Add esp32c6_devkitc basic support. Signed-off-by: Lucas Tamborrino --- .../esp32c6_devkitc/Kconfig.defconfig | 9 + .../esp32c6_devkitc/Kconfig.esp32c6_devkitc | 7 + .../esp32c6_devkitc/Kconfig.sysbuild | 10 + boards/espressif/esp32c6_devkitc/board.cmake | 9 + boards/espressif/esp32c6_devkitc/board.yml | 5 + .../espressif/esp32c6_devkitc/doc/index.rst | 274 ++++++++++++++++++ .../esp32c6_devkitc-pinctrl.dtsi | 23 ++ .../esp32c6_devkitc/esp32c6_devkitc.dts | 89 ++++++ .../esp32c6_devkitc/esp32c6_devkitc.yaml | 14 + .../esp32c6_devkitc/esp32c6_devkitc_defconfig | 7 + .../esp32c6_devkitc/support/openocd.cfg | 4 + 11 files changed, 451 insertions(+) create mode 100644 boards/espressif/esp32c6_devkitc/Kconfig.defconfig create mode 100644 boards/espressif/esp32c6_devkitc/Kconfig.esp32c6_devkitc create mode 100644 boards/espressif/esp32c6_devkitc/Kconfig.sysbuild create mode 100644 boards/espressif/esp32c6_devkitc/board.cmake create mode 100644 boards/espressif/esp32c6_devkitc/board.yml create mode 100644 boards/espressif/esp32c6_devkitc/doc/index.rst create mode 100644 boards/espressif/esp32c6_devkitc/esp32c6_devkitc-pinctrl.dtsi create mode 100644 boards/espressif/esp32c6_devkitc/esp32c6_devkitc.dts create mode 100644 boards/espressif/esp32c6_devkitc/esp32c6_devkitc.yaml create mode 100644 boards/espressif/esp32c6_devkitc/esp32c6_devkitc_defconfig create mode 100644 boards/espressif/esp32c6_devkitc/support/openocd.cfg diff --git a/boards/espressif/esp32c6_devkitc/Kconfig.defconfig b/boards/espressif/esp32c6_devkitc/Kconfig.defconfig new file mode 100644 index 0000000000000..b3b9bbf6ec113 --- /dev/null +++ b/boards/espressif/esp32c6_devkitc/Kconfig.defconfig @@ -0,0 +1,9 @@ +# ESP32C6 devkitc board configuration + +# Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. +# SPDX-License-Identifier: Apache-2.0 + +config HEAP_MEM_POOL_SIZE + default 98304 if WIFI + default 40960 if BT + default 4096 diff --git a/boards/espressif/esp32c6_devkitc/Kconfig.esp32c6_devkitc b/boards/espressif/esp32c6_devkitc/Kconfig.esp32c6_devkitc new file mode 100644 index 0000000000000..b2fbfc946affc --- /dev/null +++ b/boards/espressif/esp32c6_devkitc/Kconfig.esp32c6_devkitc @@ -0,0 +1,7 @@ +# ESP32C6 devkitc board configuration + +# Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. +# SPDX-License-Identifier: Apache-2.0 + +config BOARD_ESP32C6_DEVKITC + select SOC_ESP32_C6_WROOM_1U_N8 diff --git a/boards/espressif/esp32c6_devkitc/Kconfig.sysbuild b/boards/espressif/esp32c6_devkitc/Kconfig.sysbuild new file mode 100644 index 0000000000000..3a2d17ac5cfd0 --- /dev/null +++ b/boards/espressif/esp32c6_devkitc/Kconfig.sysbuild @@ -0,0 +1,10 @@ +# Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. +# SPDX-License-Identifier: Apache-2.0 + +choice BOOTLOADER + default BOOTLOADER_MCUBOOT +endchoice + +choice BOOT_SIGNATURE_TYPE + default BOOT_SIGNATURE_TYPE_NONE +endchoice diff --git a/boards/espressif/esp32c6_devkitc/board.cmake b/boards/espressif/esp32c6_devkitc/board.cmake new file mode 100644 index 0000000000000..2f04d1fe8861e --- /dev/null +++ b/boards/espressif/esp32c6_devkitc/board.cmake @@ -0,0 +1,9 @@ +# SPDX-License-Identifier: Apache-2.0 + +if(NOT "${OPENOCD}" MATCHES "^${ESPRESSIF_TOOLCHAIN_PATH}/.*") + set(OPENOCD OPENOCD-NOTFOUND) +endif() +find_program(OPENOCD openocd PATHS ${ESPRESSIF_TOOLCHAIN_PATH}/openocd-esp32/bin NO_DEFAULT_PATH) + +include(${ZEPHYR_BASE}/boards/common/esp32.board.cmake) +include(${ZEPHYR_BASE}/boards/common/openocd.board.cmake) diff --git a/boards/espressif/esp32c6_devkitc/board.yml b/boards/espressif/esp32c6_devkitc/board.yml new file mode 100644 index 0000000000000..ad88f3a931573 --- /dev/null +++ b/boards/espressif/esp32c6_devkitc/board.yml @@ -0,0 +1,5 @@ +board: + name: esp32c6_devkitc + vendor: espressif + socs: + - name: esp32c6 diff --git a/boards/espressif/esp32c6_devkitc/doc/index.rst b/boards/espressif/esp32c6_devkitc/doc/index.rst new file mode 100644 index 0000000000000..9eb87fe2a8acf --- /dev/null +++ b/boards/espressif/esp32c6_devkitc/doc/index.rst @@ -0,0 +1,274 @@ +.. _esp32c6_devkitc: + +ESP32-C6-DevKitC-1 +################## + +Overview +******** + +ESP32-C6 is Espressif's first Wi-Fi 6 SoC integrating 2.4 GHz Wi-Fi 6, Bluetooth 5.3 (LE) and the +802.15.4 protocol. ESP32-C6 achieves an industry-leading RF performance, with reliable security +features and multiple memory resources for IoT products. +It consists of a high-performance (HP) 32-bit RISC-V processor, which can be clocked up to 160 MHz, +and a low-power (LP) 32-bit RISC-V processor, which can be clocked up to 20 MHz. +It has a 320KB ROM, a 512KB SRAM, and works with external flash. [1]_ + +ESP32-C6-DevKitC-1 is an entry-level development board based on ESP32-C6-WROOM-1(U), +a general-purpose module with a 8 MB SPI flash. + +Most of the I/O pins are broken out to the pin headers on both sides for easy interfacing. +Developers can either connect peripherals with jumper wires or mount ESP32-C6-DevKitC-1 on +a breadboard. [2]_ + +ESP32-C6 includes the following features: + +- 32-bit core RISC-V microcontroller with a clock speed of up to 160 MHz +- 400 KB of internal RAM +- WiFi 802.11 ax 2.4GHz +- Fully compatible with IEEE 802.11b/g/n protocol +- Bluetooth LE: Bluetooth 5.3 certified +- Internal co-existence mechanism between Wi-Fi and Bluetooth to share the same antenna +- IEEE 802.15.4 (Zigbee and Thread) + +Digital interfaces: + +- 30x GPIOs (QFN40), or 22x GPIOs (QFN32) +- 2x UART +- 1x Low-power (LP) UART +- 1x General purpose SPI +- 1x I2C +- 1x Low-power (LP) I2C +- 1x I2S +- 1x Pulse counter +- 1x USB Serial/JTAG controller +- 1x TWAI® controller, compatible with ISO 11898-1 (CAN Specification 2.0) +- 1x SDIO 2.0 slave controller +- LED PWM controller, up to 6 channels +- 1x Motor control PWM (MCPWM) +- 1x Remote control peripehral +- 1x Parallel IO interface (PARLIO) +- General DMA controller (GDMA), with 3 transmit channels and 3 receive channels +- Event task matrix (ETM) + +Analog interfaces: + +- 1x 12-bit SAR ADCs, up to 7 channels +- 1x temperature sensor + +Timers: + +- 1x 52-bit system timer +- 1x 54-bit general-purpose timers +- 3x Watchdog timers +- 1x Analog watchdog timer + +Low Power: + +- Four power modes designed for typical scenarios: Active, Modem-sleep, Light-sleep, Deep-sleep + +Security: + +- Secure boot +- Flash encryption +- 4-Kbit OTP, up to 1792 bits for users +- Cryptographic hardware acceleration: (AES-128/256, ECC, HMAC, RSA, SHA, Digital signature, Hash) +- Random number generator (RNG) + +For more information, check the datasheet at `ESP32C6 Datasheet`_ + +Supported Features +================== + +Current Zephyr's ESP32-C6-DevKitC board supports the following features: + ++------------+------------+-------------------------------------+ +| Interface | Controller | Driver/Component | ++============+============+=====================================+ +| UART | on-chip | serial port | ++------------+------------+-------------------------------------+ +| GPIO | on-chip | gpio | ++------------+------------+-------------------------------------+ +| PINMUX | on-chip | pinmux | ++------------+------------+-------------------------------------+ +| USB-JTAG | on-chip | hardware interface | ++------------+------------+-------------------------------------+ +| SPI Master | on-chip | spi | ++------------+------------+-------------------------------------+ +| Watchdog | on-chip | watchdog | ++------------+------------+-------------------------------------+ +| LEDC | on-chip | pwm | ++------------+------------+-------------------------------------+ +| SPI DMA | on-chip | spi | ++------------+------------+-------------------------------------+ + +System requirements +******************* + +Prerequisites +============= + +Espressif HAL requires WiFi and Bluetooth binary blobs in order work. Run the command +below to retrieve those files. + +.. code-block:: console + + west blobs fetch hal_espressif + +.. note:: + + It is recommended running the command above after :file:`west update`. + +Building & Flashing +******************* + +Simple boot +=========== + +The board could be loaded using the single binary image, without 2nd stage bootloader. +It is the default option when building the application without additional configuration. + +.. note:: + + Simple boot does not provide any security features nor OTA updates. + +MCUboot bootloader +================== + +User may choose to use MCUboot bootloader instead. In that case the bootloader +must be build (and flash) at least once. + +There are two options to be used when building an application: + +1. Sysbuild +2. Manual build + +.. note:: + + User can select the MCUboot bootloader by adding the following line + to the board default configuration file. + ``` + CONFIG_BOOTLOADER_MCUBOOT=y + ``` + +Sysbuild +======== + +The sysbuild makes possible to build and flash all necessary images needed to +bootstrap the board with the EPS32 SoC. + +To build the sample application using sysbuild use the command: + +.. zephyr-app-commands:: + :tool: west + :app: samples/hello_world + :board: esp32c6_devkitc + :goals: build + :west-args: --sysbuild + :compact: + +By default, the ESP32 sysbuild creates bootloader (MCUboot) and application +images. But it can be configured to create other kind of images. + +Build directory structure created by sysbuild is different from traditional +Zephyr build. Output is structured by the domain subdirectories: + +.. code-block:: + + build/ + ├── hello_world + │   └── zephyr + │   ├── zephyr.elf + │   └── zephyr.bin + ├── mcuboot + │ └── zephyr + │ ├── zephyr.elf + │ └── zephyr.bin + └── domains.yaml + +.. note:: + + With ``--sysbuild`` option the bootloader will be re-build and re-flash + every time the pristine build is used. + +For more information about the system build please read the :ref:`sysbuild` documentation. + +Manual build +============ + +During the development cycle, it is intended to build & flash as quickly possible. +For that reason, images can be build one at a time using traditional build. + +The instructions following are relevant for both manual build and sysbuild. +The only difference is the structure of the build directory. + +.. note:: + + Remember that bootloader (MCUboot) needs to be flash at least once. + +Build and flash applications as usual (see :ref:`build_an_application` and +:ref:`application_run` for more details). + +.. zephyr-app-commands:: + :zephyr-app: samples/hello_world + :board: esp32c6_devkitc + :goals: build + +The usual ``flash`` target will work with the ``esp32c6_devkitc`` board +configuration. Here is an example for the :ref:`hello_world` +application. + +.. zephyr-app-commands:: + :zephyr-app: samples/hello_world + :board: esp32c6_devkitc + :goals: flash + +Open the serial monitor using the following command: + +.. code-block:: shell + + west espressif monitor + +After the board has automatically reset and booted, you should see the following +message in the monitor: + +.. code-block:: console + + ***** Booting Zephyr OS vx.x.x-xxx-gxxxxxxxxxxxx ***** + Hello World! esp32c6_devkitc + +Debugging +********* + +As with much custom hardware, the ESP32-C6 modules require patches to +OpenOCD that are not upstreamed yet. Espressif maintains their own fork of +the project. The custom OpenOCD can be obtained at `OpenOCD ESP32`_ + +The Zephyr SDK uses a bundled version of OpenOCD by default. You can overwrite that behavior by adding the +``-DOPENOCD= -DOPENOCD_DEFAULT_PATH=`` +parameter when building. + +Here is an example for building the :ref:`hello_world` application. + +.. zephyr-app-commands:: + :zephyr-app: samples/hello_world + :board: esp32c6_devkitc + :goals: build flash + :gen-args: -DOPENOCD= -DOPENOCD_DEFAULT_PATH= + +You can debug an application in the usual way. Here is an example for the :ref:`hello_world` application. + +.. zephyr-app-commands:: + :zephyr-app: samples/hello_world + :board: esp32c6_devkitc + :goals: debug + +.. _`OpenOCD ESP32`: https://github.com/espressif/openocd-esp32/releases + +References +********** + +.. [1] https://www.espressif.com/en/products/socs/esp32-c6 +.. [2] https://docs.espressif.com/projects/espressif-esp-dev-kits/en/latest/esp32c6/esp32-c6-devkitc-1/user_guide.html +.. _ESP32C6 Devkitm User Guide: https://docs.espressif.com/projects/espressif-esp-dev-kits/en/latest/esp32c6/esp32-c6-devkitc-1/user_guide.html +.. _ESP32C6 Technical Reference Manual: https://espressif.com/sites/default/files/documentation/esp32-c6_technical_reference_manual_en.pdf +.. _ESP32C6 Datasheet: https://www.espressif.com/sites/default/files/documentation/esp32-c6_datasheet_en.pdf diff --git a/boards/espressif/esp32c6_devkitc/esp32c6_devkitc-pinctrl.dtsi b/boards/espressif/esp32c6_devkitc/esp32c6_devkitc-pinctrl.dtsi new file mode 100644 index 0000000000000..410001220a38d --- /dev/null +++ b/boards/espressif/esp32c6_devkitc/esp32c6_devkitc-pinctrl.dtsi @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +&pinctrl { + + uart0_default: uart0_default { + group1 { + pinmux = ; + output-high; + }; + group2 { + pinmux = ; + bias-pull-up; + }; + }; +}; diff --git a/boards/espressif/esp32c6_devkitc/esp32c6_devkitc.dts b/boards/espressif/esp32c6_devkitc/esp32c6_devkitc.dts new file mode 100644 index 0000000000000..8838655078787 --- /dev/null +++ b/boards/espressif/esp32c6_devkitc/esp32c6_devkitc.dts @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; + +#include +#include "esp32c6_devkitc-pinctrl.dtsi" + +/ { + model = "esp32c6_devkitc"; + compatible = "espressif,esp32c6"; + + chosen { + zephyr,sram = &sram0; + zephyr,console = &uart0; + zephyr,shell-uart = &uart0; + zephyr,flash = &flash0; + zephyr,code-partition = &slot0_partition; + }; + + aliases { + sw0 = &user_button1; + }; + + gpio_keys { + compatible = "gpio-keys"; + user_button1: button_1 { + label = "User SW1"; + gpios = <&gpio0 9 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>; + }; + }; +}; + +&cpu0 { + clock-frequency = ; +}; + +&uart0 { + status = "okay"; + current-speed = <115200>; + pinctrl-0 = <&uart0_default>; + pinctrl-names = "default"; +}; + +&gpio0 { + status = "okay"; +}; + +&flash0 { + status = "okay"; + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + /* Reserve 60kB for the bootloader */ + boot_partition: partition@0 { + label = "mcuboot"; + reg = <0x00000000 0x0000F000>; + read-only; + }; + + /* Reserve 1024kB for the application in slot 0 */ + slot0_partition: partition@10000 { + label = "image-0"; + reg = <0x00010000 0x00100000>; + }; + + /* Reserve 1024kB for the application in slot 1 */ + slot1_partition: partition@110000 { + label = "image-1"; + reg = <0x00110000 0x00100000>; + }; + + /* Reserve 256kB for the scratch partition */ + scratch_partition: partition@210000 { + label = "image-scratch"; + reg = <0x00210000 0x00040000>; + }; + + storage_partition: partition@250000 { + label = "storage"; + reg = <0x00250000 0x00006000>; + }; + }; +}; diff --git a/boards/espressif/esp32c6_devkitc/esp32c6_devkitc.yaml b/boards/espressif/esp32c6_devkitc/esp32c6_devkitc.yaml new file mode 100644 index 0000000000000..01c8e2bdaa903 --- /dev/null +++ b/boards/espressif/esp32c6_devkitc/esp32c6_devkitc.yaml @@ -0,0 +1,14 @@ +identifier: esp32c6_devkitc +name: ESP32-C6 +vendor: espressif +type: mcu +arch: riscv +toolchain: + - zephyr +supported: + - gpio + - uart +testing: + ignore_tags: + - net + - bluetooth diff --git a/boards/espressif/esp32c6_devkitc/esp32c6_devkitc_defconfig b/boards/espressif/esp32c6_devkitc/esp32c6_devkitc_defconfig new file mode 100644 index 0000000000000..6539bd42e5947 --- /dev/null +++ b/boards/espressif/esp32c6_devkitc/esp32c6_devkitc_defconfig @@ -0,0 +1,7 @@ +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_MAIN_STACK_SIZE=2048 +CONFIG_CONSOLE=y +CONFIG_SERIAL=y +CONFIG_UART_CONSOLE=y +CONFIG_GPIO=y diff --git a/boards/espressif/esp32c6_devkitc/support/openocd.cfg b/boards/espressif/esp32c6_devkitc/support/openocd.cfg new file mode 100644 index 0000000000000..d86a5517a4ca9 --- /dev/null +++ b/boards/espressif/esp32c6_devkitc/support/openocd.cfg @@ -0,0 +1,4 @@ +# ESP32C6 has built-in JTAG interface over USB port in pins GPIO13/GPIO12 (D-/D+). +set ESP_RTOS none + +source [find board/esp32c6-builtin.cfg] From fe15a051accdab8d11ff5602e2cb85103381959d Mon Sep 17 00:00:00 2001 From: Lucas Tamborrino Date: Wed, 7 Jun 2023 08:58:25 -0300 Subject: [PATCH 2840/2849] drivers: Update to add support for esp32c6 Changes to bring support for esp32c6 SoC. - clock control - gpio - pinctrl - serial - timer Signed-off-by: Lucas Tamborrino --- drivers/gpio/gpio_esp32.c | 11 ++++++++++- drivers/pinctrl/pinctrl_esp32.c | 6 ++++++ drivers/serial/Kconfig.esp32 | 4 ++-- drivers/serial/serial_esp32_usb.c | 4 ++-- drivers/serial/uart_esp32.c | 16 +++++++++++----- drivers/timer/Kconfig.esp32 | 2 +- drivers/timer/esp32_sys_timer.c | 4 +--- 7 files changed, 33 insertions(+), 14 deletions(-) diff --git a/drivers/gpio/gpio_esp32.c b/drivers/gpio/gpio_esp32.c index 3851200b18130..7a1b6790388b7 100644 --- a/drivers/gpio/gpio_esp32.c +++ b/drivers/gpio/gpio_esp32.c @@ -20,7 +20,7 @@ #include #include #include -#ifdef CONFIG_SOC_SERIES_ESP32C3 +#if defined(CONFIG_SOC_SERIES_ESP32C3) || defined(CONFIG_SOC_SERIES_ESP32C6) #include #else #include @@ -42,6 +42,15 @@ LOG_MODULE_REGISTER(gpio_esp32, CONFIG_LOG_DEFAULT_LEVEL); /* arch_curr_cpu() is not available for riscv based chips */ #define CPU_ID() 0 #define ISR_HANDLER isr_handler_t +#elif defined(CONFIG_SOC_SERIES_ESP32C6) +/* gpio structs in esp32c6 are also different */ +#define out out.out_data_orig +#define in in.in_data_next +#define out_w1ts out_w1ts.val +#define out_w1tc out_w1tc.val +/* arch_curr_cpu() is not available for riscv based chips */ +#define CPU_ID() 0 +#define ISR_HANDLER isr_handler_t #else #define CPU_ID() arch_curr_cpu()->id #define ISR_HANDLER intr_handler_t diff --git a/drivers/pinctrl/pinctrl_esp32.c b/drivers/pinctrl/pinctrl_esp32.c index 71049f5b1cb5d..581cc2b2dc6ca 100644 --- a/drivers/pinctrl/pinctrl_esp32.c +++ b/drivers/pinctrl/pinctrl_esp32.c @@ -18,6 +18,12 @@ #define in in.data #define out_w1ts out_w1ts.val #define out_w1tc out_w1tc.val +#elif CONFIG_SOC_SERIES_ESP32C6 +/* gpio structs in esp32c6 are also different */ +#define out out.out_data_orig +#define in in.in_data_next +#define out_w1ts out_w1ts.val +#define out_w1tc out_w1tc.val #endif #ifndef SOC_GPIO_SUPPORT_RTC_INDEPENDENT diff --git a/drivers/serial/Kconfig.esp32 b/drivers/serial/Kconfig.esp32 index f6fa5ac9d937e..8f7f35a630c0c 100644 --- a/drivers/serial/Kconfig.esp32 +++ b/drivers/serial/Kconfig.esp32 @@ -7,7 +7,7 @@ config UART_ESP32 depends on DT_HAS_ESPRESSIF_ESP32_UART_ENABLED select SERIAL_HAS_DRIVER select SERIAL_SUPPORT_INTERRUPT - select SERIAL_SUPPORT_ASYNC if (SOC_SERIES_ESP32C3 || SOC_SERIES_ESP32S3) + select SERIAL_SUPPORT_ASYNC if (SOC_SERIES_ESP32C3 || SOC_SERIES_ESP32C6 || SOC_SERIES_ESP32S3) select GPIO_ESP32 help Enable the ESP32 UART. @@ -20,7 +20,7 @@ config SERIAL_ESP32_USB select SERIAL_SUPPORT_INTERRUPT help Enable the built-in USB serial interface present in some Espressif - MCUs like the ESP32-C3. + MCUs like ESP32-Cx. This driver uses the peripheral called USB Serial/JTAG Controller (USB_SERIAL_JTAG), which acts as a CDC-ACM interface towards the diff --git a/drivers/serial/serial_esp32_usb.c b/drivers/serial/serial_esp32_usb.c index 14e4b798a8f23..5b26ca00863ac 100644 --- a/drivers/serial/serial_esp32_usb.c +++ b/drivers/serial/serial_esp32_usb.c @@ -13,7 +13,7 @@ #include #include #include -#if defined(CONFIG_SOC_SERIES_ESP32C3) +#if defined(CONFIG_SOC_SERIES_ESP32C3) || defined(CONFIG_SOC_SERIES_ESP32C6) #include #else #include @@ -22,7 +22,7 @@ #include #include -#ifdef CONFIG_SOC_SERIES_ESP32C3 +#if defined(CONFIG_SOC_SERIES_ESP32C3) || defined(CONFIG_SOC_SERIES_ESP32C6) #define ISR_HANDLER isr_handler_t #else #define ISR_HANDLER intr_handler_t diff --git a/drivers/serial/uart_esp32.c b/drivers/serial/uart_esp32.c index 0bbc3fb4d2d1d..9bf0c3bb17cf1 100644 --- a/drivers/serial/uart_esp32.c +++ b/drivers/serial/uart_esp32.c @@ -25,6 +25,10 @@ #include #include #include +#elif defined(CONFIG_SOC_SERIES_ESP32C6) +#include +#include +#include #endif #ifdef CONFIG_UART_ASYNC_API #include @@ -43,19 +47,21 @@ #include #include -#ifndef CONFIG_SOC_SERIES_ESP32C3 -#include -#else +#if defined(CONFIG_SOC_SERIES_ESP32C3) || defined(CONFIG_SOC_SERIES_ESP32C6) #include +#else +#include #endif + #include #include #include #include #include + LOG_MODULE_REGISTER(uart_esp32, CONFIG_UART_LOG_LEVEL); -#ifdef CONFIG_SOC_SERIES_ESP32C3 +#if defined(CONFIG_SOC_SERIES_ESP32C3) || defined(CONFIG_SOC_SERIES_ESP32C6) #define ISR_HANDLER isr_handler_t #else #define ISR_HANDLER intr_handler_t @@ -257,7 +263,7 @@ static int uart_esp32_configure(const struct device *dev, const struct uart_conf clock_control_on(config->clock_dev, config->clock_subsys); - uart_hal_set_sclk(&data->hal, UART_SCLK_APB); + uart_hal_set_sclk(&data->hal, UART_SCLK_DEFAULT); uart_hal_set_rxfifo_full_thr(&data->hal, UART_RX_FIFO_THRESH); uart_hal_set_txfifo_empty_thr(&data->hal, UART_TX_FIFO_THRESH); uart_hal_rxfifo_rst(&data->hal); diff --git a/drivers/timer/Kconfig.esp32 b/drivers/timer/Kconfig.esp32 index 0634c3f0cb229..4dd289287e205 100644 --- a/drivers/timer/Kconfig.esp32 +++ b/drivers/timer/Kconfig.esp32 @@ -5,7 +5,7 @@ config ESP32_SYS_TIMER bool "ESP32 sys-timer support (ESP32Cx series)" - depends on SOC_SERIES_ESP32C3 + depends on SOC_SERIES_ESP32C3 || SOC_SERIES_ESP32C6 default y select TICKLESS_CAPABLE select TIMER_HAS_64BIT_CYCLE_COUNTER diff --git a/drivers/timer/esp32_sys_timer.c b/drivers/timer/esp32_sys_timer.c index 770a89edbdf30..2eeb71d1524e2 100644 --- a/drivers/timer/esp32_sys_timer.c +++ b/drivers/timer/esp32_sys_timer.c @@ -5,9 +5,7 @@ */ #include #include -#include -#include -#include + #include #include #include From e611b41fff9c3de96ee222b77e4177c0eb5f2c77 Mon Sep 17 00:00:00 2001 From: Raffael Rostagno Date: Wed, 3 Apr 2024 11:38:13 -0300 Subject: [PATCH 2841/2849] drivers: watchdog: Added support to C6 Added support to watchdog timer to ESP32C6 Signed-off-by: Raffael Rostagno --- .../esp32c6_devkitc/esp32c6_devkitc.dts | 5 +++++ drivers/watchdog/wdt_esp32.c | 12 ++++++++---- .../espressif/esp32c6/esp32c6_common.dtsi | 18 ++++++++++++++++++ 3 files changed, 31 insertions(+), 4 deletions(-) diff --git a/boards/espressif/esp32c6_devkitc/esp32c6_devkitc.dts b/boards/espressif/esp32c6_devkitc/esp32c6_devkitc.dts index 8838655078787..af3c57f11f939 100644 --- a/boards/espressif/esp32c6_devkitc/esp32c6_devkitc.dts +++ b/boards/espressif/esp32c6_devkitc/esp32c6_devkitc.dts @@ -23,6 +23,7 @@ aliases { sw0 = &user_button1; + watchdog0 = &wdt0; }; gpio_keys { @@ -49,6 +50,10 @@ status = "okay"; }; +&wdt0 { + status = "okay"; +}; + &flash0 { status = "okay"; partitions { diff --git a/drivers/watchdog/wdt_esp32.c b/drivers/watchdog/wdt_esp32.c index 460f130c1b5f5..f5ef51fad0271 100644 --- a/drivers/watchdog/wdt_esp32.c +++ b/drivers/watchdog/wdt_esp32.c @@ -7,7 +7,11 @@ #define DT_DRV_COMPAT espressif_esp32_watchdog /* Include esp-idf headers first to avoid redefining BIT() macro */ +#if defined(CONFIG_SOC_SERIES_ESP32C6) +#include +#else #include +#endif #include #include #include @@ -15,17 +19,17 @@ #include #include #include -#ifndef CONFIG_SOC_SERIES_ESP32C3 -#include -#else +#if defined(CONFIG_SOC_SERIES_ESP32C3) || defined(CONFIG_SOC_SERIES_ESP32C6) #include +#else +#include #endif #include #include LOG_MODULE_REGISTER(wdt_esp32, CONFIG_WDT_LOG_LEVEL); -#ifdef CONFIG_SOC_SERIES_ESP32C3 +#if defined(CONFIG_SOC_SERIES_ESP32C3) || defined(CONFIG_SOC_SERIES_ESP32C6) #define ISR_HANDLER isr_handler_t #else #define ISR_HANDLER intr_handler_t diff --git a/dts/riscv/espressif/esp32c6/esp32c6_common.dtsi b/dts/riscv/espressif/esp32c6/esp32c6_common.dtsi index 175921df6bcdd..463e2cd93df1d 100644 --- a/dts/riscv/espressif/esp32c6/esp32c6_common.dtsi +++ b/dts/riscv/espressif/esp32c6/esp32c6_common.dtsi @@ -78,6 +78,24 @@ }; }; + wdt0: watchdog@6001f048 { + compatible = "espressif,esp32-watchdog"; + reg = <0x6001f048 0x20>; + interrupts = ; + interrupt-parent = <&intc>; + clocks = <&rtc ESP32_TIMG0_MODULE>; + status = "disabled"; + }; + + wdt1: watchdog@60020048 { + compatible = "espressif,esp32-watchdog"; + reg = <0x60020048 0x20>; + interrupts = ; + interrupt-parent = <&intc>; + clocks = <&rtc ESP32_TIMG1_MODULE>; + status = "disabled"; + }; + flash: flash-controller@60002000 { compatible = "espressif,esp32-flash-controller"; reg = <0x60002000 0x1000>; From da778de48dc60d62d8926a043723b8021b90dd95 Mon Sep 17 00:00:00 2001 From: Raffael Rostagno Date: Mon, 13 May 2024 15:17:59 -0300 Subject: [PATCH 2842/2849] drivers: spi: Add suport to ESP32C6 Added GP-SPI2 (general purpose SPI2) support for ESP32C6 Signed-off-by: Raffael Rostagno --- drivers/spi/spi_esp32_spim.c | 15 +- drivers/spi/spi_esp32_spim.h | 1 - .../espressif/esp32c6/esp32c6_common.dtsi | 11 + .../dt-bindings/pinctrl/esp32c6-pinctrl.h | 657 ++++++++++++++++++ 4 files changed, 676 insertions(+), 8 deletions(-) diff --git a/drivers/spi/spi_esp32_spim.c b/drivers/spi/spi_esp32_spim.c index 5bcec47577f71..229eff0007d72 100644 --- a/drivers/spi/spi_esp32_spim.c +++ b/drivers/spi/spi_esp32_spim.c @@ -17,10 +17,10 @@ LOG_MODULE_REGISTER(esp32_spi, CONFIG_SPI_LOG_LEVEL); #include #include #include -#ifndef CONFIG_SOC_SERIES_ESP32C3 -#include -#else +#if defined(CONFIG_SOC_SERIES_ESP32C3) || defined(CONFIG_SOC_SERIES_ESP32C6) #include +#else +#include #endif #ifdef SOC_GDMA_SUPPORTED #include @@ -30,7 +30,7 @@ LOG_MODULE_REGISTER(esp32_spi, CONFIG_SPI_LOG_LEVEL); #include "spi_context.h" #include "spi_esp32_spim.h" -#ifdef CONFIG_SOC_SERIES_ESP32C3 +#if defined(CONFIG_SOC_SERIES_ESP32C3) || defined(CONFIG_SOC_SERIES_ESP32C6) #define ISR_HANDLER isr_handler_t #else #define ISR_HANDLER intr_handler_t @@ -244,7 +244,7 @@ static int spi_esp32_init(const struct device *dev) spi_ll_disable_int(cfg->spi); spi_ll_clear_int_stat(cfg->spi); - data->irq_line = esp_intr_alloc(cfg->irq_source, + esp_intr_alloc(cfg->irq_source, 0, (ISR_HANDLER)spi_esp32_isr, (void *)dev, @@ -377,10 +377,11 @@ static int IRAM_ATTR spi_esp32_configure(const struct device *dev, #endif /* - * Workaround for ESP32S3 and ESP32C3 SoC. This dummy transaction is needed to sync CLK and + * Workaround for ESP32S3 and ESP32Cx SoC. This dummy transaction is needed to sync CLK and * software controlled CS when SPI is in mode 3 */ -#if defined(CONFIG_SOC_SERIES_ESP32S3) || defined(CONFIG_SOC_SERIES_ESP32C3) +#if defined(CONFIG_SOC_SERIES_ESP32S3) || defined(CONFIG_SOC_SERIES_ESP32C3) || \ + defined(CONFIG_SOC_SERIES_ESP32C6) if (ctx->num_cs_gpios && (hal_dev->mode & (SPI_MODE_CPOL | SPI_MODE_CPHA))) { spi_esp32_transfer(dev); } diff --git a/drivers/spi/spi_esp32_spim.h b/drivers/spi/spi_esp32_spim.h index b38c2aef8b318..03da08f6b3411 100644 --- a/drivers/spi/spi_esp32_spim.h +++ b/drivers/spi/spi_esp32_spim.h @@ -53,7 +53,6 @@ struct spi_esp32_data { spi_hal_dev_config_t dev_config; spi_hal_trans_config_t trans_config; uint8_t dfs; - int irq_line; lldesc_t dma_desc_tx; lldesc_t dma_desc_rx; uint32_t clock_source_hz; diff --git a/dts/riscv/espressif/esp32c6/esp32c6_common.dtsi b/dts/riscv/espressif/esp32c6/esp32c6_common.dtsi index 463e2cd93df1d..72d87e21d3586 100644 --- a/dts/riscv/espressif/esp32c6/esp32c6_common.dtsi +++ b/dts/riscv/espressif/esp32c6/esp32c6_common.dtsi @@ -78,6 +78,17 @@ }; }; + spi2: spi@60081000 { + compatible = "espressif,esp32-spi"; + reg = <0x60081000 DT_SIZE_K(4)>; + interrupts = ; + interrupt-parent = <&intc>; + clocks = <&rtc ESP32_SPI2_MODULE>; + dma-clk = ; + dma-host = <0>; + status = "disabled"; + }; + wdt0: watchdog@6001f048 { compatible = "espressif,esp32-watchdog"; reg = <0x6001f048 0x20>; diff --git a/include/zephyr/dt-bindings/pinctrl/esp32c6-pinctrl.h b/include/zephyr/dt-bindings/pinctrl/esp32c6-pinctrl.h index 3c138c85f4391..22ecad22f681b 100644 --- a/include/zephyr/dt-bindings/pinctrl/esp32c6-pinctrl.h +++ b/include/zephyr/dt-bindings/pinctrl/esp32c6-pinctrl.h @@ -9,6 +9,663 @@ #ifndef INC_DT_BINDS_PINCTRL_ESP32C6_PINCTRL_HAL_H_ #define INC_DT_BINDS_PINCTRL_ESP32C6_PINCTRL_HAL_H_ +/* SPIM2_CSEL */ +#define SPIM2_CSEL_GPIO0 \ + ESP32_PINMUX(0, ESP_NOSIG, ESP_FSPICS0_OUT) + +#define SPIM2_CSEL_GPIO1 \ + ESP32_PINMUX(1, ESP_NOSIG, ESP_FSPICS0_OUT) + +#define SPIM2_CSEL_GPIO2 \ + ESP32_PINMUX(2, ESP_NOSIG, ESP_FSPICS0_OUT) + +#define SPIM2_CSEL_GPIO3 \ + ESP32_PINMUX(3, ESP_NOSIG, ESP_FSPICS0_OUT) + +#define SPIM2_CSEL_GPIO4 \ + ESP32_PINMUX(4, ESP_NOSIG, ESP_FSPICS0_OUT) + +#define SPIM2_CSEL_GPIO5 \ + ESP32_PINMUX(5, ESP_NOSIG, ESP_FSPICS0_OUT) + +#define SPIM2_CSEL_GPIO6 \ + ESP32_PINMUX(6, ESP_NOSIG, ESP_FSPICS0_OUT) + +#define SPIM2_CSEL_GPIO7 \ + ESP32_PINMUX(7, ESP_NOSIG, ESP_FSPICS0_OUT) + +#define SPIM2_CSEL_GPIO8 \ + ESP32_PINMUX(8, ESP_NOSIG, ESP_FSPICS0_OUT) + +#define SPIM2_CSEL_GPIO9 \ + ESP32_PINMUX(9, ESP_NOSIG, ESP_FSPICS0_OUT) + +#define SPIM2_CSEL_GPIO10 \ + ESP32_PINMUX(10, ESP_NOSIG, ESP_FSPICS0_OUT) + +#define SPIM2_CSEL_GPIO11 \ + ESP32_PINMUX(11, ESP_NOSIG, ESP_FSPICS0_OUT) + +#define SPIM2_CSEL_GPIO12 \ + ESP32_PINMUX(12, ESP_NOSIG, ESP_FSPICS0_OUT) + +#define SPIM2_CSEL_GPIO13 \ + ESP32_PINMUX(13, ESP_NOSIG, ESP_FSPICS0_OUT) + +#define SPIM2_CSEL_GPIO14 \ + ESP32_PINMUX(14, ESP_NOSIG, ESP_FSPICS0_OUT) + +#define SPIM2_CSEL_GPIO15 \ + ESP32_PINMUX(15, ESP_NOSIG, ESP_FSPICS0_OUT) + +#define SPIM2_CSEL_GPIO16 \ + ESP32_PINMUX(16, ESP_NOSIG, ESP_FSPICS0_OUT) + +#define SPIM2_CSEL_GPIO17 \ + ESP32_PINMUX(17, ESP_NOSIG, ESP_FSPICS0_OUT) + +#define SPIM2_CSEL_GPIO18 \ + ESP32_PINMUX(18, ESP_NOSIG, ESP_FSPICS0_OUT) + +#define SPIM2_CSEL_GPIO19 \ + ESP32_PINMUX(19, ESP_NOSIG, ESP_FSPICS0_OUT) + +#define SPIM2_CSEL_GPIO20 \ + ESP32_PINMUX(20, ESP_NOSIG, ESP_FSPICS0_OUT) + +#define SPIM2_CSEL_GPIO21 \ + ESP32_PINMUX(21, ESP_NOSIG, ESP_FSPICS0_OUT) + +#define SPIM2_CSEL_GPIO22 \ + ESP32_PINMUX(22, ESP_NOSIG, ESP_FSPICS0_OUT) + +#define SPIM2_CSEL_GPIO23 \ + ESP32_PINMUX(23, ESP_NOSIG, ESP_FSPICS0_OUT) + +/* SPIM2_CSEL1 */ +#define SPIM2_CSEL1_GPIO0 \ + ESP32_PINMUX(0, ESP_NOSIG, ESP_FSPICS1_OUT) + +#define SPIM2_CSEL1_GPIO1 \ + ESP32_PINMUX(1, ESP_NOSIG, ESP_FSPICS1_OUT) + +#define SPIM2_CSEL1_GPIO2 \ + ESP32_PINMUX(2, ESP_NOSIG, ESP_FSPICS1_OUT) + +#define SPIM2_CSEL1_GPIO3 \ + ESP32_PINMUX(3, ESP_NOSIG, ESP_FSPICS1_OUT) + +#define SPIM2_CSEL1_GPIO4 \ + ESP32_PINMUX(4, ESP_NOSIG, ESP_FSPICS1_OUT) + +#define SPIM2_CSEL1_GPIO5 \ + ESP32_PINMUX(5, ESP_NOSIG, ESP_FSPICS1_OUT) + +#define SPIM2_CSEL1_GPIO6 \ + ESP32_PINMUX(6, ESP_NOSIG, ESP_FSPICS1_OUT) + +#define SPIM2_CSEL1_GPIO7 \ + ESP32_PINMUX(7, ESP_NOSIG, ESP_FSPICS1_OUT) + +#define SPIM2_CSEL1_GPIO8 \ + ESP32_PINMUX(8, ESP_NOSIG, ESP_FSPICS1_OUT) + +#define SPIM2_CSEL1_GPIO9 \ + ESP32_PINMUX(9, ESP_NOSIG, ESP_FSPICS1_OUT) + +#define SPIM2_CSEL1_GPIO10 \ + ESP32_PINMUX(10, ESP_NOSIG, ESP_FSPICS1_OUT) + +#define SPIM2_CSEL1_GPIO11 \ + ESP32_PINMUX(11, ESP_NOSIG, ESP_FSPICS1_OUT) + +#define SPIM2_CSEL1_GPIO12 \ + ESP32_PINMUX(12, ESP_NOSIG, ESP_FSPICS1_OUT) + +#define SPIM2_CSEL1_GPIO13 \ + ESP32_PINMUX(13, ESP_NOSIG, ESP_FSPICS1_OUT) + +#define SPIM2_CSEL1_GPIO14 \ + ESP32_PINMUX(14, ESP_NOSIG, ESP_FSPICS1_OUT) + +#define SPIM2_CSEL1_GPIO15 \ + ESP32_PINMUX(15, ESP_NOSIG, ESP_FSPICS1_OUT) + +#define SPIM2_CSEL1_GPIO16 \ + ESP32_PINMUX(16, ESP_NOSIG, ESP_FSPICS1_OUT) + +#define SPIM2_CSEL1_GPIO17 \ + ESP32_PINMUX(17, ESP_NOSIG, ESP_FSPICS1_OUT) + +#define SPIM2_CSEL1_GPIO18 \ + ESP32_PINMUX(18, ESP_NOSIG, ESP_FSPICS1_OUT) + +#define SPIM2_CSEL1_GPIO19 \ + ESP32_PINMUX(19, ESP_NOSIG, ESP_FSPICS1_OUT) + +#define SPIM2_CSEL1_GPIO20 \ + ESP32_PINMUX(20, ESP_NOSIG, ESP_FSPICS1_OUT) + +#define SPIM2_CSEL1_GPIO21 \ + ESP32_PINMUX(21, ESP_NOSIG, ESP_FSPICS1_OUT) + +#define SPIM2_CSEL1_GPIO22 \ + ESP32_PINMUX(22, ESP_NOSIG, ESP_FSPICS1_OUT) + +#define SPIM2_CSEL1_GPIO23 \ + ESP32_PINMUX(23, ESP_NOSIG, ESP_FSPICS1_OUT) + +/* SPIM2_CSEL2 */ +#define SPIM2_CSEL2_GPIO0 \ + ESP32_PINMUX(0, ESP_NOSIG, ESP_FSPICS2_OUT) + +#define SPIM2_CSEL2_GPIO1 \ + ESP32_PINMUX(1, ESP_NOSIG, ESP_FSPICS2_OUT) + +#define SPIM2_CSEL2_GPIO2 \ + ESP32_PINMUX(2, ESP_NOSIG, ESP_FSPICS2_OUT) + +#define SPIM2_CSEL2_GPIO3 \ + ESP32_PINMUX(3, ESP_NOSIG, ESP_FSPICS2_OUT) + +#define SPIM2_CSEL2_GPIO4 \ + ESP32_PINMUX(4, ESP_NOSIG, ESP_FSPICS2_OUT) + +#define SPIM2_CSEL2_GPIO5 \ + ESP32_PINMUX(5, ESP_NOSIG, ESP_FSPICS2_OUT) + +#define SPIM2_CSEL2_GPIO6 \ + ESP32_PINMUX(6, ESP_NOSIG, ESP_FSPICS2_OUT) + +#define SPIM2_CSEL2_GPIO7 \ + ESP32_PINMUX(7, ESP_NOSIG, ESP_FSPICS2_OUT) + +#define SPIM2_CSEL2_GPIO8 \ + ESP32_PINMUX(8, ESP_NOSIG, ESP_FSPICS2_OUT) + +#define SPIM2_CSEL2_GPIO9 \ + ESP32_PINMUX(9, ESP_NOSIG, ESP_FSPICS2_OUT) + +#define SPIM2_CSEL2_GPIO10 \ + ESP32_PINMUX(10, ESP_NOSIG, ESP_FSPICS2_OUT) + +#define SPIM2_CSEL2_GPIO11 \ + ESP32_PINMUX(11, ESP_NOSIG, ESP_FSPICS2_OUT) + +#define SPIM2_CSEL2_GPIO12 \ + ESP32_PINMUX(12, ESP_NOSIG, ESP_FSPICS2_OUT) + +#define SPIM2_CSEL2_GPIO13 \ + ESP32_PINMUX(13, ESP_NOSIG, ESP_FSPICS2_OUT) + +#define SPIM2_CSEL2_GPIO14 \ + ESP32_PINMUX(14, ESP_NOSIG, ESP_FSPICS2_OUT) + +#define SPIM2_CSEL2_GPIO15 \ + ESP32_PINMUX(15, ESP_NOSIG, ESP_FSPICS2_OUT) + +#define SPIM2_CSEL2_GPIO16 \ + ESP32_PINMUX(16, ESP_NOSIG, ESP_FSPICS2_OUT) + +#define SPIM2_CSEL2_GPIO17 \ + ESP32_PINMUX(17, ESP_NOSIG, ESP_FSPICS2_OUT) + +#define SPIM2_CSEL2_GPIO18 \ + ESP32_PINMUX(18, ESP_NOSIG, ESP_FSPICS2_OUT) + +#define SPIM2_CSEL2_GPIO19 \ + ESP32_PINMUX(19, ESP_NOSIG, ESP_FSPICS2_OUT) + +#define SPIM2_CSEL2_GPIO20 \ + ESP32_PINMUX(20, ESP_NOSIG, ESP_FSPICS2_OUT) + +#define SPIM2_CSEL2_GPIO21 \ + ESP32_PINMUX(21, ESP_NOSIG, ESP_FSPICS2_OUT) + +#define SPIM2_CSEL2_GPIO22 \ + ESP32_PINMUX(22, ESP_NOSIG, ESP_FSPICS2_OUT) + +#define SPIM2_CSEL2_GPIO23 \ + ESP32_PINMUX(23, ESP_NOSIG, ESP_FSPICS2_OUT) + +/* SPIM2_CSEL3 */ +#define SPIM2_CSEL3_GPIO0 \ + ESP32_PINMUX(0, ESP_NOSIG, ESP_FSPICS3_OUT) + +#define SPIM2_CSEL3_GPIO1 \ + ESP32_PINMUX(1, ESP_NOSIG, ESP_FSPICS3_OUT) + +#define SPIM2_CSEL3_GPIO2 \ + ESP32_PINMUX(2, ESP_NOSIG, ESP_FSPICS3_OUT) + +#define SPIM2_CSEL3_GPIO3 \ + ESP32_PINMUX(3, ESP_NOSIG, ESP_FSPICS3_OUT) + +#define SPIM2_CSEL3_GPIO4 \ + ESP32_PINMUX(4, ESP_NOSIG, ESP_FSPICS3_OUT) + +#define SPIM2_CSEL3_GPIO5 \ + ESP32_PINMUX(5, ESP_NOSIG, ESP_FSPICS3_OUT) + +#define SPIM2_CSEL3_GPIO6 \ + ESP32_PINMUX(6, ESP_NOSIG, ESP_FSPICS3_OUT) + +#define SPIM2_CSEL3_GPIO7 \ + ESP32_PINMUX(7, ESP_NOSIG, ESP_FSPICS3_OUT) + +#define SPIM2_CSEL3_GPIO8 \ + ESP32_PINMUX(8, ESP_NOSIG, ESP_FSPICS3_OUT) + +#define SPIM2_CSEL3_GPIO9 \ + ESP32_PINMUX(9, ESP_NOSIG, ESP_FSPICS3_OUT) + +#define SPIM2_CSEL3_GPIO10 \ + ESP32_PINMUX(10, ESP_NOSIG, ESP_FSPICS3_OUT) + +#define SPIM2_CSEL3_GPIO11 \ + ESP32_PINMUX(11, ESP_NOSIG, ESP_FSPICS3_OUT) + +#define SPIM2_CSEL3_GPIO12 \ + ESP32_PINMUX(12, ESP_NOSIG, ESP_FSPICS3_OUT) + +#define SPIM2_CSEL3_GPIO13 \ + ESP32_PINMUX(13, ESP_NOSIG, ESP_FSPICS3_OUT) + +#define SPIM2_CSEL3_GPIO14 \ + ESP32_PINMUX(14, ESP_NOSIG, ESP_FSPICS3_OUT) + +#define SPIM2_CSEL3_GPIO15 \ + ESP32_PINMUX(15, ESP_NOSIG, ESP_FSPICS3_OUT) + +#define SPIM2_CSEL3_GPIO16 \ + ESP32_PINMUX(16, ESP_NOSIG, ESP_FSPICS3_OUT) + +#define SPIM2_CSEL3_GPIO17 \ + ESP32_PINMUX(17, ESP_NOSIG, ESP_FSPICS3_OUT) + +#define SPIM2_CSEL3_GPIO18 \ + ESP32_PINMUX(18, ESP_NOSIG, ESP_FSPICS3_OUT) + +#define SPIM2_CSEL3_GPIO19 \ + ESP32_PINMUX(19, ESP_NOSIG, ESP_FSPICS3_OUT) + +#define SPIM2_CSEL3_GPIO20 \ + ESP32_PINMUX(20, ESP_NOSIG, ESP_FSPICS3_OUT) + +#define SPIM2_CSEL3_GPIO21 \ + ESP32_PINMUX(21, ESP_NOSIG, ESP_FSPICS3_OUT) + +#define SPIM2_CSEL3_GPIO22 \ + ESP32_PINMUX(22, ESP_NOSIG, ESP_FSPICS3_OUT) + +#define SPIM2_CSEL3_GPIO23 \ + ESP32_PINMUX(23, ESP_NOSIG, ESP_FSPICS3_OUT) + +/* SPIM2_CSEL4 */ +#define SPIM2_CSEL4_GPIO0 \ + ESP32_PINMUX(0, ESP_NOSIG, ESP_FSPICS4_OUT) + +#define SPIM2_CSEL4_GPIO1 \ + ESP32_PINMUX(1, ESP_NOSIG, ESP_FSPICS4_OUT) + +#define SPIM2_CSEL4_GPIO2 \ + ESP32_PINMUX(2, ESP_NOSIG, ESP_FSPICS4_OUT) + +#define SPIM2_CSEL4_GPIO3 \ + ESP32_PINMUX(3, ESP_NOSIG, ESP_FSPICS4_OUT) + +#define SPIM2_CSEL4_GPIO4 \ + ESP32_PINMUX(4, ESP_NOSIG, ESP_FSPICS4_OUT) + +#define SPIM2_CSEL4_GPIO5 \ + ESP32_PINMUX(5, ESP_NOSIG, ESP_FSPICS4_OUT) + +#define SPIM2_CSEL4_GPIO6 \ + ESP32_PINMUX(6, ESP_NOSIG, ESP_FSPICS4_OUT) + +#define SPIM2_CSEL4_GPIO7 \ + ESP32_PINMUX(7, ESP_NOSIG, ESP_FSPICS4_OUT) + +#define SPIM2_CSEL4_GPIO8 \ + ESP32_PINMUX(8, ESP_NOSIG, ESP_FSPICS4_OUT) + +#define SPIM2_CSEL4_GPIO9 \ + ESP32_PINMUX(9, ESP_NOSIG, ESP_FSPICS4_OUT) + +#define SPIM2_CSEL4_GPIO10 \ + ESP32_PINMUX(10, ESP_NOSIG, ESP_FSPICS4_OUT) + +#define SPIM2_CSEL4_GPIO11 \ + ESP32_PINMUX(11, ESP_NOSIG, ESP_FSPICS4_OUT) + +#define SPIM2_CSEL4_GPIO12 \ + ESP32_PINMUX(12, ESP_NOSIG, ESP_FSPICS4_OUT) + +#define SPIM2_CSEL4_GPIO13 \ + ESP32_PINMUX(13, ESP_NOSIG, ESP_FSPICS4_OUT) + +#define SPIM2_CSEL4_GPIO14 \ + ESP32_PINMUX(14, ESP_NOSIG, ESP_FSPICS4_OUT) + +#define SPIM2_CSEL4_GPIO15 \ + ESP32_PINMUX(15, ESP_NOSIG, ESP_FSPICS4_OUT) + +#define SPIM2_CSEL4_GPIO16 \ + ESP32_PINMUX(16, ESP_NOSIG, ESP_FSPICS4_OUT) + +#define SPIM2_CSEL4_GPIO17 \ + ESP32_PINMUX(17, ESP_NOSIG, ESP_FSPICS4_OUT) + +#define SPIM2_CSEL4_GPIO18 \ + ESP32_PINMUX(18, ESP_NOSIG, ESP_FSPICS4_OUT) + +#define SPIM2_CSEL4_GPIO19 \ + ESP32_PINMUX(19, ESP_NOSIG, ESP_FSPICS4_OUT) + +#define SPIM2_CSEL4_GPIO20 \ + ESP32_PINMUX(20, ESP_NOSIG, ESP_FSPICS4_OUT) + +#define SPIM2_CSEL4_GPIO21 \ + ESP32_PINMUX(21, ESP_NOSIG, ESP_FSPICS4_OUT) + +#define SPIM2_CSEL4_GPIO22 \ + ESP32_PINMUX(22, ESP_NOSIG, ESP_FSPICS4_OUT) + +#define SPIM2_CSEL4_GPIO23 \ + ESP32_PINMUX(23, ESP_NOSIG, ESP_FSPICS4_OUT) + +/* SPIM2_CSEL5 */ +#define SPIM2_CSEL5_GPIO0 \ + ESP32_PINMUX(0, ESP_NOSIG, ESP_FSPICS5_OUT) + +#define SPIM2_CSEL5_GPIO1 \ + ESP32_PINMUX(1, ESP_NOSIG, ESP_FSPICS5_OUT) + +#define SPIM2_CSEL5_GPIO2 \ + ESP32_PINMUX(2, ESP_NOSIG, ESP_FSPICS5_OUT) + +#define SPIM2_CSEL5_GPIO3 \ + ESP32_PINMUX(3, ESP_NOSIG, ESP_FSPICS5_OUT) + +#define SPIM2_CSEL5_GPIO4 \ + ESP32_PINMUX(4, ESP_NOSIG, ESP_FSPICS5_OUT) + +#define SPIM2_CSEL5_GPIO5 \ + ESP32_PINMUX(5, ESP_NOSIG, ESP_FSPICS5_OUT) + +#define SPIM2_CSEL5_GPIO6 \ + ESP32_PINMUX(6, ESP_NOSIG, ESP_FSPICS5_OUT) + +#define SPIM2_CSEL5_GPIO7 \ + ESP32_PINMUX(7, ESP_NOSIG, ESP_FSPICS5_OUT) + +#define SPIM2_CSEL5_GPIO8 \ + ESP32_PINMUX(8, ESP_NOSIG, ESP_FSPICS5_OUT) + +#define SPIM2_CSEL5_GPIO9 \ + ESP32_PINMUX(9, ESP_NOSIG, ESP_FSPICS5_OUT) + +#define SPIM2_CSEL5_GPIO10 \ + ESP32_PINMUX(10, ESP_NOSIG, ESP_FSPICS5_OUT) + +#define SPIM2_CSEL5_GPIO11 \ + ESP32_PINMUX(11, ESP_NOSIG, ESP_FSPICS5_OUT) + +#define SPIM2_CSEL5_GPIO12 \ + ESP32_PINMUX(12, ESP_NOSIG, ESP_FSPICS5_OUT) + +#define SPIM2_CSEL5_GPIO13 \ + ESP32_PINMUX(13, ESP_NOSIG, ESP_FSPICS5_OUT) + +#define SPIM2_CSEL5_GPIO14 \ + ESP32_PINMUX(14, ESP_NOSIG, ESP_FSPICS5_OUT) + +#define SPIM2_CSEL5_GPIO15 \ + ESP32_PINMUX(15, ESP_NOSIG, ESP_FSPICS5_OUT) + +#define SPIM2_CSEL5_GPIO16 \ + ESP32_PINMUX(16, ESP_NOSIG, ESP_FSPICS5_OUT) + +#define SPIM2_CSEL5_GPIO17 \ + ESP32_PINMUX(17, ESP_NOSIG, ESP_FSPICS5_OUT) + +#define SPIM2_CSEL5_GPIO18 \ + ESP32_PINMUX(18, ESP_NOSIG, ESP_FSPICS5_OUT) + +#define SPIM2_CSEL5_GPIO19 \ + ESP32_PINMUX(19, ESP_NOSIG, ESP_FSPICS5_OUT) + +#define SPIM2_CSEL5_GPIO20 \ + ESP32_PINMUX(20, ESP_NOSIG, ESP_FSPICS5_OUT) + +#define SPIM2_CSEL5_GPIO21 \ + ESP32_PINMUX(21, ESP_NOSIG, ESP_FSPICS5_OUT) + +#define SPIM2_CSEL5_GPIO22 \ + ESP32_PINMUX(22, ESP_NOSIG, ESP_FSPICS5_OUT) + +#define SPIM2_CSEL5_GPIO23 \ + ESP32_PINMUX(23, ESP_NOSIG, ESP_FSPICS5_OUT) + +/* SPIM2_MISO */ +#define SPIM2_MISO_GPIO0 \ + ESP32_PINMUX(0, ESP_FSPIQ_IN, ESP_NOSIG) + +#define SPIM2_MISO_GPIO1 \ + ESP32_PINMUX(1, ESP_FSPIQ_IN, ESP_NOSIG) + +#define SPIM2_MISO_GPIO2 \ + ESP32_PINMUX(2, ESP_FSPIQ_IN, ESP_NOSIG) + +#define SPIM2_MISO_GPIO3 \ + ESP32_PINMUX(3, ESP_FSPIQ_IN, ESP_NOSIG) + +#define SPIM2_MISO_GPIO4 \ + ESP32_PINMUX(4, ESP_FSPIQ_IN, ESP_NOSIG) + +#define SPIM2_MISO_GPIO5 \ + ESP32_PINMUX(5, ESP_FSPIQ_IN, ESP_NOSIG) + +#define SPIM2_MISO_GPIO6 \ + ESP32_PINMUX(6, ESP_FSPIQ_IN, ESP_NOSIG) + +#define SPIM2_MISO_GPIO7 \ + ESP32_PINMUX(7, ESP_FSPIQ_IN, ESP_NOSIG) + +#define SPIM2_MISO_GPIO8 \ + ESP32_PINMUX(8, ESP_FSPIQ_IN, ESP_NOSIG) + +#define SPIM2_MISO_GPIO9 \ + ESP32_PINMUX(9, ESP_FSPIQ_IN, ESP_NOSIG) + +#define SPIM2_MISO_GPIO10 \ + ESP32_PINMUX(10, ESP_FSPIQ_IN, ESP_NOSIG) + +#define SPIM2_MISO_GPIO11 \ + ESP32_PINMUX(11, ESP_FSPIQ_IN, ESP_NOSIG) + +#define SPIM2_MISO_GPIO12 \ + ESP32_PINMUX(12, ESP_FSPIQ_IN, ESP_NOSIG) + +#define SPIM2_MISO_GPIO13 \ + ESP32_PINMUX(13, ESP_FSPIQ_IN, ESP_NOSIG) + +#define SPIM2_MISO_GPIO14 \ + ESP32_PINMUX(14, ESP_FSPIQ_IN, ESP_NOSIG) + +#define SPIM2_MISO_GPIO15 \ + ESP32_PINMUX(15, ESP_FSPIQ_IN, ESP_NOSIG) + +#define SPIM2_MISO_GPIO16 \ + ESP32_PINMUX(16, ESP_FSPIQ_IN, ESP_NOSIG) + +#define SPIM2_MISO_GPIO17 \ + ESP32_PINMUX(17, ESP_FSPIQ_IN, ESP_NOSIG) + +#define SPIM2_MISO_GPIO18 \ + ESP32_PINMUX(18, ESP_FSPIQ_IN, ESP_NOSIG) + +#define SPIM2_MISO_GPIO19 \ + ESP32_PINMUX(19, ESP_FSPIQ_IN, ESP_NOSIG) + +#define SPIM2_MISO_GPIO20 \ + ESP32_PINMUX(20, ESP_FSPIQ_IN, ESP_NOSIG) + +#define SPIM2_MISO_GPIO21 \ + ESP32_PINMUX(21, ESP_FSPIQ_IN, ESP_NOSIG) + +#define SPIM2_MISO_GPIO22 \ + ESP32_PINMUX(22, ESP_FSPIQ_IN, ESP_NOSIG) + +#define SPIM2_MISO_GPIO23 \ + ESP32_PINMUX(23, ESP_FSPIQ_IN, ESP_NOSIG) + +/* SPIM2_MOSI */ +#define SPIM2_MOSI_GPIO0 \ + ESP32_PINMUX(0, ESP_NOSIG, ESP_FSPID_OUT) + +#define SPIM2_MOSI_GPIO1 \ + ESP32_PINMUX(1, ESP_NOSIG, ESP_FSPID_OUT) + +#define SPIM2_MOSI_GPIO2 \ + ESP32_PINMUX(2, ESP_NOSIG, ESP_FSPID_OUT) + +#define SPIM2_MOSI_GPIO3 \ + ESP32_PINMUX(3, ESP_NOSIG, ESP_FSPID_OUT) + +#define SPIM2_MOSI_GPIO4 \ + ESP32_PINMUX(4, ESP_NOSIG, ESP_FSPID_OUT) + +#define SPIM2_MOSI_GPIO5 \ + ESP32_PINMUX(5, ESP_NOSIG, ESP_FSPID_OUT) + +#define SPIM2_MOSI_GPIO6 \ + ESP32_PINMUX(6, ESP_NOSIG, ESP_FSPID_OUT) + +#define SPIM2_MOSI_GPIO7 \ + ESP32_PINMUX(7, ESP_NOSIG, ESP_FSPID_OUT) + +#define SPIM2_MOSI_GPIO8 \ + ESP32_PINMUX(8, ESP_NOSIG, ESP_FSPID_OUT) + +#define SPIM2_MOSI_GPIO9 \ + ESP32_PINMUX(9, ESP_NOSIG, ESP_FSPID_OUT) + +#define SPIM2_MOSI_GPIO10 \ + ESP32_PINMUX(10, ESP_NOSIG, ESP_FSPID_OUT) + +#define SPIM2_MOSI_GPIO11 \ + ESP32_PINMUX(11, ESP_NOSIG, ESP_FSPID_OUT) + +#define SPIM2_MOSI_GPIO12 \ + ESP32_PINMUX(12, ESP_NOSIG, ESP_FSPID_OUT) + +#define SPIM2_MOSI_GPIO13 \ + ESP32_PINMUX(13, ESP_NOSIG, ESP_FSPID_OUT) + +#define SPIM2_MOSI_GPIO14 \ + ESP32_PINMUX(14, ESP_NOSIG, ESP_FSPID_OUT) + +#define SPIM2_MOSI_GPIO15 \ + ESP32_PINMUX(15, ESP_NOSIG, ESP_FSPID_OUT) + +#define SPIM2_MOSI_GPIO16 \ + ESP32_PINMUX(16, ESP_NOSIG, ESP_FSPID_OUT) + +#define SPIM2_MOSI_GPIO17 \ + ESP32_PINMUX(17, ESP_NOSIG, ESP_FSPID_OUT) + +#define SPIM2_MOSI_GPIO18 \ + ESP32_PINMUX(18, ESP_NOSIG, ESP_FSPID_OUT) + +#define SPIM2_MOSI_GPIO19 \ + ESP32_PINMUX(19, ESP_NOSIG, ESP_FSPID_OUT) + +#define SPIM2_MOSI_GPIO20 \ + ESP32_PINMUX(20, ESP_NOSIG, ESP_FSPID_OUT) + +#define SPIM2_MOSI_GPIO21 \ + ESP32_PINMUX(21, ESP_NOSIG, ESP_FSPID_OUT) + +#define SPIM2_MOSI_GPIO22 \ + ESP32_PINMUX(22, ESP_NOSIG, ESP_FSPID_OUT) + +#define SPIM2_MOSI_GPIO23 \ + ESP32_PINMUX(23, ESP_NOSIG, ESP_FSPID_OUT) + +/* SPIM2_SCLK */ +#define SPIM2_SCLK_GPIO0 \ + ESP32_PINMUX(0, ESP_NOSIG, ESP_FSPICLK_OUT) + +#define SPIM2_SCLK_GPIO1 \ + ESP32_PINMUX(1, ESP_NOSIG, ESP_FSPICLK_OUT) + +#define SPIM2_SCLK_GPIO2 \ + ESP32_PINMUX(2, ESP_NOSIG, ESP_FSPICLK_OUT) + +#define SPIM2_SCLK_GPIO3 \ + ESP32_PINMUX(3, ESP_NOSIG, ESP_FSPICLK_OUT) + +#define SPIM2_SCLK_GPIO4 \ + ESP32_PINMUX(4, ESP_NOSIG, ESP_FSPICLK_OUT) + +#define SPIM2_SCLK_GPIO5 \ + ESP32_PINMUX(5, ESP_NOSIG, ESP_FSPICLK_OUT) + +#define SPIM2_SCLK_GPIO6 \ + ESP32_PINMUX(6, ESP_NOSIG, ESP_FSPICLK_OUT) + +#define SPIM2_SCLK_GPIO7 \ + ESP32_PINMUX(7, ESP_NOSIG, ESP_FSPICLK_OUT) + +#define SPIM2_SCLK_GPIO8 \ + ESP32_PINMUX(8, ESP_NOSIG, ESP_FSPICLK_OUT) + +#define SPIM2_SCLK_GPIO9 \ + ESP32_PINMUX(9, ESP_NOSIG, ESP_FSPICLK_OUT) + +#define SPIM2_SCLK_GPIO10 \ + ESP32_PINMUX(10, ESP_NOSIG, ESP_FSPICLK_OUT) + +#define SPIM2_SCLK_GPIO11 \ + ESP32_PINMUX(11, ESP_NOSIG, ESP_FSPICLK_OUT) + +#define SPIM2_SCLK_GPIO12 \ + ESP32_PINMUX(12, ESP_NOSIG, ESP_FSPICLK_OUT) + +#define SPIM2_SCLK_GPIO13 \ + ESP32_PINMUX(13, ESP_NOSIG, ESP_FSPICLK_OUT) + +#define SPIM2_SCLK_GPIO14 \ + ESP32_PINMUX(14, ESP_NOSIG, ESP_FSPICLK_OUT) + +#define SPIM2_SCLK_GPIO15 \ + ESP32_PINMUX(15, ESP_NOSIG, ESP_FSPICLK_OUT) + +#define SPIM2_SCLK_GPIO16 \ + ESP32_PINMUX(16, ESP_NOSIG, ESP_FSPICLK_OUT) + +#define SPIM2_SCLK_GPIO17 \ + ESP32_PINMUX(17, ESP_NOSIG, ESP_FSPICLK_OUT) + +#define SPIM2_SCLK_GPIO18 \ + ESP32_PINMUX(18, ESP_NOSIG, ESP_FSPICLK_OUT) + +#define SPIM2_SCLK_GPIO19 \ + ESP32_PINMUX(19, ESP_NOSIG, ESP_FSPICLK_OUT) + +#define SPIM2_SCLK_GPIO20 \ + ESP32_PINMUX(20, ESP_NOSIG, ESP_FSPICLK_OUT) + +#define SPIM2_SCLK_GPIO21 \ + ESP32_PINMUX(21, ESP_NOSIG, ESP_FSPICLK_OUT) + +#define SPIM2_SCLK_GPIO22 \ + ESP32_PINMUX(22, ESP_NOSIG, ESP_FSPICLK_OUT) + +#define SPIM2_SCLK_GPIO23 \ + ESP32_PINMUX(23, ESP_NOSIG, ESP_FSPICLK_OUT) + /* UART0_CTS */ #define UART0_CTS_GPIO0 \ ESP32_PINMUX(0, ESP_U0CTS_IN, ESP_NOSIG) From 4a68b3be91d32b287106ebcb6685c3357b602519 Mon Sep 17 00:00:00 2001 From: Raffael Rostagno Date: Mon, 13 May 2024 15:22:13 -0300 Subject: [PATCH 2843/2849] boards: esp32c6_devkitc: Added support for GP-SPI2 Added support for general purpose SPI2 (GP-SPI2) Signed-off-by: Raffael Rostagno --- .../esp32c6_devkitc-pinctrl.dtsi | 12 +++++ .../esp32c6_devkitc/esp32c6_devkitc.dts | 8 ++++ .../spi/spi_loopback/socs/esp32c6.conf | 2 + .../spi/spi_loopback/socs/esp32c6.overlay | 44 +++++++++++++++++++ 4 files changed, 66 insertions(+) create mode 100644 tests/drivers/spi/spi_loopback/socs/esp32c6.conf create mode 100644 tests/drivers/spi/spi_loopback/socs/esp32c6.overlay diff --git a/boards/espressif/esp32c6_devkitc/esp32c6_devkitc-pinctrl.dtsi b/boards/espressif/esp32c6_devkitc/esp32c6_devkitc-pinctrl.dtsi index 410001220a38d..a9cda93d22a35 100644 --- a/boards/espressif/esp32c6_devkitc/esp32c6_devkitc-pinctrl.dtsi +++ b/boards/espressif/esp32c6_devkitc/esp32c6_devkitc-pinctrl.dtsi @@ -20,4 +20,16 @@ bias-pull-up; }; }; + + spim2_default: spim2_default { + group1 { + pinmux = , + , + ; + }; + group2 { + pinmux = ; + output-low; + }; + }; }; diff --git a/boards/espressif/esp32c6_devkitc/esp32c6_devkitc.dts b/boards/espressif/esp32c6_devkitc/esp32c6_devkitc.dts index af3c57f11f939..c69aba1ddae84 100644 --- a/boards/espressif/esp32c6_devkitc/esp32c6_devkitc.dts +++ b/boards/espressif/esp32c6_devkitc/esp32c6_devkitc.dts @@ -46,6 +46,14 @@ pinctrl-names = "default"; }; +&spi2 { + #address-cells = <1>; + #size-cells = <0>; + status = "okay"; + pinctrl-0 = <&spim2_default>; + pinctrl-names = "default"; +}; + &gpio0 { status = "okay"; }; diff --git a/tests/drivers/spi/spi_loopback/socs/esp32c6.conf b/tests/drivers/spi/spi_loopback/socs/esp32c6.conf new file mode 100644 index 0000000000000..3438f794f66ae --- /dev/null +++ b/tests/drivers/spi/spi_loopback/socs/esp32c6.conf @@ -0,0 +1,2 @@ +CONFIG_SPI_ESP32_INTERRUPT=y +CONFIG_HEAP_MEM_POOL_SIZE=32768 diff --git a/tests/drivers/spi/spi_loopback/socs/esp32c6.overlay b/tests/drivers/spi/spi_loopback/socs/esp32c6.overlay new file mode 100644 index 0000000000000..f34b784339cfc --- /dev/null +++ b/tests/drivers/spi/spi_loopback/socs/esp32c6.overlay @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2022 Kumar Gala + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&pinctrl { + spim2_loopback: spim2_loopback { + group1 { + pinmux = ; + output-enable; /* Connect GPIO2 and GPIO3 externally for testing */ + }; + group2 { + pinmux = ; + input-enable; /* Connect GPIO2 and GPIO3 externally for testing */ + }; + group3 { + pinmux = , + ; + }; + }; +}; + +&spi2 { + slow@0 { + compatible = "test-spi-loopback-slow"; + reg = <0>; + spi-max-frequency = <500000>; + }; + fast@0 { + compatible = "test-spi-loopback-fast"; + reg = <0>; + spi-max-frequency = <16000000>; + }; +}; + +&spi2 { + #address-cells = <1>; + #size-cells = <0>; + dma-enabled; + pinctrl-0 = <&spim2_loopback>; + pinctrl-names = "default"; + status = "okay"; +}; From 28ac43f2b0763504fc8e802176f46287bbb38ec0 Mon Sep 17 00:00:00 2001 From: Raffael Rostagno Date: Tue, 14 May 2024 12:33:47 -0300 Subject: [PATCH 2844/2849] drivers: intc: Fix for ESP32C6 interrupt sources allocation Fix to properly allocate IRQs for interrupt sources over 60. It also screens out non-allocatable IRQs used by the CPU. Signed-off-by: Raffael Rostagno --- drivers/interrupt_controller/Kconfig.esp32 | 2 +- drivers/interrupt_controller/Kconfig.esp32c3 | 2 +- drivers/interrupt_controller/intc_esp32c3.c | 114 ++++++++++++++++--- soc/espressif/esp32c6/soc_irq.c | 29 ++++- 4 files changed, 124 insertions(+), 23 deletions(-) diff --git a/drivers/interrupt_controller/Kconfig.esp32 b/drivers/interrupt_controller/Kconfig.esp32 index 1d88fcb196605..26d6a0f56fef8 100644 --- a/drivers/interrupt_controller/Kconfig.esp32 +++ b/drivers/interrupt_controller/Kconfig.esp32 @@ -5,7 +5,7 @@ config INTC_ESP32 bool "Interrupt allocator for Xtensa-based Espressif SoCs" - default y if SOC_FAMILY_ESPRESSIF_ESP32 && !SOC_SERIES_ESP32C3 + default y if SOC_FAMILY_ESPRESSIF_ESP32 && !SOC_SERIES_ESP32C3 && !SOC_SERIES_ESP32C6 help Enable custom interrupt allocator for Espressif SoCs based on Xtensa architecture. diff --git a/drivers/interrupt_controller/Kconfig.esp32c3 b/drivers/interrupt_controller/Kconfig.esp32c3 index c6d4b7da88f6f..f2bb54b0fc80e 100644 --- a/drivers/interrupt_controller/Kconfig.esp32c3 +++ b/drivers/interrupt_controller/Kconfig.esp32c3 @@ -3,7 +3,7 @@ config INTC_ESP32C3 bool "ESP32C3 interrupt controller driver" - depends on SOC_SERIES_ESP32C3 + depends on SOC_SERIES_ESP32C3 || SOC_SERIES_ESP32C6 default y help Enables the esp32c3 interrupt controller driver to handle ISR diff --git a/drivers/interrupt_controller/intc_esp32c3.c b/drivers/interrupt_controller/intc_esp32c3.c index 6293afd07f123..575254ecdfae7 100644 --- a/drivers/interrupt_controller/intc_esp32c3.c +++ b/drivers/interrupt_controller/intc_esp32c3.c @@ -41,7 +41,34 @@ LOG_MODULE_REGISTER(intc_esp32c3, CONFIG_LOG_DEFAULT_LEVEL); #define ESP32C3_INTC_SRCS_PER_IRQ 2 #define ESP32C3_INTC_AVAILABLE_IRQS 30 -static uint32_t esp_intr_enabled_mask[2] = {0, 0}; +#if defined(CONFIG_SOC_SERIES_ESP32C6) + +#define IRQ_NA 0xFF /* IRQ not available */ +#define IRQ_FREE 0xFE + +#define ESP32C6_INTC_SRCS_PER_IRQ 2 +#define ESP32C6_INTC_AVAILABLE_IRQS 31 + +/* For ESP32C6 only CPU peripheral interrupts number + * 1, 2, 5, 6, 8 ~ 31 are available. + * IRQ 31 is reserved for disabled interrupts + */ +static uint8_t esp_intr_irq_alloc[ESP32C6_INTC_AVAILABLE_IRQS][ESP32C6_INTC_SRCS_PER_IRQ] = { + [0] = {IRQ_NA, IRQ_NA}, + [3] = {IRQ_NA, IRQ_NA}, + [4] = {IRQ_NA, IRQ_NA}, + [7] = {IRQ_NA, IRQ_NA}, + [1 ... 2] = {IRQ_FREE, IRQ_FREE}, + [5 ... 6] = {IRQ_FREE, IRQ_FREE}, + [8 ... 30] = {IRQ_FREE, IRQ_FREE} +}; +#endif + +#define STATUS_MASK_NUM 3 + +static uint32_t esp_intr_enabled_mask[STATUS_MASK_NUM] = {0, 0, 0}; + +#if defined(CONFIG_SOC_SERIES_ESP32C3) static uint32_t esp_intr_find_irq_for_source(uint32_t source) { @@ -62,6 +89,33 @@ static uint32_t esp_intr_find_irq_for_source(uint32_t source) return irq; } +#elif defined(CONFIG_SOC_SERIES_ESP32C6) + +static uint32_t esp_intr_find_irq_for_source(uint32_t source) +{ + uint32_t irq = 0; + + /* First allocate one source per IRQ, then two + * if there are more sources than free IRQs + */ + for (int j = 0; j < ESP32C6_INTC_SRCS_PER_IRQ; j++) { + for (int i = 0; i < ESP32C6_INTC_AVAILABLE_IRQS; i++) { + if (esp_intr_irq_alloc[i][j] == IRQ_FREE) { + esp_intr_irq_alloc[i][j] = (uint8_t)source; + irq = i; + goto found; + } + } + } + +found: + INTC_LOG("Found IRQ: %d for source: %d", irq, source); + + return irq; +} + +#endif + void esp_intr_initialize(void) { /* IRQ 31 is reserved for disabled interrupts, @@ -75,6 +129,18 @@ void esp_intr_initialize(void) esp_rom_intr_matrix_set(0, i, ESP32C3_INTC_DISABLED_SLOT); } +#if defined(CONFIG_SOC_SERIES_ESP32C6) + /* Clear up IRQ allocation */ + for (int j = 0; j < ESP32C6_INTC_SRCS_PER_IRQ; j++) { + for (int i = 0; i < ESP32C6_INTC_AVAILABLE_IRQS; i++) { + /* screen out reserved IRQs */ + if (esp_intr_irq_alloc[i][j] != IRQ_NA) { + esp_intr_irq_alloc[i][j] = IRQ_FREE; + } + } + } +#endif + /* set global esp32c3's INTC masking level */ esprv_intc_int_set_threshold(ESP32C3_INTC_DEFAULT_THRESHOLD); } @@ -106,12 +172,14 @@ int esp_intr_alloc(int source, if (source < 32) { esp_intr_enabled_mask[0] |= (1 << source); - } else { + } else if (source < 64) { esp_intr_enabled_mask[1] |= (1 << (source - 32)); + } else if (source < 96) { + esp_intr_enabled_mask[2] |= (1 << (source - 64)); } - INTC_LOG("Enabled ISRs -- 0: 0x%X -- 1: 0x%X", - esp_intr_enabled_mask[0], esp_intr_enabled_mask[1]); + INTC_LOG("Enabled ISRs -- 0: 0x%X -- 1: 0x%X -- 2: 0x%X", + esp_intr_enabled_mask[0], esp_intr_enabled_mask[1], esp_intr_enabled_mask[2]); irq_unlock(key); irq_enable(source); @@ -131,14 +199,28 @@ int esp_intr_disable(int source) source, ESP32C3_INTC_DISABLED_SLOT); +#if defined(CONFIG_SOC_SERIES_ESP32C6) + for (int j = 0; j < ESP32C6_INTC_SRCS_PER_IRQ; j++) { + for (int i = 0; i < ESP32C6_INTC_AVAILABLE_IRQS; i++) { + if (esp_intr_irq_alloc[i][j] == source) { + esp_intr_irq_alloc[i][j] = IRQ_FREE; + goto freed; + } + } + } +freed: +#endif + if (source < 32) { esp_intr_enabled_mask[0] &= ~(1 << source); - } else { + } else if (source < 64) { esp_intr_enabled_mask[1] &= ~(1 << (source - 32)); + } else if (source < 96) { + esp_intr_enabled_mask[2] &= ~(1 << (source - 64)); } - INTC_LOG("Enabled ISRs -- 0: 0x%X -- 1: 0x%X", - esp_intr_enabled_mask[0], esp_intr_enabled_mask[1]); + INTC_LOG("Enabled ISRs -- 0: 0x%X -- 1: 0x%X -- 2: 0x%X", + esp_intr_enabled_mask[0], esp_intr_enabled_mask[1], esp_intr_enabled_mask[2]); irq_unlock(key); @@ -158,12 +240,14 @@ int esp_intr_enable(int source) if (source < 32) { esp_intr_enabled_mask[0] |= (1 << source); - } else { + } else if (source < 64) { esp_intr_enabled_mask[1] |= (1 << (source - 32)); + } else if (source < 96) { + esp_intr_enabled_mask[2] |= (1 << (source - 64)); } - INTC_LOG("Enabled ISRs -- 0: 0x%X -- 1: 0x%X", - esp_intr_enabled_mask[0], esp_intr_enabled_mask[1]); + INTC_LOG("Enabled ISRs -- 0: 0x%X -- 1: 0x%X -- 2: 0x%X", + esp_intr_enabled_mask[0], esp_intr_enabled_mask[1], esp_intr_enabled_mask[2]); esprv_intc_int_set_priority(irq, ESP32C3_INTC_DEFAULT_PRIO); esprv_intc_int_set_type(irq, INTR_TYPE_LEVEL); @@ -176,12 +260,12 @@ int esp_intr_enable(int source) uint32_t esp_intr_get_enabled_intmask(int status_mask_number) { - INTC_LOG("Enabled ISRs -- 0: 0x%X -- 1: 0x%X", - esp_intr_enabled_mask[0], esp_intr_enabled_mask[1]); + INTC_LOG("Enabled ISRs -- 0: 0x%X -- 1: 0x%X -- 2: 0x%X", + esp_intr_enabled_mask[0], esp_intr_enabled_mask[1], esp_intr_enabled_mask[2]); - if (status_mask_number == 0) { - return esp_intr_enabled_mask[0]; + if (status_mask_number < STATUS_MASK_NUM) { + return esp_intr_enabled_mask[status_mask_number]; } else { - return esp_intr_enabled_mask[1]; + return 0; /* error */ } } diff --git a/soc/espressif/esp32c6/soc_irq.c b/soc/espressif/esp32c6/soc_irq.c index 42e5e47eaf2f2..6a452ec78b956 100644 --- a/soc/espressif/esp32c6/soc_irq.c +++ b/soc/espressif/esp32c6/soc_irq.c @@ -19,7 +19,8 @@ #include #include -#define ESP32C6_INTSTATUS_SLOT1_THRESHOLD 32 +#define ESP32C6_INTSTATUS_REG1_THRESHOLD 32 +#define ESP32C6_INTSTATUS_REG2_THRESHOLD 64 void arch_irq_enable(unsigned int irq) { @@ -38,8 +39,10 @@ int arch_irq_is_enabled(unsigned int irq) if (irq < 32) { res = esp_intr_get_enabled_intmask(0) & BIT(irq); - } else { + } else if (irq < 64) { res = esp_intr_get_enabled_intmask(1) & BIT(irq - 32); + } else { + res = esp_intr_get_enabled_intmask(2) & BIT(irq - 64); } irq_unlock(key); @@ -52,16 +55,30 @@ uint32_t soc_intr_get_next_source(void) uint32_t status; uint32_t source; + /* Status register for interrupt sources 0 ~ 31 */ status = REG_READ(INTMTX_CORE0_INT_STATUS_REG_0_REG) & esp_intr_get_enabled_intmask(0); if (status) { source = __builtin_ffs(status) - 1; - } else { - status = REG_READ(INTMTX_CORE0_INT_STATUS_REG_1_REG) & - esp_intr_get_enabled_intmask(1); - source = (__builtin_ffs(status) - 1 + ESP32C6_INTSTATUS_SLOT1_THRESHOLD); + goto ret; } + /* Status register for interrupt sources 32 ~ 63 */ + status = REG_READ(INTMTX_CORE0_INT_STATUS_REG_1_REG) & + esp_intr_get_enabled_intmask(1); + + if (status) { + source = (__builtin_ffs(status) - 1 + ESP32C6_INTSTATUS_REG1_THRESHOLD); + goto ret; + } + + /* Status register for interrupt sources 64 ~ 76 */ + status = REG_READ(INTMTX_CORE0_INT_STATUS_REG_2_REG) & + esp_intr_get_enabled_intmask(2); + + source = (__builtin_ffs(status) - 1 + ESP32C6_INTSTATUS_REG2_THRESHOLD); + +ret: return source; } From b194080aba3a1367633c0e939fa486a70f7344fc Mon Sep 17 00:00:00 2001 From: Raffael Rostagno Date: Tue, 21 May 2024 11:41:15 -0300 Subject: [PATCH 2845/2849] drivers: ledc: Clock source update to support ESP32C6 Clock source SCLK added for C6 on LEDC Signed-off-by: Raffael Rostagno --- drivers/pwm/pwm_led_esp32.c | 25 +- .../espressif/esp32c6/esp32c6_common.dtsi | 9 + .../dt-bindings/pinctrl/esp32c6-pinctrl.h | 438 ++++++++++++++++++ 3 files changed, 471 insertions(+), 1 deletion(-) diff --git a/drivers/pwm/pwm_led_esp32.c b/drivers/pwm/pwm_led_esp32.c index 1754d5dc36d7f..fb20ae19ce7d9 100644 --- a/drivers/pwm/pwm_led_esp32.c +++ b/drivers/pwm/pwm_led_esp32.c @@ -124,7 +124,11 @@ static int pwm_led_esp32_calculate_max_resolution(struct pwm_ledc_esp32_channel_ * Max duty resolution can be obtained with * max_res = log2(CLK_FREQ/FREQ) */ +#if SOC_LEDC_SUPPORT_APB_CLOCK uint64_t clock_freq = channel->clock_src == LEDC_APB_CLK ? APB_CLK_FREQ : REF_CLK_FREQ; +#elif SOC_LEDC_SUPPORT_PLL_DIV_CLOCK + uint64_t clock_freq = SCLK_CLK_FREQ; +#endif uint32_t max_precision_n = clock_freq/channel->freq; for (uint8_t i = 0; i <= SOC_LEDC_TIMER_BIT_WIDTH; i++) { @@ -159,7 +163,9 @@ static int pwm_led_esp32_timer_config(struct pwm_ledc_esp32_channel_config *chan * If the given frequency doesn't support it, we move to the next clock source. */ +#if SOC_LEDC_SUPPORT_APB_CLOCK channel->clock_src = LEDC_APB_CLK; +#endif if (!pwm_led_esp32_calculate_max_resolution(channel)) { return 0; } @@ -194,6 +200,7 @@ static int pwm_led_esp32_timer_set(const struct device *dev, __ASSERT_NO_MSG(channel->freq > 0); switch (channel->clock_src) { +#if SOC_LEDC_SUPPORT_APB_CLOCK case LEDC_APB_CLK: /** This expression comes from ESP32 Espressif's Technical Reference * Manual chapter 13.2.2 Timers. @@ -201,6 +208,12 @@ static int pwm_led_esp32_timer_set(const struct device *dev, */ prescaler = ((uint64_t) APB_CLK_FREQ << 8) / channel->freq / precision; break; +#endif +#if SOC_LEDC_SUPPORT_PLL_DIV_CLOCK + case LEDC_SCLK: + prescaler = ((uint64_t) SCLK_CLK_FREQ << 8) / channel->freq / precision; + break; +#endif #if SOC_LEDC_SUPPORT_REF_TICK case LEDC_REF_TICK: prescaler = ((uint64_t) REF_CLK_FREQ << 8) / channel->freq / precision; @@ -245,7 +258,11 @@ static int pwm_led_esp32_get_cycles_per_sec(const struct device *dev, return -EINVAL; } +#if SOC_LEDC_SUPPORT_APB_CLOCK *cycles = channel->clock_src == LEDC_APB_CLK ? APB_CLK_FREQ : REF_CLK_FREQ; +#elif SOC_LEDC_SUPPORT_PLL_DIV_CLOCK + *cycles = SCLK_CLK_FREQ; +#endif return 0; } @@ -338,6 +355,12 @@ static const struct pwm_driver_api pwm_led_esp32_api = { PINCTRL_DT_INST_DEFINE(0); +#if SOC_LEDC_SUPPORT_APB_CLOCK + #define CLOCK_SOURCE LEDC_APB_CLK +#elif SOC_LEDC_SUPPORT_PLL_DIV_CLOCK + #define CLOCK_SOURCE LEDC_SCLK +#endif + #define CHANNEL_CONFIG(node_id) \ { \ .idx = DT_REG_ADDR(node_id), \ @@ -346,7 +369,7 @@ PINCTRL_DT_INST_DEFINE(0); .speed_mode = DT_REG_ADDR(node_id) < SOC_LEDC_CHANNEL_NUM \ ? LEDC_LOW_SPEED_MODE \ : !LEDC_LOW_SPEED_MODE, \ - .clock_src = LEDC_APB_CLK, \ + .clock_src = CLOCK_SOURCE, \ }, static struct pwm_ledc_esp32_channel_config channel_config[] = { diff --git a/dts/riscv/espressif/esp32c6/esp32c6_common.dtsi b/dts/riscv/espressif/esp32c6/esp32c6_common.dtsi index 72d87e21d3586..38e2be850afaa 100644 --- a/dts/riscv/espressif/esp32c6/esp32c6_common.dtsi +++ b/dts/riscv/espressif/esp32c6/esp32c6_common.dtsi @@ -149,6 +149,15 @@ clocks = <&rtc ESP32_UART1_MODULE>; current-speed = <115200>; }; + + ledc0: ledc@60007000 { + compatible = "espressif,esp32-ledc"; + pwm-controller; + #pwm-cells = <3>; + reg = <0x60007000 0x1000>; + clocks = <&rtc ESP32_LEDC_MODULE>; + status = "disabled"; + }; }; }; diff --git a/include/zephyr/dt-bindings/pinctrl/esp32c6-pinctrl.h b/include/zephyr/dt-bindings/pinctrl/esp32c6-pinctrl.h index 22ecad22f681b..6c80beb59d5a7 100644 --- a/include/zephyr/dt-bindings/pinctrl/esp32c6-pinctrl.h +++ b/include/zephyr/dt-bindings/pinctrl/esp32c6-pinctrl.h @@ -9,6 +9,444 @@ #ifndef INC_DT_BINDS_PINCTRL_ESP32C6_PINCTRL_HAL_H_ #define INC_DT_BINDS_PINCTRL_ESP32C6_PINCTRL_HAL_H_ +/* LEDC_CH0 */ +#define LEDC_CH0_GPIO0 \ + ESP32_PINMUX(0, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT0) + +#define LEDC_CH0_GPIO1 \ + ESP32_PINMUX(1, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT0) + +#define LEDC_CH0_GPIO2 \ + ESP32_PINMUX(2, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT0) + +#define LEDC_CH0_GPIO3 \ + ESP32_PINMUX(3, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT0) + +#define LEDC_CH0_GPIO4 \ + ESP32_PINMUX(4, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT0) + +#define LEDC_CH0_GPIO5 \ + ESP32_PINMUX(5, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT0) + +#define LEDC_CH0_GPIO6 \ + ESP32_PINMUX(6, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT0) + +#define LEDC_CH0_GPIO7 \ + ESP32_PINMUX(7, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT0) + +#define LEDC_CH0_GPIO8 \ + ESP32_PINMUX(8, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT0) + +#define LEDC_CH0_GPIO9 \ + ESP32_PINMUX(9, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT0) + +#define LEDC_CH0_GPIO10 \ + ESP32_PINMUX(10, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT0) + +#define LEDC_CH0_GPIO11 \ + ESP32_PINMUX(11, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT0) + +#define LEDC_CH0_GPIO12 \ + ESP32_PINMUX(12, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT0) + +#define LEDC_CH0_GPIO13 \ + ESP32_PINMUX(13, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT0) + +#define LEDC_CH0_GPIO14 \ + ESP32_PINMUX(14, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT0) + +#define LEDC_CH0_GPIO15 \ + ESP32_PINMUX(15, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT0) + +#define LEDC_CH0_GPIO16 \ + ESP32_PINMUX(16, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT0) + +#define LEDC_CH0_GPIO17 \ + ESP32_PINMUX(17, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT0) + +#define LEDC_CH0_GPIO18 \ + ESP32_PINMUX(18, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT0) + +#define LEDC_CH0_GPIO19 \ + ESP32_PINMUX(19, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT0) + +#define LEDC_CH0_GPIO20 \ + ESP32_PINMUX(20, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT0) + +#define LEDC_CH0_GPIO21 \ + ESP32_PINMUX(21, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT0) + +#define LEDC_CH0_GPIO22 \ + ESP32_PINMUX(22, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT0) + +#define LEDC_CH0_GPIO23 \ + ESP32_PINMUX(23, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT0) + +/* LEDC_CH1 */ +#define LEDC_CH1_GPIO0 \ + ESP32_PINMUX(0, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT1) + +#define LEDC_CH1_GPIO1 \ + ESP32_PINMUX(1, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT1) + +#define LEDC_CH1_GPIO2 \ + ESP32_PINMUX(2, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT1) + +#define LEDC_CH1_GPIO3 \ + ESP32_PINMUX(3, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT1) + +#define LEDC_CH1_GPIO4 \ + ESP32_PINMUX(4, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT1) + +#define LEDC_CH1_GPIO5 \ + ESP32_PINMUX(5, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT1) + +#define LEDC_CH1_GPIO6 \ + ESP32_PINMUX(6, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT1) + +#define LEDC_CH1_GPIO7 \ + ESP32_PINMUX(7, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT1) + +#define LEDC_CH1_GPIO8 \ + ESP32_PINMUX(8, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT1) + +#define LEDC_CH1_GPIO9 \ + ESP32_PINMUX(9, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT1) + +#define LEDC_CH1_GPIO10 \ + ESP32_PINMUX(10, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT1) + +#define LEDC_CH1_GPIO11 \ + ESP32_PINMUX(11, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT1) + +#define LEDC_CH1_GPIO12 \ + ESP32_PINMUX(12, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT1) + +#define LEDC_CH1_GPIO13 \ + ESP32_PINMUX(13, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT1) + +#define LEDC_CH1_GPIO14 \ + ESP32_PINMUX(14, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT1) + +#define LEDC_CH1_GPIO15 \ + ESP32_PINMUX(15, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT1) + +#define LEDC_CH1_GPIO16 \ + ESP32_PINMUX(16, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT1) + +#define LEDC_CH1_GPIO17 \ + ESP32_PINMUX(17, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT1) + +#define LEDC_CH1_GPIO18 \ + ESP32_PINMUX(18, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT1) + +#define LEDC_CH1_GPIO19 \ + ESP32_PINMUX(19, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT1) + +#define LEDC_CH1_GPIO20 \ + ESP32_PINMUX(20, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT1) + +#define LEDC_CH1_GPIO21 \ + ESP32_PINMUX(21, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT1) + +#define LEDC_CH1_GPIO22 \ + ESP32_PINMUX(22, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT1) + +#define LEDC_CH1_GPIO23 \ + ESP32_PINMUX(23, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT1) + +/* LEDC_CH2 */ +#define LEDC_CH2_GPIO0 \ + ESP32_PINMUX(0, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT2) + +#define LEDC_CH2_GPIO1 \ + ESP32_PINMUX(1, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT2) + +#define LEDC_CH2_GPIO2 \ + ESP32_PINMUX(2, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT2) + +#define LEDC_CH2_GPIO3 \ + ESP32_PINMUX(3, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT2) + +#define LEDC_CH2_GPIO4 \ + ESP32_PINMUX(4, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT2) + +#define LEDC_CH2_GPIO5 \ + ESP32_PINMUX(5, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT2) + +#define LEDC_CH2_GPIO6 \ + ESP32_PINMUX(6, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT2) + +#define LEDC_CH2_GPIO7 \ + ESP32_PINMUX(7, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT2) + +#define LEDC_CH2_GPIO8 \ + ESP32_PINMUX(8, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT2) + +#define LEDC_CH2_GPIO9 \ + ESP32_PINMUX(9, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT2) + +#define LEDC_CH2_GPIO10 \ + ESP32_PINMUX(10, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT2) + +#define LEDC_CH2_GPIO11 \ + ESP32_PINMUX(11, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT2) + +#define LEDC_CH2_GPIO12 \ + ESP32_PINMUX(12, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT2) + +#define LEDC_CH2_GPIO13 \ + ESP32_PINMUX(13, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT2) + +#define LEDC_CH2_GPIO14 \ + ESP32_PINMUX(14, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT2) + +#define LEDC_CH2_GPIO15 \ + ESP32_PINMUX(15, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT2) + +#define LEDC_CH2_GPIO16 \ + ESP32_PINMUX(16, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT2) + +#define LEDC_CH2_GPIO17 \ + ESP32_PINMUX(17, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT2) + +#define LEDC_CH2_GPIO18 \ + ESP32_PINMUX(18, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT2) + +#define LEDC_CH2_GPIO19 \ + ESP32_PINMUX(19, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT2) + +#define LEDC_CH2_GPIO20 \ + ESP32_PINMUX(20, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT2) + +#define LEDC_CH2_GPIO21 \ + ESP32_PINMUX(21, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT2) + +#define LEDC_CH2_GPIO22 \ + ESP32_PINMUX(22, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT2) + +#define LEDC_CH2_GPIO23 \ + ESP32_PINMUX(23, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT2) + +/* LEDC_CH3 */ +#define LEDC_CH3_GPIO0 \ + ESP32_PINMUX(0, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT3) + +#define LEDC_CH3_GPIO1 \ + ESP32_PINMUX(1, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT3) + +#define LEDC_CH3_GPIO2 \ + ESP32_PINMUX(2, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT3) + +#define LEDC_CH3_GPIO3 \ + ESP32_PINMUX(3, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT3) + +#define LEDC_CH3_GPIO4 \ + ESP32_PINMUX(4, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT3) + +#define LEDC_CH3_GPIO5 \ + ESP32_PINMUX(5, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT3) + +#define LEDC_CH3_GPIO6 \ + ESP32_PINMUX(6, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT3) + +#define LEDC_CH3_GPIO7 \ + ESP32_PINMUX(7, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT3) + +#define LEDC_CH3_GPIO8 \ + ESP32_PINMUX(8, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT3) + +#define LEDC_CH3_GPIO9 \ + ESP32_PINMUX(9, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT3) + +#define LEDC_CH3_GPIO10 \ + ESP32_PINMUX(10, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT3) + +#define LEDC_CH3_GPIO11 \ + ESP32_PINMUX(11, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT3) + +#define LEDC_CH3_GPIO12 \ + ESP32_PINMUX(12, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT3) + +#define LEDC_CH3_GPIO13 \ + ESP32_PINMUX(13, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT3) + +#define LEDC_CH3_GPIO14 \ + ESP32_PINMUX(14, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT3) + +#define LEDC_CH3_GPIO15 \ + ESP32_PINMUX(15, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT3) + +#define LEDC_CH3_GPIO16 \ + ESP32_PINMUX(16, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT3) + +#define LEDC_CH3_GPIO17 \ + ESP32_PINMUX(17, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT3) + +#define LEDC_CH3_GPIO18 \ + ESP32_PINMUX(18, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT3) + +#define LEDC_CH3_GPIO19 \ + ESP32_PINMUX(19, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT3) + +#define LEDC_CH3_GPIO20 \ + ESP32_PINMUX(20, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT3) + +#define LEDC_CH3_GPIO21 \ + ESP32_PINMUX(21, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT3) + +#define LEDC_CH3_GPIO22 \ + ESP32_PINMUX(22, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT3) + +#define LEDC_CH3_GPIO23 \ + ESP32_PINMUX(23, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT3) + +/* LEDC_CH4 */ +#define LEDC_CH4_GPIO0 \ + ESP32_PINMUX(0, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT4) + +#define LEDC_CH4_GPIO1 \ + ESP32_PINMUX(1, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT4) + +#define LEDC_CH4_GPIO2 \ + ESP32_PINMUX(2, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT4) + +#define LEDC_CH4_GPIO3 \ + ESP32_PINMUX(3, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT4) + +#define LEDC_CH4_GPIO4 \ + ESP32_PINMUX(4, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT4) + +#define LEDC_CH4_GPIO5 \ + ESP32_PINMUX(5, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT4) + +#define LEDC_CH4_GPIO6 \ + ESP32_PINMUX(6, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT4) + +#define LEDC_CH4_GPIO7 \ + ESP32_PINMUX(7, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT4) + +#define LEDC_CH4_GPIO8 \ + ESP32_PINMUX(8, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT4) + +#define LEDC_CH4_GPIO9 \ + ESP32_PINMUX(9, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT4) + +#define LEDC_CH4_GPIO10 \ + ESP32_PINMUX(10, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT4) + +#define LEDC_CH4_GPIO11 \ + ESP32_PINMUX(11, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT4) + +#define LEDC_CH4_GPIO12 \ + ESP32_PINMUX(12, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT4) + +#define LEDC_CH4_GPIO13 \ + ESP32_PINMUX(13, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT4) + +#define LEDC_CH4_GPIO14 \ + ESP32_PINMUX(14, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT4) + +#define LEDC_CH4_GPIO15 \ + ESP32_PINMUX(15, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT4) + +#define LEDC_CH4_GPIO16 \ + ESP32_PINMUX(16, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT4) + +#define LEDC_CH4_GPIO17 \ + ESP32_PINMUX(17, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT4) + +#define LEDC_CH4_GPIO18 \ + ESP32_PINMUX(18, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT4) + +#define LEDC_CH4_GPIO19 \ + ESP32_PINMUX(19, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT4) + +#define LEDC_CH4_GPIO20 \ + ESP32_PINMUX(20, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT4) + +#define LEDC_CH4_GPIO21 \ + ESP32_PINMUX(21, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT4) + +#define LEDC_CH4_GPIO22 \ + ESP32_PINMUX(22, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT4) + +#define LEDC_CH4_GPIO23 \ + ESP32_PINMUX(23, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT4) + +/* LEDC_CH5 */ +#define LEDC_CH5_GPIO0 \ + ESP32_PINMUX(0, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT5) + +#define LEDC_CH5_GPIO1 \ + ESP32_PINMUX(1, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT5) + +#define LEDC_CH5_GPIO2 \ + ESP32_PINMUX(2, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT5) + +#define LEDC_CH5_GPIO3 \ + ESP32_PINMUX(3, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT5) + +#define LEDC_CH5_GPIO4 \ + ESP32_PINMUX(4, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT5) + +#define LEDC_CH5_GPIO5 \ + ESP32_PINMUX(5, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT5) + +#define LEDC_CH5_GPIO6 \ + ESP32_PINMUX(6, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT5) + +#define LEDC_CH5_GPIO7 \ + ESP32_PINMUX(7, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT5) + +#define LEDC_CH5_GPIO8 \ + ESP32_PINMUX(8, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT5) + +#define LEDC_CH5_GPIO9 \ + ESP32_PINMUX(9, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT5) + +#define LEDC_CH5_GPIO10 \ + ESP32_PINMUX(10, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT5) + +#define LEDC_CH5_GPIO11 \ + ESP32_PINMUX(11, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT5) + +#define LEDC_CH5_GPIO12 \ + ESP32_PINMUX(12, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT5) + +#define LEDC_CH5_GPIO13 \ + ESP32_PINMUX(13, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT5) + +#define LEDC_CH5_GPIO14 \ + ESP32_PINMUX(14, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT5) + +#define LEDC_CH5_GPIO15 \ + ESP32_PINMUX(15, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT5) + +#define LEDC_CH5_GPIO16 \ + ESP32_PINMUX(16, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT5) + +#define LEDC_CH5_GPIO17 \ + ESP32_PINMUX(17, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT5) + +#define LEDC_CH5_GPIO18 \ + ESP32_PINMUX(18, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT5) + +#define LEDC_CH5_GPIO19 \ + ESP32_PINMUX(19, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT5) + +#define LEDC_CH5_GPIO20 \ + ESP32_PINMUX(20, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT5) + +#define LEDC_CH5_GPIO21 \ + ESP32_PINMUX(21, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT5) + +#define LEDC_CH5_GPIO22 \ + ESP32_PINMUX(22, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT5) + +#define LEDC_CH5_GPIO23 \ + ESP32_PINMUX(23, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT5) + /* SPIM2_CSEL */ #define SPIM2_CSEL_GPIO0 \ ESP32_PINMUX(0, ESP_NOSIG, ESP_FSPICS0_OUT) From 73c3c1ece3ec654e2f19ac0c438ec2915410d088 Mon Sep 17 00:00:00 2001 From: Raffael Rostagno Date: Tue, 21 May 2024 11:43:05 -0300 Subject: [PATCH 2846/2849] boards: esp32c6: Added PWM test file for esp32c6_devkitc Added basic PWM test for esp32c6_devkitc Signed-off-by: Raffael Rostagno --- .../esp32c6_devkitc/Kconfig.defconfig | 8 +++-- .../esp32c6_devkitc/Kconfig.esp32c6_devkitc | 2 +- .../esp32c6_devkitc/esp32c6_devkitc.dts | 2 ++ .../esp32c6_devkitc/esp32c6_devkitc.yaml | 4 +++ .../pwm_api/boards/esp32c6_devkitc.overlay | 34 +++++++++++++++++++ 5 files changed, 46 insertions(+), 4 deletions(-) create mode 100644 tests/drivers/pwm/pwm_api/boards/esp32c6_devkitc.overlay diff --git a/boards/espressif/esp32c6_devkitc/Kconfig.defconfig b/boards/espressif/esp32c6_devkitc/Kconfig.defconfig index b3b9bbf6ec113..fccfb36845b2b 100644 --- a/boards/espressif/esp32c6_devkitc/Kconfig.defconfig +++ b/boards/espressif/esp32c6_devkitc/Kconfig.defconfig @@ -1,9 +1,11 @@ # ESP32C6 devkitc board configuration -# Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. +# Copyright (c) 2024 Espressif Systems (Shanghai) Co., Ltd. # SPDX-License-Identifier: Apache-2.0 -config HEAP_MEM_POOL_SIZE - default 98304 if WIFI +config HEAP_MEM_POOL_ADD_SIZE_BOARD + int + default 65535 if WIFI && BT + default 51200 if WIFI default 40960 if BT default 4096 diff --git a/boards/espressif/esp32c6_devkitc/Kconfig.esp32c6_devkitc b/boards/espressif/esp32c6_devkitc/Kconfig.esp32c6_devkitc index b2fbfc946affc..4bd1fce4efc33 100644 --- a/boards/espressif/esp32c6_devkitc/Kconfig.esp32c6_devkitc +++ b/boards/espressif/esp32c6_devkitc/Kconfig.esp32c6_devkitc @@ -1,6 +1,6 @@ # ESP32C6 devkitc board configuration -# Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. +# Copyright (c) 2024 Espressif Systems (Shanghai) Co., Ltd. # SPDX-License-Identifier: Apache-2.0 config BOARD_ESP32C6_DEVKITC diff --git a/boards/espressif/esp32c6_devkitc/esp32c6_devkitc.dts b/boards/espressif/esp32c6_devkitc/esp32c6_devkitc.dts index c69aba1ddae84..93f4e959a5604 100644 --- a/boards/espressif/esp32c6_devkitc/esp32c6_devkitc.dts +++ b/boards/espressif/esp32c6_devkitc/esp32c6_devkitc.dts @@ -8,6 +8,7 @@ #include #include "esp32c6_devkitc-pinctrl.dtsi" +#include / { model = "esp32c6_devkitc"; @@ -31,6 +32,7 @@ user_button1: button_1 { label = "User SW1"; gpios = <&gpio0 9 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>; + zephyr,code = ; }; }; }; diff --git a/boards/espressif/esp32c6_devkitc/esp32c6_devkitc.yaml b/boards/espressif/esp32c6_devkitc/esp32c6_devkitc.yaml index 01c8e2bdaa903..06f7d8d8d29c0 100644 --- a/boards/espressif/esp32c6_devkitc/esp32c6_devkitc.yaml +++ b/boards/espressif/esp32c6_devkitc/esp32c6_devkitc.yaml @@ -7,8 +7,12 @@ toolchain: - zephyr supported: - gpio + - watchdog - uart + - spi testing: ignore_tags: - net - bluetooth + - pm + - tracing diff --git a/tests/drivers/pwm/pwm_api/boards/esp32c6_devkitc.overlay b/tests/drivers/pwm/pwm_api/boards/esp32c6_devkitc.overlay new file mode 100644 index 0000000000000..409f7dc30a7c1 --- /dev/null +++ b/tests/drivers/pwm/pwm_api/boards/esp32c6_devkitc.overlay @@ -0,0 +1,34 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. + */ + +#include + +/ { + aliases { + pwm-0 = &ledc0; + }; +}; + +&pinctrl { + ledc0_default: ledc0_default { + group1 { + pinmux = ; + output-enable; + }; + }; +}; + +&ledc0 { + pinctrl-0 = <&ledc0_default>; + pinctrl-names = "default"; + status = "okay"; + #address-cells = <1>; + #size-cells = <0>; + channel0@0 { + reg = <0x0>; + timer = <0>; + }; +}; From 0ace35c5da5fb906991c0a6da669c27f84b6d8cf Mon Sep 17 00:00:00 2001 From: Raffael Rostagno Date: Tue, 28 May 2024 13:22:46 -0300 Subject: [PATCH 2847/2849] drivers: clock_control: Refactor for ESP32C6 Added support for C6 to allow CPU clock config Signed-off-by: Raffael Rostagno --- .../esp32c6_devkitc/esp32c6_devkitc.dts | 4 - drivers/clock_control/clock_control_esp32.c | 99 ++++++++++++++++++- .../espressif/esp32c6/esp32c6_common.dtsi | 23 +++-- .../clock_control/esp32_clock_control.h | 2 + .../zephyr/dt-bindings/clock/esp32c6_clock.h | 37 ++++--- soc/espressif/esp32c6/Kconfig.rtc | 50 ---------- soc/espressif/esp32c6/soc.c | 5 - 7 files changed, 133 insertions(+), 87 deletions(-) delete mode 100644 soc/espressif/esp32c6/Kconfig.rtc diff --git a/boards/espressif/esp32c6_devkitc/esp32c6_devkitc.dts b/boards/espressif/esp32c6_devkitc/esp32c6_devkitc.dts index 93f4e959a5604..3917430cdb282 100644 --- a/boards/espressif/esp32c6_devkitc/esp32c6_devkitc.dts +++ b/boards/espressif/esp32c6_devkitc/esp32c6_devkitc.dts @@ -37,10 +37,6 @@ }; }; -&cpu0 { - clock-frequency = ; -}; - &uart0 { status = "okay"; current-speed = <115200>; diff --git a/drivers/clock_control/clock_control_esp32.c b/drivers/clock_control/clock_control_esp32.c index 3dd40792486ee..02cf64d52b5a9 100644 --- a/drivers/clock_control/clock_control_esp32.c +++ b/drivers/clock_control/clock_control_esp32.c @@ -32,6 +32,15 @@ #define DT_CPU_COMPAT espressif_riscv #include #include +#elif CONFIG_SOC_SERIES_ESP32C6 +#define DT_CPU_COMPAT espressif_riscv +#include +#include +#include +#include +#include +#include +#include #endif /* CONFIG_SOC_SERIES_ESP32xx */ #include @@ -68,6 +77,49 @@ static bool reset_reason_is_cpu_reset(void) return false; } +#if defined(CONFIG_SOC_SERIES_ESP32C6) +static void esp32_clock_perip_init(void) +{ + soc_reset_reason_t rst_reason = esp_rom_get_reset_reason(0); + + if ((rst_reason != RESET_REASON_CPU0_MWDT0) && (rst_reason != RESET_REASON_CPU0_MWDT1) && + (rst_reason != RESET_REASON_CPU0_SW) && (rst_reason != RESET_REASON_CPU0_RTC_WDT)) { + + periph_ll_disable_clk_set_rst(PERIPH_UART1_MODULE); + periph_ll_disable_clk_set_rst(PERIPH_I2C0_MODULE); + periph_ll_disable_clk_set_rst(PERIPH_RMT_MODULE); + periph_ll_disable_clk_set_rst(PERIPH_LEDC_MODULE); + periph_ll_disable_clk_set_rst(PERIPH_TIMG1_MODULE); + periph_ll_disable_clk_set_rst(PERIPH_TWAI0_MODULE); + periph_ll_disable_clk_set_rst(PERIPH_TWAI1_MODULE); + periph_ll_disable_clk_set_rst(PERIPH_I2S1_MODULE); + periph_ll_disable_clk_set_rst(PERIPH_PCNT_MODULE); + periph_ll_disable_clk_set_rst(PERIPH_ETM_MODULE); + periph_ll_disable_clk_set_rst(PERIPH_MCPWM0_MODULE); + periph_ll_disable_clk_set_rst(PERIPH_PARLIO_MODULE); + periph_ll_disable_clk_set_rst(PERIPH_GDMA_MODULE); + periph_ll_disable_clk_set_rst(PERIPH_SPI2_MODULE); + periph_ll_disable_clk_set_rst(PERIPH_TEMPSENSOR_MODULE); + periph_ll_disable_clk_set_rst(PERIPH_UHCI0_MODULE); + periph_ll_disable_clk_set_rst(PERIPH_SARADC_MODULE); + periph_ll_disable_clk_set_rst(PERIPH_SDIO_SLAVE_MODULE); + periph_ll_disable_clk_set_rst(PERIPH_RSA_MODULE); + periph_ll_disable_clk_set_rst(PERIPH_AES_MODULE); + periph_ll_disable_clk_set_rst(PERIPH_SHA_MODULE); + periph_ll_disable_clk_set_rst(PERIPH_ECC_MODULE); + periph_ll_disable_clk_set_rst(PERIPH_HMAC_MODULE); + periph_ll_disable_clk_set_rst(PERIPH_DS_MODULE); + + REG_CLR_BIT(PCR_CTRL_TICK_CONF_REG, PCR_TICK_ENABLE); + REG_CLR_BIT(PCR_TRACE_CONF_REG, PCR_TRACE_CLK_EN); + REG_CLR_BIT(PCR_RETENTION_CONF_REG, PCR_RETENTION_CLK_EN); + REG_CLR_BIT(PCR_MEM_MONITOR_CONF_REG, PCR_MEM_MONITOR_CLK_EN); + REG_CLR_BIT(PCR_PVT_MONITOR_CONF_REG, PCR_PVT_MONITOR_CLK_EN); + REG_CLR_BIT(PCR_PVT_MONITOR_FUNC_CLK_CONF_REG, PCR_PVT_MONITOR_FUNC_CLK_EN); + WRITE_PERI_REG(PCR_CTRL_CLK_OUT_EN_REG, 0); + } +} +#else static void esp32_clock_perip_init(void) { uint32_t common_perip_clk; @@ -330,6 +382,7 @@ static void esp32_clock_perip_init(void) periph_module_enable(PERIPH_TIMG0_MODULE); #endif } +#endif static enum clock_control_status clock_control_esp32_get_status(const struct device *dev, clock_control_subsys_t sys) @@ -389,7 +442,11 @@ static int clock_control_esp32_get_rate(const struct device *dev, clock_control_ static int esp32_select_rtc_slow_clk(uint8_t slow_clk) { +#if !defined(CONFIG_SOC_SERIES_ESP32C6) soc_rtc_slow_clk_src_t rtc_slow_clk_src = slow_clk & RTC_CNTL_ANA_CLK_RTC_SEL_V; +#else + soc_rtc_slow_clk_src_t rtc_slow_clk_src = slow_clk; +#endif uint32_t cal_val = 0; /* number of times to repeat 32k XTAL calibration * before giving up and switching to the internal RC @@ -424,9 +481,15 @@ static int esp32_select_rtc_slow_clk(uint8_t slow_clk) return -ENODEV; } } +#if defined(CONFIG_SOC_SERIES_ESP32C6) + } else if (rtc_slow_clk_src == SOC_RTC_SLOW_CLK_SRC_RC32K) { + rtc_clk_rc32k_enable(true); + } +#else } else if (rtc_slow_clk_src == SOC_RTC_SLOW_CLK_SRC_RC_FAST_D256) { rtc_clk_8m_enable(true, true); } +#endif rtc_clk_slow_src_set(rtc_slow_clk_src); if (CONFIG_RTC_CLK_CAL_CYCLES > 0) { @@ -458,22 +521,36 @@ static int esp32_cpu_clock_configure(const struct esp32_cpu_clock_config *cpu_cf esp_rom_uart_tx_wait_idle(ESP_CONSOLE_UART_NUM); +#if defined(CONFIG_SOC_SERIES_ESP32C6) + rtc_clk_modem_clock_domain_active_state_icg_map_preinit(); + + REG_SET_FIELD(LP_CLKRST_FOSC_CNTL_REG, LP_CLKRST_FOSC_DFREQ, rtc_clk_cfg.clk_8m_dfreq); + REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_SCK_DCAP, rtc_clk_cfg.slow_clk_dcap); + REG_SET_FIELD(LP_CLKRST_RC32K_CNTL_REG, LP_CLKRST_RC32K_DFREQ, rtc_clk_cfg.rc32k_dfreq); +#else REG_SET_FIELD(RTC_CNTL_REG, RTC_CNTL_SCK_DCAP, rtc_clk_cfg.slow_clk_dcap); REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_CK8M_DFREQ, rtc_clk_cfg.clk_8m_dfreq); +#endif -#if !defined(CONFIG_SOC_SERIES_ESP32) +#if defined(CONFIG_SOC_SERIES_ESP32) + REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_CK8M_DIV_SEL, rtc_clk_cfg.clk_8m_div - 1); +#elif defined(CONFIG_SOC_SERIES_ESP32C6) + clk_ll_rc_fast_tick_conf(); +#else /* Configure 150k clock division */ rtc_clk_divider_set(rtc_clk_cfg.clk_rtc_clk_div); /* Configure 8M clock division */ rtc_clk_8m_divider_set(rtc_clk_cfg.clk_8m_clk_div); -#else - REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_CK8M_DIV_SEL, rtc_clk_cfg.clk_8m_div - 1); #endif + +#if !defined(CONFIG_SOC_SERIES_ESP32C6) /* Reset (disable) i2c internal bus for all regi2c registers */ regi2c_ctrl_ll_i2c_reset(); /* Enable the internal bus used to configure BBPLL */ regi2c_ctrl_ll_i2c_bbpll_enable(); +#endif + #if defined(CONFIG_SOC_SERIES_ESP32S2) || defined(CONFIG_SOC_SERIES_ESP32) regi2c_ctrl_ll_i2c_apll_enable(); #endif @@ -481,7 +558,16 @@ static int esp32_cpu_clock_configure(const struct esp32_cpu_clock_config *cpu_cf #if !defined(CONFIG_SOC_SERIES_ESP32S2) rtc_clk_xtal_freq_update(rtc_clk_cfg.xtal_freq); #endif +#if defined(CONFIG_SOC_SERIES_ESP32C6) + /* On ESP32C6, MSPI source clock's default HS divider leads to 120MHz, + * which is unusable before calibration. Therefore, before switching + * SOC_ROOT_CLK to HS, we need to set MSPI source clock HS divider + * to make it run at 80MHz after the switch. PLL = 480MHz, so divider is 6. + */ + clk_ll_mspi_fast_set_hs_divider(6); +#else rtc_clk_apb_freq_update(rtc_clk_cfg.xtal_freq * MHZ(1)); +#endif /* Set CPU frequency */ rtc_clk_cpu_freq_get_config(&old_config); @@ -498,6 +584,7 @@ static int esp32_cpu_clock_configure(const struct esp32_cpu_clock_config *cpu_cf esp_cpu_set_cycle_count((uint64_t)esp_cpu_get_cycle_count() * rtc_clk_cfg.cpu_freq_mhz / old_config.freq_mhz); +#if !defined(CONFIG_SOC_SERIES_ESP32C6) #if ESP_ROM_UART_CLK_IS_XTAL uart_clock_src_hz = (uint32_t)rtc_clk_xtal_freq_get() * MHZ(1); #else @@ -507,6 +594,7 @@ static int esp32_cpu_clock_configure(const struct esp32_cpu_clock_config *cpu_cf #if !defined(ESP_CONSOLE_UART_NONE) esp_rom_uart_set_clock_baudrate(ESP_CONSOLE_UART_NUM, uart_clock_src_hz, ESP_CONSOLE_UART_BAUDRATE); +#endif #endif return 0; } @@ -546,10 +634,10 @@ static int clock_control_esp32_configure(const struct device *dev, clock_control static int clock_control_esp32_init(const struct device *dev) { const struct esp32_clock_config *cfg = dev->config; - struct esp32_clock_data *data = dev->data; + bool ret; +#if !defined(CONFIG_SOC_SERIES_ESP32C6) soc_reset_reason_t rst_reas; rtc_config_t rtc_cfg = RTC_CONFIG_DEFAULT(); - bool ret; rst_reas = esp_rom_get_reset_reason(0); #if !defined(CONFIG_SOC_SERIES_ESP32) @@ -562,6 +650,7 @@ static int clock_control_esp32_init(const struct device *dev) } #endif rtc_init(rtc_cfg); +#endif ret = esp32_cpu_clock_configure(&cfg->cpu); if (ret) { diff --git a/dts/riscv/espressif/esp32c6/esp32c6_common.dtsi b/dts/riscv/espressif/esp32c6/esp32c6_common.dtsi index 38e2be850afaa..fc3f61cdcb3df 100644 --- a/dts/riscv/espressif/esp32c6/esp32c6_common.dtsi +++ b/dts/riscv/espressif/esp32c6/esp32c6_common.dtsi @@ -4,6 +4,7 @@ * SPDX-License-Identifier: Apache-2.0 */ #include +#include #include #include #include @@ -26,6 +27,9 @@ compatible = "espressif,riscv"; riscv,isa = "rv32imc_zicsr"; reg = <0>; + clock-source = ; + clock-frequency = ; + xtal-freq = ; }; }; @@ -65,17 +69,20 @@ rtc: rtc@600b000 { compatible = "espressif,esp32-rtc"; reg = <0x600B000 DT_SIZE_K(1)>; - xtal-freq = ; + fast-clk-src = ; + slow-clk-src = ; #clock-cells = <1>; status = "okay"; - rtc_timer: rtc_timer { - compatible = "espressif,esp32-rtc-timer"; - slow-clk-freq = ; - interrupts = ; - interrupt-parent = <&intc>; - status = "okay"; - }; + }; + + rtc_timer: rtc_timer@600b0c00 { + compatible = "espressif,esp32-rtc-timer"; + reg = <0x600B0C00 DT_SIZE_K(1)>; + clocks = <&rtc ESP32_MODULE_MAX>; + interrupts = ; + interrupt-parent = <&intc>; + status = "okay"; }; spi2: spi@60081000 { diff --git a/include/zephyr/drivers/clock_control/esp32_clock_control.h b/include/zephyr/drivers/clock_control/esp32_clock_control.h index d74b2c0aeff28..aa83d78e3960c 100644 --- a/include/zephyr/drivers/clock_control/esp32_clock_control.h +++ b/include/zephyr/drivers/clock_control/esp32_clock_control.h @@ -15,6 +15,8 @@ #include #elif defined(CONFIG_SOC_SERIES_ESP32C3) #include +#elif defined(CONFIG_SOC_SERIES_ESP32C6) +#include #endif /* CONFIG_SOC_SERIES_ESP32xx */ #define ESP32_CLOCK_CONTROL_SUBSYS_CPU 50 diff --git a/include/zephyr/dt-bindings/clock/esp32c6_clock.h b/include/zephyr/dt-bindings/clock/esp32c6_clock.h index c1ccc604986f3..9aa39b2c51edb 100644 --- a/include/zephyr/dt-bindings/clock/esp32c6_clock.h +++ b/include/zephyr/dt-bindings/clock/esp32c6_clock.h @@ -7,27 +7,34 @@ #ifndef ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_ESP32C6_H_ #define ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_ESP32C6_H_ -/* System Clock Source */ -#define ESP32_CLK_SRC_XTAL 0U -#define ESP32_CLK_SRC_PLL 1U -#define ESP32_CLK_SRC_RC_FAST 2U +/* Supported CPU clock Sources */ +#define ESP32_CPU_CLK_SRC_XTAL 0U +#define ESP32_CPU_CLK_SRC_PLL 1U +#define ESP32_CLK_SRC_RC_FAST 2U -/* Supported CPU Frequencies */ -#define ESP32_CLK_CPU_80M 80000000 -#define ESP32_CLK_CPU_160M 160000000 +/* Supported CPU frequencies */ +#define ESP32_CLK_CPU_PLL_80M 80000000 +#define ESP32_CLK_CPU_PLL_160M 160000000 +#define ESP32_CLK_CPU_RC_FAST_FREQ 17500000 /* Supported XTAL Frequencies */ -#define ESP32_CLK_XTAL_32M 32 -#define ESP32_CLK_XTAL_40M 40 +#define ESP32_CLK_XTAL_32M 32000000 +#define ESP32_CLK_XTAL_40M 40000000 -/* Supported RTC fast clock frequencies */ -#define ESP32_RTC_FAST_CLK_FREQ_8M 8500000U -#define ESP32_RTC_FAST_CLK_FREQ_APPROX ESP32_RTC_FAST_CLK_FREQ_8M +/* Supported RTC fast clock sources */ +#define ESP32_RTC_FAST_CLK_SRC_RC_FAST 0 +#define ESP32_RTC_FAST_CLK_SRC_XTAL_D2 1 /* Supported RTC slow clock frequencies */ -#define ESP32_RTC_SLOW_CLK_FREQ_90K 90000U -#define ESP32_RTC_SLOW_CLK_FREQ_8MD256 (ESP32_RTC_FAST_CLK_FREQ_APPROX / 256) -#define ESP32_RTC_SLOW_CLK_FREQ_32K 32768U +#define ESP32_RTC_SLOW_CLK_SRC_RC_SLOW 0 +#define ESP32_RTC_SLOW_CLK_SRC_XTAL32K 1 +#define ESP32_RTC_SLOW_CLK_SRC_RC32K 2 +#define ESP32_RTC_SLOW_CLK_32K_EXT_OSC 9 + +/* RTC slow clock frequencies */ +#define ESP32_RTC_SLOW_CLK_SRC_RC_SLOW_FREQ 136000 +#define ESP32_RTC_SLOW_CLK_SRC_XTAL32K_FREQ 32768 +#define ESP32_RTC_SLOW_CLK_SRC_RC32K_FREQ 32768 /* Modules IDs * These IDs are actually offsets in CLK and RST Control registers. diff --git a/soc/espressif/esp32c6/Kconfig.rtc b/soc/espressif/esp32c6/Kconfig.rtc deleted file mode 100644 index 2a9a864d01bd4..0000000000000 --- a/soc/espressif/esp32c6/Kconfig.rtc +++ /dev/null @@ -1,50 +0,0 @@ -# Copyright (c) 2024 Espressif Systems (Shanghai) Co., Ltd. -# SPDX-License-Identifier: Apache-2.0 - -if SOC_SERIES_ESP32C6 - -choice RTC_CLK_SRC - prompt "RTC clock source" - default RTC_CLK_SRC_INT_RC - help - Choose which clock is used as RTC clock source. - -config RTC_CLK_SRC_INT_RC - bool "Internal 136kHz RC oscillator" - -config RTC_CLK_SRC_EXT_CRYS - bool "External 32kHz crystal" - select ESP_SYSTEM_RTC_EXT_XTAL - -config RTC_CLK_SRC_EXT_OSC - bool "External 32kHz oscillator at 32K_XP pin" - select ESP_SYSTEM_RTC_EXT_OSC - -config RTC_CLK_SRC_INT_8MD256 - bool "Internal 17.5MHz oscillator, divided by 256" - -endchoice # ESP32C6_RTC_CLK_SRC - -config RTC_CLK_CAL_CYCLES - int "Number of cycles for RTC_SLOW_CLK calibration" - default 3000 if RTC_CLK_SRC_EXT_CRYS || RTC_CLK_SRC_EXT_OSC || RTC_CLK_SRC_INT_8MD256 - default 1024 if RTC_CLK_SRC_INT_RC - range 0 27000 if RTC_CLK_SRC_EXT_CRYS || RTC_CLK_SRC_EXT_OSC || RTC_CLK_SRC_INT_8MD256 - range 0 32766 if RTC_CLK_SRC_INT_RC - help - When the startup code initializes RTC_SLOW_CLK, it can perform - calibration by comparing the RTC_SLOW_CLK frequency with main XTAL - frequency. This option sets the number of RTC_SLOW_CLK cycles measured - by the calibration routine. Higher numbers increase calibration - precision, which may be important for applications which spend a lot of - time in deep sleep. Lower numbers reduce startup time. - - When this option is set to 0, clock calibration will not be performed at - startup, and approximate clock frequencies will be assumed: - - - 150000 Hz if internal RC oscillator is used as clock source. For this use value 1024. - - 32768 Hz if the 32k crystal oscillator is used. For this use value 3000 or more. - 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. - -endif # SOC_SERIES_ESP32C6 diff --git a/soc/espressif/esp32c6/soc.c b/soc/espressif/esp32c6/soc.c index 4bdfacbc0570e..2a30fe457310f 100644 --- a/soc/espressif/esp32c6/soc.c +++ b/soc/espressif/esp32c6/soc.c @@ -56,11 +56,6 @@ void IRAM_ATTR __esp_platform_start(void) wdt_hal_disable(&rtc_wdt_ctx); wdt_hal_write_protect_enable(&rtc_wdt_ctx); - /* Configures the CPU clock, RTC slow and fast clocks, and performs - * RTC slow clock calibration. - */ - esp_clk_init(); - esp_timer_early_init(); #if CONFIG_SOC_FLASH_ESP32 From 885651c54eb245bbc7863acec77096ec8dd0b308 Mon Sep 17 00:00:00 2001 From: Raffael Rostagno Date: Tue, 28 May 2024 13:24:12 -0300 Subject: [PATCH 2848/2849] tests: rtc_clk: Added support to ESP32C6 Added support for C6 for CPU and LP clock testing Signed-off-by: Raffael Rostagno --- tests/boards/espressif_esp32/rtc_clk/README.rst | 1 + .../espressif_esp32/rtc_clk/src/rtc_clk_test.c | 12 ++++++++++-- tests/boards/espressif_esp32/rtc_clk/testcase.yaml | 2 ++ 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/tests/boards/espressif_esp32/rtc_clk/README.rst b/tests/boards/espressif_esp32/rtc_clk/README.rst index caeb6d027c69c..f629ae1ae2ada 100644 --- a/tests/boards/espressif_esp32/rtc_clk/README.rst +++ b/tests/boards/espressif_esp32/rtc_clk/README.rst @@ -14,6 +14,7 @@ Supported Boards **************** - esp32_devkitc_wrover/esp32/procpu - esp32c3_devkitm +- esp32c6_devkitc - esp32s2_saola - esp32s3_devkitm/esp32s3/procpu diff --git a/tests/boards/espressif_esp32/rtc_clk/src/rtc_clk_test.c b/tests/boards/espressif_esp32/rtc_clk/src/rtc_clk_test.c index 2b621d0e715ae..f539b20994fae 100644 --- a/tests/boards/espressif_esp32/rtc_clk/src/rtc_clk_test.c +++ b/tests/boards/espressif_esp32/rtc_clk/src/rtc_clk_test.c @@ -15,7 +15,7 @@ #define DT_CPU_COMPAT espressif_xtensa_lx6 #elif defined(CONFIG_SOC_SERIES_ESP32S2) || defined(CONFIG_SOC_SERIES_ESP32S3) #define DT_CPU_COMPAT espressif_xtensa_lx7 -#elif CONFIG_SOC_SERIES_ESP32C3 +#elif defined(CONFIG_SOC_SERIES_ESP32C3) || defined(CONFIG_SOC_SERIES_ESP32C6) #define DT_CPU_COMPAT espressif_riscv #endif @@ -75,7 +75,7 @@ ZTEST(rtc_clk, test_cpu_xtal_src) uint32_t rtc_pll_src_freq_mhz[] = { ESP32_CLK_CPU_PLL_80M, ESP32_CLK_CPU_PLL_160M, -#if !defined(CONFIG_SOC_SERIES_ESP32C3) +#if !defined(CONFIG_SOC_SERIES_ESP32C3) && !defined(CONFIG_SOC_SERIES_ESP32C6) ESP32_CLK_CPU_PLL_240M, #endif }; @@ -154,7 +154,11 @@ ZTEST(rtc_clk, test_rtc_fast_src) uint32_t rtc_rtc_slow_clk_src[] = { ESP32_RTC_SLOW_CLK_SRC_RC_SLOW, +#if defined(CONFIG_SOC_SERIES_ESP32C6) + ESP32_RTC_SLOW_CLK_SRC_RC32K, +#else ESP32_RTC_SLOW_CLK_SRC_RC_FAST_D256, +#endif #if CONFIG_FIXTURE_XTAL ESP32_RTC_SLOW_CLK_SRC_XTAL32K, #endif @@ -162,7 +166,11 @@ uint32_t rtc_rtc_slow_clk_src[] = { uint32_t rtc_rtc_slow_clk_src_freq[] = { ESP32_RTC_SLOW_CLK_SRC_RC_SLOW_FREQ, +#if defined(CONFIG_SOC_SERIES_ESP32C6) + ESP32_RTC_SLOW_CLK_SRC_RC32K_FREQ, +#else ESP32_RTC_SLOW_CLK_SRC_RC_FAST_D256_FREQ, +#endif #if CONFIG_FIXTURE_XTAL ESP32_RTC_SLOW_CLK_SRC_XTAL32K_FREQ, #endif diff --git a/tests/boards/espressif_esp32/rtc_clk/testcase.yaml b/tests/boards/espressif_esp32/rtc_clk/testcase.yaml index c968be3850ccc..b656b93437434 100644 --- a/tests/boards/espressif_esp32/rtc_clk/testcase.yaml +++ b/tests/boards/espressif_esp32/rtc_clk/testcase.yaml @@ -3,12 +3,14 @@ tests: platform_allow: - esp32_devkitc_wrover/esp32/procpu - esp32c3_devkitm + - esp32c6_devkitc - esp32s2_saola - esp32s3_devkitm/esp32s3/procpu boards.esp32.rtc_clk.xtal: platform_allow: - esp32_devkitc_wrover/esp32/procpu - esp32c3_devkitm + - esp32c6_devkitc - esp32s2_saola - esp32s3_devkitm/esp32s3/procpu harness_config: From c5fb9ee82245ff2cc3771f02e561346152251e63 Mon Sep 17 00:00:00 2001 From: Raffael Rostagno Date: Wed, 29 May 2024 17:58:15 -0300 Subject: [PATCH 2849/2849] soc: esp32c6: Kconfig and .ld updates, DTS and comments fix Kconfig, .ld and comments fixing Fixed address of UART1, WDT and RTC timer disabled by default Signed-off-by: Raffael Rostagno --- arch/Kconfig | 2 +- .../espressif/esp32c6/esp32c6_common.dtsi | 18 +++++++++--------- soc/espressif/esp32c6/CMakeLists.txt | 2 +- soc/espressif/esp32c6/Kconfig | 8 ++------ soc/espressif/esp32c6/Kconfig.defconfig | 4 ++-- soc/espressif/esp32c6/Kconfig.soc | 5 ++--- soc/espressif/esp32c6/default.ld | 14 +++++++------- soc/espressif/esp32c6/mcuboot.ld | 2 +- 8 files changed, 25 insertions(+), 30 deletions(-) diff --git a/arch/Kconfig b/arch/Kconfig index 2d9b59292cca8..6b8fa7dcb4bf0 100644 --- a/arch/Kconfig +++ b/arch/Kconfig @@ -110,7 +110,7 @@ config RISCV bool select ARCH_IS_SET select ARCH_SUPPORTS_COREDUMP - select ARCH_SUPPORTS_ROM_START if !SOC_SERIES_ESP32C3 + select ARCH_SUPPORTS_ROM_START if !SOC_FAMILY_ESPRESSIF_ESP32 select ARCH_HAS_CODE_DATA_RELOCATION select ARCH_HAS_THREAD_LOCAL_STORAGE select ARCH_HAS_STACKWALK diff --git a/dts/riscv/espressif/esp32c6/esp32c6_common.dtsi b/dts/riscv/espressif/esp32c6/esp32c6_common.dtsi index fc3f61cdcb3df..0edf5bf95a3db 100644 --- a/dts/riscv/espressif/esp32c6/esp32c6_common.dtsi +++ b/dts/riscv/espressif/esp32c6/esp32c6_common.dtsi @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. + * Copyright (c) 2024 Espressif Systems (Shanghai) Co., Ltd. * * SPDX-License-Identifier: Apache-2.0 */ @@ -25,7 +25,7 @@ cpu0: cpu@0 { device_type = "cpu"; compatible = "espressif,riscv"; - riscv,isa = "rv32imc_zicsr"; + riscv,isa = "rv32imac_zicsr"; reg = <0>; clock-source = ; clock-frequency = ; @@ -82,7 +82,7 @@ clocks = <&rtc ESP32_MODULE_MAX>; interrupts = ; interrupt-parent = <&intc>; - status = "okay"; + status = "disabled"; }; spi2: spi@60081000 { @@ -96,18 +96,18 @@ status = "disabled"; }; - wdt0: watchdog@6001f048 { + wdt0: watchdog@60008048 { compatible = "espressif,esp32-watchdog"; - reg = <0x6001f048 0x20>; + reg = <0x60008048 0x20>; interrupts = ; interrupt-parent = <&intc>; clocks = <&rtc ESP32_TIMG0_MODULE>; status = "disabled"; }; - wdt1: watchdog@60020048 { + wdt1: watchdog@60009048 { compatible = "espressif,esp32-watchdog"; - reg = <0x60020048 0x20>; + reg = <0x60009048 0x20>; interrupts = ; interrupt-parent = <&intc>; clocks = <&rtc ESP32_TIMG1_MODULE>; @@ -147,9 +147,9 @@ clocks = <&rtc ESP32_UART0_MODULE>; }; - uart1: uart@60010000 { + uart1: uart@60001000 { compatible = "espressif,esp32-uart"; - reg = <0x60010000 DT_SIZE_K(4)>; + reg = <0x60001000 DT_SIZE_K(4)>; status = "disabled"; interrupts = ; interrupt-parent = <&intc>; diff --git a/soc/espressif/esp32c6/CMakeLists.txt b/soc/espressif/esp32c6/CMakeLists.txt index 279a373adc17a..4e90a854cb02c 100644 --- a/soc/espressif/esp32c6/CMakeLists.txt +++ b/soc/espressif/esp32c6/CMakeLists.txt @@ -62,7 +62,7 @@ if(CONFIG_MCUBOOT) ${PYTHON_EXECUTABLE} ${ESP_IDF_PATH}/tools/ci/check_callgraph.py ARGS --rtl-dirs ${CMAKE_BINARY_DIR}/zephyr - --elf-file ${CMAKE_BINARY_DIR}/zephyr/${CONFIG_KERNEL_BIN_NAME}.elf + --elf-file ${CMAKE_BINARY_DIR}/zephyr/${CONFIG_KERNEL_BIN_NAME}.elf find-refs --from-section=.iram0.iram_loader --to-section=.iram0.text --exit-code) endif() diff --git a/soc/espressif/esp32c6/Kconfig b/soc/espressif/esp32c6/Kconfig index 48aad9c0a4baf..c33528ac3254a 100644 --- a/soc/espressif/esp32c6/Kconfig +++ b/soc/espressif/esp32c6/Kconfig @@ -1,4 +1,4 @@ -# Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. +# Copyright (c) 2024 Espressif Systems (Shanghai) Co., Ltd. # SPDX-License-Identifier: Apache-2.0 config SOC_SERIES_ESP32C6 @@ -8,6 +8,7 @@ config SOC_SERIES_ESP32C6 select CLOCK_CONTROL select PINCTRL select RISCV_ISA_RV32I + select RISCV_ISA_EXT_A select RISCV_ISA_EXT_M select RISCV_ISA_EXT_C select RISCV_ISA_EXT_ZICSR @@ -18,10 +19,6 @@ config SOC_SERIES_ESP32C6 if SOC_SERIES_ESP32C6 -config IDF_TARGET_ESP32C6 - bool "ESP32C6 as target board" - default y - config ESP32_PHY_MAX_WIFI_TX_POWER int "Max WiFi TX power (dBm)" range 10 20 @@ -37,7 +34,6 @@ config ESP32_PHY_MAX_TX_POWER config MAC_BB_PD bool "Power down MAC and baseband of Wi-Fi and Bluetooth when PHY is disabled" depends on SOC_SERIES_ESP32C6 && TICKLESS_KERNEL - default n help If enabled, the MAC and baseband of Wi-Fi and Bluetooth will be powered down when PHY is disabled. Enabling this setting reduces power consumption diff --git a/soc/espressif/esp32c6/Kconfig.defconfig b/soc/espressif/esp32c6/Kconfig.defconfig index 498f486b75c26..feb27615d9fe6 100644 --- a/soc/espressif/esp32c6/Kconfig.defconfig +++ b/soc/espressif/esp32c6/Kconfig.defconfig @@ -1,6 +1,6 @@ -# ESP32C3 board configuration +# ESP32C6 board configuration -# Copyright (c) 2021 Espressif Systems (Shanghai) Co., Ltd. +# Copyright (c) 2024 Espressif Systems (Shanghai) Co., Ltd. # SPDX-License-Identifier: Apache-2.0 if SOC_SERIES_ESP32C6 diff --git a/soc/espressif/esp32c6/Kconfig.soc b/soc/espressif/esp32c6/Kconfig.soc index 7e2e3295ebc3d..0fe5f8faa0582 100644 --- a/soc/espressif/esp32c6/Kconfig.soc +++ b/soc/espressif/esp32c6/Kconfig.soc @@ -1,4 +1,4 @@ -# Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. +# Copyright (c) 2024 Espressif Systems (Shanghai) Co., Ltd. # SPDX-License-Identifier: Apache-2.0 config SOC_SERIES_ESP32C6 @@ -21,9 +21,8 @@ config SOC_SERIES default "esp32c6" if SOC_SERIES_ESP32C6 config SOC - default "esp32c6" if SOC_SERIES_ESP32C6 + default "esp32c6" if SOC_ESP32C6 config SOC_PART_NUMBER default "ESP32_C6_WROOM_1U_N4" if SOC_ESP32_C6_WROOM_1U_N4 default "ESP32_C6_WROOM_1U_N8" if SOC_ESP32_C6_WROOM_1U_N8 - default "ESP32C6" if SOC_ESP32C6 diff --git a/soc/espressif/esp32c6/default.ld b/soc/espressif/esp32c6/default.ld index eda1381888409..e932ca84c416c 100644 --- a/soc/espressif/esp32c6/default.ld +++ b/soc/espressif/esp32c6/default.ld @@ -610,8 +610,6 @@ SECTIONS __bss_start = ABSOLUTE(.); _bss_start = ABSOLUTE(.); - /* bluetooth library requires this symbol to be defined */ - _btdm_bss_start = ABSOLUTE(.); *libbtdm_app.a:(.bss .bss.* COMMON) . = ALIGN (4); _btdm_bss_end = ABSOLUTE(.); @@ -662,6 +660,7 @@ SECTIONS _instruction_reserved_start = ABSOLUTE(.); _text_start = ABSOLUTE(.); _instruction_reserved_start = ABSOLUTE(.); + __text_region_start = ABSOLUTE(.); #if !defined(CONFIG_ESP32_WIFI_IRAM_OPT) *libnet80211.a:( .wifi0iram .wifi0iram.* .wifislpiram .wifislpiram.*) @@ -692,6 +691,7 @@ SECTIONS _instruction_reserved_end = ABSOLUTE(.); _text_end = ABSOLUTE(.); _instruction_reserved_end = ABSOLUTE(.); + __text_region_end = ABSOLUTE(.); _etext = .; } GROUP_DATA_LINK_IN(CACHED_REGION, ROMABLE_REGION) @@ -701,16 +701,16 @@ SECTIONS /* --- START OF .rodata --- */ /* Align next section to 64k to allow mapping */ - .flash.align_rodata (NOLOAD) : + .flash.align_rom (NOLOAD) : { - /* Subsequent segment lma and vma align */ . = ALIGN(CACHE_ALIGN); - } GROUP_DATA_LINK_IN(CACHED_REGION, ROMABLE_REGION) + } GROUP_LINK_IN(ROMABLE_REGION) - .flash.align_rom (NOLOAD) : + .flash.align_rodata (NOLOAD) : { + /* Subsequent segment lma and vma align */ . = ALIGN(CACHE_ALIGN); - } GROUP_LINK_IN(ROMABLE_REGION) + } GROUP_LINK_IN(CACHED_REGION) /* Symbols used during the application memory mapping */ _image_drom_start = LOADADDR(.flash.rodata); diff --git a/soc/espressif/esp32c6/mcuboot.ld b/soc/espressif/esp32c6/mcuboot.ld index ac87f871847fd..642ad365a37e9 100644 --- a/soc/espressif/esp32c6/mcuboot.ld +++ b/soc/espressif/esp32c6/mcuboot.ld @@ -101,7 +101,7 @@ SECTIONS *(.iram1 .iram1.*) *(.iram0.literal .iram.literal .iram.text.literal .iram0.text .iram.text) - /* C3 memprot requires 512 B alignment for split lines */ + /* C6 memprot requires 512 B alignment for split lines */ . = ALIGN (16); _init_end = ABSOLUTE(.); . = ALIGN(16);

e8=iGF$mcOX8KF1&9aL&@c0YK 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 literal 0 HcmV?d00001 diff --git a/boards/adi/max32655fthr/doc/img/max32655fthr_img3.jpg b/boards/adi/max32655fthr/doc/img/max32655fthr_img3.jpg new file mode 100644 index 0000000000000000000000000000000000000000..f523ef2aed2561fdd9cf86b7dd476fdcfdec87af GIT binary patch literal 95147 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 +#include +#include + +/ { + model = "Analog Devices MAX32655FTHR"; + compatible = "adi,max32655fthr"; + + chosen { + zephyr,console = &uart0; + zephyr,shell-uart = &uart0; + zephyr,sram = &sram2; + zephyr,flash = &flash0; + }; + + leds { + compatible = "gpio-leds"; + led1: led_1 { + gpios = <&gpio0 18 GPIO_ACTIVE_LOW>; + label = "Red LED"; + }; + led2: led_2 { + gpios = <&gpio0 19 GPIO_ACTIVE_LOW>; + label = "Blue LED"; + }; + led3: led_3 { + gpios = <&gpio0 26 GPIO_ACTIVE_LOW>; + label = "Green LED"; + }; + }; + + buttons { + compatible = "gpio-keys"; + pb1: pb1 { + gpios = <&gpio0 2 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>; + label = "SW2"; + }; + pb2: pb2 { + gpios = <&gpio0 3 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>; + label = "SW3"; + }; + pb_wakeup: pb_wakeup { + gpios = <&gpio3 1 (GPIO_PULL_UP | GPIO_ACTIVE_LOW + | MAX32_GPIO_VSEL_VDDIOH)>; + label = "Wakeup"; + }; + }; + + /* These aliases are provided for compatibility with samples */ + aliases { + led0 = &led1; + led1 = &led2; + led2 = &led3; + sw0 = &pb1; + sw1 = &pb2; + }; + + /* Used for accessing other pins */ + feather_header: feather_connector { + compatible = "adafruit-feather-header"; + #gpio-cells = <2>; + gpio-map-mask = <0xffffffff 0xffffffc0>; + gpio-map-pass-thru = <0 0x3f>; + gpio-map = <12 0 &gpio0 31 0>, /* SDA */ + <13 0 &gpio0 30 0>, /* SCL */ + <14 0 &gpio1 9 0>, /* GPIO */ + <15 0 &gpio1 8 0>, /* GPIO */ + <16 0 &gpio0 20 0>, /* GPIO */ + <17 0 &gpio0 24 0>, /* GPIO */ + <18 0 &gpio0 25 0>, /* GPIO */ + <19 0 &gpio1 7 0>, /* GPIO */ + <20 0 &gpio1 6 0>, /* GPIO */ + /* 11 not connected */ + <10 0 &gpio2 7 0>, /* TX */ + <9 0 &gpio2 6 0>, /* RX */ + <8 0 &gpio0 22 0>, /* MISO */ + <7 0 &gpio0 21 0>, /* MOSI */ + <6 0 &gpio0 23 0>, /* SCK */ + <5 0 &gpio2 5 0>, /* AIN5 */ + <4 0 &gpio2 4 0>, /* AIN4 */ + <3 0 &gpio2 3 0>, /* AIN3 */ + <2 0 &gpio2 2 0>, /* AIN2 */ + <1 0 &gpio2 1 0>, /* AIN1 */ + <0 0 &gpio2 0 0>; /* AIN0 */ + }; +}; + +&uart0 { + pinctrl-0 = <&uart0a_tx_p0_1 &uart0a_rx_p0_0>; + pinctrl-names = "default"; + current-speed = <115200>; + data-bits = <8>; + parity = "none"; + status = "okay"; +}; + +&clk_ipo { + status = "okay"; +}; + +&gpio0 { + status = "okay"; +}; + +&gpio1 { + status = "okay"; +}; + +&gpio2 { + status = "okay"; +}; + +&gpio3 { + status = "okay"; +}; diff --git a/boards/adi/max32655fthr/max32655fthr_max32655_m4.yaml b/boards/adi/max32655fthr/max32655fthr_max32655_m4.yaml new file mode 100644 index 0000000000000..af17994f344e7 --- /dev/null +++ b/boards/adi/max32655fthr/max32655fthr_max32655_m4.yaml @@ -0,0 +1,13 @@ +identifier: max32655fthr/max32655/m4 +name: max32655fthr m4 +type: mcu +arch: arm +toolchain: + - zephyr + - gnuarmemb + - xtools +supported: + - gpio + - serial +ram: 128 +flash: 512 diff --git a/boards/adi/max32655fthr/max32655fthr_max32655_m4_defconfig b/boards/adi/max32655fthr/max32655fthr_max32655_m4_defconfig new file mode 100644 index 0000000000000..4fa0a46410634 --- /dev/null +++ b/boards/adi/max32655fthr/max32655fthr_max32655_m4_defconfig @@ -0,0 +1,13 @@ +# Copyright (c) 2023-2024 Analog Devices, Inc. +# SPDX-License-Identifier: Apache-2.0 + +# Enable GPIO +CONFIG_GPIO=y + +# Console +CONFIG_CONSOLE=y +CONFIG_UART_CONSOLE=y + +# Enable UART +CONFIG_SERIAL=y +CONFIG_UART_INTERRUPT_DRIVEN=y From b9f8bd26d83ad19194ff13bcf48756f60c0e34d6 Mon Sep 17 00:00:00 2001 From: Sadik Ozer Date: Tue, 14 Nov 2023 18:16:29 +0300 Subject: [PATCH 1683/2849] tests: drivers: gpio: Enable gpio driver tests for max32655fthr board Enable gpio driver test for max32655fthr board Signed-off-by: Sadik Ozer --- .../boards/max32655fthr_max32655_m4.overlay | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 tests/drivers/gpio/gpio_basic_api/boards/max32655fthr_max32655_m4.overlay diff --git a/tests/drivers/gpio/gpio_basic_api/boards/max32655fthr_max32655_m4.overlay b/tests/drivers/gpio/gpio_basic_api/boards/max32655fthr_max32655_m4.overlay new file mode 100644 index 0000000000000..aef5fe92da573 --- /dev/null +++ b/tests/drivers/gpio/gpio_basic_api/boards/max32655fthr_max32655_m4.overlay @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2023-2024 Analog Devices, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + resources { + compatible = "test-gpio-basic-api"; + out-gpios = <&gpio2 0 0>; + in-gpios = <&gpio2 1 0>; + }; +}; From 3929e3fbc92c0a1e56c95e72eeb75d62e7aef4b0 Mon Sep 17 00:00:00 2001 From: Tomasz Chyrowicz Date: Fri, 24 May 2024 11:49:26 +0200 Subject: [PATCH 1684/2849] boards: nrf54h20dk: Add default DFU partition Define the default DFU partition. Signed-off-by: Tomasz Chyrowicz --- .../nrf54h20dk/nrf54h20dk_nrf54h20-memory_map.dtsi | 14 +++++++++----- .../nrf54h20dk/nrf54h20dk_nrf54h20_cpuapp.yaml | 2 +- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20-memory_map.dtsi b/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20-memory_map.dtsi index f67ddfb80bf48..7e4f859753c32 100644 --- a/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20-memory_map.dtsi +++ b/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20-memory_map.dtsi @@ -170,11 +170,11 @@ #size-cells = <1>; cpuapp_slot0_partition: partition@a6000 { - reg = <0xa6000 DT_SIZE_K(512)>; + reg = <0xa6000 DT_SIZE_K(296)>; }; - cpuppr_code_partition: partition@126000 { - reg = <0x126000 DT_SIZE_K(64)>; + cpuppr_code_partition: partition@f0000 { + reg = <0xf0000 DT_SIZE_K(64)>; }; }; @@ -187,8 +187,12 @@ #address-cells = <1>; #size-cells = <1>; - storage_partition: partition@136000 { - reg = <0x136000 DT_SIZE_K(24)>; + dfu_partition: partition@100000 { + reg = < 0x100000 DT_SIZE_K(892) >; + }; + + storage_partition: partition@1df000 { + reg = < 0x1df000 DT_SIZE_K(24) >; }; }; }; diff --git a/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpuapp.yaml b/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpuapp.yaml index f33351c61afe1..85d28db349467 100644 --- a/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpuapp.yaml +++ b/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpuapp.yaml @@ -10,7 +10,7 @@ toolchain: - xtools - zephyr ram: 256 -flash: 512 +flash: 296 supported: - can - counter From 209fc2e947828f16db1a2cd62b2d9dac46642748 Mon Sep 17 00:00:00 2001 From: Grzegorz Chwierut Date: Mon, 27 May 2024 10:55:47 +0200 Subject: [PATCH 1685/2849] MAINTAINERS: extend test area for boot tests Take all tests from tests/boot to mcuboot maintainer list Signed-off-by: Grzegorz Chwierut --- MAINTAINERS.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MAINTAINERS.yml b/MAINTAINERS.yml index b6346106bb426..44d2c990a0d3e 100644 --- a/MAINTAINERS.yml +++ b/MAINTAINERS.yml @@ -4603,7 +4603,7 @@ West: - nordicjm files: - modules/Kconfig.mcuboot - - tests/boot/test_mcuboot/ + - tests/boot/ labels: - "area: MCUBoot" From adfe3129d3d278339a0d08e32444be0dd75cea8b Mon Sep 17 00:00:00 2001 From: Grzegorz Chwierut Date: Mon, 27 May 2024 11:57:38 +0200 Subject: [PATCH 1686/2849] tests: boot: Add nrf54l15pdk to platform_allow list in with_mcumgr tests Extend platform_allow list for with_mcumgr tests with nRF54L board. Signed-off-by: Grzegorz Chwierut --- tests/boot/with_mcumgr/testcase.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/boot/with_mcumgr/testcase.yaml b/tests/boot/with_mcumgr/testcase.yaml index 3926819e6f2ff..98d5dbe7a2990 100644 --- a/tests/boot/with_mcumgr/testcase.yaml +++ b/tests/boot/with_mcumgr/testcase.yaml @@ -3,6 +3,7 @@ common: platform_allow: - nrf52840dk/nrf52840 - nrf5340dk/nrf5340/cpuapp + - nrf54l15pdk/nrf54l15/cpuapp - nrf9160dk/nrf9160 integration_platforms: - nrf52840dk/nrf52840 From 0f3fe4daab6e3e9043fc4b2ab982cfec368b9e68 Mon Sep 17 00:00:00 2001 From: Piotr Wojnarowski Date: Wed, 22 May 2024 22:04:55 +0200 Subject: [PATCH 1687/2849] riscv: Align _isr_wrapper to 64 bytes for CLIC The CLIC requires that mtvec.base is aligned to 64 bytes. _isr_wrapper is used as mtvec.base, so align it to 64 bytes. Signed-off-by: Piotr Wojnarowski --- arch/riscv/Kconfig | 1 + soc/common/riscv-privileged/vector.S | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig index 0993189b99cca..00121adc7148e 100644 --- a/arch/riscv/Kconfig +++ b/arch/riscv/Kconfig @@ -369,6 +369,7 @@ config ARCH_IRQ_VECTOR_TABLE_ALIGN config RISCV_TRAP_HANDLER_ALIGNMENT int "Alignment of RISC-V trap handler in bytes" + default 64 if RISCV_HAS_CLIC default 4 help This value configures the alignment of RISC-V trap handling diff --git a/soc/common/riscv-privileged/vector.S b/soc/common/riscv-privileged/vector.S index 4822fa5533358..5d7f84eab585a 100644 --- a/soc/common/riscv-privileged/vector.S +++ b/soc/common/riscv-privileged/vector.S @@ -33,7 +33,7 @@ SECTION_FUNC(vectors, __start) * * CLIC vectored mode uses mtvec exclusively for exception handling and * mtvec.base must be aligned to 64 bytes (this is done using - * CONFIG_ARCH_SW_ISR_TABLE_ALIGN) + * CONFIG_RISCV_TRAP_HANDLER_ALIGNMENT) */ la t0, _isr_wrapper addi t0, t0, 0x03 /* Enable CLIC vectored mode by setting LSB */ From ca19e6bbaa541d606dbbb8a6d267f448d231c00e Mon Sep 17 00:00:00 2001 From: Vivekananda Uppunda Date: Tue, 4 Jun 2024 12:53:28 +0530 Subject: [PATCH 1688/2849] net: wifi_shell: Resolve filter settings mismatch The control and data settings are set improperly for packet filter operation for sniffer operation. The change sets them properly. Signed-off-by: Vivekananda Uppunda --- subsys/net/l2/wifi/wifi_shell.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/subsys/net/l2/wifi/wifi_shell.c b/subsys/net/l2/wifi/wifi_shell.c index b0fcb63ad6dbb..399ef457fc567 100644 --- a/subsys/net/l2/wifi/wifi_shell.c +++ b/subsys/net/l2/wifi/wifi_shell.c @@ -1833,10 +1833,10 @@ void parse_filter_args_to_params(const struct shell *sh, int argc, filter->filter |= WIFI_PACKET_FILTER_MGMT; break; case 'c': - filter->filter |= WIFI_PACKET_FILTER_DATA; + filter->filter |= WIFI_PACKET_FILTER_CTRL; break; case 'd': - filter->filter |= WIFI_PACKET_FILTER_CTRL; + filter->filter |= WIFI_PACKET_FILTER_DATA; break; case 'i': filter->if_index = (uint8_t)atoi(state->optarg); From cee8080117cb42d8a6490e7df5360ca649705871 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Anders=20Storr=C3=B8?= Date: Thu, 30 May 2024 15:56:05 +0200 Subject: [PATCH 1689/2849] Bluetooth: Mesh: Fix PB GATT adv name MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes issue where PB GATT Server will drop advertising device name if optional provisioning URI is not provided. Signed-off-by: Anders Storrø --- subsys/bluetooth/mesh/pb_gatt_srv.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/subsys/bluetooth/mesh/pb_gatt_srv.c b/subsys/bluetooth/mesh/pb_gatt_srv.c index 62436a3c8d02f..f125bbb293c19 100644 --- a/subsys/bluetooth/mesh/pb_gatt_srv.c +++ b/subsys/bluetooth/mesh/pb_gatt_srv.c @@ -226,26 +226,27 @@ static size_t gatt_prov_adv_create(struct bt_data prov_sd[2]) sys_put_be16(prov->oob_info, prov_svc_data + 18); if (!prov->uri) { - return 0; + goto dev_name; } uri_len = strlen(prov->uri); if (uri_len > 29) { /* There's no way to shorten an URI */ LOG_WRN("Too long URI to fit advertising packet"); - return 0; + goto dev_name; } - prov_sd[0].type = BT_DATA_URI; - prov_sd[0].data_len = uri_len; - prov_sd[0].data = (const uint8_t *)prov->uri; + prov_sd[prov_sd_len].type = BT_DATA_URI; + prov_sd[prov_sd_len].data_len = uri_len; + prov_sd[prov_sd_len].data = (const uint8_t *)prov->uri; prov_sd_len += 1; +dev_name: #if defined(CONFIG_BT_MESH_PB_GATT_USE_DEVICE_NAME) - prov_sd[1].type = BT_DATA_NAME_COMPLETE; - prov_sd[1].data_len = sizeof(CONFIG_BT_DEVICE_NAME) - 1; - prov_sd[1].data = CONFIG_BT_DEVICE_NAME; + prov_sd[prov_sd_len].type = BT_DATA_NAME_COMPLETE; + prov_sd[prov_sd_len].data_len = sizeof(CONFIG_BT_DEVICE_NAME) - 1; + prov_sd[prov_sd_len].data = CONFIG_BT_DEVICE_NAME; prov_sd_len += 1; #endif From c11a08648b9a1b5e37d4d5b34617d59f5ef83b17 Mon Sep 17 00:00:00 2001 From: Ioannis Karachalios Date: Mon, 3 Jun 2024 22:21:40 +0300 Subject: [PATCH 1690/2849] west: Update manifest revision Update the manifest SHA to point to the HAL PR that removes the USB check from the DIV1 clock evaluation. This is because the USB block should be evaluated explicitly by the clock manager as a virtual USB clock is introduced in #73458. Signed-off-by: Ioannis Karachalios --- west.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/west.yml b/west.yml index dc048e90c7628..009b5ad3ddc1d 100644 --- a/west.yml +++ b/west.yml @@ -215,7 +215,7 @@ manifest: - hal - name: hal_renesas path: modules/hal/renesas - revision: 4ceafe0543a9e81c22e522a56228b789e1cb5b2c + revision: a8cd5ed480a31982a86dab8952ac8baaf646c3cb groups: - hal - name: hal_rpi_pico From 7c3b66eac85cdade79d090fc4d9360d07ce04d2b Mon Sep 17 00:00:00 2001 From: Nazar Palamar Date: Tue, 14 May 2024 11:37:43 +0300 Subject: [PATCH 1691/2849] soc: psoc6: update pinctrl for PSoC6 MCU (legacy) update pinctrl for PSoC6 MCU (legacy) Signed-off-by: Nazar Palamar --- .../cy8ckit_062_ble_common.dtsi | 5 +- .../cy8ckit_062_ble_cy8c6347-pinctrl.dtsi | 45 + .../cy8ckit_062_ble_cy8c6347_m0_0_0_0.overlay | 4 +- .../cy8ckit_062_ble_cy8c6347_m0_1_0_0.overlay | 10 +- .../cy8ckit_062_ble_cy8c6347_m4_0_0_0.overlay | 5 +- .../cy8ckit_062_wifi_bt_cy8c6247-pinctrl.dtsi | 45 + .../cy8ckit_062_wifi_bt_cy8c6247_m0.dts | 4 +- .../cy8ckit_062_wifi_bt_cy8c6247_m4.dts | 4 +- drivers/pinctrl/pinctrl_ifx_cat1.c | 1 - drivers/serial/Kconfig.psoc6 | 1 + drivers/serial/uart_psoc6.c | 23 +- drivers/spi/Kconfig.psoc6 | 1 + drivers/spi/spi_psoc6.c | 14 +- .../infineon/cat1a/legacy/psoc6-pinctrl.dtsi | 840 +++++++++++++++--- dts/arm/infineon/cat1a/legacy/psoc6.dtsi | 2 +- .../pinctrl/cypress,psoc6-pinctrl.yaml | 39 - dts/bindings/serial/cypress,psoc6-uart.yaml | 2 +- dts/bindings/spi/cypress,psoc6-spi.yaml | 2 +- soc/infineon/cat1a/CMakeLists.txt | 1 - soc/infineon/cat1a/psoc6_legacy/pinctrl_soc.h | 126 +++ soc/infineon/cat1a/psoc6_legacy/soc.h | 1 - soc/infineon/cat1a/psoc6_legacy/soc_gpio.c | 59 -- soc/infineon/cat1a/psoc6_legacy/soc_gpio.h | 99 --- 23 files changed, 973 insertions(+), 360 deletions(-) create mode 100644 boards/cypress/cy8ckit_062_ble/cy8ckit_062_ble_cy8c6347-pinctrl.dtsi create mode 100644 boards/cypress/cy8ckit_062_wifi_bt/cy8ckit_062_wifi_bt_cy8c6247-pinctrl.dtsi delete mode 100644 dts/bindings/pinctrl/cypress,psoc6-pinctrl.yaml create mode 100644 soc/infineon/cat1a/psoc6_legacy/pinctrl_soc.h delete mode 100644 soc/infineon/cat1a/psoc6_legacy/soc_gpio.c delete mode 100644 soc/infineon/cat1a/psoc6_legacy/soc_gpio.h diff --git a/boards/cypress/cy8ckit_062_ble/cy8ckit_062_ble_common.dtsi b/boards/cypress/cy8ckit_062_ble/cy8ckit_062_ble_common.dtsi index 437ea9ad225a0..764348106c9f7 100644 --- a/boards/cypress/cy8ckit_062_ble/cy8ckit_062_ble_common.dtsi +++ b/boards/cypress/cy8ckit_062_ble/cy8ckit_062_ble_common.dtsi @@ -86,7 +86,8 @@ &spi6 { cs-gpios = <&gpio_prt12 3 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>, - <&gpio_prt13 0 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>; + <&gpio_prt13 0 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>; - pinctrl-0 = <&p12_0_spi6_mosi &p12_1_spi6_miso &p12_2_spi6_clk>; + pinctrl-0 = <&p12_0_scb6_spi_m_mosi &p12_1_scb6_spi_m_miso &p12_2_scb6_spi_m_clk>; + pinctrl-names = "default"; }; diff --git a/boards/cypress/cy8ckit_062_ble/cy8ckit_062_ble_cy8c6347-pinctrl.dtsi b/boards/cypress/cy8ckit_062_ble/cy8ckit_062_ble_cy8c6347-pinctrl.dtsi new file mode 100644 index 0000000000000..1e42a6e464699 --- /dev/null +++ b/boards/cypress/cy8ckit_062_ble/cy8ckit_062_ble_cy8c6347-pinctrl.dtsi @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2023 Cypress Semiconductor Corporation (an Infineon company) or + * an affiliate of Cypress Semiconductor Corporation + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +/* Configure pin control bias mode for uart5 pins */ +&p5_1_scb5_uart_tx { + drive-push-pull; +}; + +&p5_0_scb5_uart_rx { + input-enable; +}; + +&p9_1_scb2_uart_tx { + drive-push-pull; +}; + +&p9_0_scb2_uart_rx { + input-enable; +}; + +&p13_1_scb6_uart_tx { + drive-push-pull; +}; + +&p13_0_scb6_uart_rx { + input-enable; +}; + +/* Configure pin control bias mode for SPI pins */ +&p12_0_scb6_spi_m_mosi { + drive-push-pull; +}; + +&p12_1_scb6_spi_m_miso { + input-enable; +}; + +&p12_2_scb6_spi_m_clk { + drive-push-pull; +}; diff --git a/boards/cypress/cy8ckit_062_ble/cy8ckit_062_ble_cy8c6347_m0_0_0_0.overlay b/boards/cypress/cy8ckit_062_ble/cy8ckit_062_ble_cy8c6347_m0_0_0_0.overlay index eab076f247cb8..9ef0f747cd06a 100644 --- a/boards/cypress/cy8ckit_062_ble/cy8ckit_062_ble_cy8c6347_m0_0_0_0.overlay +++ b/boards/cypress/cy8ckit_062_ble/cy8ckit_062_ble_cy8c6347_m0_0_0_0.overlay @@ -3,6 +3,7 @@ * * SPDX-License-Identifier: Apache-2.0 */ +#include "cy8ckit_062_ble_cy8c6347-pinctrl.dtsi" / { aliases { @@ -21,7 +22,8 @@ interrupt-parent = <&intmux_ch21>; - pinctrl-0 = <&p5_0_uart5_rx &p5_1_uart5_tx>; + pinctrl-0 = <&p5_0_scb5_uart_rx &p5_1_scb5_uart_tx>; + pinctrl-names = "default"; }; arduino_serial: &uart5 {}; diff --git a/boards/cypress/cy8ckit_062_ble/cy8ckit_062_ble_cy8c6347_m0_1_0_0.overlay b/boards/cypress/cy8ckit_062_ble/cy8ckit_062_ble_cy8c6347_m0_1_0_0.overlay index 49944a6dea498..ea63d017a6515 100644 --- a/boards/cypress/cy8ckit_062_ble/cy8ckit_062_ble_cy8c6347_m0_1_0_0.overlay +++ b/boards/cypress/cy8ckit_062_ble/cy8ckit_062_ble_cy8c6347_m0_1_0_0.overlay @@ -4,6 +4,8 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include "cy8ckit_062_ble_cy8c6347-pinctrl.dtsi" + / { aliases { uart-2 = &uart2; @@ -21,7 +23,9 @@ interrupt-parent = <&intmux_ch21>; - pinctrl-0 = <&p9_0_uart2_rx &p9_1_uart2_tx>; + pinctrl-0 = <&p9_0_scb2_uart_rx &p9_1_scb2_uart_tx>; + pinctrl-names = "default"; + }; &uart5 { @@ -30,7 +34,9 @@ interrupt-parent = <&intmux_ch22>; - pinctrl-0 = <&p5_0_uart5_rx &p5_1_uart5_tx>; + pinctrl-0 = <&p5_0_scb5_uart_rx &p5_1_scb5_uart_tx>; + pinctrl-names = "default"; + }; arduino_serial: &uart5 {}; diff --git a/boards/cypress/cy8ckit_062_ble/cy8ckit_062_ble_cy8c6347_m4_0_0_0.overlay b/boards/cypress/cy8ckit_062_ble/cy8ckit_062_ble_cy8c6347_m4_0_0_0.overlay index 9284d41cea78e..26f422a9b4dc3 100644 --- a/boards/cypress/cy8ckit_062_ble/cy8ckit_062_ble_cy8c6347_m4_0_0_0.overlay +++ b/boards/cypress/cy8ckit_062_ble/cy8ckit_062_ble_cy8c6347_m4_0_0_0.overlay @@ -4,6 +4,8 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include "cy8ckit_062_ble_cy8c6347-pinctrl.dtsi" + / { aliases { uart-6 = &uart6; @@ -19,5 +21,6 @@ status = "okay"; current-speed = <115200>; - pinctrl-0 = <&p13_0_uart6_rx &p13_1_uart6_tx>; + pinctrl-0 = <&p13_0_scb6_uart_rx &p13_1_scb6_uart_tx>; + pinctrl-names = "default"; }; diff --git a/boards/cypress/cy8ckit_062_wifi_bt/cy8ckit_062_wifi_bt_cy8c6247-pinctrl.dtsi b/boards/cypress/cy8ckit_062_wifi_bt/cy8ckit_062_wifi_bt_cy8c6247-pinctrl.dtsi new file mode 100644 index 0000000000000..1e42a6e464699 --- /dev/null +++ b/boards/cypress/cy8ckit_062_wifi_bt/cy8ckit_062_wifi_bt_cy8c6247-pinctrl.dtsi @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2023 Cypress Semiconductor Corporation (an Infineon company) or + * an affiliate of Cypress Semiconductor Corporation + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +/* Configure pin control bias mode for uart5 pins */ +&p5_1_scb5_uart_tx { + drive-push-pull; +}; + +&p5_0_scb5_uart_rx { + input-enable; +}; + +&p9_1_scb2_uart_tx { + drive-push-pull; +}; + +&p9_0_scb2_uart_rx { + input-enable; +}; + +&p13_1_scb6_uart_tx { + drive-push-pull; +}; + +&p13_0_scb6_uart_rx { + input-enable; +}; + +/* Configure pin control bias mode for SPI pins */ +&p12_0_scb6_spi_m_mosi { + drive-push-pull; +}; + +&p12_1_scb6_spi_m_miso { + input-enable; +}; + +&p12_2_scb6_spi_m_clk { + drive-push-pull; +}; 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 18fe196201b2f..73766b76c1049 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 @@ -9,6 +9,7 @@ #include #include +#include "cy8ckit_062_wifi_bt_cy8c6247-pinctrl.dtsi" / { model = "cy8ckit_062_wifi_bt_m0 with a Cypress PSoC6 SoC"; @@ -61,5 +62,6 @@ interrupt-parent = <&intmux_ch21>; - pinctrl-0 = <&p13_0_uart6_rx &p13_1_uart6_tx>; + pinctrl-0 = <&p13_0_scb6_uart_rx &p13_1_scb6_uart_tx>; + pinctrl-names = "default"; }; 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 7cd87ba86342f..29ea4b85134c3 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 @@ -7,6 +7,7 @@ /dts-v1/; #include +#include "cy8ckit_062_wifi_bt_cy8c6247-pinctrl.dtsi" / { model = "cy8ckit_062_wifi_bt_m4 with a Cypress PSoC6 SoC"; @@ -28,5 +29,6 @@ status = "okay"; current-speed = <115200>; - pinctrl-0 = <&p5_0_uart5_rx &p5_1_uart5_tx>; + pinctrl-0 = <&p5_0_scb5_uart_rx &p5_1_scb5_uart_tx>; + pinctrl-names = "default"; }; diff --git a/drivers/pinctrl/pinctrl_ifx_cat1.c b/drivers/pinctrl/pinctrl_ifx_cat1.c index dbeaab855f300..d1806346a8fa2 100644 --- a/drivers/pinctrl/pinctrl_ifx_cat1.c +++ b/drivers/pinctrl/pinctrl_ifx_cat1.c @@ -10,7 +10,6 @@ */ #include -#include #include #define GPIO_PORT_OR_NULL(node_id) \ diff --git a/drivers/serial/Kconfig.psoc6 b/drivers/serial/Kconfig.psoc6 index 66981e3766c40..4f0bb2c8fca0a 100644 --- a/drivers/serial/Kconfig.psoc6 +++ b/drivers/serial/Kconfig.psoc6 @@ -11,5 +11,6 @@ config UART_PSOC6 select SERIAL_HAS_DRIVER select SERIAL_SUPPORT_INTERRUPT select USE_INFINEON_UART + select PINCTRL help This option enables the SCB[UART] driver for PSoC-6 SoC family. diff --git a/drivers/serial/uart_psoc6.c b/drivers/serial/uart_psoc6.c index 6bf09b22b7174..fa46d8a8224ea 100644 --- a/drivers/serial/uart_psoc6.c +++ b/drivers/serial/uart_psoc6.c @@ -12,12 +12,8 @@ * - Error handling is not implemented. * - The driver works only in polling mode, interrupt mode is not implemented. */ -#include -#include -#include -#include -#include #include +#include #include "cy_syslib.h" #include "cy_sysclk.h" @@ -50,8 +46,7 @@ struct cypress_psoc6_config { #ifdef CONFIG_UART_INTERRUPT_DRIVEN uart_irq_config_func_t irq_config_func; #endif - uint32_t num_pins; - struct soc_gpio_pin pins[]; + const struct pinctrl_dev_config *pcfg; }; #ifdef CONFIG_UART_INTERRUPT_DRIVEN @@ -104,9 +99,14 @@ static const cy_stc_scb_uart_config_t uartConfig = { */ static int uart_psoc6_init(const struct device *dev) { + int ret; const struct cypress_psoc6_config *config = dev->config; - soc_gpio_list_configure(config->pins, config->num_pins); + /* Configure dt provided device signals when available */ + ret = pinctrl_apply_state(config->pcfg, PINCTRL_STATE_DEFAULT); + if (ret < 0) { + return ret; + } /* Connect assigned divider to be a clock source for UART */ Cy_SysClk_PeriphAssignDivider(config->periph_id, @@ -344,14 +344,11 @@ static const struct uart_driver_api uart_psoc6_driver_api = { #endif #define CY_PSOC6_UART_INIT(n) \ - CY_PSOC6_UART_DECL_DATA(n) \ - CY_PSOC6_UART_IRQ_FUNC(n) \ + PINCTRL_DT_INST_DEFINE(n); \ static const struct cypress_psoc6_config cy_psoc6_uart##n##_config = { \ .base = (CySCB_Type *)DT_INST_REG_ADDR(n), \ .periph_id = DT_INST_PROP(n, peripheral_id), \ - \ - .num_pins = CY_PSOC6_DT_INST_NUM_PINS(n), \ - .pins = CY_PSOC6_DT_INST_PINS(n), \ + .pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n), \ \ CY_PSOC6_UART_IRQ_SET_FUNC(n) \ }; \ diff --git a/drivers/spi/Kconfig.psoc6 b/drivers/spi/Kconfig.psoc6 index 21b4bfe596bcd..5b7fe353d8190 100644 --- a/drivers/spi/Kconfig.psoc6 +++ b/drivers/spi/Kconfig.psoc6 @@ -8,5 +8,6 @@ config SPI_PSOC6 default y depends on DT_HAS_CYPRESS_PSOC6_SPI_ENABLED select USE_INFINEON_SPI + select PINCTRL help This option enables the SCB[SPI] driver for PSoC-6 SoC family. diff --git a/drivers/spi/spi_psoc6.c b/drivers/spi/spi_psoc6.c index 7b6a30d3a6540..817c94899b274 100644 --- a/drivers/spi/spi_psoc6.c +++ b/drivers/spi/spi_psoc6.c @@ -31,8 +31,7 @@ struct spi_psoc6_config { CySCB_Type *base; uint32_t periph_id; void (*irq_config_func)(const struct device *dev); - uint32_t num_pins; - struct soc_gpio_pin pins[]; + const struct pinctrl_dev_config *pcfg; }; struct spi_psoc6_transfer { @@ -377,7 +376,12 @@ static int spi_psoc6_init(const struct device *dev) const struct spi_psoc6_config *config = dev->config; struct spi_psoc6_data *data = dev->data; - soc_gpio_list_configure(config->pins, config->num_pins); + + /* Configure dt provided device signals when available */ + err = pinctrl_apply_state(config->pcfg, PINCTRL_STATE_DEFAULT); + if (ret < 0) { + return ret; + } Cy_SysClk_PeriphAssignDivider(config->periph_id, CY_SYSCLK_DIV_8_BIT, @@ -408,12 +412,12 @@ static const struct spi_driver_api spi_psoc6_driver_api = { }; #define SPI_PSOC6_DEVICE_INIT(n) \ + PINCTRL_DT_INST_DEFINE(n); \ static void spi_psoc6_spi##n##_irq_cfg(const struct device *port); \ static const struct spi_psoc6_config spi_psoc6_config_##n = { \ .base = (CySCB_Type *)DT_INST_REG_ADDR(n), \ .periph_id = DT_INST_PROP(n, peripheral_id), \ - .num_pins = CY_PSOC6_DT_INST_NUM_PINS(n), \ - .pins = CY_PSOC6_DT_INST_PINS(n), \ + .pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n), \ .irq_config_func = spi_psoc6_spi##n##_irq_cfg, \ }; \ static struct spi_psoc6_data spi_psoc6_dev_data_##n = { \ diff --git a/dts/arm/infineon/cat1a/legacy/psoc6-pinctrl.dtsi b/dts/arm/infineon/cat1a/legacy/psoc6-pinctrl.dtsi index 526f74eea036c..2f06ed2269fcb 100644 --- a/dts/arm/infineon/cat1a/legacy/psoc6-pinctrl.dtsi +++ b/dts/arm/infineon/cat1a/legacy/psoc6-pinctrl.dtsi @@ -4,140 +4,718 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include "pinctrl_cypress_psoc6.h" +#include +#include / { soc { - pinctrl@40310000 { - /* instance, signal, port, pin, hsiom [, flag1, ... ] */ - DT_CYPRESS_HSIOM(spi0, mosi, 0, 2, act_8, drive-push-pull); - DT_CYPRESS_HSIOM(spi0, miso, 0, 3, act_8, input-enable); - DT_CYPRESS_HSIOM(spi0, clk, 0, 4, act_8, drive-push-pull); - DT_CYPRESS_HSIOM(spi0, sel0, 0, 5, act_8, drive-push-pull); - DT_CYPRESS_HSIOM(spi0, sel1, 0, 0, act_8, drive-push-pull); - DT_CYPRESS_HSIOM(spi0, sel2, 0, 1, act_8, drive-push-pull); - DT_CYPRESS_HSIOM(spi1, mosi, 10, 0, act_8, drive-push-pull); - DT_CYPRESS_HSIOM(spi1, miso, 10, 1, act_8, input-enable); - DT_CYPRESS_HSIOM(spi1, clk, 10, 2, act_8, drive-push-pull); - DT_CYPRESS_HSIOM(spi1, sel0, 10, 3, act_8, drive-push-pull); - DT_CYPRESS_HSIOM(spi1, sel1, 10, 4, act_8, drive-push-pull); - DT_CYPRESS_HSIOM(spi1, sel2, 10, 5, act_8, drive-push-pull); - DT_CYPRESS_HSIOM(spi1, sel3, 10, 6, act_8, drive-push-pull); - DT_CYPRESS_HSIOM(spi2, mosi, 9, 0, act_8, drive-push-pull); - DT_CYPRESS_HSIOM(spi2, miso, 9, 1, act_8, input-enable); - DT_CYPRESS_HSIOM(spi2, clk, 9, 2, act_8, drive-push-pull); - DT_CYPRESS_HSIOM(spi2, sel0, 9, 3, act_8, drive-push-pull); - DT_CYPRESS_HSIOM(spi2, sel1, 9, 4, act_8, drive-push-pull); - DT_CYPRESS_HSIOM(spi2, sel2, 9, 5, act_8, drive-push-pull); - DT_CYPRESS_HSIOM(spi2, sel3, 9, 6, act_8, drive-push-pull); - DT_CYPRESS_HSIOM(spi3, mosi, 6, 0, act_8, drive-push-pull); - DT_CYPRESS_HSIOM(spi3, miso, 6, 1, act_8, input-enable); - DT_CYPRESS_HSIOM(spi3, clk, 6, 2, act_8, drive-push-pull); - DT_CYPRESS_HSIOM(spi3, sel0, 6, 3, act_8, drive-push-pull); - DT_CYPRESS_HSIOM(spi3, sel1, 7, 7, act_8, drive-push-pull); - DT_CYPRESS_HSIOM(spi3, sel2, 8, 7, act_8, drive-push-pull); - DT_CYPRESS_HSIOM(spi3, sel3, 5, 7, act_8, drive-push-pull); - DT_CYPRESS_HSIOM(spi4, mosi, 7, 0, act_8, drive-push-pull); - DT_CYPRESS_HSIOM(spi4, miso, 7, 1, act_8, input-enable); - DT_CYPRESS_HSIOM(spi4, clk, 7, 2, act_8, drive-push-pull); - DT_CYPRESS_HSIOM(spi4, sel0, 7, 3, act_8, drive-push-pull); - DT_CYPRESS_HSIOM(spi4, sel1, 7, 4, act_8, drive-push-pull); - DT_CYPRESS_HSIOM(spi4, sel2, 7, 5, act_8, drive-push-pull); - DT_CYPRESS_HSIOM(spi4, sel3, 7, 6, act_8, drive-push-pull); - DT_CYPRESS_HSIOM(spi4, mosi, 8, 0, act_8, drive-push-pull); - DT_CYPRESS_HSIOM(spi4, miso, 8, 1, act_8, input-enable); - DT_CYPRESS_HSIOM(spi4, clk, 8, 2, act_8, drive-push-pull); - DT_CYPRESS_HSIOM(spi4, sel0, 8, 3, act_8, drive-push-pull); - DT_CYPRESS_HSIOM(spi4, sel1, 8, 4, act_8, drive-push-pull); - DT_CYPRESS_HSIOM(spi4, sel2, 8, 5, act_8, drive-push-pull); - DT_CYPRESS_HSIOM(spi4, sel3, 8, 6, act_8, drive-push-pull); - DT_CYPRESS_HSIOM(spi5, mosi, 5, 0, act_8, drive-push-pull); - DT_CYPRESS_HSIOM(spi5, miso, 5, 1, act_8, input-enable); - DT_CYPRESS_HSIOM(spi5, clk, 5, 2, act_8, drive-push-pull); - DT_CYPRESS_HSIOM(spi5, sel0, 5, 3, act_8, drive-push-pull); - DT_CYPRESS_HSIOM(spi5, sel1, 5, 4, act_8, drive-push-pull); - DT_CYPRESS_HSIOM(spi5, sel2, 5, 5, act_8, drive-push-pull); - DT_CYPRESS_HSIOM(spi5, sel3, 5, 6, act_8, drive-push-pull); - DT_CYPRESS_HSIOM(spi5, mosi, 11, 0, act_8, drive-push-pull); - DT_CYPRESS_HSIOM(spi5, miso, 11, 1, act_8, input-enable); - DT_CYPRESS_HSIOM(spi5, clk, 11, 2, act_8, drive-push-pull); - DT_CYPRESS_HSIOM(spi5, sel0, 11, 3, act_8, drive-push-pull); - DT_CYPRESS_HSIOM(spi5, sel1, 11, 4, act_8, drive-push-pull); - DT_CYPRESS_HSIOM(spi5, sel2, 11, 5, act_8, drive-push-pull); - DT_CYPRESS_HSIOM(spi5, sel3, 11, 6, act_8, drive-push-pull); - DT_CYPRESS_HSIOM(spi6, mosi, 6, 4, act_8, drive-push-pull); - DT_CYPRESS_HSIOM(spi6, miso, 6, 5, act_8, input-enable); - DT_CYPRESS_HSIOM(spi6, clk, 6, 6, act_8, drive-push-pull); - DT_CYPRESS_HSIOM(spi6, sel0, 6, 7, act_8, drive-push-pull); - DT_CYPRESS_HSIOM(spi6, mosi, 12, 0, act_8, drive-push-pull); - DT_CYPRESS_HSIOM(spi6, miso, 12, 1, act_8, input-enable); - DT_CYPRESS_HSIOM(spi6, clk, 12, 2, act_8, drive-push-pull); - DT_CYPRESS_HSIOM(spi6, sel0, 12, 3, act_8, drive-push-pull); - DT_CYPRESS_HSIOM(spi6, sel1, 12, 4, act_8, drive-push-pull); - DT_CYPRESS_HSIOM(spi6, sel2, 12, 5, act_8, drive-push-pull); - DT_CYPRESS_HSIOM(spi6, sel3, 12, 6, act_8, drive-push-pull); - DT_CYPRESS_HSIOM(spi6, mosi, 13, 0, act_8, drive-push-pull); - DT_CYPRESS_HSIOM(spi6, miso, 13, 1, act_8, input-enable); - DT_CYPRESS_HSIOM(spi6, clk, 13, 2, act_8, drive-push-pull); - DT_CYPRESS_HSIOM(spi6, sel0, 13, 3, act_8, drive-push-pull); - DT_CYPRESS_HSIOM(spi6, sel1, 13, 4, act_8, drive-push-pull); - DT_CYPRESS_HSIOM(spi6, sel2, 13, 5, act_8, drive-push-pull); - DT_CYPRESS_HSIOM(spi6, sel3, 13, 6, act_8, drive-push-pull); - DT_CYPRESS_HSIOM(spi7, mosi, 1, 0, act_8, drive-push-pull); - DT_CYPRESS_HSIOM(spi7, miso, 1, 1, act_8, input-enable); - DT_CYPRESS_HSIOM(spi7, clk, 1, 2, act_8, drive-push-pull); - DT_CYPRESS_HSIOM(spi7, sel0, 1, 3, act_8, drive-push-pull); - DT_CYPRESS_HSIOM(spi7, sel1, 1, 4, act_8, drive-push-pull); - DT_CYPRESS_HSIOM(spi7, sel2, 1, 5, act_8, drive-push-pull); - - DT_CYPRESS_HSIOM(uart0, rx, 0, 2, act_6, input-enable); - DT_CYPRESS_HSIOM(uart0, tx, 0, 3, act_6, drive-push-pull); - DT_CYPRESS_HSIOM(uart0, rts, 0, 4, act_6, drive-push-pull); - DT_CYPRESS_HSIOM(uart0, cts, 0, 5, act_6, input-enable); - DT_CYPRESS_HSIOM(uart1, rx, 10, 0, act_6, input-enable); - DT_CYPRESS_HSIOM(uart1, tx, 10, 1, act_6, drive-push-pull); - DT_CYPRESS_HSIOM(uart1, rts, 10, 2, act_6, drive-push-pull); - DT_CYPRESS_HSIOM(uart1, cts, 10, 3, act_6, input-enable); - DT_CYPRESS_HSIOM(uart2, rx, 9, 0, act_6, input-enable); - DT_CYPRESS_HSIOM(uart2, tx, 9, 1, act_6, drive-push-pull); - DT_CYPRESS_HSIOM(uart2, rts, 9, 2, act_6, drive-push-pull); - DT_CYPRESS_HSIOM(uart2, cts, 9, 3, act_6, input-enable); - DT_CYPRESS_HSIOM(uart3, rx, 6, 0, act_6, input-enable); - DT_CYPRESS_HSIOM(uart3, tx, 6, 1, act_6, drive-push-pull); - DT_CYPRESS_HSIOM(uart3, rts, 6, 2, act_6, drive-push-pull); - DT_CYPRESS_HSIOM(uart3, cts, 6, 3, act_6, input-enable); - DT_CYPRESS_HSIOM(uart4, rx, 7, 0, act_6, input-enable); - DT_CYPRESS_HSIOM(uart4, tx, 7, 1, act_6, drive-push-pull); - DT_CYPRESS_HSIOM(uart4, rts, 7, 2, act_6, drive-push-pull); - DT_CYPRESS_HSIOM(uart4, cts, 7, 3, act_6, input-enable); - DT_CYPRESS_HSIOM(uart4, rx, 8, 0, act_6, input-enable); - DT_CYPRESS_HSIOM(uart4, tx, 8, 1, act_6, drive-push-pull); - DT_CYPRESS_HSIOM(uart4, rts, 8, 2, act_6, drive-push-pull); - DT_CYPRESS_HSIOM(uart4, cts, 8, 3, act_6, input-enable); - DT_CYPRESS_HSIOM(uart5, rx, 5, 0, act_6, input-enable); - DT_CYPRESS_HSIOM(uart5, tx, 5, 1, act_6, drive-push-pull); - DT_CYPRESS_HSIOM(uart5, rts, 5, 2, act_6, drive-push-pull); - DT_CYPRESS_HSIOM(uart5, cts, 5, 3, act_6, input-enable); - DT_CYPRESS_HSIOM(uart5, rx, 11, 0, act_6, input-enable); - DT_CYPRESS_HSIOM(uart5, tx, 11, 1, act_6, drive-push-pull); - DT_CYPRESS_HSIOM(uart5, rts, 11, 2, act_6, drive-push-pull); - DT_CYPRESS_HSIOM(uart5, cts, 11, 3, act_6, input-enable); - DT_CYPRESS_HSIOM(uart6, rx, 6, 4, act_6, input-enable); - DT_CYPRESS_HSIOM(uart6, tx, 6, 5, act_6, drive-push-pull); - DT_CYPRESS_HSIOM(uart6, rts, 6, 6, act_6, drive-push-pull); - DT_CYPRESS_HSIOM(uart6, cts, 6, 7, act_6, input-enable); - DT_CYPRESS_HSIOM(uart6, rx, 12, 0, act_6, input-enable); - DT_CYPRESS_HSIOM(uart6, tx, 12, 1, act_6, drive-push-pull); - DT_CYPRESS_HSIOM(uart6, rts, 12, 2, act_6, drive-push-pull); - DT_CYPRESS_HSIOM(uart6, cts, 12, 3, act_6, input-enable); - DT_CYPRESS_HSIOM(uart6, rx, 13, 0, act_6, input-enable); - DT_CYPRESS_HSIOM(uart6, tx, 13, 1, act_6, drive-push-pull); - DT_CYPRESS_HSIOM(uart6, rts, 13, 2, act_6, drive-push-pull); - DT_CYPRESS_HSIOM(uart6, cts, 13, 3, act_6, input-enable); - DT_CYPRESS_HSIOM(uart7, rx, 1, 0, act_6, input-enable); - DT_CYPRESS_HSIOM(uart7, tx, 1, 1, act_6, drive-push-pull); - DT_CYPRESS_HSIOM(uart7, rts, 1, 2, act_6, drive-push-pull); - DT_CYPRESS_HSIOM(uart7, cts, 1, 3, act_6, input-enable); + + pinctrl: pinctrl@40310000 { + /* 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/ p5_0_scb5_i2c_scl: p5_0_scb5_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/ 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 = ; + }; + + /* 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/ p5_1_scb5_i2c_sda: p5_1_scb5_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/ 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 = ; + }; + + /* 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/ p5_2_scb5_spi_m_clk: p5_2_scb5_spi_m_clk { + pinmux = ; + }; + /omit-if-no-ref/ p6_2_scb3_spi_m_clk: p6_2_scb3_spi_m_clk { + pinmux = ; + }; + /omit-if-no-ref/ p6_2_scb8_spi_m_clk: p6_2_scb8_spi_m_clk { + pinmux = ; + }; + /omit-if-no-ref/ p6_6_scb6_spi_m_clk: p6_6_scb6_spi_m_clk { + pinmux = ; + }; + /omit-if-no-ref/ p6_6_scb8_spi_m_clk: p6_6_scb8_spi_m_clk { + pinmux = ; + }; + /omit-if-no-ref/ p7_2_scb4_spi_m_clk: p7_2_scb4_spi_m_clk { + pinmux = ; + }; + /omit-if-no-ref/ p8_2_scb4_spi_m_clk: p8_2_scb4_spi_m_clk { + pinmux = ; + }; + /omit-if-no-ref/ p9_2_scb2_spi_m_clk: p9_2_scb2_spi_m_clk { + pinmux = ; + }; + /omit-if-no-ref/ p10_2_scb1_spi_m_clk: p10_2_scb1_spi_m_clk { + pinmux = ; + }; + /omit-if-no-ref/ p11_2_scb5_spi_m_clk: p11_2_scb5_spi_m_clk { + pinmux = ; + }; + /omit-if-no-ref/ p12_2_scb6_spi_m_clk: p12_2_scb6_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_1_scb7_spi_m_miso: p1_1_scb7_spi_m_miso { + pinmux = ; + }; + /omit-if-no-ref/ p5_1_scb5_spi_m_miso: p5_1_scb5_spi_m_miso { + pinmux = ; + }; + /omit-if-no-ref/ p6_1_scb3_spi_m_miso: p6_1_scb3_spi_m_miso { + pinmux = ; + }; + /omit-if-no-ref/ p6_1_scb8_spi_m_miso: p6_1_scb8_spi_m_miso { + pinmux = ; + }; + /omit-if-no-ref/ p6_5_scb6_spi_m_miso: p6_5_scb6_spi_m_miso { + pinmux = ; + }; + /omit-if-no-ref/ p6_5_scb8_spi_m_miso: p6_5_scb8_spi_m_miso { + pinmux = ; + }; + /omit-if-no-ref/ p7_1_scb4_spi_m_miso: p7_1_scb4_spi_m_miso { + pinmux = ; + }; + /omit-if-no-ref/ p8_1_scb4_spi_m_miso: p8_1_scb4_spi_m_miso { + pinmux = ; + }; + /omit-if-no-ref/ p9_1_scb2_spi_m_miso: p9_1_scb2_spi_m_miso { + pinmux = ; + }; + /omit-if-no-ref/ p10_1_scb1_spi_m_miso: p10_1_scb1_spi_m_miso { + pinmux = ; + }; + /omit-if-no-ref/ p11_1_scb5_spi_m_miso: p11_1_scb5_spi_m_miso { + pinmux = ; + }; + /omit-if-no-ref/ p12_1_scb6_spi_m_miso: p12_1_scb6_spi_m_miso { + pinmux = ; + }; + /omit-if-no-ref/ p13_1_scb6_spi_m_miso: p13_1_scb6_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_0_scb7_spi_m_mosi: p1_0_scb7_spi_m_mosi { + pinmux = ; + }; + /omit-if-no-ref/ p5_0_scb5_spi_m_mosi: p5_0_scb5_spi_m_mosi { + pinmux = ; + }; + /omit-if-no-ref/ p6_0_scb3_spi_m_mosi: p6_0_scb3_spi_m_mosi { + pinmux = ; + }; + /omit-if-no-ref/ p6_0_scb8_spi_m_mosi: p6_0_scb8_spi_m_mosi { + pinmux = ; + }; + /omit-if-no-ref/ p6_4_scb6_spi_m_mosi: p6_4_scb6_spi_m_mosi { + pinmux = ; + }; + /omit-if-no-ref/ p6_4_scb8_spi_m_mosi: p6_4_scb8_spi_m_mosi { + pinmux = ; + }; + /omit-if-no-ref/ p7_0_scb4_spi_m_mosi: p7_0_scb4_spi_m_mosi { + pinmux = ; + }; + /omit-if-no-ref/ p8_0_scb4_spi_m_mosi: p8_0_scb4_spi_m_mosi { + pinmux = ; + }; + /omit-if-no-ref/ p9_0_scb2_spi_m_mosi: p9_0_scb2_spi_m_mosi { + pinmux = ; + }; + /omit-if-no-ref/ p10_0_scb1_spi_m_mosi: p10_0_scb1_spi_m_mosi { + pinmux = ; + }; + /omit-if-no-ref/ p11_0_scb5_spi_m_mosi: p11_0_scb5_spi_m_mosi { + pinmux = ; + }; + /omit-if-no-ref/ p12_0_scb6_spi_m_mosi: p12_0_scb6_spi_m_mosi { + pinmux = ; + }; + /omit-if-no-ref/ p13_0_scb6_spi_m_mosi: p13_0_scb6_spi_m_mosi { + pinmux = ; + }; + + /* scb_spi_m_select0 */ + /omit-if-no-ref/ p0_5_scb0_spi_m_select0: p0_5_scb0_spi_m_select0 { + pinmux = ; + }; + /omit-if-no-ref/ p5_3_scb5_spi_m_select0: p5_3_scb5_spi_m_select0 { + pinmux = ; + }; + /omit-if-no-ref/ p6_3_scb3_spi_m_select0: p6_3_scb3_spi_m_select0 { + pinmux = ; + }; + /omit-if-no-ref/ p6_3_scb8_spi_m_select0: p6_3_scb8_spi_m_select0 { + pinmux = ; + }; + /omit-if-no-ref/ p6_7_scb6_spi_m_select0: p6_7_scb6_spi_m_select0 { + pinmux = ; + }; + /omit-if-no-ref/ p6_7_scb8_spi_m_select0: p6_7_scb8_spi_m_select0 { + pinmux = ; + }; + /omit-if-no-ref/ p7_3_scb4_spi_m_select0: p7_3_scb4_spi_m_select0 { + pinmux = ; + }; + /omit-if-no-ref/ p8_3_scb4_spi_m_select0: p8_3_scb4_spi_m_select0 { + pinmux = ; + }; + /omit-if-no-ref/ p9_3_scb2_spi_m_select0: p9_3_scb2_spi_m_select0 { + pinmux = ; + }; + /omit-if-no-ref/ p10_3_scb1_spi_m_select0: p10_3_scb1_spi_m_select0 { + pinmux = ; + }; + /omit-if-no-ref/ p11_3_scb5_spi_m_select0: p11_3_scb5_spi_m_select0 { + pinmux = ; + }; + /omit-if-no-ref/ p12_3_scb6_spi_m_select0: p12_3_scb6_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/ p1_4_scb7_spi_m_select1: p1_4_scb7_spi_m_select1 { + pinmux = ; + }; + /omit-if-no-ref/ p5_4_scb5_spi_m_select1: p5_4_scb5_spi_m_select1 { + pinmux = ; + }; + /omit-if-no-ref/ p7_4_scb4_spi_m_select1: p7_4_scb4_spi_m_select1 { + pinmux = ; + }; + /omit-if-no-ref/ p7_7_scb3_spi_m_select1: p7_7_scb3_spi_m_select1 { + pinmux = ; + }; + /omit-if-no-ref/ p8_4_scb4_spi_m_select1: p8_4_scb4_spi_m_select1 { + pinmux = ; + }; + /omit-if-no-ref/ p10_4_scb1_spi_m_select1: p10_4_scb1_spi_m_select1 { + pinmux = ; + }; + /omit-if-no-ref/ p11_4_scb5_spi_m_select1: p11_4_scb5_spi_m_select1 { + pinmux = ; + }; + /omit-if-no-ref/ p12_4_scb6_spi_m_select1: p12_4_scb6_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/ p1_5_scb7_spi_m_select2: p1_5_scb7_spi_m_select2 { + pinmux = ; + }; + /omit-if-no-ref/ p5_5_scb5_spi_m_select2: p5_5_scb5_spi_m_select2 { + pinmux = ; + }; + /omit-if-no-ref/ p7_5_scb4_spi_m_select2: p7_5_scb4_spi_m_select2 { + pinmux = ; + }; + /omit-if-no-ref/ p8_5_scb4_spi_m_select2: p8_5_scb4_spi_m_select2 { + pinmux = ; + }; + /omit-if-no-ref/ p8_7_scb3_spi_m_select2: p8_7_scb3_spi_m_select2 { + pinmux = ; + }; + /omit-if-no-ref/ p10_5_scb1_spi_m_select2: p10_5_scb1_spi_m_select2 { + pinmux = ; + }; + /omit-if-no-ref/ p11_5_scb5_spi_m_select2: p11_5_scb5_spi_m_select2 { + pinmux = ; + }; + + /* scb_spi_m_select3 */ + /omit-if-no-ref/ p5_6_scb5_spi_m_select3: p5_6_scb5_spi_m_select3 { + pinmux = ; + }; + /omit-if-no-ref/ p5_7_scb3_spi_m_select3: p5_7_scb3_spi_m_select3 { + pinmux = ; + }; + /omit-if-no-ref/ p7_6_scb4_spi_m_select3: p7_6_scb4_spi_m_select3 { + pinmux = ; + }; + /omit-if-no-ref/ p8_6_scb4_spi_m_select3: p8_6_scb4_spi_m_select3 { + pinmux = ; + }; + /omit-if-no-ref/ p10_6_scb1_spi_m_select3: p10_6_scb1_spi_m_select3 { + pinmux = ; + }; + /omit-if-no-ref/ p11_6_scb5_spi_m_select3: p11_6_scb5_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/ p5_2_scb5_spi_s_clk: p5_2_scb5_spi_s_clk { + pinmux = ; + }; + /omit-if-no-ref/ p6_2_scb3_spi_s_clk: p6_2_scb3_spi_s_clk { + pinmux = ; + }; + /omit-if-no-ref/ p6_2_scb8_spi_s_clk: p6_2_scb8_spi_s_clk { + pinmux = ; + }; + /omit-if-no-ref/ p6_6_scb6_spi_s_clk: p6_6_scb6_spi_s_clk { + pinmux = ; + }; + /omit-if-no-ref/ p6_6_scb8_spi_s_clk: p6_6_scb8_spi_s_clk { + pinmux = ; + }; + /omit-if-no-ref/ p7_2_scb4_spi_s_clk: p7_2_scb4_spi_s_clk { + pinmux = ; + }; + /omit-if-no-ref/ p8_2_scb4_spi_s_clk: p8_2_scb4_spi_s_clk { + pinmux = ; + }; + /omit-if-no-ref/ p9_2_scb2_spi_s_clk: p9_2_scb2_spi_s_clk { + pinmux = ; + }; + /omit-if-no-ref/ p10_2_scb1_spi_s_clk: p10_2_scb1_spi_s_clk { + pinmux = ; + }; + /omit-if-no-ref/ p11_2_scb5_spi_s_clk: p11_2_scb5_spi_s_clk { + pinmux = ; + }; + /omit-if-no-ref/ p12_2_scb6_spi_s_clk: p12_2_scb6_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_1_scb7_spi_s_miso: p1_1_scb7_spi_s_miso { + pinmux = ; + }; + /omit-if-no-ref/ p5_1_scb5_spi_s_miso: p5_1_scb5_spi_s_miso { + pinmux = ; + }; + /omit-if-no-ref/ p6_1_scb3_spi_s_miso: p6_1_scb3_spi_s_miso { + pinmux = ; + }; + /omit-if-no-ref/ p6_1_scb8_spi_s_miso: p6_1_scb8_spi_s_miso { + pinmux = ; + }; + /omit-if-no-ref/ p6_5_scb6_spi_s_miso: p6_5_scb6_spi_s_miso { + pinmux = ; + }; + /omit-if-no-ref/ p6_5_scb8_spi_s_miso: p6_5_scb8_spi_s_miso { + pinmux = ; + }; + /omit-if-no-ref/ p7_1_scb4_spi_s_miso: p7_1_scb4_spi_s_miso { + pinmux = ; + }; + /omit-if-no-ref/ p8_1_scb4_spi_s_miso: p8_1_scb4_spi_s_miso { + pinmux = ; + }; + /omit-if-no-ref/ p9_1_scb2_spi_s_miso: p9_1_scb2_spi_s_miso { + pinmux = ; + }; + /omit-if-no-ref/ p10_1_scb1_spi_s_miso: p10_1_scb1_spi_s_miso { + pinmux = ; + }; + /omit-if-no-ref/ p11_1_scb5_spi_s_miso: p11_1_scb5_spi_s_miso { + pinmux = ; + }; + /omit-if-no-ref/ p12_1_scb6_spi_s_miso: p12_1_scb6_spi_s_miso { + pinmux = ; + }; + /omit-if-no-ref/ p13_1_scb6_spi_s_miso: p13_1_scb6_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_0_scb7_spi_s_mosi: p1_0_scb7_spi_s_mosi { + pinmux = ; + }; + /omit-if-no-ref/ p5_0_scb5_spi_s_mosi: p5_0_scb5_spi_s_mosi { + pinmux = ; + }; + /omit-if-no-ref/ p6_0_scb3_spi_s_mosi: p6_0_scb3_spi_s_mosi { + pinmux = ; + }; + /omit-if-no-ref/ p6_0_scb8_spi_s_mosi: p6_0_scb8_spi_s_mosi { + pinmux = ; + }; + /omit-if-no-ref/ p6_4_scb6_spi_s_mosi: p6_4_scb6_spi_s_mosi { + pinmux = ; + }; + /omit-if-no-ref/ p6_4_scb8_spi_s_mosi: p6_4_scb8_spi_s_mosi { + pinmux = ; + }; + /omit-if-no-ref/ p7_0_scb4_spi_s_mosi: p7_0_scb4_spi_s_mosi { + pinmux = ; + }; + /omit-if-no-ref/ p8_0_scb4_spi_s_mosi: p8_0_scb4_spi_s_mosi { + pinmux = ; + }; + /omit-if-no-ref/ p9_0_scb2_spi_s_mosi: p9_0_scb2_spi_s_mosi { + pinmux = ; + }; + /omit-if-no-ref/ p10_0_scb1_spi_s_mosi: p10_0_scb1_spi_s_mosi { + pinmux = ; + }; + /omit-if-no-ref/ p11_0_scb5_spi_s_mosi: p11_0_scb5_spi_s_mosi { + pinmux = ; + }; + /omit-if-no-ref/ p12_0_scb6_spi_s_mosi: p12_0_scb6_spi_s_mosi { + pinmux = ; + }; + /omit-if-no-ref/ p13_0_scb6_spi_s_mosi: p13_0_scb6_spi_s_mosi { + pinmux = ; + }; + + /* scb_spi_s_select0 */ + /omit-if-no-ref/ p0_5_scb0_spi_s_select0: p0_5_scb0_spi_s_select0 { + pinmux = ; + }; + /omit-if-no-ref/ p5_3_scb5_spi_s_select0: p5_3_scb5_spi_s_select0 { + pinmux = ; + }; + /omit-if-no-ref/ p6_3_scb3_spi_s_select0: p6_3_scb3_spi_s_select0 { + pinmux = ; + }; + /omit-if-no-ref/ p6_3_scb8_spi_s_select0: p6_3_scb8_spi_s_select0 { + pinmux = ; + }; + /omit-if-no-ref/ p6_7_scb6_spi_s_select0: p6_7_scb6_spi_s_select0 { + pinmux = ; + }; + /omit-if-no-ref/ p6_7_scb8_spi_s_select0: p6_7_scb8_spi_s_select0 { + pinmux = ; + }; + /omit-if-no-ref/ p7_3_scb4_spi_s_select0: p7_3_scb4_spi_s_select0 { + pinmux = ; + }; + /omit-if-no-ref/ p8_3_scb4_spi_s_select0: p8_3_scb4_spi_s_select0 { + pinmux = ; + }; + /omit-if-no-ref/ p9_3_scb2_spi_s_select0: p9_3_scb2_spi_s_select0 { + pinmux = ; + }; + /omit-if-no-ref/ p10_3_scb1_spi_s_select0: p10_3_scb1_spi_s_select0 { + pinmux = ; + }; + /omit-if-no-ref/ p11_3_scb5_spi_s_select0: p11_3_scb5_spi_s_select0 { + pinmux = ; + }; + /omit-if-no-ref/ p12_3_scb6_spi_s_select0: p12_3_scb6_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/ p1_4_scb7_spi_s_select1: p1_4_scb7_spi_s_select1 { + pinmux = ; + }; + /omit-if-no-ref/ p5_4_scb5_spi_s_select1: p5_4_scb5_spi_s_select1 { + pinmux = ; + }; + /omit-if-no-ref/ p7_4_scb4_spi_s_select1: p7_4_scb4_spi_s_select1 { + pinmux = ; + }; + /omit-if-no-ref/ p7_7_scb3_spi_s_select1: p7_7_scb3_spi_s_select1 { + pinmux = ; + }; + /omit-if-no-ref/ p8_4_scb4_spi_s_select1: p8_4_scb4_spi_s_select1 { + pinmux = ; + }; + /omit-if-no-ref/ p10_4_scb1_spi_s_select1: p10_4_scb1_spi_s_select1 { + pinmux = ; + }; + /omit-if-no-ref/ p11_4_scb5_spi_s_select1: p11_4_scb5_spi_s_select1 { + pinmux = ; + }; + /omit-if-no-ref/ p12_4_scb6_spi_s_select1: p12_4_scb6_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/ p1_5_scb7_spi_s_select2: p1_5_scb7_spi_s_select2 { + pinmux = ; + }; + /omit-if-no-ref/ p5_5_scb5_spi_s_select2: p5_5_scb5_spi_s_select2 { + pinmux = ; + }; + /omit-if-no-ref/ p7_5_scb4_spi_s_select2: p7_5_scb4_spi_s_select2 { + pinmux = ; + }; + /omit-if-no-ref/ p8_5_scb4_spi_s_select2: p8_5_scb4_spi_s_select2 { + pinmux = ; + }; + /omit-if-no-ref/ p8_7_scb3_spi_s_select2: p8_7_scb3_spi_s_select2 { + pinmux = ; + }; + /omit-if-no-ref/ p10_5_scb1_spi_s_select2: p10_5_scb1_spi_s_select2 { + pinmux = ; + }; + /omit-if-no-ref/ p11_5_scb5_spi_s_select2: p11_5_scb5_spi_s_select2 { + pinmux = ; + }; + + /* scb_spi_s_select3 */ + /omit-if-no-ref/ p5_6_scb5_spi_s_select3: p5_6_scb5_spi_s_select3 { + pinmux = ; + }; + /omit-if-no-ref/ p5_7_scb3_spi_s_select3: p5_7_scb3_spi_s_select3 { + pinmux = ; + }; + /omit-if-no-ref/ p7_6_scb4_spi_s_select3: p7_6_scb4_spi_s_select3 { + pinmux = ; + }; + /omit-if-no-ref/ p8_6_scb4_spi_s_select3: p8_6_scb4_spi_s_select3 { + pinmux = ; + }; + /omit-if-no-ref/ p10_6_scb1_spi_s_select3: p10_6_scb1_spi_s_select3 { + pinmux = ; + }; + /omit-if-no-ref/ p11_6_scb5_spi_s_select3: p11_6_scb5_spi_s_select3 { + pinmux = ; + }; + + /* scb_uart_cts */ + /omit-if-no-ref/ p0_5_scb0_uart_cts: p0_5_scb0_uart_cts { + pinmux = ; + }; + /omit-if-no-ref/ p5_3_scb5_uart_cts: p5_3_scb5_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/ 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 = ; + }; + + /* scb_uart_rts */ + /omit-if-no-ref/ p0_4_scb0_uart_rts: p0_4_scb0_uart_rts { + pinmux = ; + }; + /omit-if-no-ref/ p5_2_scb5_uart_rts: p5_2_scb5_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/ 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 = ; + }; + + /* 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/ p5_0_scb5_uart_rx: p5_0_scb5_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/ 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 = ; + }; + + /* 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/ p5_1_scb5_uart_tx: p5_1_scb5_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/ 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 = ; + }; }; }; }; diff --git a/dts/arm/infineon/cat1a/legacy/psoc6.dtsi b/dts/arm/infineon/cat1a/legacy/psoc6.dtsi index a6ab61e9949dd..ad9fef2e0fdef 100644 --- a/dts/arm/infineon/cat1a/legacy/psoc6.dtsi +++ b/dts/arm/infineon/cat1a/legacy/psoc6.dtsi @@ -67,7 +67,7 @@ soc { pinctrl@40310000 { - compatible = "cypress,psoc6-pinctrl"; + compatible = "infineon,cat1-pinctrl"; #address-cells = <1>; #size-cells = <1>; ranges = <0x40310000 0x40310000 0x2024>; diff --git a/dts/bindings/pinctrl/cypress,psoc6-pinctrl.yaml b/dts/bindings/pinctrl/cypress,psoc6-pinctrl.yaml deleted file mode 100644 index 8914f873f81f2..0000000000000 --- a/dts/bindings/pinctrl/cypress,psoc6-pinctrl.yaml +++ /dev/null @@ -1,39 +0,0 @@ -# Copyright (c) 2020, Linaro Limited -# Copyright (c) 2021, ATL Electronics -# SPDX-License-Identifier: Apache-2.0 - -description: | - Cypress PSoC-6 Pinctrl container node - - The Cypress PSoC-6 pins implements following pin configuration option: - - * bias-pull-up - * bias-pull-down - * drive-open-drain - * drive-open-source - * drive-push-pull (strong) - * input-enable (input-buffer) - - These options define devicetree flags that are converted to SoC flags at - CY_PSOC6_PIN_FLAGS(). - -compatible: "cypress,psoc6-pinctrl" - -include: base.yaml - -properties: - "#address-cells": - required: true - const: 1 - "#size-cells": - required: true - const: 1 - -child-binding: - description: cypress pins - - include: pincfg-node.yaml - - properties: - "cypress,pins": - type: phandle-array diff --git a/dts/bindings/serial/cypress,psoc6-uart.yaml b/dts/bindings/serial/cypress,psoc6-uart.yaml index 543975ab7c8c2..6cf83bce61790 100644 --- a/dts/bindings/serial/cypress,psoc6-uart.yaml +++ b/dts/bindings/serial/cypress,psoc6-uart.yaml @@ -6,7 +6,7 @@ description: Cypress SCB[UART] compatible: "cypress,psoc6-uart" -include: uart-controller.yaml +include: [uart-controller.yaml, pinctrl-device.yaml] properties: reg: diff --git a/dts/bindings/spi/cypress,psoc6-spi.yaml b/dts/bindings/spi/cypress,psoc6-spi.yaml index 81a12f44ec5db..bebdc53d314b1 100644 --- a/dts/bindings/spi/cypress,psoc6-spi.yaml +++ b/dts/bindings/spi/cypress,psoc6-spi.yaml @@ -5,7 +5,7 @@ description: Cypress SBC[SPI] compatible: "cypress,psoc6-spi" -include: spi-controller.yaml +include: [spi-controller.yaml, pinctrl-device.yaml] properties: reg: diff --git a/soc/infineon/cat1a/CMakeLists.txt b/soc/infineon/cat1a/CMakeLists.txt index c08c13ac0cc9e..fa77e29d0ced9 100644 --- a/soc/infineon/cat1a/CMakeLists.txt +++ b/soc/infineon/cat1a/CMakeLists.txt @@ -21,7 +21,6 @@ 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) diff --git a/soc/infineon/cat1a/psoc6_legacy/pinctrl_soc.h b/soc/infineon/cat1a/psoc6_legacy/pinctrl_soc.h new file mode 100644 index 0000000000000..30316fe87e8a9 --- /dev/null +++ b/soc/infineon/cat1a/psoc6_legacy/pinctrl_soc.h @@ -0,0 +1,126 @@ +/* + * 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_MASK GENMASK(7, 0) +#define SOC_PINMUX_PIN_MASK GENMASK(15, 8) +#define SOC_PINMUX_HSIOM_MASK GENMASK(23, 16) +#define SOC_PINMUX_SIGNAL_MASK GENMASK(31, 24) + +/* + * Pin flags/attributes + */ +#define SOC_GPIO_DEFAULT (0) +#define SOC_GPIO_FLAGS_POS (0) +#define SOC_GPIO_FLAGS_MASK GENMASK(6, 0) +#define SOC_GPIO_PULLUP_POS (0) +#define SOC_GPIO_PULLUP BIT(SOC_GPIO_PULLUP_POS) +#define SOC_GPIO_PULLDOWN_POS (1) +#define SOC_GPIO_PULLDOWN BIT(SOC_GPIO_PULLDOWN_POS) +#define SOC_GPIO_OPENDRAIN_POS (2) +#define SOC_GPIO_OPENDRAIN BIT(SOC_GPIO_OPENDRAIN_POS) +#define SOC_GPIO_OPENSOURCE_POS (3) +#define SOC_GPIO_OPENSOURCE BIT(SOC_GPIO_OPENSOURCE_POS) + +/* Push-Pull means Strong, see dts/pinctrl/pincfg-node.yaml */ +#define SOC_GPIO_PUSHPULL_POS (4) +#define SOC_GPIO_PUSHPULL BIT(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 BIT(SOC_GPIO_INPUTENABLE_POS) + +#define SOC_GPIO_HIGHZ_POS (6) +#define SOC_GPIO_HIGHZ BIT(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) FIELD_GET(SOC_PINMUX_PORT_MASK, pinmux) +#define CAT1_PINMUX_GET_PIN_NUM(pinmux) FIELD_GET(SOC_PINMUX_PIN_MASK, pinmux) +#define CAT1_PINMUX_GET_HSIOM_FUNC(pinmux) FIELD_GET(SOC_PINMUX_HSIOM_MASK, pinmux) + +/** + * @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/cat1a/psoc6_legacy/soc.h b/soc/infineon/cat1a/psoc6_legacy/soc.h index 8bd23b04ec2ae..a686d7a1b40d4 100644 --- a/soc/infineon/cat1a/psoc6_legacy/soc.h +++ b/soc/infineon/cat1a/psoc6_legacy/soc.h @@ -20,7 +20,6 @@ #ifndef _ASMLANGUAGE #include -#include "soc_gpio.h" #include "cypress_psoc6_dt.h" #endif /* !_ASMLANGUAGE */ diff --git a/soc/infineon/cat1a/psoc6_legacy/soc_gpio.c b/soc/infineon/cat1a/psoc6_legacy/soc_gpio.c deleted file mode 100644 index b58a88b0654fe..0000000000000 --- a/soc/infineon/cat1a/psoc6_legacy/soc_gpio.c +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (c) 2016 Piotr Mienkowski - * Copyright (c) 2021 ATL Electronics - * SPDX-License-Identifier: Apache-2.0 - */ - -/** @file - * @brief Cypress PSoC-6 MCU family General Purpose Input Output (GPIO) - * module HAL driver. - */ - -#include "soc_gpio.h" -#include "cy_gpio.h" - -static uint32_t soc_gpio_get_drv_mode(uint32_t flags) -{ - uint32_t drv_mode = CY_GPIO_DM_ANALOG; - - flags = ((flags & SOC_GPIO_FLAGS_MASK) >> SOC_GPIO_FLAGS_POS); - - if (flags & SOC_GPIO_OPENDRAIN) { - drv_mode = CY_GPIO_DM_OD_DRIVESLOW_IN_OFF; - } else if (flags & SOC_GPIO_OPENSOURCE) { - drv_mode = CY_GPIO_DM_OD_DRIVESHIGH_IN_OFF; - } else if (flags & SOC_GPIO_PUSHPULL) { - drv_mode = CY_GPIO_DM_STRONG_IN_OFF; - } else if ((flags & SOC_GPIO_PULLUP) && (flags & SOC_GPIO_PULLDOWN)) { - drv_mode = CY_GPIO_DM_PULLUP_DOWN_IN_OFF; - } else if (flags & SOC_GPIO_PULLUP) { - drv_mode = CY_GPIO_DM_PULLUP_IN_OFF; - } else if (flags & SOC_GPIO_PULLDOWN) { - drv_mode = CY_GPIO_DM_PULLDOWN_IN_OFF; - } else { - ; - } - - if (flags & SOC_GPIO_INPUTENABLE) { - drv_mode |= CY_GPIO_DM_HIGHZ; - } - - return drv_mode; -} - -void soc_gpio_configure(const struct soc_gpio_pin *pin) -{ - uint32_t drv_mode = soc_gpio_get_drv_mode(pin->flags); - uint32_t function = ((pin->flags & SOC_GPIO_FUNC_MASK) >> - SOC_GPIO_FUNC_POS); - - Cy_GPIO_SetHSIOM(pin->regs, pin->pinum, function); - Cy_GPIO_SetDrivemode(pin->regs, pin->pinum, drv_mode); -} - -void soc_gpio_list_configure(const struct soc_gpio_pin pins[], size_t size) -{ - for (size_t i = 0; i < size; i++) { - soc_gpio_configure(&pins[i]); - } -} diff --git a/soc/infineon/cat1a/psoc6_legacy/soc_gpio.h b/soc/infineon/cat1a/psoc6_legacy/soc_gpio.h deleted file mode 100644 index b14bcee4f723c..0000000000000 --- a/soc/infineon/cat1a/psoc6_legacy/soc_gpio.h +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright (c) 2016-2017 Piotr Mienkowski - * Copyright (c) 2021 ATL Electronics - * SPDX-License-Identifier: Apache-2.0 - */ - -/** @file - * @brief Cypress PSoC-6 MCU family General Purpose Input Output (GPIO) - * module HAL driver. - */ - -#ifndef _CYPRESS_PSOC6_SOC_GPIO_H_ -#define _CYPRESS_PSOC6_SOC_GPIO_H_ - -#include -#include - -/* - * 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) - -/* Bit field: SOC_GPIO_IN_FILTER */ -#define SOC_GPIO_IN_FILTER_POS (6) -#define SOC_GPIO_IN_FILTER_MASK (3 << SOC_GPIO_IN_FILTER_POS) -#define SOC_GPIO_IN_FILTER_NONE (0 << SOC_GPIO_IN_FILTER_POS) -#define SOC_GPIO_IN_FILTER_DEBOUNCE (1 << SOC_GPIO_IN_FILTER_POS) -#define SOC_GPIO_IN_FILTER_DEGLITCH (2 << SOC_GPIO_IN_FILTER_POS) - -#define SOC_GPIO_INT_ENABLE (1 << 8) - -/* Bit field: SOC_GPIO_INT_TRIG */ -#define SOC_GPIO_INT_TRIG_POS (9) -#define SOC_GPIO_INT_TRIG_MASK (3 << SOC_GPIO_INT_TRIG_POS) -/** Interrupt is triggered by a level detection event. */ -#define SOC_GPIO_INT_TRIG_LEVEL (0 << SOC_GPIO_INT_TRIG_POS) -/** Interrupt is triggered by an edge detection event. */ -#define SOC_GPIO_INT_TRIG_EDGE (1 << SOC_GPIO_INT_TRIG_POS) -/** Interrupt is triggered by any edge detection event. */ -#define SOC_GPIO_INT_TRIG_DOUBLE_EDGE (2 << SOC_GPIO_INT_TRIG_POS) - -/** Interrupt is triggered by a high level / rising edge detection event */ -#define SOC_GPIO_INT_ACTIVE_HIGH (1 << 11) - -/* Bit field: SOC_GPIO_FUNC */ -#define SOC_GPIO_FUNC_POS (16) -#define SOC_GPIO_FUNC_MASK (0x1F << SOC_GPIO_FUNC_POS) - -struct soc_gpio_pin { - GPIO_PRT_Type *regs; /** pointer to registers of the GPIO controller */ - uint32_t pinum; /** pin number */ - uint32_t flags; /** pin flags/attributes */ -}; - -/** - * @brief Configure GPIO pin(s). - * - * Configure one or several pins belonging to the same GPIO port. - * Example scenarios: - * - configure pin(s) as input with debounce filter enabled. - * - connect pin(s) to a HSIOM function and enable pull-up. - * - configure pin(s) as open drain output. - * All pins are configured in the same way. - * - * @param pin pin's configuration data such as pin mask, pin attributes, etc. - */ -void soc_gpio_configure(const struct soc_gpio_pin *pin); - -/** - * @brief Configure a list of GPIO pin(s). - * - * Configure an arbitrary amount of pins in an arbitrary way. Each - * configuration entry is a single item in an array passed as an - * argument to the function. - * - * @param pins an array where each item contains pin's configuration data. - * @param size size of the pin list. - */ -void soc_gpio_list_configure(const struct soc_gpio_pin pins[], size_t size); - -#endif /* _CYPRESS_PSOC6_SOC_GPIO_H_ */ From 052eb6180d25f42de0b25b06b5fe0cef88441ae4 Mon Sep 17 00:00:00 2001 From: Jeppe Odgaard Date: Wed, 22 May 2024 08:46:56 +0200 Subject: [PATCH 1692/2849] drivers: adc: adc_ad559x: fix 5593 adc read The AD5593 conversion result also contains the channel read and not just a value: | adc channel (3 bits) | adc value (12 bits) | This value was not removed from the result before using it as an adc value. Reuse the AD5592 code to fix the issue. Signed-off-by: Jeppe Odgaard --- drivers/adc/adc_ad559x.c | 43 +++++++++++++++++++--------------------- 1 file changed, 20 insertions(+), 23 deletions(-) diff --git a/drivers/adc/adc_ad559x.c b/drivers/adc/adc_ad559x.c index 21ee1e62e18de..b0e7bb9581087 100644 --- a/drivers/adc/adc_ad559x.c +++ b/drivers/adc/adc_ad559x.c @@ -130,9 +130,6 @@ static int adc_ad559x_read_channel(const struct device *dev, uint8_t channel, ui if (ret < 0) { return ret; } - - *result = sys_get_be16((uint8_t *)&val); - } else { /* * Invalid data: @@ -145,31 +142,31 @@ static int adc_ad559x_read_channel(const struct device *dev, uint8_t channel, ui if (ret < 0) { return ret; } + } - val = sys_be16_to_cpu(val); + val = sys_be16_to_cpu(val); - /* - * Invalid data: - * See "ADC section" in "Theory of operation" chapter. - * Valid ADC result has MSB bit set to 0. - */ - if ((val & AD559X_ADC_RES_IND_BIT) != 0) { - return -EAGAIN; - } - - /* - * Invalid channel converted: - * See "ADC section" in "Theory of operation" chapter. - * Conversion result contains channel number which should match requested channel. - */ - conv_channel = FIELD_GET(AD559X_ADC_RES_CHAN_MASK, val); - if (conv_channel != channel) { - return -EIO; - } + /* + * Invalid data: + * See AD5592 "ADC section" in "Theory of operation" chapter. + * Valid ADC result has MSB bit set to 0. + */ + if ((val & AD559X_ADC_RES_IND_BIT) != 0) { + return -EAGAIN; + } - *result = val & AD559X_ADC_RES_VAL_MASK; + /* + * Invalid channel converted: + * See AD5592 "ADC section" in "Theory of operation" chapter. + * Conversion result contains channel number which should match requested channel. + */ + conv_channel = FIELD_GET(AD559X_ADC_RES_CHAN_MASK, val); + if (conv_channel != channel) { + return -EIO; } + *result = val & AD559X_ADC_RES_VAL_MASK; + return 0; } From 371f22b9371c04564d671a10d90e70fad29c9e3f Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Sat, 18 May 2024 08:25:07 +0200 Subject: [PATCH 1693/2849] drivers: sensor: st: add driver for the STM32 Digital Temperature Sensor This add basic support for the STM32 Digital Temperature Sensor found notably on the STM32H7 series. It work in interrupt mode and support basic power device management. It does not support the more advanced features like using the temperature threshold, triggers from LPTIM or using the LSE clock in during sleep or stop. Signed-off-by: Aurelien Jarno --- drivers/sensor/st/CMakeLists.txt | 1 + drivers/sensor/st/Kconfig | 1 + .../sensor/st/stm32_digi_temp/CMakeLists.txt | 5 + drivers/sensor/st/stm32_digi_temp/Kconfig | 18 ++ .../st/stm32_digi_temp/stm32_digi_temp.c | 294 ++++++++++++++++++ dts/bindings/sensor/st,stm32-digi-temp.yaml | 18 ++ 6 files changed, 337 insertions(+) create mode 100644 drivers/sensor/st/stm32_digi_temp/CMakeLists.txt create mode 100644 drivers/sensor/st/stm32_digi_temp/Kconfig create mode 100644 drivers/sensor/st/stm32_digi_temp/stm32_digi_temp.c create mode 100644 dts/bindings/sensor/st,stm32-digi-temp.yaml diff --git a/drivers/sensor/st/CMakeLists.txt b/drivers/sensor/st/CMakeLists.txt index 31b191490b5c5..b833043ae6c66 100644 --- a/drivers/sensor/st/CMakeLists.txt +++ b/drivers/sensor/st/CMakeLists.txt @@ -33,6 +33,7 @@ add_subdirectory_ifdef(CONFIG_LSM6DSV16X lsm6dsv16x) add_subdirectory_ifdef(CONFIG_LSM9DS0_GYRO lsm9ds0_gyro) add_subdirectory_ifdef(CONFIG_LSM9DS0_MFD lsm9ds0_mfd) add_subdirectory_ifdef(CONFIG_QDEC_STM32 qdec_stm32) +add_subdirectory_ifdef(CONFIG_STM32_DIGI_TEMP stm32_digi_temp) add_subdirectory_ifdef(CONFIG_STM32_TEMP stm32_temp) add_subdirectory_ifdef(CONFIG_STM32_VBAT stm32_vbat) add_subdirectory_ifdef(CONFIG_STM32_VREF stm32_vref) diff --git a/drivers/sensor/st/Kconfig b/drivers/sensor/st/Kconfig index bb1cbd6b6a09e..a3f03a36b668d 100644 --- a/drivers/sensor/st/Kconfig +++ b/drivers/sensor/st/Kconfig @@ -32,6 +32,7 @@ source "drivers/sensor/st/lsm6dsv16x/Kconfig" source "drivers/sensor/st/lsm9ds0_gyro/Kconfig" source "drivers/sensor/st/lsm9ds0_mfd/Kconfig" source "drivers/sensor/st/qdec_stm32/Kconfig" +source "drivers/sensor/st/stm32_digi_temp/Kconfig" source "drivers/sensor/st/stm32_temp/Kconfig" source "drivers/sensor/st/stm32_vbat/Kconfig" source "drivers/sensor/st/stm32_vref/Kconfig" diff --git a/drivers/sensor/st/stm32_digi_temp/CMakeLists.txt b/drivers/sensor/st/stm32_digi_temp/CMakeLists.txt new file mode 100644 index 0000000000000..1f155f3219ded --- /dev/null +++ b/drivers/sensor/st/stm32_digi_temp/CMakeLists.txt @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: Apache-2.0 + +zephyr_library() + +zephyr_library_sources(stm32_digi_temp.c) diff --git a/drivers/sensor/st/stm32_digi_temp/Kconfig b/drivers/sensor/st/stm32_digi_temp/Kconfig new file mode 100644 index 0000000000000..e44814ee541f3 --- /dev/null +++ b/drivers/sensor/st/stm32_digi_temp/Kconfig @@ -0,0 +1,18 @@ +# STM32 digital temperature sensor configuration options + +# Copyright (c) 2024 Aurelien Jarno +# SPDX-License-Identifier: Apache-2.0 + +config STM32_DIGI_TEMP + bool "STM32 Digital Temperature Sensor" + default y + depends on DT_HAS_ST_STM32_DIGI_TEMP_ENABLED + depends on SOC_FAMILY_STM32 + help + Enable the driver for STM32 digital temperature sensor. This sensor + is different from the STM32 analog temperature sensor, which is read + by an ADC. While both drivers have similar code footprint, the analog + temperature driver also requires the ADC driver to be enabled. The + sensors differ in precision, accuracy and power consumption. Users + are encouraged to consult the datasheet to select the sensor that + best suits their needs. diff --git a/drivers/sensor/st/stm32_digi_temp/stm32_digi_temp.c b/drivers/sensor/st/stm32_digi_temp/stm32_digi_temp.c new file mode 100644 index 0000000000000..d862bb7a29a39 --- /dev/null +++ b/drivers/sensor/st/stm32_digi_temp/stm32_digi_temp.c @@ -0,0 +1,294 @@ +/* + * Copyright (c) 2024 Aurelien Jarno + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT st_stm32_digi_temp + +#include +#include +#include +#include +#include +#include + +LOG_MODULE_REGISTER(stm32_digi_temp, CONFIG_SENSOR_LOG_LEVEL); + +/* Constants */ +#define ONE_MHZ 1000000 /* Hz */ +#define TS1_T0_VAL0 30 /* °C */ +#define TS1_T0_VAL1 130 /* °C */ +#define SAMPLING_TIME 15 /* best precision */ + +struct stm32_digi_temp_data { + struct k_sem sem_isr; + struct k_mutex mutex; + + /* Peripheral clock frequency */ + uint32_t pclk_freq; + /* Engineering value of the frequency measured at T0 in Hz */ + uint32_t t0_freq; + /* Engineering value of the T0 temperature in °C */ + uint16_t t0; + /* Engineering value of the ramp coefficient in Hz / °C */ + uint16_t ramp_coeff; + + /* Raw sensor value */ + uint16_t raw; +}; + +struct stm32_digi_temp_config { + /* DTS instance. */ + DTS_TypeDef *base; + /* Clock configuration. */ + struct stm32_pclken pclken; + /* Interrupt configuration. */ + void (*irq_config)(const struct device *dev); +}; + +static void stm32_digi_temp_isr(const struct device *dev) +{ + struct stm32_digi_temp_data *data = dev->data; + const struct stm32_digi_temp_config *cfg = dev->config; + DTS_TypeDef *dts = cfg->base; + + /* Clear interrupt */ + SET_BIT(dts->ICIFR, DTS_ICIFR_TS1_CITEF); + + /* Give semaphore */ + k_sem_give(&data->sem_isr); +} + +static int stm32_digi_temp_sample_fetch(const struct device *dev, enum sensor_channel chan) +{ + const struct stm32_digi_temp_config *cfg = dev->config; + struct stm32_digi_temp_data *data = dev->data; + DTS_TypeDef *dts = cfg->base; + + if (chan != SENSOR_CHAN_ALL && chan != SENSOR_CHAN_DIE_TEMP) { + return -ENOTSUP; + } + + k_mutex_lock(&data->mutex, K_FOREVER); + + /* Wait for the sensor to be ready (~40µS delay after enabling it) */ + while (READ_BIT(dts->SR, DTS_SR_TS1_RDY) == 0) { + k_yield(); + } + + /* Trigger a measurement */ + SET_BIT(dts->CFGR1, DTS_CFGR1_TS1_START); + CLEAR_BIT(dts->CFGR1, DTS_CFGR1_TS1_START); + + /* Wait for interrupt */ + k_sem_take(&data->sem_isr, K_FOREVER); + + /* Read value */ + data->raw = READ_REG(dts->DR); + + k_mutex_unlock(&data->mutex); + + return 0; +} + +static int stm32_digi_temp_channel_get(const struct device *dev, enum sensor_channel chan, + struct sensor_value *val) +{ + struct stm32_digi_temp_data *data = dev->data; + float meas_freq, temp; + + if (chan != SENSOR_CHAN_ALL && chan != SENSOR_CHAN_DIE_TEMP) { + return -ENOTSUP; + } + + meas_freq = ((float)data->pclk_freq * SAMPLING_TIME) / data->raw; + temp = data->t0 + (meas_freq - data->t0_freq) / data->ramp_coeff; + + return sensor_value_from_float(val, temp); +} + +static void stm32_digi_temp_configure(const struct device *dev) +{ + const struct stm32_digi_temp_config *cfg = dev->config; + struct stm32_digi_temp_data *data = dev->data; + DTS_TypeDef *dts = cfg->base; + int clk_div; + + /* Use the prescaler to obtain an internal frequency lower than 1 MHz. + * Allowed values are between 0 and 127. + */ + clk_div = MIN(DIV_ROUND_UP(data->pclk_freq, ONE_MHZ), 127); + MODIFY_REG(dts->CFGR1, DTS_CFGR1_HSREF_CLK_DIV_Msk, + clk_div << DTS_CFGR1_HSREF_CLK_DIV_Pos); + + /* Select PCLK as reference clock */ + MODIFY_REG(dts->CFGR1, DTS_CFGR1_REFCLK_SEL_Msk, + 0 << DTS_CFGR1_REFCLK_SEL_Pos); + + /* Select trigger */ + MODIFY_REG(dts->CFGR1, DTS_CFGR1_TS1_INTRIG_SEL_Msk, + 0 << DTS_CFGR1_TS1_INTRIG_SEL_Pos); + + /* Set sampling time */ + MODIFY_REG(dts->CFGR1, DTS_CFGR1_TS1_SMP_TIME_Msk, + SAMPLING_TIME << DTS_CFGR1_TS1_SMP_TIME_Pos); +} + +static void stm32_digi_temp_enable(const struct device *dev) +{ + const struct stm32_digi_temp_config *cfg = dev->config; + DTS_TypeDef *dts = cfg->base; + + /* Enable the sensor */ + SET_BIT(dts->CFGR1, DTS_CFGR1_TS1_EN); + + /* Enable interrupt */ + SET_BIT(dts->ITENR, DTS_ITENR_TS1_ITEEN); +} + +#ifdef CONFIG_PM_DEVICE +static void stm32_digi_temp_disable(const struct device *dev) +{ + const struct stm32_digi_temp_config *cfg = dev->config; + DTS_TypeDef *dts = cfg->base; + + /* Disable interrupt */ + CLEAR_BIT(dts->ITENR, DTS_ITENR_TS1_ITEEN); + + /* Disable the sensor */ + CLEAR_BIT(dts->CFGR1, DTS_CFGR1_TS1_EN); +} +#endif + +static int stm32_digi_temp_init(const struct device *dev) +{ + const struct stm32_digi_temp_config *cfg = dev->config; + struct stm32_digi_temp_data *data = dev->data; + DTS_TypeDef *dts = cfg->base; + + /* enable clock for subsystem */ + 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_ERR("Could not enable DTS clock"); + return -EIO; + } + + /* Save the peripheral clock frequency in the data structure to avoid + * querying it for each call to the channel_get method. + */ + if (clock_control_get_rate(clk, (clock_control_subsys_t) &cfg->pclken, + &data->pclk_freq) < 0) { + LOG_ERR("Failed call clock_control_get_rate(pclken)"); + return -EIO; + } + + /* Save the calibration data in the data structure to avoid reading + * them for each call to the channel_get method, as this requires + * enabling the peripheral clock. + */ + data->ramp_coeff = dts->RAMPVALR & DTS_RAMPVALR_TS1_RAMP_COEFF; + data->t0_freq = (dts->T0VALR1 & DTS_T0VALR1_TS1_FMT0) * 100; /* 0.1 kHz -> Hz */ + + /* T0 temperature from the datasheet */ + switch (dts->T0VALR1 >> DTS_T0VALR1_TS1_T0_Pos) { + case 0: + data->t0 = TS1_T0_VAL0; + break; + case 1: + data->t0 = TS1_T0_VAL1; + break; + default: + LOG_ERR("Unknown T0 temperature value"); + return -EIO; + } + + /* Init mutex and semaphore */ + k_mutex_init(&data->mutex); + k_sem_init(&data->sem_isr, 0, 1); + + /* Configure and enable the sensor */ + cfg->irq_config(dev); + stm32_digi_temp_configure(dev); + stm32_digi_temp_enable(dev); + + return 0; +} + +#ifdef CONFIG_PM_DEVICE +static int stm32_digi_temp_pm_action(const struct device *dev, enum pm_device_action action) +{ + const struct stm32_digi_temp_config *cfg = dev->config; + const struct device *const clk = DEVICE_DT_GET(STM32_CLOCK_CONTROL_NODE); + int err; + + switch (action) { + case PM_DEVICE_ACTION_RESUME: + /* enable clock */ + err = clock_control_on(clk, (clock_control_subsys_t)&cfg->pclken); + if (err != 0) { + LOG_ERR("Could not enable DTS clock"); + return err; + } + /* Enable sensor */ + stm32_digi_temp_enable(dev); + break; + case PM_DEVICE_ACTION_SUSPEND: + /* Disable sensor */ + stm32_digi_temp_disable(dev); + /* Stop device clock */ + err = clock_control_off(clk, (clock_control_subsys_t)&cfg->pclken); + if (err != 0) { + LOG_ERR("Could not disable DTS clock"); + return err; + } + break; + default: + return -ENOTSUP; + } + + return 0; +} +#endif /* CONFIG_PM_DEVICE */ + +static const struct sensor_driver_api stm32_digi_temp_driver_api = { + .sample_fetch = stm32_digi_temp_sample_fetch, + .channel_get = stm32_digi_temp_channel_get, +}; + +#define STM32_DIGI_TEMP_INIT(index) \ +static void stm32_digi_temp_irq_config_func_##index(const struct device *dev) \ +{ \ + IRQ_CONNECT(DT_INST_IRQN(index), \ + DT_INST_IRQ(index, priority), \ + stm32_digi_temp_isr, DEVICE_DT_INST_GET(index), 0); \ + irq_enable(DT_INST_IRQN(index)); \ +} \ + \ +static struct stm32_digi_temp_data stm32_digi_temp_dev_data_##index; \ + \ +static const struct stm32_digi_temp_config stm32_digi_temp_dev_config_##index = { \ + .base = (DTS_TypeDef *)DT_INST_REG_ADDR(index), \ + .pclken = { \ + .enr = DT_INST_CLOCKS_CELL(index, bits), \ + .bus = DT_INST_CLOCKS_CELL(index, bus) \ + }, \ + .irq_config = stm32_digi_temp_irq_config_func_##index, \ +}; \ + \ +PM_DEVICE_DT_INST_DEFINE(index, stm32_digi_temp_pm_action); \ + \ +SENSOR_DEVICE_DT_INST_DEFINE(index, stm32_digi_temp_init, \ + PM_DEVICE_DT_INST_GET(index), \ + &stm32_digi_temp_dev_data_##index, \ + &stm32_digi_temp_dev_config_##index, \ + POST_KERNEL, CONFIG_SENSOR_INIT_PRIORITY, \ + &stm32_digi_temp_driver_api); \ + +DT_INST_FOREACH_STATUS_OKAY(STM32_DIGI_TEMP_INIT) diff --git a/dts/bindings/sensor/st,stm32-digi-temp.yaml b/dts/bindings/sensor/st,stm32-digi-temp.yaml new file mode 100644 index 0000000000000..4faba85246dd2 --- /dev/null +++ b/dts/bindings/sensor/st,stm32-digi-temp.yaml @@ -0,0 +1,18 @@ +# Copyright (c) 2024, Aurelien Jarno +# SPDX-License-Identifier: Apache-2.0 + +description: STM32 family Digital Temperature Sensor node + +compatible: "st,stm32-digi-temp" + +include: base.yaml + +properties: + reg: + required: true + + interrupts: + required: true + + clocks: + required: true From fe8c100252cf250c02cb270fce246d9e1f0d89cb Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Sat, 18 May 2024 08:26:19 +0200 Subject: [PATCH 1694/2849] dts: arm: st: h723/h7a3: add digi_dietemp node into DTSI file Add a digi_dietemp node for the STM32 Digital Temperature Sensor into stm32h723.dtsi (used as a base for H723, H725, H730 and H735) and stm32h7a3.dtsi (used as a base for H7A3, H7B0 and H7B3). The sensor is not available on other H7 SoCs. Signed-off-by: Aurelien Jarno --- dts/arm/st/h7/stm32h723.dtsi | 9 +++++++++ dts/arm/st/h7/stm32h7a3.dtsi | 9 +++++++++ 2 files changed, 18 insertions(+) diff --git a/dts/arm/st/h7/stm32h723.dtsi b/dts/arm/st/h7/stm32h723.dtsi index 662ecef5da94d..05e596974982c 100644 --- a/dts/arm/st/h7/stm32h723.dtsi +++ b/dts/arm/st/h7/stm32h723.dtsi @@ -177,6 +177,15 @@ status = "disabled"; }; }; + + digi_die_temp: digi_dietemp@58006800 { + compatible = "st,stm32-digi-temp"; + reg = <0x58006800 0x400>; + interrupts = <147 0>; + interrupt-names = "digi_temp"; + clocks = <&rcc STM32_CLOCK_BUS_APB4 0x04000000>; + status = "disabled"; + }; }; /* D1 domain, AXI SRAM (128KB with shared ITCM 192KB as `TCM_AXI_SHARED` is `000`) */ diff --git a/dts/arm/st/h7/stm32h7a3.dtsi b/dts/arm/st/h7/stm32h7a3.dtsi index 68f7d82969f54..a9a570e07abaf 100644 --- a/dts/arm/st/h7/stm32h7a3.dtsi +++ b/dts/arm/st/h7/stm32h7a3.dtsi @@ -97,6 +97,15 @@ health-test-magic = <0x17590abc>; health-test-config = <0x72ac>; }; + + digi_die_temp: digi_dietemp@58006800 { + compatible = "st,stm32-digi-temp"; + reg = <0x58006800 0x400>; + interrupts = <147 0>; + interrupt-names = "digi_temp"; + clocks = <&rcc STM32_CLOCK_BUS_APB4 0x04000000>; + status = "disabled"; + }; }; /* System data RAM accessible over AXI bus: AXI SRAM1 in CD domain */ From 460169df75292eee50ba0941162ec7a5ef802e90 Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Tue, 21 May 2024 22:12:22 +0200 Subject: [PATCH 1695/2849] samples: sensors: nucleo_h7a3zi_q board added to die_temp_polling Added board nucleo_h7a3zi_q overlay file to permit testing the STM32 Digital Temperature Sensor. Also added the board as integration platform to the sample. Signed-off-by: Aurelien Jarno --- .../boards/nucleo_h7a3zi_q.overlay | 17 +++++++++++++++++ samples/sensor/die_temp_polling/sample.yaml | 1 + 2 files changed, 18 insertions(+) create mode 100644 samples/sensor/die_temp_polling/boards/nucleo_h7a3zi_q.overlay diff --git a/samples/sensor/die_temp_polling/boards/nucleo_h7a3zi_q.overlay b/samples/sensor/die_temp_polling/boards/nucleo_h7a3zi_q.overlay new file mode 100644 index 0000000000000..f2081833b8cc3 --- /dev/null +++ b/samples/sensor/die_temp_polling/boards/nucleo_h7a3zi_q.overlay @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2024, Aurelien Jarno + * + * SPDX-License-Identifier: Apache-2.0 + * + * Application overlay for creating temperature sensor device instance + */ + +/ { + aliases { + die-temp0 = &digi_die_temp; + }; +}; + +&digi_die_temp { + status = "okay"; +}; diff --git a/samples/sensor/die_temp_polling/sample.yaml b/samples/sensor/die_temp_polling/sample.yaml index f64b321c2bdfe..adf8c4c003e58 100644 --- a/samples/sensor/die_temp_polling/sample.yaml +++ b/samples/sensor/die_temp_polling/sample.yaml @@ -8,6 +8,7 @@ tests: filter: dt_alias_exists("die-temp0") integration_platforms: - stm32f3_disco + - nucleo_h7a3zi_q harness: console harness_config: type: one_line From 61536c1096a9f617ed932a78c9c047f7922a1ffc Mon Sep 17 00:00:00 2001 From: Chris Braissant Date: Sat, 13 Apr 2024 15:38:18 +0200 Subject: [PATCH 1696/2849] drivers/sensor: lps22hh: Enable fetching individual sensor channels Add the possibility to fetch specific sensor channels independently, either pressure data with SENSOR_CHAN_PRESS or temperature data with SENSOR_CHAN_AMBIENT_TEMP. Additionally, the option to fetch both channels simultaneously remains available using SENSOR_CHAN_ALL, thus not breaking any samples. Signed-off-by: Chris Braissant --- drivers/sensor/st/lps22hh/lps22hh.c | 39 ++++++++++++++++++++++------- 1 file changed, 30 insertions(+), 9 deletions(-) diff --git a/drivers/sensor/st/lps22hh/lps22hh.c b/drivers/sensor/st/lps22hh/lps22hh.c index 01c698ba3c622..1ea4f2afb5b8e 100644 --- a/drivers/sensor/st/lps22hh/lps22hh.c +++ b/drivers/sensor/st/lps22hh/lps22hh.c @@ -39,15 +39,36 @@ static int lps22hh_sample_fetch(const struct device *dev, uint32_t raw_press; int16_t raw_temp; - __ASSERT_NO_MSG(chan == SENSOR_CHAN_ALL); - - if (lps22hh_pressure_raw_get(ctx, &raw_press) < 0) { - LOG_DBG("Failed to read sample"); - return -EIO; - } - if (lps22hh_temperature_raw_get(ctx, &raw_temp) < 0) { - LOG_DBG("Failed to read sample"); - return -EIO; + __ASSERT_NO_MSG(chan == SENSOR_CHAN_ALL + || chan == SENSOR_CHAN_PRESS + || chan == SENSOR_CHAN_AMBIENT_TEMP); + + switch (chan) { + case SENSOR_CHAN_PRESS: + if (lps22hh_pressure_raw_get(ctx, &raw_press) < 0) { + LOG_DBG("Failed to read sample"); + return -EIO; + } + break; + case SENSOR_CHAN_AMBIENT_TEMP: + if (lps22hh_temperature_raw_get(ctx, &raw_temp) < 0) { + LOG_DBG("Failed to read sample"); + return -EIO; + } + break; + case SENSOR_CHAN_ALL: + if (lps22hh_pressure_raw_get(ctx, &raw_press) < 0) { + LOG_DBG("Failed to read sample"); + return -EIO; + } + if (lps22hh_temperature_raw_get(ctx, &raw_temp) < 0) { + LOG_DBG("Failed to read sample"); + return -EIO; + } + break; + default: + LOG_ERR("Unsupported sensor channel"); + return -ENOTSUP; } data->sample_press = raw_press; From 422a709d9217d2326bd76ee53eed6e9769a33974 Mon Sep 17 00:00:00 2001 From: Ian Morris Date: Mon, 3 Jun 2024 09:48:48 -0700 Subject: [PATCH 1697/2849] soc: renesas: ra: added support for segger rtt Added support for Segger RTT to Renesas RA family of Microcontrollers. Signed-off-by: Ian Morris --- soc/renesas/ra/Kconfig | 3 +++ 1 file changed, 3 insertions(+) diff --git a/soc/renesas/ra/Kconfig b/soc/renesas/ra/Kconfig index 52a056a761265..c3651008a4198 100644 --- a/soc/renesas/ra/Kconfig +++ b/soc/renesas/ra/Kconfig @@ -1,6 +1,9 @@ # Copyright (c) 2023 TOKITA Hiroshi # SPDX-License-Identifier: Apache-2.0 +config SOC_FAMILY_RENESAS_RA + select HAS_SEGGER_RTT if ZEPHYR_SEGGER_MODULE + if SOC_FAMILY_RENESAS_RA config SERIES_SPECIFIC_SOC_INIT From 1cd6dd16c16d72dd80f9432b8a48ef238b1f5497 Mon Sep 17 00:00:00 2001 From: Yong Cong Sin Date: Sat, 1 Jun 2024 00:27:41 +0800 Subject: [PATCH 1698/2849] arch: Create `include/zephyr/arch/exception.h` Create `zephyr/include/zephyr/arch/exception.h`, which will redirect to the corrent architecture-specific exception header based on Kconfig. Some of the architectures define their esf struct in architecture-specific `arch.h`, refactor them out into a separate `exception.h`. Signed-off-by: Yong Cong Sin --- include/zephyr/arch/exception.h | 35 ++++++++++ include/zephyr/arch/nios2/arch.h | 24 +------ include/zephyr/arch/nios2/exception.h | 46 ++++++++++++ include/zephyr/arch/posix/arch.h | 7 +- include/zephyr/arch/posix/exception.h | 30 ++++++++ include/zephyr/arch/sparc/arch.h | 14 +--- include/zephyr/arch/sparc/exception.h | 36 ++++++++++ include/zephyr/arch/x86/ia32/arch.h | 48 +------------ include/zephyr/arch/x86/ia32/exception.h | 70 +++++++++++++++++++ include/zephyr/arch/x86/intel64/arch.h | 56 +-------------- include/zephyr/arch/x86/intel64/exception.h | 77 +++++++++++++++++++++ 11 files changed, 299 insertions(+), 144 deletions(-) create mode 100644 include/zephyr/arch/exception.h create mode 100644 include/zephyr/arch/nios2/exception.h create mode 100644 include/zephyr/arch/posix/exception.h create mode 100644 include/zephyr/arch/sparc/exception.h create mode 100644 include/zephyr/arch/x86/ia32/exception.h create mode 100644 include/zephyr/arch/x86/intel64/exception.h diff --git a/include/zephyr/arch/exception.h b/include/zephyr/arch/exception.h new file mode 100644 index 0000000000000..074a5e0b0d71c --- /dev/null +++ b/include/zephyr/arch/exception.h @@ -0,0 +1,35 @@ +/* exception.h - automatically selects the correct exception.h file to include */ + +/* + * Copyright (c) 2024 Meta Platforms + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_ARCH_EXCEPTION_H_ +#define ZEPHYR_INCLUDE_ARCH_EXCEPTION_H_ + +#if defined(CONFIG_X86_64) +#include +#elif defined(CONFIG_X86) +#include +#elif defined(CONFIG_ARM64) +#include +#elif defined(CONFIG_ARM) +#include +#elif defined(CONFIG_ARC) +#include +#elif defined(CONFIG_NIOS2) +#include +#elif defined(CONFIG_RISCV) +#include +#elif defined(CONFIG_XTENSA) +#include +#elif defined(CONFIG_MIPS) +#include +#elif defined(CONFIG_ARCH_POSIX) +#include +#elif defined(CONFIG_SPARC) +#include +#endif + +#endif /* ZEPHYR_INCLUDE_ARCH_EXCEPTION_H_ */ diff --git a/include/zephyr/arch/nios2/arch.h b/include/zephyr/arch/nios2/arch.h index 7df7ae9a91aa8..bbc41b200a6a8 100644 --- a/include/zephyr/arch/nios2/arch.h +++ b/include/zephyr/arch/nios2/arch.h @@ -17,6 +17,7 @@ #include #include +#include #include #include #include @@ -99,29 +100,6 @@ static ALWAYS_INLINE bool arch_irq_unlocked(unsigned int key) void arch_irq_enable(unsigned int irq); void arch_irq_disable(unsigned int irq); -struct __esf { - uint32_t ra; /* return address r31 */ - uint32_t r1; /* at */ - uint32_t r2; /* return value */ - uint32_t r3; /* return value */ - uint32_t r4; /* register args */ - uint32_t r5; /* register args */ - uint32_t r6; /* register args */ - uint32_t r7; /* register args */ - uint32_t r8; /* Caller-saved general purpose */ - uint32_t r9; /* Caller-saved general purpose */ - uint32_t r10; /* Caller-saved general purpose */ - uint32_t r11; /* Caller-saved general purpose */ - uint32_t r12; /* Caller-saved general purpose */ - uint32_t r13; /* Caller-saved general purpose */ - uint32_t r14; /* Caller-saved general purpose */ - uint32_t r15; /* Caller-saved general purpose */ - uint32_t estatus; - uint32_t instr; /* Instruction being executed when exc occurred */ -}; - -typedef struct __esf z_arch_esf_t; - FUNC_NORETURN void z_SysFatalErrorHandler(unsigned int reason, const z_arch_esf_t *esf); diff --git a/include/zephyr/arch/nios2/exception.h b/include/zephyr/arch/nios2/exception.h new file mode 100644 index 0000000000000..5b781e9114bb4 --- /dev/null +++ b/include/zephyr/arch/nios2/exception.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2016 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_ARCH_NIOS2_EXPCEPTION_H_ +#define ZEPHYR_INCLUDE_ARCH_NIOS2_EXPCEPTION_H_ + +#ifndef _ASMLANGUAGE +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct __esf { + uint32_t ra; /* return address r31 */ + uint32_t r1; /* at */ + uint32_t r2; /* return value */ + uint32_t r3; /* return value */ + uint32_t r4; /* register args */ + uint32_t r5; /* register args */ + uint32_t r6; /* register args */ + uint32_t r7; /* register args */ + uint32_t r8; /* Caller-saved general purpose */ + uint32_t r9; /* Caller-saved general purpose */ + uint32_t r10; /* Caller-saved general purpose */ + uint32_t r11; /* Caller-saved general purpose */ + uint32_t r12; /* Caller-saved general purpose */ + uint32_t r13; /* Caller-saved general purpose */ + uint32_t r14; /* Caller-saved general purpose */ + uint32_t r15; /* Caller-saved general purpose */ + uint32_t estatus; + uint32_t instr; /* Instruction being executed when exc occurred */ +}; + +typedef struct __esf z_arch_esf_t; + +#ifdef __cplusplus +} +#endif + +#endif /* _ASMLANGUAGE */ + +#endif /* ZEPHYR_INCLUDE_ARCH_NIOS2_EXPCEPTION_H_ */ diff --git a/include/zephyr/arch/posix/arch.h b/include/zephyr/arch/posix/arch.h index 83aceb1c14ba1..7dbfb6b386450 100644 --- a/include/zephyr/arch/posix/arch.h +++ b/include/zephyr/arch/posix/arch.h @@ -22,6 +22,7 @@ #include #include +#include #include #include #include /* Each board must define this */ @@ -38,12 +39,6 @@ extern "C" { #define ARCH_STACK_PTR_ALIGN 4 #endif -struct __esf { - uint32_t dummy; /*maybe we will want to add something someday*/ -}; - -typedef struct __esf z_arch_esf_t; - extern uint32_t sys_clock_cycle_get_32(void); static inline uint32_t arch_k_cycle_get_32(void) diff --git a/include/zephyr/arch/posix/exception.h b/include/zephyr/arch/posix/exception.h new file mode 100644 index 0000000000000..2e5e7155bc0a0 --- /dev/null +++ b/include/zephyr/arch/posix/exception.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2010-2014 Wind River Systems, Inc. + * Copyright (c) 2017 Oticon A/S + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_ARCH_POSIX_EXPCEPTION_H_ +#define ZEPHYR_INCLUDE_ARCH_POSIX_EXPCEPTION_H_ + +#ifndef _ASMLANGUAGE +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct __esf { + uint32_t dummy; /*maybe we will want to add something someday*/ +}; + +typedef struct __esf z_arch_esf_t; + +#ifdef __cplusplus +} +#endif + +#endif /* _ASMLANGUAGE */ + +#endif /* ZEPHYR_INCLUDE_ARCH_POSIX_EXPCEPTION_H_ */ diff --git a/include/zephyr/arch/sparc/arch.h b/include/zephyr/arch/sparc/arch.h index df3c40e4ba4a3..c1d87682f39bb 100644 --- a/include/zephyr/arch/sparc/arch.h +++ b/include/zephyr/arch/sparc/arch.h @@ -14,6 +14,7 @@ #ifndef ZEPHYR_INCLUDE_ARCH_SPARC_ARCH_H_ #define ZEPHYR_INCLUDE_ARCH_SPARC_ARCH_H_ +#include #include #include #include @@ -107,19 +108,6 @@ static inline uint64_t arch_k_cycle_get_64(void) return sys_clock_cycle_get_64(); } -struct __esf { - uint32_t out[8]; - uint32_t global[8]; - uint32_t psr; - uint32_t pc; - uint32_t npc; - uint32_t wim; - uint32_t tbr; - uint32_t y; -}; - -typedef struct __esf z_arch_esf_t; - #define ARCH_EXCEPT(reason_p) \ do { \ register uint32_t _g1 __asm__("g1") = reason_p; \ diff --git a/include/zephyr/arch/sparc/exception.h b/include/zephyr/arch/sparc/exception.h new file mode 100644 index 0000000000000..d867d4d5651bc --- /dev/null +++ b/include/zephyr/arch/sparc/exception.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2019-2020 Cobham Gaisler AB + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_ARCH_SPARC_EXPCEPTION_H_ +#define ZEPHYR_INCLUDE_ARCH_SPARC_EXPCEPTION_H_ + +#ifndef _ASMLANGUAGE +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct __esf { + uint32_t out[8]; + uint32_t global[8]; + uint32_t psr; + uint32_t pc; + uint32_t npc; + uint32_t wim; + uint32_t tbr; + uint32_t y; +}; + +typedef struct __esf z_arch_esf_t; + +#ifdef __cplusplus +} +#endif + +#endif /* _ASMLANGUAGE */ + +#endif /* ZEPHYR_INCLUDE_ARCH_SPARC_EXPCEPTION_H_ */ diff --git a/include/zephyr/arch/x86/ia32/arch.h b/include/zephyr/arch/x86/ia32/arch.h index 490dfdb40f334..b82e0db0f1733 100644 --- a/include/zephyr/arch/x86/ia32/arch.h +++ b/include/zephyr/arch/x86/ia32/arch.h @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -333,53 +334,6 @@ static inline void arch_isr_direct_footer(int swap) static inline int name##_body(void) #endif /* !CONFIG_X86_KPTI */ -/** - * @brief Exception Stack Frame - * - * A pointer to an "exception stack frame" (ESF) is passed as an argument - * to exception handlers registered via nanoCpuExcConnect(). As the system - * always operates at ring 0, only the EIP, CS and EFLAGS registers are pushed - * onto the stack when an exception occurs. - * - * The exception stack frame includes the volatile registers (EAX, ECX, and - * EDX) as well as the 5 non-volatile registers (EDI, ESI, EBX, EBP and ESP). - * Those registers are pushed onto the stack by _ExcEnt(). - */ - -typedef struct nanoEsf { -#ifdef CONFIG_GDBSTUB - unsigned int ss; - unsigned int gs; - unsigned int fs; - unsigned int es; - unsigned int ds; -#endif - unsigned int esp; - unsigned int ebp; - unsigned int ebx; - unsigned int esi; - unsigned int edi; - unsigned int edx; - unsigned int eax; - unsigned int ecx; - unsigned int errorCode; - unsigned int eip; - unsigned int cs; - unsigned int eflags; -} z_arch_esf_t; - -extern unsigned int z_x86_exception_vector; - -struct _x86_syscall_stack_frame { - uint32_t eip; - uint32_t cs; - uint32_t eflags; - - /* These are only present if cs = USER_CODE_SEG */ - uint32_t esp; - uint32_t ss; -}; - static ALWAYS_INLINE unsigned int arch_irq_lock(void) { unsigned int key; diff --git a/include/zephyr/arch/x86/ia32/exception.h b/include/zephyr/arch/x86/ia32/exception.h new file mode 100644 index 0000000000000..30fe3bd973f9c --- /dev/null +++ b/include/zephyr/arch/x86/ia32/exception.h @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2010-2014 Wind River Systems, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_ARCH_X86_IA32_EXPCEPTION_H_ +#define ZEPHYR_INCLUDE_ARCH_X86_IA32_EXPCEPTION_H_ + +#ifndef _ASMLANGUAGE +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Exception Stack Frame + * + * A pointer to an "exception stack frame" (ESF) is passed as an argument + * to exception handlers registered via nanoCpuExcConnect(). As the system + * always operates at ring 0, only the EIP, CS and EFLAGS registers are pushed + * onto the stack when an exception occurs. + * + * The exception stack frame includes the volatile registers (EAX, ECX, and + * EDX) as well as the 5 non-volatile registers (EDI, ESI, EBX, EBP and ESP). + * Those registers are pushed onto the stack by _ExcEnt(). + */ + +typedef struct nanoEsf { +#ifdef CONFIG_GDBSTUB + unsigned int ss; + unsigned int gs; + unsigned int fs; + unsigned int es; + unsigned int ds; +#endif + unsigned int esp; + unsigned int ebp; + unsigned int ebx; + unsigned int esi; + unsigned int edi; + unsigned int edx; + unsigned int eax; + unsigned int ecx; + unsigned int errorCode; + unsigned int eip; + unsigned int cs; + unsigned int eflags; +} z_arch_esf_t; + +extern unsigned int z_x86_exception_vector; + +struct _x86_syscall_stack_frame { + uint32_t eip; + uint32_t cs; + uint32_t eflags; + + /* These are only present if cs = USER_CODE_SEG */ + uint32_t esp; + uint32_t ss; +}; + +#ifdef __cplusplus +} +#endif + +#endif /* _ASMLANGUAGE */ + +#endif /* ZEPHYR_INCLUDE_ARCH_X86_IA32_EXPCEPTION_H_ */ diff --git a/include/zephyr/arch/x86/intel64/arch.h b/include/zephyr/arch/x86/intel64/arch.h index c176e4e0bb0ba..86de01297f472 100644 --- a/include/zephyr/arch/x86/intel64/arch.h +++ b/include/zephyr/arch/x86/intel64/arch.h @@ -6,6 +6,7 @@ #ifndef ZEPHYR_INCLUDE_ARCH_X86_INTEL64_ARCH_H_ #define ZEPHYR_INCLUDE_ARCH_X86_INTEL64_ARCH_H_ +#include #include #include #if defined(CONFIG_PCIE) && !defined(_ASMLANGUAGE) @@ -52,61 +53,6 @@ static ALWAYS_INLINE unsigned int arch_irq_lock(void) return (unsigned int) key; } -/* - * the exception stack frame - */ - -struct x86_esf { -#ifdef CONFIG_EXCEPTION_DEBUG - /* callee-saved */ - unsigned long rbx; - unsigned long r12; - unsigned long r13; - unsigned long r14; - unsigned long r15; -#endif /* CONFIG_EXCEPTION_DEBUG */ - unsigned long rbp; - - /* Caller-saved regs */ - unsigned long rax; - unsigned long rcx; - unsigned long rdx; - unsigned long rsi; - unsigned long rdi; - unsigned long r8; - unsigned long r9; - unsigned long r10; - /* Must be aligned 16 bytes from the end of this struct due to - * requirements of 'fxsave (%rsp)' - */ - char fxsave[X86_FXSAVE_SIZE]; - unsigned long r11; - - /* Pushed by CPU or assembly stub */ - unsigned long vector; - unsigned long code; - unsigned long rip; - unsigned long cs; - unsigned long rflags; - unsigned long rsp; - unsigned long ss; -}; - -typedef struct x86_esf z_arch_esf_t; - -struct x86_ssf { - unsigned long rip; - unsigned long rflags; - unsigned long r10; - unsigned long r9; - unsigned long r8; - unsigned long rdx; - unsigned long rsi; - char fxsave[X86_FXSAVE_SIZE]; - unsigned long rdi; - unsigned long rsp; -}; - #define ARCH_EXCEPT(reason_p) do { \ __asm__ volatile( \ "movq %[reason], %%rax\n\t" \ diff --git a/include/zephyr/arch/x86/intel64/exception.h b/include/zephyr/arch/x86/intel64/exception.h new file mode 100644 index 0000000000000..7184d4a9ebba0 --- /dev/null +++ b/include/zephyr/arch/x86/intel64/exception.h @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2019 Intel Corp. + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_ARCH_X86_INTEL64_EXPCEPTION_H_ +#define ZEPHYR_INCLUDE_ARCH_X86_INTEL64_EXPCEPTION_H_ + +#ifndef _ASMLANGUAGE +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * the exception stack frame + */ + +struct x86_esf { +#ifdef CONFIG_EXCEPTION_DEBUG + /* callee-saved */ + unsigned long rbx; + unsigned long r12; + unsigned long r13; + unsigned long r14; + unsigned long r15; +#endif /* CONFIG_EXCEPTION_DEBUG */ + unsigned long rbp; + + /* Caller-saved regs */ + unsigned long rax; + unsigned long rcx; + unsigned long rdx; + unsigned long rsi; + unsigned long rdi; + unsigned long r8; + unsigned long r9; + unsigned long r10; + /* Must be aligned 16 bytes from the end of this struct due to + * requirements of 'fxsave (%rsp)' + */ + char fxsave[X86_FXSAVE_SIZE]; + unsigned long r11; + + /* Pushed by CPU or assembly stub */ + unsigned long vector; + unsigned long code; + unsigned long rip; + unsigned long cs; + unsigned long rflags; + unsigned long rsp; + unsigned long ss; +}; + +typedef struct x86_esf z_arch_esf_t; + +struct x86_ssf { + unsigned long rip; + unsigned long rflags; + unsigned long r10; + unsigned long r9; + unsigned long r8; + unsigned long rdx; + unsigned long rsi; + char fxsave[X86_FXSAVE_SIZE]; + unsigned long rdi; + unsigned long rsp; +}; + +#ifdef __cplusplus +} +#endif + +#endif /* _ASMLANGUAGE */ + +#endif /* ZEPHYR_INCLUDE_ARCH_X86_INTEL64_EXPCEPTION_H_ */ From 31742d0294e16a15debff798fd221192e265ffd0 Mon Sep 17 00:00:00 2001 From: Yong Cong Sin Date: Sat, 1 Jun 2024 00:32:55 +0800 Subject: [PATCH 1699/2849] include: include `exception.h` in `fatal.h` `fatal.h` has 2 functions that use the `z_arch_esf_t` type. Include `exception.h`, which should have the `z_arch_esf_t` defined. Signed-off-by: Yong Cong Sin --- include/zephyr/fatal.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/zephyr/fatal.h b/include/zephyr/fatal.h index be3dd2078c5cd..2333df91112d0 100644 --- a/include/zephyr/fatal.h +++ b/include/zephyr/fatal.h @@ -12,6 +12,7 @@ #define ZEPHYR_INCLUDE_FATAL_H #include +#include #include #include From 3998e18ec463c3542240e62b53270de507bc472a Mon Sep 17 00:00:00 2001 From: Yong Cong Sin Date: Sat, 1 Jun 2024 10:26:04 +0800 Subject: [PATCH 1700/2849] arch: rename all esf struct to `struct arch_esf` Rename every architecture's esf struct to `struct esf`. Signed-off-by: Yong Cong Sin --- arch/arc/include/kernel_arch_data.h | 6 +++--- arch/arm/include/kernel_arch_data.h | 2 +- arch/arm64/core/thread.c | 2 +- arch/arm64/include/kernel_arch_data.h | 2 +- arch/mips/core/thread.c | 6 +++--- arch/riscv/Kconfig | 2 +- arch/riscv/core/thread.c | 6 +++--- include/zephyr/arch/arc/v2/exception.h | 2 +- include/zephyr/arch/arm/cortex_a_r/exception.h | 4 ++-- include/zephyr/arch/arm/cortex_m/exception.h | 4 ++-- include/zephyr/arch/arm64/exception.h | 4 ++-- include/zephyr/arch/mips/exception.h | 4 ++-- include/zephyr/arch/nios2/exception.h | 4 ++-- include/zephyr/arch/posix/exception.h | 4 ++-- include/zephyr/arch/riscv/exception.h | 4 ++-- include/zephyr/arch/sparc/exception.h | 4 ++-- include/zephyr/arch/x86/ia32/exception.h | 2 +- include/zephyr/arch/x86/intel64/exception.h | 4 ++-- include/zephyr/arch/xtensa/exception.h | 3 +++ scripts/coredump/gdbstubs/arch/arm64.py | 2 +- soc/nordic/common/vpr/soc_isr_stacking.h | 4 ++-- subsys/testsuite/ztest/include/zephyr/ztest.h | 4 ++-- tests/arch/arm/arm_interrupt/src/arm_interrupt.c | 2 +- 23 files changed, 42 insertions(+), 39 deletions(-) diff --git a/arch/arc/include/kernel_arch_data.h b/arch/arc/include/kernel_arch_data.h index efe2bd7d1c658..b0dc733446b08 100644 --- a/arch/arc/include/kernel_arch_data.h +++ b/arch/arc/include/kernel_arch_data.h @@ -36,7 +36,7 @@ extern "C" { #endif #ifdef CONFIG_ARC_HAS_SECURE -struct _irq_stack_frame { +struct arch_esf { #ifdef CONFIG_ARC_HAS_ZOL uintptr_t lp_end; uintptr_t lp_start; @@ -72,7 +72,7 @@ struct _irq_stack_frame { uintptr_t status32; }; #else -struct _irq_stack_frame { +struct arch_esf { uintptr_t r0; uintptr_t r1; uintptr_t r2; @@ -108,7 +108,7 @@ struct _irq_stack_frame { }; #endif -typedef struct _irq_stack_frame _isf_t; +typedef struct arch_esf _isf_t; diff --git a/arch/arm/include/kernel_arch_data.h b/arch/arm/include/kernel_arch_data.h index 5ad19db8f84b8..9b4ca04f66c56 100644 --- a/arch/arm/include/kernel_arch_data.h +++ b/arch/arm/include/kernel_arch_data.h @@ -42,7 +42,7 @@ extern "C" { #endif -typedef struct __esf _esf_t; +typedef struct arch_esf _esf_t; typedef struct __basic_sf _basic_sf_t; #if defined(CONFIG_FPU) && defined(CONFIG_FPU_SHARING) typedef struct __fpu_sf _fpu_sf_t; diff --git a/arch/arm64/core/thread.c b/arch/arm64/core/thread.c index a0269501c19ac..667a868602dfc 100644 --- a/arch/arm64/core/thread.c +++ b/arch/arm64/core/thread.c @@ -102,7 +102,7 @@ void arch_new_thread(struct k_thread *thread, k_thread_stack_t *stack, * dropping into EL0. */ - pInitCtx = Z_STACK_PTR_TO_FRAME(struct __esf, stack_ptr); + pInitCtx = Z_STACK_PTR_TO_FRAME(struct arch_esf, stack_ptr); pInitCtx->x0 = (uint64_t)entry; pInitCtx->x1 = (uint64_t)p1; diff --git a/arch/arm64/include/kernel_arch_data.h b/arch/arm64/include/kernel_arch_data.h index ec781fc902dd5..8b607c1dbf47d 100644 --- a/arch/arm64/include/kernel_arch_data.h +++ b/arch/arm64/include/kernel_arch_data.h @@ -36,7 +36,7 @@ extern "C" { #endif -typedef struct __esf _esf_t; +typedef struct arch_esf _esf_t; typedef struct __basic_sf _basic_sf_t; #ifdef __cplusplus diff --git a/arch/mips/core/thread.c b/arch/mips/core/thread.c index e551674d5215d..7966ff462f5fd 100644 --- a/arch/mips/core/thread.c +++ b/arch/mips/core/thread.c @@ -19,11 +19,11 @@ void arch_new_thread(struct k_thread *thread, k_thread_stack_t *stack, char *stack_ptr, k_thread_entry_t entry, void *p1, void *p2, void *p3) { - struct __esf *stack_init; + struct arch_esf *stack_init; /* Initial stack frame for thread */ - stack_init = (struct __esf *)Z_STACK_PTR_ALIGN( - Z_STACK_PTR_TO_FRAME(struct __esf, stack_ptr) + stack_init = (struct arch_esf *)Z_STACK_PTR_ALIGN( + Z_STACK_PTR_TO_FRAME(struct arch_esf, stack_ptr) ); /* Setup the initial stack frame */ diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig index 00121adc7148e..76ea74026ac3d 100644 --- a/arch/riscv/Kconfig +++ b/arch/riscv/Kconfig @@ -88,7 +88,7 @@ config RISCV_SOC_HAS_ISR_STACKING guarded by !_ASMLANGUAGE. The ESF should be defined to account for the hardware stacked registers in the proper order as they are saved on the stack by the hardware, and the registers saved by the - software macros. The structure must be called '__esf'. + software macros. The structure must be called 'struct arch_esf'. config RISCV_SOC_HAS_CUSTOM_IRQ_HANDLING bool diff --git a/arch/riscv/core/thread.c b/arch/riscv/core/thread.c index 38d5dbde092c6..60f73a5f531e4 100644 --- a/arch/riscv/core/thread.c +++ b/arch/riscv/core/thread.c @@ -23,15 +23,15 @@ void arch_new_thread(struct k_thread *thread, k_thread_stack_t *stack, void *p1, void *p2, void *p3) { extern void z_riscv_thread_start(void); - struct __esf *stack_init; + struct arch_esf *stack_init; #ifdef CONFIG_RISCV_SOC_CONTEXT_SAVE const struct soc_esf soc_esf_init = {SOC_ESF_INIT}; #endif /* Initial stack frame for thread */ - stack_init = (struct __esf *)Z_STACK_PTR_ALIGN( - Z_STACK_PTR_TO_FRAME(struct __esf, stack_ptr) + stack_init = (struct arch_esf *)Z_STACK_PTR_ALIGN( + Z_STACK_PTR_TO_FRAME(struct arch_esf, stack_ptr) ); /* Setup the initial stack frame */ diff --git a/include/zephyr/arch/arc/v2/exception.h b/include/zephyr/arch/arc/v2/exception.h index 553024fa3a8c6..8993d7cfe067a 100644 --- a/include/zephyr/arch/arc/v2/exception.h +++ b/include/zephyr/arch/arc/v2/exception.h @@ -20,7 +20,7 @@ extern "C" { #ifdef _ASMLANGUAGE #else -typedef struct _irq_stack_frame z_arch_esf_t; +typedef struct arch_esf z_arch_esf_t; #endif #ifdef __cplusplus diff --git a/include/zephyr/arch/arm/cortex_a_r/exception.h b/include/zephyr/arch/arm/cortex_a_r/exception.h index 3bef647566d3c..2a6bd313e15cd 100644 --- a/include/zephyr/arch/arm/cortex_a_r/exception.h +++ b/include/zephyr/arch/arm/cortex_a_r/exception.h @@ -54,7 +54,7 @@ struct __extra_esf_info { }; #endif /* CONFIG_EXTRA_EXCEPTION_INFO */ -struct __esf { +struct arch_esf { #if defined(CONFIG_EXTRA_EXCEPTION_INFO) struct __extra_esf_info extra_info; #endif @@ -75,7 +75,7 @@ struct __esf { extern uint32_t z_arm_coredump_fault_sp; -typedef struct __esf z_arch_esf_t; +typedef struct arch_esf z_arch_esf_t; extern void z_arm_exc_exit(bool fatal); diff --git a/include/zephyr/arch/arm/cortex_m/exception.h b/include/zephyr/arch/arm/cortex_m/exception.h index a9896cea1e4ed..09ab68575b008 100644 --- a/include/zephyr/arch/arm/cortex_m/exception.h +++ b/include/zephyr/arch/arm/cortex_m/exception.h @@ -98,7 +98,7 @@ struct __extra_esf_info { }; #endif /* CONFIG_EXTRA_EXCEPTION_INFO */ -struct __esf { +struct arch_esf { struct __basic_sf { sys_define_gpr_with_alias(a1, r0); sys_define_gpr_with_alias(a2, r1); @@ -119,7 +119,7 @@ struct __esf { extern uint32_t z_arm_coredump_fault_sp; -typedef struct __esf z_arch_esf_t; +typedef struct arch_esf z_arch_esf_t; extern void z_arm_exc_exit(void); diff --git a/include/zephyr/arch/arm64/exception.h b/include/zephyr/arch/arm64/exception.h index 05257c087feda..d6be6715d5dcd 100644 --- a/include/zephyr/arch/arm64/exception.h +++ b/include/zephyr/arch/arm64/exception.h @@ -24,7 +24,7 @@ extern "C" { #endif -struct __esf { +struct arch_esf { uint64_t x0; uint64_t x1; uint64_t x2; @@ -55,7 +55,7 @@ struct __esf { #endif } __aligned(16); -typedef struct __esf z_arch_esf_t; +typedef struct arch_esf z_arch_esf_t; #ifdef __cplusplus } diff --git a/include/zephyr/arch/mips/exception.h b/include/zephyr/arch/mips/exception.h index d4403f1d5995e..40e9ac0506f50 100644 --- a/include/zephyr/arch/mips/exception.h +++ b/include/zephyr/arch/mips/exception.h @@ -17,7 +17,7 @@ extern "C" { #endif -struct __esf { +struct arch_esf { unsigned long ra; /* return address */ unsigned long gp; /* global pointer */ @@ -50,7 +50,7 @@ struct __esf { unsigned long cause; }; -typedef struct __esf z_arch_esf_t; +typedef struct arch_esf z_arch_esf_t; #ifdef __cplusplus } diff --git a/include/zephyr/arch/nios2/exception.h b/include/zephyr/arch/nios2/exception.h index 5b781e9114bb4..af13754baa605 100644 --- a/include/zephyr/arch/nios2/exception.h +++ b/include/zephyr/arch/nios2/exception.h @@ -14,7 +14,7 @@ extern "C" { #endif -struct __esf { +struct arch_esf { uint32_t ra; /* return address r31 */ uint32_t r1; /* at */ uint32_t r2; /* return value */ @@ -35,7 +35,7 @@ struct __esf { uint32_t instr; /* Instruction being executed when exc occurred */ }; -typedef struct __esf z_arch_esf_t; +typedef struct arch_esf z_arch_esf_t; #ifdef __cplusplus } diff --git a/include/zephyr/arch/posix/exception.h b/include/zephyr/arch/posix/exception.h index 2e5e7155bc0a0..d267d87363c6c 100644 --- a/include/zephyr/arch/posix/exception.h +++ b/include/zephyr/arch/posix/exception.h @@ -15,11 +15,11 @@ extern "C" { #endif -struct __esf { +struct arch_esf { uint32_t dummy; /*maybe we will want to add something someday*/ }; -typedef struct __esf z_arch_esf_t; +typedef struct arch_esf z_arch_esf_t; #ifdef __cplusplus } diff --git a/include/zephyr/arch/riscv/exception.h b/include/zephyr/arch/riscv/exception.h index 644df2cd1fbf9..05d5bac02c2dd 100644 --- a/include/zephyr/arch/riscv/exception.h +++ b/include/zephyr/arch/riscv/exception.h @@ -48,7 +48,7 @@ struct soc_esf { #if defined(CONFIG_RISCV_SOC_HAS_ISR_STACKING) SOC_ISR_STACKING_ESF_DECLARE; #else -struct __esf { +struct arch_esf { unsigned long ra; /* return address */ unsigned long t0; /* Caller-saved temporary register */ @@ -87,7 +87,7 @@ struct __esf { } __aligned(16); #endif /* CONFIG_RISCV_SOC_HAS_ISR_STACKING */ -typedef struct __esf z_arch_esf_t; +typedef struct arch_esf z_arch_esf_t; #ifdef CONFIG_RISCV_SOC_CONTEXT_SAVE typedef struct soc_esf soc_esf_t; #endif diff --git a/include/zephyr/arch/sparc/exception.h b/include/zephyr/arch/sparc/exception.h index d867d4d5651bc..597d1f94df738 100644 --- a/include/zephyr/arch/sparc/exception.h +++ b/include/zephyr/arch/sparc/exception.h @@ -14,7 +14,7 @@ extern "C" { #endif -struct __esf { +struct arch_esf { uint32_t out[8]; uint32_t global[8]; uint32_t psr; @@ -25,7 +25,7 @@ struct __esf { uint32_t y; }; -typedef struct __esf z_arch_esf_t; +typedef struct arch_esf z_arch_esf_t; #ifdef __cplusplus } diff --git a/include/zephyr/arch/x86/ia32/exception.h b/include/zephyr/arch/x86/ia32/exception.h index 30fe3bd973f9c..929c65428b220 100644 --- a/include/zephyr/arch/x86/ia32/exception.h +++ b/include/zephyr/arch/x86/ia32/exception.h @@ -27,7 +27,7 @@ extern "C" { * Those registers are pushed onto the stack by _ExcEnt(). */ -typedef struct nanoEsf { +typedef struct arch_esf { #ifdef CONFIG_GDBSTUB unsigned int ss; unsigned int gs; diff --git a/include/zephyr/arch/x86/intel64/exception.h b/include/zephyr/arch/x86/intel64/exception.h index 7184d4a9ebba0..eb6690eca5712 100644 --- a/include/zephyr/arch/x86/intel64/exception.h +++ b/include/zephyr/arch/x86/intel64/exception.h @@ -17,7 +17,7 @@ extern "C" { * the exception stack frame */ -struct x86_esf { +struct arch_esf { #ifdef CONFIG_EXCEPTION_DEBUG /* callee-saved */ unsigned long rbx; @@ -53,7 +53,7 @@ struct x86_esf { unsigned long ss; }; -typedef struct x86_esf z_arch_esf_t; +typedef struct arch_esf z_arch_esf_t; struct x86_ssf { unsigned long rip; diff --git a/include/zephyr/arch/xtensa/exception.h b/include/zephyr/arch/xtensa/exception.h index 51a5d5aef9036..94cb4ce5bb2cc 100644 --- a/include/zephyr/arch/xtensa/exception.h +++ b/include/zephyr/arch/xtensa/exception.h @@ -25,6 +25,9 @@ extern "C" { * register windows are in use. This isn't a struct type, it just * matches the register/stack-unit width. */ +struct arch_esf { + int dummy; +}; typedef int z_arch_esf_t; #endif diff --git a/scripts/coredump/gdbstubs/arch/arm64.py b/scripts/coredump/gdbstubs/arch/arm64.py index 008fb88c1b963..7f4c03eb375ea 100644 --- a/scripts/coredump/gdbstubs/arch/arm64.py +++ b/scripts/coredump/gdbstubs/arch/arm64.py @@ -95,7 +95,7 @@ def parse_arch_data_block(self): self.registers[RegNum.X17] = tu[17] self.registers[RegNum.X18] = tu[18] - # Callee saved registers are not provided in __esf structure + # Callee saved registers are not provided in arch_esf structure # So they will be omitted (set to undefined) when stub generates the # packet in handle_register_group_read_packet. diff --git a/soc/nordic/common/vpr/soc_isr_stacking.h b/soc/nordic/common/vpr/soc_isr_stacking.h index ff34f9d4e09a6..da4dffc4b8cb1 100644 --- a/soc/nordic/common/vpr/soc_isr_stacking.h +++ b/soc/nordic/common/vpr/soc_isr_stacking.h @@ -17,7 +17,7 @@ #if DT_PROP(VPR_CPU, nordic_bus_width) == 64 #define SOC_ISR_STACKING_ESF_DECLARE \ - struct __esf { \ + struct arch_esf { \ unsigned long s0; \ unsigned long mstatus; \ unsigned long tp; \ @@ -40,7 +40,7 @@ #else /* DT_PROP(VPR_CPU, nordic_bus_width) == 32 */ #define SOC_ISR_STACKING_ESF_DECLARE \ - struct __esf { \ + struct arch_esf { \ unsigned long s0; \ unsigned long mstatus; \ unsigned long tp; \ diff --git a/subsys/testsuite/ztest/include/zephyr/ztest.h b/subsys/testsuite/ztest/include/zephyr/ztest.h index 52d686756c64e..5dba0afa3367b 100644 --- a/subsys/testsuite/ztest/include/zephyr/ztest.h +++ b/subsys/testsuite/ztest/include/zephyr/ztest.h @@ -28,8 +28,8 @@ #ifdef __cplusplus extern "C" { #endif -struct esf; -typedef struct esf z_arch_esf_t; +struct arch_esf; +typedef struct arch_esf z_arch_esf_t; #ifdef __cplusplus } #endif diff --git a/tests/arch/arm/arm_interrupt/src/arm_interrupt.c b/tests/arch/arm/arm_interrupt/src/arm_interrupt.c index b569bbe1678a3..5494d77d70db3 100644 --- a/tests/arch/arm/arm_interrupt/src/arm_interrupt.c +++ b/tests/arch/arm/arm_interrupt/src/arm_interrupt.c @@ -74,7 +74,7 @@ static int check_esf_matches_expectations(const z_arch_esf_t *pEsf) * is overwritten in fault.c) */ if (memcmp((void *)callee_regs->psp, pEsf, - offsetof(struct __esf, basic.xpsr)) != 0) { + offsetof(struct arch_esf, basic.xpsr)) != 0) { printk("psp does not match __basic_sf provided\n"); return -1; } From e54b27b9671447f7a74d6221fc753c6bd22f8f94 Mon Sep 17 00:00:00 2001 From: Yong Cong Sin Date: Sat, 1 Jun 2024 00:07:14 +0800 Subject: [PATCH 1701/2849] arch: define `struct arch_esf` and deprecate `z_arch_esf_t` Make `struct arch_esf` compulsory for all architectures by declaring it in the `arch_interface.h` header. After this commit, the named struct `z_arch_esf_t` is only used internally to generate offsets, and is slated to be removed from the `arch_interface.h` header in the future. Signed-off-by: Yong Cong Sin --- arch/arc/core/fatal.c | 4 +- arch/arc/core/fault.c | 2 +- arch/arc/include/kernel_arch_func.h | 2 +- arch/arm/core/cortex_a_r/fault.c | 8 +-- arch/arm/core/cortex_a_r/irq_manage.c | 2 +- arch/arm/core/cortex_m/coredump.c | 2 +- arch/arm/core/cortex_m/fault.c | 58 +++++++++---------- arch/arm/core/cortex_m/irq_manage.c | 2 +- arch/arm/core/fatal.c | 12 ++-- arch/arm/core/gdbstub.c | 2 +- arch/arm/include/cortex_a_r/exception.h | 4 +- .../arm/include/cortex_a_r/kernel_arch_func.h | 2 +- arch/arm/include/cortex_m/exception.h | 4 +- arch/arm/include/cortex_m/kernel_arch_func.h | 2 +- arch/arm64/core/coredump.c | 6 +- arch/arm64/core/fatal.c | 12 ++-- arch/arm64/core/fpu.c | 4 +- arch/arm64/core/irq_manage.c | 2 +- arch/arm64/core/thread.c | 2 +- arch/arm64/include/kernel_arch_func.h | 2 +- arch/mips/core/fatal.c | 4 +- arch/mips/include/kernel_arch_func.h | 2 +- arch/nios2/core/fatal.c | 4 +- arch/nios2/include/kernel_arch_func.h | 2 +- arch/riscv/core/coredump.c | 2 +- arch/riscv/core/fatal.c | 18 +++--- arch/riscv/core/fpu.c | 4 +- arch/riscv/core/stacktrace.c | 8 +-- arch/riscv/include/kernel_arch_func.h | 4 +- arch/sparc/core/fatal.c | 12 ++-- arch/sparc/include/kernel_arch_func.h | 2 +- arch/x86/core/fatal.c | 22 +++---- arch/x86/core/ia32/coredump.c | 2 +- arch/x86/core/ia32/fatal.c | 16 ++--- arch/x86/core/ia32/float.c | 2 +- arch/x86/core/ia32/gdbstub.c | 6 +- arch/x86/core/intel64/coredump.c | 2 +- arch/x86/core/intel64/fatal.c | 4 +- arch/x86/core/offsets/ia32_offsets.c | 1 - arch/x86/include/ia32/exception.h | 4 +- arch/x86/include/intel64/kernel_arch_func.h | 2 +- arch/x86/include/kernel_arch_func.h | 8 +-- arch/xtensa/core/coredump.c | 2 +- arch/xtensa/core/fatal.c | 2 +- arch/xtensa/core/gdbstub.c | 6 +- arch/xtensa/core/vector_handlers.c | 7 ++- arch/xtensa/include/xtensa_internal.h | 4 +- drivers/edac/edac_ibecc.c | 2 +- include/zephyr/arch/arc/v2/exception.h | 5 -- include/zephyr/arch/arch_interface.h | 3 + .../zephyr/arch/arm/cortex_a_r/exception.h | 2 - include/zephyr/arch/arm/cortex_m/exception.h | 2 - include/zephyr/arch/arm/gdbstub.h | 2 +- include/zephyr/arch/arm64/exception.h | 2 - include/zephyr/arch/mips/exception.h | 2 - include/zephyr/arch/nios2/arch.h | 4 +- include/zephyr/arch/nios2/exception.h | 2 - include/zephyr/arch/posix/exception.h | 2 - include/zephyr/arch/riscv/arch.h | 4 +- include/zephyr/arch/riscv/exception.h | 1 - include/zephyr/arch/sparc/exception.h | 2 - include/zephyr/arch/x86/ia32/exception.h | 4 +- include/zephyr/arch/x86/intel64/exception.h | 2 - include/zephyr/arch/xtensa/exception.h | 1 - include/zephyr/bluetooth/hci_vs.h | 2 +- include/zephyr/debug/coredump.h | 6 +- include/zephyr/fatal.h | 4 +- kernel/fatal.c | 4 +- kernel/include/gen_offset.h | 2 + kernel/include/kernel_arch_interface.h | 2 +- samples/bluetooth/hci_ipc/src/main.c | 2 +- samples/subsys/llext/edk/app/src/main.c | 2 +- subsys/bluetooth/controller/hci/hci.c | 4 +- subsys/debug/coredump/coredump_core.c | 2 +- subsys/testsuite/ztest/include/zephyr/ztest.h | 1 - .../ztest/include/zephyr/ztest_error_hook.h | 2 +- subsys/testsuite/ztest/src/ztest_error_hook.c | 4 +- .../src/arm_hardfault.c | 2 +- .../arm/arm_interrupt/src/arm_interrupt.c | 4 +- .../arch/arm/arm_no_multithreading/src/main.c | 2 +- tests/arch/x86/nmi/src/main.c | 2 +- tests/arch/x86/static_idt/src/main.c | 4 +- tests/bluetooth/audio/mocks/src/fatal.c | 2 +- .../drivers/coredump/coredump_api/src/main.c | 2 +- tests/kernel/fatal/exception/src/main.c | 2 +- tests/kernel/fatal/message_capture/src/main.c | 2 +- .../kernel/fatal/no-multithreading/src/main.c | 2 +- .../mem_protect/demand_paging/src/main.c | 2 +- tests/kernel/mem_protect/mem_map/src/main.c | 2 +- .../mem_protect/mem_protect/src/common.c | 2 +- .../kernel/mem_protect/protection/src/main.c | 2 +- tests/kernel/mem_protect/stackprot/src/main.c | 2 +- tests/kernel/mem_protect/sys_sem/src/main.c | 2 +- tests/kernel/mem_protect/syscalls/src/main.c | 2 +- tests/kernel/mem_protect/userspace/src/main.c | 2 +- .../mutex_error_case/src/test_mutex_error.c | 2 +- tests/kernel/pipe/pipe/src/test_pipe.c | 2 +- tests/kernel/smp/src/main.c | 2 +- .../kernel/threads/dynamic_thread/src/main.c | 2 +- .../threads/dynamic_thread_stack/src/main.c | 2 +- .../thread_apis/src/test_essential_thread.c | 2 +- tests/lib/mem_blocks/src/main.c | 2 +- tests/subsys/debug/coredump/src/main.c | 2 +- .../subsys/debug/coredump_backends/src/main.c | 2 +- tests/ztest/error_hook/src/main.c | 2 +- 105 files changed, 203 insertions(+), 222 deletions(-) diff --git a/arch/arc/core/fatal.c b/arch/arc/core/fatal.c index f193c0b09f1f2..512d1cc442c6f 100644 --- a/arch/arc/core/fatal.c +++ b/arch/arc/core/fatal.c @@ -23,7 +23,7 @@ LOG_MODULE_DECLARE(os, CONFIG_KERNEL_LOG_LEVEL); #ifdef CONFIG_EXCEPTION_DEBUG -static void dump_arc_esf(const z_arch_esf_t *esf) +static void dump_arc_esf(const struct arch_esf *esf) { ARC_EXCEPTION_DUMP(" r0: 0x%" PRIxPTR " r1: 0x%" PRIxPTR " r2: 0x%" PRIxPTR " r3: 0x%" PRIxPTR "", esf->r0, esf->r1, esf->r2, esf->r3); @@ -42,7 +42,7 @@ static void dump_arc_esf(const z_arch_esf_t *esf) } #endif -void z_arc_fatal_error(unsigned int reason, const z_arch_esf_t *esf) +void z_arc_fatal_error(unsigned int reason, const struct arch_esf *esf) { #ifdef CONFIG_EXCEPTION_DEBUG if (esf != NULL) { diff --git a/arch/arc/core/fault.c b/arch/arc/core/fault.c index 763ed7a2c737a..6f9da3cd1e0e9 100644 --- a/arch/arc/core/fault.c +++ b/arch/arc/core/fault.c @@ -346,7 +346,7 @@ static void dump_exception_info(uint32_t vector, uint32_t cause, uint32_t parame * invokes the user provided routine k_sys_fatal_error_handler() which is * responsible for implementing the error handling policy. */ -void _Fault(z_arch_esf_t *esf, uint32_t old_sp) +void _Fault(struct arch_esf *esf, uint32_t old_sp) { uint32_t vector, cause, parameter; uint32_t exc_addr = z_arc_v2_aux_reg_read(_ARC_V2_EFA); diff --git a/arch/arc/include/kernel_arch_func.h b/arch/arc/include/kernel_arch_func.h index 1c46423cb4f03..65a497e02d078 100644 --- a/arch/arc/include/kernel_arch_func.h +++ b/arch/arc/include/kernel_arch_func.h @@ -62,7 +62,7 @@ extern void z_arc_userspace_enter(k_thread_entry_t user_entry, void *p1, void *p2, void *p3, uint32_t stack, uint32_t size, struct k_thread *thread); -extern void z_arc_fatal_error(unsigned int reason, const z_arch_esf_t *esf); +extern void z_arc_fatal_error(unsigned int reason, const struct arch_esf *esf); extern void arch_sched_ipi(void); diff --git a/arch/arm/core/cortex_a_r/fault.c b/arch/arm/core/cortex_a_r/fault.c index a39efeb96e027..d792fc57da8de 100644 --- a/arch/arm/core/cortex_a_r/fault.c +++ b/arch/arm/core/cortex_a_r/fault.c @@ -206,7 +206,7 @@ bool z_arm_fault_undef_instruction_fp(void) * * @return Returns true if the fault is fatal */ -bool z_arm_fault_undef_instruction(z_arch_esf_t *esf) +bool z_arm_fault_undef_instruction(struct arch_esf *esf) { #if defined(CONFIG_FPU_SHARING) /* @@ -243,7 +243,7 @@ bool z_arm_fault_undef_instruction(z_arch_esf_t *esf) * * @return Returns true if the fault is fatal */ -bool z_arm_fault_prefetch(z_arch_esf_t *esf) +bool z_arm_fault_prefetch(struct arch_esf *esf) { uint32_t reason = K_ERR_CPU_EXCEPTION; @@ -299,7 +299,7 @@ static const struct z_exc_handle exceptions[] = { * * @return true if error is recoverable, otherwise return false. */ -static bool memory_fault_recoverable(z_arch_esf_t *esf) +static bool memory_fault_recoverable(struct arch_esf *esf) { for (int i = 0; i < ARRAY_SIZE(exceptions); i++) { /* Mask out instruction mode */ @@ -321,7 +321,7 @@ static bool memory_fault_recoverable(z_arch_esf_t *esf) * * @return Returns true if the fault is fatal */ -bool z_arm_fault_data(z_arch_esf_t *esf) +bool z_arm_fault_data(struct arch_esf *esf) { uint32_t reason = K_ERR_CPU_EXCEPTION; diff --git a/arch/arm/core/cortex_a_r/irq_manage.c b/arch/arm/core/cortex_a_r/irq_manage.c index 1dca75e297ab0..48c9ede3327bb 100644 --- a/arch/arm/core/cortex_a_r/irq_manage.c +++ b/arch/arm/core/cortex_a_r/irq_manage.c @@ -71,7 +71,7 @@ void z_arm_irq_priority_set(unsigned int irq, unsigned int prio, uint32_t flags) } #endif /* !CONFIG_ARM_CUSTOM_INTERRUPT_CONTROLLER */ -void z_arm_fatal_error(unsigned int reason, const z_arch_esf_t *esf); +void z_arm_fatal_error(unsigned int reason, const struct arch_esf *esf); /** * diff --git a/arch/arm/core/cortex_m/coredump.c b/arch/arm/core/cortex_m/coredump.c index 2b4a86a1bb9b2..c688c91d9819d 100644 --- a/arch/arm/core/cortex_m/coredump.c +++ b/arch/arm/core/cortex_m/coredump.c @@ -41,7 +41,7 @@ struct arm_arch_block { */ static struct arm_arch_block arch_blk; -void arch_coredump_info_dump(const z_arch_esf_t *esf) +void arch_coredump_info_dump(const struct arch_esf *esf) { struct coredump_arch_hdr_t hdr = { .id = COREDUMP_ARCH_HDR_ID, diff --git a/arch/arm/core/cortex_m/fault.c b/arch/arm/core/cortex_m/fault.c index 5090381fa317d..78b87092976f6 100644 --- a/arch/arm/core/cortex_m/fault.c +++ b/arch/arm/core/cortex_m/fault.c @@ -146,7 +146,7 @@ LOG_MODULE_DECLARE(os, CONFIG_KERNEL_LOG_LEVEL); */ #if (CONFIG_FAULT_DUMP == 1) -static void fault_show(const z_arch_esf_t *esf, int fault) +static void fault_show(const struct arch_esf *esf, int fault) { PR_EXC("Fault! EXC #%d", fault); @@ -165,7 +165,7 @@ static void fault_show(const z_arch_esf_t *esf, int fault) * * For Dump level 0, no information needs to be generated. */ -static void fault_show(const z_arch_esf_t *esf, int fault) +static void fault_show(const struct arch_esf *esf, int fault) { (void)esf; (void)fault; @@ -185,7 +185,7 @@ static const struct z_exc_handle exceptions[] = { * * @return true if error is recoverable, otherwise return false. */ -static bool memory_fault_recoverable(z_arch_esf_t *esf, bool synchronous) +static bool memory_fault_recoverable(struct arch_esf *esf, bool synchronous) { #ifdef CONFIG_USERSPACE for (int i = 0; i < ARRAY_SIZE(exceptions); i++) { @@ -228,7 +228,7 @@ uint32_t z_check_thread_stack_fail(const uint32_t fault_addr, * * @return error code to identify the fatal error reason */ -static uint32_t mem_manage_fault(z_arch_esf_t *esf, int from_hard_fault, +static uint32_t mem_manage_fault(struct arch_esf *esf, int from_hard_fault, bool *recoverable) { uint32_t reason = K_ERR_ARM_MEM_GENERIC; @@ -387,7 +387,7 @@ static uint32_t mem_manage_fault(z_arch_esf_t *esf, int from_hard_fault, * @return error code to identify the fatal error reason. * */ -static int bus_fault(z_arch_esf_t *esf, int from_hard_fault, bool *recoverable) +static int bus_fault(struct arch_esf *esf, int from_hard_fault, bool *recoverable) { uint32_t reason = K_ERR_ARM_BUS_GENERIC; @@ -549,7 +549,7 @@ static int bus_fault(z_arch_esf_t *esf, int from_hard_fault, bool *recoverable) * * @return error code to identify the fatal error reason */ -static uint32_t usage_fault(const z_arch_esf_t *esf) +static uint32_t usage_fault(const struct arch_esf *esf) { uint32_t reason = K_ERR_ARM_USAGE_GENERIC; @@ -612,7 +612,7 @@ static uint32_t usage_fault(const z_arch_esf_t *esf) * * @return error code to identify the fatal error reason */ -static uint32_t secure_fault(const z_arch_esf_t *esf) +static uint32_t secure_fault(const struct arch_esf *esf) { uint32_t reason = K_ERR_ARM_SECURE_GENERIC; @@ -661,7 +661,7 @@ static uint32_t secure_fault(const z_arch_esf_t *esf) * See z_arm_fault_dump() for example. * */ -static void debug_monitor(z_arch_esf_t *esf, bool *recoverable) +static void debug_monitor(struct arch_esf *esf, bool *recoverable) { *recoverable = false; @@ -687,7 +687,7 @@ static void debug_monitor(z_arch_esf_t *esf, bool *recoverable) #error Unknown ARM architecture #endif /* CONFIG_ARMV6_M_ARMV8_M_BASELINE */ -static inline bool z_arm_is_synchronous_svc(z_arch_esf_t *esf) +static inline bool z_arm_is_synchronous_svc(struct arch_esf *esf) { uint16_t *ret_addr = (uint16_t *)esf->basic.pc; /* SVC is a 16-bit instruction. On a synchronous SVC @@ -762,7 +762,7 @@ static inline bool z_arm_is_pc_valid(uintptr_t pc) * * @return error code to identify the fatal error reason */ -static uint32_t hard_fault(z_arch_esf_t *esf, bool *recoverable) +static uint32_t hard_fault(struct arch_esf *esf, bool *recoverable) { uint32_t reason = K_ERR_CPU_EXCEPTION; @@ -829,7 +829,7 @@ static uint32_t hard_fault(z_arch_esf_t *esf, bool *recoverable) * See z_arm_fault_dump() for example. * */ -static void reserved_exception(const z_arch_esf_t *esf, int fault) +static void reserved_exception(const struct arch_esf *esf, int fault) { ARG_UNUSED(esf); @@ -839,7 +839,7 @@ static void reserved_exception(const z_arch_esf_t *esf, int fault) } /* Handler function for ARM fault conditions. */ -static uint32_t fault_handle(z_arch_esf_t *esf, int fault, bool *recoverable) +static uint32_t fault_handle(struct arch_esf *esf, int fault, bool *recoverable) { uint32_t reason = K_ERR_CPU_EXCEPTION; @@ -893,7 +893,7 @@ static uint32_t fault_handle(z_arch_esf_t *esf, int fault, bool *recoverable) * * @param secure_esf Pointer to the secure stack frame. */ -static void secure_stack_dump(const z_arch_esf_t *secure_esf) +static void secure_stack_dump(const struct arch_esf *secure_esf) { /* * In case a Non-Secure exception interrupted the Secure @@ -918,7 +918,7 @@ static void secure_stack_dump(const z_arch_esf_t *secure_esf) * Non-Secure exception entry. */ top_of_sec_stack += ADDITIONAL_STATE_CONTEXT_WORDS; - secure_esf = (const z_arch_esf_t *)top_of_sec_stack; + secure_esf = (const struct arch_esf *)top_of_sec_stack; sec_ret_addr = secure_esf->basic.pc; } else { /* Exception during Non-Secure function call. @@ -947,11 +947,11 @@ static void secure_stack_dump(const z_arch_esf_t *secure_esf) * * @return ESF pointer on success, otherwise return NULL */ -static inline z_arch_esf_t *get_esf(uint32_t msp, uint32_t psp, uint32_t exc_return, +static inline struct arch_esf *get_esf(uint32_t msp, uint32_t psp, uint32_t exc_return, bool *nested_exc) { bool alternative_state_exc = false; - z_arch_esf_t *ptr_esf = NULL; + struct arch_esf *ptr_esf = NULL; *nested_exc = false; @@ -979,14 +979,14 @@ static inline z_arch_esf_t *get_esf(uint32_t msp, uint32_t psp, uint32_t exc_ret alternative_state_exc = true; /* Dump the Secure stack before handling the actual fault. */ - z_arch_esf_t *secure_esf; + struct arch_esf *secure_esf; if (exc_return & EXC_RETURN_SPSEL_PROCESS) { /* Secure stack pointed by PSP */ - secure_esf = (z_arch_esf_t *)psp; + secure_esf = (struct arch_esf *)psp; } else { /* Secure stack pointed by MSP */ - secure_esf = (z_arch_esf_t *)msp; + secure_esf = (struct arch_esf *)msp; *nested_exc = true; } @@ -997,9 +997,9 @@ static inline z_arch_esf_t *get_esf(uint32_t msp, uint32_t psp, uint32_t exc_ret * and supply it to the fault handing function. */ if (exc_return & EXC_RETURN_MODE_THREAD) { - ptr_esf = (z_arch_esf_t *)__TZ_get_PSP_NS(); + ptr_esf = (struct arch_esf *)__TZ_get_PSP_NS(); } else { - ptr_esf = (z_arch_esf_t *)__TZ_get_MSP_NS(); + ptr_esf = (struct arch_esf *)__TZ_get_MSP_NS(); } } #elif defined(CONFIG_ARM_NONSECURE_FIRMWARE) @@ -1024,10 +1024,10 @@ static inline z_arch_esf_t *get_esf(uint32_t msp, uint32_t psp, uint32_t exc_ret if (exc_return & EXC_RETURN_SPSEL_PROCESS) { /* Non-Secure stack frame on PSP */ - ptr_esf = (z_arch_esf_t *)psp; + ptr_esf = (struct arch_esf *)psp; } else { /* Non-Secure stack frame on MSP */ - ptr_esf = (z_arch_esf_t *)msp; + ptr_esf = (struct arch_esf *)msp; } } else { /* Exception entry occurred in Non-Secure stack. */ @@ -1046,11 +1046,11 @@ static inline z_arch_esf_t *get_esf(uint32_t msp, uint32_t psp, uint32_t exc_ret if (!alternative_state_exc) { if (exc_return & EXC_RETURN_MODE_THREAD) { /* Returning to thread mode */ - ptr_esf = (z_arch_esf_t *)psp; + ptr_esf = (struct arch_esf *)psp; } else { /* Returning to handler mode */ - ptr_esf = (z_arch_esf_t *)msp; + ptr_esf = (struct arch_esf *)msp; *nested_exc = true; } } @@ -1095,12 +1095,12 @@ void z_arm_fault(uint32_t msp, uint32_t psp, uint32_t exc_return, uint32_t reason = K_ERR_CPU_EXCEPTION; int fault = SCB->ICSR & SCB_ICSR_VECTACTIVE_Msk; bool recoverable, nested_exc; - z_arch_esf_t *esf; + struct arch_esf *esf; /* Create a stack-ed copy of the ESF to be used during * the fault handling process. */ - z_arch_esf_t esf_copy; + struct arch_esf esf_copy; /* Force unlock interrupts */ arch_irq_unlock(0); @@ -1123,13 +1123,13 @@ void z_arm_fault(uint32_t msp, uint32_t psp, uint32_t exc_return, /* Copy ESF */ #if !defined(CONFIG_EXTRA_EXCEPTION_INFO) - memcpy(&esf_copy, esf, sizeof(z_arch_esf_t)); + memcpy(&esf_copy, esf, sizeof(struct arch_esf)); ARG_UNUSED(callee_regs); #else /* the extra exception info is not present in the original esf * so we only copy the fields before those. */ - memcpy(&esf_copy, esf, offsetof(z_arch_esf_t, extra_info)); + memcpy(&esf_copy, esf, offsetof(struct arch_esf, extra_info)); esf_copy.extra_info = (struct __extra_esf_info) { .callee = callee_regs, .exc_return = exc_return, diff --git a/arch/arm/core/cortex_m/irq_manage.c b/arch/arm/core/cortex_m/irq_manage.c index b72332b32e81a..f2030ec4ab020 100644 --- a/arch/arm/core/cortex_m/irq_manage.c +++ b/arch/arm/core/cortex_m/irq_manage.c @@ -94,7 +94,7 @@ void z_arm_irq_priority_set(unsigned int irq, unsigned int prio, uint32_t flags) #endif /* !defined(CONFIG_ARM_CUSTOM_INTERRUPT_CONTROLLER) */ -void z_arm_fatal_error(unsigned int reason, const z_arch_esf_t *esf); +void z_arm_fatal_error(unsigned int reason, const struct arch_esf *esf); /** * diff --git a/arch/arm/core/fatal.c b/arch/arm/core/fatal.c index 4364d48d45d57..4532e238f05c9 100644 --- a/arch/arm/core/fatal.c +++ b/arch/arm/core/fatal.c @@ -18,7 +18,7 @@ LOG_MODULE_DECLARE(os, CONFIG_KERNEL_LOG_LEVEL); #ifdef CONFIG_EXCEPTION_DEBUG -static void esf_dump(const z_arch_esf_t *esf) +static void esf_dump(const struct arch_esf *esf) { LOG_ERR("r0/a1: 0x%08x r1/a2: 0x%08x r2/a3: 0x%08x", esf->basic.a1, esf->basic.a2, esf->basic.a3); @@ -66,7 +66,7 @@ static void esf_dump(const z_arch_esf_t *esf) } #endif /* CONFIG_EXCEPTION_DEBUG */ -void z_arm_fatal_error(unsigned int reason, const z_arch_esf_t *esf) +void z_arm_fatal_error(unsigned int reason, const struct arch_esf *esf) { #ifdef CONFIG_EXCEPTION_DEBUG if (esf != NULL) { @@ -102,7 +102,7 @@ void z_arm_fatal_error(unsigned int reason, const z_arch_esf_t *esf) * @param esf exception frame * @param callee_regs Callee-saved registers (R4-R11) */ -void z_do_kernel_oops(const z_arch_esf_t *esf, _callee_saved_t *callee_regs) +void z_do_kernel_oops(const struct arch_esf *esf, _callee_saved_t *callee_regs) { #if !(defined(CONFIG_EXTRA_EXCEPTION_INFO) && defined(CONFIG_ARMV7_M_ARMV8_M_MAINLINE)) ARG_UNUSED(callee_regs); @@ -130,9 +130,9 @@ void z_do_kernel_oops(const z_arch_esf_t *esf, _callee_saved_t *callee_regs) #if !defined(CONFIG_EXTRA_EXCEPTION_INFO) z_arm_fatal_error(reason, esf); #else - z_arch_esf_t esf_copy; + struct arch_esf esf_copy; - memcpy(&esf_copy, esf, offsetof(z_arch_esf_t, extra_info)); + memcpy(&esf_copy, esf, offsetof(struct arch_esf, extra_info)); #if defined(CONFIG_ARMV7_M_ARMV8_M_MAINLINE) /* extra exception info is collected in callee_reg param * on CONFIG_ARMV7_M_ARMV8_M_MAINLINE @@ -156,7 +156,7 @@ void z_do_kernel_oops(const z_arch_esf_t *esf, _callee_saved_t *callee_regs) FUNC_NORETURN void arch_syscall_oops(void *ssf_ptr) { uint32_t *ssf_contents = ssf_ptr; - z_arch_esf_t oops_esf = { 0 }; + struct arch_esf oops_esf = { 0 }; /* TODO: Copy the rest of the register set out of ssf_ptr */ oops_esf.basic.pc = ssf_contents[3]; diff --git a/arch/arm/core/gdbstub.c b/arch/arm/core/gdbstub.c index 5386cfa619f1a..60d16b78c319c 100644 --- a/arch/arm/core/gdbstub.c +++ b/arch/arm/core/gdbstub.c @@ -42,7 +42,7 @@ static int is_bkpt(unsigned int exc_cause) } /* Wrapper function to save and restore execution c */ -void z_gdb_entry(z_arch_esf_t *esf, unsigned int exc_cause) +void z_gdb_entry(struct arch_esf *esf, unsigned int exc_cause) { /* Disable the hardware breakpoint in case it was set */ __asm__ volatile("mcr p14, 0, %0, c0, c0, 5" ::"r"(0x0) :); diff --git a/arch/arm/include/cortex_a_r/exception.h b/arch/arm/include/cortex_a_r/exception.h index 7519016176c5e..6daa9c106ee2b 100644 --- a/arch/arm/include/cortex_a_r/exception.h +++ b/arch/arm/include/cortex_a_r/exception.h @@ -38,7 +38,7 @@ static ALWAYS_INLINE bool arch_is_in_isr(void) return (arch_curr_cpu()->nested != 0U); } -static ALWAYS_INLINE bool arch_is_in_nested_exception(const z_arch_esf_t *esf) +static ALWAYS_INLINE bool arch_is_in_nested_exception(const struct arch_esf *esf) { return (arch_curr_cpu()->arch.exc_depth > 1U) ? (true) : (false); } @@ -48,7 +48,7 @@ static ALWAYS_INLINE bool arch_is_in_nested_exception(const z_arch_esf_t *esf) * This function is used by privileged code to determine if the thread * associated with the stack frame is in user mode. */ -static ALWAYS_INLINE bool z_arm_preempted_thread_in_user_mode(const z_arch_esf_t *esf) +static ALWAYS_INLINE bool z_arm_preempted_thread_in_user_mode(const struct arch_esf *esf) { return ((esf->basic.xpsr & CPSR_M_Msk) == CPSR_M_USR); } diff --git a/arch/arm/include/cortex_a_r/kernel_arch_func.h b/arch/arm/include/cortex_a_r/kernel_arch_func.h index 88f631ff4b487..3486d7d4d4e02 100644 --- a/arch/arm/include/cortex_a_r/kernel_arch_func.h +++ b/arch/arm/include/cortex_a_r/kernel_arch_func.h @@ -59,7 +59,7 @@ extern FUNC_NORETURN void z_arm_userspace_enter(k_thread_entry_t user_entry, uint32_t stack_end, uint32_t stack_start); -extern void z_arm_fatal_error(unsigned int reason, const z_arch_esf_t *esf); +extern void z_arm_fatal_error(unsigned int reason, const struct arch_esf *esf); #endif /* _ASMLANGUAGE */ diff --git a/arch/arm/include/cortex_m/exception.h b/arch/arm/include/cortex_m/exception.h index bf86abd77c70f..89bdd4b83e9a2 100644 --- a/arch/arm/include/cortex_m/exception.h +++ b/arch/arm/include/cortex_m/exception.h @@ -68,7 +68,7 @@ static ALWAYS_INLINE bool arch_is_in_isr(void) * @return true if execution state was in handler mode, before * the current exception occurred, otherwise false. */ -static ALWAYS_INLINE bool arch_is_in_nested_exception(const z_arch_esf_t *esf) +static ALWAYS_INLINE bool arch_is_in_nested_exception(const struct arch_esf *esf) { return (esf->basic.xpsr & IPSR_ISR_Msk) ? (true) : (false); } @@ -80,7 +80,7 @@ static ALWAYS_INLINE bool arch_is_in_nested_exception(const z_arch_esf_t *esf) * @param esf the exception stack frame (unused) * @return true if the current thread was in unprivileged mode */ -static ALWAYS_INLINE bool z_arm_preempted_thread_in_user_mode(const z_arch_esf_t *esf) +static ALWAYS_INLINE bool z_arm_preempted_thread_in_user_mode(const struct arch_esf *esf) { return z_arm_thread_is_in_user_mode(); } diff --git a/arch/arm/include/cortex_m/kernel_arch_func.h b/arch/arm/include/cortex_m/kernel_arch_func.h index 77619c9d6c4f8..132c056c91022 100644 --- a/arch/arm/include/cortex_m/kernel_arch_func.h +++ b/arch/arm/include/cortex_m/kernel_arch_func.h @@ -76,7 +76,7 @@ extern FUNC_NORETURN void z_arm_userspace_enter(k_thread_entry_t user_entry, uint32_t stack_end, uint32_t stack_start); -extern void z_arm_fatal_error(unsigned int reason, const z_arch_esf_t *esf); +extern void z_arm_fatal_error(unsigned int reason, const struct arch_esf *esf); #endif /* _ASMLANGUAGE */ diff --git a/arch/arm64/core/coredump.c b/arch/arm64/core/coredump.c index 399cf85e3d0f4..0176b61612ec1 100644 --- a/arch/arm64/core/coredump.c +++ b/arch/arm64/core/coredump.c @@ -13,7 +13,7 @@ #define ARCH_HDR_VER 1 /* Structure to store the architecture registers passed arch_coredump_info_dump - * As callee saved registers are not provided in z_arch_esf_t structure in Zephyr + * As callee saved registers are not provided in struct arch_esf structure in Zephyr * we just need 22 registers. */ struct arm64_arch_block { @@ -50,7 +50,7 @@ struct arm64_arch_block { */ static struct arm64_arch_block arch_blk; -void arch_coredump_info_dump(const z_arch_esf_t *esf) +void arch_coredump_info_dump(const struct arch_esf *esf) { /* Target architecture information header */ /* Information just relevant to the python parser */ @@ -69,7 +69,7 @@ void arch_coredump_info_dump(const z_arch_esf_t *esf) /* * Copies the thread registers to a memory block that will be printed out - * The thread registers are already provided by structure z_arch_esf_t + * The thread registers are already provided by structure struct arch_esf */ arch_blk.r.x0 = esf->x0; arch_blk.r.x1 = esf->x1; diff --git a/arch/arm64/core/fatal.c b/arch/arm64/core/fatal.c index f921c4ccf5aa6..a02ae13acf89c 100644 --- a/arch/arm64/core/fatal.c +++ b/arch/arm64/core/fatal.c @@ -181,7 +181,7 @@ static void dump_esr(uint64_t esr, bool *dump_far) LOG_ERR(" ISS: 0x%llx", GET_ESR_ISS(esr)); } -static void esf_dump(const z_arch_esf_t *esf) +static void esf_dump(const struct arch_esf *esf) { LOG_ERR("x0: 0x%016llx x1: 0x%016llx", esf->x0, esf->x1); LOG_ERR("x2: 0x%016llx x3: 0x%016llx", esf->x2, esf->x3); @@ -196,7 +196,7 @@ static void esf_dump(const z_arch_esf_t *esf) } #ifdef CONFIG_EXCEPTION_STACK_TRACE -static void esf_unwind(const z_arch_esf_t *esf) +static void esf_unwind(const struct arch_esf *esf) { /* * For GCC: @@ -244,7 +244,7 @@ static void esf_unwind(const z_arch_esf_t *esf) #endif /* CONFIG_EXCEPTION_DEBUG */ #ifdef CONFIG_ARM64_STACK_PROTECTION -static bool z_arm64_stack_corruption_check(z_arch_esf_t *esf, uint64_t esr, uint64_t far) +static bool z_arm64_stack_corruption_check(struct arch_esf *esf, uint64_t esr, uint64_t far) { uint64_t sp, sp_limit, guard_start; /* 0x25 means data abort from current EL */ @@ -284,7 +284,7 @@ static bool z_arm64_stack_corruption_check(z_arch_esf_t *esf, uint64_t esr, uint } #endif -static bool is_recoverable(z_arch_esf_t *esf, uint64_t esr, uint64_t far, +static bool is_recoverable(struct arch_esf *esf, uint64_t esr, uint64_t far, uint64_t elr) { if (!esf) @@ -306,7 +306,7 @@ static bool is_recoverable(z_arch_esf_t *esf, uint64_t esr, uint64_t far, return false; } -void z_arm64_fatal_error(unsigned int reason, z_arch_esf_t *esf) +void z_arm64_fatal_error(unsigned int reason, struct arch_esf *esf) { uint64_t esr = 0; uint64_t elr = 0; @@ -379,7 +379,7 @@ void z_arm64_fatal_error(unsigned int reason, z_arch_esf_t *esf) * * @param esf exception frame */ -void z_arm64_do_kernel_oops(z_arch_esf_t *esf) +void z_arm64_do_kernel_oops(struct arch_esf *esf) { /* x8 holds the exception reason */ unsigned int reason = esf->x8; diff --git a/arch/arm64/core/fpu.c b/arch/arm64/core/fpu.c index 0133eed2dcaaf..a585165b94339 100644 --- a/arch/arm64/core/fpu.c +++ b/arch/arm64/core/fpu.c @@ -159,7 +159,7 @@ void z_arm64_fpu_enter_exc(void) * simulate them and leave the FPU access disabled. This also avoids the * need for disabling interrupts in syscalls and IRQ handlers as well. */ -static bool simulate_str_q_insn(z_arch_esf_t *esf) +static bool simulate_str_q_insn(struct arch_esf *esf) { /* * Support only the "FP in exception" cases for now. @@ -221,7 +221,7 @@ static bool simulate_str_q_insn(z_arch_esf_t *esf) * don't get interrupted that is. To ensure that we mask interrupts to * the triggering exception context. */ -void z_arm64_fpu_trap(z_arch_esf_t *esf) +void z_arm64_fpu_trap(struct arch_esf *esf) { __ASSERT(read_daif() & DAIF_IRQ_BIT, "must be called with IRQs disabled"); diff --git a/arch/arm64/core/irq_manage.c b/arch/arm64/core/irq_manage.c index 4e96ce77bfa20..6344d1e3696c0 100644 --- a/arch/arm64/core/irq_manage.c +++ b/arch/arm64/core/irq_manage.c @@ -18,7 +18,7 @@ #include #include -void z_arm64_fatal_error(unsigned int reason, z_arch_esf_t *esf); +void z_arm64_fatal_error(unsigned int reason, struct arch_esf *esf); #if !defined(CONFIG_ARM_CUSTOM_INTERRUPT_CONTROLLER) /* diff --git a/arch/arm64/core/thread.c b/arch/arm64/core/thread.c index 667a868602dfc..18f49945eda49 100644 --- a/arch/arm64/core/thread.c +++ b/arch/arm64/core/thread.c @@ -87,7 +87,7 @@ void arch_new_thread(struct k_thread *thread, k_thread_stack_t *stack, void *p1, void *p2, void *p3) { extern void z_arm64_exit_exc(void); - z_arch_esf_t *pInitCtx; + struct arch_esf *pInitCtx; /* * Clean the thread->arch to avoid unexpected behavior because the diff --git a/arch/arm64/include/kernel_arch_func.h b/arch/arm64/include/kernel_arch_func.h index a5c3d59d87a6f..cc91abc3b49f3 100644 --- a/arch/arm64/include/kernel_arch_func.h +++ b/arch/arm64/include/kernel_arch_func.h @@ -43,7 +43,7 @@ static inline void arch_switch(void *switch_to, void **switched_from) z_arm64_context_switch(new, old); } -extern void z_arm64_fatal_error(unsigned int reason, z_arch_esf_t *esf); +extern void z_arm64_fatal_error(unsigned int reason, struct arch_esf *esf); extern void z_arm64_set_ttbr0(uint64_t ttbr0); extern void z_arm64_mem_cfg_ipi(void); diff --git a/arch/mips/core/fatal.c b/arch/mips/core/fatal.c index 16011241666ab..a53e5bb0f5e6c 100644 --- a/arch/mips/core/fatal.c +++ b/arch/mips/core/fatal.c @@ -9,7 +9,7 @@ LOG_MODULE_DECLARE(os, CONFIG_KERNEL_LOG_LEVEL); FUNC_NORETURN void z_mips_fatal_error(unsigned int reason, - const z_arch_esf_t *esf) + const struct arch_esf *esf) { #ifdef CONFIG_EXCEPTION_DEBUG if (esf != NULL) { @@ -84,7 +84,7 @@ static char *cause_str(unsigned long cause) } } -void _Fault(z_arch_esf_t *esf) +void _Fault(struct arch_esf *esf) { unsigned long cause; diff --git a/arch/mips/include/kernel_arch_func.h b/arch/mips/include/kernel_arch_func.h index ad89f75dd7f14..b01cc1a4c65da 100644 --- a/arch/mips/include/kernel_arch_func.h +++ b/arch/mips/include/kernel_arch_func.h @@ -35,7 +35,7 @@ arch_thread_return_value_set(struct k_thread *thread, unsigned int value) } FUNC_NORETURN void z_mips_fatal_error(unsigned int reason, - const z_arch_esf_t *esf); + const struct arch_esf *esf); static inline bool arch_is_in_isr(void) { diff --git a/arch/nios2/core/fatal.c b/arch/nios2/core/fatal.c index ac64b5bc30944..b531bb41e1789 100644 --- a/arch/nios2/core/fatal.c +++ b/arch/nios2/core/fatal.c @@ -12,7 +12,7 @@ LOG_MODULE_DECLARE(os, CONFIG_KERNEL_LOG_LEVEL); FUNC_NORETURN void z_nios2_fatal_error(unsigned int reason, - const z_arch_esf_t *esf) + const struct arch_esf *esf) { #if CONFIG_EXCEPTION_DEBUG if (esf != NULL) { @@ -102,7 +102,7 @@ static char *cause_str(uint32_t cause_code) } #endif -FUNC_NORETURN void _Fault(const z_arch_esf_t *esf) +FUNC_NORETURN void _Fault(const struct arch_esf *esf) { #if defined(CONFIG_PRINTK) || defined(CONFIG_LOG) /* Unfortunately, completely unavailable on Nios II/e cores */ diff --git a/arch/nios2/include/kernel_arch_func.h b/arch/nios2/include/kernel_arch_func.h index 2f2030c1c731c..2df268a1c6245 100644 --- a/arch/nios2/include/kernel_arch_func.h +++ b/arch/nios2/include/kernel_arch_func.h @@ -39,7 +39,7 @@ arch_thread_return_value_set(struct k_thread *thread, unsigned int value) } FUNC_NORETURN void z_nios2_fatal_error(unsigned int reason, - const z_arch_esf_t *esf); + const struct arch_esf *esf); static inline bool arch_is_in_isr(void) { diff --git a/arch/riscv/core/coredump.c b/arch/riscv/core/coredump.c index f232816433a08..70d7a9976d4ad 100644 --- a/arch/riscv/core/coredump.c +++ b/arch/riscv/core/coredump.c @@ -67,7 +67,7 @@ struct riscv_arch_block { */ static struct riscv_arch_block arch_blk; -void arch_coredump_info_dump(const z_arch_esf_t *esf) +void arch_coredump_info_dump(const struct arch_esf *esf) { struct coredump_arch_hdr_t hdr = { .id = COREDUMP_ARCH_HDR_ID, diff --git a/arch/riscv/core/fatal.c b/arch/riscv/core/fatal.c index bd4ed3dca36bc..d6dd4bc38869a 100644 --- a/arch/riscv/core/fatal.c +++ b/arch/riscv/core/fatal.c @@ -30,15 +30,15 @@ static const struct z_exc_handle exceptions[] = { #endif /* Stack trace function */ -void z_riscv_unwind_stack(const z_arch_esf_t *esf); +void z_riscv_unwind_stack(const struct arch_esf *esf); -uintptr_t z_riscv_get_sp_before_exc(const z_arch_esf_t *esf) +uintptr_t z_riscv_get_sp_before_exc(const struct arch_esf *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); + uintptr_t sp = (uintptr_t)esf + sizeof(struct arch_esf); #ifdef CONFIG_USERSPACE if ((esf->mstatus & MSTATUS_MPP) == PRV_U) { @@ -54,12 +54,12 @@ uintptr_t z_riscv_get_sp_before_exc(const z_arch_esf_t *esf) } FUNC_NORETURN void z_riscv_fatal_error(unsigned int reason, - const z_arch_esf_t *esf) + const struct arch_esf *esf) { z_riscv_fatal_error_csf(reason, esf, NULL); } -FUNC_NORETURN void z_riscv_fatal_error_csf(unsigned int reason, const z_arch_esf_t *esf, +FUNC_NORETURN void z_riscv_fatal_error_csf(unsigned int reason, const struct arch_esf *esf, const _callee_saved_t *csf) { #ifdef CONFIG_EXCEPTION_DEBUG @@ -152,14 +152,14 @@ static char *cause_str(unsigned long cause) } } -static bool bad_stack_pointer(z_arch_esf_t *esf) +static bool bad_stack_pointer(struct arch_esf *esf) { #ifdef CONFIG_PMP_STACK_GUARD /* * Check if the kernel stack pointer prior this exception (before * storing the exception stack frame) was in the stack guard area. */ - uintptr_t sp = (uintptr_t)esf + sizeof(z_arch_esf_t); + uintptr_t sp = (uintptr_t)esf + sizeof(struct arch_esf); #ifdef CONFIG_USERSPACE if (_current->arch.priv_stack_start != 0 && @@ -197,7 +197,7 @@ static bool bad_stack_pointer(z_arch_esf_t *esf) return false; } -void _Fault(z_arch_esf_t *esf) +void _Fault(struct arch_esf *esf) { #ifdef CONFIG_USERSPACE /* @@ -249,7 +249,7 @@ FUNC_NORETURN void arch_syscall_oops(void *ssf_ptr) void z_impl_user_fault(unsigned int reason) { - z_arch_esf_t *oops_esf = _current->syscall_frame; + struct arch_esf *oops_esf = _current->syscall_frame; if (((_current->base.user_options & K_USER) != 0) && reason != K_ERR_STACK_CHK_FAIL) { diff --git a/arch/riscv/core/fpu.c b/arch/riscv/core/fpu.c index da5d07b314640..318e97e0002a9 100644 --- a/arch/riscv/core/fpu.c +++ b/arch/riscv/core/fpu.c @@ -204,7 +204,7 @@ void z_riscv_fpu_enter_exc(void) * Note that the exception depth count was not incremented before this call * as no further exceptions are expected before returning to normal mode. */ -void z_riscv_fpu_trap(z_arch_esf_t *esf) +void z_riscv_fpu_trap(struct arch_esf *esf) { __ASSERT((esf->mstatus & MSTATUS_FS) == 0 && (csr_read(mstatus) & MSTATUS_FS) == 0, @@ -293,7 +293,7 @@ static bool fpu_access_allowed(unsigned int exc_update_level) * This is called on every exception exit except for z_riscv_fpu_trap(). * In that case the exception level of interest is 1 (soon to be 0). */ -void z_riscv_fpu_exit_exc(z_arch_esf_t *esf) +void z_riscv_fpu_exit_exc(struct arch_esf *esf) { if (fpu_access_allowed(1)) { esf->mstatus &= ~MSTATUS_FS; diff --git a/arch/riscv/core/stacktrace.c b/arch/riscv/core/stacktrace.c index 7dbcd8067cc34..cda6748c36371 100644 --- a/arch/riscv/core/stacktrace.c +++ b/arch/riscv/core/stacktrace.c @@ -12,7 +12,7 @@ LOG_MODULE_DECLARE(os, CONFIG_KERNEL_LOG_LEVEL); -uintptr_t z_riscv_get_sp_before_exc(const z_arch_esf_t *esf); +uintptr_t z_riscv_get_sp_before_exc(const struct arch_esf *esf); #if __riscv_xlen == 32 #define PR_REG "%08" PRIxPTR @@ -42,7 +42,7 @@ struct stackframe { LOG_ERR(" %2d: " SFP_FMT PR_REG " ra: " PR_REG, idx, sfp, ra) #endif -static bool in_stack_bound(uintptr_t addr, const z_arch_esf_t *esf) +static bool in_stack_bound(uintptr_t addr, const struct arch_esf *esf) { #ifdef CONFIG_THREAD_STACK_INFO uintptr_t start, end; @@ -86,7 +86,7 @@ static inline bool in_text_region(uintptr_t addr) } #ifdef CONFIG_FRAME_POINTER -void z_riscv_unwind_stack(const z_arch_esf_t *esf) +void z_riscv_unwind_stack(const struct arch_esf *esf) { uintptr_t fp = esf->s0; uintptr_t ra; @@ -115,7 +115,7 @@ void z_riscv_unwind_stack(const z_arch_esf_t *esf) LOG_ERR(""); } #else /* !CONFIG_FRAME_POINTER */ -void z_riscv_unwind_stack(const z_arch_esf_t *esf) +void z_riscv_unwind_stack(const struct arch_esf *esf) { uintptr_t sp = z_riscv_get_sp_before_exc(esf); uintptr_t ra; diff --git a/arch/riscv/include/kernel_arch_func.h b/arch/riscv/include/kernel_arch_func.h index bdfc0527b9502..c5ed6ff3f7f42 100644 --- a/arch/riscv/include/kernel_arch_func.h +++ b/arch/riscv/include/kernel_arch_func.h @@ -71,9 +71,9 @@ arch_switch(void *switch_to, void **switched_from) /* Thin wrapper around z_riscv_fatal_error_csf */ FUNC_NORETURN void z_riscv_fatal_error(unsigned int reason, - const z_arch_esf_t *esf); + const struct arch_esf *esf); -FUNC_NORETURN void z_riscv_fatal_error_csf(unsigned int reason, const z_arch_esf_t *esf, +FUNC_NORETURN void z_riscv_fatal_error_csf(unsigned int reason, const struct arch_esf *esf, const _callee_saved_t *csf); static inline bool arch_is_in_isr(void) diff --git a/arch/sparc/core/fatal.c b/arch/sparc/core/fatal.c index 55100606b9242..40fd9d16792bc 100644 --- a/arch/sparc/core/fatal.c +++ b/arch/sparc/core/fatal.c @@ -122,7 +122,7 @@ static const struct { { .tt = 0x0A, .desc = "tag_overflow", }, }; -static void print_trap_type(const z_arch_esf_t *esf) +static void print_trap_type(const struct arch_esf *esf) { const int tt = (esf->tbr & TBR_TT) >> TBR_TT_BIT; const char *desc = "unknown"; @@ -142,7 +142,7 @@ static void print_trap_type(const z_arch_esf_t *esf) LOG_ERR("tt = 0x%02X, %s", tt, desc); } -static void print_integer_registers(const z_arch_esf_t *esf) +static void print_integer_registers(const struct arch_esf *esf) { const struct savearea *flushed = (struct savearea *) esf->out[6]; @@ -159,7 +159,7 @@ static void print_integer_registers(const z_arch_esf_t *esf) } } -static void print_special_registers(const z_arch_esf_t *esf) +static void print_special_registers(const struct arch_esf *esf) { LOG_ERR( "psr: %08x wim: %08x tbr: %08x y: %08x", @@ -168,7 +168,7 @@ static void print_special_registers(const z_arch_esf_t *esf) LOG_ERR(" pc: %08x npc: %08x", esf->pc, esf->npc); } -static void print_backtrace(const z_arch_esf_t *esf) +static void print_backtrace(const struct arch_esf *esf) { const int MAX_LOGLINES = 40; const struct savearea *s = (struct savearea *) esf->out[6]; @@ -190,7 +190,7 @@ static void print_backtrace(const z_arch_esf_t *esf) } } -static void print_all(const z_arch_esf_t *esf) +static void print_all(const struct arch_esf *esf) { LOG_ERR(""); print_trap_type(esf); @@ -205,7 +205,7 @@ static void print_all(const z_arch_esf_t *esf) #endif /* CONFIG_EXCEPTION_DEBUG */ FUNC_NORETURN void z_sparc_fatal_error(unsigned int reason, - const z_arch_esf_t *esf) + const struct arch_esf *esf) { #if CONFIG_EXCEPTION_DEBUG if (esf != NULL) { diff --git a/arch/sparc/include/kernel_arch_func.h b/arch/sparc/include/kernel_arch_func.h index 41f48ccc44a4e..8b79b130ad655 100644 --- a/arch/sparc/include/kernel_arch_func.h +++ b/arch/sparc/include/kernel_arch_func.h @@ -43,7 +43,7 @@ static inline void arch_switch(void *switch_to, void **switched_from) } FUNC_NORETURN void z_sparc_fatal_error(unsigned int reason, - const z_arch_esf_t *esf); + const struct arch_esf *esf); static inline bool arch_is_in_isr(void) { diff --git a/arch/x86/core/fatal.c b/arch/x86/core/fatal.c index 5db20eb5deb27..1561b51b84d54 100644 --- a/arch/x86/core/fatal.c +++ b/arch/x86/core/fatal.c @@ -35,7 +35,7 @@ FUNC_NORETURN void arch_system_halt(unsigned int reason) #ifdef CONFIG_THREAD_STACK_INFO -static inline uintptr_t esf_get_sp(const z_arch_esf_t *esf) +static inline uintptr_t esf_get_sp(const struct arch_esf *esf) { #ifdef CONFIG_X86_64 return esf->rsp; @@ -122,7 +122,7 @@ bool z_x86_check_guard_page(uintptr_t addr) #ifdef CONFIG_EXCEPTION_DEBUG -static inline uintptr_t esf_get_code(const z_arch_esf_t *esf) +static inline uintptr_t esf_get_code(const struct arch_esf *esf) { #ifdef CONFIG_X86_64 return esf->code; @@ -188,7 +188,7 @@ static void unwind_stack(uintptr_t base_ptr, uint16_t cs) } #endif /* CONFIG_EXCEPTION_STACK_TRACE */ -static inline uintptr_t get_cr3(const z_arch_esf_t *esf) +static inline uintptr_t get_cr3(const struct arch_esf *esf) { #if defined(CONFIG_USERSPACE) && defined(CONFIG_X86_KPTI) /* If the interrupted thread was in user mode, we did a page table @@ -206,14 +206,14 @@ static inline uintptr_t get_cr3(const z_arch_esf_t *esf) return z_x86_cr3_get(); } -static inline pentry_t *get_ptables(const z_arch_esf_t *esf) +static inline pentry_t *get_ptables(const struct arch_esf *esf) { return z_mem_virt_addr(get_cr3(esf)); } #ifdef CONFIG_X86_64 __pinned_func -static void dump_regs(const z_arch_esf_t *esf) +static void dump_regs(const struct arch_esf *esf) { LOG_ERR("RAX: 0x%016lx RBX: 0x%016lx RCX: 0x%016lx RDX: 0x%016lx", esf->rax, esf->rbx, esf->rcx, esf->rdx); @@ -236,7 +236,7 @@ static void dump_regs(const z_arch_esf_t *esf) } #else /* 32-bit */ __pinned_func -static void dump_regs(const z_arch_esf_t *esf) +static void dump_regs(const struct arch_esf *esf) { LOG_ERR("EAX: 0x%08x, EBX: 0x%08x, ECX: 0x%08x, EDX: 0x%08x", esf->eax, esf->ebx, esf->ecx, esf->edx); @@ -327,7 +327,7 @@ static void log_exception(uintptr_t vector, uintptr_t code) } __pinned_func -static void dump_page_fault(z_arch_esf_t *esf) +static void dump_page_fault(struct arch_esf *esf) { uintptr_t err; void *cr2; @@ -362,7 +362,7 @@ static void dump_page_fault(z_arch_esf_t *esf) __pinned_func FUNC_NORETURN void z_x86_fatal_error(unsigned int reason, - const z_arch_esf_t *esf) + const struct arch_esf *esf) { if (esf != NULL) { #ifdef CONFIG_EXCEPTION_DEBUG @@ -385,7 +385,7 @@ FUNC_NORETURN void z_x86_fatal_error(unsigned int reason, __pinned_func FUNC_NORETURN void z_x86_unhandled_cpu_exception(uintptr_t vector, - const z_arch_esf_t *esf) + const struct arch_esf *esf) { #ifdef CONFIG_EXCEPTION_DEBUG log_exception(vector, esf_get_code(esf)); @@ -404,7 +404,7 @@ static const struct z_exc_handle exceptions[] = { #endif __pinned_func -void z_x86_page_fault_handler(z_arch_esf_t *esf) +void z_x86_page_fault_handler(struct arch_esf *esf) { #ifdef CONFIG_DEMAND_PAGING if ((esf->errorCode & PF_P) == 0) { @@ -488,7 +488,7 @@ void z_x86_page_fault_handler(z_arch_esf_t *esf) } __pinned_func -void z_x86_do_kernel_oops(const z_arch_esf_t *esf) +void z_x86_do_kernel_oops(const struct arch_esf *esf) { uintptr_t reason; diff --git a/arch/x86/core/ia32/coredump.c b/arch/x86/core/ia32/coredump.c index b49373aab771e..fb7d0fcfd8cc5 100644 --- a/arch/x86/core/ia32/coredump.c +++ b/arch/x86/core/ia32/coredump.c @@ -34,7 +34,7 @@ struct x86_arch_block { */ static struct x86_arch_block arch_blk; -void arch_coredump_info_dump(const z_arch_esf_t *esf) +void arch_coredump_info_dump(const struct arch_esf *esf) { struct coredump_arch_hdr_t hdr = { .id = COREDUMP_ARCH_HDR_ID, diff --git a/arch/x86/core/ia32/fatal.c b/arch/x86/core/ia32/fatal.c index 597f21a01adc6..e510d6b1a2dbc 100644 --- a/arch/x86/core/ia32/fatal.c +++ b/arch/x86/core/ia32/fatal.c @@ -27,10 +27,10 @@ LOG_MODULE_DECLARE(os, CONFIG_KERNEL_LOG_LEVEL); unsigned int z_x86_exception_vector; #endif -__weak void z_debug_fatal_hook(const z_arch_esf_t *esf) { ARG_UNUSED(esf); } +__weak void z_debug_fatal_hook(const struct arch_esf *esf) { ARG_UNUSED(esf); } __pinned_func -void z_x86_spurious_irq(const z_arch_esf_t *esf) +void z_x86_spurious_irq(const struct arch_esf *esf) { int vector = z_irq_controller_isr_vector_get(); @@ -46,7 +46,7 @@ void arch_syscall_oops(void *ssf) { struct _x86_syscall_stack_frame *ssf_ptr = (struct _x86_syscall_stack_frame *)ssf; - z_arch_esf_t oops = { + struct arch_esf oops = { .eip = ssf_ptr->eip, .cs = ssf_ptr->cs, .eflags = ssf_ptr->eflags @@ -66,7 +66,7 @@ NANO_CPU_INT_REGISTER(_kernel_oops_handler, NANO_SOFT_IRQ, #if CONFIG_EXCEPTION_DEBUG __pinned_func FUNC_NORETURN static void generic_exc_handle(unsigned int vector, - const z_arch_esf_t *pEsf) + const struct arch_esf *pEsf) { #ifdef CONFIG_DEBUG_COREDUMP z_x86_exception_vector = vector; @@ -77,7 +77,7 @@ FUNC_NORETURN static void generic_exc_handle(unsigned int vector, #define _EXC_FUNC(vector) \ __pinned_func \ -FUNC_NORETURN __used static void handle_exc_##vector(const z_arch_esf_t *pEsf) \ +FUNC_NORETURN __used static void handle_exc_##vector(const struct arch_esf *pEsf) \ { \ generic_exc_handle(vector, pEsf); \ } @@ -120,7 +120,7 @@ EXC_FUNC_NOCODE(IV_MACHINE_CHECK, 0); _EXCEPTION_CONNECT_CODE(z_x86_page_fault_handler, IV_PAGE_FAULT, 0); #ifdef CONFIG_X86_ENABLE_TSS -static __pinned_noinit volatile z_arch_esf_t _df_esf; +static __pinned_noinit volatile struct arch_esf _df_esf; /* Very tiny stack; just enough for the bogus error code pushed by the CPU * and a frame pointer push by the compiler. All df_handler_top does is @@ -182,14 +182,14 @@ static __used void df_handler_bottom(void) reason = K_ERR_STACK_CHK_FAIL; } #endif - z_x86_fatal_error(reason, (z_arch_esf_t *)&_df_esf); + z_x86_fatal_error(reason, (struct arch_esf *)&_df_esf); } __pinned_func static FUNC_NORETURN __used void df_handler_top(void) { /* State of the system when the double-fault forced a task switch - * will be in _main_tss. Set up a z_arch_esf_t and copy system state into + * will be in _main_tss. Set up a struct arch_esf and copy system state into * it */ _df_esf.esp = _main_tss.esp; diff --git a/arch/x86/core/ia32/float.c b/arch/x86/core/ia32/float.c index a33a40a0a7832..c89bf7accd5a1 100644 --- a/arch/x86/core/ia32/float.c +++ b/arch/x86/core/ia32/float.c @@ -302,7 +302,7 @@ int z_float_disable(struct k_thread *thread) * instruction is executed while CR0[TS]=1. The handler then enables the * current thread to use all supported floating point registers. */ -void _FpNotAvailableExcHandler(z_arch_esf_t *pEsf) +void _FpNotAvailableExcHandler(struct arch_esf *pEsf) { ARG_UNUSED(pEsf); diff --git a/arch/x86/core/ia32/gdbstub.c b/arch/x86/core/ia32/gdbstub.c index 692ea78baf41c..252f15d79ffeb 100644 --- a/arch/x86/core/ia32/gdbstub.c +++ b/arch/x86/core/ia32/gdbstub.c @@ -78,7 +78,7 @@ static unsigned int get_exception(unsigned int vector) /* * Debug exception handler. */ -static void z_gdb_interrupt(unsigned int vector, z_arch_esf_t *esf) +static void z_gdb_interrupt(unsigned int vector, struct arch_esf *esf) { debug_ctx.exception = get_exception(vector); @@ -212,7 +212,7 @@ size_t arch_gdb_reg_writeone(struct gdb_ctx *ctx, uint8_t *hex, size_t hexlen, return ret; } -static __used void z_gdb_debug_isr(z_arch_esf_t *esf) +static __used void z_gdb_debug_isr(struct arch_esf *esf) { #ifdef CONFIG_GDBSTUB_TRACE printk("gdbstub:enter %s (IV_DEBUG)\n", __func__); @@ -225,7 +225,7 @@ static __used void z_gdb_debug_isr(z_arch_esf_t *esf) #endif } -static __used void z_gdb_break_isr(z_arch_esf_t *esf) +static __used void z_gdb_break_isr(struct arch_esf *esf) { #ifdef CONFIG_GDBSTUB_TRACE printk("gdbstub:enter %s (IV_BREAKPOINT)\n", __func__); diff --git a/arch/x86/core/intel64/coredump.c b/arch/x86/core/intel64/coredump.c index f1c1a15eaff37..65a9306ca07da 100644 --- a/arch/x86/core/intel64/coredump.c +++ b/arch/x86/core/intel64/coredump.c @@ -46,7 +46,7 @@ struct x86_64_arch_block { */ static struct x86_64_arch_block arch_blk; -void arch_coredump_info_dump(const z_arch_esf_t *esf) +void arch_coredump_info_dump(const struct arch_esf *esf) { struct coredump_arch_hdr_t hdr = { .id = COREDUMP_ARCH_HDR_ID, diff --git a/arch/x86/core/intel64/fatal.c b/arch/x86/core/intel64/fatal.c index 9dd97614dc1e3..9eed95bfaa3ad 100644 --- a/arch/x86/core/intel64/fatal.c +++ b/arch/x86/core/intel64/fatal.c @@ -13,14 +13,14 @@ LOG_MODULE_DECLARE(os, CONFIG_KERNEL_LOG_LEVEL); /* NMI handlers should override weak implementation * return true if NMI is handled, false otherwise */ -__weak bool z_x86_do_kernel_nmi(const z_arch_esf_t *esf) +__weak bool z_x86_do_kernel_nmi(const struct arch_esf *esf) { ARG_UNUSED(esf); return false; } -void z_x86_exception(z_arch_esf_t *esf) +void z_x86_exception(struct arch_esf *esf) { switch (esf->vector) { case Z_X86_OOPS_VECTOR: diff --git a/arch/x86/core/offsets/ia32_offsets.c b/arch/x86/core/offsets/ia32_offsets.c index 61a7f25bb2a40..747ca235831ff 100644 --- a/arch/x86/core/offsets/ia32_offsets.c +++ b/arch/x86/core/offsets/ia32_offsets.c @@ -53,6 +53,5 @@ GEN_ABSOLUTE_SYM(_K_THREAD_NO_FLOAT_SIZEOF, GEN_OFFSET_SYM(_callee_saved_t, esp); /* z_arch_esf_t structure member offsets */ - GEN_OFFSET_SYM(z_arch_esf_t, eflags); #endif /* _X86_OFFSETS_INC_ */ diff --git a/arch/x86/include/ia32/exception.h b/arch/x86/include/ia32/exception.h index 27119709c2ade..1b0ce9ee3b52d 100644 --- a/arch/x86/include/ia32/exception.h +++ b/arch/x86/include/ia32/exception.h @@ -62,7 +62,7 @@ * Assign an exception handler to a particular vector in the IDT. * * @param handler A handler function of the prototype - * void handler(const z_arch_esf_t *esf) + * void handler(const struct arch_esf *esf) * @param vector Vector index in the IDT */ #define _EXCEPTION_CONNECT_NOCODE(handler, vector, dpl) \ @@ -75,7 +75,7 @@ * The error code will be accessible in esf->errorCode * * @param handler A handler function of the prototype - * void handler(const z_arch_esf_t *esf) + * void handler(const struct arch_esf *esf) * @param vector Vector index in the IDT */ #define _EXCEPTION_CONNECT_CODE(handler, vector, dpl) \ diff --git a/arch/x86/include/intel64/kernel_arch_func.h b/arch/x86/include/intel64/kernel_arch_func.h index a749a9b9af178..abf022fe5fd55 100644 --- a/arch/x86/include/intel64/kernel_arch_func.h +++ b/arch/x86/include/intel64/kernel_arch_func.h @@ -36,7 +36,7 @@ void x86_sse_init(struct k_thread *thread); void z_x86_syscall_entry_stub(void); -bool z_x86_do_kernel_nmi(const z_arch_esf_t *esf); +bool z_x86_do_kernel_nmi(const struct arch_esf *esf); #endif /* _ASMLANGUAGE */ diff --git a/arch/x86/include/kernel_arch_func.h b/arch/x86/include/kernel_arch_func.h index 00b411978ec65..9bc7cfe4212f8 100644 --- a/arch/x86/include/kernel_arch_func.h +++ b/arch/x86/include/kernel_arch_func.h @@ -49,16 +49,16 @@ void z_x86_early_serial_init(void); * interesting info and call z_x86_fatal_error() */ FUNC_NORETURN void z_x86_unhandled_cpu_exception(uintptr_t vector, - const z_arch_esf_t *esf); + const struct arch_esf *esf); /* Called upon unrecoverable error; dump registers and transfer control to * kernel via z_fatal_error() */ FUNC_NORETURN void z_x86_fatal_error(unsigned int reason, - const z_arch_esf_t *esf); + const struct arch_esf *esf); /* Common handling for page fault exceptions */ -void z_x86_page_fault_handler(z_arch_esf_t *esf); +void z_x86_page_fault_handler(struct arch_esf *esf); #ifdef CONFIG_THREAD_STACK_INFO /** @@ -90,7 +90,7 @@ void *z_x86_userspace_prepare_thread(struct k_thread *thread); #endif /* CONFIG_USERSPACE */ -void z_x86_do_kernel_oops(const z_arch_esf_t *esf); +void z_x86_do_kernel_oops(const struct arch_esf *esf); /* * Find a free IRQ vector at the specified priority, or return -1 if none left. diff --git a/arch/xtensa/core/coredump.c b/arch/xtensa/core/coredump.c index 7f010eb1954a7..0ee1f8992a6b7 100644 --- a/arch/xtensa/core/coredump.c +++ b/arch/xtensa/core/coredump.c @@ -91,7 +91,7 @@ struct xtensa_arch_block { */ static struct xtensa_arch_block arch_blk; -void arch_coredump_info_dump(const z_arch_esf_t *esf) +void arch_coredump_info_dump(const struct arch_esf *esf) { struct coredump_arch_hdr_t hdr = { .id = COREDUMP_ARCH_HDR_ID, diff --git a/arch/xtensa/core/fatal.c b/arch/xtensa/core/fatal.c index 0d5da1ca8179d..39e84b86f6b13 100644 --- a/arch/xtensa/core/fatal.c +++ b/arch/xtensa/core/fatal.c @@ -84,7 +84,7 @@ char *xtensa_exccause(unsigned int cause_code) #endif } -void xtensa_fatal_error(unsigned int reason, const z_arch_esf_t *esf) +void xtensa_fatal_error(unsigned int reason, const struct arch_esf *esf) { #ifdef CONFIG_EXCEPTION_DEBUG if (esf) { diff --git a/arch/xtensa/core/gdbstub.c b/arch/xtensa/core/gdbstub.c index 4df72f0d355c7..0ebc9cc68ccd5 100644 --- a/arch/xtensa/core/gdbstub.c +++ b/arch/xtensa/core/gdbstub.c @@ -422,7 +422,7 @@ static unsigned int get_gdb_exception_reason(unsigned int reason) * @param ctx GDB context * @param stack Pointer to the stack frame */ -static void copy_to_ctx(struct gdb_ctx *ctx, const z_arch_esf_t *stack) +static void copy_to_ctx(struct gdb_ctx *ctx, const struct arch_esf *stack) { struct xtensa_register *reg; int idx, num_laddr_regs; @@ -513,7 +513,7 @@ static void copy_to_ctx(struct gdb_ctx *ctx, const z_arch_esf_t *stack) * @param ctx GDB context * @param stack Pointer to the stack frame */ -static void restore_from_ctx(struct gdb_ctx *ctx, const z_arch_esf_t *stack) +static void restore_from_ctx(struct gdb_ctx *ctx, const struct arch_esf *stack) { struct xtensa_register *reg; int idx, num_laddr_regs; @@ -913,7 +913,7 @@ int arch_gdb_remove_breakpoint(struct gdb_ctx *ctx, uint8_t type, return ret; } -void z_gdb_isr(z_arch_esf_t *esf) +void z_gdb_isr(struct arch_esf *esf) { uint32_t reg; diff --git a/arch/xtensa/core/vector_handlers.c b/arch/xtensa/core/vector_handlers.c index dd3c0c00f5246..471a67c086304 100644 --- a/arch/xtensa/core/vector_handlers.c +++ b/arch/xtensa/core/vector_handlers.c @@ -37,7 +37,7 @@ static const struct z_exc_handle exceptions[] = { }; #endif /* CONFIG_USERSPACE */ -void xtensa_dump_stack(const z_arch_esf_t *stack) +void xtensa_dump_stack(const void *stack) { _xtensa_irq_stack_frame_raw_t *frame = (void *)stack; _xtensa_irq_bsa_t *bsa = frame->ptr_to_bsa; @@ -218,9 +218,10 @@ static inline DEF_INT_C_HANDLER(1) * different because exceptions and interrupts land at the same * vector; other interrupt levels have their own vectors. */ -void *xtensa_excint1_c(int *interrupted_stack) +void *xtensa_excint1_c(void *esf) { int cause; + int *interrupted_stack = &((struct arch_esf *)esf)->dummy; _xtensa_irq_bsa_t *bsa = (void *)*(int **)interrupted_stack; bool is_fatal_error = false; bool is_dblexc = false; @@ -385,7 +386,7 @@ void *xtensa_excint1_c(int *interrupted_stack) #if defined(CONFIG_GDBSTUB) void *xtensa_debugint_c(int *interrupted_stack) { - extern void z_gdb_isr(z_arch_esf_t *esf); + extern void z_gdb_isr(struct arch_esf *esf); z_gdb_isr((void *)interrupted_stack); diff --git a/arch/xtensa/include/xtensa_internal.h b/arch/xtensa/include/xtensa_internal.h index 60b512ab57135..f3e1ab4f44e20 100644 --- a/arch/xtensa/include/xtensa_internal.h +++ b/arch/xtensa/include/xtensa_internal.h @@ -25,7 +25,7 @@ * * @param stack Pointer to stack frame. */ -void xtensa_dump_stack(const z_arch_esf_t *stack); +void xtensa_dump_stack(const void *stack); /** * @brief Get string description from an exception code. @@ -43,7 +43,7 @@ char *xtensa_exccause(unsigned int cause_code); * @param esf Exception context, with details and partial or full register * state when the error occurred. May in some cases be NULL. */ -void xtensa_fatal_error(unsigned int reason, const z_arch_esf_t *esf); +void xtensa_fatal_error(unsigned int reason, const struct arch_esf *esf); /** * @brief Perform a one-way transition from supervisor to user mode. diff --git a/drivers/edac/edac_ibecc.c b/drivers/edac/edac_ibecc.c index 06033a2bbb407..f8ea556f434ba 100644 --- a/drivers/edac/edac_ibecc.c +++ b/drivers/edac/edac_ibecc.c @@ -387,7 +387,7 @@ static bool handle_nmi(void) return true; } -bool z_x86_do_kernel_nmi(const z_arch_esf_t *esf) +bool z_x86_do_kernel_nmi(const struct arch_esf *esf) { const struct device *const dev = DEVICE_DT_GET(DEVICE_NODE); struct ibecc_data *data = dev->data; diff --git a/include/zephyr/arch/arc/v2/exception.h b/include/zephyr/arch/arc/v2/exception.h index 8993d7cfe067a..f606cf1ea9a7c 100644 --- a/include/zephyr/arch/arc/v2/exception.h +++ b/include/zephyr/arch/arc/v2/exception.h @@ -18,11 +18,6 @@ extern "C" { #endif -#ifdef _ASMLANGUAGE -#else -typedef struct arch_esf z_arch_esf_t; -#endif - #ifdef __cplusplus } #endif diff --git a/include/zephyr/arch/arch_interface.h b/include/zephyr/arch/arch_interface.h index 04aef8157558b..797a60bbaa58c 100644 --- a/include/zephyr/arch/arch_interface.h +++ b/include/zephyr/arch/arch_interface.h @@ -39,6 +39,7 @@ extern "C" { #endif /* NOTE: We cannot pull in kernel.h here, need some forward declarations */ +struct arch_esf; struct k_thread; struct k_mem_domain; @@ -46,6 +47,8 @@ typedef struct z_thread_stack_element k_thread_stack_t; typedef void (*k_thread_entry_t)(void *p1, void *p2, void *p3); +__deprecated typedef struct arch_esf z_arch_esf_t; + /** * @defgroup arch-timing Architecture timing APIs * @ingroup arch-interface diff --git a/include/zephyr/arch/arm/cortex_a_r/exception.h b/include/zephyr/arch/arm/cortex_a_r/exception.h index 2a6bd313e15cd..cd8377bc3a70c 100644 --- a/include/zephyr/arch/arm/cortex_a_r/exception.h +++ b/include/zephyr/arch/arm/cortex_a_r/exception.h @@ -75,8 +75,6 @@ struct arch_esf { extern uint32_t z_arm_coredump_fault_sp; -typedef struct arch_esf z_arch_esf_t; - extern void z_arm_exc_exit(bool fatal); #ifdef __cplusplus diff --git a/include/zephyr/arch/arm/cortex_m/exception.h b/include/zephyr/arch/arm/cortex_m/exception.h index 09ab68575b008..2deed9bdf832d 100644 --- a/include/zephyr/arch/arm/cortex_m/exception.h +++ b/include/zephyr/arch/arm/cortex_m/exception.h @@ -119,8 +119,6 @@ struct arch_esf { extern uint32_t z_arm_coredump_fault_sp; -typedef struct arch_esf z_arch_esf_t; - extern void z_arm_exc_exit(void); #ifdef __cplusplus diff --git a/include/zephyr/arch/arm/gdbstub.h b/include/zephyr/arch/arm/gdbstub.h index e8e606d7def80..55fceff173d10 100644 --- a/include/zephyr/arch/arm/gdbstub.h +++ b/include/zephyr/arch/arm/gdbstub.h @@ -64,7 +64,7 @@ struct gdb_ctx { unsigned int registers[GDB_NUM_REGS]; }; -void z_gdb_entry(z_arch_esf_t *esf, unsigned int exc_cause); +void z_gdb_entry(struct arch_esf *esf, unsigned int exc_cause); #endif diff --git a/include/zephyr/arch/arm64/exception.h b/include/zephyr/arch/arm64/exception.h index d6be6715d5dcd..a1348f608e3b9 100644 --- a/include/zephyr/arch/arm64/exception.h +++ b/include/zephyr/arch/arm64/exception.h @@ -55,8 +55,6 @@ struct arch_esf { #endif } __aligned(16); -typedef struct arch_esf z_arch_esf_t; - #ifdef __cplusplus } #endif diff --git a/include/zephyr/arch/mips/exception.h b/include/zephyr/arch/mips/exception.h index 40e9ac0506f50..f33af4c4387d8 100644 --- a/include/zephyr/arch/mips/exception.h +++ b/include/zephyr/arch/mips/exception.h @@ -50,8 +50,6 @@ struct arch_esf { unsigned long cause; }; -typedef struct arch_esf z_arch_esf_t; - #ifdef __cplusplus } #endif diff --git a/include/zephyr/arch/nios2/arch.h b/include/zephyr/arch/nios2/arch.h index bbc41b200a6a8..5369f690b5d37 100644 --- a/include/zephyr/arch/nios2/arch.h +++ b/include/zephyr/arch/nios2/arch.h @@ -101,10 +101,10 @@ void arch_irq_enable(unsigned int irq); void arch_irq_disable(unsigned int irq); FUNC_NORETURN void z_SysFatalErrorHandler(unsigned int reason, - const z_arch_esf_t *esf); + const struct arch_esf *esf); FUNC_NORETURN void z_NanoFatalErrorHandler(unsigned int reason, - const z_arch_esf_t *esf); + const struct arch_esf *esf); enum nios2_exception_cause { NIOS2_EXCEPTION_UNKNOWN = -1, diff --git a/include/zephyr/arch/nios2/exception.h b/include/zephyr/arch/nios2/exception.h index af13754baa605..223fa583114e6 100644 --- a/include/zephyr/arch/nios2/exception.h +++ b/include/zephyr/arch/nios2/exception.h @@ -35,8 +35,6 @@ struct arch_esf { uint32_t instr; /* Instruction being executed when exc occurred */ }; -typedef struct arch_esf z_arch_esf_t; - #ifdef __cplusplus } #endif diff --git a/include/zephyr/arch/posix/exception.h b/include/zephyr/arch/posix/exception.h index d267d87363c6c..6c7962aa05799 100644 --- a/include/zephyr/arch/posix/exception.h +++ b/include/zephyr/arch/posix/exception.h @@ -19,8 +19,6 @@ struct arch_esf { uint32_t dummy; /*maybe we will want to add something someday*/ }; -typedef struct arch_esf z_arch_esf_t; - #ifdef __cplusplus } #endif diff --git a/include/zephyr/arch/riscv/arch.h b/include/zephyr/arch/riscv/arch.h index e7dcfbef3aed1..4cdedb700d326 100644 --- a/include/zephyr/arch/riscv/arch.h +++ b/include/zephyr/arch/riscv/arch.h @@ -48,12 +48,12 @@ */ #ifdef CONFIG_PMP_POWER_OF_TWO_ALIGNMENT #define Z_RISCV_STACK_GUARD_SIZE \ - Z_POW2_CEIL(MAX(sizeof(z_arch_esf_t) + CONFIG_PMP_STACK_GUARD_MIN_SIZE, \ + Z_POW2_CEIL(MAX(sizeof(struct arch_esf) + CONFIG_PMP_STACK_GUARD_MIN_SIZE, \ Z_RISCV_STACK_PMP_ALIGN)) #define ARCH_KERNEL_STACK_OBJ_ALIGN Z_RISCV_STACK_GUARD_SIZE #else #define Z_RISCV_STACK_GUARD_SIZE \ - ROUND_UP(sizeof(z_arch_esf_t) + CONFIG_PMP_STACK_GUARD_MIN_SIZE, \ + ROUND_UP(sizeof(struct arch_esf) + CONFIG_PMP_STACK_GUARD_MIN_SIZE, \ Z_RISCV_STACK_PMP_ALIGN) #define ARCH_KERNEL_STACK_OBJ_ALIGN Z_RISCV_STACK_PMP_ALIGN #endif diff --git a/include/zephyr/arch/riscv/exception.h b/include/zephyr/arch/riscv/exception.h index 05d5bac02c2dd..097776227bb47 100644 --- a/include/zephyr/arch/riscv/exception.h +++ b/include/zephyr/arch/riscv/exception.h @@ -87,7 +87,6 @@ struct arch_esf { } __aligned(16); #endif /* CONFIG_RISCV_SOC_HAS_ISR_STACKING */ -typedef struct arch_esf z_arch_esf_t; #ifdef CONFIG_RISCV_SOC_CONTEXT_SAVE typedef struct soc_esf soc_esf_t; #endif diff --git a/include/zephyr/arch/sparc/exception.h b/include/zephyr/arch/sparc/exception.h index 597d1f94df738..a2d3fae52e203 100644 --- a/include/zephyr/arch/sparc/exception.h +++ b/include/zephyr/arch/sparc/exception.h @@ -25,8 +25,6 @@ struct arch_esf { uint32_t y; }; -typedef struct arch_esf z_arch_esf_t; - #ifdef __cplusplus } #endif diff --git a/include/zephyr/arch/x86/ia32/exception.h b/include/zephyr/arch/x86/ia32/exception.h index 929c65428b220..de618f4e01d43 100644 --- a/include/zephyr/arch/x86/ia32/exception.h +++ b/include/zephyr/arch/x86/ia32/exception.h @@ -27,7 +27,7 @@ extern "C" { * Those registers are pushed onto the stack by _ExcEnt(). */ -typedef struct arch_esf { +struct arch_esf { #ifdef CONFIG_GDBSTUB unsigned int ss; unsigned int gs; @@ -47,7 +47,7 @@ typedef struct arch_esf { unsigned int eip; unsigned int cs; unsigned int eflags; -} z_arch_esf_t; +}; extern unsigned int z_x86_exception_vector; diff --git a/include/zephyr/arch/x86/intel64/exception.h b/include/zephyr/arch/x86/intel64/exception.h index eb6690eca5712..55c7cc2b4ee84 100644 --- a/include/zephyr/arch/x86/intel64/exception.h +++ b/include/zephyr/arch/x86/intel64/exception.h @@ -53,8 +53,6 @@ struct arch_esf { unsigned long ss; }; -typedef struct arch_esf z_arch_esf_t; - struct x86_ssf { unsigned long rip; unsigned long rflags; diff --git a/include/zephyr/arch/xtensa/exception.h b/include/zephyr/arch/xtensa/exception.h index 94cb4ce5bb2cc..acc6d4a30413b 100644 --- a/include/zephyr/arch/xtensa/exception.h +++ b/include/zephyr/arch/xtensa/exception.h @@ -28,7 +28,6 @@ extern "C" { struct arch_esf { int dummy; }; -typedef int z_arch_esf_t; #endif diff --git a/include/zephyr/bluetooth/hci_vs.h b/include/zephyr/bluetooth/hci_vs.h index 3561e20e9aa58..dabbe2902eaf9 100644 --- a/include/zephyr/bluetooth/hci_vs.h +++ b/include/zephyr/bluetooth/hci_vs.h @@ -451,7 +451,7 @@ struct bt_hci_evt_mesh_scanning_report { struct bt_hci_evt_mesh_scan_report reports[0]; } __packed; -struct net_buf *hci_vs_err_stack_frame(unsigned int reason, const z_arch_esf_t *esf); +struct net_buf *hci_vs_err_stack_frame(unsigned int reason, const struct arch_esf *esf); struct net_buf *hci_vs_err_trace(const char *file, uint32_t line, uint64_t pc); struct net_buf *hci_vs_err_assert(const char *file, uint32_t line); diff --git a/include/zephyr/debug/coredump.h b/include/zephyr/debug/coredump.h index 9d4f37a4f870f..f61f4e94a38b7 100644 --- a/include/zephyr/debug/coredump.h +++ b/include/zephyr/debug/coredump.h @@ -232,7 +232,7 @@ struct coredump_backend_api { coredump_backend_cmd_t cmd; }; -void coredump(unsigned int reason, const z_arch_esf_t *esf, +void coredump(unsigned int reason, const struct arch_esf *esf, struct k_thread *thread); void coredump_memory_dump(uintptr_t start_addr, uintptr_t end_addr); void coredump_buffer_output(uint8_t *buf, size_t buflen); @@ -242,7 +242,7 @@ int coredump_cmd(enum coredump_cmd_id cmd_id, void *arg); #else -static inline void coredump(unsigned int reason, const z_arch_esf_t *esf, +static inline void coredump(unsigned int reason, const struct arch_esf *esf, struct k_thread *thread) { ARG_UNUSED(reason); @@ -279,7 +279,7 @@ static inline int coredump_cmd(enum coredump_cmd_id query_id, void *arg) #endif /* CONFIG_DEBUG_COREDUMP */ /** - * @fn void coredump(unsigned int reason, const z_arch_esf_t *esf, struct k_thread *thread); + * @fn void coredump(unsigned int reason, const struct arch_esf *esf, struct k_thread *thread); * @brief Perform coredump. * * Normally, this is called inside z_fatal_error() to generate coredump diff --git a/include/zephyr/fatal.h b/include/zephyr/fatal.h index 2333df91112d0..0fa1e93363ed4 100644 --- a/include/zephyr/fatal.h +++ b/include/zephyr/fatal.h @@ -65,7 +65,7 @@ FUNC_NORETURN void k_fatal_halt(unsigned int reason); * @param esf Exception context, with details and partial or full register * state when the error occurred. May in some cases be NULL. */ -void k_sys_fatal_error_handler(unsigned int reason, const z_arch_esf_t *esf); +void k_sys_fatal_error_handler(unsigned int reason, const struct arch_esf *esf); /** * Called by architecture code upon a fatal error. @@ -81,7 +81,7 @@ void k_sys_fatal_error_handler(unsigned int reason, const z_arch_esf_t *esf); * @param esf Exception context, with details and partial or full register * state when the error occurred. May in some cases be NULL. */ -void z_fatal_error(unsigned int reason, const z_arch_esf_t *esf); +void z_fatal_error(unsigned int reason, const struct arch_esf *esf); /** @} */ diff --git a/kernel/fatal.c b/kernel/fatal.c index caee224bf5f63..06966066e3020 100644 --- a/kernel/fatal.c +++ b/kernel/fatal.c @@ -35,7 +35,7 @@ FUNC_NORETURN __weak void arch_system_halt(unsigned int reason) /* LCOV_EXCL_START */ __weak void k_sys_fatal_error_handler(unsigned int reason, - const z_arch_esf_t *esf) + const struct arch_esf *esf) { ARG_UNUSED(esf); @@ -82,7 +82,7 @@ FUNC_NORETURN void k_fatal_halt(unsigned int reason) } /* LCOV_EXCL_STOP */ -void z_fatal_error(unsigned int reason, const z_arch_esf_t *esf) +void z_fatal_error(unsigned int reason, const struct arch_esf *esf) { /* We can't allow this code to be preempted, but don't need to * synchronize between CPUs, so an arch-layer lock is diff --git a/kernel/include/gen_offset.h b/kernel/include/gen_offset.h index bdc9f785809a6..3cd2d14e336e6 100644 --- a/kernel/include/gen_offset.h +++ b/kernel/include/gen_offset.h @@ -79,6 +79,8 @@ #include #include +typedef struct arch_esf z_arch_esf_t; + /* definition of the GEN_OFFSET_SYM() macros is toolchain independent */ #define GEN_OFFSET_SYM(S, M) \ diff --git a/kernel/include/kernel_arch_interface.h b/kernel/include/kernel_arch_interface.h index 9860070542edf..f12a9d3577b20 100644 --- a/kernel/include/kernel_arch_interface.h +++ b/kernel/include/kernel_arch_interface.h @@ -583,7 +583,7 @@ static inline void arch_nop(void); * * @param esf Exception Stack Frame (arch-specific) */ -void arch_coredump_info_dump(const z_arch_esf_t *esf); +void arch_coredump_info_dump(const struct arch_esf *esf); /** * @brief Get the target code specified by the architecture. diff --git a/samples/bluetooth/hci_ipc/src/main.c b/samples/bluetooth/hci_ipc/src/main.c index 814001646e46c..6e1f275ffd03c 100644 --- a/samples/bluetooth/hci_ipc/src/main.c +++ b/samples/bluetooth/hci_ipc/src/main.c @@ -320,7 +320,7 @@ void bt_ctlr_assert_handle(char *file, uint32_t line) #endif /* CONFIG_BT_CTLR_ASSERT_HANDLER */ #if defined(CONFIG_BT_HCI_VS_FATAL_ERROR) -void k_sys_fatal_error_handler(unsigned int reason, const z_arch_esf_t *esf) +void k_sys_fatal_error_handler(unsigned int reason, const struct arch_esf *esf) { /* Disable interrupts, this is unrecoverable */ (void)irq_lock(); diff --git a/samples/subsys/llext/edk/app/src/main.c b/samples/subsys/llext/edk/app/src/main.c index 502901d59bdd0..78f1a664661a0 100644 --- a/samples/subsys/llext/edk/app/src/main.c +++ b/samples/subsys/llext/edk/app/src/main.c @@ -100,7 +100,7 @@ static void user_function(void *p1, void *p2, void *p3) printk("[app]Thread %p done\n", k_current_get()); } -void k_sys_fatal_error_handler(unsigned int reason, const z_arch_esf_t *esf) +void k_sys_fatal_error_handler(unsigned int reason, const struct arch_esf *esf) { int i; diff --git a/subsys/bluetooth/controller/hci/hci.c b/subsys/bluetooth/controller/hci/hci.c index 0edc10310cb0f..ac7c55613ad1f 100644 --- a/subsys/bluetooth/controller/hci/hci.c +++ b/subsys/bluetooth/controller/hci/hci.c @@ -5001,7 +5001,7 @@ NET_BUF_POOL_FIXED_DEFINE(vs_err_tx_pool, 1, BT_BUF_EVT_RX_SIZE, typedef struct bt_hci_vs_fata_error_cpu_data_cortex_m bt_hci_vs_fatal_error_cpu_data; static void vs_err_fatal_cpu_data_fill(bt_hci_vs_fatal_error_cpu_data *cpu_data, - const z_arch_esf_t *esf) + const struct arch_esf *esf) { cpu_data->a1 = sys_cpu_to_le32(esf->basic.a1); cpu_data->a2 = sys_cpu_to_le32(esf->basic.a2); @@ -5036,7 +5036,7 @@ static struct net_buf *vs_err_evt_create(uint8_t subevt, uint8_t len) return buf; } -struct net_buf *hci_vs_err_stack_frame(unsigned int reason, const z_arch_esf_t *esf) +struct net_buf *hci_vs_err_stack_frame(unsigned int reason, const struct arch_esf *esf) { /* Prepare vendor specific HCI Fatal Error event */ struct bt_hci_vs_fatal_error_stack_frame *sf; diff --git a/subsys/debug/coredump/coredump_core.c b/subsys/debug/coredump/coredump_core.c index 71a3880006a92..e939a81ea29b5 100644 --- a/subsys/debug/coredump/coredump_core.c +++ b/subsys/debug/coredump/coredump_core.c @@ -117,7 +117,7 @@ void process_memory_region_list(void) #endif } -void coredump(unsigned int reason, const z_arch_esf_t *esf, +void coredump(unsigned int reason, const struct arch_esf *esf, struct k_thread *thread) { z_coredump_start(); diff --git a/subsys/testsuite/ztest/include/zephyr/ztest.h b/subsys/testsuite/ztest/include/zephyr/ztest.h index 5dba0afa3367b..1c58b2daec664 100644 --- a/subsys/testsuite/ztest/include/zephyr/ztest.h +++ b/subsys/testsuite/ztest/include/zephyr/ztest.h @@ -29,7 +29,6 @@ extern "C" { #endif struct arch_esf; -typedef struct arch_esf z_arch_esf_t; #ifdef __cplusplus } #endif diff --git a/subsys/testsuite/ztest/include/zephyr/ztest_error_hook.h b/subsys/testsuite/ztest/include/zephyr/ztest_error_hook.h index 5d6ac64a9c1bd..e4a5937d13bd3 100644 --- a/subsys/testsuite/ztest/include/zephyr/ztest_error_hook.h +++ b/subsys/testsuite/ztest/include/zephyr/ztest_error_hook.h @@ -38,7 +38,7 @@ __syscall void ztest_set_fault_valid(bool valid); * By default, it will do nothing before leaving error handler. */ void ztest_post_fatal_error_hook(unsigned int reason, - const z_arch_esf_t *pEsf); + const struct arch_esf *pEsf); #endif diff --git a/subsys/testsuite/ztest/src/ztest_error_hook.c b/subsys/testsuite/ztest/src/ztest_error_hook.c index 6982e96c7c552..e910dc33c3151 100644 --- a/subsys/testsuite/ztest/src/ztest_error_hook.c +++ b/subsys/testsuite/ztest/src/ztest_error_hook.c @@ -42,11 +42,11 @@ static inline void z_vrfy_ztest_set_fault_valid(bool valid) #endif __weak void ztest_post_fatal_error_hook(unsigned int reason, - const z_arch_esf_t *pEsf) + const struct arch_esf *pEsf) { } -void k_sys_fatal_error_handler(unsigned int reason, const z_arch_esf_t *pEsf) +void k_sys_fatal_error_handler(unsigned int reason, const struct arch_esf *pEsf) { k_tid_t curr_tid = k_current_get(); bool valid_fault = (curr_tid == valid_fault_tid) || fault_in_isr; diff --git a/tests/arch/arm/arm_hardfault_validation/src/arm_hardfault.c b/tests/arch/arm/arm_hardfault_validation/src/arm_hardfault.c index 1e7ac1ef71f84..d7b4b509f1721 100644 --- a/tests/arch/arm/arm_hardfault_validation/src/arm_hardfault.c +++ b/tests/arch/arm/arm_hardfault_validation/src/arm_hardfault.c @@ -13,7 +13,7 @@ static volatile int expected_reason = -1; -void k_sys_fatal_error_handler(unsigned int reason, const z_arch_esf_t *pEsf) +void k_sys_fatal_error_handler(unsigned int reason, const struct arch_esf *pEsf) { static bool triggered_synchronous_svc; diff --git a/tests/arch/arm/arm_interrupt/src/arm_interrupt.c b/tests/arch/arm/arm_interrupt/src/arm_interrupt.c index 5494d77d70db3..3891c9b1d41c2 100644 --- a/tests/arch/arm/arm_interrupt/src/arm_interrupt.c +++ b/tests/arch/arm/arm_interrupt/src/arm_interrupt.c @@ -24,7 +24,7 @@ static struct k_thread esf_collection_thread; /** * Validates that pEsf matches state from set_regs_with_known_pattern() */ -static int check_esf_matches_expectations(const z_arch_esf_t *pEsf) +static int check_esf_matches_expectations(const struct arch_esf *pEsf) { const uint16_t expected_fault_instruction = 0xde5a; /* udf #90 */ const bool caller_regs_match_expected = @@ -88,7 +88,7 @@ static int check_esf_matches_expectations(const z_arch_esf_t *pEsf) return 0; } -void k_sys_fatal_error_handler(unsigned int reason, const z_arch_esf_t *pEsf) +void k_sys_fatal_error_handler(unsigned int reason, const struct arch_esf *pEsf) { TC_PRINT("Caught system error -- reason %d\n", reason); diff --git a/tests/arch/arm/arm_no_multithreading/src/main.c b/tests/arch/arm/arm_no_multithreading/src/main.c index a1b5c67a28f43..c9e4cdd02f329 100644 --- a/tests/arch/arm/arm_no_multithreading/src/main.c +++ b/tests/arch/arm/arm_no_multithreading/src/main.c @@ -36,7 +36,7 @@ void arm_isr_handler(const void *args) test_flag++; } -void k_sys_fatal_error_handler(unsigned int reason, const z_arch_esf_t *pEsf) +void k_sys_fatal_error_handler(unsigned int reason, const struct arch_esf *pEsf) { printk("Caught system error -- reason %d\n", reason); diff --git a/tests/arch/x86/nmi/src/main.c b/tests/arch/x86/nmi/src/main.c index 852e949c1150f..55a5bc9973400 100644 --- a/tests/arch/x86/nmi/src/main.c +++ b/tests/arch/x86/nmi/src/main.c @@ -35,7 +35,7 @@ uint8_t *nmi_stacks[] = { #endif }; -bool z_x86_do_kernel_nmi(const z_arch_esf_t *esf) +bool z_x86_do_kernel_nmi(const struct arch_esf *esf) { uint64_t stack; diff --git a/tests/arch/x86/static_idt/src/main.c b/tests/arch/x86/static_idt/src/main.c index 79a25d1886672..b260b0bbe7ed0 100644 --- a/tests/arch/x86/static_idt/src/main.c +++ b/tests/arch/x86/static_idt/src/main.c @@ -47,7 +47,7 @@ static volatile int int_handler_executed; /* Assume the spurious interrupt handler will execute and abort the task */ static volatile int spur_handler_aborted_thread = 1; -void k_sys_fatal_error_handler(unsigned int reason, const z_arch_esf_t *esf) +void k_sys_fatal_error_handler(unsigned int reason, const struct arch_esf *esf) { if (reason != K_ERR_SPURIOUS_IRQ) { printk("wrong error reason\n"); @@ -89,7 +89,7 @@ void isr_handler(void) * */ -void exc_divide_error_handler(z_arch_esf_t *p_esf) +void exc_divide_error_handler(struct arch_esf *p_esf) { p_esf->eip += 2; /* provide evidence that the handler executed */ diff --git a/tests/bluetooth/audio/mocks/src/fatal.c b/tests/bluetooth/audio/mocks/src/fatal.c index f36f518b34573..0793de62267d1 100644 --- a/tests/bluetooth/audio/mocks/src/fatal.c +++ b/tests/bluetooth/audio/mocks/src/fatal.c @@ -7,7 +7,7 @@ #include #include -void z_fatal_error(unsigned int reason, const z_arch_esf_t *esf) +void z_fatal_error(unsigned int reason, const struct arch_esf *esf) { ztest_test_fail(); } diff --git a/tests/drivers/coredump/coredump_api/src/main.c b/tests/drivers/coredump/coredump_api/src/main.c index ddac6d0458527..66797add42b28 100644 --- a/tests/drivers/coredump/coredump_api/src/main.c +++ b/tests/drivers/coredump/coredump_api/src/main.c @@ -32,7 +32,7 @@ static struct coredump_mem_region_node dump_region0 = { .size = sizeof(values_to_dump) }; -void k_sys_fatal_error_handler(unsigned int reason, const z_arch_esf_t *pEsf) +void k_sys_fatal_error_handler(unsigned int reason, const struct arch_esf *pEsf) { ARG_UNUSED(pEsf); diff --git a/tests/kernel/fatal/exception/src/main.c b/tests/kernel/fatal/exception/src/main.c index 8d2cff2b1d9ef..a946d02de7f9e 100644 --- a/tests/kernel/fatal/exception/src/main.c +++ b/tests/kernel/fatal/exception/src/main.c @@ -50,7 +50,7 @@ volatile int rv; static ZTEST_DMEM volatile int expected_reason = -1; -void k_sys_fatal_error_handler(unsigned int reason, const z_arch_esf_t *pEsf) +void k_sys_fatal_error_handler(unsigned int reason, const struct arch_esf *pEsf) { TC_PRINT("Caught system error -- reason %d\n", reason); diff --git a/tests/kernel/fatal/message_capture/src/main.c b/tests/kernel/fatal/message_capture/src/main.c index 820a28216f9f8..514f3ea6e55c9 100644 --- a/tests/kernel/fatal/message_capture/src/main.c +++ b/tests/kernel/fatal/message_capture/src/main.c @@ -12,7 +12,7 @@ static volatile int expected_reason = -1; void z_thread_essential_clear(struct k_thread *thread); -void k_sys_fatal_error_handler(unsigned int reason, const z_arch_esf_t *pEsf) +void k_sys_fatal_error_handler(unsigned int reason, const struct arch_esf *pEsf) { printk("Caught system error -- reason %d\n", reason); diff --git a/tests/kernel/fatal/no-multithreading/src/main.c b/tests/kernel/fatal/no-multithreading/src/main.c index 22f2987c29180..c48ef3d9fd535 100644 --- a/tests/kernel/fatal/no-multithreading/src/main.c +++ b/tests/kernel/fatal/no-multithreading/src/main.c @@ -13,7 +13,7 @@ static ZTEST_DMEM volatile int expected_reason = -1; -void k_sys_fatal_error_handler(unsigned int reason, const z_arch_esf_t *pEsf) +void k_sys_fatal_error_handler(unsigned int reason, const struct arch_esf *pEsf) { int rv = TC_PASS; diff --git a/tests/kernel/mem_protect/demand_paging/src/main.c b/tests/kernel/mem_protect/demand_paging/src/main.c index fab82b68f7da8..5df3442b8f979 100644 --- a/tests/kernel/mem_protect/demand_paging/src/main.c +++ b/tests/kernel/mem_protect/demand_paging/src/main.c @@ -64,7 +64,7 @@ __pinned_bss static bool expect_fault; __pinned_func -void k_sys_fatal_error_handler(unsigned int reason, const z_arch_esf_t *pEsf) +void k_sys_fatal_error_handler(unsigned int reason, const struct arch_esf *pEsf) { printk("Caught system error -- reason %d\n", reason); diff --git a/tests/kernel/mem_protect/mem_map/src/main.c b/tests/kernel/mem_protect/mem_map/src/main.c index 46fa5d4543d51..3bbc1cd6add57 100644 --- a/tests/kernel/mem_protect/mem_map/src/main.c +++ b/tests/kernel/mem_protect/mem_map/src/main.c @@ -33,7 +33,7 @@ volatile bool expect_fault; __pinned_noinit static uint8_t __aligned(CONFIG_MMU_PAGE_SIZE) test_page[TEST_PAGE_SZ]; -void k_sys_fatal_error_handler(unsigned int reason, const z_arch_esf_t *pEsf) +void k_sys_fatal_error_handler(unsigned int reason, const struct arch_esf *pEsf) { printk("Caught system error -- reason %d\n", reason); diff --git a/tests/kernel/mem_protect/mem_protect/src/common.c b/tests/kernel/mem_protect/mem_protect/src/common.c index a0addcbda55b0..93febc8b9a1a4 100644 --- a/tests/kernel/mem_protect/mem_protect/src/common.c +++ b/tests/kernel/mem_protect/mem_protect/src/common.c @@ -8,7 +8,7 @@ ZTEST_BMEM volatile bool valid_fault; -void k_sys_fatal_error_handler(unsigned int reason, const z_arch_esf_t *pEsf) +void k_sys_fatal_error_handler(unsigned int reason, const struct arch_esf *pEsf) { printk("Caught system error -- reason %d %d\n", reason, valid_fault); if (valid_fault) { diff --git a/tests/kernel/mem_protect/protection/src/main.c b/tests/kernel/mem_protect/protection/src/main.c index 2f66edcdb90a9..7c72700d98754 100644 --- a/tests/kernel/mem_protect/protection/src/main.c +++ b/tests/kernel/mem_protect/protection/src/main.c @@ -28,7 +28,7 @@ #define INFO(fmt, ...) printk(fmt, ##__VA_ARGS__) -void k_sys_fatal_error_handler(unsigned int reason, const z_arch_esf_t *pEsf) +void k_sys_fatal_error_handler(unsigned int reason, const struct arch_esf *pEsf) { INFO("Caught system error -- reason %d\n", reason); ztest_test_pass(); diff --git a/tests/kernel/mem_protect/stackprot/src/main.c b/tests/kernel/mem_protect/stackprot/src/main.c index cb927670eaa1f..6ebbe2deb8980 100644 --- a/tests/kernel/mem_protect/stackprot/src/main.c +++ b/tests/kernel/mem_protect/stackprot/src/main.c @@ -15,7 +15,7 @@ ZTEST_BMEM static int count; ZTEST_BMEM static int ret = TC_PASS; -void k_sys_fatal_error_handler(unsigned int reason, const z_arch_esf_t *esf) +void k_sys_fatal_error_handler(unsigned int reason, const struct arch_esf *esf) { if (reason != K_ERR_STACK_CHK_FAIL) { printk("wrong error type\n"); diff --git a/tests/kernel/mem_protect/sys_sem/src/main.c b/tests/kernel/mem_protect/sys_sem/src/main.c index f7bcbfd21d0c4..c5aeeee51fc46 100644 --- a/tests/kernel/mem_protect/sys_sem/src/main.c +++ b/tests/kernel/mem_protect/sys_sem/src/main.c @@ -568,7 +568,7 @@ ZTEST_USER(sys_sem_1cpu, test_sem_multiple_threads_wait) * @} */ -void k_sys_fatal_error_handler(unsigned int reason, const z_arch_esf_t *pEsf) +void k_sys_fatal_error_handler(unsigned int reason, const struct arch_esf *pEsf) { printk("Caught system error -- reason %d\n", reason); printk("Unexpected fault during test\n"); diff --git a/tests/kernel/mem_protect/syscalls/src/main.c b/tests/kernel/mem_protect/syscalls/src/main.c index 7d2b0568f96d0..2f92257f70eeb 100644 --- a/tests/kernel/mem_protect/syscalls/src/main.c +++ b/tests/kernel/mem_protect/syscalls/src/main.c @@ -36,7 +36,7 @@ char kernel_string[BUF_SIZE]; char kernel_buf[BUF_SIZE]; ZTEST_BMEM char user_string[BUF_SIZE]; -void k_sys_fatal_error_handler(unsigned int reason, const z_arch_esf_t *pEsf) +void k_sys_fatal_error_handler(unsigned int reason, const struct arch_esf *pEsf) { printk("Caught system error -- reason %d\n", reason); printk("Unexpected fault during test\n"); diff --git a/tests/kernel/mem_protect/userspace/src/main.c b/tests/kernel/mem_protect/userspace/src/main.c index 98510461e220c..4c88d6e90d54d 100644 --- a/tests/kernel/mem_protect/userspace/src/main.c +++ b/tests/kernel/mem_protect/userspace/src/main.c @@ -76,7 +76,7 @@ static void set_fault(unsigned int reason) compiler_barrier(); } -void k_sys_fatal_error_handler(unsigned int reason, const z_arch_esf_t *pEsf) +void k_sys_fatal_error_handler(unsigned int reason, const struct arch_esf *pEsf) { INFO("Caught system error -- reason %d\n", reason); diff --git a/tests/kernel/mutex/mutex_error_case/src/test_mutex_error.c b/tests/kernel/mutex/mutex_error_case/src/test_mutex_error.c index d1ba055772770..ea4210ff3d129 100644 --- a/tests/kernel/mutex/mutex_error_case/src/test_mutex_error.c +++ b/tests/kernel/mutex/mutex_error_case/src/test_mutex_error.c @@ -38,7 +38,7 @@ extern struct k_sem offload_sem; /* A call back function which is hooked in default assert handler. */ void ztest_post_fatal_error_hook(unsigned int reason, - const z_arch_esf_t *pEsf) + const struct arch_esf *pEsf) { /* check if expected error */ diff --git a/tests/kernel/pipe/pipe/src/test_pipe.c b/tests/kernel/pipe/pipe/src/test_pipe.c index 04d1f7ec14e1d..4ad9ee230a457 100644 --- a/tests/kernel/pipe/pipe/src/test_pipe.c +++ b/tests/kernel/pipe/pipe/src/test_pipe.c @@ -674,7 +674,7 @@ void pipe_put_get_timeout(void) /******************************************************************************/ ZTEST_BMEM bool valid_fault; -void k_sys_fatal_error_handler(unsigned int reason, const z_arch_esf_t *pEsf) +void k_sys_fatal_error_handler(unsigned int reason, const struct arch_esf *pEsf) { printk("Caught system error -- reason %d\n", reason); if (valid_fault) { diff --git a/tests/kernel/smp/src/main.c b/tests/kernel/smp/src/main.c index 776b5b6beb690..f73a1dfdbbb6e 100644 --- a/tests/kernel/smp/src/main.c +++ b/tests/kernel/smp/src/main.c @@ -757,7 +757,7 @@ ZTEST(smp, test_smp_ipi) } #endif -void k_sys_fatal_error_handler(unsigned int reason, const z_arch_esf_t *esf) +void k_sys_fatal_error_handler(unsigned int reason, const struct arch_esf *esf) { static int trigger; diff --git a/tests/kernel/threads/dynamic_thread/src/main.c b/tests/kernel/threads/dynamic_thread/src/main.c index 0fa88caee8cc0..e456e8db13304 100644 --- a/tests/kernel/threads/dynamic_thread/src/main.c +++ b/tests/kernel/threads/dynamic_thread/src/main.c @@ -16,7 +16,7 @@ static K_SEM_DEFINE(end_sem, 0, 1); static ZTEST_BMEM struct k_thread *dyn_thread; static struct k_thread *dynamic_threads[CONFIG_MAX_THREAD_BYTES * 8]; -void k_sys_fatal_error_handler(unsigned int reason, const z_arch_esf_t *esf) +void k_sys_fatal_error_handler(unsigned int reason, const struct arch_esf *esf) { if (reason != K_ERR_KERNEL_OOPS) { printk("wrong error reason\n"); diff --git a/tests/kernel/threads/dynamic_thread_stack/src/main.c b/tests/kernel/threads/dynamic_thread_stack/src/main.c index a833197d36126..cb6fba523cddb 100644 --- a/tests/kernel/threads/dynamic_thread_stack/src/main.c +++ b/tests/kernel/threads/dynamic_thread_stack/src/main.c @@ -179,7 +179,7 @@ static void set_fault(unsigned int reason) compiler_barrier(); } -void k_sys_fatal_error_handler(unsigned int reason, const z_arch_esf_t *pEsf) +void k_sys_fatal_error_handler(unsigned int reason, const struct arch_esf *pEsf) { if (expect_fault) { if (expected_reason == reason) { diff --git a/tests/kernel/threads/thread_apis/src/test_essential_thread.c b/tests/kernel/threads/thread_apis/src/test_essential_thread.c index 1814346932301..082765bd14816 100644 --- a/tests/kernel/threads/thread_apis/src/test_essential_thread.c +++ b/tests/kernel/threads/thread_apis/src/test_essential_thread.c @@ -61,7 +61,7 @@ ZTEST(threads_lifecycle, test_essential_thread_operation) } void k_sys_fatal_error_handler(unsigned int reason, - const z_arch_esf_t *esf) + const struct arch_esf *esf) { ARG_UNUSED(esf); ARG_UNUSED(reason); diff --git a/tests/lib/mem_blocks/src/main.c b/tests/lib/mem_blocks/src/main.c index 4641a6db643ef..52232b007efbf 100644 --- a/tests/lib/mem_blocks/src/main.c +++ b/tests/lib/mem_blocks/src/main.c @@ -25,7 +25,7 @@ static sys_multi_mem_blocks_t alloc_group; static ZTEST_DMEM volatile int expected_reason = -1; -void k_sys_fatal_error_handler(unsigned int reason, const z_arch_esf_t *pEsf) +void k_sys_fatal_error_handler(unsigned int reason, const struct arch_esf *pEsf) { printk("Caught system error -- reason %d\n", reason); diff --git a/tests/subsys/debug/coredump/src/main.c b/tests/subsys/debug/coredump/src/main.c index fac5395971cf6..f97494df1712d 100644 --- a/tests/subsys/debug/coredump/src/main.c +++ b/tests/subsys/debug/coredump/src/main.c @@ -13,7 +13,7 @@ #endif -void k_sys_fatal_error_handler(unsigned int reason, const z_arch_esf_t *pEsf) +void k_sys_fatal_error_handler(unsigned int reason, const struct arch_esf *pEsf) { ARG_UNUSED(pEsf); diff --git a/tests/subsys/debug/coredump_backends/src/main.c b/tests/subsys/debug/coredump_backends/src/main.c index 8b7636edbd9f6..0678bff306207 100644 --- a/tests/subsys/debug/coredump_backends/src/main.c +++ b/tests/subsys/debug/coredump_backends/src/main.c @@ -19,7 +19,7 @@ static struct k_thread dump_thread; static K_THREAD_STACK_DEFINE(dump_stack, STACK_SIZE); -void k_sys_fatal_error_handler(unsigned int reason, const z_arch_esf_t *pEsf) +void k_sys_fatal_error_handler(unsigned int reason, const struct arch_esf *pEsf) { ARG_UNUSED(reason); ARG_UNUSED(pEsf); diff --git a/tests/ztest/error_hook/src/main.c b/tests/ztest/error_hook/src/main.c index dfa998e0075d8..060b856e156d1 100644 --- a/tests/ztest/error_hook/src/main.c +++ b/tests/ztest/error_hook/src/main.c @@ -153,7 +153,7 @@ static void release_offload_sem(void) * default one. */ void ztest_post_fatal_error_hook(unsigned int reason, - const z_arch_esf_t *pEsf) + const struct arch_esf *pEsf) { switch (case_type) { case ZTEST_CATCH_FATAL_ACCESS: From 6a3cb93d88129c58141144d841914c7780e1575f Mon Sep 17 00:00:00 2001 From: Yong Cong Sin Date: Mon, 3 Jun 2024 18:02:05 +0800 Subject: [PATCH 1702/2849] arch: remove the use of `z_arch_esf_t` completely from internal Created `GEN_OFFSET_STRUCT` & `GEN_NAMED_OFFSET_STRUCT` that works for `struct`, and remove the use of `z_arch_esf_t` completely. Signed-off-by: Yong Cong Sin --- arch/mips/core/isr.S | 6 +- arch/mips/core/offsets/offsets.c | 52 ++++++------ arch/nios2/core/exception.S | 78 ++++++++--------- arch/nios2/core/offsets/offsets.c | 38 ++++----- arch/riscv/core/isr.S | 102 +++++++++++------------ arch/riscv/core/offsets/offsets.c | 45 +++++----- arch/sparc/core/fault_trap.S | 24 +++--- arch/sparc/core/offsets/offsets.c | 12 +-- arch/x86/core/ia32/excstub.S | 4 +- arch/x86/core/offsets/ia32_offsets.c | 4 +- kernel/include/gen_offset.h | 8 +- soc/nordic/common/vpr/soc_isr_stacking.h | 12 +-- 12 files changed, 195 insertions(+), 190 deletions(-) diff --git a/arch/mips/core/isr.S b/arch/mips/core/isr.S index 44babb2149be2..86d05d1983356 100644 --- a/arch/mips/core/isr.S +++ b/arch/mips/core/isr.S @@ -14,7 +14,7 @@ #include #include -#define ESF_O(FIELD) __z_arch_esf_t_##FIELD##_OFFSET +#define ESF_O(FIELD) __struct_arch_esf_##FIELD##_OFFSET #define THREAD_O(FIELD) _thread_offset_to_##FIELD /* Convenience macros for loading/storing register states. */ @@ -58,12 +58,12 @@ op v1, ESF_O(v1)(sp) ; #define STORE_CALLER_SAVED() \ - addi sp, sp, -__z_arch_esf_t_SIZEOF ;\ + addi sp, sp, -__struct_arch_esf_SIZEOF ;\ DO_CALLER_SAVED(OP_STOREREG) ; #define LOAD_CALLER_SAVED() \ DO_CALLER_SAVED(OP_LOADREG) ;\ - addi sp, sp, __z_arch_esf_t_SIZEOF ; + addi sp, sp, __struct_arch_esf_SIZEOF ; /* imports */ GTEXT(_Fault) diff --git a/arch/mips/core/offsets/offsets.c b/arch/mips/core/offsets/offsets.c index 24b477e9558ea..c70ce3c39fc7e 100644 --- a/arch/mips/core/offsets/offsets.c +++ b/arch/mips/core/offsets/offsets.c @@ -23,32 +23,32 @@ GEN_OFFSET_SYM(_callee_saved_t, s6); GEN_OFFSET_SYM(_callee_saved_t, s7); GEN_OFFSET_SYM(_callee_saved_t, s8); -GEN_OFFSET_SYM(z_arch_esf_t, ra); -GEN_OFFSET_SYM(z_arch_esf_t, gp); -GEN_OFFSET_SYM(z_arch_esf_t, t0); -GEN_OFFSET_SYM(z_arch_esf_t, t1); -GEN_OFFSET_SYM(z_arch_esf_t, t2); -GEN_OFFSET_SYM(z_arch_esf_t, t3); -GEN_OFFSET_SYM(z_arch_esf_t, t4); -GEN_OFFSET_SYM(z_arch_esf_t, t5); -GEN_OFFSET_SYM(z_arch_esf_t, t6); -GEN_OFFSET_SYM(z_arch_esf_t, t7); -GEN_OFFSET_SYM(z_arch_esf_t, t8); -GEN_OFFSET_SYM(z_arch_esf_t, t9); -GEN_OFFSET_SYM(z_arch_esf_t, a0); -GEN_OFFSET_SYM(z_arch_esf_t, a1); -GEN_OFFSET_SYM(z_arch_esf_t, a2); -GEN_OFFSET_SYM(z_arch_esf_t, a3); -GEN_OFFSET_SYM(z_arch_esf_t, v0); -GEN_OFFSET_SYM(z_arch_esf_t, v1); -GEN_OFFSET_SYM(z_arch_esf_t, at); -GEN_OFFSET_SYM(z_arch_esf_t, epc); -GEN_OFFSET_SYM(z_arch_esf_t, badvaddr); -GEN_OFFSET_SYM(z_arch_esf_t, hi); -GEN_OFFSET_SYM(z_arch_esf_t, lo); -GEN_OFFSET_SYM(z_arch_esf_t, status); -GEN_OFFSET_SYM(z_arch_esf_t, cause); +GEN_OFFSET_STRUCT(arch_esf, ra); +GEN_OFFSET_STRUCT(arch_esf, gp); +GEN_OFFSET_STRUCT(arch_esf, t0); +GEN_OFFSET_STRUCT(arch_esf, t1); +GEN_OFFSET_STRUCT(arch_esf, t2); +GEN_OFFSET_STRUCT(arch_esf, t3); +GEN_OFFSET_STRUCT(arch_esf, t4); +GEN_OFFSET_STRUCT(arch_esf, t5); +GEN_OFFSET_STRUCT(arch_esf, t6); +GEN_OFFSET_STRUCT(arch_esf, t7); +GEN_OFFSET_STRUCT(arch_esf, t8); +GEN_OFFSET_STRUCT(arch_esf, t9); +GEN_OFFSET_STRUCT(arch_esf, a0); +GEN_OFFSET_STRUCT(arch_esf, a1); +GEN_OFFSET_STRUCT(arch_esf, a2); +GEN_OFFSET_STRUCT(arch_esf, a3); +GEN_OFFSET_STRUCT(arch_esf, v0); +GEN_OFFSET_STRUCT(arch_esf, v1); +GEN_OFFSET_STRUCT(arch_esf, at); +GEN_OFFSET_STRUCT(arch_esf, epc); +GEN_OFFSET_STRUCT(arch_esf, badvaddr); +GEN_OFFSET_STRUCT(arch_esf, hi); +GEN_OFFSET_STRUCT(arch_esf, lo); +GEN_OFFSET_STRUCT(arch_esf, status); +GEN_OFFSET_STRUCT(arch_esf, cause); -GEN_ABSOLUTE_SYM(__z_arch_esf_t_SIZEOF, STACK_ROUND_UP(sizeof(z_arch_esf_t))); +GEN_ABSOLUTE_SYM(__struct_arch_esf_SIZEOF, STACK_ROUND_UP(sizeof(struct arch_esf))); GEN_ABS_SYM_END diff --git a/arch/nios2/core/exception.S b/arch/nios2/core/exception.S index 6b003262bb04d..ab2d3463dd437 100644 --- a/arch/nios2/core/exception.S +++ b/arch/nios2/core/exception.S @@ -35,35 +35,35 @@ GTEXT(_offload_routine) */ SECTION_FUNC(exception.entry, _exception) /* Reserve thread stack space for saving context */ - subi sp, sp, __z_arch_esf_t_SIZEOF + subi sp, sp, __struct_arch_esf_SIZEOF /* Preserve all caller-saved registers onto the thread's stack */ - stw ra, __z_arch_esf_t_ra_OFFSET(sp) - stw r1, __z_arch_esf_t_r1_OFFSET(sp) - stw r2, __z_arch_esf_t_r2_OFFSET(sp) - stw r3, __z_arch_esf_t_r3_OFFSET(sp) - stw r4, __z_arch_esf_t_r4_OFFSET(sp) - stw r5, __z_arch_esf_t_r5_OFFSET(sp) - stw r6, __z_arch_esf_t_r6_OFFSET(sp) - stw r7, __z_arch_esf_t_r7_OFFSET(sp) - stw r8, __z_arch_esf_t_r8_OFFSET(sp) - stw r9, __z_arch_esf_t_r9_OFFSET(sp) - stw r10, __z_arch_esf_t_r10_OFFSET(sp) - stw r11, __z_arch_esf_t_r11_OFFSET(sp) - stw r12, __z_arch_esf_t_r12_OFFSET(sp) - stw r13, __z_arch_esf_t_r13_OFFSET(sp) - stw r14, __z_arch_esf_t_r14_OFFSET(sp) - stw r15, __z_arch_esf_t_r15_OFFSET(sp) + stw ra, __struct_arch_esf_ra_OFFSET(sp) + stw r1, __struct_arch_esf_r1_OFFSET(sp) + stw r2, __struct_arch_esf_r2_OFFSET(sp) + stw r3, __struct_arch_esf_r3_OFFSET(sp) + stw r4, __struct_arch_esf_r4_OFFSET(sp) + stw r5, __struct_arch_esf_r5_OFFSET(sp) + stw r6, __struct_arch_esf_r6_OFFSET(sp) + stw r7, __struct_arch_esf_r7_OFFSET(sp) + stw r8, __struct_arch_esf_r8_OFFSET(sp) + stw r9, __struct_arch_esf_r9_OFFSET(sp) + stw r10, __struct_arch_esf_r10_OFFSET(sp) + stw r11, __struct_arch_esf_r11_OFFSET(sp) + stw r12, __struct_arch_esf_r12_OFFSET(sp) + stw r13, __struct_arch_esf_r13_OFFSET(sp) + stw r14, __struct_arch_esf_r14_OFFSET(sp) + stw r15, __struct_arch_esf_r15_OFFSET(sp) /* Store value of estatus control register */ rdctl et, estatus - stw et, __z_arch_esf_t_estatus_OFFSET(sp) + stw et, __struct_arch_esf_estatus_OFFSET(sp) /* ea-4 is the address of the instruction when the exception happened, * put this in the stack frame as well */ addi r15, ea, -4 - stw r15, __z_arch_esf_t_instr_OFFSET(sp) + stw r15, __struct_arch_esf_instr_OFFSET(sp) /* Figure out whether we are here because of an interrupt or an * exception. If an interrupt, switch stacks and enter IRQ handling @@ -157,7 +157,7 @@ not_interrupt: * * We earlier put ea - 4 in the stack frame, replace it with just ea */ - stw ea, __z_arch_esf_t_instr_OFFSET(sp) + stw ea, __struct_arch_esf_instr_OFFSET(sp) #ifdef CONFIG_IRQ_OFFLOAD /* Check the contents of _offload_routine. If non-NULL, jump into @@ -193,35 +193,35 @@ _exception_exit: * and return to the interrupted context */ /* Return address from the exception */ - ldw ea, __z_arch_esf_t_instr_OFFSET(sp) + ldw ea, __struct_arch_esf_instr_OFFSET(sp) /* Restore estatus * XXX is this right??? */ - ldw r5, __z_arch_esf_t_estatus_OFFSET(sp) + ldw r5, __struct_arch_esf_estatus_OFFSET(sp) wrctl estatus, r5 /* Restore caller-saved registers */ - ldw ra, __z_arch_esf_t_ra_OFFSET(sp) - ldw r1, __z_arch_esf_t_r1_OFFSET(sp) - ldw r2, __z_arch_esf_t_r2_OFFSET(sp) - ldw r3, __z_arch_esf_t_r3_OFFSET(sp) - ldw r4, __z_arch_esf_t_r4_OFFSET(sp) - ldw r5, __z_arch_esf_t_r5_OFFSET(sp) - ldw r6, __z_arch_esf_t_r6_OFFSET(sp) - ldw r7, __z_arch_esf_t_r7_OFFSET(sp) - ldw r8, __z_arch_esf_t_r8_OFFSET(sp) - ldw r9, __z_arch_esf_t_r9_OFFSET(sp) - ldw r10, __z_arch_esf_t_r10_OFFSET(sp) - ldw r11, __z_arch_esf_t_r11_OFFSET(sp) - ldw r12, __z_arch_esf_t_r12_OFFSET(sp) - ldw r13, __z_arch_esf_t_r13_OFFSET(sp) - ldw r14, __z_arch_esf_t_r14_OFFSET(sp) - ldw r15, __z_arch_esf_t_r15_OFFSET(sp) + ldw ra, __struct_arch_esf_ra_OFFSET(sp) + ldw r1, __struct_arch_esf_r1_OFFSET(sp) + ldw r2, __struct_arch_esf_r2_OFFSET(sp) + ldw r3, __struct_arch_esf_r3_OFFSET(sp) + ldw r4, __struct_arch_esf_r4_OFFSET(sp) + ldw r5, __struct_arch_esf_r5_OFFSET(sp) + ldw r6, __struct_arch_esf_r6_OFFSET(sp) + ldw r7, __struct_arch_esf_r7_OFFSET(sp) + ldw r8, __struct_arch_esf_r8_OFFSET(sp) + ldw r9, __struct_arch_esf_r9_OFFSET(sp) + ldw r10, __struct_arch_esf_r10_OFFSET(sp) + ldw r11, __struct_arch_esf_r11_OFFSET(sp) + ldw r12, __struct_arch_esf_r12_OFFSET(sp) + ldw r13, __struct_arch_esf_r13_OFFSET(sp) + ldw r14, __struct_arch_esf_r14_OFFSET(sp) + ldw r15, __struct_arch_esf_r15_OFFSET(sp) /* Put the stack pointer back where it was when we entered * exception state */ - addi sp, sp, __z_arch_esf_t_SIZEOF + addi sp, sp, __struct_arch_esf_SIZEOF /* All done, copy estatus into status and transfer to ea */ eret diff --git a/arch/nios2/core/offsets/offsets.c b/arch/nios2/core/offsets/offsets.c index 8f3b3f748c1a1..9d381d87446c1 100644 --- a/arch/nios2/core/offsets/offsets.c +++ b/arch/nios2/core/offsets/offsets.c @@ -44,24 +44,24 @@ GEN_OFFSET_SYM(_callee_saved_t, sp); GEN_OFFSET_SYM(_callee_saved_t, key); GEN_OFFSET_SYM(_callee_saved_t, retval); -GEN_OFFSET_SYM(z_arch_esf_t, ra); -GEN_OFFSET_SYM(z_arch_esf_t, r1); -GEN_OFFSET_SYM(z_arch_esf_t, r2); -GEN_OFFSET_SYM(z_arch_esf_t, r3); -GEN_OFFSET_SYM(z_arch_esf_t, r4); -GEN_OFFSET_SYM(z_arch_esf_t, r5); -GEN_OFFSET_SYM(z_arch_esf_t, r6); -GEN_OFFSET_SYM(z_arch_esf_t, r7); -GEN_OFFSET_SYM(z_arch_esf_t, r8); -GEN_OFFSET_SYM(z_arch_esf_t, r9); -GEN_OFFSET_SYM(z_arch_esf_t, r10); -GEN_OFFSET_SYM(z_arch_esf_t, r11); -GEN_OFFSET_SYM(z_arch_esf_t, r12); -GEN_OFFSET_SYM(z_arch_esf_t, r13); -GEN_OFFSET_SYM(z_arch_esf_t, r14); -GEN_OFFSET_SYM(z_arch_esf_t, r15); -GEN_OFFSET_SYM(z_arch_esf_t, estatus); -GEN_OFFSET_SYM(z_arch_esf_t, instr); -GEN_ABSOLUTE_SYM(__z_arch_esf_t_SIZEOF, sizeof(z_arch_esf_t)); +GEN_OFFSET_STRUCT(arch_esf, ra); +GEN_OFFSET_STRUCT(arch_esf, r1); +GEN_OFFSET_STRUCT(arch_esf, r2); +GEN_OFFSET_STRUCT(arch_esf, r3); +GEN_OFFSET_STRUCT(arch_esf, r4); +GEN_OFFSET_STRUCT(arch_esf, r5); +GEN_OFFSET_STRUCT(arch_esf, r6); +GEN_OFFSET_STRUCT(arch_esf, r7); +GEN_OFFSET_STRUCT(arch_esf, r8); +GEN_OFFSET_STRUCT(arch_esf, r9); +GEN_OFFSET_STRUCT(arch_esf, r10); +GEN_OFFSET_STRUCT(arch_esf, r11); +GEN_OFFSET_STRUCT(arch_esf, r12); +GEN_OFFSET_STRUCT(arch_esf, r13); +GEN_OFFSET_STRUCT(arch_esf, r14); +GEN_OFFSET_STRUCT(arch_esf, r15); +GEN_OFFSET_STRUCT(arch_esf, estatus); +GEN_OFFSET_STRUCT(arch_esf, instr); +GEN_ABSOLUTE_SYM(__struct_arch_esf_SIZEOF, sizeof(struct arch_esf)); GEN_ABS_SYM_END diff --git a/arch/riscv/core/isr.S b/arch/riscv/core/isr.S index e9a3d523127a4..8a829fd66b17f 100644 --- a/arch/riscv/core/isr.S +++ b/arch/riscv/core/isr.S @@ -24,22 +24,22 @@ /* Convenience macro for loading/storing register states. */ #define DO_CALLER_SAVED(op) \ - RV_E( op t0, __z_arch_esf_t_t0_OFFSET(sp) );\ - RV_E( op t1, __z_arch_esf_t_t1_OFFSET(sp) );\ - RV_E( op t2, __z_arch_esf_t_t2_OFFSET(sp) );\ - RV_I( op t3, __z_arch_esf_t_t3_OFFSET(sp) );\ - RV_I( op t4, __z_arch_esf_t_t4_OFFSET(sp) );\ - RV_I( op t5, __z_arch_esf_t_t5_OFFSET(sp) );\ - RV_I( op t6, __z_arch_esf_t_t6_OFFSET(sp) );\ - RV_E( op a0, __z_arch_esf_t_a0_OFFSET(sp) );\ - RV_E( op a1, __z_arch_esf_t_a1_OFFSET(sp) );\ - RV_E( op a2, __z_arch_esf_t_a2_OFFSET(sp) );\ - RV_E( op a3, __z_arch_esf_t_a3_OFFSET(sp) );\ - RV_E( op a4, __z_arch_esf_t_a4_OFFSET(sp) );\ - RV_E( op a5, __z_arch_esf_t_a5_OFFSET(sp) );\ - RV_I( op a6, __z_arch_esf_t_a6_OFFSET(sp) );\ - RV_I( op a7, __z_arch_esf_t_a7_OFFSET(sp) );\ - RV_E( op ra, __z_arch_esf_t_ra_OFFSET(sp) ) + RV_E( op t0, __struct_arch_esf_t0_OFFSET(sp) );\ + RV_E( op t1, __struct_arch_esf_t1_OFFSET(sp) );\ + RV_E( op t2, __struct_arch_esf_t2_OFFSET(sp) );\ + RV_I( op t3, __struct_arch_esf_t3_OFFSET(sp) );\ + RV_I( op t4, __struct_arch_esf_t4_OFFSET(sp) );\ + RV_I( op t5, __struct_arch_esf_t5_OFFSET(sp) );\ + RV_I( op t6, __struct_arch_esf_t6_OFFSET(sp) );\ + RV_E( op a0, __struct_arch_esf_a0_OFFSET(sp) );\ + RV_E( op a1, __struct_arch_esf_a1_OFFSET(sp) );\ + RV_E( op a2, __struct_arch_esf_a2_OFFSET(sp) );\ + RV_E( op a3, __struct_arch_esf_a3_OFFSET(sp) );\ + RV_E( op a4, __struct_arch_esf_a4_OFFSET(sp) );\ + RV_E( op a5, __struct_arch_esf_a5_OFFSET(sp) );\ + RV_I( op a6, __struct_arch_esf_a6_OFFSET(sp) );\ + RV_I( op a7, __struct_arch_esf_a7_OFFSET(sp) );\ + RV_E( op ra, __struct_arch_esf_ra_OFFSET(sp) ) #ifdef CONFIG_EXCEPTION_DEBUG /* Convenience macro for storing callee saved register [s0 - s11] states. */ @@ -157,7 +157,7 @@ SECTION_FUNC(exception.entry, _isr_wrapper) /* Save user stack value. Coming from user space, we know this * can't overflow the privileged stack. The esf will be allocated * later but it is safe to store our saved user sp here. */ - sr t0, (-__z_arch_esf_t_SIZEOF + __z_arch_esf_t_sp_OFFSET)(sp) + sr t0, (-__struct_arch_esf_SIZEOF + __struct_arch_esf_sp_OFFSET)(sp) /* Make sure tls pointer is sane */ lr t0, ___cpu_t_current_OFFSET(s0) @@ -180,21 +180,21 @@ SECTION_FUNC(exception.entry, _isr_wrapper) SOC_ISR_SW_STACKING #else /* Save caller-saved registers on current thread stack. */ - addi sp, sp, -__z_arch_esf_t_SIZEOF + addi sp, sp, -__struct_arch_esf_SIZEOF DO_CALLER_SAVED(sr) ; #endif /* CONFIG_RISCV_SOC_HAS_ISR_STACKING */ /* Save s0 in the esf and load it with &_current_cpu. */ - sr s0, __z_arch_esf_t_s0_OFFSET(sp) + sr s0, __struct_arch_esf_s0_OFFSET(sp) get_current_cpu s0 /* Save MEPC register */ csrr t0, mepc - sr t0, __z_arch_esf_t_mepc_OFFSET(sp) + sr t0, __struct_arch_esf_mepc_OFFSET(sp) /* Save MSTATUS register */ csrr t2, mstatus - sr t2, __z_arch_esf_t_mstatus_OFFSET(sp) + sr t2, __struct_arch_esf_mstatus_OFFSET(sp) #if defined(CONFIG_FPU_SHARING) /* determine if FPU access was disabled */ @@ -301,7 +301,7 @@ no_fp: /* increment _current->arch.exception_depth */ #ifdef CONFIG_RISCV_SOC_CONTEXT_SAVE /* Handle context saving at SOC level. */ - addi a0, sp, __z_arch_esf_t_soc_context_OFFSET + addi a0, sp, __struct_arch_esf_soc_context_OFFSET jal ra, __soc_save_context #endif /* CONFIG_RISCV_SOC_CONTEXT_SAVE */ @@ -351,7 +351,7 @@ no_fp: /* increment _current->arch.exception_depth */ /* * Call _Fault to handle exception. - * Stack pointer is pointing to a z_arch_esf_t structure, pass it + * Stack pointer is pointing to a struct_arch_esf structure, pass it * to _Fault (via register a0). * If _Fault shall return, set return address to * no_reschedule to restore stack. @@ -370,9 +370,9 @@ is_kernel_syscall: * It's safe to always increment by 4, even with compressed * instructions, because the ecall instruction is always 4 bytes. */ - lr t0, __z_arch_esf_t_mepc_OFFSET(sp) + lr t0, __struct_arch_esf_mepc_OFFSET(sp) addi t0, t0, 4 - sr t0, __z_arch_esf_t_mepc_OFFSET(sp) + sr t0, __struct_arch_esf_mepc_OFFSET(sp) #ifdef CONFIG_PMP_STACK_GUARD /* Re-activate PMP for m-mode */ @@ -383,7 +383,7 @@ is_kernel_syscall: #endif /* Determine what to do. Operation code is in t0. */ - lr t0, __z_arch_esf_t_t0_OFFSET(sp) + lr t0, __struct_arch_esf_t0_OFFSET(sp) .if RV_ECALL_RUNTIME_EXCEPT != 0; .err; .endif beqz t0, do_fault @@ -396,8 +396,8 @@ is_kernel_syscall: #ifdef CONFIG_RISCV_ALWAYS_SWITCH_THROUGH_ECALL li t1, RV_ECALL_SCHEDULE bne t0, t1, skip_schedule - lr a0, __z_arch_esf_t_a0_OFFSET(sp) - lr a1, __z_arch_esf_t_a1_OFFSET(sp) + lr a0, __struct_arch_esf_a0_OFFSET(sp) + lr a1, __struct_arch_esf_a1_OFFSET(sp) j reschedule skip_schedule: #endif @@ -408,7 +408,7 @@ skip_schedule: do_fault: /* Handle RV_ECALL_RUNTIME_EXCEPT. Retrieve reason in a0, esf in A1. */ - lr a0, __z_arch_esf_t_a0_OFFSET(sp) + lr a0, __struct_arch_esf_a0_OFFSET(sp) 1: mv a1, sp #ifdef CONFIG_EXCEPTION_DEBUG @@ -431,8 +431,8 @@ do_irq_offload: * Routine pointer is in saved a0, argument in saved a1 * so we load them with a1/a0 (reversed). */ - lr a1, __z_arch_esf_t_a0_OFFSET(sp) - lr a0, __z_arch_esf_t_a1_OFFSET(sp) + lr a1, __struct_arch_esf_a0_OFFSET(sp) + lr a0, __struct_arch_esf_a1_OFFSET(sp) /* Increment _current_cpu->nested */ lw t1, ___cpu_t_nested_OFFSET(s0) @@ -474,18 +474,18 @@ is_user_syscall: * Same as for is_kernel_syscall: increment saved MEPC by 4 to * prevent triggering the same ecall again upon exiting the ISR. */ - lr t1, __z_arch_esf_t_mepc_OFFSET(sp) + lr t1, __struct_arch_esf_mepc_OFFSET(sp) addi t1, t1, 4 - sr t1, __z_arch_esf_t_mepc_OFFSET(sp) + sr t1, __struct_arch_esf_mepc_OFFSET(sp) /* Restore argument registers from user stack */ - lr a0, __z_arch_esf_t_a0_OFFSET(sp) - lr a1, __z_arch_esf_t_a1_OFFSET(sp) - lr a2, __z_arch_esf_t_a2_OFFSET(sp) - lr a3, __z_arch_esf_t_a3_OFFSET(sp) - lr a4, __z_arch_esf_t_a4_OFFSET(sp) - lr a5, __z_arch_esf_t_a5_OFFSET(sp) - lr t0, __z_arch_esf_t_t0_OFFSET(sp) + lr a0, __struct_arch_esf_a0_OFFSET(sp) + lr a1, __struct_arch_esf_a1_OFFSET(sp) + lr a2, __struct_arch_esf_a2_OFFSET(sp) + lr a3, __struct_arch_esf_a3_OFFSET(sp) + lr a4, __struct_arch_esf_a4_OFFSET(sp) + lr a5, __struct_arch_esf_a5_OFFSET(sp) + lr t0, __struct_arch_esf_t0_OFFSET(sp) #if defined(CONFIG_RISCV_ISA_RV32E) /* Stack alignment for RV32E is 4 bytes */ addi sp, sp, -4 @@ -519,7 +519,7 @@ valid_syscall_id: #endif /* CONFIG_RISCV_ISA_RV32E */ /* Update a0 (return value) on the stack */ - sr a0, __z_arch_esf_t_a0_OFFSET(sp) + sr a0, __struct_arch_esf_a0_OFFSET(sp) /* Disable IRQs again before leaving */ csrc mstatus, MSTATUS_IEN @@ -534,7 +534,7 @@ is_interrupt: * If we came from userspace then we need to reconfigure the * PMP for kernel mode stack guard. */ - lr t0, __z_arch_esf_t_mstatus_OFFSET(sp) + lr t0, __struct_arch_esf_mstatus_OFFSET(sp) li t1, MSTATUS_MPP and t0, t0, t1 bnez t0, 1f @@ -665,7 +665,7 @@ no_reschedule: #ifdef CONFIG_RISCV_SOC_CONTEXT_SAVE /* Restore context at SOC level */ - addi a0, sp, __z_arch_esf_t_soc_context_OFFSET + addi a0, sp, __struct_arch_esf_soc_context_OFFSET jal ra, __soc_restore_context #endif /* CONFIG_RISCV_SOC_CONTEXT_SAVE */ @@ -683,8 +683,8 @@ fp_trap_exit: #endif /* Restore MEPC and MSTATUS registers */ - lr t0, __z_arch_esf_t_mepc_OFFSET(sp) - lr t2, __z_arch_esf_t_mstatus_OFFSET(sp) + lr t0, __struct_arch_esf_mepc_OFFSET(sp) + lr t2, __struct_arch_esf_mstatus_OFFSET(sp) csrw mepc, t0 csrw mstatus, t2 @@ -711,7 +711,7 @@ fp_trap_exit: sb t1, %tprel_lo(is_user_mode)(t0) /* preserve stack pointer for next exception entry */ - add t0, sp, __z_arch_esf_t_SIZEOF + add t0, sp, __struct_arch_esf_SIZEOF sr t0, _curr_cpu_arch_user_exc_sp(s0) j 2f @@ -720,13 +720,13 @@ fp_trap_exit: * We are returning to kernel mode. Store the stack pointer to * be re-loaded further down. */ - addi t0, sp, __z_arch_esf_t_SIZEOF - sr t0, __z_arch_esf_t_sp_OFFSET(sp) + addi t0, sp, __struct_arch_esf_SIZEOF + sr t0, __struct_arch_esf_sp_OFFSET(sp) 2: #endif /* Restore s0 (it is no longer ours) */ - lr s0, __z_arch_esf_t_s0_OFFSET(sp) + lr s0, __struct_arch_esf_s0_OFFSET(sp) #ifdef CONFIG_RISCV_SOC_HAS_ISR_STACKING SOC_ISR_SW_UNSTACKING @@ -736,10 +736,10 @@ fp_trap_exit: #ifdef CONFIG_USERSPACE /* retrieve saved stack pointer */ - lr sp, __z_arch_esf_t_sp_OFFSET(sp) + lr sp, __struct_arch_esf_sp_OFFSET(sp) #else /* remove esf from the stack */ - addi sp, sp, __z_arch_esf_t_SIZEOF + addi sp, sp, __struct_arch_esf_SIZEOF #endif #endif /* CONFIG_RISCV_SOC_HAS_ISR_STACKING */ diff --git a/arch/riscv/core/offsets/offsets.c b/arch/riscv/core/offsets/offsets.c index 9bc9306c2e9d1..7b2d55953b29b 100644 --- a/arch/riscv/core/offsets/offsets.c +++ b/arch/riscv/core/offsets/offsets.c @@ -13,6 +13,7 @@ * structures. */ +#include #include #include #include @@ -88,43 +89,43 @@ GEN_OFFSET_SYM(_thread_arch_t, exception_depth); #endif /* CONFIG_FPU_SHARING */ /* esf member offsets */ -GEN_OFFSET_SYM(z_arch_esf_t, ra); -GEN_OFFSET_SYM(z_arch_esf_t, t0); -GEN_OFFSET_SYM(z_arch_esf_t, t1); -GEN_OFFSET_SYM(z_arch_esf_t, t2); -GEN_OFFSET_SYM(z_arch_esf_t, a0); -GEN_OFFSET_SYM(z_arch_esf_t, a1); -GEN_OFFSET_SYM(z_arch_esf_t, a2); -GEN_OFFSET_SYM(z_arch_esf_t, a3); -GEN_OFFSET_SYM(z_arch_esf_t, a4); -GEN_OFFSET_SYM(z_arch_esf_t, a5); +GEN_OFFSET_STRUCT(arch_esf, ra); +GEN_OFFSET_STRUCT(arch_esf, t0); +GEN_OFFSET_STRUCT(arch_esf, t1); +GEN_OFFSET_STRUCT(arch_esf, t2); +GEN_OFFSET_STRUCT(arch_esf, a0); +GEN_OFFSET_STRUCT(arch_esf, a1); +GEN_OFFSET_STRUCT(arch_esf, a2); +GEN_OFFSET_STRUCT(arch_esf, a3); +GEN_OFFSET_STRUCT(arch_esf, a4); +GEN_OFFSET_STRUCT(arch_esf, a5); #if !defined(CONFIG_RISCV_ISA_RV32E) -GEN_OFFSET_SYM(z_arch_esf_t, t3); -GEN_OFFSET_SYM(z_arch_esf_t, t4); -GEN_OFFSET_SYM(z_arch_esf_t, t5); -GEN_OFFSET_SYM(z_arch_esf_t, t6); -GEN_OFFSET_SYM(z_arch_esf_t, a6); -GEN_OFFSET_SYM(z_arch_esf_t, a7); +GEN_OFFSET_STRUCT(arch_esf, t3); +GEN_OFFSET_STRUCT(arch_esf, t4); +GEN_OFFSET_STRUCT(arch_esf, t5); +GEN_OFFSET_STRUCT(arch_esf, t6); +GEN_OFFSET_STRUCT(arch_esf, a6); +GEN_OFFSET_STRUCT(arch_esf, a7); #endif /* !CONFIG_RISCV_ISA_RV32E */ -GEN_OFFSET_SYM(z_arch_esf_t, mepc); -GEN_OFFSET_SYM(z_arch_esf_t, mstatus); +GEN_OFFSET_STRUCT(arch_esf, mepc); +GEN_OFFSET_STRUCT(arch_esf, mstatus); -GEN_OFFSET_SYM(z_arch_esf_t, s0); +GEN_OFFSET_STRUCT(arch_esf, s0); #ifdef CONFIG_USERSPACE -GEN_OFFSET_SYM(z_arch_esf_t, sp); +GEN_OFFSET_STRUCT(arch_esf, sp); #endif #if defined(CONFIG_RISCV_SOC_CONTEXT_SAVE) -GEN_OFFSET_SYM(z_arch_esf_t, soc_context); +GEN_OFFSET_STRUCT(arch_esf, soc_context); #endif #if defined(CONFIG_RISCV_SOC_OFFSETS) GEN_SOC_OFFSET_SYMS(); #endif -GEN_ABSOLUTE_SYM(__z_arch_esf_t_SIZEOF, sizeof(z_arch_esf_t)); +GEN_ABSOLUTE_SYM(__struct_arch_esf_SIZEOF, sizeof(struct arch_esf)); #ifdef CONFIG_EXCEPTION_DEBUG GEN_ABSOLUTE_SYM(__callee_saved_t_SIZEOF, ROUND_UP(sizeof(_callee_saved_t), ARCH_STACK_PTR_ALIGN)); diff --git a/arch/sparc/core/fault_trap.S b/arch/sparc/core/fault_trap.S index c1a8977ba233c..53b3d9f0b98cd 100644 --- a/arch/sparc/core/fault_trap.S +++ b/arch/sparc/core/fault_trap.S @@ -72,7 +72,7 @@ SECTION_FUNC(TEXT, __sparc_trap_except_reason) mov %l5, %g3 /* Allocate an ABI stack frame and exception stack frame */ - sub %fp, 96 + __z_arch_esf_t_SIZEOF, %sp + sub %fp, 96 + __struct_arch_esf_SIZEOF, %sp /* * %fp: %sp of interrupted task * %sp: %sp of interrupted task - ABI_frame - esf @@ -81,19 +81,19 @@ SECTION_FUNC(TEXT, __sparc_trap_except_reason) mov %l7, %o0 /* Fill in the content of the exception stack frame */ #if defined(CONFIG_EXTRA_EXCEPTION_INFO) - std %i0, [%sp + 96 + __z_arch_esf_t_out_OFFSET + 0x00] - std %i2, [%sp + 96 + __z_arch_esf_t_out_OFFSET + 0x08] - std %i4, [%sp + 96 + __z_arch_esf_t_out_OFFSET + 0x10] - std %i6, [%sp + 96 + __z_arch_esf_t_out_OFFSET + 0x18] - std %g0, [%sp + 96 + __z_arch_esf_t_global_OFFSET + 0x00] - std %g2, [%sp + 96 + __z_arch_esf_t_global_OFFSET + 0x08] - std %g4, [%sp + 96 + __z_arch_esf_t_global_OFFSET + 0x10] - std %g6, [%sp + 96 + __z_arch_esf_t_global_OFFSET + 0x18] + std %i0, [%sp + 96 + __struct_arch_esf_out_OFFSET + 0x00] + std %i2, [%sp + 96 + __struct_arch_esf_out_OFFSET + 0x08] + std %i4, [%sp + 96 + __struct_arch_esf_out_OFFSET + 0x10] + std %i6, [%sp + 96 + __struct_arch_esf_out_OFFSET + 0x18] + std %g0, [%sp + 96 + __struct_arch_esf_global_OFFSET + 0x00] + std %g2, [%sp + 96 + __struct_arch_esf_global_OFFSET + 0x08] + std %g4, [%sp + 96 + __struct_arch_esf_global_OFFSET + 0x10] + std %g6, [%sp + 96 + __struct_arch_esf_global_OFFSET + 0x18] #endif - std %l0, [%sp + 96 + __z_arch_esf_t_psr_OFFSET] /* psr pc */ - std %l2, [%sp + 96 + __z_arch_esf_t_npc_OFFSET] /* npc wim */ + std %l0, [%sp + 96 + __struct_arch_esf_psr_OFFSET] /* psr pc */ + std %l2, [%sp + 96 + __struct_arch_esf_npc_OFFSET] /* npc wim */ rd %y, %l7 - std %l6, [%sp + 96 + __z_arch_esf_t_tbr_OFFSET] /* tbr y */ + std %l6, [%sp + 96 + __struct_arch_esf_tbr_OFFSET] /* tbr y */ /* Enable traps, raise PIL to mask all maskable interrupts. */ or %l0, PSR_PIL, %o2 diff --git a/arch/sparc/core/offsets/offsets.c b/arch/sparc/core/offsets/offsets.c index 3796117ac0945..023ef7452c443 100644 --- a/arch/sparc/core/offsets/offsets.c +++ b/arch/sparc/core/offsets/offsets.c @@ -31,11 +31,11 @@ GEN_OFFSET_SYM(_callee_saved_t, i6); GEN_OFFSET_SYM(_callee_saved_t, o6); /* esf member offsets */ -GEN_OFFSET_SYM(z_arch_esf_t, out); -GEN_OFFSET_SYM(z_arch_esf_t, global); -GEN_OFFSET_SYM(z_arch_esf_t, npc); -GEN_OFFSET_SYM(z_arch_esf_t, psr); -GEN_OFFSET_SYM(z_arch_esf_t, tbr); -GEN_ABSOLUTE_SYM(__z_arch_esf_t_SIZEOF, STACK_ROUND_UP(sizeof(z_arch_esf_t))); +GEN_OFFSET_STRUCT(arch_esf, out); +GEN_OFFSET_STRUCT(arch_esf, global); +GEN_OFFSET_STRUCT(arch_esf, npc); +GEN_OFFSET_STRUCT(arch_esf, psr); +GEN_OFFSET_STRUCT(arch_esf, tbr); +GEN_ABSOLUTE_SYM(__struct_arch_esf_SIZEOF, sizeof(struct arch_esf)); GEN_ABS_SYM_END diff --git a/arch/x86/core/ia32/excstub.S b/arch/x86/core/ia32/excstub.S index 9c5f3f0319152..6c0a13a37cde3 100644 --- a/arch/x86/core/ia32/excstub.S +++ b/arch/x86/core/ia32/excstub.S @@ -161,12 +161,12 @@ SECTION_FUNC(PINNED_TEXT, _exception_enter) /* ESP is still pointing to the ESF at this point */ - testl $0x200, __z_arch_esf_t_eflags_OFFSET(%esp) + testl $0x200, __struct_arch_esf_eflags_OFFSET(%esp) je allDone sti allDone: - pushl %esp /* push z_arch_esf_t * parameter */ + pushl %esp /* push struct_arch_esf * parameter */ call *%ecx /* call exception handler */ addl $0x4, %esp diff --git a/arch/x86/core/offsets/ia32_offsets.c b/arch/x86/core/offsets/ia32_offsets.c index 747ca235831ff..2dfbb5c38ef28 100644 --- a/arch/x86/core/offsets/ia32_offsets.c +++ b/arch/x86/core/offsets/ia32_offsets.c @@ -52,6 +52,6 @@ GEN_ABSOLUTE_SYM(_K_THREAD_NO_FLOAT_SIZEOF, GEN_OFFSET_SYM(_callee_saved_t, esp); -/* z_arch_esf_t structure member offsets */ -GEN_OFFSET_SYM(z_arch_esf_t, eflags); +/* struct arch_esf structure member offsets */ +GEN_OFFSET_STRUCT(arch_esf, eflags); #endif /* _X86_OFFSETS_INC_ */ diff --git a/kernel/include/gen_offset.h b/kernel/include/gen_offset.h index 3cd2d14e336e6..46a651cf28da7 100644 --- a/kernel/include/gen_offset.h +++ b/kernel/include/gen_offset.h @@ -79,14 +79,18 @@ #include #include -typedef struct arch_esf z_arch_esf_t; - /* definition of the GEN_OFFSET_SYM() macros is toolchain independent */ #define GEN_OFFSET_SYM(S, M) \ GEN_ABSOLUTE_SYM(__##S##_##M##_##OFFSET, offsetof(S, M)) +#define GEN_OFFSET_STRUCT(S, M) \ + GEN_ABSOLUTE_SYM(__struct_##S##_##M##_##OFFSET, offsetof(struct S, M)) + #define GEN_NAMED_OFFSET_SYM(S, M, N) \ GEN_ABSOLUTE_SYM(__##S##_##N##_##OFFSET, offsetof(S, M)) +#define GEN_NAMED_OFFSET_STRUCT(S, M, N) \ + GEN_ABSOLUTE_SYM(__struct_##S##_##N##_##OFFSET, offsetof(struct S, M)) + #endif /* ZEPHYR_KERNEL_INCLUDE_GEN_OFFSET_H_ */ diff --git a/soc/nordic/common/vpr/soc_isr_stacking.h b/soc/nordic/common/vpr/soc_isr_stacking.h index da4dffc4b8cb1..8d2f64ad7291f 100644 --- a/soc/nordic/common/vpr/soc_isr_stacking.h +++ b/soc/nordic/common/vpr/soc_isr_stacking.h @@ -73,7 +73,7 @@ /* * Size of the SW managed part of the ESF in case of exception */ -#define ESF_SW_EXC_SIZEOF (__z_arch_esf_t_SIZEOF - ESF_HW_SIZEOF) +#define ESF_SW_EXC_SIZEOF (__struct_arch_esf_SIZEOF - ESF_HW_SIZEOF) /* * Size of the SW managed part of the ESF in case of interrupt @@ -90,17 +90,17 @@ #define MEPC_SP_ALIGN_BIT_MASK (0x1UL) #define STORE_SP_ALIGN_BIT_FROM_MEPC \ - addi t1, sp, __z_arch_esf_t_soc_context_OFFSET; \ - lr t0, __z_arch_esf_t_mepc_OFFSET(sp); \ + addi t1, sp, __struct_arch_esf_soc_context_OFFSET; \ + lr t0, __struct_arch_esf_mepc_OFFSET(sp); \ andi t0, t0, MEPC_SP_ALIGN_BIT_MASK; \ sr t0, __soc_esf_t_sp_align_OFFSET(t1) #define RESTORE_SP_ALIGN_BIT_TO_MEPC \ - addi t1, sp, __z_arch_esf_t_soc_context_OFFSET; \ + addi t1, sp, __struct_arch_esf_soc_context_OFFSET; \ lr t0, __soc_esf_t_sp_align_OFFSET(t1); \ - lr t1, __z_arch_esf_t_mepc_OFFSET(sp); \ + lr t1, __struct_arch_esf_mepc_OFFSET(sp); \ or t2, t1, t0; \ - sr t2, __z_arch_esf_t_mepc_OFFSET(sp) + sr t2, __struct_arch_esf_mepc_OFFSET(sp) #define SOC_ISR_SW_STACKING \ csrw mscratch, t0; \ From e0efc2cd4c9ba4cf1e81156dd04e76f859b60f9a Mon Sep 17 00:00:00 2001 From: Yong Cong Sin Date: Mon, 3 Jun 2024 18:12:12 +0800 Subject: [PATCH 1703/2849] doc: releases: update migration guide for the `struct arch_esf` Add a note about the introduction of `struct arch_esf` and the deprecation of `z_arch_esf_t`. Signed-off-by: Yong Cong Sin --- doc/releases/migration-guide-3.7.rst | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/doc/releases/migration-guide-3.7.rst b/doc/releases/migration-guide-3.7.rst index 0fa08a6af9db0..b7f2b3630eeb7 100644 --- a/doc/releases/migration-guide-3.7.rst +++ b/doc/releases/migration-guide-3.7.rst @@ -59,6 +59,11 @@ Build System Kernel ****** +* All architectures are now required to define the new ``struct arch_esf``, which describes the members + of a stack frame. This new struct replaces the named struct ``z_arch_esf_t``. (:github:`73593`) + +* The named struct ``z_arch_esf_t`` is now deprecated. Use ``struct arch_esf`` instead. (:github:`73593`) + Boards ****** From 3fc0e022f472626fed7d9022dc72a92b3e18bae4 Mon Sep 17 00:00:00 2001 From: Yong Cong Sin Date: Tue, 4 Jun 2024 01:29:28 +0800 Subject: [PATCH 1704/2849] manifest: update `sof` git revision Update the git revision of the `sof` module. Signed-off-by: Yong Cong Sin --- submanifests/optional.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/submanifests/optional.yaml b/submanifests/optional.yaml index db5f6c392b8f1..8da441bf05ab0 100644 --- a/submanifests/optional.yaml +++ b/submanifests/optional.yaml @@ -34,7 +34,7 @@ manifest: groups: - optional - name: sof - revision: c11a3185afbc8e1b2a79916de3dfefaf326d9ad1 + revision: a44758883f3f6cfb6c67b19bc76fcb01f77ca50b path: modules/audio/sof remote: upstream groups: From f18af662c5f9282a2782c3805e2b86dfc28c68ea Mon Sep 17 00:00:00 2001 From: Yong Cong Sin Date: Tue, 4 Jun 2024 16:22:12 +0800 Subject: [PATCH 1705/2849] include: optimize the order of includes for x86 x86 32bit defines `CONFIG_X86` while its 64bit counterpart defines an additional `CONFIG_X86_64`, by reordering the include order we can make it look a bit cleaner. Signed-off-by: Yong Cong Sin --- include/zephyr/arch/arch_inlines.h | 2 +- include/zephyr/arch/syscall.h | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/include/zephyr/arch/arch_inlines.h b/include/zephyr/arch/arch_inlines.h index 4e1cd149dfb4d..2c9b12a447b1a 100644 --- a/include/zephyr/arch/arch_inlines.h +++ b/include/zephyr/arch/arch_inlines.h @@ -12,7 +12,7 @@ #ifndef ZEPHYR_INCLUDE_ARCH_INLINES_H_ #define ZEPHYR_INCLUDE_ARCH_INLINES_H_ -#if defined(CONFIG_X86) || defined(CONFIG_X86_64) +#if defined(CONFIG_X86) #include #elif defined(CONFIG_ARM) #include diff --git a/include/zephyr/arch/syscall.h b/include/zephyr/arch/syscall.h index 5b41561b68190..966f6003098ba 100644 --- a/include/zephyr/arch/syscall.h +++ b/include/zephyr/arch/syscall.h @@ -9,12 +9,10 @@ #ifndef ZEPHYR_INCLUDE_ARCH_SYSCALL_H_ #define ZEPHYR_INCLUDE_ARCH_SYSCALL_H_ -#if defined(CONFIG_X86) #if defined(CONFIG_X86_64) #include -#else +#elif defined(CONFIG_X86) #include -#endif #elif defined(CONFIG_ARM64) #include #elif defined(CONFIG_ARM) From a2b0c2c46779499ca697d8abab03d4e52c884b78 Mon Sep 17 00:00:00 2001 From: Yong Cong Sin Date: Tue, 4 Jun 2024 16:24:41 +0800 Subject: [PATCH 1706/2849] include: stop breaking the compilation of OOT architectures Zephyr support out-of-tree architectures so we shouldn't throw error for archs not listed here. Signed-off-by: Yong Cong Sin --- include/zephyr/arch/arch_inlines.h | 2 -- include/zephyr/arch/cpu.h | 2 -- 2 files changed, 4 deletions(-) diff --git a/include/zephyr/arch/arch_inlines.h b/include/zephyr/arch/arch_inlines.h index 2c9b12a447b1a..0f32159e2f1bf 100644 --- a/include/zephyr/arch/arch_inlines.h +++ b/include/zephyr/arch/arch_inlines.h @@ -32,8 +32,6 @@ #include #elif defined(CONFIG_SPARC) #include -#else -#error "Unknown Architecture" #endif #endif /* ZEPHYR_INCLUDE_ARCH_INLINES_H_ */ diff --git a/include/zephyr/arch/cpu.h b/include/zephyr/arch/cpu.h index 11abe8df8c0b5..1e107512fa2a4 100644 --- a/include/zephyr/arch/cpu.h +++ b/include/zephyr/arch/cpu.h @@ -31,8 +31,6 @@ #include #elif defined(CONFIG_SPARC) #include -#else -#error "Unknown Architecture" #endif #endif /* ZEPHYR_INCLUDE_ARCH_CPU_H_ */ From 6ad9b6ccabeb9aefd231d2472a744cf09ee65914 Mon Sep 17 00:00:00 2001 From: Kai Vehmanen Date: Mon, 27 May 2024 20:16:31 +0300 Subject: [PATCH 1707/2849] soc: intel_adsp: tools: add intel_adsp_ace30 support to cavstool.py Add support for intel_adsp_ace30 platforms into cavstool.py. Signed-off-by: Kai Vehmanen --- soc/intel/intel_adsp/tools/cavstool.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/soc/intel/intel_adsp/tools/cavstool.py b/soc/intel/intel_adsp/tools/cavstool.py index 07e548893ff52..375131b7bd784 100755 --- a/soc/intel/intel_adsp/tools/cavstool.py +++ b/soc/intel/intel_adsp/tools/cavstool.py @@ -201,7 +201,7 @@ def adsp_is_cavs(): return cavs15 or cavs18 or cavs15 def adsp_is_ace(): - return ace15 or ace20 + return ace15 or ace20 or ace30 def adsp_mem_window_config(): if adsp_is_ace(): @@ -218,13 +218,14 @@ def map_regs(): pcidir = os.path.dirname(p) # Platform/quirk detection. ID lists cribbed from the SOF kernel driver - global cavs15, cavs18, cavs25, ace15, ace20 + global cavs15, cavs18, cavs25, ace15, ace20, ace30 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 ] + ace30 = did in [ 0xe428 ] # Check sysfs for a loaded driver and remove it if os.path.exists(f"{pcidir}/driver"): @@ -277,8 +278,8 @@ def map_regs(): dsp = Regs(bar4_mem) if adsp_is_ace(): dsp.HFDSSCS = 0x1000 - dsp.HFPWRCTL = 0x1d18 - dsp.HFPWRSTS = 0x1d1c + dsp.HFPWRCTL = 0x1d18 if ace20 else 0x1d20 + dsp.HFPWRSTS = 0x1d1c if ace20 else 0x1d24 dsp.DSP2CXCTL_PRIMARY = 0x178d04 dsp.HFIPCXTDR = 0x73200 dsp.HFIPCXTDA = 0x73204 From e4cf90faa3443f860cfd76f92b2e6b35971d162f Mon Sep 17 00:00:00 2001 From: Declan Snyder Date: Mon, 3 Jun 2024 19:51:59 -0500 Subject: [PATCH 1708/2849] drivers: counter_smartbond_timer: Fix warning Fix the warning about control reaching end of non void function by adding a default to the switch statement. Signed-off-by: Declan Snyder --- drivers/counter/counter_smartbond_timer.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/counter/counter_smartbond_timer.c b/drivers/counter/counter_smartbond_timer.c index 3e42f10b8fd26..c15bdfad86e05 100644 --- a/drivers/counter/counter_smartbond_timer.c +++ b/drivers/counter/counter_smartbond_timer.c @@ -105,6 +105,8 @@ static uint8_t counter_smartbond_pdc_trigger_get(const struct device *dev) return MCU_PDC_TRIGGER_TIMER3; case (uint32_t)TIMER4: return MCU_PDC_TRIGGER_TIMER4; + default: + return 0; } } From e8a71d9d83f4b6dba4b9bbbbef2cfebba95c4058 Mon Sep 17 00:00:00 2001 From: Declan Snyder Date: Mon, 3 Jun 2024 19:53:00 -0500 Subject: [PATCH 1709/2849] soc: renesas: Fix linker error from multiple IRQ17 Fix linker error caused by the smartbond timer driver being enabled at the same time as the smartbond timer counter driver. For some reason putting SMARTBOND_TIMER=n in a conf file does not fix this, this change has to be made to the Kconfig.defconfig to not add this default y case in order to fix the error. At least that is all I could figure out, and not sure why the .conf doesn't override it. Signed-off-by: Declan Snyder --- soc/renesas/smartbond/da1469x/Kconfig.defconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/soc/renesas/smartbond/da1469x/Kconfig.defconfig b/soc/renesas/smartbond/da1469x/Kconfig.defconfig index 239c34482b0c2..418c4ea126ce6 100644 --- a/soc/renesas/smartbond/da1469x/Kconfig.defconfig +++ b/soc/renesas/smartbond/da1469x/Kconfig.defconfig @@ -4,7 +4,7 @@ if SOC_SERIES_DA1469X config SMARTBOND_TIMER - default y if PM + default y if PM && !$(dt_nodelabel_enabled,timer2) config CORTEX_M_SYSTICK default n if SMARTBOND_TIMER From 8d6d700375017426fa9bb11e104e81973016d716 Mon Sep 17 00:00:00 2001 From: Alberto Escolar Piedras Date: Fri, 31 May 2024 14:32:40 +0200 Subject: [PATCH 1710/2849] manifest: Update nRF hw models to latest Update the HW models module to: 4447a22aea5e791c9bd18e7d71cc092623ddd2bb Including the following: * 4447a22a CLOCK,POWER,RESET: Add stubs for the 54L 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 009b5ad3ddc1d..dad29b8d96156 100644 --- a/west.yml +++ b/west.yml @@ -300,7 +300,7 @@ manifest: groups: - tools - name: nrf_hw_models - revision: 53635212495e4575955fc717369be4362126456a + revision: 4447a22aea5e791c9bd18e7d71cc092623ddd2bb path: modules/bsim_hw_models/nrf_hw_models - name: open-amp revision: da78aea63159771956fe0c9263f2e6985b66e9d5 From 61db56915f8d746f41b211e6420260aa8464febe Mon Sep 17 00:00:00 2001 From: Alberto Escolar Piedras Date: Wed, 29 May 2024 14:00:04 +0200 Subject: [PATCH 1711/2849] boards nrf54l15bsim: Set clock status as ok in DT So the nRF clock driver is built in as in real targets. Signed-off-by: Alberto Escolar Piedras --- boards/native/nrf_bsim/nrf54l15bsim_nrf54l15_cpuapp.dts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/boards/native/nrf_bsim/nrf54l15bsim_nrf54l15_cpuapp.dts b/boards/native/nrf_bsim/nrf54l15bsim_nrf54l15_cpuapp.dts index ec34448017e5b..91c2233d70b76 100644 --- a/boards/native/nrf_bsim/nrf54l15bsim_nrf54l15_cpuapp.dts +++ b/boards/native/nrf_bsim/nrf54l15bsim_nrf54l15_cpuapp.dts @@ -59,7 +59,6 @@ /delete-node/ watchdog@109000; /delete-node/ gpio@10a000; /delete-node/ gpiote@10c000; - /delete-node/ clock@10e000; }; /delete-node/ spu@50003000; /delete-node/ gpiote@5000d000; @@ -99,3 +98,7 @@ /* This feature is not yet supported by the RADIO model */ /delete-property/ dfe-supported; }; + +&clock { + status = "okay"; +}; From 038b7b8c4181a8c3141cbdd1111a7d4769036655 Mon Sep 17 00:00:00 2001 From: Alberto Escolar Piedras Date: Wed, 29 May 2024 13:01:52 +0200 Subject: [PATCH 1712/2849] drivers/clock_control nrf: Treat simulated nRF54L15 like real Default the clock accuracy for the simulated 54L15 target just as for the real target. Signed-off-by: Alberto Escolar Piedras --- drivers/clock_control/Kconfig.nrf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clock_control/Kconfig.nrf b/drivers/clock_control/Kconfig.nrf index 725a76949869f..37e09ce21a998 100644 --- a/drivers/clock_control/Kconfig.nrf +++ b/drivers/clock_control/Kconfig.nrf @@ -132,7 +132,7 @@ choice CLOCK_CONTROL_NRF_ACCURACY_PPM prompt "32KHz clock accuracy" default CLOCK_CONTROL_NRF_K32SRC_500PPM if CLOCK_CONTROL_NRF_K32SRC_RC && SOC_COMPATIBLE_NRF52X default CLOCK_CONTROL_NRF_K32SRC_250PPM if CLOCK_CONTROL_NRF_K32SRC_RC - default CLOCK_CONTROL_NRF_K32SRC_150PPM if CLOCK_CONTROL_NRF_K32SRC_XTAL && SOC_SERIES_NRF54LX + default CLOCK_CONTROL_NRF_K32SRC_150PPM if CLOCK_CONTROL_NRF_K32SRC_XTAL && SOC_COMPATIBLE_NRF54LX default CLOCK_CONTROL_NRF_K32SRC_50PPM config CLOCK_CONTROL_NRF_K32SRC_500PPM From e99874142717f0f03efe477dd221b5069b51a6b6 Mon Sep 17 00:00:00 2001 From: Alberto Escolar Piedras Date: Wed, 29 May 2024 11:17:23 +0200 Subject: [PATCH 1713/2849] boards nrf54l15bsim: Default to build BT Controller if BT Just as for the other simulated targets. Signed-off-by: Alberto Escolar Piedras --- boards/native/nrf_bsim/Kconfig.defconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/boards/native/nrf_bsim/Kconfig.defconfig b/boards/native/nrf_bsim/Kconfig.defconfig index 81f90836b543b..c3c786e45db24 100644 --- a/boards/native/nrf_bsim/Kconfig.defconfig +++ b/boards/native/nrf_bsim/Kconfig.defconfig @@ -39,7 +39,7 @@ config SYS_CLOCK_TICKS_PER_SEC default 32768 config BT_CTLR - default y if BOARD_NRF52_BSIM || BOARD_NRF5340BSIM_NRF5340_CPUNET + default y if BOARD_NRF52_BSIM || BOARD_NRF5340BSIM_NRF5340_CPUNET || BOARD_NRF54L15BSIM_NRF54L15_CPUAPP depends on BT config HEAP_MEM_POOL_ADD_SIZE_BOARD From 329dbeae0aaa03d995b387b788fc90678564645c Mon Sep 17 00:00:00 2001 From: Alberto Escolar Piedras Date: Fri, 31 May 2024 14:39:40 +0200 Subject: [PATCH 1714/2849] boards: nrf54l15bsim: Mention CLOCK As now we have a sufficient model of the CLOCK peripheral, let's mention it in the docs, and correct the warning about not supporting the BLE stack. Signed-off-by: Alberto Escolar Piedras --- boards/native/nrf_bsim/doc/nrf54l15bsim.rst | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/boards/native/nrf_bsim/doc/nrf54l15bsim.rst b/boards/native/nrf_bsim/doc/nrf54l15bsim.rst index bb113510c4a0a..8c0b2fb64f01d 100644 --- a/boards/native/nrf_bsim/doc/nrf54l15bsim.rst +++ b/boards/native/nrf_bsim/doc/nrf54l15bsim.rst @@ -32,11 +32,12 @@ on the simulated nRF54L15 SOC. .. warning:: This target is experimental, and even though it includes models of the RADIO, it does not yet - include models of the AAR, CCM, ECB or CLOCK peripherals, so the BLE and 802.15.4 stacks cannot - be run on it yet. + include models of the AAR, CCM or ECB peripherals, so the BLE and 802.15.4 stacks can only be + run without encryption or privacy features so far. This boards include models of some of the nRF54L15 SOC peripherals: +* CLOCK (Clock control) * DPPI (Distributed Programmable Peripheral Interconnect) * EGU (Event Generator Unit) * FICR (Factory Information Configuration Registers) From 4b64e001fe6bbfbd939e336613060d24c64862b6 Mon Sep 17 00:00:00 2001 From: Alberto Escolar Piedras Date: Fri, 31 May 2024 14:45:19 +0200 Subject: [PATCH 1715/2849] boards nrf54l15bsim: DT: Set radio status as ok Set the radio status as ok as the SOC/CPU DT include does not do it for us. Signed-off-by: Alberto Escolar Piedras --- boards/native/nrf_bsim/nrf54l15bsim_nrf54l15_cpuapp.dts | 1 + 1 file changed, 1 insertion(+) diff --git a/boards/native/nrf_bsim/nrf54l15bsim_nrf54l15_cpuapp.dts b/boards/native/nrf_bsim/nrf54l15bsim_nrf54l15_cpuapp.dts index 91c2233d70b76..bdcd1f2300bc4 100644 --- a/boards/native/nrf_bsim/nrf54l15bsim_nrf54l15_cpuapp.dts +++ b/boards/native/nrf_bsim/nrf54l15bsim_nrf54l15_cpuapp.dts @@ -95,6 +95,7 @@ }; &radio { + status = "okay"; /* This feature is not yet supported by the RADIO model */ /delete-property/ dfe-supported; }; From ed954bf63895538547c51418d1fa1e7be0e800c9 Mon Sep 17 00:00:00 2001 From: Torsten Rasmussen Date: Fri, 24 May 2024 14:38:38 +0200 Subject: [PATCH 1716/2849] doc: describe Kconfig tracking symbol Fixes: #73132 Add a subsection on tracking Kconfig symbols whose default values is obtained from another Kconfig symbol. Signed-off-by: Torsten Rasmussen --- doc/build/kconfig/setting.rst | 49 +++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/doc/build/kconfig/setting.rst b/doc/build/kconfig/setting.rst index b938e233f975b..05308589d53f6 100644 --- a/doc/build/kconfig/setting.rst +++ b/doc/build/kconfig/setting.rst @@ -198,6 +198,55 @@ configuration that gets modified when making changes in the :ref:`interactive configuration interfaces `. +Tracking Kconfig symbols +************************ + +It is possible to create Kconfig symbols which takes the default value of +another Kconfig symbol. + +This is valuable when you want a symbol specific to an application or subsystem +but do not want to rely directly on the common symbol. For example, you might +want to decouple the settings so they can be independently configured, or to +ensure you always have a locally named setting, even if the external setting name changes. +is later changed. + +For example, consider the common ``FOO_STRING`` setting where a subsystem wants +to have a ``SUB_FOO_STRING`` but still allow for customization. + +This can be done like this: + +.. code-block:: kconfig + + config FOO_STRING + string "Foo" + default "foo" + + config SUB_FOO_STRING + string "Sub-foo" + default FOO_STRING + +This ensures that the default value of ``SUB_FOO_STRING`` is identical to +``FOO_STRING`` while still allows users to configure both settings +independently. + +It is also possible to make ``SUB_FOO_STRING`` invisible and thereby keep the +two symbols in sync, unless the value of the tracking symbol is changed in a +:file:`defconfig` file. + +.. code-block:: kconfig + + config FOO_STRING + string "Foo" + default "foo" + + config SUB_FOO_STRING + string + default FOO_STRING + help + Hidden symbol which follows FOO_STRING + Can be changed through *.defconfig files. + + Configuring invisible Kconfig symbols ************************************* From 81bc939553ce6b73651ef60d21166e6e84018f24 Mon Sep 17 00:00:00 2001 From: Fabian Blatz Date: Wed, 22 May 2024 13:33:00 +0200 Subject: [PATCH 1717/2849] modules: lvgl: lvgl_fs: Free file on close Add missing call to LV_MEM_CUSTOM_FREE when closing a file to prevent memory from leaking. Resolves issue #73148. Signed-off-by: Fabian Blatz --- modules/lvgl/lvgl_fs.c | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/lvgl/lvgl_fs.c b/modules/lvgl/lvgl_fs.c index a05e21748d41a..63a902ea9572d 100644 --- a/modules/lvgl/lvgl_fs.c +++ b/modules/lvgl/lvgl_fs.c @@ -88,6 +88,7 @@ static lv_fs_res_t lvgl_fs_close(struct _lv_fs_drv_t *drv, void *file) int err; err = fs_close((struct fs_file_t *)file); + LV_MEM_CUSTOM_FREE(file); return errno_to_lv_fs_res(err); } From 54733aa2cbb464c85948e0290d940e5baf5db0a3 Mon Sep 17 00:00:00 2001 From: Pieter De Gendt Date: Wed, 29 May 2024 09:42:45 +0200 Subject: [PATCH 1718/2849] submanifests: optional: Sync upstream nanopb Set the latest version for nanopb. This fixes searching for the nanopb_generator.py script in the module instead of system wide. Signed-off-by: Pieter De Gendt --- submanifests/optional.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/submanifests/optional.yaml b/submanifests/optional.yaml index 8da441bf05ab0..35f5d93116769 100644 --- a/submanifests/optional.yaml +++ b/submanifests/optional.yaml @@ -22,7 +22,7 @@ manifest: groups: - optional - name: nanopb - revision: 7f88274070afa5edfaf608f4d8e32f3d3c1de139 + revision: 4474bd35bd39de067f0532a1b19ce3aed9ed9807 path: modules/lib/nanopb remote: upstream groups: From 7bf6e8bb9773d88b96b09112298b7faab244848b Mon Sep 17 00:00:00 2001 From: Mike Szczys Date: Mon, 20 May 2024 23:06:47 -0500 Subject: [PATCH 1719/2849] boards: rak5010: add blackmagicprobe runner Add blackmagicprobe as a supported runner. Signed-off-by: Mike Szczys --- boards/rak/rak5010/board.cmake | 1 + 1 file changed, 1 insertion(+) diff --git a/boards/rak/rak5010/board.cmake b/boards/rak/rak5010/board.cmake index 1bf111421e2b7..d91b58c847d8a 100644 --- a/boards/rak/rak5010/board.cmake +++ b/boards/rak/rak5010/board.cmake @@ -7,3 +7,4 @@ include(${ZEPHYR_BASE}/boards/common/nrfjprog.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) +include(${ZEPHYR_BASE}/boards/common/blackmagicprobe.board.cmake) From ddd49f32d9fb1848a1d58eef45ebd77a837f6e2f Mon Sep 17 00:00:00 2001 From: Chris Friedt Date: Mon, 20 May 2024 22:29:46 -0400 Subject: [PATCH 1720/2849] tests: posix: headers: remove tests for varying features The header tests for the existence of constants like _POSIX_SPIN_LOCKS are bound to fail in one circumstance or another because each of those options are (theoretically) features which can be enabled or disabled. Moreover, some implementations (e.g. external libc) might not implement one particular subset or option group. These tests are poorly conditioned, so remove them. Signed-off-by: Chris Friedt --- tests/posix/headers/src/unistd_h.c | 93 ------------------------------ 1 file changed, 93 deletions(-) diff --git a/tests/posix/headers/src/unistd_h.c b/tests/posix/headers/src/unistd_h.c index a0b51c3320654..bf713c0aca948 100644 --- a/tests/posix/headers/src/unistd_h.c +++ b/tests/posix/headers/src/unistd_h.c @@ -19,99 +19,6 @@ */ ZTEST(posix_headers, test_unistd_h) { - zassert_not_equal(-1, _POSIX_VERSION); - /* zassert_not_equal(-1, _POSIX2_VERSION); */ /* not implemented */ - /* zassert_not_equal(-1, _XOPEN_VERSION); */ /* not implemented */ - - zassert_not_equal(INT_MIN, _POSIX_ADVISORY_INFO); /* not implemented */ - zassert_not_equal(INT_MIN, _POSIX_ASYNCHRONOUS_IO); /* not implemented */ - zassert_not_equal(INT_MIN, _POSIX_BARRIERS); /* not implemented */ - zassert_not_equal(INT_MIN, _POSIX_CHOWN_RESTRICTED); /* not implemented */ - zassert_not_equal(INT_MIN, _POSIX_CPUTIME); /* not implemented */ - zassert_not_equal(INT_MIN, _POSIX_FSYNC); /* not implemented */ - zassert_not_equal(INT_MIN, _POSIX_IPV6); /* not implemented */ - zassert_not_equal(INT_MIN, _POSIX_JOB_CONTROL); /* not implemented */ - zassert_not_equal(INT_MIN, _POSIX_MAPPED_FILES); /* not implemented */ - zassert_not_equal(INT_MIN, _POSIX_MEMLOCK); /* not implemented */ - zassert_not_equal(INT_MIN, _POSIX_MEMLOCK_RANGE); /* not implemented */ - zassert_not_equal(INT_MIN, _POSIX_MEMORY_PROTECTION); /* not implemented */ - zassert_not_equal(INT_MIN, _POSIX_MESSAGE_PASSING); /* not implemented */ - zassert_not_equal(INT_MIN, _POSIX_MONOTONIC_CLOCK); /* not implemented */ - zassert_not_equal(INT_MIN, _POSIX_NO_TRUNC); /* not implemented */ - zassert_not_equal(INT_MIN, _POSIX_PRIORITIZED_IO); /* not implemented */ - zassert_not_equal(INT_MIN, _POSIX_PRIORITY_SCHEDULING); /* not implemented */ - zassert_not_equal(INT_MIN, _POSIX_RAW_SOCKETS); /* not implemented */ - zassert_not_equal(INT_MIN, _POSIX_READER_WRITER_LOCKS); /* not implemented */ - zassert_not_equal(INT_MIN, _POSIX_REALTIME_SIGNALS); /* not implemented */ - zassert_not_equal(INT_MIN, _POSIX_REGEXP); /* not implemented */ - zassert_not_equal(INT_MIN, _POSIX_SAVED_IDS); /* not implemented */ - zassert_not_equal(INT_MIN, _POSIX_SHARED_MEMORY_OBJECTS); /* not implemented */ - zassert_not_equal(INT_MIN, _POSIX_SHELL); /* not implemented */ - zassert_not_equal(INT_MIN, _POSIX_SPAWN); /* not implemented */ - zassert_not_equal(INT_MIN, _POSIX_SPIN_LOCKS); /* not implemented */ - zassert_not_equal(INT_MIN, _POSIX_SPORADIC_SERVER); /* not implemented */ - zassert_not_equal(INT_MIN, _POSIX_SYNCHRONIZED_IO); /* not implemented */ - zassert_not_equal(INT_MIN, _POSIX_THREAD_ATTR_STACKADDR); /* not implemented */ - zassert_not_equal(INT_MIN, _POSIX_THREAD_ATTR_STACKSIZE); /* not implemented */ - zassert_not_equal(INT_MIN, _POSIX_THREAD_CPUTIME); /* not implemented */ - zassert_not_equal(INT_MIN, _POSIX_THREAD_PRIO_INHERIT); /* not implemented */ - zassert_not_equal(INT_MIN, _POSIX_THREAD_PRIO_PROTECT); /* not implemented */ - zassert_not_equal(INT_MIN, _POSIX_THREAD_PRIORITY_SCHEDULING); /* not implemented */ - zassert_not_equal(INT_MIN, _POSIX_THREAD_PROCESS_SHARED); /* not implemented */ - zassert_not_equal(INT_MIN, _POSIX_THREAD_ROBUST_PRIO_INHERIT); /* not implemented */ - zassert_not_equal(INT_MIN, _POSIX_THREAD_ROBUST_PRIO_PROTECT); /* not implemented */ - zassert_not_equal(INT_MIN, _POSIX_THREAD_SAFE_FUNCTIONS); /* not implemented */ - zassert_not_equal(INT_MIN, _POSIX_THREAD_SPORADIC_SERVER); /* not implemented */ - zassert_not_equal(INT_MIN, _POSIX_THREADS); /* not implemented */ - zassert_not_equal(INT_MIN, _POSIX_TIMEOUTS); /* not implemented */ - zassert_not_equal(INT_MIN, _POSIX_TIMERS); /* not implemented */ - zassert_not_equal(INT_MIN, _POSIX_TRACE); /* not implemented */ - zassert_not_equal(INT_MIN, _POSIX_TRACE_EVENT_FILTER); /* not implemented */ - zassert_not_equal(INT_MIN, _POSIX_TRACE_INHERIT); /* not implemented */ - zassert_not_equal(INT_MIN, _POSIX_TRACE_LOG); /* not implemented */ - zassert_not_equal(INT_MIN, _POSIX_TYPED_MEMORY_OBJECTS); /* not implemented */ - - zassert_not_equal(INT_MIN, _POSIX_V6_ILP32_OFF32); /* not implemented */ - zassert_not_equal(INT_MIN, _POSIX_V6_ILP32_OFFBIG); /* not implemented */ - zassert_not_equal(INT_MIN, _POSIX_V6_LP64_OFF64); /* not implemented */ - zassert_not_equal(INT_MIN, _POSIX_V6_LPBIG_OFFBIG); /* not implemented */ - - zassert_not_equal(INT_MIN, _POSIX_V7_ILP32_OFF32); /* not implemented */ - zassert_not_equal(INT_MIN, _POSIX_V7_ILP32_OFFBIG); /* not implemented */ - zassert_not_equal(INT_MIN, _POSIX_V7_LP64_OFF64); /* not implemented */ - zassert_not_equal(INT_MIN, _POSIX_V7_LPBIG_OFFBIG); /* not implemented */ - - zassert_not_equal(INT_MIN, _POSIX2_C_BIND); /* not implemented */ - zassert_not_equal(INT_MIN, _POSIX2_C_DEV); /* not implemented */ - zassert_not_equal(INT_MIN, _POSIX2_CHAR_TERM); /* not implemented */ - zassert_not_equal(INT_MIN, _POSIX2_FORT_DEV); /* not implemented */ - zassert_not_equal(INT_MIN, _POSIX2_FORT_RUN); /* not implemented */ - zassert_not_equal(INT_MIN, _POSIX2_LOCALEDEF); /* not implemented */ - zassert_not_equal(INT_MIN, _POSIX2_PBS); /* not implemented */ - zassert_not_equal(INT_MIN, _POSIX2_PBS_ACCOUNTING); /* not implemented */ - zassert_not_equal(INT_MIN, _POSIX2_PBS_CHECKPOINT); /* not implemented */ - zassert_not_equal(INT_MIN, _POSIX2_PBS_LOCATE); /* not implemented */ - zassert_not_equal(INT_MIN, _POSIX2_PBS_MESSAGE); /* not implemented */ - zassert_not_equal(INT_MIN, _POSIX2_PBS_TRACK); /* not implemented */ - zassert_not_equal(INT_MIN, _POSIX2_SW_DEV); /* not implemented */ - zassert_not_equal(INT_MIN, _POSIX2_UPE); /* not implemented */ - - zassert_not_equal(INT_MIN, _XOPEN_CRYPT); /* not implemented */ - zassert_not_equal(INT_MIN, _XOPEN_ENH_I18N); /* not implemented */ - zassert_not_equal(INT_MIN, _XOPEN_REALTIME); /* not implemented */ - zassert_not_equal(INT_MIN, _XOPEN_REALTIME_THREADS); /* not implemented */ - zassert_not_equal(INT_MIN, _XOPEN_SHM); /* not implemented */ - zassert_not_equal(INT_MIN, _XOPEN_STREAMS); /* not implemented */ - zassert_not_equal(INT_MIN, _XOPEN_UNIX); /* not implemented */ - zassert_not_equal(INT_MIN, _XOPEN_UUCP); /* not implemented */ - - /* zassert_not_equal(INT_MIN, _POSIX_ASYNC_IO); */ /* not implemented */ - /* zassert_not_equal(INT_MIN, _POSIX_PRIO_IO); */ /* not implemented */ - /* zassert_not_equal(INT_MIN, _POSIX_SYNC_IO); */ /* not implemented */ - - /* zassert_not_equal(-1, _POSIX_TIMESTAMP_RESOLUTION); */ /* not implemented */ - /* zassert_not_equal(INT_MIN, _POSIX2_SYMLINKS); */ /* not implemented */ - /* zassert_not_equal(-1, F_OK); */ /* not implemented */ /* zassert_not_equal(-1, R_OK); */ /* not implemented */ /* zassert_not_equal(-1, W_OK); */ /* not implemented */ From f4be0ee859ae888cf5b8b18d4696c0021339e506 Mon Sep 17 00:00:00 2001 From: Chris Friedt Date: Mon, 20 May 2024 22:31:54 -0400 Subject: [PATCH 1721/2849] tests: posix: headers: check some structs only when posix_api=y Some POSIX header tests assumed that various structures would be declared even if POSIX_API=n. Actually most meaningful POSIX structures are guarded by feature test macros defined by the implementation (i.e. implementation conformance macros). So only run tests on those structures when CONFIG_POSIX_API=y. Signed-off-by: Chris Friedt --- tests/posix/headers/src/dirent_h.c | 26 ++-- tests/posix/headers/src/pthread_h.c | 202 ++++++++++++++-------------- 2 files changed, 114 insertions(+), 114 deletions(-) diff --git a/tests/posix/headers/src/dirent_h.c b/tests/posix/headers/src/dirent_h.c index ca5527603c039..dc7ef4ba8aaed 100644 --- a/tests/posix/headers/src/dirent_h.c +++ b/tests/posix/headers/src/dirent_h.c @@ -19,22 +19,22 @@ */ ZTEST(posix_headers, test_dirent_h) { +#ifdef CONFIG_POSIX_API zassert_not_equal((DIR *)-1, (DIR *)NULL); zassert_not_equal(-1, offsetof(struct dirent, d_ino)); zassert_not_equal(-1, offsetof(struct dirent, d_name)); - if (IS_ENABLED(CONFIG_POSIX_API)) { - /* zassert_not_null(alphasort); */ /* not implemented */ - zassert_not_null(closedir); - /* zassert_not_null(dirfd); */ /* not implemented */ - /* zassert_not_null(fdopendir); */ /* not implemented */ - zassert_not_null(opendir); - zassert_not_null(readdir); - /* zassert_not_null(readdir_r); */ /* not implemented */ - /* zassert_not_null(rewinddir); */ /* not implemented */ - /* zassert_not_null(scandir); */ /* not implemented */ - /* zassert_not_null(seekdir); */ /* not implemented */ - /* zassert_not_null(telldir); */ /* not implemented */ - } + /* zassert_not_null(alphasort); */ /* not implemented */ + zassert_not_null(closedir); + /* zassert_not_null(dirfd); */ /* not implemented */ + /* zassert_not_null(fdopendir); */ /* not implemented */ + zassert_not_null(opendir); + zassert_not_null(readdir); + /* zassert_not_null(readdir_r); */ /* not implemented */ + /* zassert_not_null(rewinddir); */ /* not implemented */ + /* zassert_not_null(scandir); */ /* not implemented */ + /* zassert_not_null(seekdir); */ /* not implemented */ + /* zassert_not_null(telldir); */ /* not implemented */ +#endif } diff --git a/tests/posix/headers/src/pthread_h.c b/tests/posix/headers/src/pthread_h.c index fdf9b66c1ae6f..4363d3b476419 100644 --- a/tests/posix/headers/src/pthread_h.c +++ b/tests/posix/headers/src/pthread_h.c @@ -21,6 +21,7 @@ */ ZTEST(posix_headers, test_pthread_h) { +#ifdef CONFIG_POSIX_API zassert_not_equal(-1, PTHREAD_BARRIER_SERIAL_THREAD); zassert_not_equal(-1, PTHREAD_CANCEL_ASYNCHRONOUS); @@ -41,7 +42,7 @@ ZTEST(posix_headers, test_pthread_h) zassert_not_equal(-1, PTHREAD_MUTEX_ERRORCHECK); zassert_not_equal(-1, PTHREAD_MUTEX_ERRORCHECK); zassert_not_equal(-1, PTHREAD_MUTEX_RECURSIVE); - /* zassert_not_equal(-1, PTHREAD_MUTEX_ROBUST); */ /* not implemented */ + /* zassert_not_equal(-1, PTHREAD_MUTEX_ROBUST); */ /* not implemented */ /* zassert_not_equal(-1, PTHREAD_MUTEX_STALLED); */ /* not implemented */ pthread_once_t once = PTHREAD_ONCE_INIT; @@ -60,105 +61,104 @@ ZTEST(posix_headers, test_pthread_h) pthread_mutex_t mu = PTHREAD_MUTEX_INITIALIZER; /* pthread_rwlock_t lock = PTHREAD_RWLOCK_INITIALIZER; */ /* not implemented */ - if (IS_ENABLED(CONFIG_POSIX_API)) { - zassert_not_null(pthread_atfork); - zassert_not_null(pthread_attr_destroy); - zassert_not_null(pthread_attr_getdetachstate); - zassert_not_null(pthread_attr_getguardsize); - zassert_not_null(pthread_attr_getinheritsched); - zassert_not_null(pthread_attr_getschedparam); - zassert_not_null(pthread_attr_getschedpolicy); - zassert_not_null(pthread_attr_getscope); - zassert_not_null(pthread_attr_getstack); - zassert_not_null(pthread_attr_getstacksize); - zassert_not_null(pthread_attr_init); - zassert_not_null(pthread_attr_setdetachstate); - zassert_not_null(pthread_attr_setguardsize); - zassert_not_null(pthread_attr_setinheritsched); - zassert_not_null(pthread_attr_setschedparam); - zassert_not_null(pthread_attr_setschedpolicy); - zassert_not_null(pthread_attr_setscope); - zassert_not_null(pthread_attr_setstack); - zassert_not_null(pthread_attr_setstacksize); - zassert_not_null(pthread_barrier_destroy); - zassert_not_null(pthread_barrier_init); - zassert_not_null(pthread_barrier_wait); - zassert_not_null(pthread_barrierattr_destroy); - /* zassert_not_null(pthread_barrierattr_getpshared); */ /* not implemented */ - zassert_not_null(pthread_barrierattr_init); - /* zassert_not_null(pthread_barrierattr_setpshared); */ /* not implemented */ - zassert_not_null(pthread_cancel); - zassert_not_null(pthread_cond_broadcast); - zassert_not_null(pthread_cond_destroy); - zassert_not_null(pthread_cond_init); - zassert_not_null(pthread_cond_signal); - zassert_not_null(pthread_cond_timedwait); - zassert_not_null(pthread_cond_wait); - zassert_not_null(pthread_condattr_destroy); - zassert_not_null(pthread_condattr_getclock); - /* zassert_not_null(pthread_condattr_getpshared); */ /* not implemented */ - zassert_not_null(pthread_condattr_init); - zassert_not_null(pthread_condattr_setclock); - /* zassert_not_null(pthread_condattr_setpshared); */ /* not implemented */ - zassert_not_null(pthread_create); - zassert_not_null(pthread_detach); - zassert_not_null(pthread_equal); - zassert_not_null(pthread_exit); - zassert_not_null(pthread_getconcurrency); - /* zassert_not_null(pthread_getcpuclockid); */ /* not implemented */ - zassert_not_null(pthread_getschedparam); - zassert_not_null(pthread_getspecific); - zassert_not_null(pthread_join); - zassert_not_null(pthread_key_create); - zassert_not_null(pthread_key_delete); - /* zassert_not_null(pthread_mutex_consistent); */ /* not implemented */ - zassert_not_null(pthread_mutex_destroy); - /* zassert_not_null(pthread_mutex_getprioceiling); */ /* not implemented */ - zassert_not_null(pthread_mutex_init); - zassert_not_null(pthread_mutex_lock); - /* zassert_not_null(pthread_mutex_setprioceiling); */ /* not implemented */ - zassert_not_null(pthread_mutex_timedlock); - zassert_not_null(pthread_mutex_trylock); - zassert_not_null(pthread_mutex_unlock); - zassert_not_null(pthread_mutexattr_destroy); - /* zassert_not_null(pthread_mutexattr_getprioceiling); */ /* not implemented */ - zassert_not_null(pthread_mutexattr_getprotocol); - /* zassert_not_null(pthread_mutexattr_getpshared); */ /* not implemented */ - /* zassert_not_null(pthread_mutexattr_getrobust); */ /* not implemented */ - zassert_not_null(pthread_mutexattr_gettype); - zassert_not_null(pthread_mutexattr_init); - /* zassert_not_null(pthread_mutexattr_setprioceiling); */ /* not implemented */ - /* zassert_not_null(pthread_mutexattr_setprotocol); */ /* not implemented */ - /* zassert_not_null(pthread_mutexattr_setpshared); */ /* not implemented */ - /* zassert_not_null(pthread_mutexattr_setrobust); */ /* not implemented */ - zassert_not_null(pthread_mutexattr_settype); - zassert_not_null(pthread_once); - zassert_not_null(pthread_rwlock_destroy); - zassert_not_null(pthread_rwlock_init); - zassert_not_null(pthread_rwlock_rdlock); - zassert_not_null(pthread_rwlock_timedrdlock); - zassert_not_null(pthread_rwlock_timedwrlock); - zassert_not_null(pthread_rwlock_tryrdlock); - zassert_not_null(pthread_rwlock_trywrlock); - zassert_not_null(pthread_rwlock_unlock); - zassert_not_null(pthread_rwlock_wrlock); - zassert_not_null(pthread_rwlockattr_destroy); - zassert_not_null(pthread_rwlockattr_getpshared); - zassert_not_null(pthread_rwlockattr_init); - zassert_not_null(pthread_rwlockattr_setpshared); - zassert_not_null(pthread_self); - zassert_not_null(pthread_setcancelstate); - zassert_not_null(pthread_setcanceltype); - zassert_not_null(pthread_setconcurrency); - zassert_not_null(pthread_setschedparam); - zassert_not_null(pthread_setschedprio); - zassert_not_null(pthread_setspecific); - zassert_not_null(pthread_spin_destroy); - zassert_not_null(pthread_spin_init); - zassert_not_null(pthread_spin_lock); - zassert_not_null(pthread_spin_trylock); - zassert_not_null(pthread_spin_unlock); - zassert_not_null(pthread_testcancel); - } + zassert_not_null(pthread_atfork); + zassert_not_null(pthread_attr_destroy); + zassert_not_null(pthread_attr_getdetachstate); + zassert_not_null(pthread_attr_getguardsize); + zassert_not_null(pthread_attr_getinheritsched); + zassert_not_null(pthread_attr_getschedparam); + zassert_not_null(pthread_attr_getschedpolicy); + zassert_not_null(pthread_attr_getscope); + zassert_not_null(pthread_attr_getstack); + zassert_not_null(pthread_attr_getstacksize); + zassert_not_null(pthread_attr_init); + zassert_not_null(pthread_attr_setdetachstate); + zassert_not_null(pthread_attr_setguardsize); + zassert_not_null(pthread_attr_setinheritsched); + zassert_not_null(pthread_attr_setschedparam); + zassert_not_null(pthread_attr_setschedpolicy); + zassert_not_null(pthread_attr_setscope); + zassert_not_null(pthread_attr_setstack); + zassert_not_null(pthread_attr_setstacksize); + zassert_not_null(pthread_barrier_destroy); + zassert_not_null(pthread_barrier_init); + zassert_not_null(pthread_barrier_wait); + zassert_not_null(pthread_barrierattr_destroy); + /* zassert_not_null(pthread_barrierattr_getpshared); */ /* not implemented */ + zassert_not_null(pthread_barrierattr_init); + /* zassert_not_null(pthread_barrierattr_setpshared); */ /* not implemented */ + zassert_not_null(pthread_cancel); + zassert_not_null(pthread_cond_broadcast); + zassert_not_null(pthread_cond_destroy); + zassert_not_null(pthread_cond_init); + zassert_not_null(pthread_cond_signal); + zassert_not_null(pthread_cond_timedwait); + zassert_not_null(pthread_cond_wait); + zassert_not_null(pthread_condattr_destroy); + zassert_not_null(pthread_condattr_getclock); + /* zassert_not_null(pthread_condattr_getpshared); */ /* not implemented */ + zassert_not_null(pthread_condattr_init); + zassert_not_null(pthread_condattr_setclock); + /* zassert_not_null(pthread_condattr_setpshared); */ /* not implemented */ + zassert_not_null(pthread_create); + zassert_not_null(pthread_detach); + zassert_not_null(pthread_equal); + zassert_not_null(pthread_exit); + zassert_not_null(pthread_getconcurrency); + /* zassert_not_null(pthread_getcpuclockid); */ /* not implemented */ + zassert_not_null(pthread_getschedparam); + zassert_not_null(pthread_getspecific); + zassert_not_null(pthread_join); + zassert_not_null(pthread_key_create); + zassert_not_null(pthread_key_delete); + /* zassert_not_null(pthread_mutex_consistent); */ /* not implemented */ + zassert_not_null(pthread_mutex_destroy); + /* zassert_not_null(pthread_mutex_getprioceiling); */ /* not implemented */ + zassert_not_null(pthread_mutex_init); + zassert_not_null(pthread_mutex_lock); + /* zassert_not_null(pthread_mutex_setprioceiling); */ /* not implemented */ + zassert_not_null(pthread_mutex_timedlock); + zassert_not_null(pthread_mutex_trylock); + zassert_not_null(pthread_mutex_unlock); + zassert_not_null(pthread_mutexattr_destroy); + /* zassert_not_null(pthread_mutexattr_getprioceiling); */ /* not implemented */ + zassert_not_null(pthread_mutexattr_getprotocol); + /* zassert_not_null(pthread_mutexattr_getpshared); */ /* not implemented */ + /* zassert_not_null(pthread_mutexattr_getrobust); */ /* not implemented */ + zassert_not_null(pthread_mutexattr_gettype); + zassert_not_null(pthread_mutexattr_init); + /* zassert_not_null(pthread_mutexattr_setprioceiling); */ /* not implemented */ + /* zassert_not_null(pthread_mutexattr_setprotocol); */ /* not implemented */ + /* zassert_not_null(pthread_mutexattr_setpshared); */ /* not implemented */ + /* zassert_not_null(pthread_mutexattr_setrobust); */ /* not implemented */ + zassert_not_null(pthread_mutexattr_settype); + zassert_not_null(pthread_once); + zassert_not_null(pthread_rwlock_destroy); + zassert_not_null(pthread_rwlock_init); + zassert_not_null(pthread_rwlock_rdlock); + zassert_not_null(pthread_rwlock_timedrdlock); + zassert_not_null(pthread_rwlock_timedwrlock); + zassert_not_null(pthread_rwlock_tryrdlock); + zassert_not_null(pthread_rwlock_trywrlock); + zassert_not_null(pthread_rwlock_unlock); + zassert_not_null(pthread_rwlock_wrlock); + zassert_not_null(pthread_rwlockattr_destroy); + zassert_not_null(pthread_rwlockattr_getpshared); + zassert_not_null(pthread_rwlockattr_init); + zassert_not_null(pthread_rwlockattr_setpshared); + zassert_not_null(pthread_self); + zassert_not_null(pthread_setcancelstate); + zassert_not_null(pthread_setcanceltype); + zassert_not_null(pthread_setconcurrency); + zassert_not_null(pthread_setschedparam); + zassert_not_null(pthread_setschedprio); + zassert_not_null(pthread_setspecific); + zassert_not_null(pthread_spin_destroy); + zassert_not_null(pthread_spin_init); + zassert_not_null(pthread_spin_lock); + zassert_not_null(pthread_spin_trylock); + zassert_not_null(pthread_spin_unlock); + zassert_not_null(pthread_testcancel); +#endif } #pragma GCC diagnostic pop From 1426350bcfb5e50abb27a3082174671a0ee5522d Mon Sep 17 00:00:00 2001 From: Chris Friedt Date: Mon, 20 May 2024 17:51:35 -0400 Subject: [PATCH 1722/2849] posix: sysconf: correct typo on _SC_MAPPED_FILE(S) The standard macro is plural - so _SC_MAPPED_FILES - which corresponds to _POSIX_MAPPED_FILES. In Zephyr, we previously had _SC_MAPPED_FILE and _POSIX_MAPPED_FILE, so it's a simple correction. Signed-off-by: Chris Friedt --- include/zephyr/posix/sys/sysconf.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/include/zephyr/posix/sys/sysconf.h b/include/zephyr/posix/sys/sysconf.h index a88f16493e187..b027f2fc5c889 100644 --- a/include/zephyr/posix/sys/sysconf.h +++ b/include/zephyr/posix/sys/sysconf.h @@ -1,5 +1,6 @@ /* * Copyright (c) 2024, Meta + * Copyright (c) 2024, Tenstorrent AI ULC * * SPDX-License-Identifier: Apache-2.0 */ @@ -21,7 +22,7 @@ enum { _SC_FSYNC, _SC_IPV6, _SC_JOB_CONTROL, - _SC_MAPPED_FILE, + _SC_MAPPED_FILES, _SC_MEMLOCK, _SC_MEMLOCK_RANGE, _SC_MEMORY_PROTECTION, @@ -149,7 +150,7 @@ enum { #define __z_posix_sysconf_SC_FSYNC _POSIX_FSYNC #define __z_posix_sysconf_SC_IPV6 _POSIX_IPV6 #define __z_posix_sysconf_SC_JOB_CONTROL _POSIX_JOB_CONTROL -#define __z_posix_sysconf_SC_MAPPED_FILE _POSIX_MAPPED_FILES +#define __z_posix_sysconf_SC_MAPPED_FILES _POSIX_MAPPED_FILES #define __z_posix_sysconf_SC_MEMLOCK _POSIX_MEMLOCK #define __z_posix_sysconf_SC_MEMLOCK_RANGE _POSIX_MEMLOCK_RANGE #define __z_posix_sysconf_SC_MEMORY_PROTECTION _POSIX_MEMORY_PROTECTION From e83c37401585d01d5296177797297488e49284ce Mon Sep 17 00:00:00 2001 From: Chris Friedt Date: Mon, 20 May 2024 22:32:33 -0400 Subject: [PATCH 1723/2849] tests: posix: headers: enable checks for sysconf() constants For some reason, even though sysconf() has multiple implementations in Zephyr, the header tests were not checking for the existence of _SC_ constants. Uncomment the checks - they should be run on a regular basis. Signed-off-by: Chris Friedt --- include/zephyr/posix/sys/sysconf.h | 6 +- tests/posix/headers/src/unistd_h.c | 252 ++++++++++++++--------------- 2 files changed, 127 insertions(+), 131 deletions(-) diff --git a/include/zephyr/posix/sys/sysconf.h b/include/zephyr/posix/sys/sysconf.h index b027f2fc5c889..54bdd8e4a1a35 100644 --- a/include/zephyr/posix/sys/sysconf.h +++ b/include/zephyr/posix/sys/sysconf.h @@ -11,8 +11,6 @@ extern "C" { #endif -#ifdef CONFIG_POSIX_SYSCONF - enum { _SC_ADVISORY_INFO, _SC_ASYNCHRONOUS_IO, @@ -141,7 +139,6 @@ enum { _SC_TZNAME_MAX, }; -#ifdef CONFIG_POSIX_SYSCONF_IMPL_MACRO #define __z_posix_sysconf_SC_ADVISORY_INFO _POSIX_ADVISORY_INFO #define __z_posix_sysconf_SC_ASYNCHRONOUS_IO _POSIX_ASYNCHRONOUS_IO #define __z_posix_sysconf_SC_BARRIERS _POSIX_BARRIERS @@ -268,11 +265,10 @@ enum { #define __z_posix_sysconf_SC_TTY_NAME_MAX TTY_NAME_MAX #define __z_posix_sysconf_SC_TZNAME_MAX TZNAME_MAX +#ifdef CONFIG_POSIX_SYSCONF_IMPL_MACRO #define sysconf(x) (long)CONCAT(__z_posix_sysconf, x) #endif -#endif - #ifdef __cplusplus } #endif diff --git a/tests/posix/headers/src/unistd_h.c b/tests/posix/headers/src/unistd_h.c index bf713c0aca948..048b0e5f1436e 100644 --- a/tests/posix/headers/src/unistd_h.c +++ b/tests/posix/headers/src/unistd_h.c @@ -70,137 +70,137 @@ ZTEST(posix_headers, test_unistd_h) /* zassert_not_equal(INT_MIN, _PC_TIMESTAMP_RESOLUTION); */ /* not implemented */ /* zassert_not_equal(INT_MIN, _PC_VDISABLE); */ /* not implemented */ - /* zassert_not_equal(INT_MIN, _SC_2_C_BIND); */ /* not implemented */ - /* zassert_not_equal(INT_MIN, _SC_2_C_DEV); */ /* not implemented */ - /* zassert_not_equal(INT_MIN, _SC_2_CHAR_TERM); */ /* not implemented */ - /* zassert_not_equal(INT_MIN, _SC_2_FORT_DEV); */ /* not implemented */ - /* zassert_not_equal(INT_MIN, _SC_2_FORT_RUN); */ /* not implemented */ - /* zassert_not_equal(INT_MIN, _SC_2_LOCALEDEF); */ /* not implemented */ - /* zassert_not_equal(INT_MIN, _SC_2_PBS); */ /* not implemented */ - /* zassert_not_equal(INT_MIN, _SC_2_PBS_ACCOUNTING); */ /* not implemented */ - /* zassert_not_equal(INT_MIN, _SC_2_PBS_CHECKPOINT); */ /* not implemented */ - /* zassert_not_equal(INT_MIN, _SC_2_PBS_LOCATE); */ /* not implemented */ - /* zassert_not_equal(INT_MIN, _SC_2_PBS_MESSAGE); */ /* not implemented */ - /* zassert_not_equal(INT_MIN, _SC_2_PBS_TRACK); */ /* not implemented */ - /* zassert_not_equal(INT_MIN, _SC_2_SW_DEV); */ /* not implemented */ - /* zassert_not_equal(INT_MIN, _SC_2_UPE); */ /* not implemented */ - /* zassert_not_equal(INT_MIN, _SC_2_VERSION); */ /* not implemented */ - /* zassert_not_equal(INT_MIN, _SC_ADVISORY_INFO); */ /* not implemented */ - /* zassert_not_equal(INT_MIN, _SC_AIO_LISTIO_MAX); */ /* not implemented */ - /* zassert_not_equal(INT_MIN, _SC_AIO_MAX); */ /* not implemented */ - /* zassert_not_equal(INT_MIN, _SC_AIO_PRIO_DELTA_MAX); */ /* not implemented */ - /* zassert_not_equal(INT_MIN, _SC_ARG_MAX); */ /* not implemented */ - /* zassert_not_equal(INT_MIN, _SC_ASYNCHRONOUS_IO); */ /* not implemented */ - /* zassert_not_equal(INT_MIN, _SC_ATEXIT_MAX); */ /* not implemented */ - /* zassert_not_equal(INT_MIN, _SC_BARRIERS); */ /* not implemented */ - /* zassert_not_equal(INT_MIN, _SC_BC_BASE_MAX); */ /* not implemented */ - /* zassert_not_equal(INT_MIN, _SC_BC_DIM_MAX); */ /* not implemented */ - /* zassert_not_equal(INT_MIN, _SC_BC_SCALE_MAX); */ /* not implemented */ - /* zassert_not_equal(INT_MIN, _SC_BC_STRING_MAX); */ /* not implemented */ - /* zassert_not_equal(INT_MIN, _SC_CHILD_MAX); */ /* not implemented */ - /* zassert_not_equal(INT_MIN, _SC_CLK_TCK); */ /* not implemented */ - /* zassert_not_equal(INT_MIN, _SC_CLOCK_SELECTION); */ /* not implemented */ - /* zassert_not_equal(INT_MIN, _SC_COLL_WEIGHTS_MAX); */ /* not implemented */ - /* zassert_not_equal(INT_MIN, _SC_CPUTIME); */ /* not implemented */ - /* zassert_not_equal(INT_MIN, _SC_DELAYTIMER_MAX); */ /* not implemented */ - /* zassert_not_equal(INT_MIN, _SC_EXPR_NEST_MAX); */ /* not implemented */ - /* zassert_not_equal(INT_MIN, _SC_FSYNC); */ /* not implemented */ - /* zassert_not_equal(INT_MIN, _SC_GETGR_R_SIZE_MAX); */ /* not implemented */ - /* zassert_not_equal(INT_MIN, _SC_GETPW_R_SIZE_MAX); */ /* not implemented */ - /* zassert_not_equal(INT_MIN, _SC_HOST_NAME_MAX); */ /* not implemented */ - /* zassert_not_equal(INT_MIN, _SC_IOV_MAX); */ /* not implemented */ - /* zassert_not_equal(INT_MIN, _SC_IPV6); */ /* not implemented */ - /* zassert_not_equal(INT_MIN, _SC_JOB_CONTROL); */ /* not implemented */ - /* zassert_not_equal(INT_MIN, _SC_LINE_MAX); */ /* not implemented */ - /* zassert_not_equal(INT_MIN, _SC_LOGIN_NAME_MAX); */ /* not implemented */ - /* zassert_not_equal(INT_MIN, _SC_MAPPED_FILES); */ /* not implemented */ - /* zassert_not_equal(INT_MIN, _SC_MEMLOCK); */ /* not implemented */ - /* zassert_not_equal(INT_MIN, _SC_MEMLOCK_RANGE); */ /* not implemented */ - /* zassert_not_equal(INT_MIN, _SC_MEMORY_PROTECTION); */ /* not implemented */ - /* zassert_not_equal(INT_MIN, _SC_MESSAGE_PASSING); */ /* not implemented */ - /* zassert_not_equal(INT_MIN, _SC_MONOTONIC_CLOCK); */ /* not implemented */ - /* zassert_not_equal(INT_MIN, _SC_MQ_OPEN_MAX); */ /* not implemented */ - /* zassert_not_equal(INT_MIN, _SC_MQ_PRIO_MAX); */ /* not implemented */ - /* zassert_not_equal(INT_MIN, _SC_NGROUPS_MAX); */ /* not implemented */ - /* zassert_not_equal(INT_MIN, _SC_OPEN_MAX); */ /* not implemented */ - /* zassert_not_equal(INT_MIN, _SC_PAGE_SIZE); */ /* not implemented */ - /* zassert_not_equal(INT_MIN, _SC_PAGESIZE); */ /* not implemented */ - /* zassert_not_equal(INT_MIN, _SC_PRIORITIZED_IO); */ /* not implemented */ - /* zassert_not_equal(INT_MIN, _SC_PRIORITY_SCHEDULING); */ /* not implemented */ - /* zassert_not_equal(INT_MIN, _SC_RAW_SOCKETS); */ /* not implemented */ - /* zassert_not_equal(INT_MIN, _SC_RE_DUP_MAX); */ /* not implemented */ - /* zassert_not_equal(INT_MIN, _SC_READER_WRITER_LOCKS); */ /* not implemented */ - /* zassert_not_equal(INT_MIN, _SC_REALTIME_SIGNALS); */ /* not implemented */ - /* zassert_not_equal(INT_MIN, _SC_REGEXP); */ /* not implemented */ - /* zassert_not_equal(INT_MIN, _SC_RTSIG_MAX); */ /* not implemented */ - /* zassert_not_equal(INT_MIN, _SC_SAVED_IDS); */ /* not implemented */ - /* zassert_not_equal(INT_MIN, _SC_SEM_NSEMS_MAX); */ /* not implemented */ - /* zassert_not_equal(INT_MIN, _SC_SEM_VALUE_MAX); */ /* not implemented */ - /* zassert_not_equal(INT_MIN, _SC_SEMAPHORES); */ /* not implemented */ - /* zassert_not_equal(INT_MIN, _SC_SHARED_MEMORY_OBJECTS); */ /* not implemented */ - /* zassert_not_equal(INT_MIN, _SC_SHELL); */ /* not implemented */ - /* zassert_not_equal(INT_MIN, _SC_SIGQUEUE_MAX); */ /* not implemented */ - /* zassert_not_equal(INT_MIN, _SC_SPAWN); */ /* not implemented */ - /* zassert_not_equal(INT_MIN, _SC_SPIN_LOCKS); */ /* not implemented */ - /* zassert_not_equal(INT_MIN, _SC_SPORADIC_SERVER); */ /* not implemented */ - /* zassert_not_equal(INT_MIN, _SC_SS_REPL_MAX); */ /* not implemented */ - /* zassert_not_equal(INT_MIN, _SC_STREAM_MAX); */ /* not implemented */ - /* zassert_not_equal(INT_MIN, _SC_SYMLOOP_MAX); */ /* not implemented */ - /* zassert_not_equal(INT_MIN, _SC_SYNCHRONIZED_IO); */ /* not implemented */ - /* zassert_not_equal(INT_MIN, _SC_THREAD_ATTR_STACKADDR); */ /* not implemented */ - /* zassert_not_equal(INT_MIN, _SC_THREAD_ATTR_STACKSIZE); */ /* not implemented */ - /* zassert_not_equal(INT_MIN, _SC_THREAD_CPUTIME); */ /* not implemented */ - /* zassert_not_equal(INT_MIN, _SC_THREAD_DESTRUCTOR_ITERATIONS); */ /* not implemented */ - /* zassert_not_equal(INT_MIN, _SC_THREAD_KEYS_MAX); */ /* not implemented */ - /* zassert_not_equal(INT_MIN, _SC_THREAD_PRIO_INHERIT); */ /* not implemented */ - /* zassert_not_equal(INT_MIN, _SC_THREAD_PRIO_PROTECT); */ /* not implemented */ - /* zassert_not_equal(INT_MIN, _SC_THREAD_PRIORITY_SCHEDULING); */ /* not implemented */ - /* zassert_not_equal(INT_MIN, _SC_THREAD_PROCESS_SHARED); */ /* not implemented */ - /* zassert_not_equal(INT_MIN, _SC_THREAD_ROBUST_PRIO_INHERIT); */ /* not implemented */ - /* zassert_not_equal(INT_MIN, _SC_THREAD_ROBUST_PRIO_PROTECT); */ /* not implemented */ - /* zassert_not_equal(INT_MIN, _SC_THREAD_SAFE_FUNCTIONS); */ /* not implemented */ - /* zassert_not_equal(INT_MIN, _SC_THREAD_SPORADIC_SERVER); */ /* not implemented */ - /* zassert_not_equal(INT_MIN, _SC_THREAD_STACK_MIN); */ /* not implemented */ - /* zassert_not_equal(INT_MIN, _SC_THREAD_THREADS_MAX); */ /* not implemented */ - /* zassert_not_equal(INT_MIN, _SC_THREADS); */ /* not implemented */ - /* zassert_not_equal(INT_MIN, _SC_TIMEOUTS); */ /* not implemented */ - /* zassert_not_equal(INT_MIN, _SC_TIMER_MAX); */ /* not implemented */ - /* zassert_not_equal(INT_MIN, _SC_TIMERS); */ /* not implemented */ - /* zassert_not_equal(INT_MIN, _SC_TRACE); */ /* not implemented */ - /* zassert_not_equal(INT_MIN, _SC_TRACE_EVENT_FILTER); */ /* not implemented */ - /* zassert_not_equal(INT_MIN, _SC_TRACE_EVENT_NAME_MAX); */ /* not implemented */ - /* zassert_not_equal(INT_MIN, _SC_TRACE_INHERIT); */ /* not implemented */ - /* zassert_not_equal(INT_MIN, _SC_TRACE_LOG); */ /* not implemented */ - /* zassert_not_equal(INT_MIN, _SC_TRACE_NAME_MAX); */ /* not implemented */ - /* zassert_not_equal(INT_MIN, _SC_TRACE_SYS_MAX); */ /* not implemented */ - /* zassert_not_equal(INT_MIN, _SC_TRACE_USER_EVENT_MAX); */ /* not implemented */ - /* zassert_not_equal(INT_MIN, _SC_TTY_NAME_MAX); */ /* not implemented */ - /* zassert_not_equal(INT_MIN, _SC_TYPED_MEMORY_OBJECTS); */ /* not implemented */ - /* zassert_not_equal(INT_MIN, _SC_TZNAME_MAX); */ /* not implemented */ - /* zassert_not_equal(INT_MIN, _SC_V7_ILP32_OFF32); */ /* not implemented */ - /* zassert_not_equal(INT_MIN, _SC_V7_ILP32_OFFBIG); */ /* not implemented */ - /* zassert_not_equal(INT_MIN, _SC_V7_LP64_OFF64); */ /* not implemented */ - /* zassert_not_equal(INT_MIN, _SC_V7_LPBIG_OFFBIG); */ /* not implemented */ - /* zassert_not_equal(INT_MIN, _SC_V6_ILP32_OFF32); */ /* not implemented */ - /* zassert_not_equal(INT_MIN, _SC_V6_ILP32_OFFBIG); */ /* not implemented */ - /* zassert_not_equal(INT_MIN, _SC_V6_LP64_OFF64); */ /* not implemented */ - /* zassert_not_equal(INT_MIN, _SC_V6_LPBIG_OFFBIG); */ /* not implemented */ - /* zassert_not_equal(INT_MIN, _SC_VERSION); */ /* not implemented */ - /* zassert_not_equal(INT_MIN, _SC_XOPEN_CRYPT); */ /* not implemented */ - /* zassert_not_equal(INT_MIN, _SC_XOPEN_ENH_I18N); */ /* not implemented */ - /* zassert_not_equal(INT_MIN, _SC_XOPEN_REALTIME); */ /* not implemented */ - /* zassert_not_equal(INT_MIN, _SC_XOPEN_REALTIME_THREADS); */ /* not implemented */ - /* zassert_not_equal(INT_MIN, _SC_XOPEN_SHM); */ /* not implemented */ - /* zassert_not_equal(INT_MIN, _SC_XOPEN_STREAMS); */ /* not implemented */ - /* zassert_not_equal(INT_MIN, _SC_XOPEN_UNIX); */ /* not implemented */ - /* zassert_not_equal(INT_MIN, _SC_XOPEN_UUCP); */ /* not implemented */ - /* zassert_not_equal(INT_MIN, _SC_XOPEN_VERSION); */ /* not implemented */ + zassert_not_equal(INT_MIN, _SC_2_C_BIND); + zassert_not_equal(INT_MIN, _SC_2_C_DEV); + zassert_not_equal(INT_MIN, _SC_2_CHAR_TERM); + zassert_not_equal(INT_MIN, _SC_2_FORT_DEV); + zassert_not_equal(INT_MIN, _SC_2_FORT_RUN); + zassert_not_equal(INT_MIN, _SC_2_LOCALEDEF); + zassert_not_equal(INT_MIN, _SC_2_PBS); + zassert_not_equal(INT_MIN, _SC_2_PBS_ACCOUNTING); + zassert_not_equal(INT_MIN, _SC_2_PBS_CHECKPOINT); + zassert_not_equal(INT_MIN, _SC_2_PBS_LOCATE); + zassert_not_equal(INT_MIN, _SC_2_PBS_MESSAGE); + zassert_not_equal(INT_MIN, _SC_2_PBS_TRACK); + zassert_not_equal(INT_MIN, _SC_2_SW_DEV); + zassert_not_equal(INT_MIN, _SC_2_UPE); + zassert_not_equal(INT_MIN, _SC_2_VERSION); + zassert_not_equal(INT_MIN, _SC_ADVISORY_INFO); + zassert_not_equal(INT_MIN, _SC_AIO_LISTIO_MAX); + zassert_not_equal(INT_MIN, _SC_AIO_MAX); + zassert_not_equal(INT_MIN, _SC_AIO_PRIO_DELTA_MAX); + zassert_not_equal(INT_MIN, _SC_ARG_MAX); + zassert_not_equal(INT_MIN, _SC_ASYNCHRONOUS_IO); + zassert_not_equal(INT_MIN, _SC_ATEXIT_MAX); + zassert_not_equal(INT_MIN, _SC_BARRIERS); + zassert_not_equal(INT_MIN, _SC_BC_BASE_MAX); + zassert_not_equal(INT_MIN, _SC_BC_DIM_MAX); + zassert_not_equal(INT_MIN, _SC_BC_SCALE_MAX); + zassert_not_equal(INT_MIN, _SC_BC_STRING_MAX); + zassert_not_equal(INT_MIN, _SC_CHILD_MAX); + zassert_not_equal(INT_MIN, _SC_CLK_TCK); + zassert_not_equal(INT_MIN, _SC_CLOCK_SELECTION); + zassert_not_equal(INT_MIN, _SC_COLL_WEIGHTS_MAX); + zassert_not_equal(INT_MIN, _SC_CPUTIME); + zassert_not_equal(INT_MIN, _SC_DELAYTIMER_MAX); + zassert_not_equal(INT_MIN, _SC_EXPR_NEST_MAX); + zassert_not_equal(INT_MIN, _SC_FSYNC); + zassert_not_equal(INT_MIN, _SC_GETGR_R_SIZE_MAX); + zassert_not_equal(INT_MIN, _SC_GETPW_R_SIZE_MAX); + zassert_not_equal(INT_MIN, _SC_HOST_NAME_MAX); + zassert_not_equal(INT_MIN, _SC_IOV_MAX); + zassert_not_equal(INT_MIN, _SC_IPV6); + zassert_not_equal(INT_MIN, _SC_JOB_CONTROL); + zassert_not_equal(INT_MIN, _SC_LINE_MAX); + zassert_not_equal(INT_MIN, _SC_LOGIN_NAME_MAX); + zassert_not_equal(INT_MIN, _SC_MAPPED_FILES); + zassert_not_equal(INT_MIN, _SC_MEMLOCK); + zassert_not_equal(INT_MIN, _SC_MEMLOCK_RANGE); + zassert_not_equal(INT_MIN, _SC_MEMORY_PROTECTION); + zassert_not_equal(INT_MIN, _SC_MESSAGE_PASSING); + zassert_not_equal(INT_MIN, _SC_MONOTONIC_CLOCK); + zassert_not_equal(INT_MIN, _SC_MQ_OPEN_MAX); + zassert_not_equal(INT_MIN, _SC_MQ_PRIO_MAX); + zassert_not_equal(INT_MIN, _SC_NGROUPS_MAX); + zassert_not_equal(INT_MIN, _SC_OPEN_MAX); + zassert_not_equal(INT_MIN, _SC_PAGE_SIZE); + zassert_not_equal(INT_MIN, _SC_PAGESIZE); + zassert_not_equal(INT_MIN, _SC_PRIORITIZED_IO); + zassert_not_equal(INT_MIN, _SC_PRIORITY_SCHEDULING); + zassert_not_equal(INT_MIN, _SC_RAW_SOCKETS); + zassert_not_equal(INT_MIN, _SC_RE_DUP_MAX); + zassert_not_equal(INT_MIN, _SC_READER_WRITER_LOCKS); + zassert_not_equal(INT_MIN, _SC_REALTIME_SIGNALS); + zassert_not_equal(INT_MIN, _SC_REGEXP); + zassert_not_equal(INT_MIN, _SC_RTSIG_MAX); + zassert_not_equal(INT_MIN, _SC_SAVED_IDS); + zassert_not_equal(INT_MIN, _SC_SEM_NSEMS_MAX); + zassert_not_equal(INT_MIN, _SC_SEM_VALUE_MAX); + zassert_not_equal(INT_MIN, _SC_SEMAPHORES); + zassert_not_equal(INT_MIN, _SC_SHARED_MEMORY_OBJECTS); + zassert_not_equal(INT_MIN, _SC_SHELL); + zassert_not_equal(INT_MIN, _SC_SIGQUEUE_MAX); + zassert_not_equal(INT_MIN, _SC_SPAWN); + zassert_not_equal(INT_MIN, _SC_SPIN_LOCKS); + zassert_not_equal(INT_MIN, _SC_SPORADIC_SERVER); + zassert_not_equal(INT_MIN, _SC_SS_REPL_MAX); + zassert_not_equal(INT_MIN, _SC_STREAM_MAX); + zassert_not_equal(INT_MIN, _SC_SYMLOOP_MAX); + zassert_not_equal(INT_MIN, _SC_SYNCHRONIZED_IO); + zassert_not_equal(INT_MIN, _SC_THREAD_ATTR_STACKADDR); + zassert_not_equal(INT_MIN, _SC_THREAD_ATTR_STACKSIZE); + zassert_not_equal(INT_MIN, _SC_THREAD_CPUTIME); + zassert_not_equal(INT_MIN, _SC_THREAD_DESTRUCTOR_ITERATIONS); + zassert_not_equal(INT_MIN, _SC_THREAD_KEYS_MAX); + zassert_not_equal(INT_MIN, _SC_THREAD_PRIO_INHERIT); + zassert_not_equal(INT_MIN, _SC_THREAD_PRIO_PROTECT); + zassert_not_equal(INT_MIN, _SC_THREAD_PRIORITY_SCHEDULING); + zassert_not_equal(INT_MIN, _SC_THREAD_PROCESS_SHARED); + zassert_not_equal(INT_MIN, _SC_THREAD_ROBUST_PRIO_INHERIT); + zassert_not_equal(INT_MIN, _SC_THREAD_ROBUST_PRIO_PROTECT); + zassert_not_equal(INT_MIN, _SC_THREAD_SAFE_FUNCTIONS); + zassert_not_equal(INT_MIN, _SC_THREAD_SPORADIC_SERVER); + zassert_not_equal(INT_MIN, _SC_THREAD_STACK_MIN); + zassert_not_equal(INT_MIN, _SC_THREAD_THREADS_MAX); + zassert_not_equal(INT_MIN, _SC_THREADS); + zassert_not_equal(INT_MIN, _SC_TIMEOUTS); + zassert_not_equal(INT_MIN, _SC_TIMER_MAX); + zassert_not_equal(INT_MIN, _SC_TIMERS); + zassert_not_equal(INT_MIN, _SC_TRACE); + zassert_not_equal(INT_MIN, _SC_TRACE_EVENT_FILTER); + zassert_not_equal(INT_MIN, _SC_TRACE_EVENT_NAME_MAX); + zassert_not_equal(INT_MIN, _SC_TRACE_INHERIT); + zassert_not_equal(INT_MIN, _SC_TRACE_LOG); + zassert_not_equal(INT_MIN, _SC_TRACE_NAME_MAX); + zassert_not_equal(INT_MIN, _SC_TRACE_SYS_MAX); + zassert_not_equal(INT_MIN, _SC_TRACE_USER_EVENT_MAX); + zassert_not_equal(INT_MIN, _SC_TTY_NAME_MAX); + zassert_not_equal(INT_MIN, _SC_TYPED_MEMORY_OBJECTS); + zassert_not_equal(INT_MIN, _SC_TZNAME_MAX); + zassert_not_equal(INT_MIN, _SC_V7_ILP32_OFF32); + zassert_not_equal(INT_MIN, _SC_V7_ILP32_OFFBIG); + zassert_not_equal(INT_MIN, _SC_V7_LP64_OFF64); + zassert_not_equal(INT_MIN, _SC_V7_LPBIG_OFFBIG); + zassert_not_equal(INT_MIN, _SC_V6_ILP32_OFF32); + zassert_not_equal(INT_MIN, _SC_V6_ILP32_OFFBIG); + zassert_not_equal(INT_MIN, _SC_V6_LP64_OFF64); + zassert_not_equal(INT_MIN, _SC_V6_LPBIG_OFFBIG); + zassert_not_equal(INT_MIN, _SC_VERSION); + zassert_not_equal(INT_MIN, _SC_XOPEN_CRYPT); + zassert_not_equal(INT_MIN, _SC_XOPEN_ENH_I18N); + zassert_not_equal(INT_MIN, _SC_XOPEN_REALTIME); + zassert_not_equal(INT_MIN, _SC_XOPEN_REALTIME_THREADS); + zassert_not_equal(INT_MIN, _SC_XOPEN_SHM); + zassert_not_equal(INT_MIN, _SC_XOPEN_STREAMS); + zassert_not_equal(INT_MIN, _SC_XOPEN_UNIX); + zassert_not_equal(INT_MIN, _SC_XOPEN_UUCP); + zassert_not_equal(INT_MIN, _SC_XOPEN_VERSION); /* zassert_equal(STDERR_FILENO, 2); */ /* not implemented */ /* zassert_equal(STDIN_FILENO, 0); */ /* not implemented */ /* zassert_equal(STDOUT_FILENO, 1); */ /* not implemented */ - /* zassert_not_equal(INT_MIN, _POSIX_VDISABLE); */ /* not implemented */ + zassert_not_equal(INT_MIN, _POSIX_VDISABLE); /* * FIXME: this should really use IS_ENABLED() From c1dd480823879d8fdd669991d2c5df3324b43181 Mon Sep 17 00:00:00 2001 From: Chris Friedt Date: Mon, 20 May 2024 23:24:23 -0400 Subject: [PATCH 1724/2849] tests: posix: headers: enable checks for confstr() constants For some reason, even though confstr() is implemented in Zephyr, the header tests were not checking for the existence of _CS_ constants. Uncomment the tests so that they can be run regularly. Signed-off-by: Chris Friedt --- tests/posix/headers/src/unistd_h.c | 35 +++++++++++++++--------------- 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/tests/posix/headers/src/unistd_h.c b/tests/posix/headers/src/unistd_h.c index 048b0e5f1436e..55d1218c14a54 100644 --- a/tests/posix/headers/src/unistd_h.c +++ b/tests/posix/headers/src/unistd_h.c @@ -24,24 +24,23 @@ ZTEST(posix_headers, test_unistd_h) /* zassert_not_equal(-1, W_OK); */ /* not implemented */ /* zassert_not_equal(-1, X_OK); */ /* not implemented */ - /* zassert_not_equal(INT_MIN, _CS_PATH); */ /* not implemented */ - - /* zassert_not_equal(INT_MIN, _CS_POSIX_V7_ILP32_OFF32_CFLAGS); */ /* not implemented */ - /* zassert_not_equal(INT_MIN, _CS_POSIX_V7_ILP32_OFF32_LDFLAGS); */ /* not implemented */ - /* zassert_not_equal(INT_MIN, _CS_POSIX_V7_ILP32_OFF32_LIBS); */ /* not implemented */ - /* zassert_not_equal(INT_MIN, _CS_POSIX_V7_ILP32_OFFBIG_CFLAGS); */ /* not implemented */ - /* zassert_not_equal(INT_MIN, _CS_POSIX_V7_ILP32_OFFBIG_LDFLAGS); */ /* not implemented */ - /* zassert_not_equal(INT_MIN, _CS_POSIX_V7_ILP32_OFFBIG_LIBS); */ /* not implemented */ - /* zassert_not_equal(INT_MIN, _CS_POSIX_V7_LP64_OFF64_CFLAGS); */ /* not implemented */ - /* zassert_not_equal(INT_MIN, _CS_POSIX_V7_LP64_OFF64_LDFLAGS); */ /* not implemented */ - /* zassert_not_equal(INT_MIN, _CS_POSIX_V7_LP64_OFF64_LIBS); */ /* not implemented */ - /* zassert_not_equal(INT_MIN, _CS_POSIX_V7_LPBIG_OFFBIG_CFLAGS); */ /* not implemented */ - /* zassert_not_equal(INT_MIN, _CS_POSIX_V7_LPBIG_OFFBIG_LDFLAGS); */ /* not implemented */ - /* zassert_not_equal(INT_MIN, _CS_POSIX_V7_LPBIG_OFFBIG_LIBS); */ /* not implemented */ - /* zassert_not_equal(INT_MIN, _CS_POSIX_V7_THREADS_CFLAGS); */ /* not implemented */ - /* zassert_not_equal(INT_MIN, _CS_POSIX_V7_THREADS_LDFLAGS); */ /* not implemented */ - /* zassert_not_equal(INT_MIN, _CS_POSIX_V7_WIDTH_RESTRICTED_ENVS); */ /* not implemented */ - /* zassert_not_equal(INT_MIN, _CS_V7_ENV); */ /* not implemented */ + zassert_not_equal(INT_MIN, _CS_PATH); + zassert_not_equal(INT_MIN, _CS_POSIX_V7_ILP32_OFF32_CFLAGS); + zassert_not_equal(INT_MIN, _CS_POSIX_V7_ILP32_OFF32_LDFLAGS); + zassert_not_equal(INT_MIN, _CS_POSIX_V7_ILP32_OFF32_LIBS); + zassert_not_equal(INT_MIN, _CS_POSIX_V7_ILP32_OFFBIG_CFLAGS); + zassert_not_equal(INT_MIN, _CS_POSIX_V7_ILP32_OFFBIG_LDFLAGS); + zassert_not_equal(INT_MIN, _CS_POSIX_V7_ILP32_OFFBIG_LIBS); + zassert_not_equal(INT_MIN, _CS_POSIX_V7_LP64_OFF64_CFLAGS); + zassert_not_equal(INT_MIN, _CS_POSIX_V7_LP64_OFF64_LDFLAGS); + zassert_not_equal(INT_MIN, _CS_POSIX_V7_LP64_OFF64_LIBS); + zassert_not_equal(INT_MIN, _CS_POSIX_V7_LPBIG_OFFBIG_CFLAGS); + zassert_not_equal(INT_MIN, _CS_POSIX_V7_LPBIG_OFFBIG_LDFLAGS); + zassert_not_equal(INT_MIN, _CS_POSIX_V7_LPBIG_OFFBIG_LIBS); + zassert_not_equal(INT_MIN, _CS_POSIX_V7_THREADS_CFLAGS); + zassert_not_equal(INT_MIN, _CS_POSIX_V7_THREADS_LDFLAGS); + zassert_not_equal(INT_MIN, _CS_POSIX_V7_WIDTH_RESTRICTED_ENVS); + zassert_not_equal(INT_MIN, _CS_V7_ENV); /* zassert_not_equal(-1, F_LOCK); */ /* not implemented */ /* zassert_not_equal(-1, F_TEST); */ /* not implemented */ From 2dad7330129cff7b9bfdef67fc7ab10ff0cf0faa Mon Sep 17 00:00:00 2001 From: Chris Friedt Date: Mon, 20 May 2024 09:01:26 -0400 Subject: [PATCH 1725/2849] posix: unistd: move posix features to separate header file Move posix features to a separate header file and include that header file from unistd.h. Signed-off-by: Chris Friedt --- include/zephyr/posix/posix_features.h | 217 ++++++++++++++++++++++++++ include/zephyr/posix/signal.h | 2 +- include/zephyr/posix/unistd.h | 209 +------------------------ 3 files changed, 220 insertions(+), 208 deletions(-) create mode 100644 include/zephyr/posix/posix_features.h diff --git a/include/zephyr/posix/posix_features.h b/include/zephyr/posix/posix_features.h new file mode 100644 index 0000000000000..074823b9dc608 --- /dev/null +++ b/include/zephyr/posix/posix_features.h @@ -0,0 +1,217 @@ +/* + * Copyright (c) 2024 BayLibre SAS + * Copyright (c) 2024 Tenstorrent AI ULC + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef INCLUDE_ZEPHYR_POSIX_POSIX_FEATURES_H_ +#define INCLUDE_ZEPHYR_POSIX_POSIX_FEATURES_H_ + +#include /* CONFIG_* */ +#include /* COND_CODE_1() */ + +/* Version test macros */ +#define _POSIX_VERSION 200809L +#define _POSIX2_VERSION (-1L) +#define _XOPEN_VERSION (-1L) + +/* Internal helper macro to set constant if required Kconfig symbol is enabled */ +#define Z_SC_VAL_IFDEF(_def, _val) COND_CODE_1(_def, (_val), (-1L)) + +/* 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_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 (-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 (0) +#define _POSIX_PRIORITIZED_IO (-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) +#define _POSIX_REGEXP (-1L) +#define _POSIX_SAVED_IDS (-1L) +#define _POSIX_SEMAPHORES Z_SC_VAL_IFDEF(CONFIG_PTHREAD_IPC, _POSIX_VERSION) +#define _POSIX_SHARED_MEMORY_OBJECTS (-1L) +#define _POSIX_SHELL (-1L) +#define _POSIX_SPAWN (-1L) +#define _POSIX_SPIN_LOCKS Z_SC_VAL_IFDEF(CONFIG_PTHREAD_SPINLOCK, _POSIX_VERSION) +#define _POSIX_SPORADIC_SERVER (-1L) +#define _POSIX_SYNCHRONIZED_IO (-1L) +#define _POSIX_THREAD_ATTR_STACKADDR Z_SC_VAL_IFDEF(CONFIG_PTHREAD_IPC, _POSIX_VERSION) +#define _POSIX_THREAD_ATTR_STACKSIZE Z_SC_VAL_IFDEF(CONFIG_PTHREAD_IPC, _POSIX_VERSION) +#define _POSIX_THREAD_CPUTIME (-1L) +#define _POSIX_THREAD_PRIO_INHERIT _POSIX_VERSION +#define _POSIX_THREAD_PRIO_PROTECT (-1L) +#define _POSIX_THREAD_PRIORITY_SCHEDULING Z_SC_VAL_IFDEF(CONFIG_PTHREAD_IPC, _POSIX_VERSION) +#define _POSIX_THREAD_PROCESS_SHARED (-1L) +#define _POSIX_THREAD_ROBUST_PRIO_INHERIT (-1L) +#define _POSIX_THREAD_ROBUST_PRIO_PROTECT (-1L) +#define _POSIX_THREAD_SAFE_FUNCTIONS Z_SC_VAL_IFDEF(CONFIG_PTHREAD_IPC, _POSIX_VERSION) +#define _POSIX_THREAD_SPORADIC_SERVER (-1L) + +#ifndef _POSIX_THREADS +#define _POSIX_THREADS Z_SC_VAL_IFDEF(CONFIG_PTHREAD_IPC, _POSIX_VERSION) +#endif + +#define _POSIX_TIMEOUTS Z_SC_VAL_IFDEF(CONFIG_POSIX_CLOCK, _POSIX_VERSION) +#define _POSIX_TIMERS Z_SC_VAL_IFDEF(CONFIG_POSIX_CLOCK, _POSIX_VERSION) +#define _POSIX_TRACE (-1L) +#define _POSIX_TRACE_EVENT_FILTER (-1L) +#define _POSIX_TRACE_INHERIT (-1L) +#define _POSIX_TRACE_LOG (-1L) +#define _POSIX_TYPED_MEMORY_OBJECTS (-1L) +#define _POSIX_V6_ILP32_OFF32 (-1L) +#define _POSIX_V6_ILP32_OFFBIG (-1L) +#define _POSIX_V6_LP64_OFF64 (-1L) +#define _POSIX_V6_LPBIG_OFFBIG (-1L) +#define _POSIX_V7_ILP32_OFF32 (-1L) +#define _POSIX_V7_ILP32_OFFBIG (-1L) +#define _POSIX_V7_LP64_OFF64 (-1L) +#define _POSIX_V7_LPBIG_OFFBIG (-1L) +#define _POSIX2_C_BIND _POSIX_VERSION +#define _POSIX2_C_DEV (-1L) +#define _POSIX2_CHAR_TERM (-1L) +#define _POSIX2_DELAYTIMER_MAX (-1L) +#define _POSIX2_FORT_DEV (-1L) +#define _POSIX2_FORT_RUN (-1L) +#define _POSIX2_LOCALEDEF (-1L) +#define _POSIX2_PBS (-1L) +#define _POSIX2_PBS_ACCOUNTING (-1L) +#define _POSIX2_PBS_CHECKPOINT (-1L) +#define _POSIX2_PBS_LOCATE (-1L) +#define _POSIX2_PBS_MESSAGE (-1L) +#define _POSIX2_PBS_TRACK (-1L) +#define _POSIX2_SW_DEV (-1L) +#define _POSIX2_UPE (-1L) +#define _XOPEN_CRYPT (-1L) +#define _XOPEN_ENH_I18N (-1L) +#define _XOPEN_REALTIME (-1L) +#define _XOPEN_REALTIME_THREADS (-1L) +#define _XOPEN_SHM (-1L) +#define _XOPEN_STREAMS (-1L) +#define _XOPEN_UNIX (-1L) +#define _XOPEN_UUCP (-1L) + +/* Maximum values */ +#define _POSIX_CLOCKRES_MIN (20000000L) + +/* Minimum values */ +#define _POSIX_AIO_LISTIO_MAX (2) +#define _POSIX_AIO_MAX (1) +#define _POSIX_ARG_MAX (4096) +#define _POSIX_CHILD_MAX (25) +#define _POSIX_DELAYTIMER_MAX (32) +#define _POSIX_HOST_NAME_MAX (255) +#define _POSIX_LINK_MAX (8) +#define _POSIX_LOGIN_NAME_MAX (9) +#define _POSIX_MAX_CANON (255) +#define _POSIX_MAX_INPUT (255) +#define _POSIX_MQ_OPEN_MAX \ + Z_SC_VAL_IFDEF(CONFIG_POSIX_MQUEUE, CONFIG_MSG_COUNT_MAX) +#define _POSIX_MQ_PRIO_MAX (32) +#define _POSIX_NAME_MAX (14) +#define _POSIX_NGROUPS_MAX (8) +#define _POSIX_OPEN_MAX CONFIG_POSIX_MAX_FDS +#define _POSIX_PATH_MAX (256) +#define _POSIX_PIPE_BUF (512) +#define _POSIX_RE_DUP_MAX (255) +#define _POSIX_RTSIG_MAX \ + COND_CODE_1(CONFIG_POSIX_REALTIME_SIGNALS, (CONFIG_POSIX_RTSIG_MAX), (0)) +#define _POSIX_SEM_NSEMS_MAX CONFIG_SEM_NAMELEN_MAX +#define _POSIX_SEM_VALUE_MAX CONFIG_SEM_VALUE_MAX +#define _POSIX_SIGQUEUE_MAX (32) +#define _POSIX_SSIZE_MAX (32767) +#define _POSIX_SS_REPL_MAX (4) +#define _POSIX_STREAM_MAX (8) +#define _POSIX_SYMLINK_MAX (255) +#define _POSIX_SYMLOOP_MAX (8) +#define _POSIX_THREAD_DESTRUCTOR_ITERATIONS (4) +#define _POSIX_THREAD_KEYS_MAX (128) +#define _POSIX_THREAD_THREADS_MAX (64) +#define _POSIX_TIMER_MAX (32) +#define _POSIX_TRACE_EVENT_NAME_MAX (30) +#define _POSIX_TRACE_NAME_MAX (8) +#define _POSIX_TRACE_SYS_MAX (8) +#define _POSIX_TRACE_USER_EVENT_MAX (32) +#define _POSIX_TTY_NAME_MAX (9) +#define _POSIX_TZNAME_MAX (6) +#define _POSIX2_BC_BASE_MAX (99) +#define _POSIX2_BC_DIM_MAX (2048) +#define _POSIX2_BC_SCALE_MAX (99) +#define _POSIX2_BC_STRING_MAX (1000) +#define _POSIX2_CHARCLASS_NAME_MAX (14) +#define _POSIX2_COLL_WEIGHTS_MAX (2) +#define _POSIX2_EXPR_NEST_MAX (32) +#define _POSIX2_LINE_MAX (2048) +#define _XOPEN_IOV_MAX (16) +#define _XOPEN_NAME_MAX (255) +#define _XOPEN_PATH_MAX (1024) + +/* Other invariant values */ +#define NL_LANGMAX (14) +#define NL_MSGMAX (32767) +#define NL_SETMAX (255) +#define NL_TEXTMAX (_POSIX2_LINE_MAX) +#define NZERO (20) + +/* Runtime invariant values */ +#define AIO_LISTIO_MAX _POSIX_AIO_LISTIO_MAX +#define AIO_MAX _POSIX_AIO_MAX +#define AIO_PRIO_DELTA_MAX (0) +#define DELAYTIMER_MAX _POSIX_DELAYTIMER_MAX +#define HOST_NAME_MAX \ + COND_CODE_1(CONFIG_NETWORKING, (NET_HOSTNAME_MAX_LEN), (_POSIX_HOST_NAME_MAX)) +#define LOGIN_NAME_MAX _POSIX_LOGIN_NAME_MAX +#define MQ_OPEN_MAX _POSIX_MQ_OPEN_MAX +#define MQ_PRIO_MAX _POSIX_MQ_PRIO_MAX + +#ifndef ATEXIT_MAX +#define ATEXIT_MAX 8 +#endif + +#ifndef PAGE_SIZE +#define PAGE_SIZE BIT(CONFIG_POSIX_PAGE_SIZE_BITS) +#endif + +#ifndef PAGESIZE +#define PAGESIZE PAGE_SIZE +#endif + +#define PTHREAD_DESTRUCTOR_ITERATIONS _POSIX_THREAD_DESTRUCTOR_ITERATIONS +#define PTHREAD_KEYS_MAX \ + COND_CODE_1(CONFIG_PTHREAD_IPC, (CONFIG_MAX_PTHREAD_KEY_COUNT), (_POSIX_THREAD_KEYS_MAX)) +#define PTHREAD_THREADS_MAX COND_CODE_1(CONFIG_PTHREAD_IPC, (CONFIG_MAX_PTHREAD_COUNT), (0)) +#define SEM_NSEMS_MAX _POSIX_SEM_NSEMS_MAX +#define SEM_VALUE_MAX CONFIG_SEM_VALUE_MAX +#define SIGQUEUE_MAX _POSIX_SIGQUEUE_MAX +#define STREAM_MAX _POSIX_STREAM_MAX +#define SYMLOOP_MAX _POSIX_SYMLOOP_MAX +#define TIMER_MAX Z_SC_VAL_IFDEF(CONFIG_TIMER, CONFIG_MAX_TIMER_COUNT) +#define TTY_NAME_MAX _POSIX_TTY_NAME_MAX +#define TZNAME_MAX _POSIX_TZNAME_MAX + +/* Pathname variable values */ +#define FILESIZEBITS (32) +#define POSIX_ALLOC_SIZE_MIN (256) +#define POSIX_REC_INCR_XFER_SIZE (1024) +#define POSIX_REC_MAX_XFER_SIZE (32767) +#define POSIX_REC_MIN_XFER_SIZE (1) +#define POSIX_REC_XFER_ALIGN (4) +#define SYMLINK_MAX _POSIX_SYMLINK_MAX + +#endif /* INCLUDE_ZEPHYR_POSIX_POSIX_FEATURES_H_ */ diff --git a/include/zephyr/posix/signal.h b/include/zephyr/posix/signal.h index 3bbdee7317aca..b6942f026a8fc 100644 --- a/include/zephyr/posix/signal.h +++ b/include/zephyr/posix/signal.h @@ -7,6 +7,7 @@ #define ZEPHYR_INCLUDE_POSIX_SIGNAL_H_ #include "posix_types.h" +#include "posix_features.h" #ifdef __cplusplus extern "C" { @@ -44,7 +45,6 @@ extern "C" { /* 30 not used */ #define SIGSYS 31 /**< Bad system call */ -#define RTSIG_MAX CONFIG_POSIX_RTSIG_MAX #define SIGRTMIN 32 #define SIGRTMAX (SIGRTMIN + RTSIG_MAX) #define _NSIG (SIGRTMAX + 1) diff --git a/include/zephyr/posix/unistd.h b/include/zephyr/posix/unistd.h index f829ebac23513..e70ce1f806e1f 100644 --- a/include/zephyr/posix/unistd.h +++ b/include/zephyr/posix/unistd.h @@ -16,221 +16,16 @@ #include #include #endif -#ifdef CONFIG_POSIX_SYSCONF -#include -#endif #include #include #include +#include "posix_features.h" + #ifdef __cplusplus extern "C" { #endif -/* Version test macros */ -#define _POSIX_VERSION 200809L -#define _POSIX2_VERSION (-1L) -#define _XOPEN_VERSION (-1L) - -/* Internal helper macro to set constant if required Kconfig symbol is enabled */ -#define Z_SC_VAL_IFDEF(_def, _val) COND_CODE_1(_def, (_val), (-1L)) - -/* 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_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 (-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 (0) -#define _POSIX_PRIORITIZED_IO (-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) -#define _POSIX_REGEXP (-1L) -#define _POSIX_SAVED_IDS (-1L) -#define _POSIX_SEMAPHORES Z_SC_VAL_IFDEF(CONFIG_PTHREAD_IPC, _POSIX_VERSION) -#define _POSIX_SHARED_MEMORY_OBJECTS (-1L) -#define _POSIX_SHELL (-1L) -#define _POSIX_SPAWN (-1L) -#define _POSIX_SPIN_LOCKS Z_SC_VAL_IFDEF(CONFIG_PTHREAD_SPINLOCK, _POSIX_VERSION) -#define _POSIX_SPORADIC_SERVER (-1L) -#define _POSIX_SYNCHRONIZED_IO (-1L) -#define _POSIX_THREAD_ATTR_STACKADDR Z_SC_VAL_IFDEF(CONFIG_PTHREAD_IPC, _POSIX_VERSION) -#define _POSIX_THREAD_ATTR_STACKSIZE Z_SC_VAL_IFDEF(CONFIG_PTHREAD_IPC, _POSIX_VERSION) -#define _POSIX_THREAD_CPUTIME (-1L) -#define _POSIX_THREAD_PRIO_INHERIT _POSIX_VERSION -#define _POSIX_THREAD_PRIO_PROTECT (-1L) -#define _POSIX_THREAD_PRIORITY_SCHEDULING Z_SC_VAL_IFDEF(CONFIG_PTHREAD_IPC, _POSIX_VERSION) -#define _POSIX_THREAD_PROCESS_SHARED (-1L) -#define _POSIX_THREAD_ROBUST_PRIO_INHERIT (-1L) -#define _POSIX_THREAD_ROBUST_PRIO_PROTECT (-1L) -#define _POSIX_THREAD_SAFE_FUNCTIONS Z_SC_VAL_IFDEF(CONFIG_PTHREAD_IPC, _POSIX_VERSION) -#define _POSIX_THREAD_SPORADIC_SERVER (-1L) - -#ifndef _POSIX_THREADS -#define _POSIX_THREADS Z_SC_VAL_IFDEF(CONFIG_PTHREAD_IPC, _POSIX_VERSION) -#endif - -#define _POSIX_TIMEOUTS Z_SC_VAL_IFDEF(CONFIG_POSIX_CLOCK, _POSIX_VERSION) -#define _POSIX_TIMERS Z_SC_VAL_IFDEF(CONFIG_POSIX_CLOCK, _POSIX_VERSION) -#define _POSIX_TRACE (-1L) -#define _POSIX_TRACE_EVENT_FILTER (-1L) -#define _POSIX_TRACE_INHERIT (-1L) -#define _POSIX_TRACE_LOG (-1L) -#define _POSIX_TYPED_MEMORY_OBJECTS (-1L) -#define _POSIX_V6_ILP32_OFF32 (-1L) -#define _POSIX_V6_ILP32_OFFBIG (-1L) -#define _POSIX_V6_LP64_OFF64 (-1L) -#define _POSIX_V6_LPBIG_OFFBIG (-1L) -#define _POSIX_V7_ILP32_OFF32 (-1L) -#define _POSIX_V7_ILP32_OFFBIG (-1L) -#define _POSIX_V7_LP64_OFF64 (-1L) -#define _POSIX_V7_LPBIG_OFFBIG (-1L) -#define _POSIX2_C_BIND _POSIX_VERSION -#define _POSIX2_C_DEV (-1L) -#define _POSIX2_CHAR_TERM (-1L) -#define _POSIX2_DELAYTIMER_MAX (-1L) -#define _POSIX2_FORT_DEV (-1L) -#define _POSIX2_FORT_RUN (-1L) -#define _POSIX2_LOCALEDEF (-1L) -#define _POSIX2_PBS (-1L) -#define _POSIX2_PBS_ACCOUNTING (-1L) -#define _POSIX2_PBS_CHECKPOINT (-1L) -#define _POSIX2_PBS_LOCATE (-1L) -#define _POSIX2_PBS_MESSAGE (-1L) -#define _POSIX2_PBS_TRACK (-1L) -#define _POSIX2_SW_DEV (-1L) -#define _POSIX2_UPE (-1L) -#define _XOPEN_CRYPT (-1L) -#define _XOPEN_ENH_I18N (-1L) -#define _XOPEN_REALTIME (-1L) -#define _XOPEN_REALTIME_THREADS (-1L) -#define _XOPEN_SHM (-1L) -#define _XOPEN_STREAMS (-1L) -#define _XOPEN_UNIX (-1L) -#define _XOPEN_UUCP (-1L) - -/* Maximum values */ -#define _POSIX_CLOCKRES_MIN (20000000L) - -/* Minimum values */ -#define _POSIX_AIO_LISTIO_MAX (2) -#define _POSIX_AIO_MAX (1) -#define _POSIX_ARG_MAX (4096) -#define _POSIX_CHILD_MAX (25) -#define _POSIX_DELAYTIMER_MAX (32) -#define _POSIX_HOST_NAME_MAX (255) -#define _POSIX_LINK_MAX (8) -#define _POSIX_LOGIN_NAME_MAX (9) -#define _POSIX_MAX_CANON (255) -#define _POSIX_MAX_INPUT (255) -#define _POSIX_MQ_OPEN_MAX Z_SC_VAL_IFDEF(CONFIG_POSIX_MQUEUE, \ - CONFIG_MSG_COUNT_MAX) -#define _POSIX_MQ_PRIO_MAX (32) -#define _POSIX_NAME_MAX (14) -#define _POSIX_NGROUPS_MAX (8) -#define _POSIX_OPEN_MAX CONFIG_POSIX_MAX_FDS -#define _POSIX_PATH_MAX (256) -#define _POSIX_PIPE_BUF (512) -#define _POSIX_RE_DUP_MAX (255) -#define _POSIX_RTSIG_MAX CONFIG_POSIX_RTSIG_MAX -#define _POSIX_SEM_NSEMS_MAX CONFIG_SEM_NAMELEN_MAX -#define _POSIX_SEM_VALUE_MAX CONFIG_SEM_VALUE_MAX -#define _POSIX_SIGQUEUE_MAX (32) -#define _POSIX_SSIZE_MAX (32767) -#define _POSIX_SS_REPL_MAX (4) -#define _POSIX_STREAM_MAX (8) -#define _POSIX_SYMLINK_MAX (255) -#define _POSIX_SYMLOOP_MAX (8) -#define _POSIX_THREAD_DESTRUCTOR_ITERATIONS (4) -#define _POSIX_THREAD_KEYS_MAX (128) -#define _POSIX_THREAD_THREADS_MAX (64) -#define _POSIX_TIMER_MAX (32) -#define _POSIX_TRACE_EVENT_NAME_MAX (30) -#define _POSIX_TRACE_NAME_MAX (8) -#define _POSIX_TRACE_SYS_MAX (8) -#define _POSIX_TRACE_USER_EVENT_MAX (32) -#define _POSIX_TTY_NAME_MAX (9) -#define _POSIX_TZNAME_MAX (6) -#define _POSIX2_BC_BASE_MAX (99) -#define _POSIX2_BC_DIM_MAX (2048) -#define _POSIX2_BC_SCALE_MAX (99) -#define _POSIX2_BC_STRING_MAX (1000) -#define _POSIX2_CHARCLASS_NAME_MAX (14) -#define _POSIX2_COLL_WEIGHTS_MAX (2) -#define _POSIX2_EXPR_NEST_MAX (32) -#define _POSIX2_LINE_MAX (2048) -#define _XOPEN_IOV_MAX (16) -#define _XOPEN_NAME_MAX (255) -#define _XOPEN_PATH_MAX (1024) - -/* Other invariant values */ -#define NL_LANGMAX (14) -#define NL_MSGMAX (32767) -#define NL_SETMAX (255) -#define NL_TEXTMAX (_POSIX2_LINE_MAX) -#define NZERO (20) - -/* Runtime invariant values */ -#define AIO_LISTIO_MAX _POSIX_AIO_LISTIO_MAX -#define AIO_MAX _POSIX_AIO_MAX -#define AIO_PRIO_DELTA_MAX (0) -#define DELAYTIMER_MAX _POSIX_DELAYTIMER_MAX -#define HOST_NAME_MAX COND_CODE_1(CONFIG_NETWORKING, \ - (NET_HOSTNAME_MAX_LEN), \ - (_POSIX_HOST_NAME_MAX)) -#define LOGIN_NAME_MAX _POSIX_LOGIN_NAME_MAX -#define MQ_OPEN_MAX _POSIX_MQ_OPEN_MAX -#define MQ_PRIO_MAX _POSIX_MQ_PRIO_MAX - -#ifndef ATEXIT_MAX -#define ATEXIT_MAX 8 -#endif - -#ifndef PAGE_SIZE -#define PAGE_SIZE BIT(CONFIG_POSIX_PAGE_SIZE_BITS) -#endif - -#ifndef PAGESIZE -#define PAGESIZE PAGE_SIZE -#endif - -#define PTHREAD_DESTRUCTOR_ITERATIONS _POSIX_THREAD_DESTRUCTOR_ITERATIONS -#define PTHREAD_KEYS_MAX COND_CODE_1(CONFIG_PTHREAD_IPC, \ - (CONFIG_MAX_PTHREAD_KEY_COUNT), \ - (_POSIX_THREAD_KEYS_MAX)) -#define PTHREAD_THREADS_MAX COND_CODE_1(CONFIG_PTHREAD_IPC, \ - (CONFIG_MAX_PTHREAD_COUNT), \ - (0)) -#define SEM_NSEMS_MAX _POSIX_SEM_NSEMS_MAX -#define SEM_VALUE_MAX CONFIG_SEM_VALUE_MAX -#define SIGQUEUE_MAX _POSIX_SIGQUEUE_MAX -#define STREAM_MAX _POSIX_STREAM_MAX -#define SYMLOOP_MAX _POSIX_SYMLOOP_MAX -#define TIMER_MAX Z_SC_VAL_IFDEF(CONFIG_TIMER, CONFIG_MAX_TIMER_COUNT) -#define TTY_NAME_MAX _POSIX_TTY_NAME_MAX -#define TZNAME_MAX _POSIX_TZNAME_MAX - -/* Pathname variable values */ -#define FILESIZEBITS (32) -#define POSIX_ALLOC_SIZE_MIN (256) -#define POSIX_REC_INCR_XFER_SIZE (1024) -#define POSIX_REC_MAX_XFER_SIZE (32767) -#define POSIX_REC_MIN_XFER_SIZE (1) -#define POSIX_REC_XFER_ALIGN (4) -#define SYMLINK_MAX _POSIX_SYMLINK_MAX - #ifdef CONFIG_POSIX_API /* File related operations */ int close(int file); From 49ef0df67df04c994db9a81f89c0e204a8cbdd64 Mon Sep 17 00:00:00 2001 From: Chris Friedt Date: Mon, 20 May 2024 17:17:17 -0400 Subject: [PATCH 1726/2849] posix: features: leave feature test macros undefined if unimpl Rather than forcing the macro to -1, simply leave it undefined if the particular feature in question is unimplemented. This is the convention used by external libcs. Signed-off-by: Chris Friedt --- include/zephyr/posix/posix_features.h | 294 +++++++++++++++++--------- 1 file changed, 189 insertions(+), 105 deletions(-) diff --git a/include/zephyr/posix/posix_features.h b/include/zephyr/posix/posix_features.h index 074823b9dc608..09af5d3e6c584 100644 --- a/include/zephyr/posix/posix_features.h +++ b/include/zephyr/posix/posix_features.h @@ -11,101 +11,181 @@ #include /* CONFIG_* */ #include /* COND_CODE_1() */ -/* Version test macros */ -#define _POSIX_VERSION 200809L -#define _POSIX2_VERSION (-1L) -#define _XOPEN_VERSION (-1L) - -/* Internal helper macro to set constant if required Kconfig symbol is enabled */ -#define Z_SC_VAL_IFDEF(_def, _val) COND_CODE_1(_def, (_val), (-1L)) - -/* 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_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 (-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 (0) -#define _POSIX_PRIORITIZED_IO (-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) -#define _POSIX_REGEXP (-1L) -#define _POSIX_SAVED_IDS (-1L) -#define _POSIX_SEMAPHORES Z_SC_VAL_IFDEF(CONFIG_PTHREAD_IPC, _POSIX_VERSION) -#define _POSIX_SHARED_MEMORY_OBJECTS (-1L) -#define _POSIX_SHELL (-1L) -#define _POSIX_SPAWN (-1L) -#define _POSIX_SPIN_LOCKS Z_SC_VAL_IFDEF(CONFIG_PTHREAD_SPINLOCK, _POSIX_VERSION) -#define _POSIX_SPORADIC_SERVER (-1L) -#define _POSIX_SYNCHRONIZED_IO (-1L) -#define _POSIX_THREAD_ATTR_STACKADDR Z_SC_VAL_IFDEF(CONFIG_PTHREAD_IPC, _POSIX_VERSION) -#define _POSIX_THREAD_ATTR_STACKSIZE Z_SC_VAL_IFDEF(CONFIG_PTHREAD_IPC, _POSIX_VERSION) -#define _POSIX_THREAD_CPUTIME (-1L) -#define _POSIX_THREAD_PRIO_INHERIT _POSIX_VERSION -#define _POSIX_THREAD_PRIO_PROTECT (-1L) -#define _POSIX_THREAD_PRIORITY_SCHEDULING Z_SC_VAL_IFDEF(CONFIG_PTHREAD_IPC, _POSIX_VERSION) -#define _POSIX_THREAD_PROCESS_SHARED (-1L) -#define _POSIX_THREAD_ROBUST_PRIO_INHERIT (-1L) -#define _POSIX_THREAD_ROBUST_PRIO_PROTECT (-1L) -#define _POSIX_THREAD_SAFE_FUNCTIONS Z_SC_VAL_IFDEF(CONFIG_PTHREAD_IPC, _POSIX_VERSION) -#define _POSIX_THREAD_SPORADIC_SERVER (-1L) +/* + * POSIX System Interfaces + */ + +#define _POSIX_VERSION 200809L + +#define _POSIX_CHOWN_RESTRICTED (0) +#define _POSIX_NO_TRUNC (0) +#define _POSIX_VDISABLE ('\0') + +/* #define _POSIX_ADVISORY_INFO (-1L) */ + +#ifdef CONFIG_POSIX_ASYNCHRONOUS_IO +#define _POSIX_ASYNCHRONOUS_IO _POSIX_VERSION +#endif + +#ifdef CONFIG_PTHREAD_BARRIER +#define _POSIX_BARRIERS _POSIX_VERSION +#endif + +#ifdef CONFIG_POSIX_CLOCK +#define _POSIX_CLOCK_SELECTION _POSIX_VERSION +#endif + +/* #define _POSIX_CPUTIME (-1L) */ + +#ifdef CONFIG_POSIX_FSYNC +#define _POSIX_FSYNC _POSIX_VERSION +#endif + +#ifdef CONFIG_NET_IPV6 +#define _POSIX_IPV6 _POSIX_VERSION +#endif + +/* #define _POSIX_JOB_CONTROL (-1L) */ +/* #define _POSIX_MAPPED_FILES (-1L) */ +/* #define _POSIX_MEMLOCK (-1L) */ +/* #define _POSIX_MEMLOCK_RANGE (-1L) */ +/* #define _POSIX_MEMORY_PROTECTION (-1L) */ +#ifdef CONFIG_POSIX_MQUEUE +#define _POSIX_MESSAGE_PASSING _POSIX_VERSION +#endif + +#ifdef CONFIG_POSIX_CLOCK +#define _POSIX_MONOTONIC_CLOCK _POSIX_VERSION +#endif + +/* #define _POSIX_PRIORITIZED_IO (-1L) */ + +#ifdef CONFIG_POSIX_PRIORITY_SCHEDULING +#define _POSIX_PRIORITY_SCHEDULING _POSIX_VERSION +#endif + +#ifdef CONFIG_NET_SOCKETS_PACKET +#define _POSIX_RAW_SOCKETS _POSIX_VERSION +#endif + +#ifdef CONFIG_PTHREAD_IPC +#define _POSIX_READER_WRITER_LOCKS _POSIX_VERSION +#endif + +/* #define _POSIX_REALTIME_SIGNALS (-1L) */ +/* #define _POSIX_REGEXP (-1L) */ +/* #define _POSIX_SAVED_IDS (-1L) */ + +#ifdef CONFIG_PTHREAD_IPC +#define _POSIX_SEMAPHORES _POSIX_VERSION +#endif + +/* #define _POSIX_SHARED_MEMORY_OBJECTS (-1L) */ +/* #define _POSIX_SHELL (-1L) */ +/* #define _POSIX_SPAWN (-1L) */ + +#ifdef CONFIG_PTHREAD_SPINLOCK +#define _POSIX_SPIN_LOCKS _POSIX_VERSION +#endif + +/* #define _POSIX_SPORADIC_SERVER (-1L) */ +/* #define _POSIX_SYNCHRONIZED_IO (-1L) */ + +#ifdef CONFIG_PTHREAD_IPC +#define _POSIX_THREAD_ATTR_STACKADDR _POSIX_VERSION +#endif + +#ifdef CONFIG_PTHREAD_IPC +#define _POSIX_THREAD_ATTR_STACKSIZE _POSIX_VERSION +#endif + +/* #define _POSIX_THREAD_CPUTIME (-1L) */ + +#ifdef CONFIG_PTHREAD_IPC +#define _POSIX_THREAD_PRIO_INHERIT _POSIX_VERSION +#endif + +/* #define _POSIX_THREAD_PRIO_PROTECT (-1L) */ +/* #define _POSIX_THREAD_PRIORITY_SCHEDULING (-1L) */ +/* #define _POSIX_THREAD_PROCESS_SHARED (-1L) */ +/* #define _POSIX_THREAD_ROBUST_PRIO_INHERIT (-1L) */ +/* #define _POSIX_THREAD_ROBUST_PRIO_PROTECT (-1L) */ + +#ifdef CONFIG_PTHREAD_IPC +#define _POSIX_THREAD_SAFE_FUNCTIONS _POSIX_VERSION +#endif + +/* #define _POSIX_THREAD_SPORADIC_SERVER (-1L) */ + +#ifdef CONFIG_PTHREAD_IPC #ifndef _POSIX_THREADS -#define _POSIX_THREADS Z_SC_VAL_IFDEF(CONFIG_PTHREAD_IPC, _POSIX_VERSION) -#endif - -#define _POSIX_TIMEOUTS Z_SC_VAL_IFDEF(CONFIG_POSIX_CLOCK, _POSIX_VERSION) -#define _POSIX_TIMERS Z_SC_VAL_IFDEF(CONFIG_POSIX_CLOCK, _POSIX_VERSION) -#define _POSIX_TRACE (-1L) -#define _POSIX_TRACE_EVENT_FILTER (-1L) -#define _POSIX_TRACE_INHERIT (-1L) -#define _POSIX_TRACE_LOG (-1L) -#define _POSIX_TYPED_MEMORY_OBJECTS (-1L) -#define _POSIX_V6_ILP32_OFF32 (-1L) -#define _POSIX_V6_ILP32_OFFBIG (-1L) -#define _POSIX_V6_LP64_OFF64 (-1L) -#define _POSIX_V6_LPBIG_OFFBIG (-1L) -#define _POSIX_V7_ILP32_OFF32 (-1L) -#define _POSIX_V7_ILP32_OFFBIG (-1L) -#define _POSIX_V7_LP64_OFF64 (-1L) -#define _POSIX_V7_LPBIG_OFFBIG (-1L) -#define _POSIX2_C_BIND _POSIX_VERSION -#define _POSIX2_C_DEV (-1L) -#define _POSIX2_CHAR_TERM (-1L) -#define _POSIX2_DELAYTIMER_MAX (-1L) -#define _POSIX2_FORT_DEV (-1L) -#define _POSIX2_FORT_RUN (-1L) -#define _POSIX2_LOCALEDEF (-1L) -#define _POSIX2_PBS (-1L) -#define _POSIX2_PBS_ACCOUNTING (-1L) -#define _POSIX2_PBS_CHECKPOINT (-1L) -#define _POSIX2_PBS_LOCATE (-1L) -#define _POSIX2_PBS_MESSAGE (-1L) -#define _POSIX2_PBS_TRACK (-1L) -#define _POSIX2_SW_DEV (-1L) -#define _POSIX2_UPE (-1L) -#define _XOPEN_CRYPT (-1L) -#define _XOPEN_ENH_I18N (-1L) -#define _XOPEN_REALTIME (-1L) -#define _XOPEN_REALTIME_THREADS (-1L) -#define _XOPEN_SHM (-1L) -#define _XOPEN_STREAMS (-1L) -#define _XOPEN_UNIX (-1L) -#define _XOPEN_UUCP (-1L) +#define _POSIX_THREADS _POSIX_VERSION +#endif +#endif + +#ifdef CONFIG_POSIX_CLOCK +#define _POSIX_TIMEOUTS _POSIX_VERSION +#endif + +#ifdef CONFIG_POSIX_CLOCK +#define _POSIX_TIMERS _POSIX_VERSION +#endif + +/* #define _POSIX_TRACE (-1L) */ +/* #define _POSIX_TRACE_EVENT_FILTER (-1L) */ +/* #define _POSIX_TRACE_INHERIT (-1L) */ +/* #define _POSIX_TRACE_LOG (-1L) */ +/* #define _POSIX_TYPED_MEMORY_OBJECTS (-1L) */ + +/* + * POSIX v6 Options + */ +/* #define _POSIX_V6_ILP32_OFF32 (-1L) */ +/* #define _POSIX_V6_ILP32_OFFBIG (-1L) */ +/* #define _POSIX_V6_LP64_OFF64 (-1L) */ +/* #define _POSIX_V6_LPBIG_OFFBIG (-1L) */ + +/* + * POSIX v7 Options + */ +/* #define _POSIX_V7_ILP32_OFF32 (-1L) */ +/* #define _POSIX_V7_ILP32_OFFBIG (-1L) */ +/* #define _POSIX_V7_LP64_OFF64 (-1L) */ +/* #define _POSIX_V7_LPBIG_OFFBIG (-1L) */ + +/* + * POSIX2 Options + */ +#define _POSIX2_VERSION _POSIX_VERSION +#define _POSIX2_C_BIND _POSIX2_VERSION +#define _POSIX2_C_DEV _POSIX2_VERSION +/* #define _POSIX2_CHAR_TERM (-1L) */ +/* #define _POSIX2_DELAYTIMER_MAX (-1L) */ +/* #define _POSIX2_FORT_DEV (-1L) */ +/* #define _POSIX2_FORT_RUN (-1L) */ +/* #define _POSIX2_LOCALEDEF (-1L) */ +/* #define _POSIX2_PBS (-1L) */ +/* #define _POSIX2_PBS_ACCOUNTING (-1L) */ +/* #define _POSIX2_PBS_CHECKPOINT (-1L) */ +/* #define _POSIX2_PBS_LOCATE (-1L) */ +/* #define _POSIX2_PBS_MESSAGE (-1L) */ +/* #define _POSIX2_PBS_TRACK (-1L) */ +/* #define _POSIX2_SW_DEV (-1L) */ +/* #define _POSIX2_UPE (-1L) */ + +/* + * X/Open System Interfaces + */ +#define _XOPEN_VERSION 700 +/* #define _XOPEN_CRYPT (-1L) */ +/* #define _XOPEN_ENH_I18N (-1L) */ +/* #define _XOPEN_REALTIME (-1L) */ +/* #define _XOPEN_REALTIME_THREADS (-1L) */ +/* #define _XOPEN_SHM (-1L) */ +/* #define _XOPEN_STREAMS (-1L) */ +/* #define _XOPEN_UNIX (-1L) */ +/* #define _XOPEN_UUCP (-1L) */ /* Maximum values */ #define _POSIX_CLOCKRES_MIN (20000000L) @@ -115,14 +195,16 @@ #define _POSIX_AIO_MAX (1) #define _POSIX_ARG_MAX (4096) #define _POSIX_CHILD_MAX (25) -#define _POSIX_DELAYTIMER_MAX (32) -#define _POSIX_HOST_NAME_MAX (255) +#define _POSIX_DELAYTIMER_MAX \ + COND_CODE_1(CONFIG_POSIX_TIMERS, (CONFIG_POSIX_DELAYTIMER_MAX), (0)) +#define _POSIX_HOST_NAME_MAX \ + COND_CODE_1(CONFIG_NET_HOSTNAME_MAX_LEN, (NET_HOSTNAME_MAX_LEN), (0)) #define _POSIX_LINK_MAX (8) #define _POSIX_LOGIN_NAME_MAX (9) #define _POSIX_MAX_CANON (255) #define _POSIX_MAX_INPUT (255) #define _POSIX_MQ_OPEN_MAX \ - Z_SC_VAL_IFDEF(CONFIG_POSIX_MQUEUE, CONFIG_MSG_COUNT_MAX) + COND_CODE_1(CONFIG_POSIX_MQUEUE, (CONFIG_MSG_COUNT_MAX), (0)) #define _POSIX_MQ_PRIO_MAX (32) #define _POSIX_NAME_MAX (14) #define _POSIX_NGROUPS_MAX (8) @@ -141,9 +223,12 @@ #define _POSIX_SYMLINK_MAX (255) #define _POSIX_SYMLOOP_MAX (8) #define _POSIX_THREAD_DESTRUCTOR_ITERATIONS (4) -#define _POSIX_THREAD_KEYS_MAX (128) -#define _POSIX_THREAD_THREADS_MAX (64) -#define _POSIX_TIMER_MAX (32) +#define _POSIX_THREAD_KEYS_MAX \ + COND_CODE_1(CONFIG_PTHREAD_IPC, (CONFIG_MAX_PTHREAD_KEY_COUNT), (0)) +#define _POSIX_THREAD_THREADS_MAX \ + COND_CODE_1(CONFIG_PTHREAD_IPC, (CONFIG_MAX_PTHREAD_COUNT), (0)) +#define _POSIX_TIMER_MAX \ + COND_CODE_1(CONFIG_POSIX_TIMERS, (CONFIG_POSIX_TIMER_MAX), (0)) #define _POSIX_TRACE_EVENT_NAME_MAX (30) #define _POSIX_TRACE_NAME_MAX (8) #define _POSIX_TRACE_SYS_MAX (8) @@ -174,8 +259,7 @@ #define AIO_MAX _POSIX_AIO_MAX #define AIO_PRIO_DELTA_MAX (0) #define DELAYTIMER_MAX _POSIX_DELAYTIMER_MAX -#define HOST_NAME_MAX \ - COND_CODE_1(CONFIG_NETWORKING, (NET_HOSTNAME_MAX_LEN), (_POSIX_HOST_NAME_MAX)) +#define HOST_NAME_MAX _POSIX_HOST_NAME_MAX #define LOGIN_NAME_MAX _POSIX_LOGIN_NAME_MAX #define MQ_OPEN_MAX _POSIX_MQ_OPEN_MAX #define MQ_PRIO_MAX _POSIX_MQ_PRIO_MAX @@ -193,15 +277,15 @@ #endif #define PTHREAD_DESTRUCTOR_ITERATIONS _POSIX_THREAD_DESTRUCTOR_ITERATIONS -#define PTHREAD_KEYS_MAX \ - COND_CODE_1(CONFIG_PTHREAD_IPC, (CONFIG_MAX_PTHREAD_KEY_COUNT), (_POSIX_THREAD_KEYS_MAX)) -#define PTHREAD_THREADS_MAX COND_CODE_1(CONFIG_PTHREAD_IPC, (CONFIG_MAX_PTHREAD_COUNT), (0)) +#define PTHREAD_KEYS_MAX _POSIX_THREAD_KEYS_MAX +#define PTHREAD_THREADS_MAX _POSIX_THREAD_THREADS_MAX +#define RTSIG_MAX _POSIX_RTSIG_MAX #define SEM_NSEMS_MAX _POSIX_SEM_NSEMS_MAX #define SEM_VALUE_MAX CONFIG_SEM_VALUE_MAX #define SIGQUEUE_MAX _POSIX_SIGQUEUE_MAX #define STREAM_MAX _POSIX_STREAM_MAX #define SYMLOOP_MAX _POSIX_SYMLOOP_MAX -#define TIMER_MAX Z_SC_VAL_IFDEF(CONFIG_TIMER, CONFIG_MAX_TIMER_COUNT) +#define TIMER_MAX _POSIX_TIMER_MAX #define TTY_NAME_MAX _POSIX_TTY_NAME_MAX #define TZNAME_MAX _POSIX_TZNAME_MAX From aa6a47235552392900067e2384dd3d1ad3b206a2 Mon Sep 17 00:00:00 2001 From: Chris Friedt Date: Mon, 20 May 2024 17:54:29 -0400 Subject: [PATCH 1727/2849] posix: sysconf: define z sysconf macros with COND_CODE_1 It's sort of more conventient to do the opposite of what was done with the __z_sysconf_ macros, and use them for both the full implementation and the macro implementation. Signed-off-by: Chris Friedt --- include/zephyr/posix/sys/sysconf.h | 62 +++---- include/zephyr/posix/unistd.h | 9 +- lib/posix/options/sysconf.c | 268 +++++++++++++++-------------- 3 files changed, 176 insertions(+), 163 deletions(-) diff --git a/include/zephyr/posix/sys/sysconf.h b/include/zephyr/posix/sys/sysconf.h index 54bdd8e4a1a35..b96e3b4da4dce 100644 --- a/include/zephyr/posix/sys/sysconf.h +++ b/include/zephyr/posix/sys/sysconf.h @@ -7,6 +7,8 @@ #ifndef ZEPHYR_INCLUDE_POSIX_SYS_SYSCONF_H_ #define ZEPHYR_INCLUDE_POSIX_SYS_SYSCONF_H_ +#include + #ifdef __cplusplus extern "C" { #endif @@ -191,47 +193,47 @@ enum { #define __z_posix_sysconf_SC_TRACE_NAME_MAX _POSIX_TRACE_NAME_MAX #define __z_posix_sysconf_SC_TRACE_SYS_MAX _POSIX_TRACE_SYS_MAX #define __z_posix_sysconf_SC_TRACE_USER_EVENT_MAX _POSIX_TRACE_USER_EVENT_MAX -#define __z_posix_sysconf_SC_TYPED_MEMORY_OBJECTS _POSIX_TYPED_MEMORY_OBJECTS +#define __z_posix_sysconf_SC_TYPED_MEMORY_OBJECTS (-1L) #define __z_posix_sysconf_SC_VERSION _POSIX_VERSION -#define __z_posix_sysconf_SC_V7_ILP32_OFF32 _POSIX_V7_ILP32_OFF32 -#define __z_posix_sysconf_SC_V7_ILP32_OFFBIG _POSIX_V7_ILP32_OFFBIG -#define __z_posix_sysconf_SC_V7_LP64_OFF64 _POSIX_V7_LP64_OFF64 -#define __z_posix_sysconf_SC_V7_LPBIG_OFFBIG _POSIX_V7_LPBIG_OFFBIG -#define __z_posix_sysconf_SC_V6_ILP32_OFF32 _POSIX_V6_ILP32_OFF32 -#define __z_posix_sysconf_SC_V6_ILP32_OFFBIG _POSIX_V6_ILP32_OFFBIG -#define __z_posix_sysconf_SC_V6_LP64_OFF64 _POSIX_V6_LP64_OFF64 -#define __z_posix_sysconf_SC_V6_LPBIG_OFFBIG _POSIX_V6_LPBIG_OFFBIG +#define __z_posix_sysconf_SC_V6_ILP32_OFF32 (-1L) +#define __z_posix_sysconf_SC_V6_ILP32_OFFBIG (-1L) +#define __z_posix_sysconf_SC_V6_LP64_OFF64 (-1L) +#define __z_posix_sysconf_SC_V6_LPBIG_OFFBIG (-1L) +#define __z_posix_sysconf_SC_V7_ILP32_OFF32 (-1L) +#define __z_posix_sysconf_SC_V7_ILP32_OFFBIG (-1L) +#define __z_posix_sysconf_SC_V7_LP64_OFF64 (-1L) +#define __z_posix_sysconf_SC_V7_LPBIG_OFFBIG (-1L) #define __z_posix_sysconf_SC_BC_BASE_MAX _POSIX2_BC_BASE_MAX #define __z_posix_sysconf_SC_BC_DIM_MAX _POSIX2_BC_DIM_MAX #define __z_posix_sysconf_SC_BC_SCALE_MAX _POSIX2_BC_SCALE_MAX #define __z_posix_sysconf_SC_BC_STRING_MAX _POSIX2_BC_STRING_MAX #define __z_posix_sysconf_SC_2_C_BIND _POSIX2_C_BIND #define __z_posix_sysconf_SC_2_C_DEV _POSIX2_C_DEV -#define __z_posix_sysconf_SC_2_CHAR_TERM _POSIX2_CHAR_TERM +#define __z_posix_sysconf_SC_2_CHAR_TERM (-1L) #define __z_posix_sysconf_SC_COLL_WEIGHTS_MAX _POSIX2_COLL_WEIGHTS_MAX #define __z_posix_sysconf_SC_DELAYTIMER_MAX _POSIX2_DELAYTIMER_MAX #define __z_posix_sysconf_SC_EXPR_NEST_MAX _POSIX2_EXPR_NEST_MAX -#define __z_posix_sysconf_SC_2_FORT_DEV _POSIX2_FORT_DEV -#define __z_posix_sysconf_SC_2_FORT_RUN _POSIX2_FORT_RUN -#define __z_posix_sysconf_SC_LINE_MAX _POSIX2_LINE_MAX -#define __z_posix_sysconf_SC_2_LOCALEDEF _POSIX2_LOCALEDEF -#define __z_posix_sysconf_SC_2_PBS _POSIX2_PBS -#define __z_posix_sysconf_SC_2_PBS_ACCOUNTING _POSIX2_PBS_ACCOUNTING -#define __z_posix_sysconf_SC_2_PBS_CHECKPOINT _POSIX2_PBS_CHECKPOINT -#define __z_posix_sysconf_SC_2_PBS_LOCATE _POSIX2_PBS_LOCATE -#define __z_posix_sysconf_SC_2_PBS_MESSAGE _POSIX2_PBS_MESSAGE -#define __z_posix_sysconf_SC_2_PBS_TRACK _POSIX2_PBS_TRACK -#define __z_posix_sysconf_SC_2_SW_DEV _POSIX2_SW_DEV -#define __z_posix_sysconf_SC_2_UPE _POSIX2_UPE +#define __z_posix_sysconf_SC_2_FORT_DEV (-1L) +#define __z_posix_sysconf_SC_2_FORT_RUN (-1L) +#define __z_posix_sysconf_SC_LINE_MAX (-1L) +#define __z_posix_sysconf_SC_2_LOCALEDEF (-1L) +#define __z_posix_sysconf_SC_2_PBS (-1L) +#define __z_posix_sysconf_SC_2_PBS_ACCOUNTING (-1L) +#define __z_posix_sysconf_SC_2_PBS_CHECKPOINT (-1L) +#define __z_posix_sysconf_SC_2_PBS_LOCATE (-1L) +#define __z_posix_sysconf_SC_2_PBS_MESSAGE (-1L) +#define __z_posix_sysconf_SC_2_PBS_TRACK (-1L) +#define __z_posix_sysconf_SC_2_SW_DEV (-1L) +#define __z_posix_sysconf_SC_2_UPE (-1L) #define __z_posix_sysconf_SC_2_VERSION _POSIX2_VERSION -#define __z_posix_sysconf_SC_XOPEN_CRYPT _XOPEN_CRYPT -#define __z_posix_sysconf_SC_XOPEN_ENH_I18N _XOPEN_ENH_I18N -#define __z_posix_sysconf_SC_XOPEN_REALTIME _XOPEN_REALTIME -#define __z_posix_sysconf_SC_XOPEN_REALTIME_THREADS _XOPEN_REALTIME_THREADS -#define __z_posix_sysconf_SC_XOPEN_SHM _XOPEN_SHM -#define __z_posix_sysconf_SC_XOPEN_STREAMS _XOPEN_STREAMS -#define __z_posix_sysconf_SC_XOPEN_UNIX _XOPEN_UNIX -#define __z_posix_sysconf_SC_XOPEN_UUCP _XOPEN_UUCP +#define __z_posix_sysconf_SC_XOPEN_CRYPT (-1L) +#define __z_posix_sysconf_SC_XOPEN_ENH_I18N (-1L) +#define __z_posix_sysconf_SC_XOPEN_REALTIME (-1L) +#define __z_posix_sysconf_SC_XOPEN_REALTIME_THREADS (-1L) +#define __z_posix_sysconf_SC_XOPEN_SHM (-1L) +#define __z_posix_sysconf_SC_XOPEN_STREAMS (-1L) +#define __z_posix_sysconf_SC_XOPEN_UNIX (-1L) +#define __z_posix_sysconf_SC_XOPEN_UUCP (-1L) #define __z_posix_sysconf_SC_XOPEN_VERSION _XOPEN_VERSION #define __z_posix_sysconf_SC_CLK_TCK (100L) #define __z_posix_sysconf_SC_GETGR_R_SIZE_MAX (0L) diff --git a/include/zephyr/posix/unistd.h b/include/zephyr/posix/unistd.h index e70ce1f806e1f..3102dd89be048 100644 --- a/include/zephyr/posix/unistd.h +++ b/include/zephyr/posix/unistd.h @@ -62,13 +62,16 @@ int getentropy(void *buffer, size_t length); pid_t getpid(void); unsigned sleep(unsigned int seconds); int usleep(useconds_t useconds); -#ifdef CONFIG_POSIX_SYSCONF_IMPL_FULL -long sysconf(int opt); -#endif #if _POSIX_C_SOURCE >= 2 size_t confstr(int name, char *buf, size_t len); #endif +#ifdef CONFIG_POSIX_SYSCONF_IMPL_MACRO +#define sysconf(x) (long)CONCAT(__z_posix_sysconf, x) +#else +long sysconf(int opt); +#endif /* CONFIG_POSIX_SYSCONF_IMPL_FULL */ + #ifdef __cplusplus } #endif diff --git a/lib/posix/options/sysconf.c b/lib/posix/options/sysconf.c index 78491bd6eb019..5d3492918fb40 100644 --- a/lib/posix/options/sysconf.c +++ b/lib/posix/options/sysconf.c @@ -4,263 +4,271 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include +#include #include +#ifdef CONFIG_POSIX_SYSCONF_IMPL_FULL + +#define z_sysconf(x) (long)CONCAT(__z_posix_sysconf, x) + long sysconf(int x) { switch (x) { case _SC_ADVISORY_INFO: - return _POSIX_ADVISORY_INFO; + return z_sysconf(_SC_ADVISORY_INFO); case _SC_ASYNCHRONOUS_IO: - return _POSIX_ASYNCHRONOUS_IO; + return z_sysconf(_SC_ASYNCHRONOUS_IO); case _SC_BARRIERS: - return _POSIX_BARRIERS; + return z_sysconf(_SC_BARRIERS); case _SC_CLOCK_SELECTION: - return _POSIX_CLOCK_SELECTION; + return z_sysconf(_SC_CLOCK_SELECTION); case _SC_CPUTIME: - return _POSIX_CPUTIME; + return z_sysconf(_SC_CPUTIME); case _SC_FSYNC: - return _POSIX_FSYNC; + return z_sysconf(_SC_FSYNC); case _SC_IPV6: - return _POSIX_IPV6; + return z_sysconf(_SC_IPV6); case _SC_JOB_CONTROL: - return _POSIX_JOB_CONTROL; - case _SC_MAPPED_FILE: - return _POSIX_MAPPED_FILES; + return z_sysconf(_SC_JOB_CONTROL); + case _SC_MAPPED_FILES: + return z_sysconf(_SC_MAPPED_FILES); case _SC_MEMLOCK: - return _POSIX_MEMLOCK; + return z_sysconf(_SC_MEMLOCK); case _SC_MEMLOCK_RANGE: - return _POSIX_MEMLOCK_RANGE; + return z_sysconf(_SC_MEMLOCK_RANGE); case _SC_MEMORY_PROTECTION: - return _POSIX_MEMORY_PROTECTION; + return z_sysconf(_SC_MEMORY_PROTECTION); case _SC_MESSAGE_PASSING: - return _POSIX_MESSAGE_PASSING; + return z_sysconf(_SC_MESSAGE_PASSING); case _SC_MONOTONIC_CLOCK: - return _POSIX_MONOTONIC_CLOCK; + return z_sysconf(_SC_MONOTONIC_CLOCK); case _SC_PRIORITIZED_IO: - return _POSIX_PRIORITIZED_IO; + return z_sysconf(_SC_PRIORITIZED_IO); case _SC_PRIORITY_SCHEDULING: - return _POSIX_PRIORITY_SCHEDULING; + return z_sysconf(_SC_PRIORITY_SCHEDULING); case _SC_RAW_SOCKETS: - return _POSIX_RAW_SOCKETS; + return z_sysconf(_SC_RAW_SOCKETS); case _SC_RE_DUP_MAX: - return _POSIX_RE_DUP_MAX; + return z_sysconf(_SC_RE_DUP_MAX); case _SC_READER_WRITER_LOCKS: - return _POSIX_READER_WRITER_LOCKS; + return z_sysconf(_SC_READER_WRITER_LOCKS); case _SC_REALTIME_SIGNALS: - return _POSIX_REALTIME_SIGNALS; + return z_sysconf(_SC_REALTIME_SIGNALS); case _SC_REGEXP: - return _POSIX_REGEXP; + return z_sysconf(_SC_REGEXP); case _SC_SAVED_IDS: - return _POSIX_SAVED_IDS; + return z_sysconf(_SC_SAVED_IDS); case _SC_SEMAPHORES: - return _POSIX_SEMAPHORES; + return z_sysconf(_SC_SEMAPHORES); case _SC_SHARED_MEMORY_OBJECTS: - return _POSIX_SHARED_MEMORY_OBJECTS; + return z_sysconf(_SC_SHARED_MEMORY_OBJECTS); case _SC_SHELL: - return _POSIX_SHELL; + return z_sysconf(_SC_SHELL); case _SC_SPAWN: - return _POSIX_SPAWN; + return z_sysconf(_SC_SPAWN); case _SC_SPIN_LOCKS: - return _POSIX_SPIN_LOCKS; + return z_sysconf(_SC_SPIN_LOCKS); case _SC_SPORADIC_SERVER: - return _POSIX_SPORADIC_SERVER; + return z_sysconf(_SC_SPORADIC_SERVER); case _SC_SS_REPL_MAX: - return _POSIX_SS_REPL_MAX; + return z_sysconf(_SC_SS_REPL_MAX); case _SC_SYNCHRONIZED_IO: - return _POSIX_SYNCHRONIZED_IO; + return z_sysconf(_SC_SYNCHRONIZED_IO); case _SC_THREAD_ATTR_STACKADDR: - return _POSIX_THREAD_ATTR_STACKADDR; + return z_sysconf(_SC_THREAD_ATTR_STACKADDR); case _SC_THREAD_ATTR_STACKSIZE: - return _POSIX_THREAD_ATTR_STACKSIZE; + return z_sysconf(_SC_THREAD_ATTR_STACKSIZE); case _SC_THREAD_CPUTIME: - return _POSIX_THREAD_CPUTIME; + return z_sysconf(_SC_THREAD_CPUTIME); case _SC_THREAD_PRIO_INHERIT: - return _POSIX_THREAD_PRIO_INHERIT; + return z_sysconf(_SC_THREAD_PRIO_INHERIT); case _SC_THREAD_PRIO_PROTECT: - return _POSIX_THREAD_PRIO_PROTECT; + return z_sysconf(_SC_THREAD_PRIO_PROTECT); case _SC_THREAD_PRIORITY_SCHEDULING: - return _POSIX_THREAD_PRIORITY_SCHEDULING; + return z_sysconf(_SC_THREAD_PRIORITY_SCHEDULING); case _SC_THREAD_PROCESS_SHARED: - return _POSIX_THREAD_PROCESS_SHARED; + return z_sysconf(_SC_THREAD_PROCESS_SHARED); case _SC_THREAD_ROBUST_PRIO_INHERIT: - return _POSIX_THREAD_ROBUST_PRIO_INHERIT; + return z_sysconf(_SC_THREAD_ROBUST_PRIO_INHERIT); case _SC_THREAD_ROBUST_PRIO_PROTECT: - return _POSIX_THREAD_ROBUST_PRIO_PROTECT; + return z_sysconf(_SC_THREAD_ROBUST_PRIO_PROTECT); case _SC_THREAD_SAFE_FUNCTIONS: - return _POSIX_THREAD_SAFE_FUNCTIONS; + return z_sysconf(_SC_THREAD_SAFE_FUNCTIONS); case _SC_THREAD_SPORADIC_SERVER: - return _POSIX_THREAD_SPORADIC_SERVER; + return z_sysconf(_SC_THREAD_SPORADIC_SERVER); case _SC_THREADS: - return _POSIX_THREADS; + return z_sysconf(_SC_THREADS); case _SC_TIMEOUTS: - return _POSIX_TIMEOUTS; + return z_sysconf(_SC_TIMEOUTS); case _SC_TIMERS: - return _POSIX_TIMERS; + return z_sysconf(_SC_TIMERS); case _SC_TRACE: - return _POSIX_TRACE; + return z_sysconf(_SC_TRACE); case _SC_TRACE_EVENT_FILTER: - return _POSIX_TRACE_EVENT_FILTER; + return z_sysconf(_SC_TRACE_EVENT_FILTER); case _SC_TRACE_EVENT_NAME_MAX: - return _POSIX_TRACE_EVENT_NAME_MAX; + return z_sysconf(_SC_TRACE_EVENT_NAME_MAX); case _SC_TRACE_INHERIT: - return _POSIX_TRACE_INHERIT; + return z_sysconf(_SC_TRACE_INHERIT); case _SC_TRACE_LOG: - return _POSIX_TRACE_LOG; + return z_sysconf(_SC_TRACE_LOG); case _SC_TRACE_NAME_MAX: - return _POSIX_TRACE_NAME_MAX; + return z_sysconf(_SC_TRACE_NAME_MAX); case _SC_TRACE_SYS_MAX: - return _POSIX_TRACE_SYS_MAX; + return z_sysconf(_SC_TRACE_SYS_MAX); case _SC_TRACE_USER_EVENT_MAX: - return _POSIX_TRACE_USER_EVENT_MAX; + return z_sysconf(_SC_TRACE_USER_EVENT_MAX); case _SC_TYPED_MEMORY_OBJECTS: - return _POSIX_TYPED_MEMORY_OBJECTS; + return z_sysconf(_SC_TYPED_MEMORY_OBJECTS); case _SC_VERSION: - return _POSIX_VERSION; - case _SC_V7_ILP32_OFF32: - return _POSIX_V7_ILP32_OFF32; - case _SC_V7_ILP32_OFFBIG: - return _POSIX_V7_ILP32_OFFBIG; - case _SC_V7_LP64_OFF64: - return _POSIX_V7_LP64_OFF64; - case _SC_V7_LPBIG_OFFBIG: - return _POSIX_V7_LPBIG_OFFBIG; + return z_sysconf(_SC_VERSION); case _SC_V6_ILP32_OFF32: - return _POSIX_V6_ILP32_OFF32; + return z_sysconf(_SC_V6_ILP32_OFF32); case _SC_V6_ILP32_OFFBIG: - return _POSIX_V6_ILP32_OFFBIG; + return z_sysconf(_SC_V6_ILP32_OFFBIG); case _SC_V6_LP64_OFF64: - return _POSIX_V6_LP64_OFF64; + return z_sysconf(_SC_V6_LP64_OFF64); case _SC_V6_LPBIG_OFFBIG: - return _POSIX_V6_LPBIG_OFFBIG; + return z_sysconf(_SC_V6_LPBIG_OFFBIG); + case _SC_V7_ILP32_OFF32: + return z_sysconf(_SC_V7_ILP32_OFF32); + case _SC_V7_ILP32_OFFBIG: + return z_sysconf(_SC_V7_ILP32_OFFBIG); + case _SC_V7_LP64_OFF64: + return z_sysconf(_SC_V7_LP64_OFF64); + case _SC_V7_LPBIG_OFFBIG: + return z_sysconf(_SC_V7_LPBIG_OFFBIG); case _SC_BC_BASE_MAX: - return _POSIX2_BC_BASE_MAX; + return z_sysconf(_SC_BC_BASE_MAX); case _SC_BC_DIM_MAX: - return _POSIX2_BC_DIM_MAX; + return z_sysconf(_SC_BC_DIM_MAX); case _SC_BC_SCALE_MAX: - return _POSIX2_BC_SCALE_MAX; + return z_sysconf(_SC_BC_SCALE_MAX); case _SC_BC_STRING_MAX: - return _POSIX2_BC_STRING_MAX; + return z_sysconf(_SC_BC_STRING_MAX); case _SC_2_C_BIND: - return _POSIX2_C_BIND; + return z_sysconf(_SC_2_C_BIND); case _SC_2_C_DEV: - return _POSIX2_C_DEV; + return z_sysconf(_SC_2_C_DEV); case _SC_2_CHAR_TERM: - return _POSIX2_CHAR_TERM; + return z_sysconf(_SC_2_CHAR_TERM); case _SC_COLL_WEIGHTS_MAX: - return _POSIX2_COLL_WEIGHTS_MAX; + return z_sysconf(_SC_COLL_WEIGHTS_MAX); case _SC_DELAYTIMER_MAX: - return _POSIX2_DELAYTIMER_MAX; + return z_sysconf(_SC_DELAYTIMER_MAX); case _SC_EXPR_NEST_MAX: - return _POSIX2_EXPR_NEST_MAX; + return z_sysconf(_SC_EXPR_NEST_MAX); case _SC_2_FORT_DEV: - return _POSIX2_FORT_DEV; + return z_sysconf(_SC_2_FORT_DEV); case _SC_2_FORT_RUN: - return _POSIX2_FORT_RUN; + return z_sysconf(_SC_2_FORT_RUN); case _SC_LINE_MAX: - return _POSIX2_LINE_MAX; + return z_sysconf(_SC_LINE_MAX); case _SC_2_LOCALEDEF: - return _POSIX2_LOCALEDEF; + return z_sysconf(_SC_2_LOCALEDEF); case _SC_2_PBS: - return _POSIX2_PBS; + return z_sysconf(_SC_2_PBS); case _SC_2_PBS_ACCOUNTING: - return _POSIX2_PBS_ACCOUNTING; + return z_sysconf(_SC_2_PBS_ACCOUNTING); case _SC_2_PBS_CHECKPOINT: - return _POSIX2_PBS_CHECKPOINT; + return z_sysconf(_SC_2_PBS_CHECKPOINT); case _SC_2_PBS_LOCATE: - return _POSIX2_PBS_LOCATE; + return z_sysconf(_SC_2_PBS_LOCATE); case _SC_2_PBS_MESSAGE: - return _POSIX2_PBS_MESSAGE; + return z_sysconf(_SC_2_PBS_MESSAGE); case _SC_2_PBS_TRACK: - return _POSIX2_PBS_TRACK; + return z_sysconf(_SC_2_PBS_TRACK); case _SC_2_SW_DEV: - return _POSIX2_SW_DEV; + return z_sysconf(_SC_2_SW_DEV); case _SC_2_UPE: - return _POSIX2_UPE; + return z_sysconf(_SC_2_UPE); case _SC_2_VERSION: - return _POSIX2_VERSION; + return z_sysconf(_SC_2_VERSION); case _SC_XOPEN_CRYPT: - return _XOPEN_CRYPT; + return z_sysconf(_SC_XOPEN_CRYPT); case _SC_XOPEN_ENH_I18N: - return _XOPEN_ENH_I18N; + return z_sysconf(_SC_XOPEN_ENH_I18N); case _SC_XOPEN_REALTIME: - return _XOPEN_REALTIME; + return z_sysconf(_SC_XOPEN_REALTIME); case _SC_XOPEN_REALTIME_THREADS: - return _XOPEN_REALTIME_THREADS; + return z_sysconf(_SC_XOPEN_REALTIME_THREADS); case _SC_XOPEN_SHM: - return _XOPEN_SHM; + return z_sysconf(_SC_XOPEN_SHM); case _SC_XOPEN_STREAMS: - return _XOPEN_STREAMS; + return z_sysconf(_SC_XOPEN_STREAMS); case _SC_XOPEN_UNIX: - return _XOPEN_UNIX; + return z_sysconf(_SC_XOPEN_UNIX); case _SC_XOPEN_UUCP: - return _XOPEN_UUCP; + return z_sysconf(_SC_XOPEN_UUCP); case _SC_XOPEN_VERSION: - return _XOPEN_VERSION; + return z_sysconf(_SC_XOPEN_VERSION); case _SC_CLK_TCK: - return (100L); + return z_sysconf(_SC_CLK_TCK); case _SC_GETGR_R_SIZE_MAX: - return (0L); + return z_sysconf(_SC_GETGR_R_SIZE_MAX); case _SC_GETPW_R_SIZE_MAX: - return (0L); + return z_sysconf(_SC_GETPW_R_SIZE_MAX); case _SC_AIO_LISTIO_MAX: - return AIO_LISTIO_MAX; + return z_sysconf(_SC_AIO_LISTIO_MAX); case _SC_AIO_MAX: - return AIO_MAX; + return z_sysconf(_SC_AIO_MAX); case _SC_AIO_PRIO_DELTA_MAX: - return AIO_PRIO_DELTA_MAX; + return z_sysconf(_SC_AIO_PRIO_DELTA_MAX); case _SC_ARG_MAX: - return ARG_MAX; + return z_sysconf(_SC_ARG_MAX); case _SC_ATEXIT_MAX: - return ATEXIT_MAX; + return z_sysconf(_SC_ATEXIT_MAX); case _SC_CHILD_MAX: - return CHILD_MAX; + return z_sysconf(_SC_CHILD_MAX); case _SC_HOST_NAME_MAX: - return _POSIX_HOST_NAME_MAX; + return z_sysconf(_SC_HOST_NAME_MAX); case _SC_IOV_MAX: - return IOV_MAX; + return z_sysconf(_SC_IOV_MAX); case _SC_LOGIN_NAME_MAX: - return LOGIN_NAME_MAX; + return z_sysconf(_SC_LOGIN_NAME_MAX); case _SC_NGROUPS_MAX: - return _POSIX_NGROUPS_MAX; + return z_sysconf(_SC_NGROUPS_MAX); case _SC_MQ_OPEN_MAX: - return MQ_OPEN_MAX; + return z_sysconf(_SC_MQ_OPEN_MAX); case _SC_MQ_PRIO_MAX: - return MQ_PRIO_MAX; + return z_sysconf(_SC_MQ_PRIO_MAX); case _SC_OPEN_MAX: - return CONFIG_POSIX_MAX_FDS; + return z_sysconf(_SC_OPEN_MAX); case _SC_PAGE_SIZE: - return PAGE_SIZE; + return z_sysconf(_SC_PAGE_SIZE); case _SC_PAGESIZE: - return PAGESIZE; + return z_sysconf(_SC_PAGESIZE); case _SC_THREAD_DESTRUCTOR_ITERATIONS: - return PTHREAD_DESTRUCTOR_ITERATIONS; + return z_sysconf(_SC_THREAD_DESTRUCTOR_ITERATIONS); case _SC_THREAD_KEYS_MAX: - return PTHREAD_KEYS_MAX; + return z_sysconf(_SC_THREAD_KEYS_MAX); case _SC_THREAD_STACK_MIN: - return PAGE_SIZE; + return z_sysconf(_SC_THREAD_STACK_MIN); case _SC_THREAD_THREADS_MAX: - return PTHREAD_THREADS_MAX; + return z_sysconf(_SC_THREAD_THREADS_MAX); case _SC_RTSIG_MAX: - return RTSIG_MAX; + return z_sysconf(_SC_RTSIG_MAX); case _SC_SEM_NSEMS_MAX: - return SEM_NSEMS_MAX; + return z_sysconf(_SC_SEM_NSEMS_MAX); case _SC_SEM_VALUE_MAX: - return SEM_VALUE_MAX; + return z_sysconf(_SC_SEM_VALUE_MAX); case _SC_SIGQUEUE_MAX: - return SIGQUEUE_MAX; + return z_sysconf(_SC_SIGQUEUE_MAX); case _SC_STREAM_MAX: - return STREAM_MAX; + return z_sysconf(_SC_STREAM_MAX); case _SC_SYMLOOP_MAX: - return SYMLOOP_MAX; + return z_sysconf(_SC_SYMLOOP_MAX); case _SC_TIMER_MAX: - return TIMER_MAX; + return z_sysconf(_SC_TIMER_MAX); case _SC_TTY_NAME_MAX: - return TTY_NAME_MAX; + return z_sysconf(_SC_TTY_NAME_MAX); case _SC_TZNAME_MAX: - return TZNAME_MAX; + return z_sysconf(_SC_TZNAME_MAX); default: errno = EINVAL; return -1; } } + +#endif /* CONFIG_POSIX_SYSCONF_IMPL_FULL */ From feb841a0f7af529d04ba7ee5879301f3d601fa29 Mon Sep 17 00:00:00 2001 From: Chris Friedt Date: Mon, 20 May 2024 09:04:30 -0400 Subject: [PATCH 1728/2849] posix: add Kconfig.deprecated There will be some POSIX Kconfig symbols that will be deprecated in favour of Kconfig symbols that are exact matches for those in the POSIX specification (1003.1-2017). Create the empty Kconfig file now, and then incrementally add to it as non-standard POSIX Kconfig options are replaced with standard-like POSIX Kconfig options. Signed-off-by: Chris Friedt --- lib/posix/options/Kconfig | 3 +++ lib/posix/options/Kconfig.deprecated | 8 ++++++++ 2 files changed, 11 insertions(+) create mode 100644 lib/posix/options/Kconfig.deprecated diff --git a/lib/posix/options/Kconfig b/lib/posix/options/Kconfig index 2197148bca5bb..8c49debe2a8d9 100644 --- a/lib/posix/options/Kconfig +++ b/lib/posix/options/Kconfig @@ -1,5 +1,6 @@ # Copyright (c) 2018 Intel Corporation # Copyright (c) 2023 Meta +# Copyright (c) 2024 Tenstorrent AI ULC # # SPDX-License-Identifier: Apache-2.0 @@ -53,4 +54,6 @@ rsource "Kconfig.syslog" rsource "Kconfig.timer" rsource "Kconfig.uname" +rsource "Kconfig.deprecated" + endmenu # "POSIX Options" diff --git a/lib/posix/options/Kconfig.deprecated b/lib/posix/options/Kconfig.deprecated new file mode 100644 index 0000000000000..92d3967d38c64 --- /dev/null +++ b/lib/posix/options/Kconfig.deprecated @@ -0,0 +1,8 @@ +# Copyright (c) 2024 Tenstorrent AI ULC +# +# SPDX-License-Identifier: Apache-2.0 + +# This file should be removed after Zephyr 4.0 is released + +menu "Deprecated POSIX options" +endmenu From e2fc78af23039ce02413211c7d055657c79c68a2 Mon Sep 17 00:00:00 2001 From: Chris Friedt Date: Mon, 20 May 2024 21:51:50 -0400 Subject: [PATCH 1729/2849] posix: signals: deprecate CONFIG_POSIX_LIMITS_RTSIG_MAX There were two Kconfig constants defined for (effectively) the same thing in Zephyr. Namely, RTSIG_MAX - the highest valued real-time signal. Deprecate CONFIG_POSIX_LIMITS_RTSIG_MAX in favour of CONFIG_POSIX_RTSIG_MAX since the latter more closely matches convention. Signed-off-by: Chris Friedt --- .../portability/posix/kconfig/index.rst | 1 - lib/posix/options/Kconfig.deprecated | 10 +++++++++ lib/posix/options/Kconfig.signal | 21 ++++++++++--------- lib/posix/options/signal.c | 3 +-- 4 files changed, 22 insertions(+), 13 deletions(-) diff --git a/doc/services/portability/posix/kconfig/index.rst b/doc/services/portability/posix/kconfig/index.rst index 059c0c1affe50..9263ba0bd6b65 100644 --- a/doc/services/portability/posix/kconfig/index.rst +++ b/doc/services/portability/posix/kconfig/index.rst @@ -27,7 +27,6 @@ implementation of the POSIX API. * :kconfig:option:`CONFIG_POSIX_API` * :kconfig:option:`CONFIG_POSIX_CLOCK` * :kconfig:option:`CONFIG_POSIX_FS` -* :kconfig:option:`CONFIG_POSIX_LIMITS_RTSIG_MAX` * :kconfig:option:`CONFIG_POSIX_MAX_FDS` * :kconfig:option:`CONFIG_POSIX_MAX_OPEN_FILES` * :kconfig:option:`CONFIG_POSIX_MQUEUE` diff --git a/lib/posix/options/Kconfig.deprecated b/lib/posix/options/Kconfig.deprecated index 92d3967d38c64..126d14f5aae7b 100644 --- a/lib/posix/options/Kconfig.deprecated +++ b/lib/posix/options/Kconfig.deprecated @@ -5,4 +5,14 @@ # This file should be removed after Zephyr 4.0 is released menu "Deprecated POSIX options" + +config POSIX_LIMITS_RTSIG_MAX + int "_POSIX_RTSIG_MAX value in limits.h [DEPRECATED]" + default POSIX_RTSIG_MAX if POSIX_REALTIME_SIGNALS + default 0 + help + This option is deprecated. + + Please use CONFIG_POSIX_RTSIG_MAX instead. + endmenu diff --git a/lib/posix/options/Kconfig.signal b/lib/posix/options/Kconfig.signal index 99c225564c711..a25ac268d8ae9 100644 --- a/lib/posix/options/Kconfig.signal +++ b/lib/posix/options/Kconfig.signal @@ -4,15 +4,23 @@ menu "Signal support" -# needed outside of if clause above to define constants & types in signal.h +config POSIX_REALTIME_SIGNALS + bool "POSIX realtime signals" + default y if POSIX_API + help + Enable support for POSIX realtime signals. + +if POSIX_REALTIME_SIGNALS + config POSIX_RTSIG_MAX int "Maximum number of realtime signals" - default 31 if POSIX_SIGNAL - default 0 + default 8 help Define the maximum number of realtime signals (RTSIG_MAX). The range of realtime signals is [SIGRTMIN .. (SIGRTMIN+RTSIG_MAX)] +endif # POSIX_REALTIME_SIGNALS + config POSIX_SIGNAL bool "Support for POSIX signal APIs" default y if POSIX_API @@ -28,13 +36,6 @@ config POSIX_SIGNAL_STRING_DESC Use full description for the strsignal API. Will use 256 bytes of ROM. -config POSIX_LIMITS_RTSIG_MAX - int "_POSIX_RTSIG_MAX value in limits.h" - default 8 - help - Define the _POSIX_RTSIG_MAX value in limits.h. - IEEE 1003.1 defines this to be 8. - endif endmenu # "Signal support" diff --git a/lib/posix/options/signal.c b/lib/posix/options/signal.c index f14ef7fe614f9..362742063fc7f 100644 --- a/lib/posix/options/signal.c +++ b/lib/posix/options/signal.c @@ -13,8 +13,7 @@ #define SIGNO_WORD_IDX(_signo) (signo / BITS_PER_LONG) #define SIGNO_WORD_BIT(_signo) (signo & BIT_MASK(LOG2(BITS_PER_LONG))) -BUILD_ASSERT(CONFIG_POSIX_LIMITS_RTSIG_MAX >= 0); -BUILD_ASSERT(CONFIG_POSIX_RTSIG_MAX >= CONFIG_POSIX_LIMITS_RTSIG_MAX); +BUILD_ASSERT(CONFIG_POSIX_RTSIG_MAX >= 0); static inline bool signo_valid(int signo) { From 4a5c4e5f73b7e4e71674c63c6018d02762c52855 Mon Sep 17 00:00:00 2001 From: Chris Friedt Date: Mon, 20 May 2024 12:23:58 -0400 Subject: [PATCH 1730/2849] posix: timers: deprecate CONFIG_POSIX_CLOCK and TIMER The POSIX_CLOCK option does not correspond to any standard option. It was used to active features of several distinct POSIX Options and Option Groups, which complicated API and application configuration as a result. POSIX_CLOCK is being deprecated in order to ensure that Zephyr's POSIX Kconfig variables correspond to those defined in the specification, as of IEEE 1003.1-2017. Additionally, CONFIG_TIMER is being deprecated because it does not match the corresponding POSIX Option (_POSIX_TIMERS). With this deprecation, we introduce the following Kconfig options that map directly to standard POSIX Option Groups by simply removing "CONFIG_": * CONFIG_POSIX_TIMERS Similarly, we introduce the following Kconfig options that map directly to standard POSIX Options by simply removing "CONFIG": * CONFIG_POSIX_CLOCK_SELECTION * CONFIG_POSIX_CPUTIME * CONFIG_POSIX_DELAYTIMER_MAX * CONFIG_POSIX_MONOTONIC_CLOCK * CONFIG_POSIX_TIMEOUTS * CONFIG_POSIX_TIMER_MAX In order to maintain parity with the current feature set, we introduce the following Kconfig options that map directly to standard POSIX Option Groups by simply removing "CONFIG_": * CONFIG_POSIX_MULTI_PROCESS - sleep() Similarly, in order to maintain parity with the current feature set, we introduce the following additional Kconfig options that map directly to standard POSIX Options by simply removing "CONFIG": * CONFIG_XSI_SINGLE_PROCESS - gettimeofday() Signed-off-by: Chris Friedt --- cmake/toolchain/armclang/Kconfig | 2 +- doc/connectivity/networking/api/lwm2m.rst | 2 +- doc/services/portability/posix/aep/index.rst | 6 +- .../portability/posix/conformance/index.rst | 12 +- .../portability/posix/kconfig/index.rst | 4 +- .../portability/posix/option_groups/index.rst | 11 ++ include/zephyr/posix/posix_features.h | 17 +-- include/zephyr/posix/sys/sysconf.h | 118 ++++++++++-------- include/zephyr/posix/time.h | 4 + lib/libc/minimal/Kconfig | 4 +- lib/libc/newlib/libc-hooks.c | 2 +- lib/posix/options/CMakeLists.txt | 13 +- lib/posix/options/Kconfig | 8 +- lib/posix/options/Kconfig.clock | 11 -- lib/posix/options/Kconfig.deprecated | 40 ++++++ lib/posix/options/Kconfig.procN | 16 +++ lib/posix/options/Kconfig.timer | 99 +++++++++++++-- lib/posix/options/Kconfig.xsi | 16 +++ lib/posix/options/_common.c | 4 +- lib/posix/options/clock.c | 45 ++++++- lib/posix/options/nanosleep.c | 24 ---- lib/posix/options/sleep.c | 24 ---- lib/posix/options/timer.c | 8 +- modules/Kconfig.simplelink | 2 +- modules/hostap/Kconfig | 2 +- samples/net/cloud/aws_iot_mqtt/prj.conf | 1 - .../shell/shell_module/overlay-usb.conf | 6 +- samples/subsys/shell/shell_module/prj.conf | 2 +- .../subsys/shell/shell_module/prj_getopt.conf | 2 +- .../subsys/shell/shell_module/prj_login.conf | 2 +- subsys/logging/Kconfig.processing | 2 +- subsys/net/lib/lwm2m/Kconfig | 2 +- subsys/shell/modules/Kconfig | 2 +- tests/lib/time/prj.conf | 2 +- tests/posix/common/src/uname.c | 4 +- tests/posix/headers/prj.conf | 2 +- 36 files changed, 343 insertions(+), 178 deletions(-) delete mode 100644 lib/posix/options/Kconfig.clock create mode 100644 lib/posix/options/Kconfig.procN create mode 100644 lib/posix/options/Kconfig.xsi delete mode 100644 lib/posix/options/nanosleep.c diff --git a/cmake/toolchain/armclang/Kconfig b/cmake/toolchain/armclang/Kconfig index 27be295057ca9..70b9b2bd15203 100644 --- a/cmake/toolchain/armclang/Kconfig +++ b/cmake/toolchain/armclang/Kconfig @@ -16,7 +16,7 @@ choice LIBC_IMPLEMENTATION config ARMCLANG_STD_LIBC bool "ARM Compiler C library" select COMMON_LIBC_STRNLEN - select COMMON_LIBC_TIME if POSIX_CLOCK + select COMMON_LIBC_TIME if POSIX_TIMERS help Use the full Arm Compiler runtime libraries. A reduced Zephyr minimal libc will be used for library functionality diff --git a/doc/connectivity/networking/api/lwm2m.rst b/doc/connectivity/networking/api/lwm2m.rst index 8aab68e54caa5..b340166fbff86 100644 --- a/doc/connectivity/networking/api/lwm2m.rst +++ b/doc/connectivity/networking/api/lwm2m.rst @@ -521,7 +521,7 @@ engine. Data caches depends on one of the SenML data formats :kconfig:option:`CONFIG_LWM2M_RW_SENML_CBOR_SUPPORT` or -:kconfig:option:`CONFIG_LWM2M_RW_SENML_JSON_SUPPORT` and needs :kconfig:option:`CONFIG_POSIX_CLOCK` +:kconfig:option:`CONFIG_LWM2M_RW_SENML_JSON_SUPPORT` and needs :kconfig:option:`CONFIG_POSIX_TIMERS` so it can request a timestamp from the system and :kconfig:option:`CONFIG_RING_BUFFER` for ring buffer. diff --git a/doc/services/portability/posix/aep/index.rst b/doc/services/portability/posix/aep/index.rst index a8f214ef2aacb..e1f9859e2639c 100644 --- a/doc/services/portability/posix/aep/index.rst +++ b/doc/services/portability/posix/aep/index.rst @@ -63,12 +63,12 @@ The *Minimal Realtime System Profile* (PSE51) includes all of the :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` + :ref:`_POSIX_MONOTONIC_CLOCK `, 200809L, :kconfig:option:`CONFIG_POSIX_MONOTONIC_CLOCK` :ref:`_POSIX_SHARED_MEMORY_OBJECTS `, -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` - :ref:`_POSIX_THREAD_CPUTIME `, -1, + :ref:`_POSIX_THREAD_CPUTIME `, 200809L, :kconfig:option:`CONFIG_POSIX_CPUTIME` _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` @@ -150,7 +150,7 @@ The *Dedicated Realtime System Profile* (PSE53) includes all features from PSE52 :header: Symbol, Support, Remarks :widths: 50, 10, 50 - _POSIX_CPUTIME, -1, + :ref:`_POSIX_CPUTIME `, 200809L, :kconfig:option:`CONFIG_POSIX_CPUTIME` _POSIX_PRIORITIZED_IO, -1, :ref:`_POSIX_PRIORITY_SCHEDULING `, -1, _POSIX_RAW_SOCKETS, 200809L, :kconfig:option:`CONFIG_NET_SOCKETS_PACKET` diff --git a/doc/services/portability/posix/conformance/index.rst b/doc/services/portability/posix/conformance/index.rst index 69e77eed89c35..dffc1c5ec070f 100644 --- a/doc/services/portability/posix/conformance/index.rst +++ b/doc/services/portability/posix/conformance/index.rst @@ -63,7 +63,7 @@ POSIX System Interfaces _POSIX_VERSION, 200809L, :ref:`_POSIX_ASYNCHRONOUS_IO`, 200809L, :ref:`†` :ref:`_POSIX_BARRIERS`, 200809L, :kconfig:option:`CONFIG_PTHREAD_BARRIER` - :ref:`_POSIX_CLOCK_SELECTION`, 200809L, :kconfig:option:`CONFIG_POSIX_CLOCK` + :ref:`_POSIX_CLOCK_SELECTION`, 200809L, :kconfig:option:`CONFIG_POSIX_CLOCK_SELECTION` _POSIX_MAPPED_FILES, -1, :ref:`†` _POSIX_MEMORY_PROTECTION, -1, :ref:`†` :ref:`_POSIX_READER_WRITER_LOCKS`, 200809L, :kconfig:option:`CONFIG_PTHREAD_IPC` @@ -72,8 +72,8 @@ POSIX System Interfaces :ref:`_POSIX_SPIN_LOCKS`, 200809L, :kconfig:option:`CONFIG_PTHREAD_SPINLOCK` :ref:`_POSIX_THREAD_SAFE_FUNCTIONS`, -1, :ref:`_POSIX_THREADS`, -1, :kconfig:option:`CONFIG_PTHREAD_IPC` - :ref:`_POSIX_TIMEOUTS`, 200809L, :kconfig:option:`CONFIG_PTHREAD_IPC` - :ref:`_POSIX_TIMERS`, 200809L, :kconfig:option:`CONFIG_POSIX_CLOCK` + :ref:`_POSIX_TIMEOUTS`, 200809L, :kconfig:option:`CONFIG_POSIX_TIMEOUTS` + :ref:`_POSIX_TIMERS`, 200809L, :kconfig:option:`CONFIG_POSIX_TIMERS` _POSIX2_C_BIND, 200809L, .. csv-table:: POSIX System Interfaces (Optional) @@ -81,13 +81,13 @@ POSIX System Interfaces :widths: 50, 10, 50 _POSIX_ADVISORY_INFO, -1, - _POSIX_CPUTIME, 200809L, :kconfig:option:`CONFIG_POSIX_CLOCK` + :ref:`_POSIX_CPUTIME`, 200809L, :kconfig:option:`CONFIG_POSIX_CPUTIME` :ref:`_POSIX_FSYNC`, 200809L, :kconfig:option:`CONFIG_POSIX_FSYNC` _POSIX_IPV6, 200809L, :kconfig:option:`CONFIG_NET_IPV6` _POSIX_MEMLOCK, -1, _POSIX_MEMLOCK_RANGE, -1, :ref:`_POSIX_MESSAGE_PASSING`, 200809L, :kconfig:option:`CONFIG_POSIX_MQUEUE` - :ref:`_POSIX_MONOTONIC_CLOCK`, 200809L, :kconfig:option:`CONFIG_POSIX_CLOCK` + :ref:`_POSIX_MONOTONIC_CLOCK`, 200809L, :kconfig:option:`CONFIG_POSIX_MONOTONIC_CLOCK` _POSIX_PRIORITIZED_IO, -1, :ref:`_POSIX_PRIORITY_SCHEDULING`, 200809L, :kconfig:option:`CONFIG_POSIX_PRIORITY_SCHEDULING` _POSIX_RAW_SOCKETS, 200809L, :kconfig:option:`CONFIG_NET_SOCKETS_PACKET` @@ -97,7 +97,7 @@ POSIX System Interfaces _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, + :ref:`_POSIX_THREAD_CPUTIME `, 200809L, :kconfig:option:`CONFIG_POSIX_CPUTIME` _POSIX_THREAD_PRIO_INHERIT, 200809L, :kconfig:option:`CONFIG_PTHREAD_MUTEX` _POSIX_THREAD_PRIO_PROTECT, -1, :ref:`_POSIX_THREAD_PRIORITY_SCHEDULING`, 200809L, :kconfig:option:`CONFIG_PTHREAD` diff --git a/doc/services/portability/posix/kconfig/index.rst b/doc/services/portability/posix/kconfig/index.rst index 9263ba0bd6b65..1864070fd78a0 100644 --- a/doc/services/portability/posix/kconfig/index.rst +++ b/doc/services/portability/posix/kconfig/index.rst @@ -17,7 +17,6 @@ implementation of the POSIX API. * :kconfig:option:`CONFIG_MAX_PTHREAD_KEY_COUNT` * :kconfig:option:`CONFIG_MAX_PTHREAD_MUTEX_COUNT` * :kconfig:option:`CONFIG_MAX_PTHREAD_SPINLOCK_COUNT` -* :kconfig:option:`CONFIG_MAX_TIMER_COUNT` * :kconfig:option:`CONFIG_MQUEUE_NAMELEN_MAX` * :kconfig:option:`CONFIG_MSG_COUNT_MAX` * :kconfig:option:`CONFIG_MSG_SIZE_MAX` @@ -25,7 +24,6 @@ implementation of the POSIX API. * :kconfig:option:`CONFIG_NET_SOCKETS` * :kconfig:option:`CONFIG_NET_SOCKETS_POLL_MAX` * :kconfig:option:`CONFIG_POSIX_API` -* :kconfig:option:`CONFIG_POSIX_CLOCK` * :kconfig:option:`CONFIG_POSIX_FS` * :kconfig:option:`CONFIG_POSIX_MAX_FDS` * :kconfig:option:`CONFIG_POSIX_MAX_OPEN_FILES` @@ -46,4 +44,4 @@ implementation of the POSIX API. * :kconfig:option:`CONFIG_PTHREAD_RECYCLER_DELAY_MS` * :kconfig:option:`CONFIG_PTHREAD_SPINLOCK` * :kconfig:option:`CONFIG_SEM_VALUE_MAX` -* :kconfig:option:`CONFIG_TIMER` +* :kconfig:option:`CONFIG_TIMER_CREATE_WAIT` diff --git a/doc/services/portability/posix/option_groups/index.rst b/doc/services/portability/posix/option_groups/index.rst index e284af76d0254..00a5c34ad4ffc 100644 --- a/doc/services/portability/posix/option_groups/index.rst +++ b/doc/services/portability/posix/option_groups/index.rst @@ -543,6 +543,17 @@ _POSIX_ASYNCHRONOUS_IO aio_write(),yes (will fail with ``ENOSYS``:ref:`†`) lio_listio(),yes (will fail with ``ENOSYS``:ref:`†`) +.. _posix_option_cputime: + +_POSIX_CPUTIME +++++++++++++++ + +.. csv-table:: _POSIX_CPUTIME + :header: API, Supported + :widths: 50,10 + + CLOCK_PROCESS_CPUTIME_ID,yes + .. _posix_option_fsync: _POSIX_FSYNC diff --git a/include/zephyr/posix/posix_features.h b/include/zephyr/posix/posix_features.h index 09af5d3e6c584..1b47289e2e449 100644 --- a/include/zephyr/posix/posix_features.h +++ b/include/zephyr/posix/posix_features.h @@ -31,11 +31,13 @@ #define _POSIX_BARRIERS _POSIX_VERSION #endif -#ifdef CONFIG_POSIX_CLOCK +#ifdef CONFIG_POSIX_CLOCK_SELECTION #define _POSIX_CLOCK_SELECTION _POSIX_VERSION #endif -/* #define _POSIX_CPUTIME (-1L) */ +#ifdef CONFIG_POSIX_CPUTIME +#define _POSIX_CPUTIME _POSIX_VERSION +#endif #ifdef CONFIG_POSIX_FSYNC #define _POSIX_FSYNC _POSIX_VERSION @@ -55,7 +57,7 @@ #define _POSIX_MESSAGE_PASSING _POSIX_VERSION #endif -#ifdef CONFIG_POSIX_CLOCK +#ifdef CONFIG_POSIX_MONOTONIC_CLOCK #define _POSIX_MONOTONIC_CLOCK _POSIX_VERSION #endif @@ -100,7 +102,9 @@ #define _POSIX_THREAD_ATTR_STACKSIZE _POSIX_VERSION #endif -/* #define _POSIX_THREAD_CPUTIME (-1L) */ +#ifdef CONFIG_POSIX_THREAD_CPUTIME +#define _POSIX_THREAD_CPUTIME _POSIX_VERSION +#endif #ifdef CONFIG_PTHREAD_IPC #define _POSIX_THREAD_PRIO_INHERIT _POSIX_VERSION @@ -124,11 +128,11 @@ #endif #endif -#ifdef CONFIG_POSIX_CLOCK +#ifdef CONFIG_POSIX_TIMEOUTS #define _POSIX_TIMEOUTS _POSIX_VERSION #endif -#ifdef CONFIG_POSIX_CLOCK +#ifdef CONFIG_POSIX_TIMERS #define _POSIX_TIMERS _POSIX_VERSION #endif @@ -161,7 +165,6 @@ #define _POSIX2_C_BIND _POSIX2_VERSION #define _POSIX2_C_DEV _POSIX2_VERSION /* #define _POSIX2_CHAR_TERM (-1L) */ -/* #define _POSIX2_DELAYTIMER_MAX (-1L) */ /* #define _POSIX2_FORT_DEV (-1L) */ /* #define _POSIX2_FORT_RUN (-1L) */ /* #define _POSIX2_LOCALEDEF (-1L) */ diff --git a/include/zephyr/posix/sys/sysconf.h b/include/zephyr/posix/sys/sysconf.h index b96e3b4da4dce..37f7ba2386b2f 100644 --- a/include/zephyr/posix/sys/sysconf.h +++ b/include/zephyr/posix/sys/sysconf.h @@ -141,55 +141,73 @@ enum { _SC_TZNAME_MAX, }; -#define __z_posix_sysconf_SC_ADVISORY_INFO _POSIX_ADVISORY_INFO -#define __z_posix_sysconf_SC_ASYNCHRONOUS_IO _POSIX_ASYNCHRONOUS_IO -#define __z_posix_sysconf_SC_BARRIERS _POSIX_BARRIERS -#define __z_posix_sysconf_SC_CLOCK_SELECTION _POSIX_CLOCK_SELECTION -#define __z_posix_sysconf_SC_CPUTIME _POSIX_CPUTIME -#define __z_posix_sysconf_SC_FSYNC _POSIX_FSYNC -#define __z_posix_sysconf_SC_IPV6 _POSIX_IPV6 -#define __z_posix_sysconf_SC_JOB_CONTROL _POSIX_JOB_CONTROL -#define __z_posix_sysconf_SC_MAPPED_FILES _POSIX_MAPPED_FILES -#define __z_posix_sysconf_SC_MEMLOCK _POSIX_MEMLOCK -#define __z_posix_sysconf_SC_MEMLOCK_RANGE _POSIX_MEMLOCK_RANGE -#define __z_posix_sysconf_SC_MEMORY_PROTECTION _POSIX_MEMORY_PROTECTION -#define __z_posix_sysconf_SC_MESSAGE_PASSING _POSIX_MESSAGE_PASSING -#define __z_posix_sysconf_SC_MONOTONIC_CLOCK _POSIX_MONOTONIC_CLOCK -#define __z_posix_sysconf_SC_PRIORITIZED_IO _POSIX_PRIORITIZED_IO -#define __z_posix_sysconf_SC_PRIORITY_SCHEDULING _POSIX_PRIORITY_SCHEDULING -#define __z_posix_sysconf_SC_RAW_SOCKETS _POSIX_RAW_SOCKETS -#define __z_posix_sysconf_SC_RE_DUP_MAX _POSIX_RE_DUP_MAX -#define __z_posix_sysconf_SC_READER_WRITER_LOCKS _POSIX_READER_WRITER_LOCKS -#define __z_posix_sysconf_SC_REALTIME_SIGNALS _POSIX_REALTIME_SIGNALS -#define __z_posix_sysconf_SC_REGEXP _POSIX_REGEXP -#define __z_posix_sysconf_SC_SAVED_IDS _POSIX_SAVED_IDS -#define __z_posix_sysconf_SC_SEMAPHORES _POSIX_SEMAPHORES -#define __z_posix_sysconf_SC_SHARED_MEMORY_OBJECTS _POSIX_SHARED_MEMORY_OBJECTS -#define __z_posix_sysconf_SC_SHELL _POSIX_SHELL -#define __z_posix_sysconf_SC_SPAWN _POSIX_SPAWN -#define __z_posix_sysconf_SC_SPIN_LOCKS _POSIX_SPIN_LOCKS -#define __z_posix_sysconf_SC_SPORADIC_SERVER _POSIX_SPORADIC_SERVER -#define __z_posix_sysconf_SC_SS_REPL_MAX _POSIX_SS_REPL_MAX -#define __z_posix_sysconf_SC_SYNCHRONIZED_IO _POSIX_SYNCHRONIZED_IO -#define __z_posix_sysconf_SC_THREAD_ATTR_STACKADDR _POSIX_THREAD_ATTR_STACKADDR -#define __z_posix_sysconf_SC_THREAD_ATTR_STACKSIZE _POSIX_THREAD_ATTR_STACKSIZE -#define __z_posix_sysconf_SC_THREAD_CPUTIME _POSIX_THREAD_CPUTIME -#define __z_posix_sysconf_SC_THREAD_PRIO_INHERIT _POSIX_THREAD_PRIO_INHERIT -#define __z_posix_sysconf_SC_THREAD_PRIO_PROTECT _POSIX_THREAD_PRIO_PROTECT -#define __z_posix_sysconf_SC_THREAD_PRIORITY_SCHEDULING _POSIX_THREAD_PRIORITY_SCHEDULING -#define __z_posix_sysconf_SC_THREAD_PROCESS_SHARED _POSIX_THREAD_PROCESS_SHARED -#define __z_posix_sysconf_SC_THREAD_ROBUST_PRIO_INHERIT _POSIX_THREAD_ROBUST_PRIO_INHERIT -#define __z_posix_sysconf_SC_THREAD_ROBUST_PRIO_PROTECT _POSIX_THREAD_ROBUST_PRIO_PROTECT -#define __z_posix_sysconf_SC_THREAD_SAFE_FUNCTIONS _POSIX_THREAD_SAFE_FUNCTIONS -#define __z_posix_sysconf_SC_THREAD_SPORADIC_SERVER _POSIX_THREAD_SPORADIC_SERVER -#define __z_posix_sysconf_SC_THREADS _POSIX_THREADS -#define __z_posix_sysconf_SC_TIMEOUTS _POSIX_TIMEOUTS -#define __z_posix_sysconf_SC_TIMERS _POSIX_TIMERS -#define __z_posix_sysconf_SC_TRACE _POSIX_TRACE -#define __z_posix_sysconf_SC_TRACE_EVENT_FILTER _POSIX_TRACE_EVENT_FILTER -#define __z_posix_sysconf_SC_TRACE_EVENT_NAME_MAX _POSIX_TRACE_EVENT_NAME_MAX -#define __z_posix_sysconf_SC_TRACE_INHERIT _POSIX_TRACE_INHERIT -#define __z_posix_sysconf_SC_TRACE_LOG _POSIX_TRACE_LOG +#define __z_posix_sysconf_SC_ADVISORY_INFO (-1L) +#define __z_posix_sysconf_SC_ASYNCHRONOUS_IO \ + COND_CODE_1(CONFIG_POSIX_ASYNCHRONOUS_IO, (_POSIX_ASYNCHRONOUS_IO), (-1L)) +#define __z_posix_sysconf_SC_BARRIERS COND_CODE_1(CONFIG_PTHREAD_BARRIER, (_POSIX_BARRIERS), (-1L)) +#define __z_posix_sysconf_SC_CLOCK_SELECTION \ + COND_CODE_1(CONFIG_POSIX_CLOCK_SELECTION, (_POSIX_CLOCK_SELECTION), (-1L)) +#define __z_posix_sysconf_SC_CPUTIME \ + COND_CODE_1(CONFIG_POSIX_CPUTIME, (_POSIX_CPUTIME), (-1L)) +#define __z_posix_sysconf_SC_FSYNC \ + COND_CODE_1(CONFIG_POSIX_FSYNC, (_POSIX_FSYNC), (-1L)) +#define __z_posix_sysconf_SC_IPV6 COND_CODE_1(CONFIG_NET_IPV6, (_POSIX_IPV6), (-1L)) +#define __z_posix_sysconf_SC_JOB_CONTROL (-1L) +#define __z_posix_sysconf_SC_MAPPED_FILES (-1L) +#define __z_posix_sysconf_SC_MEMLOCK (-1L) +#define __z_posix_sysconf_SC_MEMLOCK_RANGE (-1L) +#define __z_posix_sysconf_SC_MEMORY_PROTECTION (-1L) +#define __z_posix_sysconf_SC_MESSAGE_PASSING \ + COND_CODE_1(CONFIG_POSIX_MQUEUE, (_POSIX_MESSAGE_PASSING), (-1L)) +#define __z_posix_sysconf_SC_MONOTONIC_CLOCK \ + COND_CODE_1(CONFIG_POSIX_MONOTONIC_CLOCK, (_POSIX_MONOTONIC_CLOCK), (-1L)) +#define __z_posix_sysconf_SC_PRIORITIZED_IO (-1L) +#define __z_posix_sysconf_SC_PRIORITY_SCHEDULING \ + COND_CODE_1(CONFIG_POSIX_PRIORITY_SCHEDULING, (_POSIX_PRIORITY_SCHEDULING), (-1L)) +#define __z_posix_sysconf_SC_RAW_SOCKETS \ + COND_CODE_1(CONFIG_NET_SOCKETS_PACKET, (_POSIX_RAW_SOCKETS), (-1L)) +#define __z_posix_sysconf_SC_RE_DUP_MAX _POSIX_RE_DUP_MAX +#define __z_posix_sysconf_SC_READER_WRITER_LOCKS \ + COND_CODE_1(CONFIG_PTHREAD_IPC, (_POSIX_READER_WRITER_LOCKS), (-1L)) +#define __z_posix_sysconf_SC_REALTIME_SIGNALS (-1L) +#define __z_posix_sysconf_SC_REGEXP (-1L) +#define __z_posix_sysconf_SC_SAVED_IDS (-1L) +#define __z_posix_sysconf_SC_SEMAPHORES \ + COND_CODE_1(CONFIG_PTHREAD_IPC, (_POSIX_SEMAPHORES), (-1L)) +#define __z_posix_sysconf_SC_SHARED_MEMORY_OBJECTS (-1L) +#define __z_posix_sysconf_SC_SHELL (-1L) +#define __z_posix_sysconf_SC_SPAWN (-1L) +#define __z_posix_sysconf_SC_SPIN_LOCKS \ + COND_CODE_1(CONFIG_PTHREAD_SPINLOCK, (_POSIX_SPIN_LOCKS), (-1L)) +#define __z_posix_sysconf_SC_SPORADIC_SERVER (-1L) +#define __z_posix_sysconf_SC_SS_REPL_MAX _POSIX_SS_REPL_MAX +#define __z_posix_sysconf_SC_SYNCHRONIZED_IO (-1L) +#define __z_posix_sysconf_SC_THREAD_ATTR_STACKADDR \ + COND_CODE_1(CONFIG_PTHREAD_IPC, (_POSIX_THREAD_ATTR_STACKADDR), (-1)) +#define __z_posix_sysconf_SC_THREAD_ATTR_STACKSIZE \ + COND_CODE_1(CONFIG_PTHREAD_IPC, (_POSIX_THREAD_ATTR_STACKSIZE), (-1L)) +#define __z_posix_sysconf_SC_THREAD_CPUTIME (-1L) +#define __z_posix_sysconf_SC_THREAD_PRIO_INHERIT \ + COND_CODE_1(CONFIG_PTHREAD_IPC, (_POSIX_THREAD_PRIO_INHERIT), (-1L)) +#define __z_posix_sysconf_SC_THREAD_PRIO_PROTECT (-1L) +#define __z_posix_sysconf_SC_THREAD_PRIORITY_SCHEDULING (-1L) +#define __z_posix_sysconf_SC_THREAD_PROCESS_SHARED (-1L) +#define __z_posix_sysconf_SC_THREAD_ROBUST_PRIO_INHERIT (-1L) +#define __z_posix_sysconf_SC_THREAD_ROBUST_PRIO_PROTECT (-1L) +#define __z_posix_sysconf_SC_THREAD_SAFE_FUNCTIONS \ + COND_CODE_1(CONFIG_PTHREAD_IPC, (_POSIX_THREAD_SAFE_FUNCTIONS), (-1L)) +#define __z_posix_sysconf_SC_THREAD_SPORADIC_SERVER (-1L) +#define __z_posix_sysconf_SC_THREADS \ + COND_CODE_1(CONFIG_PTHREAD_IPC, (_POSIX_THREADS), (-1L)) +#define __z_posix_sysconf_SC_TIMEOUTS \ + COND_CODE_1(CONFIG_POSIX_TIMEOUTS, (_POSIX_TIMEOUTS), (-1L)) +#define __z_posix_sysconf_SC_TIMERS \ + COND_CODE_1(CONFIG_POSIX_TIMEOUTS, (_POSIX_TIMERS), (-1)) +#define __z_posix_sysconf_SC_TRACE (-1L) +#define __z_posix_sysconf_SC_TRACE_EVENT_FILTER (-1L) +#define __z_posix_sysconf_SC_TRACE_EVENT_NAME_MAX _POSIX_TRACE_NAME_MAX +#define __z_posix_sysconf_SC_TRACE_INHERIT (-1L) +#define __z_posix_sysconf_SC_TRACE_LOG (-1L) #define __z_posix_sysconf_SC_TRACE_NAME_MAX _POSIX_TRACE_NAME_MAX #define __z_posix_sysconf_SC_TRACE_SYS_MAX _POSIX_TRACE_SYS_MAX #define __z_posix_sysconf_SC_TRACE_USER_EVENT_MAX _POSIX_TRACE_USER_EVENT_MAX @@ -211,7 +229,7 @@ enum { #define __z_posix_sysconf_SC_2_C_DEV _POSIX2_C_DEV #define __z_posix_sysconf_SC_2_CHAR_TERM (-1L) #define __z_posix_sysconf_SC_COLL_WEIGHTS_MAX _POSIX2_COLL_WEIGHTS_MAX -#define __z_posix_sysconf_SC_DELAYTIMER_MAX _POSIX2_DELAYTIMER_MAX +#define __z_posix_sysconf_SC_DELAYTIMER_MAX _POSIX_DELAYTIMER_MAX #define __z_posix_sysconf_SC_EXPR_NEST_MAX _POSIX2_EXPR_NEST_MAX #define __z_posix_sysconf_SC_2_FORT_DEV (-1L) #define __z_posix_sysconf_SC_2_FORT_RUN (-1L) diff --git a/include/zephyr/posix/time.h b/include/zephyr/posix/time.h index 8038e783030f0..7ab609877573f 100644 --- a/include/zephyr/posix/time.h +++ b/include/zephyr/posix/time.h @@ -73,6 +73,10 @@ extern "C" { #define CLOCK_PROCESS_CPUTIME_ID 2 #endif +#ifndef CLOCK_THREAD_CPUTIME_ID +#define CLOCK_THREAD_CPUTIME_ID 3 +#endif + #ifndef CLOCK_MONOTONIC #define CLOCK_MONOTONIC 4 #endif diff --git a/lib/libc/minimal/Kconfig b/lib/libc/minimal/Kconfig index d7bc50c4157c2..a55bf7a87b268 100644 --- a/lib/libc/minimal/Kconfig +++ b/lib/libc/minimal/Kconfig @@ -78,13 +78,13 @@ config MINIMAL_LIBC_RAND config MINIMAL_LIBC_TIME bool "Time functions" - select COMMON_LIBC_TIME if POSIX_CLOCK + select COMMON_LIBC_TIME if POSIX_TIMERS select COMMON_LIBC_GMTIME_R default y help Enable time() and gmtime_r() for the minimal libc. - time() requires CONFIG_POSIX_CLOCK=y because it relies on the POSIX + time() requires CONFIG_POSIX_TIMERS=y because it relies on the POSIX clock_gettime() function. In order to make use of the non-reentrant gmtime(), it is necessary diff --git a/lib/libc/newlib/libc-hooks.c b/lib/libc/newlib/libc-hooks.c index 75a2859fb42a6..73137d8e4f7bd 100644 --- a/lib/libc/newlib/libc-hooks.c +++ b/lib/libc/newlib/libc-hooks.c @@ -565,7 +565,7 @@ void *_sbrk_r(struct _reent *r, int count) int _gettimeofday(struct timeval *__tp, void *__tzp) { -#ifdef CONFIG_POSIX_CLOCK +#ifdef CONFIG_XSI_SINGLE_PROCESS return gettimeofday(__tp, __tzp); #else /* Non-posix systems should not call gettimeofday() here as it will diff --git a/lib/posix/options/CMakeLists.txt b/lib/posix/options/CMakeLists.txt index 96995cbeebb81..2c8ebe8f202b0 100644 --- a/lib/posix/options/CMakeLists.txt +++ b/lib/posix/options/CMakeLists.txt @@ -24,7 +24,7 @@ if(CONFIG_POSIX_SIGNAL) ) endif() -if(CONFIG_POSIX_API OR CONFIG_PTHREAD_IPC OR CONFIG_POSIX_CLOCK OR +if(CONFIG_POSIX_API OR CONFIG_PTHREAD_IPC OR CONFIG_POSIX_TIMERS OR CONFIG_POSIX_MQUEUE OR CONFIG_POSIX_FS OR CONFIG_EVENTFD OR CONFIG_GETOPT) # This is a temporary workaround so that Newlib declares the appropriate # types for us. POSIX features to be formalized as part of #51211 @@ -39,18 +39,22 @@ zephyr_library_sources_ifdef(CONFIG_FNMATCH fnmatch.c) zephyr_library_sources_ifdef(CONFIG_GETENTROPY getentropy.c) zephyr_library_sources_ifdef(CONFIG_POSIX_API perror.c) zephyr_library_sources_ifdef(CONFIG_POSIX_ASYNCHRONOUS_IO aio.c) -zephyr_library_sources_ifdef(CONFIG_POSIX_CLOCK clock.c) -zephyr_library_sources_ifdef(CONFIG_POSIX_CLOCK nanosleep.c) -zephyr_library_sources_ifdef(CONFIG_POSIX_CLOCK sleep.c) zephyr_library_sources_ifdef(CONFIG_POSIX_CONFSTR confstr.c) zephyr_library_sources_ifdef(CONFIG_POSIX_ENV env.c) zephyr_library_sources_ifdef(CONFIG_POSIX_FS fs.c) zephyr_library_sources_ifdef(CONFIG_POSIX_MQUEUE mqueue.c) +zephyr_library_sources_ifdef(CONFIG_POSIX_MULTI_PROCESS + sleep.c +) zephyr_library_sources_ifdef(CONFIG_POSIX_NETWORKING net.c) zephyr_library_sources_ifdef(CONFIG_POSIX_PUTMSG stropts.c) zephyr_library_sources_ifdef(CONFIG_POSIX_SIGNAL signal.c ${STRSIGNAL_TABLE_H}) zephyr_library_sources_ifdef(CONFIG_POSIX_SYSCONF_IMPL_FULL sysconf.c) zephyr_library_sources_ifdef(CONFIG_POSIX_SYSLOG syslog.c) +zephyr_library_sources_ifdef(CONFIG_POSIX_TIMERS + clock.c + timer.c +) zephyr_library_sources_ifdef(CONFIG_POSIX_UNAME uname.c) zephyr_library_sources_ifdef(CONFIG_PTHREAD_IPC _common.c) zephyr_library_sources_ifdef(CONFIG_PTHREAD_BARRIER barrier.c) @@ -62,7 +66,6 @@ zephyr_library_sources_ifdef(CONFIG_PTHREAD_RWLOCK rwlock.c) zephyr_library_sources_ifdef(CONFIG_POSIX_PRIORITY_SCHEDULING sched.c) zephyr_library_sources_ifdef(CONFIG_PTHREAD_IPC semaphore.c) zephyr_library_sources_ifdef(CONFIG_PTHREAD_SPINLOCK spinlock.c) -zephyr_library_sources_ifdef(CONFIG_TIMER timer.c) zephyr_library_include_directories( ${ZEPHYR_BASE}/kernel/include diff --git a/lib/posix/options/Kconfig b/lib/posix/options/Kconfig index 8c49debe2a8d9..60993872f3d8a 100644 --- a/lib/posix/options/Kconfig +++ b/lib/posix/options/Kconfig @@ -14,21 +14,17 @@ config POSIX_API Enable mostly-standards-compliant implementations of various POSIX (IEEE 1003.1) APIs. -if POSIX_CLOCK - config PTHREAD_IPC bool "POSIX pthread IPC API" default y if POSIX_API + depends on POSIX_TIMERS help This enables a mostly-standards-compliant implementation of the pthread mutex, condition variable and barrier IPC mechanisms. -endif # POSIX_CLOCK - rsource "Kconfig.aio" rsource "Kconfig.barrier" -rsource "Kconfig.clock" rsource "Kconfig.cond" rsource "Kconfig.confstr" rsource "Kconfig.env" @@ -42,6 +38,7 @@ rsource "Kconfig.key" rsource "Kconfig.mqueue" rsource "Kconfig.mutex" rsource "Kconfig.net" +rsource "Kconfig.procN" rsource "Kconfig.pthread" rsource "Kconfig.rwlock" rsource "Kconfig.sched" @@ -53,6 +50,7 @@ rsource "Kconfig.sysconf" rsource "Kconfig.syslog" rsource "Kconfig.timer" rsource "Kconfig.uname" +rsource "Kconfig.xsi" rsource "Kconfig.deprecated" diff --git a/lib/posix/options/Kconfig.clock b/lib/posix/options/Kconfig.clock deleted file mode 100644 index 0d541c9f32fd8..0000000000000 --- a/lib/posix/options/Kconfig.clock +++ /dev/null @@ -1,11 +0,0 @@ -# Copyright (c) 2018 Intel Corporation -# -# SPDX-License-Identifier: Apache-2.0 - -config POSIX_CLOCK - bool "clock and sleep APIs" - default y if POSIX_API - imply TIMER - depends on !NATIVE_LIBC - help - This enables POSIX clock\_\*() and \*sleep() functions. diff --git a/lib/posix/options/Kconfig.deprecated b/lib/posix/options/Kconfig.deprecated index 126d14f5aae7b..50c294ac18312 100644 --- a/lib/posix/options/Kconfig.deprecated +++ b/lib/posix/options/Kconfig.deprecated @@ -6,6 +6,28 @@ menu "Deprecated POSIX options" +config MAX_TIMER_COUNT + int "Maximum number of timer_t [DEPRECATED]" + default POSIX_TIMER_MAX if POSIX_TIMERS + default 0 + help + This option is deprecated. + + Please use CONFIG_POSIX_TIMER_MAX instead. + +config POSIX_CLOCK + bool "clock and sleep APIs [DEPRECATED]" + select DEPRECATED + select POSIX_CLOCK_SELECTION + select POSIX_CPUTIME + select POSIX_MONOTONIC_CLOCK + select POSIX_TIMERS + select POSIX_TIMEOUTS + help + This option is deprecated. + + Please use CONFIG_POSIX_TIMERS instead. + config POSIX_LIMITS_RTSIG_MAX int "_POSIX_RTSIG_MAX value in limits.h [DEPRECATED]" default POSIX_RTSIG_MAX if POSIX_REALTIME_SIGNALS @@ -15,4 +37,22 @@ config POSIX_LIMITS_RTSIG_MAX Please use CONFIG_POSIX_RTSIG_MAX instead. +config TIMER + bool "Timer support [DEPRECATED]" + select DEPRECATED + select POSIX_TIMERS + help + This option is deprecated. + + Please use CONFIG_POSIX_TIMERS instead. + +config TIMER_DELAYTIMER_MAX + int "Maximum count returned my timer_getoverrun() in POSIX application [DEPRECATED]" + default POSIX_DELAYTIMER_MAX if POSIX_TIMERS + default 0 + help + This option is deprecated. + + Please use CONFIG_POSIX_DELAYTIMER_MAX instead. + endmenu diff --git a/lib/posix/options/Kconfig.procN b/lib/posix/options/Kconfig.procN new file mode 100644 index 0000000000000..3e22fcf137135 --- /dev/null +++ b/lib/posix/options/Kconfig.procN @@ -0,0 +1,16 @@ +# Copyright (c) 2024 Tenstorrent AI ULC +# +# SPDX-License-Identifier: Apache-2.0 + +config POSIX_MULTI_PROCESS + bool "POSIX multi-process support [EXPERIMENTAL]" + default y if POSIX_API + select EXPERIMENTAL + help + Support for multi-processing. + + Note: Currently Zephyr does not support multiple processes and therefore much of this option + group is not implemented and is considered undefined behaviour. + + For more information, please see + https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_subprofiles.html diff --git a/lib/posix/options/Kconfig.timer b/lib/posix/options/Kconfig.timer index 10905e9c21d56..cd53379716a53 100644 --- a/lib/posix/options/Kconfig.timer +++ b/lib/posix/options/Kconfig.timer @@ -1,13 +1,91 @@ # Copyright (c) 2018 Intel Corporation +# Copyright (c) 2024 Tenstorrent AI ULC # # SPDX-License-Identifier: Apache-2.0 -TYPE = TIMER -type = timer_t -type-function = timer_create -rsource "Kconfig.template.pooled_type" +menuconfig POSIX_TIMERS + bool "POSIX timers, clocks, and sleep functions" + default y if POSIX_API + help + Select 'y' here and Zephyr will provide implementations of clock_getres(), clock_gettime(), + clock_settime(), nanosleep(), timer_create(), timer_delete(), timer_getoverrun(), + timer_settime(), and timer_gettime(). + + For more information, please see + https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_subprofiles.html + +if POSIX_TIMERS + +config POSIX_THREAD_CPUTIME + bool "POSIX per-thread CPU-time clocks" + default y + help + This enables CLOCK_THREAD_CPUTIME_ID. + + For more information, please see + https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_port.html + https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap03.html#tag_03_118 + https://pubs.opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html#tag_15_08_05_04 + +config POSIX_MONOTONIC_CLOCK + bool "POSIX Monotonic clock support" + default y + help + This enables CLOCK_MONOTONIC. + + For more information, please see + https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_port.html + https://pubs.opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html#tag_15_08_05_03 + +config POSIX_CPUTIME + bool "POSIX per-process CPU-time clocks" + default y + help + This enables CLOCK_PROCESS_CPUTIME_ID. + + For more information, please see + https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_port.html + https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap03.html#tag_03_118 + https://pubs.opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html#tag_15_08_05_04 + +config POSIX_CLOCK_SELECTION + bool "POSIX Clock selection" + default y + help + This enables POSIX clock selection. + + For more information, please see + https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_port.html + https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_port.html#tag_24_03_04 -if TIMER +config POSIX_DELAYTIMER_MAX + int "Maximum count returned my timer_getoverrun() in POSIX application" + default 32 + help + This controls the maximum number of times a timer can overrun before + timer_getoverrun() in POSIX compliant application. + + For more information, please see + https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/limits.h.html + +config POSIX_TIMER_MAX + int "Maximum number of POSIX timers per process" + default 32 + help + Maximum simultaneously active timer_t in a POSIX application. + + For more information, please see + https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/limits.h.html + +config POSIX_TIMEOUTS + bool "Support timeouts for some blocking POSIX services" + default y + help + Enable mandatory timeouts for some blocking operations. + + For more information, please see + https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_port.html + https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_xbd_chap02.html config TIMER_CREATE_WAIT int "Time to wait for timer availability (in msec) in POSIX application" @@ -17,11 +95,8 @@ config TIMER_CREATE_WAIT This controls how long to wait for resources to come available to create a new timer in POSIX compliant application -config TIMER_DELAYTIMER_MAX - int "Maximum count returned my timer_getoverrun() in POSIX application" - default 20 - help - This controls the maximum number of times a timer can overrun before - timer_getoverrun() in POSIX compliant application. +module = TIMER +module-str = POSIX Timers +source "subsys/logging/Kconfig.template.log_config" -endif # TIMER +endif # POSIX_TIMERS diff --git a/lib/posix/options/Kconfig.xsi b/lib/posix/options/Kconfig.xsi new file mode 100644 index 0000000000000..6cc2bf58509e0 --- /dev/null +++ b/lib/posix/options/Kconfig.xsi @@ -0,0 +1,16 @@ +# Copyright (c) 2024 Tenstorrent AI ULC +# +# SPDX-License-Identifier: Apache-2.0 + +config XSI_SINGLE_PROCESS + bool "X/Open single process" + default y if POSIX_API + depends on POSIX_ENV + depends on POSIX_UNAME + depends on POSIX_CLOCK_SELECTION + help + Select 'y' here and Zephyr will provide implementations of + gethostid(), gettimeofday(), and putenv(). + + For more information, please see + https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_subprofiles.html diff --git a/lib/posix/options/_common.c b/lib/posix/options/_common.c index 85a8e7cae66db..8125570f26eec 100644 --- a/lib/posix/options/_common.c +++ b/lib/posix/options/_common.c @@ -8,7 +8,7 @@ #include #include -#ifdef CONFIG_POSIX_CLOCK +#ifdef CONFIG_POSIX_TIMERS int64_t timespec_to_timeoutms(const struct timespec *abstime) { int64_t milli_secs, secs, nsecs; @@ -30,4 +30,4 @@ int64_t timespec_to_timeoutms(const struct timespec *abstime) return milli_secs; } -#endif /* CONFIG_POSIX_CLOCK */ +#endif /* CONFIG_POSIX_TIMERS */ diff --git a/lib/posix/options/clock.c b/lib/posix/options/clock.c index 68692b5ecd6f9..5fa09daaae6d7 100644 --- a/lib/posix/options/clock.c +++ b/lib/posix/options/clock.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2018 Intel Corporation + * Copyright (c) 2018 Friedt Professional Engineering Services, Inc * * SPDX-License-Identifier: Apache-2.0 */ @@ -156,14 +157,43 @@ int clock_settime(clockid_t clock_id, const struct timespec *tp) return 0; } +/* + * Note: usleep() was removed in Issue 7. + * + * It is kept here for compatibility purposes. + * + * For more information, please see + * https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_xsh_chap01.html + * https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_xsh_chap03.html + */ +int usleep(useconds_t useconds) +{ + int32_t rem; + + if (useconds >= USEC_PER_SEC) { + errno = EINVAL; + return -1; + } + + rem = k_usleep(useconds); + __ASSERT_NO_MSG(rem >= 0); + if (rem > 0) { + /* sleep was interrupted by a call to k_wakeup() */ + errno = EINTR; + return -1; + } + + return 0; +} + /** * @brief Suspend execution for a nanosecond interval, or * until some absolute time relative to the specified clock. * * See IEEE 1003.1 */ -int clock_nanosleep(clockid_t clock_id, int flags, const struct timespec *rqtp, - struct timespec *rmtp) +static int __z_clock_nanosleep(clockid_t clock_id, int flags, const struct timespec *rqtp, + struct timespec *rmtp) { uint64_t ns; uint64_t us; @@ -225,6 +255,17 @@ int clock_nanosleep(clockid_t clock_id, int flags, const struct timespec *rqtp, return 0; } +int nanosleep(const struct timespec *rqtp, struct timespec *rmtp) +{ + return __z_clock_nanosleep(CLOCK_MONOTONIC, 0, rqtp, rmtp); +} + +int clock_nanosleep(clockid_t clock_id, int flags, const struct timespec *rqtp, + struct timespec *rmtp) +{ + return __z_clock_nanosleep(clock_id, flags, rqtp, rmtp); +} + /** * @brief Get current real time. * diff --git a/lib/posix/options/nanosleep.c b/lib/posix/options/nanosleep.c deleted file mode 100644 index aafb9dbeb7993..0000000000000 --- a/lib/posix/options/nanosleep.c +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright (c) 2018 Friedt Professional Engineering Services, Inc - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include -#include -#include -#include -/* required for struct timespec */ -#include -#include -#include - -/** - * @brief Suspend execution for nanosecond intervals. - * - * See IEEE 1003.1 - */ -int nanosleep(const struct timespec *rqtp, struct timespec *rmtp) -{ - return clock_nanosleep(CLOCK_MONOTONIC, 0, rqtp, rmtp); -} diff --git a/lib/posix/options/sleep.c b/lib/posix/options/sleep.c index 98fff715dda5f..dd739322c75ee 100644 --- a/lib/posix/options/sleep.c +++ b/lib/posix/options/sleep.c @@ -23,27 +23,3 @@ unsigned sleep(unsigned int seconds) return rem / MSEC_PER_SEC; } -/** - * @brief Suspend execution for microsecond intervals. - * - * See IEEE 1003.1 - */ -int usleep(useconds_t useconds) -{ - int32_t rem; - - if (useconds >= USEC_PER_SEC) { - errno = EINVAL; - return -1; - } - - rem = k_usleep(useconds); - __ASSERT_NO_MSG(rem >= 0); - if (rem > 0) { - /* sleep was interrupted by a call to k_wakeup() */ - errno = EINTR; - return -1; - } - - return 0; -} diff --git a/lib/posix/options/timer.c b/lib/posix/options/timer.c index 7caecc180a127..d556c78133142 100644 --- a/lib/posix/options/timer.c +++ b/lib/posix/options/timer.c @@ -29,8 +29,8 @@ struct timer_obj { uint32_t status; }; -K_MEM_SLAB_DEFINE(posix_timer_slab, sizeof(struct timer_obj), - CONFIG_MAX_TIMER_COUNT, __alignof__(struct timer_obj)); +K_MEM_SLAB_DEFINE(posix_timer_slab, sizeof(struct timer_obj), CONFIG_POSIX_TIMER_MAX, + __alignof__(struct timer_obj)); static void zephyr_timer_wrapper(struct k_timer *ztimer) { @@ -306,8 +306,8 @@ int timer_getoverrun(timer_t timerid) int overruns = k_timer_status_get(&timer->ztimer) - 1; - if (overruns > CONFIG_TIMER_DELAYTIMER_MAX) { - overruns = CONFIG_TIMER_DELAYTIMER_MAX; + if (overruns > CONFIG_POSIX_DELAYTIMER_MAX) { + overruns = CONFIG_POSIX_DELAYTIMER_MAX; } return overruns; diff --git a/modules/Kconfig.simplelink b/modules/Kconfig.simplelink index cbcf1766d6b27..843f95c36fa24 100644 --- a/modules/Kconfig.simplelink +++ b/modules/Kconfig.simplelink @@ -15,7 +15,7 @@ config SIMPLELINK_HOST_DRIVER select REQUIRES_FULL_LIBC select ERRNO select PTHREAD_IPC - select POSIX_CLOCK + select POSIX_TIMERS help Build the SimpleLink host driver diff --git a/modules/hostap/Kconfig b/modules/hostap/Kconfig index 490e70c0c7d67..9f1ba54995c79 100644 --- a/modules/hostap/Kconfig +++ b/modules/hostap/Kconfig @@ -7,7 +7,7 @@ config WIFI_NM_WPA_SUPPLICANT bool "WPA Suplicant from hostap project [EXPERIMENTAL]" - select POSIX_CLOCK + select POSIX_TIMERS select POSIX_SIGNAL select POSIX_API select NET_SOCKETS diff --git a/samples/net/cloud/aws_iot_mqtt/prj.conf b/samples/net/cloud/aws_iot_mqtt/prj.conf index 30277ffb18c18..fbede2f3bf946 100644 --- a/samples/net/cloud/aws_iot_mqtt/prj.conf +++ b/samples/net/cloud/aws_iot_mqtt/prj.conf @@ -13,7 +13,6 @@ CONFIG_HW_STACK_PROTECTION=y CONFIG_REQUIRES_FULL_LIBC=y CONFIG_SNTP=y CONFIG_JSON_LIBRARY=y -CONFIG_POSIX_CLOCK=y CONFIG_POSIX_API=y # DNS diff --git a/samples/subsys/shell/shell_module/overlay-usb.conf b/samples/subsys/shell/shell_module/overlay-usb.conf index 692287e23a120..a9afb6499cf92 100644 --- a/samples/subsys/shell/shell_module/overlay-usb.conf +++ b/samples/subsys/shell/shell_module/overlay-usb.conf @@ -4,8 +4,8 @@ CONFIG_SHELL_BACKEND_SERIAL_CHECK_DTR=y CONFIG_UART_LINE_CTRL=y CONFIG_USB_DEVICE_INITIALIZE_AT_BOOT=n -# POSIX_CLOCK requires an embedded C library while the native USB driver is incompatible with it. +# POSIX_TIMERS requires an embedded C library while the native USB driver is incompatible with it. # So let's disable it. Once USB_NATIVE_POSIX supports embedded C libraries this can be removed. -CONFIG_POSIX_CLOCK=n -# DATE_SHELL requires POSIX_CLOCK +CONFIG_POSIX_TIMERS=n +# DATE_SHELL requires POSIX_TIMERS CONFIG_DATE_SHELL=n diff --git a/samples/subsys/shell/shell_module/prj.conf b/samples/subsys/shell/shell_module/prj.conf index 41d51f8e22a7f..c6cc76bca402e 100644 --- a/samples/subsys/shell/shell_module/prj.conf +++ b/samples/subsys/shell/shell_module/prj.conf @@ -9,7 +9,7 @@ CONFIG_THREAD_MONITOR=y CONFIG_BOOT_BANNER=n CONFIG_THREAD_NAME=y CONFIG_DEVICE_SHELL=y -CONFIG_POSIX_CLOCK=y +CONFIG_POSIX_TIMERS=y CONFIG_DATE_SHELL=y CONFIG_THREAD_RUNTIME_STATS=y CONFIG_THREAD_RUNTIME_STATS_USE_TIMING_FUNCTIONS=y diff --git a/samples/subsys/shell/shell_module/prj_getopt.conf b/samples/subsys/shell/shell_module/prj_getopt.conf index 6bfeb3dec41e2..e3c8ecbc805bb 100644 --- a/samples/subsys/shell/shell_module/prj_getopt.conf +++ b/samples/subsys/shell/shell_module/prj_getopt.conf @@ -9,6 +9,6 @@ CONFIG_THREAD_MONITOR=y CONFIG_BOOT_BANNER=n CONFIG_THREAD_NAME=y CONFIG_DEVICE_SHELL=y -CONFIG_POSIX_CLOCK=y +CONFIG_POSIX_TIMERS=y CONFIG_DATE_SHELL=y CONFIG_THREAD_RUNTIME_STATS=y diff --git a/samples/subsys/shell/shell_module/prj_login.conf b/samples/subsys/shell/shell_module/prj_login.conf index d84acc15622ab..ff8e8a06c0df1 100644 --- a/samples/subsys/shell/shell_module/prj_login.conf +++ b/samples/subsys/shell/shell_module/prj_login.conf @@ -8,7 +8,7 @@ CONFIG_THREAD_MONITOR=y CONFIG_BOOT_BANNER=n CONFIG_THREAD_NAME=y CONFIG_DEVICE_SHELL=y -CONFIG_POSIX_CLOCK=y +CONFIG_POSIX_TIMERS=y CONFIG_DATE_SHELL=y CONFIG_THREAD_RUNTIME_STATS=y diff --git a/subsys/logging/Kconfig.processing b/subsys/logging/Kconfig.processing index 3cf9259c96d5a..da0a90b8126f7 100644 --- a/subsys/logging/Kconfig.processing +++ b/subsys/logging/Kconfig.processing @@ -161,7 +161,7 @@ config LOG_TIMESTAMP_64BIT config LOG_TIMESTAMP_USE_REALTIME bool "Use real time clock for timestamp" select LOG_TIMESTAMP_64BIT - depends on POSIX_CLOCK + depends on POSIX_TIMERS help When enabled, real time clock is used for timestamping. diff --git a/subsys/net/lib/lwm2m/Kconfig b/subsys/net/lib/lwm2m/Kconfig index 4fdd7228f707c..79323b165adf4 100644 --- a/subsys/net/lib/lwm2m/Kconfig +++ b/subsys/net/lib/lwm2m/Kconfig @@ -227,7 +227,7 @@ config LWM2M_RD_CLIENT_MAX_RETRIES config LWM2M_RESOURCE_DATA_CACHE_SUPPORT bool "Resource Time series data cache support" depends on (LWM2M_RW_SENML_JSON_SUPPORT || LWM2M_RW_SENML_CBOR_SUPPORT) - depends on (POSIX_CLOCK && RING_BUFFER) + depends on (POSIX_TIMERS && RING_BUFFER) help Enable time series data storage. Requires time() to provide current Unix timestamp. diff --git a/subsys/shell/modules/Kconfig b/subsys/shell/modules/Kconfig index cb7aedaa79e52..c57704ee2ae91 100644 --- a/subsys/shell/modules/Kconfig +++ b/subsys/shell/modules/Kconfig @@ -34,7 +34,7 @@ config DEVICE_SHELL config DATE_SHELL bool "Date shell" - depends on POSIX_CLOCK + depends on POSIX_TIMERS default y if !SHELL_MINIMAL help This shell provides access to date and time based on Unix time. diff --git a/tests/lib/time/prj.conf b/tests/lib/time/prj.conf index aac2e48e3649c..ce932c79220e4 100644 --- a/tests/lib/time/prj.conf +++ b/tests/lib/time/prj.conf @@ -1,3 +1,3 @@ CONFIG_ZTEST=y -CONFIG_POSIX_CLOCK=y +CONFIG_POSIX_TIMERS=y CONFIG_PICOLIBC=y diff --git a/tests/posix/common/src/uname.c b/tests/posix/common/src/uname.c index d41ab8306a108..9b1e76d6b5357 100644 --- a/tests/posix/common/src/uname.c +++ b/tests/posix/common/src/uname.c @@ -4,8 +4,10 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include #include +#include + +#include ZTEST(uname, test_uname) { diff --git a/tests/posix/headers/prj.conf b/tests/posix/headers/prj.conf index 950a7d510ef10..7161e4b311575 100644 --- a/tests/posix/headers/prj.conf +++ b/tests/posix/headers/prj.conf @@ -16,7 +16,7 @@ CONFIG_NET_SOCKETPAIR=y # for when CONFIG_POSIX_API is not selected CONFIG_PTHREAD_IPC=y CONFIG_POSIX_FS=y -CONFIG_POSIX_CLOCK=y +CONFIG_POSIX_TIMERS=y CONFIG_POSIX_MQUEUE=y CONFIG_EVENTFD=y CONFIG_GETOPT=y From 3f469665f4d9f724274f381359d8781856be6e23 Mon Sep 17 00:00:00 2001 From: Chris Friedt Date: Wed, 22 May 2024 16:35:57 -0400 Subject: [PATCH 1731/2849] posix: fd_mgmt: add fd_mgmt option group With this change, we collect implementations of functions that are part of the POSIX_FD_MGMT Option Group into one compilation unit (fd_mgmt.c) and provide a matching Kconfig symbol that is reflective of the standard. Additionally, provide Kconfig options for aliases of those functions since Newlib-based toolchains internally use an underscore-prefixed alias for many POSIX functions (in this case _lseek). Prefix Zephyr-native implementations with zvfs_ to prepare for the up-coming changes in that area. Signed-off-by: Chris Friedt --- doc/services/portability/posix/aep/index.rst | 2 +- lib/libc/Kconfig | 1 + lib/libc/newlib/libc-hooks.c | 10 ++-- lib/os/fdtable.c | 15 +----- lib/posix/options/CMakeLists.txt | 3 ++ lib/posix/options/Kconfig | 1 + lib/posix/options/Kconfig.fd_mgmt | 37 +++++++++++++++ lib/posix/options/fd_mgmt.c | 50 ++++++++++++++++++++ lib/posix/options/fs.c | 2 +- 9 files changed, 102 insertions(+), 19 deletions(-) create mode 100644 lib/posix/options/Kconfig.fd_mgmt create mode 100644 lib/posix/options/fd_mgmt.c diff --git a/doc/services/portability/posix/aep/index.rst b/doc/services/portability/posix/aep/index.rst index e1f9859e2639c..90ff03ea06c90 100644 --- a/doc/services/portability/posix/aep/index.rst +++ b/doc/services/portability/posix/aep/index.rst @@ -102,7 +102,7 @@ The *Realtime Controller System Profile* (PSE52) includes all features from PSE5 :widths: 50, 10, 50 :ref:`POSIX_C_LANG_MATH `, yes, - :ref:`POSIX_FD_MGMT `,, + :ref:`POSIX_FD_MGMT `,, :kconfig:option:`CONFIG_POSIX_FD_MGMT` :ref:`POSIX_FILE_SYSTEM `,, .. csv-table:: PSE52 Option Requirements diff --git a/lib/libc/Kconfig b/lib/libc/Kconfig index 1dcc3dc729ac3..f2835c9568f54 100644 --- a/lib/libc/Kconfig +++ b/lib/libc/Kconfig @@ -102,6 +102,7 @@ config NEWLIB_LIBC depends on !NATIVE_APPLICATION depends on NEWLIB_LIBC_SUPPORTED select NEED_LIBC_MEM_PARTITION + imply POSIX_FD_MGMT_ALIAS_LSEEK help Build with newlib library. The newlib library is expected to be part of the SDK in this case. diff --git a/lib/libc/newlib/libc-hooks.c b/lib/libc/newlib/libc-hooks.c index 73137d8e4f7bd..e45a935e66762 100644 --- a/lib/libc/newlib/libc-hooks.c +++ b/lib/libc/newlib/libc-hooks.c @@ -238,16 +238,18 @@ int _close(int file) return -1; } __weak FUNC_ALIAS(_close, close, int); +#else +extern ssize_t write(int file, const char *buffer, size_t count); +#define _write write +#endif +#ifndef CONFIG_POSIX_FD_MGMT int _lseek(int file, int ptr, int dir) { return 0; } __weak FUNC_ALIAS(_lseek, lseek, int); -#else -extern ssize_t write(int file, const char *buffer, size_t count); -#define _write write -#endif +#endif /* CONFIG_POSIX_FD_MGMT */ int _isatty(int file) { diff --git a/lib/os/fdtable.c b/lib/os/fdtable.c index e02bc2f661f41..826b616f9d5ec 100644 --- a/lib/os/fdtable.c +++ b/lib/os/fdtable.c @@ -366,7 +366,7 @@ int fsync(int fd) FUNC_ALIAS(fsync, _fsync, int); #endif /* CONFIG_POSIX_FSYNC */ -off_t lseek(int fd, off_t offset, int whence) +off_t zvfs_lseek(int fd, off_t offset, int whence) { if (_check_fd(fd) < 0) { return -1; @@ -375,7 +375,6 @@ off_t lseek(int fd, off_t offset, int whence) return z_fdtable_call_ioctl(fdtable[fd].vtable, fdtable[fd].obj, ZFD_IOCTL_LSEEK, offset, whence); } -FUNC_ALIAS(lseek, _lseek, off_t); int ioctl(int fd, unsigned long request, ...) { @@ -393,26 +392,16 @@ int ioctl(int fd, unsigned long request, ...) return res; } -int fcntl(int fd, int cmd, ...) +int zvfs_fcntl(int fd, int cmd, va_list args) { - va_list args; int res; if (_check_fd(fd) < 0) { return -1; } - /* Handle fdtable commands. */ - if (cmd == F_DUPFD) { - /* Not implemented so far. */ - errno = EINVAL; - return -1; - } - /* The rest of commands are per-fd, handled by ioctl vmethod. */ - va_start(args, cmd); res = fdtable[fd].vtable->ioctl(fdtable[fd].obj, cmd, args); - va_end(args); return res; } diff --git a/lib/posix/options/CMakeLists.txt b/lib/posix/options/CMakeLists.txt index 2c8ebe8f202b0..3ad45db28b905 100644 --- a/lib/posix/options/CMakeLists.txt +++ b/lib/posix/options/CMakeLists.txt @@ -41,6 +41,9 @@ zephyr_library_sources_ifdef(CONFIG_POSIX_API perror.c) zephyr_library_sources_ifdef(CONFIG_POSIX_ASYNCHRONOUS_IO aio.c) zephyr_library_sources_ifdef(CONFIG_POSIX_CONFSTR confstr.c) zephyr_library_sources_ifdef(CONFIG_POSIX_ENV env.c) +zephyr_library_sources_ifdef(CONFIG_POSIX_FD_MGMT + fd_mgmt.c +) zephyr_library_sources_ifdef(CONFIG_POSIX_FS fs.c) zephyr_library_sources_ifdef(CONFIG_POSIX_MQUEUE mqueue.c) zephyr_library_sources_ifdef(CONFIG_POSIX_MULTI_PROCESS diff --git a/lib/posix/options/Kconfig b/lib/posix/options/Kconfig index 60993872f3d8a..658c8cab2d6b1 100644 --- a/lib/posix/options/Kconfig +++ b/lib/posix/options/Kconfig @@ -30,6 +30,7 @@ rsource "Kconfig.confstr" rsource "Kconfig.env" rsource "Kconfig.eventfd" rsource "Kconfig.fdtable" +rsource "Kconfig.fd_mgmt" rsource "Kconfig.fnmatch" rsource "Kconfig.fs" rsource "Kconfig.getentropy" diff --git a/lib/posix/options/Kconfig.fd_mgmt b/lib/posix/options/Kconfig.fd_mgmt new file mode 100644 index 0000000000000..f1bacac36d69e --- /dev/null +++ b/lib/posix/options/Kconfig.fd_mgmt @@ -0,0 +1,37 @@ +# Copyright (c) 2024 Tenstorrent AI ULC +# +# SPDX-License-Identifier: Apache-2.0 + +menuconfig POSIX_FD_MGMT + bool "POSIX file descriptor management [EXPERIMENTAL]" + default y if POSIX_API + select EXPERIMENTAL + help + Select 'y' here and Zephyr will provide implementations for the POSIX_FD_MGMT Option Group. + This includes support for dup(), dup2(), fcntl(), fseeko(), ftello(), ftruncate(), + and lseek(). + + For more information, please see + https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_subprofiles.html + +if POSIX_FD_MGMT + +# These options are intended to be used for compatibility with external POSIX +# implementations such as those in Newlib or Picolibc. + +config POSIX_FD_MGMT_ALIAS_FCNTL + bool + help + Select 'y' here and Zephyr will provide an alias for fcntl() as _fcntl(). + +config POSIX_FD_MGMT_ALIAS_FTRUNCATE + bool + help + Select 'y' here and Zephyr will provide an alias for ftruncate() as _ftruncate(). + +config POSIX_FD_MGMT_ALIAS_LSEEK + bool + help + Select 'y' here and Zephyr will provide an alias for lseek() as _lseek(). + +endif # POSIX_FD_MGMT diff --git a/lib/posix/options/fd_mgmt.c b/lib/posix/options/fd_mgmt.c new file mode 100644 index 0000000000000..c1f60aca8e490 --- /dev/null +++ b/lib/posix/options/fd_mgmt.c @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2024, Tenstorrent AI ULC + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +#include +#include +#include +#include + +/* prototypes for external, not-yet-public, functions in fdtable.c or fs.c */ +int zvfs_fcntl(int fd, int cmd, va_list arg); +int zvfs_ftruncate(int fd, off_t length); +off_t zvfs_lseek(int fd, off_t offset, int whence); + +int fcntl(int fd, int cmd, ...) +{ + int ret; + va_list args; + + va_start(args, cmd); + ret = zvfs_fcntl(fd, cmd, args); + va_end(args); + + return ret; +} +#ifdef CONFIG_POSIX_FD_MGMT_ALIAS_FCNTL +FUNC_ALIAS(fcntl, _fcntl, int); +#endif /* CONFIG_POSIX_FD_MGMT_ALIAS_FCNTL */ + +int ftruncate(int fd, off_t length) +{ + return zvfs_ftruncate(fd, length); +} +#ifdef CONFIG_POSIX_FD_MGMT_ALIAS_FTRUNCATE +FUNC_ALIAS(ftruncate, _ftruncate, int); +#endif /* CONFIG_POSIX_FD_MGMT_ALIAS_FTRUNCATE */ + +off_t lseek(int fd, off_t offset, int whence) +{ + return zvfs_lseek(fd, offset, whence); +} +#ifdef CONFIG_POSIX_FD_MGMT_ALIAS_LSEEK +FUNC_ALIAS(lseek, _lseek, off_t); +#endif /* CONFIG_POSIX_FD_MGMT_ALIAS_LSEEK */ diff --git a/lib/posix/options/fs.c b/lib/posix/options/fs.c index 091a3ddccda0d..70b8d75b3008c 100644 --- a/lib/posix/options/fs.c +++ b/lib/posix/options/fs.c @@ -421,7 +421,7 @@ int mkdir(const char *path, mode_t mode) * @brief Truncate file to specified length. * */ -int ftruncate(int fd, off_t length) +int zvfs_ftruncate(int fd, off_t length) { int rc; struct posix_fs_desc *ptr = NULL; From bc4374b5fe526b9fbadbc2a51860d9d514dae80c Mon Sep 17 00:00:00 2001 From: Chris Friedt Date: Tue, 21 May 2024 22:45:15 -0400 Subject: [PATCH 1732/2849] posix: deprecate POSIX_MAX_FDS and add POSIX_DEVICE_IO The POSIX_MAX_FDS option does not correspond to any standard POSIX option. It was used to define the size of the file descriptor table, which is by no means exclusively used by POSIX (also net, fs, ...). POSIX_MAX_FDS is being deprecated in order to ensure that Zephyr's POSIX Kconfig variables correspond to those defined in the specification, as of IEEE 1003.1-2017. Namely, POSIX_OPEN_MAX. CONFIG_POSIX_MAX_OPEN_FILES is being deprecated for the same reason. To mitigate any possible layering violations, that option is not user selectable. It tracks the newly added CONFIG_ZVFS_OPEN_MAX option, which is native to Zephyr. With this deprecation, we introduce the following Kconfig options that map directly to standard POSIX Option Groups by simply removing "CONFIG_": * CONFIG_POSIX_DEVICE_IO Similarly, with this deprecation, we introduce the following Kconfig options that map directly to standard POSIX Options by simply removing "CONFIG": * CONFIG_POSIX_OPEN_MAX In order to maintain parity with the current feature set, we introduce the following Kconfig options. * CONFIG_POSIX_DEVICE_IO_ALIAS_CLOSE * CONFIG_POSIX_DEVICE_IO_ALIAS_OPEN * CONFIG_POSIX_DEVICE_IO_ALIAS_READ * CONFIG_POSIX_DEVICE_IO_ALIAS_WRITE Gate open(), close(), read(), and write() via the CONFIG_POSIX_DEVICE_IO Kconfig option and move implementations into device_io.c, to be conformant with the spec. Lastly, stage function names for upcoming ZVFS work, to be completed as part of the LTSv3 Roadmap (e.g. zvfs_open(), ..). Signed-off-by: Chris Friedt --- .../networking/net_config_guide.rst | 2 +- doc/services/portability/posix/aep/index.rst | 2 +- .../portability/posix/kconfig/index.rst | 4 +- drivers/modem/Kconfig | 2 +- include/zephyr/net/socket_select.h | 2 +- include/zephyr/posix/posix_features.h | 2 +- include/zephyr/posix/sys/sysconf.h | 2 +- lib/libc/Kconfig | 4 ++ lib/libc/newlib/libc-hooks.c | 21 +++--- lib/os/Kconfig | 9 +++ lib/os/fdtable.c | 34 +++++----- lib/posix/options/CMakeLists.txt | 6 +- lib/posix/options/Kconfig | 2 +- lib/posix/options/Kconfig.deprecated | 20 ++++++ lib/posix/options/Kconfig.device_io | 57 +++++++++++++++++ lib/posix/options/Kconfig.fdtable | 16 ----- lib/posix/options/Kconfig.fs | 7 -- lib/posix/options/device_io.c | 64 +++++++++++++++++++ lib/posix/options/fs.c | 15 +---- lib/posix/options/net.c | 12 ---- modules/hostap/Kconfig | 2 +- samples/modules/thrift/hello/client/prj.conf | 4 +- samples/modules/thrift/hello/server/prj.conf | 2 +- samples/net/mqtt_sn_publisher/prj.conf | 2 +- .../net/sockets/dumb_http_server_mt/prj.conf | 2 +- .../net/sockets/echo_client/overlay-tls.conf | 2 +- .../net/sockets/echo_server/overlay-tls.conf | 2 +- samples/net/sockets/echo_server/prj.conf | 4 +- samples/net/sockets/echo_service/prj.conf | 2 +- samples/net/sockets/http_server/prj.conf | 2 +- samples/net/sockets/net_mgmt/prj.conf | 2 +- samples/net/sockets/packet/prj.conf | 2 +- samples/net/zperf/prj.conf | 2 +- samples/subsys/video/tcpserversink/prj.conf | 2 +- subsys/net/lib/sockets/socket_obj_core.c | 4 +- .../thrift/ThriftTest/overlay-tls.conf | 2 +- tests/modules/thrift/ThriftTest/prj.conf | 2 +- tests/net/lib/dns_resolve/prj.conf | 2 +- tests/net/lib/http_server/crime/prj.conf | 2 +- tests/net/lib/http_server/prototype/prj.conf | 2 +- tests/net/lib/http_server/tls/prj.conf | 4 +- tests/net/pm/prj.conf | 2 +- tests/net/socket/af_packet/prj.conf | 2 +- .../net/socket/af_packet_ipproto_raw/prj.conf | 2 +- tests/net/socket/poll/prj.conf | 2 +- tests/net/socket/reuseaddr_reuseport/prj.conf | 2 +- tests/net/socket/select/prj.conf | 2 +- tests/net/socket/select/src/main.c | 2 +- tests/net/socket/service/prj.conf | 2 +- tests/net/socket/socketpair/prj.conf | 2 +- tests/net/socket/tcp/prj.conf | 2 +- tests/net/socket/tcp/src/main.c | 2 +- tests/net/socket/tls/prj.conf | 2 +- tests/net/socket/tls_ext/prj.conf | 2 +- tests/net/socket/udp/prj.conf | 2 +- tests/net/socket/udp/src/main.c | 2 +- tests/posix/fs/src/test_fs_file.c | 2 +- 57 files changed, 237 insertions(+), 128 deletions(-) create mode 100644 lib/posix/options/Kconfig.device_io delete mode 100644 lib/posix/options/Kconfig.fdtable create mode 100644 lib/posix/options/device_io.c diff --git a/doc/connectivity/networking/net_config_guide.rst b/doc/connectivity/networking/net_config_guide.rst index 177ff434e8ae1..fd4f0ff402f18 100644 --- a/doc/connectivity/networking/net_config_guide.rst +++ b/doc/connectivity/networking/net_config_guide.rst @@ -87,7 +87,7 @@ Socket Options Maximum number of supported poll() entries. One needs to select proper value here depending on how many BSD sockets are polled in the system. -:kconfig:option:`CONFIG_POSIX_MAX_FDS` +:kconfig:option:`CONFIG_ZVFS_OPEN_MAX` Maximum number of open file descriptors, this includes files, sockets, special devices, etc. One needs to select proper value here depending on how many BSD sockets are created in the system. diff --git a/doc/services/portability/posix/aep/index.rst b/doc/services/portability/posix/aep/index.rst index 90ff03ea06c90..d6cbeb9447f8c 100644 --- a/doc/services/portability/posix/aep/index.rst +++ b/doc/services/portability/posix/aep/index.rst @@ -50,7 +50,7 @@ The *Minimal Realtime System Profile* (PSE51) includes all of the :ref:`POSIX_C_LANG_JUMP `, yes, :ref:`POSIX_C_LANG_SUPPORT `, yes, - :ref:`POSIX_DEVICE_IO `,, + :ref:`POSIX_DEVICE_IO `,, :kconfig:option:`CONFIG_POSIX_DEVICE_IO` :ref:`POSIX_SIGNALS `,, :ref:`POSIX_SINGLE_PROCESS `, yes, :ref:`POSIX_THREADS_BASE `, yes, diff --git a/doc/services/portability/posix/kconfig/index.rst b/doc/services/portability/posix/kconfig/index.rst index 1864070fd78a0..58ef24943c6a6 100644 --- a/doc/services/portability/posix/kconfig/index.rst +++ b/doc/services/portability/posix/kconfig/index.rst @@ -25,8 +25,8 @@ implementation of the POSIX API. * :kconfig:option:`CONFIG_NET_SOCKETS_POLL_MAX` * :kconfig:option:`CONFIG_POSIX_API` * :kconfig:option:`CONFIG_POSIX_FS` -* :kconfig:option:`CONFIG_POSIX_MAX_FDS` -* :kconfig:option:`CONFIG_POSIX_MAX_OPEN_FILES` +* :kconfig:option:`CONFIG_ZVFS_OPEN_MAX` +* :kconfig:option:`CONFIG_POSIX_OPEN_MAX` * :kconfig:option:`CONFIG_POSIX_MQUEUE` * :kconfig:option:`CONFIG_POSIX_RTSIG_MAX` * :kconfig:option:`CONFIG_POSIX_SIGNAL` diff --git a/drivers/modem/Kconfig b/drivers/modem/Kconfig index dbc78f067d79e..578a2b77e461f 100644 --- a/drivers/modem/Kconfig +++ b/drivers/modem/Kconfig @@ -155,7 +155,7 @@ config MODEM_SOCKET modem_socket_init(). Note that the modem socket uses runtime allocated file descriptors reserved from the fdtable, for which the max count is set using the - Kconfig option POSIX_MAX_FDS. Make sure to update this value as both + Kconfig option ZVFS_OPEN_MAX. Make sure to update this value as both the modem sockets and the POSIX_API, if used, share them. config MODEM_SOCKET_PACKET_COUNT diff --git a/include/zephyr/net/socket_select.h b/include/zephyr/net/socket_select.h index 23034d31d7903..5fca2950d6a59 100644 --- a/include/zephyr/net/socket_select.h +++ b/include/zephyr/net/socket_select.h @@ -28,7 +28,7 @@ extern "C" { /** Socket file descriptor set. */ typedef struct zsock_fd_set { - uint32_t bitset[(CONFIG_POSIX_MAX_FDS + 31) / 32]; + uint32_t bitset[(CONFIG_ZVFS_OPEN_MAX + 31) / 32]; } zsock_fd_set; /** diff --git a/include/zephyr/posix/posix_features.h b/include/zephyr/posix/posix_features.h index 1b47289e2e449..da42000c7c81a 100644 --- a/include/zephyr/posix/posix_features.h +++ b/include/zephyr/posix/posix_features.h @@ -211,7 +211,7 @@ #define _POSIX_MQ_PRIO_MAX (32) #define _POSIX_NAME_MAX (14) #define _POSIX_NGROUPS_MAX (8) -#define _POSIX_OPEN_MAX CONFIG_POSIX_MAX_FDS +#define _POSIX_OPEN_MAX CONFIG_POSIX_OPEN_MAX #define _POSIX_PATH_MAX (256) #define _POSIX_PIPE_BUF (512) #define _POSIX_RE_DUP_MAX (255) diff --git a/include/zephyr/posix/sys/sysconf.h b/include/zephyr/posix/sys/sysconf.h index 37f7ba2386b2f..1732dfd0f181d 100644 --- a/include/zephyr/posix/sys/sysconf.h +++ b/include/zephyr/posix/sys/sysconf.h @@ -268,7 +268,7 @@ enum { #define __z_posix_sysconf_SC_NGROUPS_MAX _POSIX_NGROUPS_MAX #define __z_posix_sysconf_SC_MQ_OPEN_MAX MQ_OPEN_MAX #define __z_posix_sysconf_SC_MQ_PRIO_MAX MQ_PRIO_MAX -#define __z_posix_sysconf_SC_OPEN_MAX CONFIG_POSIX_MAX_FDS +#define __z_posix_sysconf_SC_OPEN_MAX CONFIG_ZVFS_OPEN_MAX #define __z_posix_sysconf_SC_PAGE_SIZE PAGE_SIZE #define __z_posix_sysconf_SC_PAGESIZE PAGESIZE #define __z_posix_sysconf_SC_THREAD_DESTRUCTOR_ITERATIONS PTHREAD_DESTRUCTOR_ITERATIONS diff --git a/lib/libc/Kconfig b/lib/libc/Kconfig index f2835c9568f54..062dd875cb0d6 100644 --- a/lib/libc/Kconfig +++ b/lib/libc/Kconfig @@ -102,6 +102,10 @@ config NEWLIB_LIBC depends on !NATIVE_APPLICATION depends on NEWLIB_LIBC_SUPPORTED select NEED_LIBC_MEM_PARTITION + imply POSIX_DEVICE_IO_ALIAS_CLOSE + imply POSIX_DEVICE_IO_ALIAS_OPEN + imply POSIX_DEVICE_IO_ALIAS_READ + imply POSIX_DEVICE_IO_ALIAS_WRITE imply POSIX_FD_MGMT_ALIAS_LSEEK help Build with newlib library. The newlib library is expected to be diff --git a/lib/libc/newlib/libc-hooks.c b/lib/libc/newlib/libc-hooks.c index e45a935e66762..048aa97a5beb6 100644 --- a/lib/libc/newlib/libc-hooks.c +++ b/lib/libc/newlib/libc-hooks.c @@ -23,6 +23,12 @@ #include #include +int _read(int fd, void *buf, int nbytes); +int _write(int fd, const void *buf, int nbytes); +int _open(const char *name, int mode); +int _close(int file); +int _lseek(int file, int ptr, int dir); + #define LIBC_BSS K_APP_BMEM(z_libc_partition) #define LIBC_DATA K_APP_DMEM(z_libc_partition) @@ -210,8 +216,8 @@ static inline int z_vrfy_zephyr_write_stdout(const void *buf, int nbytes) #include #endif -#ifndef CONFIG_POSIX_API -int _read(int fd, char *buf, int nbytes) +#ifndef CONFIG_POSIX_DEVICE_IO +int _read(int fd, void *buf, int nbytes) { ARG_UNUSED(fd); @@ -238,10 +244,7 @@ int _close(int file) return -1; } __weak FUNC_ALIAS(_close, close, int); -#else -extern ssize_t write(int file, const char *buffer, size_t count); -#define _write write -#endif +#endif /* CONFIG_POSIX_DEVICE_IO */ #ifndef CONFIG_POSIX_FD_MGMT int _lseek(int file, int ptr, int dir) @@ -275,6 +278,7 @@ int _fstat(int file, struct stat *st) return 0; } __weak FUNC_ALIAS(_fstat, fstat, int); +#endif /* CONFIG_POSIX_FILE_SYSTEM */ __weak void _exit(int status) { @@ -478,11 +482,6 @@ __weak FUNC_NORETURN void __chk_fail(void) } #if CONFIG_XTENSA -extern int _read(int fd, char *buf, int nbytes); -extern int _open(const char *name, int mode); -extern int _close(int file); -extern int _lseek(int file, int ptr, int dir); - /* The Newlib in xtensa toolchain has a few missing functions for the * reentrant versions of the syscalls. */ diff --git a/lib/os/Kconfig b/lib/os/Kconfig index 14b6241b72c93..863f5e93b3ef7 100644 --- a/lib/os/Kconfig +++ b/lib/os/Kconfig @@ -10,6 +10,15 @@ config FDTABLE for any I/O object implementing POSIX I/O semantics (i.e. read/write + aux operations). +config ZVFS_OPEN_MAX + int "Maximum number of open file descriptors" + default 16 if WIFI_NM_WPA_SUPPLICANT + default 16 if POSIX_API + default 4 + help + Maximum number of open file descriptors, this includes + files, sockets, special devices, etc. + config PRINTK_SYNC bool "Serialize printk() calls" default y if SMP && MP_MAX_NUM_CPUS > 1 && !(EFI_CONSOLE && LOG) diff --git a/lib/os/fdtable.c b/lib/os/fdtable.c index 826b616f9d5ec..1770bd008a865 100644 --- a/lib/os/fdtable.c +++ b/lib/os/fdtable.c @@ -31,12 +31,14 @@ struct fd_entry { struct k_condvar cond; }; -#ifdef CONFIG_POSIX_API +#if defined(CONFIG_POSIX_DEVICE_IO) static const struct fd_op_vtable stdinout_fd_op_vtable; -#endif -static struct fd_entry fdtable[CONFIG_POSIX_MAX_FDS] = { -#ifdef CONFIG_POSIX_API +BUILD_ASSERT(CONFIG_ZVFS_OPEN_MAX >= 3, "CONFIG_ZVFS_OPEN_MAX >= 3 for CONFIG_POSIX_DEVICE_IO"); +#endif /* defined(CONFIG_POSIX_DEVICE_IO) */ + +static struct fd_entry fdtable[CONFIG_ZVFS_OPEN_MAX] = { +#if defined(CONFIG_POSIX_DEVICE_IO) /* * Predefine entries for stdin/stdout/stderr. */ @@ -62,9 +64,7 @@ static struct fd_entry fdtable[CONFIG_POSIX_MAX_FDS] = { .cond = Z_CONDVAR_INITIALIZER(fdtable[2].cond), }, #else - { - 0 - }, + {0}, #endif }; @@ -296,9 +296,7 @@ int z_alloc_fd(void *obj, const struct fd_op_vtable *vtable) return fd; } -#ifdef CONFIG_POSIX_API - -ssize_t read(int fd, void *buf, size_t sz) +ssize_t zvfs_read(int fd, void *buf, size_t sz) { ssize_t res; @@ -314,9 +312,8 @@ ssize_t read(int fd, void *buf, size_t sz) return res; } -FUNC_ALIAS(read, _read, ssize_t); -ssize_t write(int fd, const void *buf, size_t sz) +ssize_t zvfs_write(int fd, const void *buf, size_t sz) { ssize_t res; @@ -332,9 +329,8 @@ ssize_t write(int fd, const void *buf, size_t sz) return res; } -FUNC_ALIAS(write, _write, ssize_t); -int close(int fd) +int zvfs_close(int fd) { int res; @@ -352,7 +348,6 @@ int close(int fd) return res; } -FUNC_ALIAS(close, _close, int); #ifdef CONFIG_POSIX_FSYNC int fsync(int fd) @@ -372,8 +367,8 @@ off_t zvfs_lseek(int fd, off_t offset, int whence) return -1; } - return z_fdtable_call_ioctl(fdtable[fd].vtable, fdtable[fd].obj, ZFD_IOCTL_LSEEK, - offset, whence); + return z_fdtable_call_ioctl(fdtable[fd].vtable, fdtable[fd].obj, ZFD_IOCTL_LSEEK, offset, + whence); } int ioctl(int fd, unsigned long request, ...) @@ -406,6 +401,7 @@ int zvfs_fcntl(int fd, int cmd, va_list args) return res; } +#if defined(CONFIG_POSIX_DEVICE_IO) /* * fd operations for stdio/stdout/stderr */ @@ -420,7 +416,7 @@ static ssize_t stdinout_read_vmeth(void *obj, void *buffer, size_t count) static ssize_t stdinout_write_vmeth(void *obj, const void *buffer, size_t count) { #if defined(CONFIG_BOARD_NATIVE_POSIX) - return write(1, buffer, count); + return zvfs_write(1, buffer, count); #elif defined(CONFIG_NEWLIB_LIBC) || defined(CONFIG_ARCMWDT_LIBC) return z_impl_zephyr_write_stdout(buffer, count); #else @@ -441,4 +437,4 @@ static const struct fd_op_vtable stdinout_fd_op_vtable = { .ioctl = stdinout_ioctl_vmeth, }; -#endif /* CONFIG_POSIX_API */ +#endif /* defined(CONFIG_POSIX_DEVICE_IO) */ diff --git a/lib/posix/options/CMakeLists.txt b/lib/posix/options/CMakeLists.txt index 3ad45db28b905..40326acdadaf8 100644 --- a/lib/posix/options/CMakeLists.txt +++ b/lib/posix/options/CMakeLists.txt @@ -37,9 +37,13 @@ add_subdirectory_ifdef(CONFIG_GETOPT getopt) zephyr_library_sources_ifdef(CONFIG_EVENTFD eventfd.c) zephyr_library_sources_ifdef(CONFIG_FNMATCH fnmatch.c) zephyr_library_sources_ifdef(CONFIG_GETENTROPY getentropy.c) -zephyr_library_sources_ifdef(CONFIG_POSIX_API perror.c) zephyr_library_sources_ifdef(CONFIG_POSIX_ASYNCHRONOUS_IO aio.c) zephyr_library_sources_ifdef(CONFIG_POSIX_CONFSTR confstr.c) +zephyr_library_sources_ifdef(CONFIG_POSIX_DEVICE_IO + # perror should be moved to the common libc + perror.c + device_io.c +) zephyr_library_sources_ifdef(CONFIG_POSIX_ENV env.c) zephyr_library_sources_ifdef(CONFIG_POSIX_FD_MGMT fd_mgmt.c diff --git a/lib/posix/options/Kconfig b/lib/posix/options/Kconfig index 658c8cab2d6b1..85631445f1273 100644 --- a/lib/posix/options/Kconfig +++ b/lib/posix/options/Kconfig @@ -27,9 +27,9 @@ rsource "Kconfig.aio" rsource "Kconfig.barrier" rsource "Kconfig.cond" rsource "Kconfig.confstr" +rsource "Kconfig.device_io" rsource "Kconfig.env" rsource "Kconfig.eventfd" -rsource "Kconfig.fdtable" rsource "Kconfig.fd_mgmt" rsource "Kconfig.fnmatch" rsource "Kconfig.fs" diff --git a/lib/posix/options/Kconfig.deprecated b/lib/posix/options/Kconfig.deprecated index 50c294ac18312..ab76a8b891f2c 100644 --- a/lib/posix/options/Kconfig.deprecated +++ b/lib/posix/options/Kconfig.deprecated @@ -37,6 +37,26 @@ config POSIX_LIMITS_RTSIG_MAX Please use CONFIG_POSIX_RTSIG_MAX instead. +config POSIX_MAX_FDS + int "Maximum number of open file descriptors [DEPRECATED]" + default POSIX_OPEN_MAX + help + This option is deprecated. + + Please use CONFIG_POSIX_OPEN_MAX instead. + + See also CONFIG_ZVFS_OPEN_MAX. + +config POSIX_MAX_OPEN_FILES + int "Maximum number of open file descriptors [DEPRECATED]" + default POSIX_OPEN_MAX + help + This option is deprecated. + + Please use CONFIG_POSIX_OPEN_MAX instead. + + See also CONFIG_ZVFS_OPEN_MAX. + config TIMER bool "Timer support [DEPRECATED]" select DEPRECATED diff --git a/lib/posix/options/Kconfig.device_io b/lib/posix/options/Kconfig.device_io new file mode 100644 index 0000000000000..a93b51f5be627 --- /dev/null +++ b/lib/posix/options/Kconfig.device_io @@ -0,0 +1,57 @@ +# Copyright (c) 2024 Tenstorrent AI ULC +# +# SPDX-License-Identifier: Apache-2.0 + +menu "POSIX device I/O" + +config POSIX_DEVICE_IO + bool "POSIX device I/O [EXPERIMENTAL]" + default y if POSIX_API + select FDTABLE + select EXPERIMENTAL + help + Select 'y' here and Zephyr will provide an implementation of the POSIX_DEVICE_IO Option + Group such as FD_CLR(), FD_ISSET(), FD_SET(), FD_ZERO(), close(), fdopen(), fileno(), open(), + poll(), pread(), pselect(), pwrite(), read(), select(), and write(). + + For more informnation, please see + https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_subprofiles.html + +if POSIX_DEVICE_IO + +# These options are intended to be used for compatibility with external POSIX +# implementations such as those in Newlib or Picolibc. + +config POSIX_DEVICE_IO_ALIAS_CLOSE + bool + help + Select 'y' here and Zephyr will provide an alias for close() as _close(). + +config POSIX_DEVICE_IO_ALIAS_OPEN + bool + help + Select 'y' here and Zephyr will provide an alias for open() as _open(). + +config POSIX_DEVICE_IO_ALIAS_READ + bool + help + Select 'y' here and Zephyr will provide an alias for read() as _read(). + +config POSIX_DEVICE_IO_ALIAS_WRITE + bool + help + Select 'y' here and Zephyr will provide an alias for write() as _write(). + +endif # POSIX_DEVICE_IO + +config POSIX_OPEN_MAX + int + default ZVFS_OPEN_MAX + help + The maximum number of files that a process can have open at one time. This option is not + directly user-configurable but can be adjusted via CONFIG_ZVFS_OPEN_MAX. + + For more information, please see + https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/limits.h.html + +endmenu diff --git a/lib/posix/options/Kconfig.fdtable b/lib/posix/options/Kconfig.fdtable deleted file mode 100644 index 214e4a04ae98f..0000000000000 --- a/lib/posix/options/Kconfig.fdtable +++ /dev/null @@ -1,16 +0,0 @@ -# Copyright (c) 2018 Linaro -# -# SPDX-License-Identifier: Apache-2.0 - -menu "File descriptor table options" - -config POSIX_MAX_FDS - int "Maximum number of open file descriptors" - default 16 if WIFI_NM_WPA_SUPPLICANT - default 16 if POSIX_API - default 4 - help - Maximum number of open file descriptors, this includes - files, sockets, special devices, etc. - -endmenu # "File descriptor table options" diff --git a/lib/posix/options/Kconfig.fs b/lib/posix/options/Kconfig.fs index bff95a906a9cf..35c01cf72a150 100644 --- a/lib/posix/options/Kconfig.fs +++ b/lib/posix/options/Kconfig.fs @@ -12,13 +12,6 @@ menuconfig POSIX_FS if POSIX_FS -config POSIX_MAX_OPEN_FILES - int "Maximum number of open file descriptors" - default 16 - 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 diff --git a/lib/posix/options/device_io.c b/lib/posix/options/device_io.c new file mode 100644 index 0000000000000..585dc7000c2be --- /dev/null +++ b/lib/posix/options/device_io.c @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2024, Tenstorrent AI ULC + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +#include +#include +#include +#include + +/* prototypes for external, not-yet-public, functions in fdtable.c or fs.c */ +int zvfs_close(int fd); +int zvfs_open(const char *name, int flags); +ssize_t zvfs_read(int fd, void *buf, size_t sz); +ssize_t zvfs_write(int fd, const void *buf, size_t sz); + +int close(int fd) +{ + return zvfs_close(fd); +} +#ifdef CONFIG_POSIX_DEVICE_IO_ALIAS_CLOSE +FUNC_ALIAS(close, _close, int); +#endif + +int open(const char *name, int flags, ...) +{ + /* FIXME: necessarily need to check for O_CREAT and unpack ... if set */ + return zvfs_open(name, flags); +} +#ifdef CONFIG_POSIX_DEVICE_IO_ALIAS_OPEN +FUNC_ALIAS(open, _open, int); +#endif + +int poll(struct pollfd *fds, int nfds, int timeout) +{ + /* TODO: create zvfs_poll() and dispatch to subsystems based on file type */ + return zsock_poll(fds, nfds, timeout); +} + +ssize_t read(int fd, void *buf, size_t sz) +{ + return zvfs_read(fd, buf, sz); +} +#ifdef CONFIG_POSIX_DEVICE_IO_ALIAS_READ +FUNC_ALIAS(read, _read, ssize_t); +#endif + +int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout) +{ + /* TODO: create zvfs_select() and dispatch to subsystems based on file type */ + return zsock_select(nfds, readfds, writefds, exceptfds, (struct zsock_timeval *)timeout); +} + +ssize_t write(int fd, const void *buf, size_t sz) +{ + return zvfs_write(fd, buf, sz); +} +#ifdef CONFIG_POSIX_DEVICE_IO_ALIAS_WRITE +FUNC_ALIAS(write, _write, ssize_t); +#endif diff --git a/lib/posix/options/fs.c b/lib/posix/options/fs.c index 70b8d75b3008c..caec36692d61c 100644 --- a/lib/posix/options/fs.c +++ b/lib/posix/options/fs.c @@ -26,7 +26,7 @@ struct posix_fs_desc { bool used; }; -static struct posix_fs_desc desc_array[CONFIG_POSIX_MAX_OPEN_FILES]; +static struct posix_fs_desc desc_array[CONFIG_POSIX_OPEN_MAX]; static struct fs_dirent fdirent; static struct dirent pdirent; @@ -39,7 +39,7 @@ static struct posix_fs_desc *posix_fs_alloc_obj(bool is_dir) struct posix_fs_desc *ptr = NULL; unsigned int key = irq_lock(); - for (i = 0; i < CONFIG_POSIX_MAX_OPEN_FILES; i++) { + for (i = 0; i < CONFIG_POSIX_OPEN_MAX; i++) { if (desc_array[i].used == false) { ptr = &desc_array[i]; ptr->used = true; @@ -80,12 +80,7 @@ static int posix_mode_to_zephyr(int mf) return mode; } -/** - * @brief Open a file. - * - * See IEEE 1003.1 - */ -int open(const char *name, int flags, ...) +int zvfs_open(const char *name, int flags) { int rc, fd; struct posix_fs_desc *ptr = NULL; @@ -123,10 +118,6 @@ int open(const char *name, int flags, ...) return fd; } -#if !defined(CONFIG_NEWLIB_LIBC) && !defined(CONFIG_PICOLIBC) -FUNC_ALIAS(open, _open, int); -#endif - static int fs_close_vmeth(void *obj) { struct posix_fs_desc *ptr = obj; diff --git a/lib/posix/options/net.c b/lib/posix/options/net.c index 5fcfdca464c8e..618c630630ecd 100644 --- a/lib/posix/options/net.c +++ b/lib/posix/options/net.c @@ -13,8 +13,6 @@ #include #include #include -#include -#include #include /* From arpa/inet.h */ @@ -355,11 +353,6 @@ int listen(int sock, int backlog) return zsock_listen(sock, backlog); } -int poll(struct pollfd *fds, int nfds, int timeout) -{ - return zsock_poll(fds, nfds, timeout); -} - ssize_t recv(int sock, void *buf, size_t max_len, int flags) { return zsock_recv(sock, buf, max_len, flags); @@ -376,11 +369,6 @@ ssize_t recvmsg(int sock, struct msghdr *msg, int flags) return zsock_recvmsg(sock, msg, flags); } -int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout) -{ - return zsock_select(nfds, readfds, writefds, exceptfds, (struct zsock_timeval *)timeout); -} - ssize_t send(int sock, const void *buf, size_t len, int flags) { return zsock_send(sock, buf, len, flags); diff --git a/modules/hostap/Kconfig b/modules/hostap/Kconfig index 9f1ba54995c79..ab6eadf837684 100644 --- a/modules/hostap/Kconfig +++ b/modules/hostap/Kconfig @@ -41,7 +41,7 @@ config WIFI_NM_WPA_SUPPLICANT_WQ_PRIO int "Thread priority of wpa_supplicant iface workqueue" default 7 -# Currently we default POSIX_MAX_FDS to 16 in lib/posix/Kconfig +# Currently we default ZVFS_OPEN_MAX to 16 in lib/posix/Kconfig # l2_packet - 1 # ctrl_iface - 2 * socketpairs = 4(local and global) # z_wpa_event_sock - 1 socketpair = 2 diff --git a/samples/modules/thrift/hello/client/prj.conf b/samples/modules/thrift/hello/client/prj.conf index a83715ddfc792..0f094d14d6c2e 100644 --- a/samples/modules/thrift/hello/client/prj.conf +++ b/samples/modules/thrift/hello/client/prj.conf @@ -28,7 +28,7 @@ CONFIG_NET_TCP=y CONFIG_NET_IPV6=n CONFIG_NET_IPV4=y CONFIG_NET_SOCKETS=y -CONFIG_POSIX_MAX_FDS=6 +CONFIG_ZVFS_OPEN_MAX=6 CONFIG_NET_CONNECTION_MANAGER=y # Kernel options @@ -61,7 +61,7 @@ CONFIG_NET_CONFIG_PEER_IPV4_ADDR="192.0.2.2" # Number of socket descriptors might need adjusting # if there are more than 1 handlers defined. -CONFIG_POSIX_MAX_FDS=16 +CONFIG_ZVFS_OPEN_MAX=16 # Some platforms require relatively large stack sizes. # This can be tuned per-board. diff --git a/samples/modules/thrift/hello/server/prj.conf b/samples/modules/thrift/hello/server/prj.conf index 1aacd9d14d758..fe78b9a2803a5 100644 --- a/samples/modules/thrift/hello/server/prj.conf +++ b/samples/modules/thrift/hello/server/prj.conf @@ -51,7 +51,7 @@ CONFIG_NET_CONFIG_PEER_IPV4_ADDR="192.0.2.2" # Number of socket descriptors might need adjusting # if there are more than 1 handlers defined. -CONFIG_POSIX_MAX_FDS=16 +CONFIG_ZVFS_OPEN_MAX=16 # Some platforms require relatively large stack sizes. # This can be tuned per-board. diff --git a/samples/net/mqtt_sn_publisher/prj.conf b/samples/net/mqtt_sn_publisher/prj.conf index 367ba8082f489..efe1a8f3e207e 100644 --- a/samples/net/mqtt_sn_publisher/prj.conf +++ b/samples/net/mqtt_sn_publisher/prj.conf @@ -5,7 +5,7 @@ CONFIG_NET_IPV4=y CONFIG_NET_IPV6=n CONFIG_NET_SOCKETS=y CONFIG_POSIX_API=y -CONFIG_POSIX_MAX_FDS=6 +CONFIG_ZVFS_OPEN_MAX=6 CONFIG_NET_CONNECTION_MANAGER=y # Kernel options diff --git a/samples/net/sockets/dumb_http_server_mt/prj.conf b/samples/net/sockets/dumb_http_server_mt/prj.conf index af851a0406e3e..7b802e6e8b482 100644 --- a/samples/net/sockets/dumb_http_server_mt/prj.conf +++ b/samples/net/sockets/dumb_http_server_mt/prj.conf @@ -2,7 +2,7 @@ CONFIG_TEST_RANDOM_GENERATOR=y # POSIX options -CONFIG_POSIX_MAX_FDS=20 +CONFIG_ZVFS_OPEN_MAX=20 CONFIG_POSIX_API=y # Networking config diff --git a/samples/net/sockets/echo_client/overlay-tls.conf b/samples/net/sockets/echo_client/overlay-tls.conf index 8235291cefc19..b6183e9f14daa 100644 --- a/samples/net/sockets/echo_client/overlay-tls.conf +++ b/samples/net/sockets/echo_client/overlay-tls.conf @@ -12,4 +12,4 @@ CONFIG_MBEDTLS_SSL_MAX_CONTENT_LEN=2048 CONFIG_NET_SOCKETS_SOCKOPT_TLS=y CONFIG_NET_SOCKETS_TLS_MAX_CONTEXTS=4 CONFIG_NET_SOCKETS_ENABLE_DTLS=y -CONFIG_POSIX_MAX_FDS=8 +CONFIG_ZVFS_OPEN_MAX=8 diff --git a/samples/net/sockets/echo_server/overlay-tls.conf b/samples/net/sockets/echo_server/overlay-tls.conf index f9d650ecd0293..fa91a0f6258b5 100644 --- a/samples/net/sockets/echo_server/overlay-tls.conf +++ b/samples/net/sockets/echo_server/overlay-tls.conf @@ -13,4 +13,4 @@ CONFIG_NET_SOCKETS_SOCKOPT_TLS=y CONFIG_NET_SOCKETS_TLS_MAX_CONTEXTS=6 CONFIG_NET_SOCKETS_ENABLE_DTLS=y CONFIG_NET_SOCKETS_DTLS_TIMEOUT=30000 -CONFIG_POSIX_MAX_FDS=16 +CONFIG_ZVFS_OPEN_MAX=16 diff --git a/samples/net/sockets/echo_server/prj.conf b/samples/net/sockets/echo_server/prj.conf index e88c98eda3956..c95e09b71b85f 100644 --- a/samples/net/sockets/echo_server/prj.conf +++ b/samples/net/sockets/echo_server/prj.conf @@ -6,7 +6,7 @@ CONFIG_NET_IPV6=y CONFIG_NET_IPV4=y CONFIG_NET_SOCKETS=y CONFIG_POSIX_API=y -CONFIG_POSIX_MAX_FDS=6 +CONFIG_ZVFS_OPEN_MAX=6 CONFIG_NET_CONNECTION_MANAGER=y # Kernel options @@ -48,7 +48,7 @@ CONFIG_NET_CONFIG_PEER_IPV4_ADDR="192.0.2.2" # Number of socket descriptors might need adjusting # if there are more than 1 handlers defined. -CONFIG_POSIX_MAX_FDS=12 +CONFIG_ZVFS_OPEN_MAX=12 # How many client can connect to echo-server simultaneously CONFIG_NET_SAMPLE_NUM_HANDLERS=1 diff --git a/samples/net/sockets/echo_service/prj.conf b/samples/net/sockets/echo_service/prj.conf index d7ffe73835280..b9c053c27a2b6 100644 --- a/samples/net/sockets/echo_service/prj.conf +++ b/samples/net/sockets/echo_service/prj.conf @@ -10,7 +10,7 @@ CONFIG_NET_IPV6=y CONFIG_NET_TCP=y CONFIG_NET_SOCKETS=y CONFIG_NET_IPV4_MAPPING_TO_IPV6=y -CONFIG_POSIX_MAX_FDS=10 +CONFIG_ZVFS_OPEN_MAX=10 CONFIG_NET_MAX_CONN=5 CONFIG_NET_SOCKETS_SERVICE=y CONFIG_NET_SOCKETS_POLL_MAX=20 diff --git a/samples/net/sockets/http_server/prj.conf b/samples/net/sockets/http_server/prj.conf index 3d13a55cbf29b..51d898eb15c2d 100644 --- a/samples/net/sockets/http_server/prj.conf +++ b/samples/net/sockets/http_server/prj.conf @@ -5,7 +5,7 @@ CONFIG_LOG=y CONFIG_ENTROPY_GENERATOR=y CONFIG_TEST_RANDOM_GENERATOR=y CONFIG_INIT_STACKS=y -CONFIG_POSIX_MAX_FDS=32 +CONFIG_ZVFS_OPEN_MAX=32 CONFIG_POSIX_API=y CONFIG_FDTABLE=y CONFIG_NET_SOCKETS_POLL_MAX=32 diff --git a/samples/net/sockets/net_mgmt/prj.conf b/samples/net/sockets/net_mgmt/prj.conf index 243cce2173552..a94f5da00948d 100644 --- a/samples/net/sockets/net_mgmt/prj.conf +++ b/samples/net/sockets/net_mgmt/prj.conf @@ -6,7 +6,7 @@ CONFIG_NET_IPV6=y CONFIG_NET_IPV4=y CONFIG_NET_SOCKETS=y CONFIG_POSIX_API=y -CONFIG_POSIX_MAX_FDS=6 +CONFIG_ZVFS_OPEN_MAX=6 CONFIG_NET_SOCKETS_NET_MGMT=y CONFIG_NET_MGMT_EVENT=y diff --git a/samples/net/sockets/packet/prj.conf b/samples/net/sockets/packet/prj.conf index d01c89254e155..555e824bf5880 100644 --- a/samples/net/sockets/packet/prj.conf +++ b/samples/net/sockets/packet/prj.conf @@ -7,7 +7,7 @@ CONFIG_NET_IPV4=n CONFIG_NET_MAX_CONTEXTS=10 CONFIG_NET_SOCKETS=y CONFIG_POSIX_API=y -CONFIG_POSIX_MAX_FDS=6 +CONFIG_ZVFS_OPEN_MAX=6 CONFIG_NET_CONTEXT_RCVTIMEO=y CONFIG_NET_MGMT=y CONFIG_NET_MGMT_EVENT=y diff --git a/samples/net/zperf/prj.conf b/samples/net/zperf/prj.conf index e355986210bbd..0bf23e7a7e502 100644 --- a/samples/net/zperf/prj.conf +++ b/samples/net/zperf/prj.conf @@ -20,7 +20,7 @@ CONFIG_NET_MAX_CONTEXTS=5 CONFIG_NET_TC_TX_COUNT=1 CONFIG_NET_SOCKETS=y CONFIG_NET_SOCKETS_POLL_MAX=9 -CONFIG_POSIX_MAX_FDS=8 +CONFIG_ZVFS_OPEN_MAX=8 CONFIG_POSIX_API=y CONFIG_INIT_STACKS=y diff --git a/samples/subsys/video/tcpserversink/prj.conf b/samples/subsys/video/tcpserversink/prj.conf index 43ddea77f51d2..824c424b2fa8a 100644 --- a/samples/subsys/video/tcpserversink/prj.conf +++ b/samples/subsys/video/tcpserversink/prj.conf @@ -3,7 +3,7 @@ CONFIG_NETWORKING=y CONFIG_NET_TCP=y CONFIG_NET_IPV4=y CONFIG_NET_SOCKETS=y -CONFIG_POSIX_MAX_FDS=6 +CONFIG_ZVFS_OPEN_MAX=6 CONFIG_POSIX_API=y # Kernel options diff --git a/subsys/net/lib/sockets/socket_obj_core.c b/subsys/net/lib/sockets/socket_obj_core.c index 276576e825fc6..9c3e37f6185a2 100644 --- a/subsys/net/lib/sockets/socket_obj_core.c +++ b/subsys/net/lib/sockets/socket_obj_core.c @@ -20,8 +20,8 @@ static K_MUTEX_DEFINE(sock_obj_mutex); /* Allocate some extra socket objects so that we can track * closed sockets and get some historical statistics. */ -static struct sock_obj sock_objects[CONFIG_POSIX_MAX_FDS * 2] = { - [0 ... ((CONFIG_POSIX_MAX_FDS * 2) - 1)] = { +static struct sock_obj sock_objects[CONFIG_ZVFS_OPEN_MAX * 2] = { + [0 ... ((CONFIG_ZVFS_OPEN_MAX * 2) - 1)] = { .fd = -1, .init_done = false, } diff --git a/tests/modules/thrift/ThriftTest/overlay-tls.conf b/tests/modules/thrift/ThriftTest/overlay-tls.conf index b98beb610c339..7676b38883292 100644 --- a/tests/modules/thrift/ThriftTest/overlay-tls.conf +++ b/tests/modules/thrift/ThriftTest/overlay-tls.conf @@ -14,7 +14,7 @@ CONFIG_THRIFT_SSL_SOCKET=y # tcp sockets (client, server): 2 # tls sockets (client, server): 2 # socketpairs for cancellation (accept, client, server): 6 -CONFIG_POSIX_MAX_FDS=15 +CONFIG_ZVFS_OPEN_MAX=15 # TLS configuration CONFIG_MBEDTLS=y diff --git a/tests/modules/thrift/ThriftTest/prj.conf b/tests/modules/thrift/ThriftTest/prj.conf index 6619fb8295d9b..80872a61085f0 100755 --- a/tests/modules/thrift/ThriftTest/prj.conf +++ b/tests/modules/thrift/ThriftTest/prj.conf @@ -51,7 +51,7 @@ CONFIG_NET_PKT_RX_COUNT=20 # stdin, stdout, stderr: 3 # socketpair for channel: 2 # eventfd for cancellation: 1 -CONFIG_POSIX_MAX_FDS=6 +CONFIG_ZVFS_OPEN_MAX=6 # Network address config CONFIG_NET_IPV4=y diff --git a/tests/net/lib/dns_resolve/prj.conf b/tests/net/lib/dns_resolve/prj.conf index 9f5452f5834b6..39ab38272e6ac 100644 --- a/tests/net/lib/dns_resolve/prj.conf +++ b/tests/net/lib/dns_resolve/prj.conf @@ -30,4 +30,4 @@ CONFIG_ZTEST=y CONFIG_MAIN_STACK_SIZE=1344 CONFIG_NET_SOCKETS_POLL_MAX=9 -CONFIG_POSIX_MAX_FDS=8 +CONFIG_ZVFS_OPEN_MAX=8 diff --git a/tests/net/lib/http_server/crime/prj.conf b/tests/net/lib/http_server/crime/prj.conf index 0596a54e47c77..a1f7ef3a8efe5 100644 --- a/tests/net/lib/http_server/crime/prj.conf +++ b/tests/net/lib/http_server/crime/prj.conf @@ -9,7 +9,7 @@ CONFIG_ENTROPY_GENERATOR=y CONFIG_TEST_RANDOM_GENERATOR=y CONFIG_ZTEST_STACK_SIZE=1024 -CONFIG_POSIX_MAX_FDS=10 +CONFIG_ZVFS_OPEN_MAX=10 CONFIG_REQUIRES_FULL_LIBC=y CONFIG_EVENTFD_MAX=10 CONFIG_NET_MAX_CONTEXTS=10 diff --git a/tests/net/lib/http_server/prototype/prj.conf b/tests/net/lib/http_server/prototype/prj.conf index 20570610ef79d..5e9ad2b1412ad 100644 --- a/tests/net/lib/http_server/prototype/prj.conf +++ b/tests/net/lib/http_server/prototype/prj.conf @@ -7,7 +7,7 @@ CONFIG_POSIX_API=y CONFIG_ENTROPY_GENERATOR=y CONFIG_TEST_RANDOM_GENERATOR=y -CONFIG_POSIX_MAX_FDS=10 +CONFIG_ZVFS_OPEN_MAX=10 CONFIG_REQUIRES_FULL_LIBC=y CONFIG_EVENTFD_MAX=10 CONFIG_NET_MAX_CONTEXTS=10 diff --git a/tests/net/lib/http_server/tls/prj.conf b/tests/net/lib/http_server/tls/prj.conf index 997a3b6426433..63af22cbdf6a1 100644 --- a/tests/net/lib/http_server/tls/prj.conf +++ b/tests/net/lib/http_server/tls/prj.conf @@ -37,9 +37,9 @@ CONFIG_NET_BUF_TX_COUNT=128 CONFIG_NET_BUF_RX_COUNT=128 CONFIG_NET_PKT_TX_COUNT=16 CONFIG_NET_PKT_RX_COUNT=16 -CONFIG_POSIX_MAX_FDS=32 +CONFIG_ZVFS_OPEN_MAX=32 CONFIG_NET_SOCKETS_POLL_MAX=32 -CONFIG_POSIX_MAX_FDS=32 +CONFIG_ZVFS_OPEN_MAX=32 CONFIG_REQUIRES_FULL_LIBC=y CONFIG_EVENTFD_MAX=10 CONFIG_NET_MAX_CONTEXTS=10 diff --git a/tests/net/pm/prj.conf b/tests/net/pm/prj.conf index 6008082186889..5d478e4d0700b 100644 --- a/tests/net/pm/prj.conf +++ b/tests/net/pm/prj.conf @@ -7,7 +7,7 @@ CONFIG_NET_L2_ETHERNET=n CONFIG_NET_UDP=y CONFIG_NET_IPV4=y CONFIG_NET_SOCKETS=y -CONFIG_POSIX_MAX_FDS=2 +CONFIG_ZVFS_OPEN_MAX=2 CONFIG_ZTEST_STACK_SIZE=2048 CONFIG_MAIN_STACK_SIZE=2048 CONFIG_NET_LOG=y diff --git a/tests/net/socket/af_packet/prj.conf b/tests/net/socket/af_packet/prj.conf index a0fd507497d42..2eeb220abdb50 100644 --- a/tests/net/socket/af_packet/prj.conf +++ b/tests/net/socket/af_packet/prj.conf @@ -6,7 +6,7 @@ CONFIG_NET_UDP=y CONFIG_NET_TCP=n CONFIG_NET_SOCKETS=y CONFIG_NET_SOCKETS_PACKET=y -CONFIG_POSIX_MAX_FDS=8 +CONFIG_ZVFS_OPEN_MAX=8 CONFIG_NET_IPV6_DAD=n CONFIG_NET_IPV6_MLD=n diff --git a/tests/net/socket/af_packet_ipproto_raw/prj.conf b/tests/net/socket/af_packet_ipproto_raw/prj.conf index 9edcaa6be842e..227851d398f2e 100644 --- a/tests/net/socket/af_packet_ipproto_raw/prj.conf +++ b/tests/net/socket/af_packet_ipproto_raw/prj.conf @@ -6,7 +6,7 @@ CONFIG_NET_UDP=n CONFIG_NET_TCP=n CONFIG_NET_SOCKETS=y CONFIG_NET_SOCKETS_PACKET=y -CONFIG_POSIX_MAX_FDS=8 +CONFIG_ZVFS_OPEN_MAX=8 CONFIG_NET_SOCKETS_LOG_LEVEL_DBG=y CONFIG_NET_CORE_LOG_LEVEL_DBG=y diff --git a/tests/net/socket/poll/prj.conf b/tests/net/socket/poll/prj.conf index b708020ef4335..4a404b96aea24 100644 --- a/tests/net/socket/poll/prj.conf +++ b/tests/net/socket/poll/prj.conf @@ -5,7 +5,7 @@ CONFIG_NET_IPV6=y CONFIG_NET_UDP=y CONFIG_NET_TCP=y CONFIG_NET_SOCKETS=y -CONFIG_POSIX_MAX_FDS=10 +CONFIG_ZVFS_OPEN_MAX=10 CONFIG_NET_PKT_TX_COUNT=8 CONFIG_NET_PKT_RX_COUNT=8 CONFIG_NET_MAX_CONN=5 diff --git a/tests/net/socket/reuseaddr_reuseport/prj.conf b/tests/net/socket/reuseaddr_reuseport/prj.conf index 1501ff0c1d8ea..f151d25130eb1 100644 --- a/tests/net/socket/reuseaddr_reuseport/prj.conf +++ b/tests/net/socket/reuseaddr_reuseport/prj.conf @@ -28,7 +28,7 @@ CONFIG_NET_CONTEXT_REUSEPORT=y CONFIG_NET_HOSTNAME_ENABLE=y CONFIG_NET_HOSTNAME="ztest_hostname" -CONFIG_POSIX_MAX_FDS=8 +CONFIG_ZVFS_OPEN_MAX=8 CONFIG_NET_MAX_CONN=10 CONFIG_NET_MAX_CONTEXTS=10 diff --git a/tests/net/socket/select/prj.conf b/tests/net/socket/select/prj.conf index 89918315d1151..53c0c5de3bf95 100644 --- a/tests/net/socket/select/prj.conf +++ b/tests/net/socket/select/prj.conf @@ -10,7 +10,7 @@ CONFIG_NET_IPV4=n CONFIG_NET_IPV6=y CONFIG_NET_SOCKETS=y # Defines fd_set size -CONFIG_POSIX_MAX_FDS=33 +CONFIG_ZVFS_OPEN_MAX=33 # Network driver config CONFIG_TEST_RANDOM_GENERATOR=y diff --git a/tests/net/socket/select/src/main.c b/tests/net/socket/select/src/main.c index aab52167c31b3..4a04bf67b04b9 100644 --- a/tests/net/socket/select/src/main.c +++ b/tests/net/socket/select/src/main.c @@ -34,7 +34,7 @@ ZTEST_USER(net_socket_select, test_fd_set) { zsock_fd_set set; - /* Relies on specific value of CONFIG_POSIX_MAX_FDS in prj.conf */ + /* Relies on specific value of CONFIG_ZVFS_OPEN_MAX in prj.conf */ zassert_equal(sizeof(set.bitset), sizeof(uint32_t) * 2, ""); ZSOCK_FD_ZERO(&set); diff --git a/tests/net/socket/service/prj.conf b/tests/net/socket/service/prj.conf index 5e51a0f6a53ee..5f5c2325a335b 100644 --- a/tests/net/socket/service/prj.conf +++ b/tests/net/socket/service/prj.conf @@ -5,7 +5,7 @@ CONFIG_NET_IPV6=y CONFIG_NET_UDP=y CONFIG_NET_TCP=y CONFIG_NET_SOCKETS=y -CONFIG_POSIX_MAX_FDS=10 +CONFIG_ZVFS_OPEN_MAX=10 CONFIG_NET_PKT_TX_COUNT=8 CONFIG_NET_PKT_RX_COUNT=8 CONFIG_NET_MAX_CONN=5 diff --git a/tests/net/socket/socketpair/prj.conf b/tests/net/socket/socketpair/prj.conf index fd15cb5309d88..314e999680620 100644 --- a/tests/net/socket/socketpair/prj.conf +++ b/tests/net/socket/socketpair/prj.conf @@ -7,7 +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 +CONFIG_ZVFS_OPEN_MAX=10 # Network driver config CONFIG_TEST_RANDOM_GENERATOR=y diff --git a/tests/net/socket/tcp/prj.conf b/tests/net/socket/tcp/prj.conf index ca331d3e20c88..71fc0e7d4b22c 100644 --- a/tests/net/socket/tcp/prj.conf +++ b/tests/net/socket/tcp/prj.conf @@ -11,7 +11,7 @@ CONFIG_NET_IPV6=y CONFIG_NET_IPV6_ND=n CONFIG_NET_TCP=y CONFIG_NET_SOCKETS=y -CONFIG_POSIX_MAX_FDS=10 +CONFIG_ZVFS_OPEN_MAX=10 # Network driver config CONFIG_NET_DRIVERS=y diff --git a/tests/net/socket/tcp/src/main.c b/tests/net/socket/tcp/src/main.c index 5ac3599ca1b20..643e8b5de0c27 100644 --- a/tests/net/socket/tcp/src/main.c +++ b/tests/net/socket/tcp/src/main.c @@ -2491,7 +2491,7 @@ static void after(void *arg) { ARG_UNUSED(arg); - for (int i = 0; i < CONFIG_POSIX_MAX_FDS; ++i) { + for (int i = 0; i < CONFIG_ZVFS_OPEN_MAX; ++i) { (void)zsock_close(i); } } diff --git a/tests/net/socket/tls/prj.conf b/tests/net/socket/tls/prj.conf index 514dc114925d5..ebbb19a1d9345 100644 --- a/tests/net/socket/tls/prj.conf +++ b/tests/net/socket/tls/prj.conf @@ -19,7 +19,7 @@ CONFIG_NET_SOCKETS_TLS_MAX_CONTEXTS=4 CONFIG_NET_CONTEXT_RCVTIMEO=y CONFIG_NET_CONTEXT_SNDTIMEO=y CONFIG_NET_CONTEXT_RCVBUF=y -CONFIG_POSIX_MAX_FDS=20 +CONFIG_ZVFS_OPEN_MAX=20 # Keep timings short for the test CONFIG_NET_TCP_TIME_WAIT_DELAY=10 diff --git a/tests/net/socket/tls_ext/prj.conf b/tests/net/socket/tls_ext/prj.conf index c8a18c17f76a1..02b53191a5888 100644 --- a/tests/net/socket/tls_ext/prj.conf +++ b/tests/net/socket/tls_ext/prj.conf @@ -29,7 +29,7 @@ CONFIG_NET_BUF_TX_COUNT=64 CONFIG_NET_PKT_TX_COUNT=64 CONFIG_NET_BUF_RX_COUNT=64 CONFIG_NET_PKT_RX_COUNT=64 -CONFIG_POSIX_MAX_FDS=10 +CONFIG_ZVFS_OPEN_MAX=10 # Stack sizes CONFIG_MAIN_STACK_SIZE=2048 diff --git a/tests/net/socket/udp/prj.conf b/tests/net/socket/udp/prj.conf index aed6c93088205..f90a1807c3d70 100644 --- a/tests/net/socket/udp/prj.conf +++ b/tests/net/socket/udp/prj.conf @@ -7,7 +7,7 @@ CONFIG_NET_IPV4=y CONFIG_NET_IPV6=y CONFIG_NET_UDP=y CONFIG_NET_SOCKETS=y -CONFIG_POSIX_MAX_FDS=10 +CONFIG_ZVFS_OPEN_MAX=10 CONFIG_NET_IF_UNICAST_IPV6_ADDR_COUNT=3 CONFIG_NET_IPV6_DAD=n CONFIG_NET_IPV6_MLD=n diff --git a/tests/net/socket/udp/src/main.c b/tests/net/socket/udp/src/main.c index 2f345df8b17dc..525fc502588d0 100644 --- a/tests/net/socket/udp/src/main.c +++ b/tests/net/socket/udp/src/main.c @@ -2532,7 +2532,7 @@ static void after(void *arg) { ARG_UNUSED(arg); - for (int i = 0; i < CONFIG_POSIX_MAX_FDS; ++i) { + for (int i = 0; i < CONFIG_ZVFS_OPEN_MAX; ++i) { (void)zsock_close(i); } } diff --git a/tests/posix/fs/src/test_fs_file.c b/tests/posix/fs/src/test_fs_file.c index cb015a41ddf75..9614412a07a58 100644 --- a/tests/posix/fs/src/test_fs_file.c +++ b/tests/posix/fs/src/test_fs_file.c @@ -290,7 +290,7 @@ ZTEST(posix_fs_file_test, test_fs_unlink) ZTEST(posix_fs_file_test, test_fs_fd_leak) { const int reps = - MAX(CONFIG_POSIX_MAX_OPEN_FILES, CONFIG_POSIX_MAX_FDS) + 5; + MAX(CONFIG_POSIX_OPEN_MAX, CONFIG_ZVFS_OPEN_MAX) + 5; for (int i = 0; i < reps; i++) { if (i > 0) { From b6396048331a4395922a23fc170b51e98be7002e Mon Sep 17 00:00:00 2001 From: Chris Friedt Date: Wed, 22 May 2024 16:51:41 -0400 Subject: [PATCH 1733/2849] posix: deprecate PTHREAD_BARRIER for POSIX_BARRIERS The standard specifies _POSIX_BARRIERS as an Option so let's use CONFIG_POSIX_BARRIERS for consistence. This change deprecates CONFIG_PTHREAD_BARRIER. Users should instead choose CONFIG_POSIX_BARRIERS. Signed-off-by: Chris Friedt --- .../portability/posix/conformance/index.rst | 2 +- .../portability/posix/kconfig/index.rst | 2 -- include/zephyr/posix/posix_features.h | 2 +- include/zephyr/posix/sys/sysconf.h | 2 +- lib/posix/options/CMakeLists.txt | 2 +- lib/posix/options/Kconfig.barrier | 31 ++++++++++++++----- lib/posix/options/Kconfig.deprecated | 9 ++++++ 7 files changed, 37 insertions(+), 13 deletions(-) diff --git a/doc/services/portability/posix/conformance/index.rst b/doc/services/portability/posix/conformance/index.rst index dffc1c5ec070f..3e2b945143805 100644 --- a/doc/services/portability/posix/conformance/index.rst +++ b/doc/services/portability/posix/conformance/index.rst @@ -62,7 +62,7 @@ POSIX System Interfaces _POSIX_VERSION, 200809L, :ref:`_POSIX_ASYNCHRONOUS_IO`, 200809L, :ref:`†` - :ref:`_POSIX_BARRIERS`, 200809L, :kconfig:option:`CONFIG_PTHREAD_BARRIER` + :ref:`_POSIX_BARRIERS`, 200809L, :kconfig:option:`CONFIG_POSIX_BARRIERS` :ref:`_POSIX_CLOCK_SELECTION`, 200809L, :kconfig:option:`CONFIG_POSIX_CLOCK_SELECTION` _POSIX_MAPPED_FILES, -1, :ref:`†` _POSIX_MEMORY_PROTECTION, -1, :ref:`†` diff --git a/doc/services/portability/posix/kconfig/index.rst b/doc/services/portability/posix/kconfig/index.rst index 58ef24943c6a6..e8d82d6b34596 100644 --- a/doc/services/portability/posix/kconfig/index.rst +++ b/doc/services/portability/posix/kconfig/index.rst @@ -12,7 +12,6 @@ implementation of the POSIX API. * :kconfig:option:`CONFIG_FNMATCH` * :kconfig:option:`CONFIG_GETOPT` * :kconfig:option:`CONFIG_GETOPT_LONG` -* :kconfig:option:`CONFIG_MAX_PTHREAD_BARRIER_COUNT` * :kconfig:option:`CONFIG_MAX_PTHREAD_COUNT` * :kconfig:option:`CONFIG_MAX_PTHREAD_KEY_COUNT` * :kconfig:option:`CONFIG_MAX_PTHREAD_MUTEX_COUNT` @@ -35,7 +34,6 @@ implementation of the POSIX API. * :kconfig:option:`CONFIG_POSIX_UNAME_NODENAME_LEN` * :kconfig:option:`CONFIG_POSIX_UNAME_VERSION_LEN` * :kconfig:option:`CONFIG_PTHREAD` -* :kconfig:option:`CONFIG_PTHREAD_BARRIER` * :kconfig:option:`CONFIG_PTHREAD_COND` * :kconfig:option:`CONFIG_PTHREAD_CREATE_BARRIER` * :kconfig:option:`CONFIG_PTHREAD_IPC` diff --git a/include/zephyr/posix/posix_features.h b/include/zephyr/posix/posix_features.h index da42000c7c81a..809f5143bdb68 100644 --- a/include/zephyr/posix/posix_features.h +++ b/include/zephyr/posix/posix_features.h @@ -27,7 +27,7 @@ #define _POSIX_ASYNCHRONOUS_IO _POSIX_VERSION #endif -#ifdef CONFIG_PTHREAD_BARRIER +#ifdef CONFIG_POSIX_BARRIERS #define _POSIX_BARRIERS _POSIX_VERSION #endif diff --git a/include/zephyr/posix/sys/sysconf.h b/include/zephyr/posix/sys/sysconf.h index 1732dfd0f181d..40e4e6a7b9bd5 100644 --- a/include/zephyr/posix/sys/sysconf.h +++ b/include/zephyr/posix/sys/sysconf.h @@ -144,7 +144,7 @@ enum { #define __z_posix_sysconf_SC_ADVISORY_INFO (-1L) #define __z_posix_sysconf_SC_ASYNCHRONOUS_IO \ COND_CODE_1(CONFIG_POSIX_ASYNCHRONOUS_IO, (_POSIX_ASYNCHRONOUS_IO), (-1L)) -#define __z_posix_sysconf_SC_BARRIERS COND_CODE_1(CONFIG_PTHREAD_BARRIER, (_POSIX_BARRIERS), (-1L)) +#define __z_posix_sysconf_SC_BARRIERS COND_CODE_1(CONFIG_POSIX_BARRIERS, (_POSIX_BARRIERS), (-1L)) #define __z_posix_sysconf_SC_CLOCK_SELECTION \ COND_CODE_1(CONFIG_POSIX_CLOCK_SELECTION, (_POSIX_CLOCK_SELECTION), (-1L)) #define __z_posix_sysconf_SC_CPUTIME \ diff --git a/lib/posix/options/CMakeLists.txt b/lib/posix/options/CMakeLists.txt index 40326acdadaf8..1bf0823752df5 100644 --- a/lib/posix/options/CMakeLists.txt +++ b/lib/posix/options/CMakeLists.txt @@ -38,6 +38,7 @@ zephyr_library_sources_ifdef(CONFIG_EVENTFD eventfd.c) zephyr_library_sources_ifdef(CONFIG_FNMATCH fnmatch.c) zephyr_library_sources_ifdef(CONFIG_GETENTROPY getentropy.c) zephyr_library_sources_ifdef(CONFIG_POSIX_ASYNCHRONOUS_IO aio.c) +zephyr_library_sources_ifdef(CONFIG_POSIX_BARRIERS barrier.c) zephyr_library_sources_ifdef(CONFIG_POSIX_CONFSTR confstr.c) zephyr_library_sources_ifdef(CONFIG_POSIX_DEVICE_IO # perror should be moved to the common libc @@ -64,7 +65,6 @@ zephyr_library_sources_ifdef(CONFIG_POSIX_TIMERS ) zephyr_library_sources_ifdef(CONFIG_POSIX_UNAME uname.c) zephyr_library_sources_ifdef(CONFIG_PTHREAD_IPC _common.c) -zephyr_library_sources_ifdef(CONFIG_PTHREAD_BARRIER barrier.c) zephyr_library_sources_ifdef(CONFIG_PTHREAD_COND cond.c) zephyr_library_sources_ifdef(CONFIG_PTHREAD_KEY key.c) zephyr_library_sources_ifdef(CONFIG_PTHREAD_MUTEX mutex.c) diff --git a/lib/posix/options/Kconfig.barrier b/lib/posix/options/Kconfig.barrier index 72dd814827759..1a6b2e46410d3 100644 --- a/lib/posix/options/Kconfig.barrier +++ b/lib/posix/options/Kconfig.barrier @@ -1,17 +1,30 @@ # Copyright (c) 2017 Intel Corporation # Copyright (c) 2023 Meta +# Copyright (c) 2024 Tenstorrent # # SPDX-License-Identifier: Apache-2.0 -TYPE = PTHREAD_BARRIER -type = pthread_barrier_t -type-function = pthread_barrier_wait -rsource "Kconfig.template.pooled_ipc_type" +menuconfig POSIX_BARRIERS + bool "POSIX barriers" + default y if POSIX_API + help + Select 'y' here to enable POSIX barriers. + + For more information please see + https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_subprofiles.html + +if POSIX_BARRIERS -if PTHREAD_BARRIER +config MAX_PTHREAD_BARRIER_COUNT + int "Maximum number of POSIX barriers" + default 5 + help + Maximum simultaneously active pthread_barrier_t in a POSIX application. + + Note: this is a non-standard option. config PTHREAD_CREATE_BARRIER - bool "Use a pthread_barrier_t to serialize pthread_create()" + bool "Use a POSIX barrier to serialize pthread_create()" help When running several SMP applications in parallel instances of Qemu, e.g. via twister, explicit serialization may be required between @@ -21,4 +34,8 @@ config PTHREAD_CREATE_BARRIER On such systems, say Y here to introduce explicit serialization via pthread_barrier_wait(). -endif +module = PTHREAD_BARRIER +module-str = POSIX thread barriers +source "subsys/logging/Kconfig.template.log_config" + +endif # POSIX_BARRIERS diff --git a/lib/posix/options/Kconfig.deprecated b/lib/posix/options/Kconfig.deprecated index ab76a8b891f2c..8da2f0e21addc 100644 --- a/lib/posix/options/Kconfig.deprecated +++ b/lib/posix/options/Kconfig.deprecated @@ -57,6 +57,15 @@ config POSIX_MAX_OPEN_FILES See also CONFIG_ZVFS_OPEN_MAX. +config PTHREAD_BARRIER + bool "pthread_barrier_t support [DEPRECATED]" + select DEPRECATED + select POSIX_BARRIERS + help + This option is deprecated. + + Please use CONFIG_POSIX_BARRIERS instead. + config TIMER bool "Timer support [DEPRECATED]" select DEPRECATED From 2fe9d6cd68c38dfc21bb7414ce173e42fd2e4477 Mon Sep 17 00:00:00 2001 From: Chris Friedt Date: Wed, 22 May 2024 18:04:35 -0400 Subject: [PATCH 1734/2849] posix: deprecate POSIX_ENV _CONFSTR _SYSCONF and _UNAME This change deprecates the following Kconfig options * CONFIG_POSIX_ENV * CONFIG_POSIX_CONFSTR * CONFIG_POSIX_SYSCONF * CONFIG_POSIX_UNAME and instead groups them into a single Kconfig option that maps directly to the standard. Namely, CONFIG_POSIX_SINGLE_PROCESS. Signed-off-by: Chris Friedt --- doc/services/portability/posix/aep/index.rst | 2 +- .../portability/posix/kconfig/index.rst | 1 - include/zephyr/posix/sys/utsname.h | 12 +++- lib/posix/options/CMakeLists.txt | 13 +++-- lib/posix/options/Kconfig | 6 +- lib/posix/options/Kconfig.confstr | 9 --- lib/posix/options/Kconfig.deprecated | 36 ++++++++++++ lib/posix/options/Kconfig.env | 14 ----- lib/posix/options/Kconfig.mem | 13 +++++ lib/posix/options/Kconfig.proc1 | 57 +++++++++++++++++++ lib/posix/options/Kconfig.sysconf | 48 ---------------- lib/posix/options/Kconfig.uname | 26 --------- lib/posix/options/Kconfig.xsi | 5 +- lib/posix/shell/Kconfig.env | 2 +- lib/posix/shell/Kconfig.uname | 4 +- tests/posix/env/prj.conf | 2 +- 16 files changed, 133 insertions(+), 117 deletions(-) delete mode 100644 lib/posix/options/Kconfig.confstr delete mode 100644 lib/posix/options/Kconfig.env create mode 100644 lib/posix/options/Kconfig.mem create mode 100644 lib/posix/options/Kconfig.proc1 delete mode 100644 lib/posix/options/Kconfig.sysconf delete mode 100644 lib/posix/options/Kconfig.uname diff --git a/doc/services/portability/posix/aep/index.rst b/doc/services/portability/posix/aep/index.rst index d6cbeb9447f8c..b720520ebd952 100644 --- a/doc/services/portability/posix/aep/index.rst +++ b/doc/services/portability/posix/aep/index.rst @@ -52,7 +52,7 @@ The *Minimal Realtime System Profile* (PSE51) includes all of the :ref:`POSIX_C_LANG_SUPPORT `, yes, :ref:`POSIX_DEVICE_IO `,, :kconfig:option:`CONFIG_POSIX_DEVICE_IO` :ref:`POSIX_SIGNALS `,, - :ref:`POSIX_SINGLE_PROCESS `, yes, + :ref:`POSIX_SINGLE_PROCESS `, yes, :kconfig:option:`CONFIG_POSIX_SINGLE_PROCESS` :ref:`POSIX_THREADS_BASE `, yes, :ref:`XSI_THREADS_EXT `, yes, diff --git a/doc/services/portability/posix/kconfig/index.rst b/doc/services/portability/posix/kconfig/index.rst index e8d82d6b34596..d04779aa96c2f 100644 --- a/doc/services/portability/posix/kconfig/index.rst +++ b/doc/services/portability/posix/kconfig/index.rst @@ -30,7 +30,6 @@ implementation of the POSIX API. * :kconfig:option:`CONFIG_POSIX_RTSIG_MAX` * :kconfig:option:`CONFIG_POSIX_SIGNAL` * :kconfig:option:`CONFIG_POSIX_SIGNAL_STRING_DESC` -* :kconfig:option:`CONFIG_POSIX_UNAME` * :kconfig:option:`CONFIG_POSIX_UNAME_NODENAME_LEN` * :kconfig:option:`CONFIG_POSIX_UNAME_VERSION_LEN` * :kconfig:option:`CONFIG_PTHREAD` diff --git a/include/zephyr/posix/sys/utsname.h b/include/zephyr/posix/sys/utsname.h index 32046f431d89d..542215076a400 100644 --- a/include/zephyr/posix/sys/utsname.h +++ b/include/zephyr/posix/sys/utsname.h @@ -6,15 +6,23 @@ #ifndef ZEPHYR_INCLUDE_POSIX_SYS_UTSNAME_H_ #define ZEPHYR_INCLUDE_POSIX_SYS_UTSNAME_H_ +#include + #ifdef __cplusplus extern "C" { #endif +/* These are for compatibility / practicality */ +#define _UTSNAME_NODENAME_LENGTH \ + COND_CODE_1(CONFIG_POSIX_SINGLE_PROCESS, (CONFIG_POSIX_UNAME_VERSION_LEN), (0)) +#define _UTSNAME_VERSION_LENGTH \ + COND_CODE_1(CONFIG_POSIX_SINGLE_PROCESS, (CONFIG_POSIX_UNAME_VERSION_LEN), (0)) + struct utsname { char sysname[sizeof("Zephyr")]; - char nodename[CONFIG_POSIX_UNAME_NODENAME_LEN + 1]; + char nodename[_UTSNAME_NODENAME_LENGTH + 1]; char release[sizeof("99.99.99-rc1")]; - char version[CONFIG_POSIX_UNAME_VERSION_LEN + 1]; + char version[_UTSNAME_VERSION_LENGTH + 1]; char machine[sizeof(CONFIG_ARCH)]; }; diff --git a/lib/posix/options/CMakeLists.txt b/lib/posix/options/CMakeLists.txt index 1bf0823752df5..509f1d3c0e1a2 100644 --- a/lib/posix/options/CMakeLists.txt +++ b/lib/posix/options/CMakeLists.txt @@ -25,7 +25,8 @@ if(CONFIG_POSIX_SIGNAL) endif() if(CONFIG_POSIX_API OR CONFIG_PTHREAD_IPC OR CONFIG_POSIX_TIMERS OR - CONFIG_POSIX_MQUEUE OR CONFIG_POSIX_FS OR CONFIG_EVENTFD OR CONFIG_GETOPT) + CONFIG_POSIX_MQUEUE OR CONFIG_POSIX_FS OR CONFIG_EVENTFD OR CONFIG_GETOPT OR + CONFIG_POSIX_SINGLE_PROCESS) # This is a temporary workaround so that Newlib declares the appropriate # types for us. POSIX features to be formalized as part of #51211 zephyr_compile_options($<$:-D_POSIX_THREADS>) @@ -39,13 +40,11 @@ zephyr_library_sources_ifdef(CONFIG_FNMATCH fnmatch.c) zephyr_library_sources_ifdef(CONFIG_GETENTROPY getentropy.c) zephyr_library_sources_ifdef(CONFIG_POSIX_ASYNCHRONOUS_IO aio.c) zephyr_library_sources_ifdef(CONFIG_POSIX_BARRIERS barrier.c) -zephyr_library_sources_ifdef(CONFIG_POSIX_CONFSTR confstr.c) zephyr_library_sources_ifdef(CONFIG_POSIX_DEVICE_IO # perror should be moved to the common libc perror.c device_io.c ) -zephyr_library_sources_ifdef(CONFIG_POSIX_ENV env.c) zephyr_library_sources_ifdef(CONFIG_POSIX_FD_MGMT fd_mgmt.c ) @@ -57,13 +56,17 @@ zephyr_library_sources_ifdef(CONFIG_POSIX_MULTI_PROCESS zephyr_library_sources_ifdef(CONFIG_POSIX_NETWORKING net.c) zephyr_library_sources_ifdef(CONFIG_POSIX_PUTMSG stropts.c) zephyr_library_sources_ifdef(CONFIG_POSIX_SIGNAL signal.c ${STRSIGNAL_TABLE_H}) -zephyr_library_sources_ifdef(CONFIG_POSIX_SYSCONF_IMPL_FULL sysconf.c) +zephyr_library_sources_ifdef(CONFIG_POSIX_SINGLE_PROCESS + confstr.c + env.c + sysconf.c + uname.c +) zephyr_library_sources_ifdef(CONFIG_POSIX_SYSLOG syslog.c) zephyr_library_sources_ifdef(CONFIG_POSIX_TIMERS clock.c timer.c ) -zephyr_library_sources_ifdef(CONFIG_POSIX_UNAME uname.c) zephyr_library_sources_ifdef(CONFIG_PTHREAD_IPC _common.c) zephyr_library_sources_ifdef(CONFIG_PTHREAD_COND cond.c) zephyr_library_sources_ifdef(CONFIG_PTHREAD_KEY key.c) diff --git a/lib/posix/options/Kconfig b/lib/posix/options/Kconfig index 85631445f1273..da9b00b9a84c0 100644 --- a/lib/posix/options/Kconfig +++ b/lib/posix/options/Kconfig @@ -26,9 +26,7 @@ config PTHREAD_IPC rsource "Kconfig.aio" rsource "Kconfig.barrier" rsource "Kconfig.cond" -rsource "Kconfig.confstr" rsource "Kconfig.device_io" -rsource "Kconfig.env" rsource "Kconfig.eventfd" rsource "Kconfig.fd_mgmt" rsource "Kconfig.fnmatch" @@ -36,9 +34,11 @@ rsource "Kconfig.fs" rsource "Kconfig.getentropy" rsource "Kconfig.getopt" rsource "Kconfig.key" +rsource "Kconfig.mem" rsource "Kconfig.mqueue" rsource "Kconfig.mutex" rsource "Kconfig.net" +rsource "Kconfig.proc1" rsource "Kconfig.procN" rsource "Kconfig.pthread" rsource "Kconfig.rwlock" @@ -47,10 +47,8 @@ rsource "Kconfig.semaphore" rsource "Kconfig.signal" rsource "Kconfig.spinlock" rsource "Kconfig.stropts" -rsource "Kconfig.sysconf" rsource "Kconfig.syslog" rsource "Kconfig.timer" -rsource "Kconfig.uname" rsource "Kconfig.xsi" rsource "Kconfig.deprecated" diff --git a/lib/posix/options/Kconfig.confstr b/lib/posix/options/Kconfig.confstr deleted file mode 100644 index 154f14f2d5251..0000000000000 --- a/lib/posix/options/Kconfig.confstr +++ /dev/null @@ -1,9 +0,0 @@ -# Copyright (c) 2024, Meta -# -# SPDX-License-Identifier: Apache-2.0 - -config POSIX_CONFSTR - bool "Retrieve string system configuration" - default y if POSIX_API - help - This enables the POSIX confstr() function. diff --git a/lib/posix/options/Kconfig.deprecated b/lib/posix/options/Kconfig.deprecated index 8da2f0e21addc..ecac0365d6ca1 100644 --- a/lib/posix/options/Kconfig.deprecated +++ b/lib/posix/options/Kconfig.deprecated @@ -28,6 +28,24 @@ config POSIX_CLOCK Please use CONFIG_POSIX_TIMERS instead. +config POSIX_CONFSTR + bool "Retrieve string system configuration [DEPRECATED]" + select DEPRECATED + select POSIX_SINGLE_PROCESS + help + This option is deprecated. + + Please use CONFIG_POSIX_SINGLE_PROCESS instead. + +config POSIX_ENV + bool "Support for environ, getenv(), getenv_r(), setenv(), and unsetenv() [DEPRECATED]" + select DEPRECATED + select POSIX_SINGLE_PROCESS + help + This option is deprecated. + + Please use CONFIG_POSIX_SINGLE_PROCESS instead. + config POSIX_LIMITS_RTSIG_MAX int "_POSIX_RTSIG_MAX value in limits.h [DEPRECATED]" default POSIX_RTSIG_MAX if POSIX_REALTIME_SIGNALS @@ -57,6 +75,24 @@ config POSIX_MAX_OPEN_FILES See also CONFIG_ZVFS_OPEN_MAX. +config POSIX_SYSCONF + bool "Support for sysconf() [DEPRECATED]" + select DEPRECATED + select POSIX_SINGLE_PROCESS + help + This option is deprecated. + + Please use CONFIG_POSIX_SINGLE_PROCESS instead. + +config POSIX_UNAME + bool "Support for uname [DEPRECATED]" + select DEPRECATED + select POSIX_SINGLE_PROCESS + help + This option is deprecated. + + Please use CONFIG_POSIX_SINGLE_PROCESS instead. + config PTHREAD_BARRIER bool "pthread_barrier_t support [DEPRECATED]" select DEPRECATED diff --git a/lib/posix/options/Kconfig.env b/lib/posix/options/Kconfig.env deleted file mode 100644 index 222392d273719..0000000000000 --- a/lib/posix/options/Kconfig.env +++ /dev/null @@ -1,14 +0,0 @@ -# Copyright (c) 2023, Meta -# -# SPDX-License-Identifier: Apache-2.0 - -config POSIX_ENV - bool "Support for environ, getenv(), getenv_r(), setenv(), and unsetenv()" - depends on COMMON_LIBC_MALLOC - default y if POSIX_API - help - Select this option to add support for environment variables. - -module = POSIX_ENV -module-str = POSIX env logging -source "subsys/logging/Kconfig.template.log_config" diff --git a/lib/posix/options/Kconfig.mem b/lib/posix/options/Kconfig.mem new file mode 100644 index 0000000000000..ad3f0a94ec2d4 --- /dev/null +++ b/lib/posix/options/Kconfig.mem @@ -0,0 +1,13 @@ +# Copyright (c) 2024 BayLibre SAS +# +# SPDX-License-Identifier: Apache-2.0 + +config POSIX_PAGE_SIZE_BITS + int "Number of bits to use for PAGE_SIZE" + range 6 16 + default 12 if POSIX_API + default 6 + help + Define PAGE_SIZE as BIT(n), where n is the value configured here. + PAGE_SIZE is supported in the range [64, 65536] + If CONFIG_POSIX_API=y, PAGE_SIZE defaults to 4096, otherwise, it is 64 bytes. diff --git a/lib/posix/options/Kconfig.proc1 b/lib/posix/options/Kconfig.proc1 new file mode 100644 index 0000000000000..ecdcec802e25e --- /dev/null +++ b/lib/posix/options/Kconfig.proc1 @@ -0,0 +1,57 @@ +# Copyright (c) 2023 Meta +# Copyright (c) 2024 BayLibre SAS +# Copyright (c) 2024 Tenstorrent AI ULC +# +# SPDX-License-Identifier: Apache-2.0 + +menuconfig POSIX_SINGLE_PROCESS + bool "POSIX single process support" + default y if POSIX_API + # imply COMMON_LIBC_MALLOC # for env.c + help + Select 'y' here to use confstr(), environ, errno, getenv(), setenv(), sysconf(), uname(), + or unsetenv(). + + For more information, please see + https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_subprofiles.html + +if POSIX_SINGLE_PROCESS + +choice POSIX_SYSCONF_IMPL_CHOICE + default POSIX_SYSCONF_IMPL_FULL if CPP + default POSIX_SYSCONF_IMPL_MACRO + prompt "Sysconf implementation method" + +config POSIX_SYSCONF_IMPL_MACRO + bool "Macro" + help + The sysconf() function is implemented compile-time constant via macros. This is the option + with the least overhead. The downside is that sysconf() is not an addressable function. + +config POSIX_SYSCONF_IMPL_FULL + bool "Full" + help + The sysconf() function is implemented as a large integer-integer array. The advantage if this + option is that all sysconf() options can be queried and that the sysconf() symbol is + addressable. + +endchoice + +config POSIX_UNAME_VERSION_LEN + int "uname version string length" + default 70 + help + Defines the maximum string length of uname version. + +config POSIX_UNAME_NODENAME_LEN + int "uname nodename string length" + default 6 if !NET_HOSTNAME_UNIQUE + default 22 if NET_HOSTNAME_UNIQUE + help + Defines the maximum string length of nodename version. + +module = POSIX_ENV +module-str = POSIX env logging +source "subsys/logging/Kconfig.template.log_config" + +endif # POSIX_SINGLE_PROCESS diff --git a/lib/posix/options/Kconfig.sysconf b/lib/posix/options/Kconfig.sysconf deleted file mode 100644 index 7e904d5b6722f..0000000000000 --- a/lib/posix/options/Kconfig.sysconf +++ /dev/null @@ -1,48 +0,0 @@ -# Copyright (c) 2024 BayLibre SAS -# -# SPDX-License-Identifier: Apache-2.0 - -menu "Sysconf support" - -config POSIX_SYSCONF - bool "Support for sysconf" - default y if POSIX_API - help - The sysconf() function provides a method for the application to determine - the current value of a configurable system limit or option (variable). - -config POSIX_PAGE_SIZE_BITS - int "Number of bits to use for PAGE_SIZE" - range 6 16 - default 12 if POSIX_API - default 6 - help - Define PAGE_SIZE as BIT(n), where n is the value configured here. - PAGE_SIZE is supported in the range [64, 65536] - If CONFIG_POSIX_API=y, PAGE_SIZE defaults to 4096, otherwise, it is 64 bytes. - -if POSIX_SYSCONF - -choice POSIX_SYSCONF_IMPL_CHOICE - default POSIX_SYSCONF_IMPL_FULL if CPP - default POSIX_SYSCONF_IMPL_MACRO - prompt "Sysconf implementation method" - -config POSIX_SYSCONF_IMPL_MACRO - bool "Macro" - help - The sysconf() function is implemented compile-time constant via macros. This is the option - with the least overhead. The downside is that sysconf() is not an addressable function. - -config POSIX_SYSCONF_IMPL_FULL - bool "Full" - help - The sysconf() function is implemented as a large integer-integer array. The advantage if this - option is that all sysconf() options can be queried and that the sysconf() symbol is - addressable. - -endchoice - -endif # POSIX_SYSCONF - -endmenu # "Sysconf support" diff --git a/lib/posix/options/Kconfig.uname b/lib/posix/options/Kconfig.uname deleted file mode 100644 index 8b4482252492d..0000000000000 --- a/lib/posix/options/Kconfig.uname +++ /dev/null @@ -1,26 +0,0 @@ -# Copyright (c) 2023 Meta -# -# SPDX-License-Identifier: Apache-2.0 - -menuconfig POSIX_UNAME - bool "Support for uname" - default y if POSIX_API - help - The uname() function shall store information identifying the current - system in the structure pointed to by name. - -if POSIX_UNAME -config POSIX_UNAME_VERSION_LEN - int "uname version string length" - default 70 - help - Defines the maximum string length of uname version. - -config POSIX_UNAME_NODENAME_LEN - int "uname nodename string length" - default 6 if !NET_HOSTNAME_UNIQUE - default 22 if NET_HOSTNAME_UNIQUE - help - Defines the maximum string length of nodename version. - -endif # POSIX_UNAME diff --git a/lib/posix/options/Kconfig.xsi b/lib/posix/options/Kconfig.xsi index 6cc2bf58509e0..5124e9eb8c781 100644 --- a/lib/posix/options/Kconfig.xsi +++ b/lib/posix/options/Kconfig.xsi @@ -5,9 +5,8 @@ config XSI_SINGLE_PROCESS bool "X/Open single process" default y if POSIX_API - depends on POSIX_ENV - depends on POSIX_UNAME - depends on POSIX_CLOCK_SELECTION + depends on POSIX_SINGLE_PROCESS + depends on POSIX_TIMERS help Select 'y' here and Zephyr will provide implementations of gethostid(), gettimeofday(), and putenv(). diff --git a/lib/posix/shell/Kconfig.env b/lib/posix/shell/Kconfig.env index d2d5fd53b3e97..bbe36bc9cbbb2 100644 --- a/lib/posix/shell/Kconfig.env +++ b/lib/posix/shell/Kconfig.env @@ -3,7 +3,7 @@ config POSIX_ENV_SHELL bool "Support for shell" - select POSIX_ENV + select POSIX_SINGLE_PROCESS select POSIX_SHELL help This shell provides access to system environment variables. diff --git a/lib/posix/shell/Kconfig.uname b/lib/posix/shell/Kconfig.uname index 11ea1166433a8..73547e3ac84b6 100644 --- a/lib/posix/shell/Kconfig.uname +++ b/lib/posix/shell/Kconfig.uname @@ -1,7 +1,7 @@ # Copyright (c) 2024 Meta # SPDX-License-Identifier: Apache-2.0 -if POSIX_UNAME +if POSIX_SINGLE_PROCESS config POSIX_UNAME_SHELL bool "Support for `uname` command" @@ -10,4 +10,4 @@ config POSIX_UNAME_SHELL help Support for `uname` command in the terminal. -endif # POSIX_UNAME +endif # POSIX_SINGLE_PROCESS diff --git a/tests/posix/env/prj.conf b/tests/posix/env/prj.conf index 7529d301e2ed1..fcf68903a7222 100644 --- a/tests/posix/env/prj.conf +++ b/tests/posix/env/prj.conf @@ -1,5 +1,5 @@ CONFIG_ZTEST=y -CONFIG_POSIX_ENV=y +CONFIG_POSIX_SINGLE_PROCESS=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 From 4e181f70312e8682e222d1e9033316ad91772cfe Mon Sep 17 00:00:00 2001 From: Chris Friedt Date: Wed, 22 May 2024 18:16:30 -0400 Subject: [PATCH 1735/2849] posix: deprecate PTHREAD_SPINLOCK for POSIX_SPIN_LOCKS This change deprecates CONFIG_PTHREAD_SPINLOCK in favour of CONFIG_POSIX_SPIN_LOCKS, which maps directly to the name of the standard POSIX Option Group. Signed-off-by: Chris Friedt --- .../portability/posix/conformance/index.rst | 2 +- .../portability/posix/kconfig/index.rst | 1 - include/zephyr/posix/posix_features.h | 2 +- include/zephyr/posix/sys/sysconf.h | 2 +- lib/posix/options/CMakeLists.txt | 2 +- lib/posix/options/Kconfig.deprecated | 9 ++++++ lib/posix/options/Kconfig.spinlock | 28 ++++++++++++++++--- 7 files changed, 37 insertions(+), 9 deletions(-) diff --git a/doc/services/portability/posix/conformance/index.rst b/doc/services/portability/posix/conformance/index.rst index 3e2b945143805..e82565ae83c2b 100644 --- a/doc/services/portability/posix/conformance/index.rst +++ b/doc/services/portability/posix/conformance/index.rst @@ -69,7 +69,7 @@ POSIX System Interfaces :ref:`_POSIX_READER_WRITER_LOCKS`, 200809L, :kconfig:option:`CONFIG_PTHREAD_IPC` :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_SPIN_LOCKS`, 200809L, :kconfig:option:`CONFIG_POSIX_SPIN_LOCKS` :ref:`_POSIX_THREAD_SAFE_FUNCTIONS`, -1, :ref:`_POSIX_THREADS`, -1, :kconfig:option:`CONFIG_PTHREAD_IPC` :ref:`_POSIX_TIMEOUTS`, 200809L, :kconfig:option:`CONFIG_POSIX_TIMEOUTS` diff --git a/doc/services/portability/posix/kconfig/index.rst b/doc/services/portability/posix/kconfig/index.rst index d04779aa96c2f..8adc0a4058ee0 100644 --- a/doc/services/portability/posix/kconfig/index.rst +++ b/doc/services/portability/posix/kconfig/index.rst @@ -39,6 +39,5 @@ implementation of the POSIX API. * :kconfig:option:`CONFIG_PTHREAD_KEY` * :kconfig:option:`CONFIG_PTHREAD_MUTEX` * :kconfig:option:`CONFIG_PTHREAD_RECYCLER_DELAY_MS` -* :kconfig:option:`CONFIG_PTHREAD_SPINLOCK` * :kconfig:option:`CONFIG_SEM_VALUE_MAX` * :kconfig:option:`CONFIG_TIMER_CREATE_WAIT` diff --git a/include/zephyr/posix/posix_features.h b/include/zephyr/posix/posix_features.h index 809f5143bdb68..75bb0c0efebc2 100644 --- a/include/zephyr/posix/posix_features.h +++ b/include/zephyr/posix/posix_features.h @@ -87,7 +87,7 @@ /* #define _POSIX_SHELL (-1L) */ /* #define _POSIX_SPAWN (-1L) */ -#ifdef CONFIG_PTHREAD_SPINLOCK +#ifdef CONFIG_POSIX_SPIN_LOCKS #define _POSIX_SPIN_LOCKS _POSIX_VERSION #endif diff --git a/include/zephyr/posix/sys/sysconf.h b/include/zephyr/posix/sys/sysconf.h index 40e4e6a7b9bd5..dcd4eb279226f 100644 --- a/include/zephyr/posix/sys/sysconf.h +++ b/include/zephyr/posix/sys/sysconf.h @@ -178,7 +178,7 @@ enum { #define __z_posix_sysconf_SC_SHELL (-1L) #define __z_posix_sysconf_SC_SPAWN (-1L) #define __z_posix_sysconf_SC_SPIN_LOCKS \ - COND_CODE_1(CONFIG_PTHREAD_SPINLOCK, (_POSIX_SPIN_LOCKS), (-1L)) + COND_CODE_1(CONFIG_POSIX_SPIN_LOCKS, (_POSIX_SPIN_LOCKS), (-1L)) #define __z_posix_sysconf_SC_SPORADIC_SERVER (-1L) #define __z_posix_sysconf_SC_SS_REPL_MAX _POSIX_SS_REPL_MAX #define __z_posix_sysconf_SC_SYNCHRONIZED_IO (-1L) diff --git a/lib/posix/options/CMakeLists.txt b/lib/posix/options/CMakeLists.txt index 509f1d3c0e1a2..02c8c30dd74ab 100644 --- a/lib/posix/options/CMakeLists.txt +++ b/lib/posix/options/CMakeLists.txt @@ -62,6 +62,7 @@ zephyr_library_sources_ifdef(CONFIG_POSIX_SINGLE_PROCESS sysconf.c uname.c ) +zephyr_library_sources_ifdef(CONFIG_POSIX_SPIN_LOCKS spinlock.c) zephyr_library_sources_ifdef(CONFIG_POSIX_SYSLOG syslog.c) zephyr_library_sources_ifdef(CONFIG_POSIX_TIMERS clock.c @@ -75,7 +76,6 @@ zephyr_library_sources_ifdef(CONFIG_PTHREAD pthread.c) zephyr_library_sources_ifdef(CONFIG_PTHREAD_RWLOCK rwlock.c) zephyr_library_sources_ifdef(CONFIG_POSIX_PRIORITY_SCHEDULING sched.c) zephyr_library_sources_ifdef(CONFIG_PTHREAD_IPC semaphore.c) -zephyr_library_sources_ifdef(CONFIG_PTHREAD_SPINLOCK spinlock.c) zephyr_library_include_directories( ${ZEPHYR_BASE}/kernel/include diff --git a/lib/posix/options/Kconfig.deprecated b/lib/posix/options/Kconfig.deprecated index ecac0365d6ca1..203b8463bd77e 100644 --- a/lib/posix/options/Kconfig.deprecated +++ b/lib/posix/options/Kconfig.deprecated @@ -102,6 +102,15 @@ config PTHREAD_BARRIER Please use CONFIG_POSIX_BARRIERS instead. +config PTHREAD_SPINLOCK + bool "pthread_spinlock_t support [DEPRECATED]" + select DEPRECATED + select POSIX_SPIN_LOCKS + help + This option is deprecated. + + Please use CONFIG_POSIX_SPIN_LOCKS instead. + config TIMER bool "Timer support [DEPRECATED]" select DEPRECATED diff --git a/lib/posix/options/Kconfig.spinlock b/lib/posix/options/Kconfig.spinlock index 8374aadfd6dd6..d5eb4a7028ae8 100644 --- a/lib/posix/options/Kconfig.spinlock +++ b/lib/posix/options/Kconfig.spinlock @@ -2,7 +2,27 @@ # # SPDX-License-Identifier: Apache-2.0 -TYPE = PTHREAD_SPINLOCK -type = pthread_spinlock_t -type-function = pthread_spin_lock -rsource "Kconfig.template.pooled_ipc_type" +menuconfig POSIX_SPIN_LOCKS + bool "POSIX spin locks" + default y if POSIX_API + help + Select 'y' here to enable POSIX spin locks. + + For more information please see + https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_subprofiles.html + +if POSIX_SPIN_LOCKS + +config MAX_PTHREAD_SPINLOCK_COUNT + int "Maximum number of POSIX spin locks" + default 5 + help + Maximum simultaneously active spin locks in a POSIX application. + + Note: this is a non-standard option. + +module = PTHREAD_SPINLOCK +module-str = POSIX Spin Locks +source "subsys/logging/Kconfig.template.log_config" + +endif # POSIX_SPIN_LOCKS From f270de7362ae95120f53d2a777b003232d48f678 Mon Sep 17 00:00:00 2001 From: Chris Friedt Date: Wed, 22 May 2024 18:33:38 -0400 Subject: [PATCH 1736/2849] posix: deprecate POSIX_MQUEUE in favour of POSIX_MESSAGE_PASSING This change deprecates CONFIG_POSIX_MQUEUE in favour of CONFIG_POSIX_MESSAGE_PASSING, which maps directly to the name of the standard POSIX Option. Signed-off-by: Chris Friedt --- doc/services/portability/posix/aep/index.rst | 2 +- .../portability/posix/conformance/index.rst | 2 +- .../portability/posix/kconfig/index.rst | 3 +-- include/zephyr/posix/mqueue.h | 6 ++--- include/zephyr/posix/posix_features.h | 4 ++-- include/zephyr/posix/sys/sysconf.h | 2 +- lib/posix/options/CMakeLists.txt | 4 ++-- lib/posix/options/Kconfig.deprecated | 18 +++++++++++++++ lib/posix/options/Kconfig.mqueue | 22 ++++++++++++------- lib/posix/options/mqueue.c | 2 +- tests/posix/common/prj.conf | 2 +- tests/posix/headers/prj.conf | 2 +- 12 files changed, 46 insertions(+), 23 deletions(-) diff --git a/doc/services/portability/posix/aep/index.rst b/doc/services/portability/posix/aep/index.rst index b720520ebd952..ad02c3e4cb8b1 100644 --- a/doc/services/portability/posix/aep/index.rst +++ b/doc/services/portability/posix/aep/index.rst @@ -109,7 +109,7 @@ The *Realtime Controller System Profile* (PSE52) includes all features from PSE5 :header: Symbol, Support, Remarks :widths: 50, 10, 50 - :ref:`_POSIX_MESSAGE_PASSING `, 200809L, :kconfig:option:`CONFIG_POSIX_MQUEUE` + :ref:`_POSIX_MESSAGE_PASSING `, 200809L, :kconfig:option:`CONFIG_POSIX_MESSAGE_PASSING` _POSIX_TRACE, -1, _POSIX_TRACE_EVENT_FILTER, -1, _POSIX_TRACE_LOG, -1, diff --git a/doc/services/portability/posix/conformance/index.rst b/doc/services/portability/posix/conformance/index.rst index e82565ae83c2b..b4baa41262dbc 100644 --- a/doc/services/portability/posix/conformance/index.rst +++ b/doc/services/portability/posix/conformance/index.rst @@ -86,7 +86,7 @@ POSIX System Interfaces _POSIX_IPV6, 200809L, :kconfig:option:`CONFIG_NET_IPV6` _POSIX_MEMLOCK, -1, _POSIX_MEMLOCK_RANGE, -1, - :ref:`_POSIX_MESSAGE_PASSING`, 200809L, :kconfig:option:`CONFIG_POSIX_MQUEUE` + :ref:`_POSIX_MESSAGE_PASSING`, 200809L, :kconfig:option:`CONFIG_POSIX_MESSAGE_PASSING` :ref:`_POSIX_MONOTONIC_CLOCK`, 200809L, :kconfig:option:`CONFIG_POSIX_MONOTONIC_CLOCK` _POSIX_PRIORITIZED_IO, -1, :ref:`_POSIX_PRIORITY_SCHEDULING`, 200809L, :kconfig:option:`CONFIG_POSIX_PRIORITY_SCHEDULING` diff --git a/doc/services/portability/posix/kconfig/index.rst b/doc/services/portability/posix/kconfig/index.rst index 8adc0a4058ee0..51dc795115e08 100644 --- a/doc/services/portability/posix/kconfig/index.rst +++ b/doc/services/portability/posix/kconfig/index.rst @@ -17,7 +17,7 @@ implementation of the POSIX API. * :kconfig:option:`CONFIG_MAX_PTHREAD_MUTEX_COUNT` * :kconfig:option:`CONFIG_MAX_PTHREAD_SPINLOCK_COUNT` * :kconfig:option:`CONFIG_MQUEUE_NAMELEN_MAX` -* :kconfig:option:`CONFIG_MSG_COUNT_MAX` +* :kconfig:option:`CONFIG_POSIX_MQ_OPEN_MAX` * :kconfig:option:`CONFIG_MSG_SIZE_MAX` * :kconfig:option:`CONFIG_NET_SOCKETPAIR` * :kconfig:option:`CONFIG_NET_SOCKETS` @@ -26,7 +26,6 @@ implementation of the POSIX API. * :kconfig:option:`CONFIG_POSIX_FS` * :kconfig:option:`CONFIG_ZVFS_OPEN_MAX` * :kconfig:option:`CONFIG_POSIX_OPEN_MAX` -* :kconfig:option:`CONFIG_POSIX_MQUEUE` * :kconfig:option:`CONFIG_POSIX_RTSIG_MAX` * :kconfig:option:`CONFIG_POSIX_SIGNAL` * :kconfig:option:`CONFIG_POSIX_SIGNAL_STRING_DESC` diff --git a/include/zephyr/posix/mqueue.h b/include/zephyr/posix/mqueue.h index dbaa6d42a537d..aac03426da442 100644 --- a/include/zephyr/posix/mqueue.h +++ b/include/zephyr/posix/mqueue.h @@ -4,8 +4,8 @@ * SPDX-License-Identifier: Apache-2.0 */ -#ifndef ZEPHYR_INCLUDE_POSIX_MQUEUE_H_ -#define ZEPHYR_INCLUDE_POSIX_MQUEUE_H_ +#ifndef ZEPHYR_INCLUDE_POSIX_MESSAGE_PASSING_H_ +#define ZEPHYR_INCLUDE_POSIX_MESSAGE_PASSING_H_ #include #include @@ -47,4 +47,4 @@ int mq_notify(mqd_t mqdes, const struct sigevent *notification); } #endif -#endif /* ZEPHYR_INCLUDE_POSIX_MQUEUE_H_ */ +#endif /* ZEPHYR_INCLUDE_POSIX_MESSAGE_PASSING_H_ */ diff --git a/include/zephyr/posix/posix_features.h b/include/zephyr/posix/posix_features.h index 75bb0c0efebc2..9b53a4ba6462e 100644 --- a/include/zephyr/posix/posix_features.h +++ b/include/zephyr/posix/posix_features.h @@ -53,7 +53,7 @@ /* #define _POSIX_MEMLOCK_RANGE (-1L) */ /* #define _POSIX_MEMORY_PROTECTION (-1L) */ -#ifdef CONFIG_POSIX_MQUEUE +#ifdef CONFIG_POSIX_MESSAGE_PASSING #define _POSIX_MESSAGE_PASSING _POSIX_VERSION #endif @@ -207,7 +207,7 @@ #define _POSIX_MAX_CANON (255) #define _POSIX_MAX_INPUT (255) #define _POSIX_MQ_OPEN_MAX \ - COND_CODE_1(CONFIG_POSIX_MQUEUE, (CONFIG_MSG_COUNT_MAX), (0)) + COND_CODE_1(CONFIG_POSIX_MESSAGE_PASSING, (CONFIG_POSIX_MQ_OPEN_MAX), (0)) #define _POSIX_MQ_PRIO_MAX (32) #define _POSIX_NAME_MAX (14) #define _POSIX_NGROUPS_MAX (8) diff --git a/include/zephyr/posix/sys/sysconf.h b/include/zephyr/posix/sys/sysconf.h index dcd4eb279226f..dfcebd28cc253 100644 --- a/include/zephyr/posix/sys/sysconf.h +++ b/include/zephyr/posix/sys/sysconf.h @@ -158,7 +158,7 @@ enum { #define __z_posix_sysconf_SC_MEMLOCK_RANGE (-1L) #define __z_posix_sysconf_SC_MEMORY_PROTECTION (-1L) #define __z_posix_sysconf_SC_MESSAGE_PASSING \ - COND_CODE_1(CONFIG_POSIX_MQUEUE, (_POSIX_MESSAGE_PASSING), (-1L)) + COND_CODE_1(CONFIG_POSIX_MESSAGE_PASSING, (_POSIX_MESSAGE_PASSING), (-1L)) #define __z_posix_sysconf_SC_MONOTONIC_CLOCK \ COND_CODE_1(CONFIG_POSIX_MONOTONIC_CLOCK, (_POSIX_MONOTONIC_CLOCK), (-1L)) #define __z_posix_sysconf_SC_PRIORITIZED_IO (-1L) diff --git a/lib/posix/options/CMakeLists.txt b/lib/posix/options/CMakeLists.txt index 02c8c30dd74ab..a6ce721b4ce7b 100644 --- a/lib/posix/options/CMakeLists.txt +++ b/lib/posix/options/CMakeLists.txt @@ -25,7 +25,7 @@ if(CONFIG_POSIX_SIGNAL) endif() if(CONFIG_POSIX_API OR CONFIG_PTHREAD_IPC OR CONFIG_POSIX_TIMERS OR - CONFIG_POSIX_MQUEUE OR CONFIG_POSIX_FS OR CONFIG_EVENTFD OR CONFIG_GETOPT OR + CONFIG_POSIX_MESSAGE_PASSING OR CONFIG_POSIX_FS OR CONFIG_EVENTFD OR CONFIG_GETOPT OR CONFIG_POSIX_SINGLE_PROCESS) # This is a temporary workaround so that Newlib declares the appropriate # types for us. POSIX features to be formalized as part of #51211 @@ -49,7 +49,7 @@ zephyr_library_sources_ifdef(CONFIG_POSIX_FD_MGMT fd_mgmt.c ) zephyr_library_sources_ifdef(CONFIG_POSIX_FS fs.c) -zephyr_library_sources_ifdef(CONFIG_POSIX_MQUEUE mqueue.c) +zephyr_library_sources_ifdef(CONFIG_POSIX_MESSAGE_PASSING mqueue.c) zephyr_library_sources_ifdef(CONFIG_POSIX_MULTI_PROCESS sleep.c ) diff --git a/lib/posix/options/Kconfig.deprecated b/lib/posix/options/Kconfig.deprecated index 203b8463bd77e..b2ed5e6002812 100644 --- a/lib/posix/options/Kconfig.deprecated +++ b/lib/posix/options/Kconfig.deprecated @@ -15,6 +15,15 @@ config MAX_TIMER_COUNT Please use CONFIG_POSIX_TIMER_MAX instead. +config MSG_COUNT_MAX + int "Maximum number of messages in a POSIX message queue [DEPRECATED]" + default POSIX_MQ_OPEN_MAX if POSIX_MESSAGE_PASSING + default 0 + help + This option is deprecated. + + Please use CONFIG_POSIX_MQ_OPEN_MAX instead. + config POSIX_CLOCK bool "clock and sleep APIs [DEPRECATED]" select DEPRECATED @@ -75,6 +84,15 @@ config POSIX_MAX_OPEN_FILES See also CONFIG_ZVFS_OPEN_MAX. +config POSIX_MQUEUE + bool "Message queue support [DEPRECATED]" + select DEPRECATED + select POSIX_MESSAGE_PASSING + help + This option is deprecated. + + Please use CONFIG_POSIX_MESSAGE_PASSING instead. + config POSIX_SYSCONF bool "Support for sysconf() [DEPRECATED]" select DEPRECATED diff --git a/lib/posix/options/Kconfig.mqueue b/lib/posix/options/Kconfig.mqueue index 3688455d781fa..607885b21cf75 100644 --- a/lib/posix/options/Kconfig.mqueue +++ b/lib/posix/options/Kconfig.mqueue @@ -2,33 +2,39 @@ # # SPDX-License-Identifier: Apache-2.0 -menuconfig POSIX_MQUEUE - bool "Message queue support" +menuconfig POSIX_MESSAGE_PASSING + bool "POSIX message queue support" default y if POSIX_API help This enabled POSIX message queue related APIs. -if POSIX_MQUEUE +if POSIX_MESSAGE_PASSING -config MSG_COUNT_MAX - int "Maximum number of messages in message queue" +config POSIX_MQ_OPEN_MAX + int "Maximum number of messages in a POSIX message queue" default 16 help Mention maximum number of messages in message queue in POSIX compliant application. +config POSIX_MQ_PRIO_MAX + int "Maximum number of POSIX message priorities" + default 32 + help + Maximum number of message priorities supported by the implementation. + config MSG_SIZE_MAX - int "Maximum size of a message" + int "Maximum size of a POSIX message" default 16 help Mention maximum size of message in bytes. config MQUEUE_NAMELEN_MAX - int "Maximum size of a name length" + int "Maximum POSIX message queue name size" default 16 range 2 255 help - Mention length of message queue name in number of characters. + Mention size of message queue name in number of characters. config HEAP_MEM_POOL_ADD_SIZE_MQUEUE def_int 1024 diff --git a/lib/posix/options/mqueue.c b/lib/posix/options/mqueue.c index ca8e54744889c..ce77283e63782 100644 --- a/lib/posix/options/mqueue.c +++ b/lib/posix/options/mqueue.c @@ -118,7 +118,7 @@ mqd_t mq_open(const char *name, int oflags, ...) /* Check for message quantity and size in message queue */ if (attrs->mq_msgsize > CONFIG_MSG_SIZE_MAX && - attrs->mq_maxmsg > CONFIG_MSG_COUNT_MAX) { + attrs->mq_maxmsg > CONFIG_POSIX_MQ_OPEN_MAX) { goto free_mq_desc; } diff --git a/tests/posix/common/prj.conf b/tests/posix/common/prj.conf index bc92bed8fbf31..5c5613d0e68ed 100644 --- a/tests/posix/common/prj.conf +++ b/tests/posix/common/prj.conf @@ -3,7 +3,7 @@ CONFIG_POSIX_API=y CONFIG_MAX_PTHREAD_COUNT=6 CONFIG_ZTEST=y CONFIG_SEM_VALUE_MAX=32767 -CONFIG_POSIX_MQUEUE=y +CONFIG_POSIX_MESSAGE_PASSING=y CONFIG_POSIX_PRIORITY_SCHEDULING=y CONFIG_HEAP_MEM_POOL_SIZE=4096 CONFIG_THREAD_NAME=y diff --git a/tests/posix/headers/prj.conf b/tests/posix/headers/prj.conf index 7161e4b311575..6dc46dc7b4fab 100644 --- a/tests/posix/headers/prj.conf +++ b/tests/posix/headers/prj.conf @@ -17,6 +17,6 @@ CONFIG_NET_SOCKETPAIR=y CONFIG_PTHREAD_IPC=y CONFIG_POSIX_FS=y CONFIG_POSIX_TIMERS=y -CONFIG_POSIX_MQUEUE=y +CONFIG_POSIX_MESSAGE_PASSING=y CONFIG_EVENTFD=y CONFIG_GETOPT=y From 70e2b02c8e118e11e9f6a13bb4eea0c3db2393a6 Mon Sep 17 00:00:00 2001 From: Chris Friedt Date: Wed, 22 May 2024 19:10:38 -0400 Subject: [PATCH 1737/2849] posix: deprecate PTHREAD_RWLOCK for POSIX_READER_WRITER_LOCKS This change deprecates CONFIG_PTHREAD_RWLOCK in favour of CONFIG_POSIX_READER_WRITER_LOCKS, which maps directly to the name of the standard POSIX Option. Annoyingly, the POSIX_RW_LOCKS Option Group is inconsistently named. However, it is more convenient for us to use the Option name since it is also the format used by the sysconf() variable (_SC_READER_WRITER_LOCKS). Signed-off-by: Chris Friedt --- .../portability/posix/conformance/index.rst | 2 +- include/zephyr/posix/posix_features.h | 2 +- include/zephyr/posix/pthread.h | 2 +- include/zephyr/posix/sys/sysconf.h | 2 +- lib/posix/options/CMakeLists.txt | 2 +- lib/posix/options/Kconfig.deprecated | 9 ++++++ lib/posix/options/Kconfig.rwlock | 28 ++++++++++++++++--- lib/posix/options/rwlock.c | 4 +-- tests/posix/headers/src/pthread_h.c | 2 +- 9 files changed, 41 insertions(+), 12 deletions(-) diff --git a/doc/services/portability/posix/conformance/index.rst b/doc/services/portability/posix/conformance/index.rst index b4baa41262dbc..ef0522107d07e 100644 --- a/doc/services/portability/posix/conformance/index.rst +++ b/doc/services/portability/posix/conformance/index.rst @@ -66,7 +66,7 @@ POSIX System Interfaces :ref:`_POSIX_CLOCK_SELECTION`, 200809L, :kconfig:option:`CONFIG_POSIX_CLOCK_SELECTION` _POSIX_MAPPED_FILES, -1, :ref:`†` _POSIX_MEMORY_PROTECTION, -1, :ref:`†` - :ref:`_POSIX_READER_WRITER_LOCKS`, 200809L, :kconfig:option:`CONFIG_PTHREAD_IPC` + :ref:`_POSIX_READER_WRITER_LOCKS`, 200809L, :kconfig:option:`CONFIG_POSIX_READER_WRITER_LOCKS` :ref:`_POSIX_REALTIME_SIGNALS`, -1, :ref:`_POSIX_SEMAPHORES`, 200809L, :kconfig:option:`CONFIG_PTHREAD_IPC` :ref:`_POSIX_SPIN_LOCKS`, 200809L, :kconfig:option:`CONFIG_POSIX_SPIN_LOCKS` diff --git a/include/zephyr/posix/posix_features.h b/include/zephyr/posix/posix_features.h index 9b53a4ba6462e..710c7c8f14835 100644 --- a/include/zephyr/posix/posix_features.h +++ b/include/zephyr/posix/posix_features.h @@ -71,7 +71,7 @@ #define _POSIX_RAW_SOCKETS _POSIX_VERSION #endif -#ifdef CONFIG_PTHREAD_IPC +#ifdef CONFIG_POSIX_READER_WRITER_LOCKS #define _POSIX_READER_WRITER_LOCKS _POSIX_VERSION #endif diff --git a/include/zephyr/posix/pthread.h b/include/zephyr/posix/pthread.h index 7cd0f7e116092..0a721f58be23a 100644 --- a/include/zephyr/posix/pthread.h +++ b/include/zephyr/posix/pthread.h @@ -153,7 +153,7 @@ int pthread_condattr_setclock(pthread_condattr_t *att, clockid_t clock_id); * * Initialize a rwlock with the default rwlock attributes. */ -#define PTHREAD_RWLOCK_INITIALIZER (-1) +#define POSIX_RWLOCK_INITIALIZER (-1) /* * Mutex attributes - type diff --git a/include/zephyr/posix/sys/sysconf.h b/include/zephyr/posix/sys/sysconf.h index dfcebd28cc253..d90f13580e5ff 100644 --- a/include/zephyr/posix/sys/sysconf.h +++ b/include/zephyr/posix/sys/sysconf.h @@ -168,7 +168,7 @@ enum { COND_CODE_1(CONFIG_NET_SOCKETS_PACKET, (_POSIX_RAW_SOCKETS), (-1L)) #define __z_posix_sysconf_SC_RE_DUP_MAX _POSIX_RE_DUP_MAX #define __z_posix_sysconf_SC_READER_WRITER_LOCKS \ - COND_CODE_1(CONFIG_PTHREAD_IPC, (_POSIX_READER_WRITER_LOCKS), (-1L)) + COND_CODE_1(CONFIG_POSIX_READER_WRITER_LOCKS, (_POSIX_READER_WRITER_LOCKS), (-1L)) #define __z_posix_sysconf_SC_REALTIME_SIGNALS (-1L) #define __z_posix_sysconf_SC_REGEXP (-1L) #define __z_posix_sysconf_SC_SAVED_IDS (-1L) diff --git a/lib/posix/options/CMakeLists.txt b/lib/posix/options/CMakeLists.txt index a6ce721b4ce7b..e4431df859b67 100644 --- a/lib/posix/options/CMakeLists.txt +++ b/lib/posix/options/CMakeLists.txt @@ -73,8 +73,8 @@ zephyr_library_sources_ifdef(CONFIG_PTHREAD_COND cond.c) zephyr_library_sources_ifdef(CONFIG_PTHREAD_KEY key.c) zephyr_library_sources_ifdef(CONFIG_PTHREAD_MUTEX mutex.c) zephyr_library_sources_ifdef(CONFIG_PTHREAD pthread.c) -zephyr_library_sources_ifdef(CONFIG_PTHREAD_RWLOCK rwlock.c) zephyr_library_sources_ifdef(CONFIG_POSIX_PRIORITY_SCHEDULING sched.c) +zephyr_library_sources_ifdef(CONFIG_POSIX_READER_WRITER_LOCKS rwlock.c) zephyr_library_sources_ifdef(CONFIG_PTHREAD_IPC semaphore.c) zephyr_library_include_directories( diff --git a/lib/posix/options/Kconfig.deprecated b/lib/posix/options/Kconfig.deprecated index b2ed5e6002812..5b16209fad05c 100644 --- a/lib/posix/options/Kconfig.deprecated +++ b/lib/posix/options/Kconfig.deprecated @@ -120,6 +120,15 @@ config PTHREAD_BARRIER Please use CONFIG_POSIX_BARRIERS instead. +config PTHREAD_RWLOCK + bool "pthread_spinlock_t support [DEPRECATED]" + select DEPRECATED + select POSIX_READER_WRITER_LOCKS + help + This option is deprecated. + + Please use CONFIG_POSIX_READER_WRITER_LOCKS instead. + config PTHREAD_SPINLOCK bool "pthread_spinlock_t support [DEPRECATED]" select DEPRECATED diff --git a/lib/posix/options/Kconfig.rwlock b/lib/posix/options/Kconfig.rwlock index fea61551ec356..ed19520725a68 100644 --- a/lib/posix/options/Kconfig.rwlock +++ b/lib/posix/options/Kconfig.rwlock @@ -2,7 +2,27 @@ # # SPDX-License-Identifier: Apache-2.0 -TYPE = PTHREAD_RWLOCK -type = pthread_rwlock_t -type-function = pthread_rwlock_timedrdlock -rsource "Kconfig.template.pooled_ipc_type" +menuconfig POSIX_READER_WRITER_LOCKS + bool "POSIX reader-writer locks" + default y if POSIX_API + help + Select 'y' here to enable POSIX reader-writer locks. + + For more information please see + https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_subprofiles.html + +if POSIX_READER_WRITER_LOCKS + +config MAX_PTHREAD_RWLOCK_COUNT + int "Maximum number of POSIX reader-writer locks" + default 5 + help + Maximum simultaneously active reader-writer locks in a POSIX application. + + Note: this is a non-standard option. + +module = PTHREAD_RWLOCK +module-str = POSIX Reader-Writer Locks +source "subsys/logging/Kconfig.template.log_config" + +endif # POSIX_READER_WRITER_LOCKS diff --git a/lib/posix/options/rwlock.c b/lib/posix/options/rwlock.c index b8a91a03232b8..c4143a79acb18 100644 --- a/lib/posix/options/rwlock.c +++ b/lib/posix/options/rwlock.c @@ -86,7 +86,7 @@ struct posix_rwlock *to_posix_rwlock(pthread_rwlock_t *rwlock) size_t bit; struct posix_rwlock *rwl; - if (*rwlock != PTHREAD_RWLOCK_INITIALIZER) { + if (*rwlock != POSIX_RWLOCK_INITIALIZER) { return get_posix_rwlock(*rwlock); } @@ -116,7 +116,7 @@ int pthread_rwlock_init(pthread_rwlock_t *rwlock, struct posix_rwlock *rwl; ARG_UNUSED(attr); - *rwlock = PTHREAD_RWLOCK_INITIALIZER; + *rwlock = POSIX_RWLOCK_INITIALIZER; rwl = to_posix_rwlock(rwlock); if (rwl == NULL) { diff --git a/tests/posix/headers/src/pthread_h.c b/tests/posix/headers/src/pthread_h.c index 4363d3b476419..8f1286222d5f9 100644 --- a/tests/posix/headers/src/pthread_h.c +++ b/tests/posix/headers/src/pthread_h.c @@ -59,7 +59,7 @@ ZTEST(posix_headers, test_pthread_h) pthread_cond_t cond = PTHREAD_COND_INITIALIZER; pthread_mutex_t mu = PTHREAD_MUTEX_INITIALIZER; - /* pthread_rwlock_t lock = PTHREAD_RWLOCK_INITIALIZER; */ /* not implemented */ + /* pthread_rwlock_t lock = POSIX_READER_WRITER_LOCKS_INITIALIZER; */ /* not implemented */ zassert_not_null(pthread_atfork); zassert_not_null(pthread_attr_destroy); From 2bc722a97ed6716e3effca2ce5664ec20bcb5555 Mon Sep 17 00:00:00 2001 From: Chris Friedt Date: Wed, 22 May 2024 19:44:17 -0400 Subject: [PATCH 1738/2849] posix: deprecate POSIX_FNMATCH GETOPT GETENTROPY The functions fnmatch(), getopt(), getentropy() and others are grouped into the standard Option Group POSIX_C_LIB_EXT. The getentropy() function is currently in-draft for Issue 8 as of 2021. https://www.opengroup.org/austin/docs/austin_1110.pdf Not surprisingly, the POSIX_C_LIB_EXT Option Group also includes the highly debated strnlen() function. Moving that function will be deferred until later. Signed-off-by: Chris Friedt --- .../portability/posix/kconfig/index.rst | 2 -- .../portability/posix/option_groups/index.rst | 25 ++++++++++++++++ doc/services/shell/index.rst | 2 +- drivers/sensor/seeed/grove/Kconfig | 2 -- include/zephyr/posix/unistd.h | 2 +- lib/crc/Kconfig | 2 +- lib/posix/options/CMakeLists.txt | 18 ++++++++--- lib/posix/options/Kconfig | 5 +--- lib/posix/options/Kconfig.c_lib_ext | 30 +++++++++++++++++++ lib/posix/options/Kconfig.deprecated | 27 +++++++++++++++++ lib/posix/options/Kconfig.fnmatch | 10 ------- lib/posix/options/Kconfig.getentropy | 14 --------- lib/posix/options/Kconfig.getopt | 5 ---- lib/posix/options/getentropy.c | 6 ++-- lib/posix/options/getopt/CMakeLists.txt | 20 ------------- lib/posix/options/getopt/Kconfig | 28 ----------------- lib/posix/options/getopt/getopt.h | 4 +++ samples/shields/npm6001_ek/prj.conf | 2 +- subsys/shell/Kconfig | 4 +-- subsys/shell/modules/Kconfig | 2 +- tests/posix/getentropy/prj.conf | 3 +- tests/posix/getentropy/src/main.c | 2 +- tests/posix/getopt/prj.conf | 2 +- tests/posix/headers/prj.conf | 2 +- 24 files changed, 115 insertions(+), 104 deletions(-) create mode 100644 lib/posix/options/Kconfig.c_lib_ext delete mode 100644 lib/posix/options/Kconfig.fnmatch delete mode 100644 lib/posix/options/Kconfig.getentropy delete mode 100644 lib/posix/options/Kconfig.getopt delete mode 100644 lib/posix/options/getopt/CMakeLists.txt delete mode 100644 lib/posix/options/getopt/Kconfig diff --git a/doc/services/portability/posix/kconfig/index.rst b/doc/services/portability/posix/kconfig/index.rst index 51dc795115e08..14a77e3a3e7ce 100644 --- a/doc/services/portability/posix/kconfig/index.rst +++ b/doc/services/portability/posix/kconfig/index.rst @@ -9,8 +9,6 @@ implementation of the POSIX API. * :kconfig:option:`CONFIG_EVENTFD` * :kconfig:option:`CONFIG_EVENTFD_MAX` * :kconfig:option:`CONFIG_FDTABLE` -* :kconfig:option:`CONFIG_FNMATCH` -* :kconfig:option:`CONFIG_GETOPT` * :kconfig:option:`CONFIG_GETOPT_LONG` * :kconfig:option:`CONFIG_MAX_PTHREAD_COUNT` * :kconfig:option:`CONFIG_MAX_PTHREAD_KEY_COUNT` diff --git a/doc/services/portability/posix/option_groups/index.rst b/doc/services/portability/posix/option_groups/index.rst index 00a5c34ad4ffc..a2c316a6928c6 100644 --- a/doc/services/portability/posix/option_groups/index.rst +++ b/doc/services/portability/posix/option_groups/index.rst @@ -151,6 +151,31 @@ Group. For more information on developing Zephyr applications in the C programming language, please refer to :ref:`details`. +.. _posix_option_group_c_lib_ext: + +POSIX_C_LIB_EXT +=============== + +.. csv-table:: POSIX_C_LIB_EXT + :header: API, Supported + :widths: 50,10 + + fnmatch(), yes + getopt(), yes + getsubopt(), + optarg, yes + opterr, yes + optind, yes + optopt, yes + stpcpy(), + stpncpy(), + strcasecmp(), + strdup(), + strfmon(), + strncasecmp(), yes + strndup(), + strnlen(), yes + .. _posix_option_group_realtime_signals: POSIX_REALTIME_SIGNALS diff --git a/doc/services/shell/index.rst b/doc/services/shell/index.rst index 504bef139fe01..582ddcd2f9ce7 100644 --- a/doc/services/shell/index.rst +++ b/doc/services/shell/index.rst @@ -556,7 +556,7 @@ is accomplished by the ``getopt`` family functions. For this purpose shell supports the getopt and getopt_long libraries available in the FreeBSD project. This feature is activated by: -:kconfig:option:`CONFIG_GETOPT` set to ``y`` and :kconfig:option:`CONFIG_GETOPT_LONG` +:kconfig:option:`CONFIG_POSIX_C_LIB_EXT` set to ``y`` and :kconfig:option:`CONFIG_GETOPT_LONG` set to ``y``. This feature can be used in thread safe as well as non thread safe manner. diff --git a/drivers/sensor/seeed/grove/Kconfig b/drivers/sensor/seeed/grove/Kconfig index 9563bdd7b3aa6..a91c66c099637 100644 --- a/drivers/sensor/seeed/grove/Kconfig +++ b/drivers/sensor/seeed/grove/Kconfig @@ -16,7 +16,6 @@ config GROVE_LIGHT_SENSOR bool "The Seeed Grove Light Sensor" default y depends on DT_HAS_SEEED_GROVE_LIGHT_ENABLED - depends on !MINIMAL_LIBC select ADC help Setting this value will enable driver support for the Grove Light @@ -26,7 +25,6 @@ config GROVE_TEMPERATURE_SENSOR bool "The Seeed Grove Temperature Sensor" default y depends on DT_HAS_SEEED_GROVE_TEMPERATURE_ENABLED - depends on !MINIMAL_LIBC select ADC help Setting this value will enable driver support for the Grove diff --git a/include/zephyr/posix/unistd.h b/include/zephyr/posix/unistd.h index 3102dd89be048..194b2bffe6f50 100644 --- a/include/zephyr/posix/unistd.h +++ b/include/zephyr/posix/unistd.h @@ -52,7 +52,7 @@ static inline int gethostname(char *buf, size_t len) #endif /* CONFIG_POSIX_API */ -#ifdef CONFIG_GETOPT +#ifdef CONFIG_POSIX_C_LIB_EXT int getopt(int argc, char *const argv[], const char *optstring); extern char *optarg; extern int opterr, optind, optopt; diff --git a/lib/crc/Kconfig b/lib/crc/Kconfig index f0745f0adedf2..0402df59d01fb 100644 --- a/lib/crc/Kconfig +++ b/lib/crc/Kconfig @@ -10,7 +10,7 @@ if CRC config CRC_SHELL bool "CRC Shell" depends on SHELL - select GETOPT + select POSIX_C_LIB_EXT help Enable CRC checking for memory regions from the shell. endif # CRC diff --git a/lib/posix/options/CMakeLists.txt b/lib/posix/options/CMakeLists.txt index e4431df859b67..9826156fd14b5 100644 --- a/lib/posix/options/CMakeLists.txt +++ b/lib/posix/options/CMakeLists.txt @@ -25,7 +25,7 @@ if(CONFIG_POSIX_SIGNAL) endif() if(CONFIG_POSIX_API OR CONFIG_PTHREAD_IPC OR CONFIG_POSIX_TIMERS OR - CONFIG_POSIX_MESSAGE_PASSING OR CONFIG_POSIX_FS OR CONFIG_EVENTFD OR CONFIG_GETOPT OR + CONFIG_POSIX_MESSAGE_PASSING OR CONFIG_POSIX_FS OR CONFIG_EVENTFD OR CONFIG_POSIX_C_LIB_EXT OR CONFIG_POSIX_SINGLE_PROCESS) # This is a temporary workaround so that Newlib declares the appropriate # types for us. POSIX features to be formalized as part of #51211 @@ -34,12 +34,15 @@ if(CONFIG_POSIX_API OR CONFIG_PTHREAD_IPC OR CONFIG_POSIX_TIMERS OR endif() zephyr_library() -add_subdirectory_ifdef(CONFIG_GETOPT getopt) zephyr_library_sources_ifdef(CONFIG_EVENTFD eventfd.c) -zephyr_library_sources_ifdef(CONFIG_FNMATCH fnmatch.c) -zephyr_library_sources_ifdef(CONFIG_GETENTROPY getentropy.c) zephyr_library_sources_ifdef(CONFIG_POSIX_ASYNCHRONOUS_IO aio.c) zephyr_library_sources_ifdef(CONFIG_POSIX_BARRIERS barrier.c) +zephyr_library_sources_ifdef(CONFIG_POSIX_C_LIB_EXT + fnmatch.c + getentropy.c + getopt/getopt.c + getopt/getopt_common.c +) zephyr_library_sources_ifdef(CONFIG_POSIX_DEVICE_IO # perror should be moved to the common libc perror.c @@ -77,6 +80,13 @@ zephyr_library_sources_ifdef(CONFIG_POSIX_PRIORITY_SCHEDULING sched.c) zephyr_library_sources_ifdef(CONFIG_POSIX_READER_WRITER_LOCKS rwlock.c) zephyr_library_sources_ifdef(CONFIG_PTHREAD_IPC semaphore.c) +zephyr_library_sources_ifdef(CONFIG_GETOPT_LONG + getopt/getopt_long.c +) +zephyr_include_directories_ifdef(CONFIG_POSIX_C_LIB_EXT + getopt/ +) + zephyr_library_include_directories( ${ZEPHYR_BASE}/kernel/include ${ARCH_DIR}/${ARCH}/include diff --git a/lib/posix/options/Kconfig b/lib/posix/options/Kconfig index da9b00b9a84c0..8e1f0918196e1 100644 --- a/lib/posix/options/Kconfig +++ b/lib/posix/options/Kconfig @@ -26,13 +26,10 @@ config PTHREAD_IPC rsource "Kconfig.aio" rsource "Kconfig.barrier" rsource "Kconfig.cond" +rsource "Kconfig.c_lib_ext" rsource "Kconfig.device_io" -rsource "Kconfig.eventfd" rsource "Kconfig.fd_mgmt" -rsource "Kconfig.fnmatch" rsource "Kconfig.fs" -rsource "Kconfig.getentropy" -rsource "Kconfig.getopt" rsource "Kconfig.key" rsource "Kconfig.mem" rsource "Kconfig.mqueue" diff --git a/lib/posix/options/Kconfig.c_lib_ext b/lib/posix/options/Kconfig.c_lib_ext new file mode 100644 index 0000000000000..8acfead9b342c --- /dev/null +++ b/lib/posix/options/Kconfig.c_lib_ext @@ -0,0 +1,30 @@ +# Copyright (c) 2024 Tenstorrent AI ULC +# +# SPDX-License-Identifier: Apache-2.0 + +menuconfig POSIX_C_LIB_EXT + bool "POSIX general C library extension" + default y if POSIX_API + help + Select 'y' here and Zephyr will provide an implementation of the POSIX_C_LIB_EXT Option + Group, consisting of fnmatch(), getopt(), getsubopt(), optarg, opterr, optind, optopt, + stpcpy(), stpncpy(), strcasecmp(), strdup(), strfmon(), and strncasecmp(), strndup(), and + strnlen(). + + For more informnation, please see + https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_subprofiles.html + +if POSIX_C_LIB_EXT + +config GETOPT_LONG + bool "Getopt long library support" + help + This option adds support of the getopt long. + Different shell backends are using their own instance of getopt to + not interfere with each other. + All not shell threads share one global instance of getopt state, hence + apart from shell this library is not thread safe. User can add support + for other threads by extending function getopt_state_get in + getopt_common.c file. + +endif # POSIX_C_LIB_EXT diff --git a/lib/posix/options/Kconfig.deprecated b/lib/posix/options/Kconfig.deprecated index 5b16209fad05c..f0e143736001a 100644 --- a/lib/posix/options/Kconfig.deprecated +++ b/lib/posix/options/Kconfig.deprecated @@ -6,6 +6,33 @@ menu "Deprecated POSIX options" +config FNMATCH + bool "Support for fnmatch [DEPRECATED]" + select DEPRECATED + select POSIX_C_LIB_EXT + help + This option is deprecated. + + Please use CONFIG_POSIX_C_LIB_EXT instead. + +config GETENTROPY + bool "Support for getentropy [DEPRECATED]" + select DEPRECATED + select POSIX_C_LIB_EXT + help + This option is deprecated. + + Please use CONFIG_POSIX_C_LIB_EXT instead. + +config GETOPT + bool "Getopt library support [DEPRECATED]" + select DEPRECATED + select POSIX_C_LIB_EXT + help + This option is deprecated. + + Please use CONFIG_POSIX_C_LIB_EXT instead. + config MAX_TIMER_COUNT int "Maximum number of timer_t [DEPRECATED]" default POSIX_TIMER_MAX if POSIX_TIMERS diff --git a/lib/posix/options/Kconfig.fnmatch b/lib/posix/options/Kconfig.fnmatch deleted file mode 100644 index 81f1a00938f3a..0000000000000 --- a/lib/posix/options/Kconfig.fnmatch +++ /dev/null @@ -1,10 +0,0 @@ -# Copyright (c) 2018 Nordic Semiconductor ASA -# -# SPDX-License-Identifier: Apache-2.0 - -config FNMATCH - bool "Support for fnmatch" - default y if POSIX_API - help - Match filenames using the the fnmatch function. For example, the pattern - "*.c" matches the filename "hello.c". diff --git a/lib/posix/options/Kconfig.getentropy b/lib/posix/options/Kconfig.getentropy deleted file mode 100644 index 7445413501929..0000000000000 --- a/lib/posix/options/Kconfig.getentropy +++ /dev/null @@ -1,14 +0,0 @@ -# Copyright (c) 2024 Google LLC -# -# SPDX-License-Identifier: Apache-2.0 - -DT_CHOSEN_ZEPHYR_ENTROPY := zephyr,entropy - -config GETENTROPY - bool "Support for getentropy" - depends on !NATIVE_APPLICATION - select NATIVE_LIBC_INCOMPATIBLE - depends on ENTROPY_HAS_DRIVER - depends on $(dt_chosen_enabled,$(DT_CHOSEN_ZEPHYR_ENTROPY)) - help - Enable support for getentropy() function. diff --git a/lib/posix/options/Kconfig.getopt b/lib/posix/options/Kconfig.getopt deleted file mode 100644 index 4d3559cd855c3..0000000000000 --- a/lib/posix/options/Kconfig.getopt +++ /dev/null @@ -1,5 +0,0 @@ -# Copyright (c) 2021 Nordic Semiconductor ASA -# -# SPDX-License-Identifier: Apache-2.0 - -rsource "getopt/Kconfig" diff --git a/lib/posix/options/getentropy.c b/lib/posix/options/getentropy.c index dcc271617cbe2..974ea4dce507f 100644 --- a/lib/posix/options/getentropy.c +++ b/lib/posix/options/getentropy.c @@ -10,11 +10,11 @@ #include #include -#define ENTROPY_NODE DT_CHOSEN(zephyr_entropy) +#define ENTROPY_NODE DEVICE_DT_GET_OR_NULL(DT_CHOSEN(zephyr_entropy)) int getentropy(void *buffer, size_t length) { - const struct device * const entropy = DEVICE_DT_GET(ENTROPY_NODE); + const struct device *const entropy = ENTROPY_NODE; if (!buffer) { errno = EFAULT; @@ -26,7 +26,7 @@ int getentropy(void *buffer, size_t length) return -1; } - if (!device_is_ready(entropy)) { + if (entropy == NULL || !device_is_ready(entropy)) { errno = EIO; return -1; } diff --git a/lib/posix/options/getopt/CMakeLists.txt b/lib/posix/options/getopt/CMakeLists.txt deleted file mode 100644 index 642e3b9949b5a..0000000000000 --- a/lib/posix/options/getopt/CMakeLists.txt +++ /dev/null @@ -1,20 +0,0 @@ -# Copyright (c) 2021 Nordic Semiconductor -# -# SPDX-License-Identifier: Apache-2.0 -# - -zephyr_include_directories_ifdef( - CONFIG_GETOPT - . -) - -zephyr_sources_ifdef( - CONFIG_GETOPT - getopt.c - getopt_common.c -) - -zephyr_sources_ifdef( - CONFIG_GETOPT_LONG - getopt_long.c -) diff --git a/lib/posix/options/getopt/Kconfig b/lib/posix/options/getopt/Kconfig deleted file mode 100644 index 72c9961fb9041..0000000000000 --- a/lib/posix/options/getopt/Kconfig +++ /dev/null @@ -1,28 +0,0 @@ -# Copyright (c) 2021 Nordic Semiconductor -# SPDX-License-Identifier: Apache-2.0 - - -menuconfig GETOPT - bool "Getopt library support" - default y if POSIX_API - help - This option adds support of getopt. - Different shell backends are use their own instance of getopt to - not interfere with each other. - All not shell threads share one global instance of getopt state, hence - apart from shell this library is not thread safe. User can add support - for other threads by extending function getopt_state_get in - getopt_common.c file. - This option enables the following function: getopt. - -config GETOPT_LONG - bool "Getopt long library support" - depends on GETOPT - help - This option adds support of the getopt long. - Different shell backends are using their own instance of getopt to - not interfere with each other. - All not shell threads share one global instance of getopt state, hence - apart from shell this library is not thread safe. User can add support - for other threads by extending function getopt_state_get in - getopt_common.c file. diff --git a/lib/posix/options/getopt/getopt.h b/lib/posix/options/getopt/getopt.h index 3ae474f4304fc..666c5541c635c 100644 --- a/lib/posix/options/getopt/getopt.h +++ b/lib/posix/options/getopt/getopt.h @@ -29,6 +29,10 @@ struct getopt_state { }; extern int optreset; /* reset getopt */ +extern char *optarg; +extern int opterr; +extern int optind; +extern int optopt; #define no_argument 0 #define required_argument 1 diff --git a/samples/shields/npm6001_ek/prj.conf b/samples/shields/npm6001_ek/prj.conf index 94da7cfdaef63..b0292200688e7 100644 --- a/samples/shields/npm6001_ek/prj.conf +++ b/samples/shields/npm6001_ek/prj.conf @@ -3,7 +3,7 @@ CONFIG_SHELL=y CONFIG_SHELL_GETOPT=y -CONFIG_GETOPT=y +CONFIG_POSIX_C_LIB_EXT=y CONFIG_GETOPT_LONG=y CONFIG_GPIO=y CONFIG_REGULATOR=y diff --git a/subsys/shell/Kconfig b/subsys/shell/Kconfig index c990783995981..0c3919d164e7e 100644 --- a/subsys/shell/Kconfig +++ b/subsys/shell/Kconfig @@ -132,7 +132,7 @@ config SHELL_ASCII_FILTER config SHELL_WILDCARD bool "Wildcard support in shell" - select FNMATCH + select POSIX_C_LIB_EXT default y if !SHELL_MINIMAL help Enables using wildcards: * and ? in the shell. @@ -176,7 +176,7 @@ config SHELL_VT100_COLORS config SHELL_GETOPT bool "Threadsafe getopt support in shell" - select GETOPT + select POSIX_C_LIB_EXT help This config creates a separate getopt_state for the shell instance. It ensures that using getopt with shell is thread safe. diff --git a/subsys/shell/modules/Kconfig b/subsys/shell/modules/Kconfig index c57704ee2ae91..86e9ac49a9bb6 100644 --- a/subsys/shell/modules/Kconfig +++ b/subsys/shell/modules/Kconfig @@ -42,6 +42,6 @@ config DATE_SHELL config DEVMEM_SHELL bool "Devmem shell" default y if !SHELL_MINIMAL - select GETOPT + select POSIX_C_LIB_EXT help This shell command provides read/write access to physical memory. diff --git a/tests/posix/getentropy/prj.conf b/tests/posix/getentropy/prj.conf index 58160099e325e..9d73893e0034e 100644 --- a/tests/posix/getentropy/prj.conf +++ b/tests/posix/getentropy/prj.conf @@ -1,4 +1,3 @@ CONFIG_ENTROPY_GENERATOR=y -CONFIG_GETENTROPY=y -CONFIG_POSIX_API=y +CONFIG_POSIX_C_LIB_EXT=y CONFIG_ZTEST=y diff --git a/tests/posix/getentropy/src/main.c b/tests/posix/getentropy/src/main.c index a276c4b96637f..010207e678da8 100644 --- a/tests/posix/getentropy/src/main.c +++ b/tests/posix/getentropy/src/main.c @@ -6,7 +6,7 @@ #include -#include +#include ZTEST(getentropy_test_suite, test_getentropy_too_large) { diff --git a/tests/posix/getopt/prj.conf b/tests/posix/getopt/prj.conf index 034ce191ddf23..dc97b22a9b5e3 100644 --- a/tests/posix/getopt/prj.conf +++ b/tests/posix/getopt/prj.conf @@ -1,4 +1,4 @@ -CONFIG_GETOPT=y +CONFIG_POSIX_C_LIB_EXT=y CONFIG_GETOPT_LONG=y CONFIG_LOG=n CONFIG_ZTEST=y diff --git a/tests/posix/headers/prj.conf b/tests/posix/headers/prj.conf index 6dc46dc7b4fab..c785e4592930d 100644 --- a/tests/posix/headers/prj.conf +++ b/tests/posix/headers/prj.conf @@ -19,4 +19,4 @@ CONFIG_POSIX_FS=y CONFIG_POSIX_TIMERS=y CONFIG_POSIX_MESSAGE_PASSING=y CONFIG_EVENTFD=y -CONFIG_GETOPT=y +CONFIG_POSIX_C_LIB_EXT=y From 9f6590c7b7dcbe1f3e30c1257f60993168ea4c81 Mon Sep 17 00:00:00 2001 From: Chris Friedt Date: Wed, 22 May 2024 19:56:11 -0400 Subject: [PATCH 1739/2849] posix: deprecate POSIX_FS for POSIX_FILE_SYSTEM This change deprecates CONFIG_POSIX_FS in favour of CONFIG_POSIX_FILE_SYSTEM, which maps directly to the name of the standard POSIX Option Group. Signed-off-by: Chris Friedt --- doc/services/portability/posix/aep/index.rst | 4 +- .../portability/posix/conformance/index.rst | 2 +- .../portability/posix/kconfig/index.rst | 1 - include/zephyr/posix/dirent.h | 4 +- lib/libc/Kconfig | 1 + lib/libc/newlib/libc-hooks.c | 2 + lib/os/fdtable.c | 5 +-- lib/posix/options/CMakeLists.txt | 7 ++-- lib/posix/options/Kconfig | 1 + lib/posix/options/Kconfig.deprecated | 9 +++++ lib/posix/options/Kconfig.fs | 15 ++++--- lib/posix/options/Kconfig.sync_io | 39 +++++++++++++++++++ lib/posix/options/fs.c | 12 ++++++ lib/posix/options/fsync.c | 18 +++++++++ tests/posix/fs/prj.conf | 2 +- tests/posix/headers/prj.conf | 4 +- 16 files changed, 102 insertions(+), 24 deletions(-) create mode 100644 lib/posix/options/Kconfig.sync_io create mode 100644 lib/posix/options/fsync.c diff --git a/doc/services/portability/posix/aep/index.rst b/doc/services/portability/posix/aep/index.rst index ad02c3e4cb8b1..83ff41c5a21a8 100644 --- a/doc/services/portability/posix/aep/index.rst +++ b/doc/services/portability/posix/aep/index.rst @@ -65,7 +65,7 @@ The *Minimal Realtime System Profile* (PSE51) includes all of the :ref:`_POSIX_MEMLOCK_RANGE `, -1, :ref:`_POSIX_MONOTONIC_CLOCK `, 200809L, :kconfig:option:`CONFIG_POSIX_MONOTONIC_CLOCK` :ref:`_POSIX_SHARED_MEMORY_OBJECTS `, -1, - :ref:`_POSIX_SYNCHRONIZED_IO `, -1, + :ref:`_POSIX_SYNCHRONIZED_IO `, -1, :kconfig:option:`CONFIG_POSIX_SYNCHRONIZED_IO` :ref:`_POSIX_THREAD_ATTR_STACKADDR`, 200809L, :kconfig:option:`CONFIG_PTHREAD` :ref:`_POSIX_THREAD_ATTR_STACKSIZE`, 200809L, :kconfig:option:`CONFIG_PTHREAD` :ref:`_POSIX_THREAD_CPUTIME `, 200809L, :kconfig:option:`CONFIG_POSIX_CPUTIME` @@ -103,7 +103,7 @@ The *Realtime Controller System Profile* (PSE52) includes all features from PSE5 :ref:`POSIX_C_LANG_MATH `, yes, :ref:`POSIX_FD_MGMT `,, :kconfig:option:`CONFIG_POSIX_FD_MGMT` - :ref:`POSIX_FILE_SYSTEM `,, + :ref:`POSIX_FILE_SYSTEM `,, :kconfig:option:`CONFIG_POSIX_FILE_SYSTEM` .. csv-table:: PSE52 Option Requirements :header: Symbol, Support, Remarks diff --git a/doc/services/portability/posix/conformance/index.rst b/doc/services/portability/posix/conformance/index.rst index ef0522107d07e..439f12b86d634 100644 --- a/doc/services/portability/posix/conformance/index.rst +++ b/doc/services/portability/posix/conformance/index.rst @@ -94,7 +94,7 @@ POSIX System Interfaces _POSIX_SHARED_MEMORY_OBJECTS, -1, _POSIX_SPAWN, -1, :ref:`†` _POSIX_SPORADIC_SERVER, -1, :ref:`†` - _POSIX_SYNCHRONIZED_IO, -1, + :ref:`_POSIX_SYNCHRONIZED_IO `, -1, :kconfig:option:`CONFIG_POSIX_SYNCHRONIZED_IO` :ref:`_POSIX_THREAD_ATTR_STACKADDR`, 200809L, :kconfig:option:`CONFIG_PTHREAD` :ref:`_POSIX_THREAD_ATTR_STACKSIZE`, 200809L, :kconfig:option:`CONFIG_PTHREAD` :ref:`_POSIX_THREAD_CPUTIME `, 200809L, :kconfig:option:`CONFIG_POSIX_CPUTIME` diff --git a/doc/services/portability/posix/kconfig/index.rst b/doc/services/portability/posix/kconfig/index.rst index 14a77e3a3e7ce..cc2954c00afed 100644 --- a/doc/services/portability/posix/kconfig/index.rst +++ b/doc/services/portability/posix/kconfig/index.rst @@ -21,7 +21,6 @@ implementation of the POSIX API. * :kconfig:option:`CONFIG_NET_SOCKETS` * :kconfig:option:`CONFIG_NET_SOCKETS_POLL_MAX` * :kconfig:option:`CONFIG_POSIX_API` -* :kconfig:option:`CONFIG_POSIX_FS` * :kconfig:option:`CONFIG_ZVFS_OPEN_MAX` * :kconfig:option:`CONFIG_POSIX_OPEN_MAX` * :kconfig:option:`CONFIG_POSIX_RTSIG_MAX` diff --git a/include/zephyr/posix/dirent.h b/include/zephyr/posix/dirent.h index 43c68983ebb73..12f5d44380d9b 100644 --- a/include/zephyr/posix/dirent.h +++ b/include/zephyr/posix/dirent.h @@ -9,7 +9,7 @@ #include #include "posix_types.h" -#ifdef CONFIG_POSIX_FS +#ifdef CONFIG_POSIX_FILE_SYSTEM #include #ifdef __cplusplus @@ -32,6 +32,6 @@ struct dirent *readdir(DIR *dirp); } #endif -#endif /* CONFIG_POSIX_FS */ +#endif /* CONFIG_POSIX_FILE_SYSTEM */ #endif /* ZEPHYR_INCLUDE_POSIX_DIRENT_H_ */ diff --git a/lib/libc/Kconfig b/lib/libc/Kconfig index 062dd875cb0d6..af3230554dd88 100644 --- a/lib/libc/Kconfig +++ b/lib/libc/Kconfig @@ -107,6 +107,7 @@ config NEWLIB_LIBC imply POSIX_DEVICE_IO_ALIAS_READ imply POSIX_DEVICE_IO_ALIAS_WRITE imply POSIX_FD_MGMT_ALIAS_LSEEK + imply POSIX_FILE_SYSTEM_ALIAS_FSTAT help Build with newlib library. The newlib library is expected to be part of the SDK in this case. diff --git a/lib/libc/newlib/libc-hooks.c b/lib/libc/newlib/libc-hooks.c index 048aa97a5beb6..8cbb8f80ab9f1 100644 --- a/lib/libc/newlib/libc-hooks.c +++ b/lib/libc/newlib/libc-hooks.c @@ -23,6 +23,7 @@ #include #include +int _fstat(int fd, struct stat *st); int _read(int fd, void *buf, int nbytes); int _write(int fd, const void *buf, int nbytes); int _open(const char *name, int mode); @@ -272,6 +273,7 @@ int _getpid(void) } __weak FUNC_ALIAS(_getpid, getpid, int); +#ifndef CONFIG_POSIX_FILE_SYSTEM int _fstat(int file, struct stat *st) { st->st_mode = S_IFCHR; diff --git a/lib/os/fdtable.c b/lib/os/fdtable.c index 1770bd008a865..4970fa6fbf2e6 100644 --- a/lib/os/fdtable.c +++ b/lib/os/fdtable.c @@ -349,8 +349,7 @@ int zvfs_close(int fd) return res; } -#ifdef CONFIG_POSIX_FSYNC -int fsync(int fd) +int zvfs_fsync(int fd) { if (_check_fd(fd) < 0) { return -1; @@ -358,8 +357,6 @@ 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 zvfs_lseek(int fd, off_t offset, int whence) { diff --git a/lib/posix/options/CMakeLists.txt b/lib/posix/options/CMakeLists.txt index 9826156fd14b5..e488fe263b20a 100644 --- a/lib/posix/options/CMakeLists.txt +++ b/lib/posix/options/CMakeLists.txt @@ -25,8 +25,8 @@ if(CONFIG_POSIX_SIGNAL) endif() if(CONFIG_POSIX_API OR CONFIG_PTHREAD_IPC OR CONFIG_POSIX_TIMERS OR - CONFIG_POSIX_MESSAGE_PASSING OR CONFIG_POSIX_FS OR CONFIG_EVENTFD OR CONFIG_POSIX_C_LIB_EXT OR - CONFIG_POSIX_SINGLE_PROCESS) + CONFIG_POSIX_MESSAGE_PASSING OR CONFIG_POSIX_FILE_SYSTEM OR CONFIG_EVENTFD OR + CONFIG_POSIX_C_LIB_EXT OR CONFIG_POSIX_SINGLE_PROCESS) # This is a temporary workaround so that Newlib declares the appropriate # types for us. POSIX features to be formalized as part of #51211 zephyr_compile_options($<$:-D_POSIX_THREADS>) @@ -51,7 +51,8 @@ zephyr_library_sources_ifdef(CONFIG_POSIX_DEVICE_IO zephyr_library_sources_ifdef(CONFIG_POSIX_FD_MGMT fd_mgmt.c ) -zephyr_library_sources_ifdef(CONFIG_POSIX_FS fs.c) +zephyr_library_sources_ifdef(CONFIG_POSIX_FILE_SYSTEM fs.c) +zephyr_library_sources_ifdef(CONFIG_POSIX_FSYNC fsync.c) zephyr_library_sources_ifdef(CONFIG_POSIX_MESSAGE_PASSING mqueue.c) zephyr_library_sources_ifdef(CONFIG_POSIX_MULTI_PROCESS sleep.c diff --git a/lib/posix/options/Kconfig b/lib/posix/options/Kconfig index 8e1f0918196e1..49bed90880cb6 100644 --- a/lib/posix/options/Kconfig +++ b/lib/posix/options/Kconfig @@ -44,6 +44,7 @@ rsource "Kconfig.semaphore" rsource "Kconfig.signal" rsource "Kconfig.spinlock" rsource "Kconfig.stropts" +rsource "Kconfig.sync_io" rsource "Kconfig.syslog" rsource "Kconfig.timer" rsource "Kconfig.xsi" diff --git a/lib/posix/options/Kconfig.deprecated b/lib/posix/options/Kconfig.deprecated index f0e143736001a..719105d12bc27 100644 --- a/lib/posix/options/Kconfig.deprecated +++ b/lib/posix/options/Kconfig.deprecated @@ -82,6 +82,15 @@ config POSIX_ENV Please use CONFIG_POSIX_SINGLE_PROCESS instead. +config POSIX_FS + bool "Support for environ, getenv(), getenv_r(), setenv(), and unsetenv() [DEPRECATED]" + select DEPRECATED + select POSIX_FILE_SYSTEM + help + This option is deprecated. + + Please use CONFIG_POSIX_FILE_SYSTEM instead. + config POSIX_LIMITS_RTSIG_MAX int "_POSIX_RTSIG_MAX value in limits.h [DEPRECATED]" default POSIX_RTSIG_MAX if POSIX_REALTIME_SIGNALS diff --git a/lib/posix/options/Kconfig.fs b/lib/posix/options/Kconfig.fs index 35c01cf72a150..663d706e3fb80 100644 --- a/lib/posix/options/Kconfig.fs +++ b/lib/posix/options/Kconfig.fs @@ -2,20 +2,19 @@ # # SPDX-License-Identifier: Apache-2.0 -menuconfig POSIX_FS +menuconfig POSIX_FILE_SYSTEM bool "POSIX file system API support" default y if POSIX_API - depends on FILE_SYSTEM + select FILE_SYSTEM select FDTABLE help This enables POSIX style file system related APIs. -if POSIX_FS +if POSIX_FILE_SYSTEM -config POSIX_FSYNC - bool "Support for fsync()" - default y +config POSIX_FILE_SYSTEM_ALIAS_FSTAT + bool help - This enables fsync() support. + Select 'y' here and Zephyr will provide an alias for fstat() as _fstat(). -endif # POSIX_FS +endif # POSIX_FILE_SYSTEM diff --git a/lib/posix/options/Kconfig.sync_io b/lib/posix/options/Kconfig.sync_io new file mode 100644 index 0000000000000..4575ff06020ae --- /dev/null +++ b/lib/posix/options/Kconfig.sync_io @@ -0,0 +1,39 @@ +# Copyright (c) 2024 Tenstorrent AI ULC +# +# SPDX-License-Identifier: Apache-2.0 + +menu "POSIX synchronized I/O" + +config POSIX_FSYNC + bool "Support for fsync()" + help + Select 'y' here and Zephyr will provide an implementation of fsync(). + + For more information, please see + https://pubs.opengroup.org/onlinepubs/9699919799/functions/fsync.html + + +config POSIX_SYNCHRONIZED_IO + bool "POSIX synchronized I/O" + select POSIX_FSYNC + help + Select 'y' here and Zephyr will provide an implementation of fdatasync(), fsync(), + and msync(). + + For more information, please see + https://pubs.opengroup.org/onlinepubs/9699919799/functions/msync.html + https://pubs.opengroup.org/onlinepubs/9699919799/functions/fdatasync.html + +if POSIX_FSYNC + +# These options are intended to be used for compatibility with external POSIX +# implementations such as those in Newlib or Picolibc. + +config POSIX_FILE_SYSTEM_ALIAS_FSYNC + bool + help + Select 'y' here and Zephyr will provide an alias for fsync() as _fsync(). + +endif # POSIX_FSYNC + +endmenu diff --git a/lib/posix/options/fs.c b/lib/posix/options/fs.c index caec36692d61c..6a572c278f4dd 100644 --- a/lib/posix/options/fs.c +++ b/lib/posix/options/fs.c @@ -429,3 +429,15 @@ int zvfs_ftruncate(int fd, off_t length) return 0; } + +int fstat(int fildes, struct stat *buf) +{ + ARG_UNUSED(fildes); + ARG_UNUSED(buf); + + errno = ENOTSUP; + return -1; +} +#ifdef CONFIG_POSIX_FILE_SYSTEM_ALIAS_FSTAT +FUNC_ALIAS(fstat, _fstat, int); +#endif diff --git a/lib/posix/options/fsync.c b/lib/posix/options/fsync.c new file mode 100644 index 0000000000000..8ec28b4440dc9 --- /dev/null +++ b/lib/posix/options/fsync.c @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2024 Tenstorrent AI ULC + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +/* prototypes for external, not-yet-public, functions in fdtable.c */ +int zvfs_fsync(int fd); + +int fsync(int fd) +{ + return zvfs_fsync(fd); +} +#ifdef CONFIG_POSIX_FILE_SYSTEM_ALIAS_FSYNC +FUNC_ALIAS(fsync, _fsync, int); +#endif diff --git a/tests/posix/fs/prj.conf b/tests/posix/fs/prj.conf index bb6d36b836eb3..da73481ef4d1a 100644 --- a/tests/posix/fs/prj.conf +++ b/tests/posix/fs/prj.conf @@ -2,7 +2,7 @@ CONFIG_FILE_SYSTEM=y CONFIG_LOG=y CONFIG_FAT_FILESYSTEM_ELM=y CONFIG_POSIX_API=y -CONFIG_POSIX_FS=y +CONFIG_POSIX_FILE_SYSTEM=y CONFIG_ZTEST=y CONFIG_MAIN_STACK_SIZE=4096 CONFIG_EVENTFD=n diff --git a/tests/posix/headers/prj.conf b/tests/posix/headers/prj.conf index c785e4592930d..4a75f1ac46f8b 100644 --- a/tests/posix/headers/prj.conf +++ b/tests/posix/headers/prj.conf @@ -1,7 +1,7 @@ CONFIG_POSIX_API=y CONFIG_ZTEST=y -# for POSIX_FS +# for POSIX_FILESYSTEM CONFIG_FILE_SYSTEM=y # for select to work @@ -15,7 +15,7 @@ CONFIG_NET_SOCKETPAIR=y # for when CONFIG_POSIX_API is not selected CONFIG_PTHREAD_IPC=y -CONFIG_POSIX_FS=y +CONFIG_POSIX_FILE_SYSTEM=y CONFIG_POSIX_TIMERS=y CONFIG_POSIX_MESSAGE_PASSING=y CONFIG_EVENTFD=y From 842a7b7ba109196d3338084707bf3795f321b83b Mon Sep 17 00:00:00 2001 From: Chris Friedt Date: Wed, 22 May 2024 20:53:04 -0400 Subject: [PATCH 1740/2849] posix: deprecate SEM_VALUE_MAX and SEM_NAMELEN_MAX This change deprecates CONFIG_SEM_VALUE_MAX in favour of CONFIG_POSIX_SEM_VALUE_MAX which maps directly to _POSIX_SEM_VALUE_MAX. Additionally, we add the Kconfig option CONFIG_POSIX_SEMAPHORES which maps directly to the POSIX Option _POSIX_SEMAPHORES. For consistence, deprecate CONFIG_SEM_NAMELEN_MAX in favour of CONFIG_POSIX_SEM_NAMELEN_MAX. Signed-off-by: Chris Friedt --- .../portability/posix/conformance/index.rst | 2 +- .../portability/posix/kconfig/index.rst | 4 ++- include/zephyr/posix/posix_features.h | 10 ++++--- include/zephyr/posix/sys/sysconf.h | 2 +- lib/posix/options/CMakeLists.txt | 2 +- lib/posix/options/Kconfig.deprecated | 18 +++++++++++++ lib/posix/options/Kconfig.semaphore | 27 ++++++++++++++----- lib/posix/options/semaphore.c | 12 ++++----- tests/posix/common/prj.conf | 2 +- tests/posix/common/src/semaphore.c | 24 ++++++++--------- 10 files changed, 70 insertions(+), 33 deletions(-) diff --git a/doc/services/portability/posix/conformance/index.rst b/doc/services/portability/posix/conformance/index.rst index 439f12b86d634..8408560f3a7a5 100644 --- a/doc/services/portability/posix/conformance/index.rst +++ b/doc/services/portability/posix/conformance/index.rst @@ -68,7 +68,7 @@ POSIX System Interfaces _POSIX_MEMORY_PROTECTION, -1, :ref:`†` :ref:`_POSIX_READER_WRITER_LOCKS`, 200809L, :kconfig:option:`CONFIG_POSIX_READER_WRITER_LOCKS` :ref:`_POSIX_REALTIME_SIGNALS`, -1, - :ref:`_POSIX_SEMAPHORES`, 200809L, :kconfig:option:`CONFIG_PTHREAD_IPC` + :ref:`_POSIX_SEMAPHORES`, 200809L, :kconfig:option:`CONFIG_POSIX_SEMAPHORES` :ref:`_POSIX_SPIN_LOCKS`, 200809L, :kconfig:option:`CONFIG_POSIX_SPIN_LOCKS` :ref:`_POSIX_THREAD_SAFE_FUNCTIONS`, -1, :ref:`_POSIX_THREADS`, -1, :kconfig:option:`CONFIG_PTHREAD_IPC` diff --git a/doc/services/portability/posix/kconfig/index.rst b/doc/services/portability/posix/kconfig/index.rst index cc2954c00afed..be5b2b4e8c798 100644 --- a/doc/services/portability/posix/kconfig/index.rst +++ b/doc/services/portability/posix/kconfig/index.rst @@ -35,5 +35,7 @@ implementation of the POSIX API. * :kconfig:option:`CONFIG_PTHREAD_KEY` * :kconfig:option:`CONFIG_PTHREAD_MUTEX` * :kconfig:option:`CONFIG_PTHREAD_RECYCLER_DELAY_MS` -* :kconfig:option:`CONFIG_SEM_VALUE_MAX` +* :kconfig:option:`CONFIG_POSIX_SEM_NAMELEN_MAX` +* :kconfig:option:`CONFIG_POSIX_SEM_NSEMS_MAX` +* :kconfig:option:`CONFIG_POSIX_SEM_VALUE_MAX` * :kconfig:option:`CONFIG_TIMER_CREATE_WAIT` diff --git a/include/zephyr/posix/posix_features.h b/include/zephyr/posix/posix_features.h index 710c7c8f14835..96d98d0e0f5f6 100644 --- a/include/zephyr/posix/posix_features.h +++ b/include/zephyr/posix/posix_features.h @@ -79,7 +79,7 @@ /* #define _POSIX_REGEXP (-1L) */ /* #define _POSIX_SAVED_IDS (-1L) */ -#ifdef CONFIG_PTHREAD_IPC +#ifdef CONFIG_POSIX_SEMAPHORES #define _POSIX_SEMAPHORES _POSIX_VERSION #endif @@ -217,8 +217,10 @@ #define _POSIX_RE_DUP_MAX (255) #define _POSIX_RTSIG_MAX \ COND_CODE_1(CONFIG_POSIX_REALTIME_SIGNALS, (CONFIG_POSIX_RTSIG_MAX), (0)) -#define _POSIX_SEM_NSEMS_MAX CONFIG_SEM_NAMELEN_MAX -#define _POSIX_SEM_VALUE_MAX CONFIG_SEM_VALUE_MAX +#define _POSIX_SEM_NSEMS_MAX \ + COND_CODE_1(CONFIG_POSIX_SEMAPHORES, (CONFIG_POSIX_SEM_NSEMS_MAX), (0)) +#define _POSIX_SEM_VALUE_MAX \ + COND_CODE_1(CONFIG_POSIX_SEMAPHORES, (CONFIG_POSIX_SEM_VALUE_MAX), (0)) #define _POSIX_SIGQUEUE_MAX (32) #define _POSIX_SSIZE_MAX (32767) #define _POSIX_SS_REPL_MAX (4) @@ -284,7 +286,7 @@ #define PTHREAD_THREADS_MAX _POSIX_THREAD_THREADS_MAX #define RTSIG_MAX _POSIX_RTSIG_MAX #define SEM_NSEMS_MAX _POSIX_SEM_NSEMS_MAX -#define SEM_VALUE_MAX CONFIG_SEM_VALUE_MAX +#define SEM_VALUE_MAX _POSIX_SEM_VALUE_MAX #define SIGQUEUE_MAX _POSIX_SIGQUEUE_MAX #define STREAM_MAX _POSIX_STREAM_MAX #define SYMLOOP_MAX _POSIX_SYMLOOP_MAX diff --git a/include/zephyr/posix/sys/sysconf.h b/include/zephyr/posix/sys/sysconf.h index d90f13580e5ff..bc640938f38a3 100644 --- a/include/zephyr/posix/sys/sysconf.h +++ b/include/zephyr/posix/sys/sysconf.h @@ -173,7 +173,7 @@ enum { #define __z_posix_sysconf_SC_REGEXP (-1L) #define __z_posix_sysconf_SC_SAVED_IDS (-1L) #define __z_posix_sysconf_SC_SEMAPHORES \ - COND_CODE_1(CONFIG_PTHREAD_IPC, (_POSIX_SEMAPHORES), (-1L)) + COND_CODE_1(CONFIG_POSIX_SEMAPHORES, (_POSIX_SEMAPHORES), (-1L)) #define __z_posix_sysconf_SC_SHARED_MEMORY_OBJECTS (-1L) #define __z_posix_sysconf_SC_SHELL (-1L) #define __z_posix_sysconf_SC_SPAWN (-1L) diff --git a/lib/posix/options/CMakeLists.txt b/lib/posix/options/CMakeLists.txt index e488fe263b20a..dcc850da084ce 100644 --- a/lib/posix/options/CMakeLists.txt +++ b/lib/posix/options/CMakeLists.txt @@ -79,7 +79,7 @@ zephyr_library_sources_ifdef(CONFIG_PTHREAD_MUTEX mutex.c) zephyr_library_sources_ifdef(CONFIG_PTHREAD pthread.c) zephyr_library_sources_ifdef(CONFIG_POSIX_PRIORITY_SCHEDULING sched.c) zephyr_library_sources_ifdef(CONFIG_POSIX_READER_WRITER_LOCKS rwlock.c) -zephyr_library_sources_ifdef(CONFIG_PTHREAD_IPC semaphore.c) +zephyr_library_sources_ifdef(CONFIG_POSIX_SEMAPHORES semaphore.c) zephyr_library_sources_ifdef(CONFIG_GETOPT_LONG getopt/getopt_long.c diff --git a/lib/posix/options/Kconfig.deprecated b/lib/posix/options/Kconfig.deprecated index 719105d12bc27..5c354268cdcd4 100644 --- a/lib/posix/options/Kconfig.deprecated +++ b/lib/posix/options/Kconfig.deprecated @@ -192,4 +192,22 @@ config TIMER_DELAYTIMER_MAX Please use CONFIG_POSIX_DELAYTIMER_MAX instead. +config SEM_NAMELEN_MAX + int "Maximum name length [DEPRECATED]" + default POSIX_SEM_NAMELEN_MAX if POSIX_SEMAPHORES + default 0 + help + This option is deprecated. + + Please use CONFIG_POSIX_SEM_NAMELEN_MAX instead. + +config SEM_VALUE_MAX + int "Maximum semaphore limit [DEPRECATED]" + default POSIX_SEM_VALUE_MAX if POSIX_SEMAPHORES + default 0 + help + This option is deprecated. + + Please use CONFIG_POSIX_SEM_VALUE_MAX instead. + endmenu diff --git a/lib/posix/options/Kconfig.semaphore b/lib/posix/options/Kconfig.semaphore index 53fb030736b01..231565f3258a2 100644 --- a/lib/posix/options/Kconfig.semaphore +++ b/lib/posix/options/Kconfig.semaphore @@ -2,21 +2,36 @@ # # SPDX-License-Identifier: Apache-2.0 -menu "sem_t support" +menuconfig POSIX_SEMAPHORES + bool "POSIX semaphore support" + default y if POSIX_API + help + Enable this option for POSIX semaphore support. + +if POSIX_SEMAPHORES -config SEM_VALUE_MAX - int "Maximum semaphore limit" +config POSIX_SEM_VALUE_MAX + int "Maximum semaphore value" default 32767 range 1 32767 help Maximum semaphore count in POSIX compliant Application. -config SEM_NAMELEN_MAX - int "Maximum name length" +config POSIX_SEM_NSEMS_MAX + int "Maximum number of semaphores" + default 256 + help + Maximum number of semaphores in a POSIX application. + + Note: currently, in Zephyr, this only limits the number of named semaphores (i.e. those + created via sem_open()). + +config POSIX_SEM_NAMELEN_MAX + int "Maximum semaphore name length" default 16 range 2 255 help Maximum length of name for a named semaphore. The max value of 255 corresponds to {NAME_MAX}. -endmenu # "sem_t support" +endif # POSIX_SEMAPHORES diff --git a/lib/posix/options/semaphore.c b/lib/posix/options/semaphore.c index 45cac48372f8d..fddad0caf6b20 100644 --- a/lib/posix/options/semaphore.c +++ b/lib/posix/options/semaphore.c @@ -120,7 +120,7 @@ int sem_getvalue(sem_t *semaphore, int *value) */ int sem_init(sem_t *semaphore, int pshared, unsigned int value) { - if (value > CONFIG_SEM_VALUE_MAX) { + if (value > CONFIG_POSIX_SEM_VALUE_MAX) { errno = EINVAL; return -1; } @@ -131,7 +131,7 @@ int sem_init(sem_t *semaphore, int pshared, unsigned int value) */ __ASSERT(pshared == 0, "pshared should be 0"); - k_sem_init(semaphore, value, CONFIG_SEM_VALUE_MAX); + k_sem_init(semaphore, value, CONFIG_POSIX_SEM_VALUE_MAX); return 0; } @@ -232,7 +232,7 @@ sem_t *sem_open(const char *name, int oflags, ...) value = va_arg(va, unsigned int); va_end(va); - if (value > CONFIG_SEM_VALUE_MAX) { + if (value > CONFIG_POSIX_SEM_VALUE_MAX) { errno = EINVAL; return (sem_t *)SEM_FAILED; } @@ -243,7 +243,7 @@ sem_t *sem_open(const char *name, int oflags, ...) } namelen = strlen(name); - if ((namelen + 1) > CONFIG_SEM_NAMELEN_MAX) { + if ((namelen + 1) > CONFIG_POSIX_SEM_NAMELEN_MAX) { errno = ENAMETOOLONG; return (sem_t *)SEM_FAILED; } @@ -291,7 +291,7 @@ sem_t *sem_open(const char *name, int oflags, ...) /* 1 for this open instance, +1 for the linked name */ nsem->ref_count = 2; - (void)k_sem_init(&nsem->sem, value, CONFIG_SEM_VALUE_MAX); + (void)k_sem_init(&nsem->sem, value, CONFIG_POSIX_SEM_VALUE_MAX); sys_slist_append(&nsem_list, (sys_snode_t *)&(nsem->snode)); @@ -318,7 +318,7 @@ int sem_unlink(const char *name) return -1; } - if ((strlen(name) + 1) > CONFIG_SEM_NAMELEN_MAX) { + if ((strlen(name) + 1) > CONFIG_POSIX_SEM_NAMELEN_MAX) { errno = ENAMETOOLONG; return -1; } diff --git a/tests/posix/common/prj.conf b/tests/posix/common/prj.conf index 5c5613d0e68ed..1c99d64cf5a17 100644 --- a/tests/posix/common/prj.conf +++ b/tests/posix/common/prj.conf @@ -2,7 +2,7 @@ CONFIG_PTHREAD_IPC=y CONFIG_POSIX_API=y CONFIG_MAX_PTHREAD_COUNT=6 CONFIG_ZTEST=y -CONFIG_SEM_VALUE_MAX=32767 +CONFIG_POSIX_SEM_VALUE_MAX=32767 CONFIG_POSIX_MESSAGE_PASSING=y CONFIG_POSIX_PRIORITY_SCHEDULING=y CONFIG_HEAP_MEM_POOL_SIZE=4096 diff --git a/tests/posix/common/src/semaphore.c b/tests/posix/common/src/semaphore.c index a1f15cf5c5d97..f9cfe8e8c9460 100644 --- a/tests/posix/common/src/semaphore.c +++ b/tests/posix/common/src/semaphore.c @@ -28,10 +28,10 @@ static void semaphore_test(sem_t *sem) struct timespec abstime; /* TESTPOINT: Check if sema value is less than - * CONFIG_SEM_VALUE_MAX + * CONFIG_POSIX_SEM_VALUE_MAX */ - zassert_equal(sem_init(sem, 0, (CONFIG_SEM_VALUE_MAX + 1)), -1, - "value larger than %d\n", CONFIG_SEM_VALUE_MAX); + zassert_equal(sem_init(sem, 0, (CONFIG_POSIX_SEM_VALUE_MAX + 1)), -1, + "value larger than %d\n", CONFIG_POSIX_SEM_VALUE_MAX); zassert_equal(errno, EINVAL); zassert_equal(sem_init(sem, 0, 0), 0, "sem_init failed"); @@ -158,8 +158,8 @@ ZTEST(semaphore, test_named_semaphore) zassert_equal_ptr(sem1, SEM_FAILED); zassert_equal(nsem_get_list_len(), 0); - /* Name exceeds CONFIG_SEM_NAMELEN_MAX */ - char name_too_long[CONFIG_SEM_NAMELEN_MAX + 2]; + /* Name exceeds CONFIG_POSIX_SEM_NAMELEN_MAX */ + char name_too_long[CONFIG_POSIX_SEM_NAMELEN_MAX + 2]; for (size_t i = 0; i < sizeof(name_too_long) - 1; i++) { name_too_long[i] = 'a'; @@ -168,12 +168,12 @@ ZTEST(semaphore, test_named_semaphore) sem1 = sem_open(name_too_long, 0, 0, 0); zassert_equal(errno, ENAMETOOLONG, "\"%s\" should be longer than %d", name_too_long, - CONFIG_SEM_NAMELEN_MAX); + CONFIG_POSIX_SEM_NAMELEN_MAX); zassert_equal_ptr(sem1, SEM_FAILED); zassert_equal(nsem_get_list_len(), 0); - /* `value` greater than CONFIG_SEM_VALUE_MAX */ - sem1 = sem_open("sem1", O_CREAT, 0, (CONFIG_SEM_VALUE_MAX + 1)); + /* `value` greater than CONFIG_POSIX_SEM_VALUE_MAX */ + sem1 = sem_open("sem1", O_CREAT, 0, (CONFIG_POSIX_SEM_VALUE_MAX + 1)); zassert_equal(errno, EINVAL); zassert_equal_ptr(sem1, SEM_FAILED); zassert_equal(nsem_get_list_len(), 0); @@ -238,13 +238,13 @@ ZTEST(semaphore, test_named_semaphore) zassert_equal(errno, ENOENT); zassert_equal(nsem_get_list_len(), 2); - /* Name exceeds CONFIG_SEM_NAMELEN_MAX */ - char long_sem_name[CONFIG_SEM_NAMELEN_MAX + 2]; + /* Name exceeds CONFIG_POSIX_SEM_NAMELEN_MAX */ + char long_sem_name[CONFIG_POSIX_SEM_NAMELEN_MAX + 2]; - for (int i = 0; i < CONFIG_SEM_NAMELEN_MAX + 1; i++) { + for (int i = 0; i < CONFIG_POSIX_SEM_NAMELEN_MAX + 1; i++) { long_sem_name[i] = 'a'; } - long_sem_name[CONFIG_SEM_NAMELEN_MAX + 1] = '\0'; + long_sem_name[CONFIG_POSIX_SEM_NAMELEN_MAX + 1] = '\0'; zassert_equal(sem_unlink(long_sem_name), -1); zassert_equal(errno, ENAMETOOLONG); From 23f9119176cd14e84f3ae92a97a815665ea074a1 Mon Sep 17 00:00:00 2001 From: Chris Friedt Date: Wed, 22 May 2024 21:02:26 -0400 Subject: [PATCH 1741/2849] doc: posix: add kconfig link for async io Update documentation so that there is a link to CONFIG_POSIX_ASYNCHRONOUS_IO as it was previously missing. Signed-off-by: Chris Friedt --- doc/services/portability/posix/conformance/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/services/portability/posix/conformance/index.rst b/doc/services/portability/posix/conformance/index.rst index 8408560f3a7a5..9eb2e0ae19104 100644 --- a/doc/services/portability/posix/conformance/index.rst +++ b/doc/services/portability/posix/conformance/index.rst @@ -61,7 +61,7 @@ POSIX System Interfaces :widths: 50, 10, 50 _POSIX_VERSION, 200809L, - :ref:`_POSIX_ASYNCHRONOUS_IO`, 200809L, :ref:`†` + :ref:`_POSIX_ASYNCHRONOUS_IO`, 200809L, :kconfig:option:`CONFIG_POSIX_ASYNCHRONOUS_IO`:ref:`†` :ref:`_POSIX_BARRIERS`, 200809L, :kconfig:option:`CONFIG_POSIX_BARRIERS` :ref:`_POSIX_CLOCK_SELECTION`, 200809L, :kconfig:option:`CONFIG_POSIX_CLOCK_SELECTION` _POSIX_MAPPED_FILES, -1, :ref:`†` From 0711d603f7c856d4d2ef915db940ea4ee064e25c Mon Sep 17 00:00:00 2001 From: Chris Friedt Date: Wed, 22 May 2024 21:39:21 -0400 Subject: [PATCH 1742/2849] posix: deprecate POSIX_SYSLOG for XSI_SYSTEM_LOGGING This change deprecates the CONFIG_POSIX_SYSLOG Kconfig variable for CONFIG_XSI_SYSTEM_LOGGING, which has a direct mapping to the POSIX Option Group XSI_SYSTEM_LOGGING. Signed-off-by: Chris Friedt --- .../portability/posix/option_groups/index.rst | 14 ++++++++++++++ lib/posix/options/CMakeLists.txt | 1 + lib/posix/options/Kconfig | 1 - lib/posix/options/Kconfig.deprecated | 9 +++++++++ lib/posix/options/Kconfig.syslog | 10 ---------- lib/posix/options/Kconfig.xsi | 10 ++++++++++ 6 files changed, 34 insertions(+), 11 deletions(-) delete mode 100644 lib/posix/options/Kconfig.syslog diff --git a/doc/services/portability/posix/option_groups/index.rst b/doc/services/portability/posix/option_groups/index.rst index a2c316a6928c6..29c129868bedc 100644 --- a/doc/services/portability/posix/option_groups/index.rst +++ b/doc/services/portability/posix/option_groups/index.rst @@ -102,6 +102,20 @@ This table lists service support status in Zephyr: pthread_getconcurrency(),yes pthread_setconcurrency(),yes +.. _posix_option_group_xsi_system_logging: + +XSI_SYSTEM_LOGGING +================== + +.. csv-table:: XSI_SYSTEM_LOGGING + :header: API, Supported + :widths: 50,10 + + closelog(),yes + openlog(),yes + setlogmask(),yes + syslog(),yes + .. _posix_option_group_c_lang_jump: POSIX_C_LANG_JUMP diff --git a/lib/posix/options/CMakeLists.txt b/lib/posix/options/CMakeLists.txt index dcc850da084ce..f416ad3bf4e17 100644 --- a/lib/posix/options/CMakeLists.txt +++ b/lib/posix/options/CMakeLists.txt @@ -80,6 +80,7 @@ zephyr_library_sources_ifdef(CONFIG_PTHREAD pthread.c) zephyr_library_sources_ifdef(CONFIG_POSIX_PRIORITY_SCHEDULING sched.c) zephyr_library_sources_ifdef(CONFIG_POSIX_READER_WRITER_LOCKS rwlock.c) zephyr_library_sources_ifdef(CONFIG_POSIX_SEMAPHORES semaphore.c) +zephyr_library_sources_ifdef(CONFIG_XSI_SYSTEM_LOGGING syslog.c) zephyr_library_sources_ifdef(CONFIG_GETOPT_LONG getopt/getopt_long.c diff --git a/lib/posix/options/Kconfig b/lib/posix/options/Kconfig index 49bed90880cb6..3b10f4a6614fa 100644 --- a/lib/posix/options/Kconfig +++ b/lib/posix/options/Kconfig @@ -45,7 +45,6 @@ rsource "Kconfig.signal" rsource "Kconfig.spinlock" rsource "Kconfig.stropts" rsource "Kconfig.sync_io" -rsource "Kconfig.syslog" rsource "Kconfig.timer" rsource "Kconfig.xsi" diff --git a/lib/posix/options/Kconfig.deprecated b/lib/posix/options/Kconfig.deprecated index 5c354268cdcd4..524c45edef1a9 100644 --- a/lib/posix/options/Kconfig.deprecated +++ b/lib/posix/options/Kconfig.deprecated @@ -138,6 +138,15 @@ config POSIX_SYSCONF Please use CONFIG_POSIX_SINGLE_PROCESS instead. +config POSIX_SYSLOG + bool "Support for syslog() [DEPRECATED]" + select DEPRECATED + select XSI_SYSTEM_LOGGING + help + This option is deprecated. + + Please use CONFIG_XSI_SYSTEM_LOGGING instead. + config POSIX_UNAME bool "Support for uname [DEPRECATED]" select DEPRECATED diff --git a/lib/posix/options/Kconfig.syslog b/lib/posix/options/Kconfig.syslog deleted file mode 100644 index 1fedd93cddf7c..0000000000000 --- a/lib/posix/options/Kconfig.syslog +++ /dev/null @@ -1,10 +0,0 @@ -# Copyright (c) 2024, Meta -# -# SPDX-License-Identifier: Apache-2.0 - -config POSIX_SYSLOG - bool "Support for syslog()" - default y if POSIX_API - help - This option provides support for closelog(), openlog(), syslog(), - setlogmask(), and vsyslog(). diff --git a/lib/posix/options/Kconfig.xsi b/lib/posix/options/Kconfig.xsi index 5124e9eb8c781..6fa10578c216c 100644 --- a/lib/posix/options/Kconfig.xsi +++ b/lib/posix/options/Kconfig.xsi @@ -13,3 +13,13 @@ config XSI_SINGLE_PROCESS For more information, please see https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_subprofiles.html + +config XSI_SYSTEM_LOGGING + bool "X/Open system logging" + default y if POSIX_API + help + This option provides support for closelog(), openlog(), syslog(), + setlogmask(), and vsyslog(). + + For more information, please see + https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_subprofiles.html From 2f2cad742effdbf98a2a83521aac6a1f891453af Mon Sep 17 00:00:00 2001 From: Chris Friedt Date: Wed, 22 May 2024 23:00:40 -0400 Subject: [PATCH 1743/2849] posix: deprecate POSIX_PUTMSG for XOPEN_STREAMS This change deprecates CONFIG_POSIX_PUTMSG and introduces a new Kconfig option CONFIG_XOPEN_STREAMS which maps directly to the standard POSIX Option, _XOPEN_STREAMS. Signed-off-by: Chris Friedt --- .../portability/posix/conformance/index.rst | 2 +- include/zephyr/posix/posix_features.h | 2 +- include/zephyr/posix/sys/sysconf.h | 3 ++- lib/posix/options/CMakeLists.txt | 2 +- lib/posix/options/Kconfig | 1 - lib/posix/options/Kconfig.deprecated | 9 +++++++++ lib/posix/options/Kconfig.stropts | 9 --------- lib/posix/options/Kconfig.xsi | 14 ++++++++++++++ 8 files changed, 28 insertions(+), 14 deletions(-) delete mode 100644 lib/posix/options/Kconfig.stropts diff --git a/doc/services/portability/posix/conformance/index.rst b/doc/services/portability/posix/conformance/index.rst index 9eb2e0ae19104..6a11f4d9172f9 100644 --- a/doc/services/portability/posix/conformance/index.rst +++ b/doc/services/portability/posix/conformance/index.rst @@ -111,7 +111,7 @@ POSIX System Interfaces _XOPEN_CRYPT, -1, _XOPEN_REALTIME, -1, _XOPEN_REALTIME_THREADS, -1, - :ref:`_XOPEN_STREAMS`, -1, :ref:`†` + :ref:`_XOPEN_STREAMS`, 200809L, :kconfig:option:`CONFIG_XOPEN_STREAMS` _XOPEN_UNIX, -1, POSIX Shell and Utilities diff --git a/include/zephyr/posix/posix_features.h b/include/zephyr/posix/posix_features.h index 96d98d0e0f5f6..d95ebf5494877 100644 --- a/include/zephyr/posix/posix_features.h +++ b/include/zephyr/posix/posix_features.h @@ -186,7 +186,7 @@ /* #define _XOPEN_REALTIME (-1L) */ /* #define _XOPEN_REALTIME_THREADS (-1L) */ /* #define _XOPEN_SHM (-1L) */ -/* #define _XOPEN_STREAMS (-1L) */ +#define _XOPEN_STREAMS COND_CODE_1(CONFIG_XOPEN_STREAMS, (_XOPEN_VERSION), (-1)) /* #define _XOPEN_UNIX (-1L) */ /* #define _XOPEN_UUCP (-1L) */ diff --git a/include/zephyr/posix/sys/sysconf.h b/include/zephyr/posix/sys/sysconf.h index bc640938f38a3..812f3bf8c717b 100644 --- a/include/zephyr/posix/sys/sysconf.h +++ b/include/zephyr/posix/sys/sysconf.h @@ -249,7 +249,8 @@ enum { #define __z_posix_sysconf_SC_XOPEN_REALTIME (-1L) #define __z_posix_sysconf_SC_XOPEN_REALTIME_THREADS (-1L) #define __z_posix_sysconf_SC_XOPEN_SHM (-1L) -#define __z_posix_sysconf_SC_XOPEN_STREAMS (-1L) +#define __z_posix_sysconf_SC_XOPEN_STREAMS \ + COND_CODE_1(CONFIG_XOPEN_STREAMS, (_POSIX_XOPEN_STREAMS), (-1)) #define __z_posix_sysconf_SC_XOPEN_UNIX (-1L) #define __z_posix_sysconf_SC_XOPEN_UUCP (-1L) #define __z_posix_sysconf_SC_XOPEN_VERSION _XOPEN_VERSION diff --git a/lib/posix/options/CMakeLists.txt b/lib/posix/options/CMakeLists.txt index f416ad3bf4e17..443c0ad018243 100644 --- a/lib/posix/options/CMakeLists.txt +++ b/lib/posix/options/CMakeLists.txt @@ -58,7 +58,6 @@ zephyr_library_sources_ifdef(CONFIG_POSIX_MULTI_PROCESS sleep.c ) zephyr_library_sources_ifdef(CONFIG_POSIX_NETWORKING net.c) -zephyr_library_sources_ifdef(CONFIG_POSIX_PUTMSG stropts.c) zephyr_library_sources_ifdef(CONFIG_POSIX_SIGNAL signal.c ${STRSIGNAL_TABLE_H}) zephyr_library_sources_ifdef(CONFIG_POSIX_SINGLE_PROCESS confstr.c @@ -80,6 +79,7 @@ zephyr_library_sources_ifdef(CONFIG_PTHREAD pthread.c) zephyr_library_sources_ifdef(CONFIG_POSIX_PRIORITY_SCHEDULING sched.c) zephyr_library_sources_ifdef(CONFIG_POSIX_READER_WRITER_LOCKS rwlock.c) zephyr_library_sources_ifdef(CONFIG_POSIX_SEMAPHORES semaphore.c) +zephyr_library_sources_ifdef(CONFIG_XOPEN_STREAMS stropts.c) zephyr_library_sources_ifdef(CONFIG_XSI_SYSTEM_LOGGING syslog.c) zephyr_library_sources_ifdef(CONFIG_GETOPT_LONG diff --git a/lib/posix/options/Kconfig b/lib/posix/options/Kconfig index 3b10f4a6614fa..43c9330556774 100644 --- a/lib/posix/options/Kconfig +++ b/lib/posix/options/Kconfig @@ -43,7 +43,6 @@ rsource "Kconfig.sched" rsource "Kconfig.semaphore" rsource "Kconfig.signal" rsource "Kconfig.spinlock" -rsource "Kconfig.stropts" rsource "Kconfig.sync_io" rsource "Kconfig.timer" rsource "Kconfig.xsi" diff --git a/lib/posix/options/Kconfig.deprecated b/lib/posix/options/Kconfig.deprecated index 524c45edef1a9..54564d7891fa9 100644 --- a/lib/posix/options/Kconfig.deprecated +++ b/lib/posix/options/Kconfig.deprecated @@ -129,6 +129,15 @@ config POSIX_MQUEUE Please use CONFIG_POSIX_MESSAGE_PASSING instead. +config POSIX_PUTMSG + bool "Support for putmsg function [DEPRECATED]" + select DEPRECATED + select XOPEN_STREAMS + help + This option is deprecated. + + Please use CONFIG_XOPEN_STREAMS instead. + config POSIX_SYSCONF bool "Support for sysconf() [DEPRECATED]" select DEPRECATED diff --git a/lib/posix/options/Kconfig.stropts b/lib/posix/options/Kconfig.stropts deleted file mode 100644 index 347f0f33c150a..0000000000000 --- a/lib/posix/options/Kconfig.stropts +++ /dev/null @@ -1,9 +0,0 @@ -# copyright (c) 2024 Abhinav Srivastava -# -# SPDX-License-Identifier: Apache-2.0 - -config POSIX_PUTMSG - bool "Support for putmsg function" - default y if POSIX_API - help - This option provides support for the putmsg function used in message passing. diff --git a/lib/posix/options/Kconfig.xsi b/lib/posix/options/Kconfig.xsi index 6fa10578c216c..9de3628a31f9e 100644 --- a/lib/posix/options/Kconfig.xsi +++ b/lib/posix/options/Kconfig.xsi @@ -2,6 +2,8 @@ # # SPDX-License-Identifier: Apache-2.0 +menu "X/Open system interfaces" + config XSI_SINGLE_PROCESS bool "X/Open single process" default y if POSIX_API @@ -14,6 +16,16 @@ config XSI_SINGLE_PROCESS For more information, please see https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_subprofiles.html +config XOPEN_STREAMS + bool "X/Open streams" + default y if POSIX_API + help + This option provides support for the X/Open Streams interface, including functions such as + fattach(), fdetach(), getmsg(), getpmsg(), putmsg(), and putpmsg(). + + For more information, please see + https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap02.html#tag_02_01_05_09 + config XSI_SYSTEM_LOGGING bool "X/Open system logging" default y if POSIX_API @@ -23,3 +35,5 @@ config XSI_SYSTEM_LOGGING For more information, please see https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_subprofiles.html + +endmenu From fcebe600909a61723dc0478abc429a926e1bc8fe Mon Sep 17 00:00:00 2001 From: Chris Friedt Date: Wed, 22 May 2024 23:48:17 -0400 Subject: [PATCH 1744/2849] posix: deprecate PTHREAD_IPC _MUTEX _COND and _KEY Zephyr's POSIX API is moving toward using the standard nomenclature from IEEE 1003.1-2017 for as much as possible. In particular, we want to have consistent naming between Zephyr's POSIX API Kconfig options and the naming for POSIX Options and Option Groups. The Kconfig option CONFIG_PTHREAD_IPC has been (ab)used for a very long time for a variety of different purposes. However, the standard Option / feature test macro for POSIX Threads is, intuitively _POSIX_THREADS. There is a corresponding sysconf() key named _SC_POSIX_THREADS. Annoyingly, the POSIX Option Group that corresponds to the Option is POSIX_THREADS_BASE, which is a minor inconsistency in the standard. The _POSIX_THREADS Option already includes mutexes, condition variables, and thread-specific storage (keys). So with this change, we also deprecate the redundant Kconfig variables that do not have a corresponding match in the standard. - CONFIG_PTHREAD_IPC - CONFIG_PTHREAD - CONFIG_PTHREAD_COND - CONFIG_PTHREAD_MUTEX - CONFIG_PTHREAD_KEY Additionally, create Kconfig variables for those configurables which we are lacking: - CONFIG_POSIX_THREADS_EXT - CONFIG_POSIX_THREAD_ATTR_STACKSIZE - CONFIG_POSIX_THREAD_ATTR_STACKADDR - CONFIG_POSIX_THREAD_PRIORITY_SCHEDULING - CONFIG_POSIX_THREAD_PRIO_INHERIT - CONFIG_POSIX_THREAD_PRIO_PROTECT - CONFIG_POSIX_THREAD_SAFE_FUNCTIONS Some Kconfig variables were renamed to more properly match the spec: - CONFIG_MAX_PTHREAD_COUNT -> CONFIG_POSIX_THREAD_THREADS_MAX - CONFIG_MAX_PTHREAD_KEY_COUNT -> CONFIG_POSIX_THREAD_KEYS_MAX Signed-off-by: Chris Friedt --- doc/services/portability/posix/aep/index.rst | 13 +- .../portability/posix/conformance/index.rst | 18 +-- .../portability/posix/kconfig/index.rst | 13 +- .../portability/posix/option_groups/index.rst | 28 ++++ .../portability/posix/overview/index.rst | 3 +- include/zephyr/posix/posix_features.h | 24 +-- include/zephyr/posix/pthread.h | 4 +- include/zephyr/posix/sys/sysconf.h | 14 +- lib/posix/options/CMakeLists.txt | 14 +- lib/posix/options/Kconfig | 12 -- lib/posix/options/Kconfig.cond | 9 -- lib/posix/options/Kconfig.deprecated | 64 ++++++++ lib/posix/options/Kconfig.key | 9 -- lib/posix/options/Kconfig.mutex | 9 -- lib/posix/options/Kconfig.pthread | 142 +++++++++++++++++- lib/posix/options/Kconfig.sched | 4 +- .../options/Kconfig.template.pooled_ipc_type | 29 ---- .../options/Kconfig.template.pooled_type | 25 --- .../options/Kconfig.template.with_logging | 7 - lib/posix/options/Kconfig.template.with_url | 5 - lib/posix/options/Kconfig.xsi | 10 ++ lib/posix/options/key.c | 6 +- lib/posix/options/pthread.c | 24 ++- lib/posix/options/pthread_sched.h | 24 +++ lib/posix/options/rwlock.c | 2 +- lib/posix/options/sched.c | 17 +-- .../{_common.c => timespec_to_timeout.c} | 2 - modules/Kconfig.simplelink | 4 +- samples/posix/philosophers/prj.conf | 2 +- samples/posix/philosophers/src/main.c | 6 +- tests/posix/common/prj.conf | 3 +- tests/posix/common/src/key.c | 6 +- tests/posix/common/src/pthread.c | 2 +- tests/posix/common/src/sysconf.c | 2 +- tests/posix/headers/prj.conf | 2 +- tests/posix/pthread_pressure/src/main.c | 2 +- 36 files changed, 349 insertions(+), 211 deletions(-) delete mode 100644 lib/posix/options/Kconfig.cond delete mode 100644 lib/posix/options/Kconfig.key delete mode 100644 lib/posix/options/Kconfig.mutex delete mode 100644 lib/posix/options/Kconfig.template.pooled_ipc_type delete mode 100644 lib/posix/options/Kconfig.template.pooled_type delete mode 100644 lib/posix/options/Kconfig.template.with_logging delete mode 100644 lib/posix/options/Kconfig.template.with_url rename lib/posix/options/{_common.c => timespec_to_timeout.c} (92%) diff --git a/doc/services/portability/posix/aep/index.rst b/doc/services/portability/posix/aep/index.rst index 83ff41c5a21a8..6c7ff33de6870 100644 --- a/doc/services/portability/posix/aep/index.rst +++ b/doc/services/portability/posix/aep/index.rst @@ -53,8 +53,7 @@ The *Minimal Realtime System Profile* (PSE51) includes all of the :ref:`POSIX_DEVICE_IO `,, :kconfig:option:`CONFIG_POSIX_DEVICE_IO` :ref:`POSIX_SIGNALS `,, :ref:`POSIX_SINGLE_PROCESS `, yes, :kconfig:option:`CONFIG_POSIX_SINGLE_PROCESS` - :ref:`POSIX_THREADS_BASE `, yes, - :ref:`XSI_THREADS_EXT `, yes, + :ref:`XSI_THREADS_EXT `, yes, :kconfig:option:`CONFIG_XSI_THREADS_EXT` .. csv-table:: PSE51 Option Requirements :header: Symbol, Support, Remarks @@ -66,12 +65,12 @@ The *Minimal Realtime System Profile* (PSE51) includes all of the :ref:`_POSIX_MONOTONIC_CLOCK `, 200809L, :kconfig:option:`CONFIG_POSIX_MONOTONIC_CLOCK` :ref:`_POSIX_SHARED_MEMORY_OBJECTS `, -1, :ref:`_POSIX_SYNCHRONIZED_IO `, -1, :kconfig:option:`CONFIG_POSIX_SYNCHRONIZED_IO` - :ref:`_POSIX_THREAD_ATTR_STACKADDR`, 200809L, :kconfig:option:`CONFIG_PTHREAD` - :ref:`_POSIX_THREAD_ATTR_STACKSIZE`, 200809L, :kconfig:option:`CONFIG_PTHREAD` + :ref:`_POSIX_THREAD_ATTR_STACKADDR`, 200809L, :kconfig:option:`CONFIG_POSIX_THREAD_ATTR_STACKADDR` + :ref:`_POSIX_THREAD_ATTR_STACKSIZE`, 200809L, :kconfig:option:`CONFIG_POSIX_THREAD_ATTR_STACKSIZE` :ref:`_POSIX_THREAD_CPUTIME `, 200809L, :kconfig:option:`CONFIG_POSIX_CPUTIME` - _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` + :ref:`_POSIX_THREAD_PRIO_INHERIT `, 200809L, :kconfig:option:`CONFIG_POSIX_THREAD_PRIO_INHERIT` + :ref:`_POSIX_THREAD_PRIO_PROTECT `, -1, :kconfig:option:`CONFIG_POSIX_THREAD_PRIO_PROTECT` + :ref:`_POSIX_THREAD_PRIORITY_SCHEDULING `, 200809L, :kconfig:option:`CONFIG_POSIX_THREAD_PRIORITY_SCHEDULING` _POSIX_THREAD_SPORADIC_SERVER, -1, .. _posix_aep_pse52: diff --git a/doc/services/portability/posix/conformance/index.rst b/doc/services/portability/posix/conformance/index.rst index 6a11f4d9172f9..81a2dfc90e475 100644 --- a/doc/services/portability/posix/conformance/index.rst +++ b/doc/services/portability/posix/conformance/index.rst @@ -70,8 +70,8 @@ POSIX System Interfaces :ref:`_POSIX_REALTIME_SIGNALS`, -1, :ref:`_POSIX_SEMAPHORES`, 200809L, :kconfig:option:`CONFIG_POSIX_SEMAPHORES` :ref:`_POSIX_SPIN_LOCKS`, 200809L, :kconfig:option:`CONFIG_POSIX_SPIN_LOCKS` - :ref:`_POSIX_THREAD_SAFE_FUNCTIONS`, -1, - :ref:`_POSIX_THREADS`, -1, :kconfig:option:`CONFIG_PTHREAD_IPC` + :ref:`_POSIX_THREAD_SAFE_FUNCTIONS`, -1, :kconfig:option:`CONFIG_POSIX_THREAD_SAFE_FUNCTIONS` + :ref:`_POSIX_THREADS`, -1, :kconfig:option:`CONFIG_POSIX_THREADS` :ref:`_POSIX_TIMEOUTS`, 200809L, :kconfig:option:`CONFIG_POSIX_TIMEOUTS` :ref:`_POSIX_TIMERS`, 200809L, :kconfig:option:`CONFIG_POSIX_TIMERS` _POSIX2_C_BIND, 200809L, @@ -95,12 +95,12 @@ POSIX System Interfaces _POSIX_SPAWN, -1, :ref:`†` _POSIX_SPORADIC_SERVER, -1, :ref:`†` :ref:`_POSIX_SYNCHRONIZED_IO `, -1, :kconfig:option:`CONFIG_POSIX_SYNCHRONIZED_IO` - :ref:`_POSIX_THREAD_ATTR_STACKADDR`, 200809L, :kconfig:option:`CONFIG_PTHREAD` - :ref:`_POSIX_THREAD_ATTR_STACKSIZE`, 200809L, :kconfig:option:`CONFIG_PTHREAD` + :ref:`_POSIX_THREAD_ATTR_STACKADDR`, 200809L, :kconfig:option:`CONFIG_POSIX_THREAD_ATTR_STACKADDR` + :ref:`_POSIX_THREAD_ATTR_STACKSIZE`, 200809L, :kconfig:option:`CONFIG_POSIX_THREAD_ATTR_STACKSIZE` :ref:`_POSIX_THREAD_CPUTIME `, 200809L, :kconfig:option:`CONFIG_POSIX_CPUTIME` - _POSIX_THREAD_PRIO_INHERIT, 200809L, :kconfig:option:`CONFIG_PTHREAD_MUTEX` - _POSIX_THREAD_PRIO_PROTECT, -1, - :ref:`_POSIX_THREAD_PRIORITY_SCHEDULING`, 200809L, :kconfig:option:`CONFIG_PTHREAD` + :ref:`_POSIX_THREAD_PRIO_INHERIT `, 200809L, :kconfig:option:`CONFIG_POSIX_THREAD_PRIO_INHERIT` + :ref:`_POSIX_THREAD_PRIO_PROTECT `, -1, :kconfig:option:`CONFIG_POSIX_THREAD_PRIO_PROTECT` + :ref:`_POSIX_THREAD_PRIORITY_SCHEDULING `, 200809L, :kconfig:option:`CONFIG_POSIX_THREAD_PRIORITY_SCHEDULING` _POSIX_THREAD_PROCESS_SHARED, -1, _POSIX_THREAD_SPORADIC_SERVER, -1, _POSIX_TRACE, -1, @@ -149,8 +149,8 @@ XSI System Interfaces :widths: 50, 10, 50 :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` + :ref:`_POSIX_THREAD_ATTR_STACKADDR`, 200809L, :kconfig:option:`CONFIG_POSIX_THREAD_ATTR_STACKADDR` + :ref:`_POSIX_THREAD_ATTR_STACKSIZE`, 200809L, :kconfig:option:`CONFIG_POSIX_THREAD_ATTR_STACKSIZE` _POSIX_THREAD_PROCESS_SHARED, -1, .. _CX: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap01.html diff --git a/doc/services/portability/posix/kconfig/index.rst b/doc/services/portability/posix/kconfig/index.rst index be5b2b4e8c798..6c0f6d672a33c 100644 --- a/doc/services/portability/posix/kconfig/index.rst +++ b/doc/services/portability/posix/kconfig/index.rst @@ -10,9 +10,6 @@ implementation of the POSIX API. * :kconfig:option:`CONFIG_EVENTFD_MAX` * :kconfig:option:`CONFIG_FDTABLE` * :kconfig:option:`CONFIG_GETOPT_LONG` -* :kconfig:option:`CONFIG_MAX_PTHREAD_COUNT` -* :kconfig:option:`CONFIG_MAX_PTHREAD_KEY_COUNT` -* :kconfig:option:`CONFIG_MAX_PTHREAD_MUTEX_COUNT` * :kconfig:option:`CONFIG_MAX_PTHREAD_SPINLOCK_COUNT` * :kconfig:option:`CONFIG_MQUEUE_NAMELEN_MAX` * :kconfig:option:`CONFIG_POSIX_MQ_OPEN_MAX` @@ -23,17 +20,17 @@ implementation of the POSIX API. * :kconfig:option:`CONFIG_POSIX_API` * :kconfig:option:`CONFIG_ZVFS_OPEN_MAX` * :kconfig:option:`CONFIG_POSIX_OPEN_MAX` +* :kconfig:option:`CONFIG_POSIX_PTHREAD_ATTR_GUARDSIZE_BITS` +* :kconfig:option:`CONFIG_POSIX_PTHREAD_ATTR_GUARDSIZE_DEFAULT` +* :kconfig:option:`CONFIG_POSIX_PTHREAD_ATTR_STACKSIZE_BITS` * :kconfig:option:`CONFIG_POSIX_RTSIG_MAX` * :kconfig:option:`CONFIG_POSIX_SIGNAL` * :kconfig:option:`CONFIG_POSIX_SIGNAL_STRING_DESC` +* :kconfig:option:`CONFIG_POSIX_THREAD_KEYS_MAX` +* :kconfig:option:`CONFIG_POSIX_THREAD_THREADS_MAX` * :kconfig:option:`CONFIG_POSIX_UNAME_NODENAME_LEN` * :kconfig:option:`CONFIG_POSIX_UNAME_VERSION_LEN` -* :kconfig:option:`CONFIG_PTHREAD` -* :kconfig:option:`CONFIG_PTHREAD_COND` * :kconfig:option:`CONFIG_PTHREAD_CREATE_BARRIER` -* :kconfig:option:`CONFIG_PTHREAD_IPC` -* :kconfig:option:`CONFIG_PTHREAD_KEY` -* :kconfig:option:`CONFIG_PTHREAD_MUTEX` * :kconfig:option:`CONFIG_PTHREAD_RECYCLER_DELAY_MS` * :kconfig:option:`CONFIG_POSIX_SEM_NAMELEN_MAX` * :kconfig:option:`CONFIG_POSIX_SEM_NSEMS_MAX` diff --git a/doc/services/portability/posix/option_groups/index.rst b/doc/services/portability/posix/option_groups/index.rst index 29c129868bedc..a71d753204cb1 100644 --- a/doc/services/portability/posix/option_groups/index.rst +++ b/doc/services/portability/posix/option_groups/index.rst @@ -778,6 +778,34 @@ _POSIX_THREAD_PRIORITY_SCHEDULING pthread_setschedparam(),yes pthread_setschedprio(),yes +.. _posix_option_thread_prio_inherit: + +_POSIX_THREAD_PRIO_INHERIT +++++++++++++++++++++++++++ + +.. csv-table:: _POSIX_THREAD_PRIO_INHERIT + :header: API, Supported + :widths: 50,10 + + pthread_mutexattr_getprotocol(),yes + pthread_mutexattr_setprotocol(),yes + +.. _posix_option_thread_prio_protect: + +_POSIX_THREAD_PRIO_PROTECT +++++++++++++++++++++++++++ + +.. csv-table:: _POSIX_THREAD_PRIO_PROTECT + :header: API, Supported + :widths: 50,10 + + pthread_mutex_getprioceiling(), + pthread_mutex_setprioceiling(), + pthread_mutexattr_getprioceiling(), + pthread_mutexattr_getprotocol(),yes + pthread_mutexattr_setprioceiling(), + pthread_mutexattr_setprotocol(),yes + .. _posix_thread_safe_functions: _POSIX_THREAD_SAFE_FUNCTIONS diff --git a/doc/services/portability/posix/overview/index.rst b/doc/services/portability/posix/overview/index.rst index cd00b68b1a721..2df6d39bbf5be 100644 --- a/doc/services/portability/posix/overview/index.rst +++ b/doc/services/portability/posix/overview/index.rst @@ -129,8 +129,7 @@ feature selection at various levels of granularity. Alternatively, users may enable one of the Kconfig options below as a shortcut to enable multiple :ref:`Option Groups`. -* :kconfig:option:`CONFIG_POSIX_API` -* :kconfig:option:`CONFIG_PTHREAD_IPC` +* :kconfig:option:`CONFIG_POSIX_API` - Enables all implemented POSIX API Options and Option Groups .. note:: Since the POSIX environment in Zephyr is fully configurable via :ref:`Kconfig`, diff --git a/include/zephyr/posix/posix_features.h b/include/zephyr/posix/posix_features.h index d95ebf5494877..0ff2f37158264 100644 --- a/include/zephyr/posix/posix_features.h +++ b/include/zephyr/posix/posix_features.h @@ -94,11 +94,11 @@ /* #define _POSIX_SPORADIC_SERVER (-1L) */ /* #define _POSIX_SYNCHRONIZED_IO (-1L) */ -#ifdef CONFIG_PTHREAD_IPC +#ifdef CONFIG_POSIX_THREAD_ATTR_STACKADDR #define _POSIX_THREAD_ATTR_STACKADDR _POSIX_VERSION #endif -#ifdef CONFIG_PTHREAD_IPC +#ifdef CONFIG_POSIX_THREAD_ATTR_STACKSIZE #define _POSIX_THREAD_ATTR_STACKSIZE _POSIX_VERSION #endif @@ -106,23 +106,29 @@ #define _POSIX_THREAD_CPUTIME _POSIX_VERSION #endif -#ifdef CONFIG_PTHREAD_IPC +#ifdef CONFIG_POSIX_THREAD_PRIO_INHERIT #define _POSIX_THREAD_PRIO_INHERIT _POSIX_VERSION #endif -/* #define _POSIX_THREAD_PRIO_PROTECT (-1L) */ -/* #define _POSIX_THREAD_PRIORITY_SCHEDULING (-1L) */ +#ifdef CONFIG_POSIX_THREAD_PRIO_PROTECT +#define _POSIX_THREAD_PRIO_PROTECT _POSIX_VERSION +#endif + +#ifdef CONFIG_POSIX_THREAD_PRIORITY_SCHEDULING +#define _POSIX_THREAD_PRIORITY_SCHEDULING _POSIX_VERSION +#endif + /* #define _POSIX_THREAD_PROCESS_SHARED (-1L) */ /* #define _POSIX_THREAD_ROBUST_PRIO_INHERIT (-1L) */ /* #define _POSIX_THREAD_ROBUST_PRIO_PROTECT (-1L) */ -#ifdef CONFIG_PTHREAD_IPC +#ifdef CONFIG_POSIX_THREAD_SAFE_FUNCTIONS #define _POSIX_THREAD_SAFE_FUNCTIONS _POSIX_VERSION #endif /* #define _POSIX_THREAD_SPORADIC_SERVER (-1L) */ -#ifdef CONFIG_PTHREAD_IPC +#ifdef CONFIG_POSIX_THREADS #ifndef _POSIX_THREADS #define _POSIX_THREADS _POSIX_VERSION #endif @@ -229,9 +235,9 @@ #define _POSIX_SYMLOOP_MAX (8) #define _POSIX_THREAD_DESTRUCTOR_ITERATIONS (4) #define _POSIX_THREAD_KEYS_MAX \ - COND_CODE_1(CONFIG_PTHREAD_IPC, (CONFIG_MAX_PTHREAD_KEY_COUNT), (0)) + COND_CODE_1(CONFIG_POSIX_THREADS, (CONFIG_POSIX_THREAD_KEYS_MAX), (0)) #define _POSIX_THREAD_THREADS_MAX \ - COND_CODE_1(CONFIG_PTHREAD_IPC, (CONFIG_MAX_PTHREAD_COUNT), (0)) + COND_CODE_1(CONFIG_POSIX_THREADS, (CONFIG_POSIX_THREAD_THREADS_MAX), (0)) #define _POSIX_TIMER_MAX \ COND_CODE_1(CONFIG_POSIX_TIMERS, (CONFIG_POSIX_TIMER_MAX), (0)) #define _POSIX_TRACE_EVENT_NAME_MAX (30) diff --git a/include/zephyr/posix/pthread.h b/include/zephyr/posix/pthread.h index 0a721f58be23a..33288d7d75502 100644 --- a/include/zephyr/posix/pthread.h +++ b/include/zephyr/posix/pthread.h @@ -417,7 +417,7 @@ int pthread_attr_getscope(const pthread_attr_t *attr, int *contentionscope); int pthread_attr_setscope(pthread_attr_t *attr, int contentionscope); int pthread_attr_getinheritsched(const pthread_attr_t *attr, int *inheritsched); int pthread_attr_setinheritsched(pthread_attr_t *attr, int inheritsched); -#ifdef CONFIG_PTHREAD_IPC +#ifdef CONFIG_POSIX_THREADS int pthread_once(pthread_once_t *once, void (*initFunc)(void)); #endif FUNC_NORETURN void pthread_exit(void *retval); @@ -502,7 +502,7 @@ int pthread_setname_np(pthread_t thread, const char *name); */ int pthread_getname_np(pthread_t thread, char *name, size_t len); -#ifdef CONFIG_PTHREAD_IPC +#ifdef CONFIG_POSIX_THREADS /** * @brief Destroy a pthread_spinlock_t. diff --git a/include/zephyr/posix/sys/sysconf.h b/include/zephyr/posix/sys/sysconf.h index 812f3bf8c717b..f53d598ac0ba6 100644 --- a/include/zephyr/posix/sys/sysconf.h +++ b/include/zephyr/posix/sys/sysconf.h @@ -183,22 +183,24 @@ enum { #define __z_posix_sysconf_SC_SS_REPL_MAX _POSIX_SS_REPL_MAX #define __z_posix_sysconf_SC_SYNCHRONIZED_IO (-1L) #define __z_posix_sysconf_SC_THREAD_ATTR_STACKADDR \ - COND_CODE_1(CONFIG_PTHREAD_IPC, (_POSIX_THREAD_ATTR_STACKADDR), (-1)) + COND_CODE_1(CONFIG_POSIX_THREAD_ATTR_STACKADDR, (_POSIX_THREAD_ATTR_STACKADDR), (-1)) #define __z_posix_sysconf_SC_THREAD_ATTR_STACKSIZE \ - COND_CODE_1(CONFIG_PTHREAD_IPC, (_POSIX_THREAD_ATTR_STACKSIZE), (-1L)) + COND_CODE_1(CONFIG_POSIX_THREAD_ATTR_STACKSIZE, (_POSIX_THREAD_ATTR_STACKSIZE), (-1L)) #define __z_posix_sysconf_SC_THREAD_CPUTIME (-1L) #define __z_posix_sysconf_SC_THREAD_PRIO_INHERIT \ - COND_CODE_1(CONFIG_PTHREAD_IPC, (_POSIX_THREAD_PRIO_INHERIT), (-1L)) + COND_CODE_1(CONFIG_POSIX_THREAD_PRIO_INHERIT, (_POSIX_THREAD_PRIO_INHERIT), (-1L)) #define __z_posix_sysconf_SC_THREAD_PRIO_PROTECT (-1L) -#define __z_posix_sysconf_SC_THREAD_PRIORITY_SCHEDULING (-1L) +#define __z_posix_sysconf_SC_THREAD_PRIORITY_SCHEDULING \ + COND_CODE_1(CONFIG_POSIX_THREAD_PRIORITY_SCHEDULING, (_POSIX_THREAD_PRIORITY_SCHEDULING), \ + (-1L)) #define __z_posix_sysconf_SC_THREAD_PROCESS_SHARED (-1L) #define __z_posix_sysconf_SC_THREAD_ROBUST_PRIO_INHERIT (-1L) #define __z_posix_sysconf_SC_THREAD_ROBUST_PRIO_PROTECT (-1L) #define __z_posix_sysconf_SC_THREAD_SAFE_FUNCTIONS \ - COND_CODE_1(CONFIG_PTHREAD_IPC, (_POSIX_THREAD_SAFE_FUNCTIONS), (-1L)) + COND_CODE_1(CONFIG_POSIX_THREAD_SAFE_FUNCTIONS, (_POSIX_THREAD_SAFE_FUNCTIONS), (-1L)) #define __z_posix_sysconf_SC_THREAD_SPORADIC_SERVER (-1L) #define __z_posix_sysconf_SC_THREADS \ - COND_CODE_1(CONFIG_PTHREAD_IPC, (_POSIX_THREADS), (-1L)) + COND_CODE_1(CONFIG_POSIX_THREADS, (_POSIX_THREADS), (-1L)) #define __z_posix_sysconf_SC_TIMEOUTS \ COND_CODE_1(CONFIG_POSIX_TIMEOUTS, (_POSIX_TIMEOUTS), (-1L)) #define __z_posix_sysconf_SC_TIMERS \ diff --git a/lib/posix/options/CMakeLists.txt b/lib/posix/options/CMakeLists.txt index 443c0ad018243..1da0e64f99ad0 100644 --- a/lib/posix/options/CMakeLists.txt +++ b/lib/posix/options/CMakeLists.txt @@ -24,7 +24,7 @@ if(CONFIG_POSIX_SIGNAL) ) endif() -if(CONFIG_POSIX_API OR CONFIG_PTHREAD_IPC OR CONFIG_POSIX_TIMERS OR +if(CONFIG_POSIX_API OR CONFIG_POSIX_THREADS OR CONFIG_POSIX_TIMERS OR CONFIG_POSIX_MESSAGE_PASSING OR CONFIG_POSIX_FILE_SYSTEM OR CONFIG_EVENTFD OR CONFIG_POSIX_C_LIB_EXT OR CONFIG_POSIX_SINGLE_PROCESS) # This is a temporary workaround so that Newlib declares the appropriate @@ -70,15 +70,17 @@ zephyr_library_sources_ifdef(CONFIG_POSIX_SYSLOG syslog.c) zephyr_library_sources_ifdef(CONFIG_POSIX_TIMERS clock.c timer.c + timespec_to_timeout.c ) -zephyr_library_sources_ifdef(CONFIG_PTHREAD_IPC _common.c) -zephyr_library_sources_ifdef(CONFIG_PTHREAD_COND cond.c) -zephyr_library_sources_ifdef(CONFIG_PTHREAD_KEY key.c) -zephyr_library_sources_ifdef(CONFIG_PTHREAD_MUTEX mutex.c) -zephyr_library_sources_ifdef(CONFIG_PTHREAD pthread.c) zephyr_library_sources_ifdef(CONFIG_POSIX_PRIORITY_SCHEDULING sched.c) zephyr_library_sources_ifdef(CONFIG_POSIX_READER_WRITER_LOCKS rwlock.c) zephyr_library_sources_ifdef(CONFIG_POSIX_SEMAPHORES semaphore.c) +zephyr_library_sources_ifdef(CONFIG_POSIX_THREADS + cond.c + key.c + mutex.c + pthread.c +) zephyr_library_sources_ifdef(CONFIG_XOPEN_STREAMS stropts.c) zephyr_library_sources_ifdef(CONFIG_XSI_SYSTEM_LOGGING syslog.c) diff --git a/lib/posix/options/Kconfig b/lib/posix/options/Kconfig index 43c9330556774..0157c8d884c29 100644 --- a/lib/posix/options/Kconfig +++ b/lib/posix/options/Kconfig @@ -14,26 +14,14 @@ config POSIX_API Enable mostly-standards-compliant implementations of various POSIX (IEEE 1003.1) APIs. -config PTHREAD_IPC - bool "POSIX pthread IPC API" - default y if POSIX_API - depends on POSIX_TIMERS - help - This enables a mostly-standards-compliant implementation of - the pthread mutex, condition variable and barrier IPC - mechanisms. - rsource "Kconfig.aio" rsource "Kconfig.barrier" -rsource "Kconfig.cond" rsource "Kconfig.c_lib_ext" rsource "Kconfig.device_io" rsource "Kconfig.fd_mgmt" rsource "Kconfig.fs" -rsource "Kconfig.key" rsource "Kconfig.mem" rsource "Kconfig.mqueue" -rsource "Kconfig.mutex" rsource "Kconfig.net" rsource "Kconfig.proc1" rsource "Kconfig.procN" diff --git a/lib/posix/options/Kconfig.cond b/lib/posix/options/Kconfig.cond deleted file mode 100644 index b69b35dece6f8..0000000000000 --- a/lib/posix/options/Kconfig.cond +++ /dev/null @@ -1,9 +0,0 @@ -# Copyright (c) 2017 Intel Corporation -# Copyright (c) 2023 Meta -# -# SPDX-License-Identifier: Apache-2.0 - -TYPE = PTHREAD_COND -type = pthread_cond_t -type-function = pthread_cond_wait -rsource "Kconfig.template.pooled_ipc_type" diff --git a/lib/posix/options/Kconfig.deprecated b/lib/posix/options/Kconfig.deprecated index 54564d7891fa9..83dc737bc3c2e 100644 --- a/lib/posix/options/Kconfig.deprecated +++ b/lib/posix/options/Kconfig.deprecated @@ -33,6 +33,24 @@ config GETOPT Please use CONFIG_POSIX_C_LIB_EXT instead. +config MAX_PTHREAD_COUNT + int "Maximum number of pthread_t [DEPRECATED]" + default POSIX_THREAD_THREADS_MAX if POSIX_THREADS + default 0 + help + This option is deprecated. + + Please use CONFIG_POSIX_THREAD_THREADS_MAX instead. + +config MAX_PTHREAD_KEY_COUNT + int "Maximum number of pthread_key_t [DEPRECATED]" + default POSIX_THREAD_KEYS_MAX if POSIX_THREADS + default 0 + help + This option is deprecated. + + Please use CONFIG_POSIX_THREAD_KEYS_MAX instead. + config MAX_TIMER_COUNT int "Maximum number of timer_t [DEPRECATED]" default POSIX_TIMER_MAX if POSIX_TIMERS @@ -165,6 +183,15 @@ config POSIX_UNAME Please use CONFIG_POSIX_SINGLE_PROCESS instead. +config PTHREAD + bool "pthread_t support [DEPRECATED]" + select DEPRECATED + select POSIX_THREADS + help + This option is deprecated. + + Please use CONFIG_POSIX_THREADS instead. + config PTHREAD_BARRIER bool "pthread_barrier_t support [DEPRECATED]" select DEPRECATED @@ -174,6 +201,43 @@ config PTHREAD_BARRIER Please use CONFIG_POSIX_BARRIERS instead. +config PTHREAD_COND + bool "pthread_cond_t support [DEPRECATED]" + select DEPRECATED + select POSIX_THREADS + help + This option is deprecated. + + Please use CONFIG_POSIX_THREADS instead. + + +config PTHREAD_IPC + bool "POSIX pthread IPC API [DEPRECATED]" + select DEPRECATED + select POSIX_THREADS + help + This option is deprecated. + + Please use CONFIG_POSIX_THREADS instead. + +config PTHREAD_KEY + bool "pthread_key_t support [DEPRECATED]" + select DEPRECATED + select POSIX_THREADS + help + This option is deprecated. + + Please use CONFIG_POSIX_THREADS instead. + +config PTHREAD_MUTEX + bool "pthread_mutex_t support [DEPRECATED]" + select DEPRECATED + select POSIX_THREADS + help + This option is deprecated. + + Please use CONFIG_POSIX_THREADS instead. + config PTHREAD_RWLOCK bool "pthread_spinlock_t support [DEPRECATED]" select DEPRECATED diff --git a/lib/posix/options/Kconfig.key b/lib/posix/options/Kconfig.key deleted file mode 100644 index 671cce103735d..0000000000000 --- a/lib/posix/options/Kconfig.key +++ /dev/null @@ -1,9 +0,0 @@ -# Copyright (c) 2018 Intel Corporation -# Copyright (c) 2023 Meta -# -# SPDX-License-Identifier: Apache-2.0 - -TYPE = PTHREAD_KEY -type = pthread_key_t -type-function = pthread_setspecific -rsource "Kconfig.template.pooled_ipc_type" diff --git a/lib/posix/options/Kconfig.mutex b/lib/posix/options/Kconfig.mutex deleted file mode 100644 index 6d5729e80aa02..0000000000000 --- a/lib/posix/options/Kconfig.mutex +++ /dev/null @@ -1,9 +0,0 @@ -# Copyright (c) 2017 Intel Corporation -# Copyright (c) 2023 Meta -# -# SPDX-License-Identifier: Apache-2.0 - -TYPE = PTHREAD_MUTEX -type = pthread_mutex_t -type-function = pthread_mutex_lock -rsource "Kconfig.template.pooled_ipc_type" diff --git a/lib/posix/options/Kconfig.pthread b/lib/posix/options/Kconfig.pthread index f0c65836b6000..8c1b813c872e3 100644 --- a/lib/posix/options/Kconfig.pthread +++ b/lib/posix/options/Kconfig.pthread @@ -1,14 +1,50 @@ # Copyright (c) 2017 Intel Corporation # Copyright (c) 2023 Meta +# Copyright (c) 2024 Tenstorrent AI ULC # # SPDX-License-Identifier: Apache-2.0 -TYPE = PTHREAD -type = pthread_t -type-function = pthread_create -rsource "Kconfig.template.pooled_ipc_type" +menuconfig POSIX_THREADS + bool "POSIX thread support" + default y if POSIX_API + help + Select 'y' here to enable POSIX threads, mutexes, condition variables, and thread-specific + storage. + + For more information please see + https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_subprofiles.html + +if POSIX_THREADS + +config POSIX_THREAD_THREADS_MAX + int "Maximum number of POSIX threads" + default 5 + help + Maximum simultaneously active threads in a POSIX application. -if PTHREAD + For more information, see + https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/limits.h.html + +config MAX_PTHREAD_MUTEX_COUNT + int "Maximum number of POSIX mutexes" + default 5 + help + Maximum simultaneously active mutexes in a POSIX application. + +config MAX_PTHREAD_COND_COUNT + int "Maximum number of POSIX condition variables" + default 5 + help + Maximum simultaneously active condition variables in a POSIX application. + +config POSIX_THREAD_KEYS_MAX + int "Maximum number of POSIX thread-specific-storage keys" + default 5 + help + Maximum simultaneously active thread-specific-storage keys in a POSIX application. + + For more information, see + https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/limits.h.html config PTHREAD_RECYCLER_DELAY_MS int "Delay for reclaiming dynamic pthread stacks (ms)" @@ -27,6 +63,54 @@ config PTHREAD_RECYCLER_DELAY_MS Note: this option should be considered temporary and will likely be removed once a more synchronous solution is available. +config POSIX_THREAD_ATTR_STACKADDR + bool "Support getting and setting POSIX thread stack addresses" + default y + help + Enable this option to use pthread_attr_getstackaddr() and + pthread_attr_setstackaddr(). + + This option was removed in IEEE 1003.1-2017 in favour of + pthread_attr_getstack() and pthread_attr_setstack(). + + For more information, please see + https://pubs.opengroup.org/onlinepubs/009696799/functions/pthread_attr_getstackaddr.html + https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_xsh_chap03.html + https://pubs.opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html#tag_15_09_08 + +config POSIX_THREAD_ATTR_STACKSIZE + bool "Support getting and setting POSIX thread stack sizes" + default y + help + Enable this option to use pthread_attr_getstacksize() or + pthread_attr_setstacksize(). + + For more information, please see + https://pubs.opengroup.org/onlinepubs/009696699/functions/pthread_attr_getstacksize.html + +config POSIX_THREADS_EXT + bool "Extended POSIX thread support" + default y + help + Enable this option to use pthread_attr_getguardsize(), pthread_attr_setguardsize(), + pthread_mutexattr_gettype(), or pthread_mutexattr_settype(). + + For more information, please see + https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_subprofiles.html + +config POSIX_THREAD_PRIORITY_SCHEDULING + bool "Run POSIX threads with different priorities and schedulers" + default y + help + Enabling this option allows the application to configure different priorities and + scheduling algorithms for different threads via functions such as pthread_setschedparam() + and pthread_setschedprio(). This is required for Realtime Threads and Advanced Realtime + Threads. + + For more information, please see + https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap02.html#tag_02_01_06 + https://man7.org/linux/man-pages/man7/posixoptions.7.html + config POSIX_PTHREAD_ATTR_STACKSIZE_BITS int "Significant bits for pthread_attr_t stacksize" range 8 31 @@ -59,4 +143,50 @@ config POSIX_PTHREAD_ATTR_GUARDSIZE_DEFAULT facilitate a more dynamic approach to guard areas (via software or hardware) but for now it simply increases the size of thread stacks. -endif +config POSIX_THREAD_PRIO_INHERIT + bool "POSIX mutex priority inheritance" + default y + help + Select 'y' here to enable POSIX mutex priority inheritance. + + For more information, please see + https://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_mutexattr_getprotocol.html + +config POSIX_THREAD_PRIO_PROTECT + bool "POSIX mutex priority protection" + default y + help + Select 'y' here to enable POSIX mutex priority protection. + + For more information, please see + https://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_mutexattr_getprotocol.html + +config POSIX_THREAD_SAFE_FUNCTIONS + bool "POSIX thread-safe functions" + default y + help + Select 'y' here to enable POSIX thread-safe functions including asctime_r(), ctime_r(), + flockfile(), ftrylockfile(), funlockfile(), getc_unlocked(), getchar_unlocked(), + getgrgid_r(), getgrnam_r(), getpwnam_r(), getpwuid_r(), gmtime_r(), localtime_r(), + putc_unlocked(), putchar_unlocked(), rand_r(), readdir_r(), strerror_r(), and strtok_r(). + + For more information, please see + https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_xsh_chap02.html#tag_22_02_09_07 + +module = PTHREAD +module-str = POSIX thread +source "subsys/logging/Kconfig.template.log_config" + +module = PTHREAD_MUTEX +module-str = POSIX mutex +source "subsys/logging/Kconfig.template.log_config" + +module = PTHREAD_COND +module-str = POSIX condition variable +source "subsys/logging/Kconfig.template.log_config" + +module = PTHREAD_KEY +module-str = POSIX thread-specific data +source "subsys/logging/Kconfig.template.log_config" + +endif # POSIX_THREADS diff --git a/lib/posix/options/Kconfig.sched b/lib/posix/options/Kconfig.sched index b5fb3a5dcb1e9..c6ea53be8f1ff 100644 --- a/lib/posix/options/Kconfig.sched +++ b/lib/posix/options/Kconfig.sched @@ -4,8 +4,8 @@ config POSIX_PRIORITY_SCHEDULING bool "Priority scheduling" - default y if PTHREAD + default y if POSIX_THREADS default y if POSIX_API - depends on PTHREAD + depends on POSIX_THREADS help This enables POSIX scheduling APIs (_POSIX_PRIORITY_SCHEDULING). diff --git a/lib/posix/options/Kconfig.template.pooled_ipc_type b/lib/posix/options/Kconfig.template.pooled_ipc_type deleted file mode 100644 index 08d804382e801..0000000000000 --- a/lib/posix/options/Kconfig.template.pooled_ipc_type +++ /dev/null @@ -1,29 +0,0 @@ -# Copyright (c) 2023 Meta -# -# SPDX-License-Identifier: Apache-2.0 - -rsource "Kconfig.template.with_url" - -# Not user configurable (i.e. private for now) -menuconfig $(TYPE) - bool "$(type) support" - depends on PTHREAD_IPC - default y - help - Support for $(TYPE) - For more info, see - $(posix-url-base)/$(type-function).html - -if $(TYPE) - -# eventually, this size should be defaulted to 0 -config MAX_$(TYPE)_COUNT - int "Maximum number of $(type)" - default 5 - depends on $(TYPE) - help - Maximum simultaneously active $(type) in a POSIX application. - -rsource "Kconfig.template.with_logging" - -endif # $(TYPE) diff --git a/lib/posix/options/Kconfig.template.pooled_type b/lib/posix/options/Kconfig.template.pooled_type deleted file mode 100644 index 5a75c2ee890fe..0000000000000 --- a/lib/posix/options/Kconfig.template.pooled_type +++ /dev/null @@ -1,25 +0,0 @@ -# Copyright (c) 2023 Meta -# -# SPDX-License-Identifier: Apache-2.0 - -rsource "Kconfig.template.with_url" - -# This is mainly for TIMER currently. -menuconfig $(TYPE) - bool "$(type) support" - help - For more info, see - $(posix-url-base)/$(type-function).html - -if $(TYPE) - -# eventually, this size should be defaulted to 0 as a safe value -config MAX_$(TYPE)_COUNT - int "Maximum number of $(type)" - default 5 - help - Maximum simultaneously active $(type) in a POSIX application. - -rsource "Kconfig.template.with_logging" - -endif # $(TYPE) diff --git a/lib/posix/options/Kconfig.template.with_logging b/lib/posix/options/Kconfig.template.with_logging deleted file mode 100644 index f1fc5141e7cd1..0000000000000 --- a/lib/posix/options/Kconfig.template.with_logging +++ /dev/null @@ -1,7 +0,0 @@ -# Copyright (c) 2023 Meta -# -# SPDX-License-Identifier: Apache-2.0 - -module = $(TYPE) -module-str = $(TYPE) logging -source "subsys/logging/Kconfig.template.log_config" diff --git a/lib/posix/options/Kconfig.template.with_url b/lib/posix/options/Kconfig.template.with_url deleted file mode 100644 index 33e34756ee71e..0000000000000 --- a/lib/posix/options/Kconfig.template.with_url +++ /dev/null @@ -1,5 +0,0 @@ -# Copyright (c) 2023 Meta -# -# SPDX-License-Identifier: Apache-2.0 - -posix-url-base = https://pubs.opengroup.org/onlinepubs/9699919799 diff --git a/lib/posix/options/Kconfig.xsi b/lib/posix/options/Kconfig.xsi index 9de3628a31f9e..ac66838b89217 100644 --- a/lib/posix/options/Kconfig.xsi +++ b/lib/posix/options/Kconfig.xsi @@ -36,4 +36,14 @@ config XSI_SYSTEM_LOGGING For more information, please see https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_subprofiles.html +config XSI_THREADS_EXT + bool "X/Open threads extensions" + default y if POSIX_API + help + This option provides support for pthread_attr_getstack(), pthread_attr_setstack(), + pthread_getconcurrency(), and pthread_setconcurrency(). + + For more information, please see + https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_subprofiles.html + endmenu diff --git a/lib/posix/options/key.c b/lib/posix/options/key.c index 5e68381c53b39..a7906b8d9f7ce 100644 --- a/lib/posix/options/key.c +++ b/lib/posix/options/key.c @@ -29,11 +29,11 @@ static struct k_spinlock pthread_key_lock; * perspective of the application). With a linear space, this means that * the theoretical pthread_key_t range is [0,2147483647]. */ -BUILD_ASSERT(CONFIG_MAX_PTHREAD_KEY_COUNT < PTHREAD_OBJ_MASK_INIT, +BUILD_ASSERT(CONFIG_POSIX_THREAD_KEYS_MAX < PTHREAD_OBJ_MASK_INIT, "CONFIG_MAX_PTHREAD_KEY_COUNT is too high"); -static pthread_key_obj posix_key_pool[CONFIG_MAX_PTHREAD_KEY_COUNT]; -SYS_BITARRAY_DEFINE_STATIC(posix_key_bitarray, CONFIG_MAX_PTHREAD_KEY_COUNT); +static pthread_key_obj posix_key_pool[CONFIG_POSIX_THREAD_KEYS_MAX]; +SYS_BITARRAY_DEFINE_STATIC(posix_key_bitarray, CONFIG_POSIX_THREAD_KEYS_MAX); static inline size_t posix_key_to_offset(pthread_key_obj *k) { diff --git a/lib/posix/options/pthread.c b/lib/posix/options/pthread.c index a46cde7614cbe..8e9e33ad86141 100644 --- a/lib/posix/options/pthread.c +++ b/lib/posix/options/pthread.c @@ -86,7 +86,7 @@ static sys_dlist_t posix_thread_q[] = { SYS_DLIST_STATIC_INIT(&posix_thread_q[POSIX_THREAD_RUN_Q]), SYS_DLIST_STATIC_INIT(&posix_thread_q[POSIX_THREAD_DONE_Q]), }; -static struct posix_thread posix_thread_pool[CONFIG_MAX_PTHREAD_COUNT]; +static struct posix_thread posix_thread_pool[CONFIG_POSIX_THREAD_THREADS_MAX]; static struct k_spinlock pthread_pool_lock; static int pthread_concurrency; @@ -123,8 +123,8 @@ static inline enum posix_thread_qid posix_thread_q_get(struct posix_thread *t) * perspective of the application). With a linear space, this means that * the theoretical pthread_t range is [0,2147483647]. */ -BUILD_ASSERT(CONFIG_MAX_PTHREAD_COUNT < PTHREAD_OBJ_MASK_INIT, - "CONFIG_MAX_PTHREAD_COUNT is too high"); +BUILD_ASSERT(CONFIG_POSIX_THREAD_THREADS_MAX < PTHREAD_OBJ_MASK_INIT, + "CONFIG_POSIX_THREAD_THREADS_MAX is too high"); static inline size_t posix_thread_to_offset(struct posix_thread *t) { @@ -148,7 +148,7 @@ struct posix_thread *to_posix_thread(pthread_t pthread) return NULL; } - if (bit >= CONFIG_MAX_PTHREAD_COUNT) { + if (bit >= ARRAY_SIZE(posix_thread_pool)) { LOG_DBG("Invalid pthread (%x)", pthread); return NULL; } @@ -252,8 +252,8 @@ void __z_pthread_cleanup_pop(int execute) static bool is_posix_policy_prio_valid(int priority, int policy) { - if (priority >= sched_get_priority_min(policy) && - priority <= sched_get_priority_max(policy)) { + if (priority >= posix_sched_priority_min(policy) && + priority <= posix_sched_priority_max(policy)) { return true; } @@ -879,7 +879,7 @@ int pthread_setschedprio(pthread_t thread, int prio) int ret; int new_prio = K_LOWEST_APPLICATION_THREAD_PRIO; struct posix_thread *t = NULL; - int policy; + int policy = -1; struct sched_param param; ret = pthread_getschedparam(thread, &policy, ¶m); @@ -1375,7 +1375,7 @@ int pthread_setname_np(pthread_t thread, const char *name) k_tid_t kthread; thread = get_posix_thread_idx(thread); - if (thread >= CONFIG_MAX_PTHREAD_COUNT) { + if (thread >= ARRAY_SIZE(posix_thread_pool)) { return ESRCH; } @@ -1399,7 +1399,7 @@ int pthread_getname_np(pthread_t thread, char *name, size_t len) k_tid_t kthread; thread = get_posix_thread_idx(thread); - if (thread >= CONFIG_MAX_PTHREAD_COUNT) { + if (thread >= ARRAY_SIZE(posix_thread_pool)) { return ESRCH; } @@ -1474,10 +1474,8 @@ int pthread_sigmask(int how, const sigset_t *ZRESTRICT set, sigset_t *ZRESTRICT static int posix_thread_pool_init(void) { - size_t i; - - for (i = 0; i < CONFIG_MAX_PTHREAD_COUNT; ++i) { - posix_thread_q_set(&posix_thread_pool[i], POSIX_THREAD_READY_Q); + ARRAY_FOR_EACH_PTR(posix_thread_pool, th) { + posix_thread_q_set(th, POSIX_THREAD_READY_Q); } return 0; diff --git a/lib/posix/options/pthread_sched.h b/lib/posix/options/pthread_sched.h index 4a70d081f8480..f51d05a985f09 100644 --- a/lib/posix/options/pthread_sched.h +++ b/lib/posix/options/pthread_sched.h @@ -7,6 +7,7 @@ #ifndef ZEPHYR_LIB_POSIX_POSIX_PTHREAD_SCHED_H_ #define ZEPHYR_LIB_POSIX_POSIX_PTHREAD_SCHED_H_ +#include #include #include @@ -16,4 +17,27 @@ static inline bool valid_posix_policy(int policy) return policy == SCHED_FIFO || policy == SCHED_RR || policy == SCHED_OTHER; } +static inline int posix_sched_priority_min(int policy) +{ + if (!valid_posix_policy(policy)) { + errno = EINVAL; + return -1; + } + + return 0; +} + +static inline int posix_sched_priority_max(int policy) +{ + if (IS_ENABLED(CONFIG_COOP_ENABLED) && policy == SCHED_FIFO) { + return CONFIG_NUM_COOP_PRIORITIES - 1; + } else if (IS_ENABLED(CONFIG_PREEMPT_ENABLED) && + (policy == SCHED_RR || policy == SCHED_OTHER)) { + return CONFIG_NUM_PREEMPT_PRIORITIES - 1; + } + + errno = EINVAL; + return -1; +} + #endif diff --git a/lib/posix/options/rwlock.c b/lib/posix/options/rwlock.c index c4143a79acb18..ef14867b028de 100644 --- a/lib/posix/options/rwlock.c +++ b/lib/posix/options/rwlock.c @@ -12,7 +12,7 @@ #include #include -#define CONCURRENT_READER_LIMIT (CONFIG_MAX_PTHREAD_COUNT + 1) +#define CONCURRENT_READER_LIMIT (CONFIG_POSIX_THREAD_THREADS_MAX + 1) struct posix_rwlock { struct k_sem rd_sem; diff --git a/lib/posix/options/sched.c b/lib/posix/options/sched.c index be174d92cd64e..a37b01d0106b2 100644 --- a/lib/posix/options/sched.c +++ b/lib/posix/options/sched.c @@ -16,12 +16,7 @@ */ int sched_get_priority_min(int policy) { - if (!valid_posix_policy(policy)) { - errno = EINVAL; - return -1; - } - - return 0; + return posix_sched_priority_min(policy); } /** @@ -31,15 +26,7 @@ int sched_get_priority_min(int policy) */ int sched_get_priority_max(int policy) { - if (IS_ENABLED(CONFIG_COOP_ENABLED) && policy == SCHED_FIFO) { - return CONFIG_NUM_COOP_PRIORITIES - 1; - } else if (IS_ENABLED(CONFIG_PREEMPT_ENABLED) && - (policy == SCHED_RR || policy == SCHED_OTHER)) { - return CONFIG_NUM_PREEMPT_PRIORITIES - 1; - } - - errno = EINVAL; - return -1; + return posix_sched_priority_max(policy); } /** diff --git a/lib/posix/options/_common.c b/lib/posix/options/timespec_to_timeout.c similarity index 92% rename from lib/posix/options/_common.c rename to lib/posix/options/timespec_to_timeout.c index 8125570f26eec..e72956e6e3e93 100644 --- a/lib/posix/options/_common.c +++ b/lib/posix/options/timespec_to_timeout.c @@ -8,7 +8,6 @@ #include #include -#ifdef CONFIG_POSIX_TIMERS int64_t timespec_to_timeoutms(const struct timespec *abstime) { int64_t milli_secs, secs, nsecs; @@ -30,4 +29,3 @@ int64_t timespec_to_timeoutms(const struct timespec *abstime) return milli_secs; } -#endif /* CONFIG_POSIX_TIMERS */ diff --git a/modules/Kconfig.simplelink b/modules/Kconfig.simplelink index 843f95c36fa24..13b26b1ca1a48 100644 --- a/modules/Kconfig.simplelink +++ b/modules/Kconfig.simplelink @@ -7,14 +7,14 @@ config HAS_CC3220SDK # SimpleLink drivers require types (stdint.h) from c library which is not # provided by minimal lbc # Selecting ERRNO lets host driver use Zephyr's __errno -# Selecting PTHREAD_IPC and POSIX_API are needed to build the host driver +# Selecting POSIX_THREADS and POSIX_API are needed to build the host driver config SIMPLELINK_HOST_DRIVER bool "Build the SimpleLink WiFi Host Driver" depends on HAS_CC3220SDK depends on MULTITHREADING select REQUIRES_FULL_LIBC select ERRNO - select PTHREAD_IPC + select POSIX_THREADS select POSIX_TIMERS help Build the SimpleLink host driver diff --git a/samples/posix/philosophers/prj.conf b/samples/posix/philosophers/prj.conf index 0934325aea66b..2f8c3da16c300 100644 --- a/samples/posix/philosophers/prj.conf +++ b/samples/posix/philosophers/prj.conf @@ -6,7 +6,7 @@ CONFIG_THREAD_STACK_INFO=y CONFIG_DYNAMIC_THREAD=y CONFIG_DYNAMIC_THREAD_POOL_SIZE=6 -CONFIG_MAX_PTHREAD_COUNT=6 +CONFIG_POSIX_THREAD_THREADS_MAX=6 CONFIG_MAX_PTHREAD_MUTEX_COUNT=6 #Enable thread awareness for debugging tools supporting it diff --git a/samples/posix/philosophers/src/main.c b/samples/posix/philosophers/src/main.c index 29861803aab3e..bfac15861fd6d 100644 --- a/samples/posix/philosophers/src/main.c +++ b/samples/posix/philosophers/src/main.c @@ -21,12 +21,12 @@ #define MAX_NAME_LEN 1 #endif -#define NUM_PHIL CONFIG_MAX_PTHREAD_COUNT +#define NUM_PHIL CONFIG_POSIX_THREAD_THREADS_MAX #define obj_init_type "POSIX" #define fork_type_str "mutexes" -BUILD_ASSERT(CONFIG_MAX_PTHREAD_COUNT == CONFIG_MAX_PTHREAD_MUTEX_COUNT); -BUILD_ASSERT(CONFIG_DYNAMIC_THREAD_POOL_SIZE == CONFIG_MAX_PTHREAD_COUNT); +BUILD_ASSERT(CONFIG_POSIX_THREAD_THREADS_MAX == CONFIG_MAX_PTHREAD_MUTEX_COUNT); +BUILD_ASSERT(CONFIG_DYNAMIC_THREAD_POOL_SIZE == CONFIG_POSIX_THREAD_THREADS_MAX); typedef pthread_mutex_t *fork_t; diff --git a/tests/posix/common/prj.conf b/tests/posix/common/prj.conf index 1c99d64cf5a17..ff61f29c7b5c7 100644 --- a/tests/posix/common/prj.conf +++ b/tests/posix/common/prj.conf @@ -1,6 +1,5 @@ -CONFIG_PTHREAD_IPC=y CONFIG_POSIX_API=y -CONFIG_MAX_PTHREAD_COUNT=6 +CONFIG_POSIX_THREAD_THREADS_MAX=6 CONFIG_ZTEST=y CONFIG_POSIX_SEM_VALUE_MAX=32767 CONFIG_POSIX_MESSAGE_PASSING=y diff --git a/tests/posix/common/src/key.c b/tests/posix/common/src/key.c index e7486c5327ccb..e90f4862ff7b8 100644 --- a/tests/posix/common/src/key.c +++ b/tests/posix/common/src/key.c @@ -117,7 +117,7 @@ ZTEST(key, test_key_resource_leak) { pthread_key_t key; - for (size_t i = 0; i < CONFIG_MAX_PTHREAD_KEY_COUNT; ++i) { + for (size_t i = 0; i < CONFIG_POSIX_THREAD_KEYS_MAX; ++i) { zassert_ok(pthread_key_create(&key, NULL), "failed to create key %zu", i); zassert_ok(pthread_key_delete(key), "failed to delete key %zu", i); } @@ -126,8 +126,8 @@ ZTEST(key, test_key_resource_leak) ZTEST(key, test_correct_key_is_deleted) { pthread_key_t key; - size_t j = CONFIG_MAX_PTHREAD_KEY_COUNT - 1; - pthread_key_t keys[CONFIG_MAX_PTHREAD_KEY_COUNT]; + size_t j = CONFIG_POSIX_THREAD_KEYS_MAX - 1; + pthread_key_t keys[CONFIG_POSIX_THREAD_KEYS_MAX]; for (size_t i = 0; i < ARRAY_SIZE(keys); ++i) { zassert_ok(pthread_key_create(&keys[i], NULL), "failed to create key %zu", i); diff --git a/tests/posix/common/src/pthread.c b/tests/posix/common/src/pthread.c index 109bcb4e5c844..4fea9ed60ca51 100644 --- a/tests/posix/common/src/pthread.c +++ b/tests/posix/common/src/pthread.c @@ -382,7 +382,7 @@ ZTEST(pthread, test_pthread_descriptor_leak) pthread_t pthread1; /* If we are leaking descriptors, then this loop will never complete */ - for (size_t i = 0; i < CONFIG_MAX_PTHREAD_COUNT * 2; ++i) { + for (size_t i = 0; i < CONFIG_POSIX_THREAD_THREADS_MAX * 2; ++i) { zassert_ok(pthread_create(&pthread1, NULL, create_thread1, NULL), "unable to create thread %zu", i); zassert_ok(pthread_join(pthread1, NULL), "unable to join thread %zu", i); diff --git a/tests/posix/common/src/sysconf.c b/tests/posix/common/src/sysconf.c index 67929759925c2..363d93be36549 100644 --- a/tests/posix/common/src/sysconf.c +++ b/tests/posix/common/src/sysconf.c @@ -22,7 +22,7 @@ ZTEST(posix_apis, test_posix_sysconf) /* SC that value depends on target's configuration */ ret = sysconf(_SC_SEMAPHORES); - if (IS_ENABLED(CONFIG_PTHREAD_IPC)) { + if (IS_ENABLED(CONFIG_POSIX_THREADS)) { zassert_equal(ret, _POSIX_VERSION, "sysconf returned unexpected value %d", diff --git a/tests/posix/headers/prj.conf b/tests/posix/headers/prj.conf index 4a75f1ac46f8b..cfad8467f38eb 100644 --- a/tests/posix/headers/prj.conf +++ b/tests/posix/headers/prj.conf @@ -14,7 +14,7 @@ CONFIG_NETWORKING=y CONFIG_NET_SOCKETPAIR=y # for when CONFIG_POSIX_API is not selected -CONFIG_PTHREAD_IPC=y +CONFIG_POSIX_THREADS=y CONFIG_POSIX_FILE_SYSTEM=y CONFIG_POSIX_TIMERS=y CONFIG_POSIX_MESSAGE_PASSING=y diff --git a/tests/posix/pthread_pressure/src/main.c b/tests/posix/pthread_pressure/src/main.c index c7881de4e6f27..93484c3023449 100644 --- a/tests/posix/pthread_pressure/src/main.c +++ b/tests/posix/pthread_pressure/src/main.c @@ -21,7 +21,7 @@ #endif /* 32 threads is mainly a limitation of find_lsb_set() */ -#define NUM_THREADS MIN(32, MIN(CONFIG_TEST_NUM_CPUS, CONFIG_MAX_PTHREAD_COUNT)) +#define NUM_THREADS MIN(32, MIN(CONFIG_TEST_NUM_CPUS, CONFIG_POSIX_THREAD_THREADS_MAX)) typedef int (*create_fn)(int i); typedef int (*join_fn)(int i); From 2642eaa4e9a879b32a67ae4a627971a7316bb73e Mon Sep 17 00:00:00 2001 From: Chris Friedt Date: Thu, 23 May 2024 12:19:58 -0400 Subject: [PATCH 1745/2849] posix: relocate Kconfig.eventfd to Kconfig.compat While event file descriptors (eventfd) are extremely useful, the API has still not been formalized as part of the POSIX specification. Therefore, move this to a separate Kconfig menu for "compat" (compatibility) features. Signed-off-by: Chris Friedt --- lib/posix/options/Kconfig | 2 ++ lib/posix/options/{Kconfig.eventfd => Kconfig.compat} | 9 ++++++++- 2 files changed, 10 insertions(+), 1 deletion(-) rename lib/posix/options/{Kconfig.eventfd => Kconfig.compat} (87%) diff --git a/lib/posix/options/Kconfig b/lib/posix/options/Kconfig index 0157c8d884c29..ee5161da899b7 100644 --- a/lib/posix/options/Kconfig +++ b/lib/posix/options/Kconfig @@ -35,6 +35,8 @@ rsource "Kconfig.sync_io" rsource "Kconfig.timer" rsource "Kconfig.xsi" +rsource "Kconfig.compat" + rsource "Kconfig.deprecated" endmenu # "POSIX Options" diff --git a/lib/posix/options/Kconfig.eventfd b/lib/posix/options/Kconfig.compat similarity index 87% rename from lib/posix/options/Kconfig.eventfd rename to lib/posix/options/Kconfig.compat index eadf8f80916f6..680f12f1c1a44 100644 --- a/lib/posix/options/Kconfig.eventfd +++ b/lib/posix/options/Kconfig.compat @@ -3,6 +3,8 @@ # # SPDX-License-Identifier: Apache-2.0 +menu "Miscellaneous POSIX-related options" + menuconfig EVENTFD bool "Support for eventfd" depends on !NATIVE_APPLICATION @@ -14,10 +16,15 @@ menuconfig EVENTFD be used as an event wait/notify mechanism together with POSIX calls like read, write and poll. +if EVENTFD + config EVENTFD_MAX int "Maximum number of eventfd's" - depends on EVENTFD default 1 range 1 4096 help The maximum number of supported event file descriptors. + +endif # EVENTFD + +endmenu From 3f29b17bd1e91383ee4f29b911cfbb55fc50a937 Mon Sep 17 00:00:00 2001 From: Chris Friedt Date: Thu, 23 May 2024 12:52:03 -0400 Subject: [PATCH 1746/2849] posix: deprecate POSIX_SIGNAL in favour of POSIX_SIGNALS This change deprecates CONFIG_POSIX_SIGNAL in favour of the plural CONFIG_POSIX_SIGNALS, which maps directly to the name of the standard POSIX Option Group POSIX_SIGNALS. Additionally, mark signals as experimental. Signed-off-by: Chris Friedt --- doc/services/portability/posix/aep/index.rst | 2 +- doc/services/portability/posix/kconfig/index.rst | 1 - include/zephyr/posix/signal.h | 2 -- lib/libc/newlib/libc-hooks.c | 2 ++ lib/posix/options/CMakeLists.txt | 4 ++-- lib/posix/options/Kconfig.deprecated | 9 +++++++++ lib/posix/options/Kconfig.signal | 14 ++++++++------ modules/hostap/Kconfig | 2 +- tests/posix/headers/src/signal_h.c | 4 ++-- 9 files changed, 25 insertions(+), 15 deletions(-) diff --git a/doc/services/portability/posix/aep/index.rst b/doc/services/portability/posix/aep/index.rst index 6c7ff33de6870..fed46f9c47c04 100644 --- a/doc/services/portability/posix/aep/index.rst +++ b/doc/services/portability/posix/aep/index.rst @@ -51,7 +51,7 @@ The *Minimal Realtime System Profile* (PSE51) includes all of the :ref:`POSIX_C_LANG_JUMP `, yes, :ref:`POSIX_C_LANG_SUPPORT `, yes, :ref:`POSIX_DEVICE_IO `,, :kconfig:option:`CONFIG_POSIX_DEVICE_IO` - :ref:`POSIX_SIGNALS `,, + :ref:`POSIX_SIGNALS `,, :kconfig:option:`CONFIG_POSIX_SIGNALS` :ref:`POSIX_SINGLE_PROCESS `, yes, :kconfig:option:`CONFIG_POSIX_SINGLE_PROCESS` :ref:`XSI_THREADS_EXT `, yes, :kconfig:option:`CONFIG_XSI_THREADS_EXT` diff --git a/doc/services/portability/posix/kconfig/index.rst b/doc/services/portability/posix/kconfig/index.rst index 6c0f6d672a33c..d01cf549ed815 100644 --- a/doc/services/portability/posix/kconfig/index.rst +++ b/doc/services/portability/posix/kconfig/index.rst @@ -24,7 +24,6 @@ implementation of the POSIX API. * :kconfig:option:`CONFIG_POSIX_PTHREAD_ATTR_GUARDSIZE_DEFAULT` * :kconfig:option:`CONFIG_POSIX_PTHREAD_ATTR_STACKSIZE_BITS` * :kconfig:option:`CONFIG_POSIX_RTSIG_MAX` -* :kconfig:option:`CONFIG_POSIX_SIGNAL` * :kconfig:option:`CONFIG_POSIX_SIGNAL_STRING_DESC` * :kconfig:option:`CONFIG_POSIX_THREAD_KEYS_MAX` * :kconfig:option:`CONFIG_POSIX_THREAD_THREADS_MAX` diff --git a/include/zephyr/posix/signal.h b/include/zephyr/posix/signal.h index b6942f026a8fc..165050f2ded92 100644 --- a/include/zephyr/posix/signal.h +++ b/include/zephyr/posix/signal.h @@ -92,7 +92,6 @@ struct sigevent { int sigev_signo; }; -#ifdef CONFIG_POSIX_SIGNAL char *strsignal(int signum); int sigemptyset(sigset_t *set); int sigfillset(sigset_t *set); @@ -102,7 +101,6 @@ int sigismember(const sigset_t *set, int signo); int sigprocmask(int how, const sigset_t *ZRESTRICT set, sigset_t *ZRESTRICT oset); int pthread_sigmask(int how, const sigset_t *ZRESTRICT set, sigset_t *ZRESTRICT oset); -#endif /* CONFIG_POSIX_SIGNAL */ #ifdef __cplusplus } diff --git a/lib/libc/newlib/libc-hooks.c b/lib/libc/newlib/libc-hooks.c index 8cbb8f80ab9f1..5d1c8bd665d0d 100644 --- a/lib/libc/newlib/libc-hooks.c +++ b/lib/libc/newlib/libc-hooks.c @@ -261,11 +261,13 @@ int _isatty(int file) } __weak FUNC_ALIAS(_isatty, isatty, int); +#ifndef CONFIG_POSIX_SIGNALS int _kill(int i, int j) { return 0; } __weak FUNC_ALIAS(_kill, kill, int); +#endif /* CONFIG_POSIX_SIGNALS */ int _getpid(void) { diff --git a/lib/posix/options/CMakeLists.txt b/lib/posix/options/CMakeLists.txt index 1da0e64f99ad0..1e5d96b8c2c09 100644 --- a/lib/posix/options/CMakeLists.txt +++ b/lib/posix/options/CMakeLists.txt @@ -10,7 +10,7 @@ if(CONFIG_POSIX_API) zephyr_include_directories(${ZEPHYR_BASE}/include/zephyr/posix) endif() -if(CONFIG_POSIX_SIGNAL) +if(CONFIG_POSIX_SIGNALS) set(STRSIGNAL_TABLE_H ${GEN_DIR}/posix/strsignal_table.h) add_custom_command( @@ -58,7 +58,7 @@ zephyr_library_sources_ifdef(CONFIG_POSIX_MULTI_PROCESS sleep.c ) zephyr_library_sources_ifdef(CONFIG_POSIX_NETWORKING net.c) -zephyr_library_sources_ifdef(CONFIG_POSIX_SIGNAL signal.c ${STRSIGNAL_TABLE_H}) +zephyr_library_sources_ifdef(CONFIG_POSIX_SIGNALS signal.c ${STRSIGNAL_TABLE_H}) zephyr_library_sources_ifdef(CONFIG_POSIX_SINGLE_PROCESS confstr.c env.c diff --git a/lib/posix/options/Kconfig.deprecated b/lib/posix/options/Kconfig.deprecated index 83dc737bc3c2e..500783fd78ef9 100644 --- a/lib/posix/options/Kconfig.deprecated +++ b/lib/posix/options/Kconfig.deprecated @@ -156,6 +156,15 @@ config POSIX_PUTMSG Please use CONFIG_XOPEN_STREAMS instead. +config POSIX_SIGNAL + bool "Support for POSIX signal APIs [DEPRECATED]" + select DEPRECATED + select POSIX_SIGNALS + help + This option is deprecated. + + Please use CONFIG_POSIX_SIGNALS instead. + config POSIX_SYSCONF bool "Support for sysconf() [DEPRECATED]" select DEPRECATED diff --git a/lib/posix/options/Kconfig.signal b/lib/posix/options/Kconfig.signal index a25ac268d8ae9..81fcd6a696ce9 100644 --- a/lib/posix/options/Kconfig.signal +++ b/lib/posix/options/Kconfig.signal @@ -2,11 +2,12 @@ # # SPDX-License-Identifier: Apache-2.0 -menu "Signal support" +menu "POSIX signals" config POSIX_REALTIME_SIGNALS - bool "POSIX realtime signals" + bool "POSIX realtime signals [EXPERIMENTAL]" default y if POSIX_API + select EXPERIMENTAL help Enable support for POSIX realtime signals. @@ -21,13 +22,14 @@ config POSIX_RTSIG_MAX endif # POSIX_REALTIME_SIGNALS -config POSIX_SIGNAL - bool "Support for POSIX signal APIs" +config POSIX_SIGNALS + bool "POSIX signals [EXPERIMENTAL]" default y if POSIX_API + select EXPERIMENTAL help - Enable support for POSIX signal APIs. + Enable support for POSIX signals. -if POSIX_SIGNAL +if POSIX_SIGNALS config POSIX_SIGNAL_STRING_DESC bool "Use full description for the strsignal API" diff --git a/modules/hostap/Kconfig b/modules/hostap/Kconfig index ab6eadf837684..18bfc036c0578 100644 --- a/modules/hostap/Kconfig +++ b/modules/hostap/Kconfig @@ -8,7 +8,7 @@ config WIFI_NM_WPA_SUPPLICANT bool "WPA Suplicant from hostap project [EXPERIMENTAL]" select POSIX_TIMERS - select POSIX_SIGNAL + select POSIX_SIGNALS select POSIX_API select NET_SOCKETS select NET_SOCKETS_PACKET diff --git a/tests/posix/headers/src/signal_h.c b/tests/posix/headers/src/signal_h.c index 9d0be5778d714..35616e4a29e54 100644 --- a/tests/posix/headers/src/signal_h.c +++ b/tests/posix/headers/src/signal_h.c @@ -130,7 +130,7 @@ ZTEST(posix_headers, test_signal_h) /* zassert_not_equal(-1, SI_ASYNCIO); */ /* not implemented */ /* zassert_not_equal(-1, SI_MESGQ); */ /* not implemented */ -#ifdef CONFIG_POSIX_SIGNAL +#ifdef CONFIG_POSIX_SIGNALS zassert_true(SIGRTMIN >= 0); zassert_true(SIGRTMAX >= SIGRTMIN); zassert_not_equal(-1, SIGABRT); @@ -166,7 +166,7 @@ ZTEST(posix_headers, test_signal_h) zassert_not_null(strsignal); zassert_not_null(sigprocmask); zassert_not_null(pthread_sigmask); -#endif /* CONFIG_POSIX_SIGNAL */ +#endif /* CONFIG_POSIX_SIGNALS */ if (IS_ENABLED(CONFIG_POSIX_API)) { /* zassert_not_null(kill); */ /* not implemented */ From 2e429f1b9d8094a5aab5dd9bbdd3e9b462745d77 Mon Sep 17 00:00:00 2001 From: Chris Friedt Date: Thu, 23 May 2024 12:52:34 -0400 Subject: [PATCH 1747/2849] posix: reword aio and sched options. add experimental The asynchronous I/O and (process) scheduling options needed minor rewording. Additionally, add the experimental flag to each of them since they are not yet supported. Signed-off-by: Chris Friedt --- lib/posix/options/Kconfig.aio | 3 ++- lib/posix/options/Kconfig.sched | 16 +++++++++++++--- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/lib/posix/options/Kconfig.aio b/lib/posix/options/Kconfig.aio index 6fc35349738f3..cf99ae1d30c52 100644 --- a/lib/posix/options/Kconfig.aio +++ b/lib/posix/options/Kconfig.aio @@ -3,8 +3,9 @@ # SPDX-License-Identifier: Apache-2.0 config POSIX_ASYNCHRONOUS_IO - bool "Asynchronous IO" + bool "POSIX asynchronous I/O [EXPERIMENTAL]" default y if POSIX_API + select EXPERIMENTAL help Enable this option for asynchronous I/O. This option is present for conformance purposes only. All functions listed in return -1 and set errno to ENOSYS. diff --git a/lib/posix/options/Kconfig.sched b/lib/posix/options/Kconfig.sched index c6ea53be8f1ff..f8dbbf6931b2e 100644 --- a/lib/posix/options/Kconfig.sched +++ b/lib/posix/options/Kconfig.sched @@ -2,10 +2,20 @@ # # SPDX-License-Identifier: Apache-2.0 +menu "POSIX scheduler options" + config POSIX_PRIORITY_SCHEDULING - bool "Priority scheduling" - default y if POSIX_THREADS + bool "POSIX priority-based process scheduling [EXPERIMENTAL]" default y if POSIX_API - depends on POSIX_THREADS + select EXPERIMENTAL help This enables POSIX scheduling APIs (_POSIX_PRIORITY_SCHEDULING). + + Since Zephyr does not yet support processes, most of this behaviour is undefined, except for + use of sched_get_priority_min() and sched_get_priority_max(). + + For more information, please see + https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_port.html#tag_24_03_04 + https://pubs.opengroup.org/onlinepubs/9699919799/functions/sched_get_priority_max.html + +endmenu From b051bcee25f9947e7fa8de765002f95d0c70abac Mon Sep 17 00:00:00 2001 From: Chris Friedt Date: Thu, 23 May 2024 13:51:14 -0400 Subject: [PATCH 1748/2849] posix: move getpid() to Kconfig.procN and doc MULTI_PROCESS Create a Kconfig option for POSIX_MULTI_PROCESS Option Group and mark it as experimental. Currently, Zephyr has two functions that belong to this Option Group: - sleep() - getpid() Signed-off-by: Chris Friedt --- doc/services/portability/posix/aep/index.rst | 2 +- .../portability/posix/option_groups/index.rst | 34 +++++++++++++++++++ lib/libc/Kconfig | 1 + lib/libc/newlib/libc-hooks.c | 17 ++++++---- lib/posix/options/CMakeLists.txt | 1 + lib/posix/options/Kconfig.procN | 15 +++++++- lib/posix/options/multi_process.c | 23 +++++++++++++ lib/posix/options/pthread.c | 16 --------- 8 files changed, 85 insertions(+), 24 deletions(-) create mode 100644 lib/posix/options/multi_process.c diff --git a/doc/services/portability/posix/aep/index.rst b/doc/services/portability/posix/aep/index.rst index fed46f9c47c04..8075828e99a2d 100644 --- a/doc/services/portability/posix/aep/index.rst +++ b/doc/services/portability/posix/aep/index.rst @@ -140,7 +140,7 @@ The *Dedicated Realtime System Profile* (PSE53) includes all features from PSE52 :header: Symbol, Support, Remarks :widths: 50, 10, 50 - POSIX_MULTI_PROCESS,, :ref:`†` + :ref:`POSIX_MULTI_PROCESS`,, :kconfig:option:`CONFIG_POSIX_MULTI_PROCESS`:ref:`†` :ref:`POSIX_NETWORKING `, yes, :ref:`POSIX_PIPE `,, :ref:`POSIX_SIGNAL_JUMP `,, diff --git a/doc/services/portability/posix/option_groups/index.rst b/doc/services/portability/posix/option_groups/index.rst index a71d753204cb1..da025b52be426 100644 --- a/doc/services/portability/posix/option_groups/index.rst +++ b/doc/services/portability/posix/option_groups/index.rst @@ -559,6 +559,40 @@ This table lists service support status in Zephyr for `POSIX_FD_MGMT`: putc_unlocked(), putchar_unlocked(), +.. _posix_option_group_multi_process: + +POSIX_MULTI_PROCESS +=================== + +.. csv-table:: POSIX_MULTI_PROCESS + :header: API, Supported + :widths: 50,10 + + _Exit(), yes + _exit(), yes + assert(), yes + atexit(),:ref:`†` + clock(), + execl(),:ref:`†` + execle(),:ref:`†` + execlp(),:ref:`†` + execv(),:ref:`†` + execve(),:ref:`†` + execvp(),:ref:`†` + exit(), yes + fork(),:ref:`†` + getpgrp(),:ref:`†` + getpgid(),:ref:`†` + getpid(), yes :ref:`†` + getppid(),:ref:`†` + getsid(),:ref:`†` + setsid(),:ref:`†` + sleep(),yes + times(), + wait(),:ref:`†` + waitid(),:ref:`†` + waitpid(),:ref:`†` + .. _posix_options: Additional POSIX Options diff --git a/lib/libc/Kconfig b/lib/libc/Kconfig index af3230554dd88..c04207017cf83 100644 --- a/lib/libc/Kconfig +++ b/lib/libc/Kconfig @@ -108,6 +108,7 @@ config NEWLIB_LIBC imply POSIX_DEVICE_IO_ALIAS_WRITE imply POSIX_FD_MGMT_ALIAS_LSEEK imply POSIX_FILE_SYSTEM_ALIAS_FSTAT + imply POSIX_MULTI_PROCESS_ALIAS_GETPID help Build with newlib library. The newlib library is expected to be part of the SDK in this case. diff --git a/lib/libc/newlib/libc-hooks.c b/lib/libc/newlib/libc-hooks.c index 5d1c8bd665d0d..3db4f2c885f03 100644 --- a/lib/libc/newlib/libc-hooks.c +++ b/lib/libc/newlib/libc-hooks.c @@ -29,6 +29,8 @@ int _write(int fd, const void *buf, int nbytes); int _open(const char *name, int mode); int _close(int file); int _lseek(int file, int ptr, int dir); +int _kill(int pid, int sig); +int _getpid(void); #define LIBC_BSS K_APP_BMEM(z_libc_partition) #define LIBC_DATA K_APP_DMEM(z_libc_partition) @@ -269,12 +271,6 @@ int _kill(int i, int j) __weak FUNC_ALIAS(_kill, kill, int); #endif /* CONFIG_POSIX_SIGNALS */ -int _getpid(void) -{ - return 0; -} -__weak FUNC_ALIAS(_getpid, getpid, int); - #ifndef CONFIG_POSIX_FILE_SYSTEM int _fstat(int file, struct stat *st) { @@ -284,6 +280,15 @@ int _fstat(int file, struct stat *st) __weak FUNC_ALIAS(_fstat, fstat, int); #endif /* CONFIG_POSIX_FILE_SYSTEM */ +#ifndef CONFIG_POSIX_MULTI_PROCESS +int _getpid(void) +{ + return 0; +} +__weak FUNC_ALIAS(_getpid, getpid, int); + +#endif /* CONFIG_POSIX_MULTI_PROCESS */ + __weak void _exit(int status) { _write(1, "exit\n", 5); diff --git a/lib/posix/options/CMakeLists.txt b/lib/posix/options/CMakeLists.txt index 1e5d96b8c2c09..c67ef4807acec 100644 --- a/lib/posix/options/CMakeLists.txt +++ b/lib/posix/options/CMakeLists.txt @@ -56,6 +56,7 @@ zephyr_library_sources_ifdef(CONFIG_POSIX_FSYNC fsync.c) zephyr_library_sources_ifdef(CONFIG_POSIX_MESSAGE_PASSING mqueue.c) zephyr_library_sources_ifdef(CONFIG_POSIX_MULTI_PROCESS sleep.c + multi_process.c ) zephyr_library_sources_ifdef(CONFIG_POSIX_NETWORKING net.c) zephyr_library_sources_ifdef(CONFIG_POSIX_SIGNALS signal.c ${STRSIGNAL_TABLE_H}) diff --git a/lib/posix/options/Kconfig.procN b/lib/posix/options/Kconfig.procN index 3e22fcf137135..7cc248e1abee0 100644 --- a/lib/posix/options/Kconfig.procN +++ b/lib/posix/options/Kconfig.procN @@ -2,7 +2,7 @@ # # SPDX-License-Identifier: Apache-2.0 -config POSIX_MULTI_PROCESS +menuconfig POSIX_MULTI_PROCESS bool "POSIX multi-process support [EXPERIMENTAL]" default y if POSIX_API select EXPERIMENTAL @@ -14,3 +14,16 @@ config POSIX_MULTI_PROCESS For more information, please see https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_subprofiles.html + +if POSIX_MULTI_PROCESS + +# These options are intended to be used for compatibility with external POSIX +# implementations such as those in Newlib or Picolibc. + +config POSIX_MULTI_PROCESS_ALIAS_GETPID + bool + default y + help + Select 'y' here and Zephyr will provide an alias for getpid() as _getpid(). + +endif # POSIX_MULTI_PROCESS diff --git a/lib/posix/options/multi_process.c b/lib/posix/options/multi_process.c new file mode 100644 index 0000000000000..221dc04ae1ad9 --- /dev/null +++ b/lib/posix/options/multi_process.c @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2024, Tenstorrent AI ULC + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +pid_t getpid(void) +{ + /* + * To maintain compatibility with some other POSIX operating systems, + * a PID of zero is used to indicate that the process exists in another namespace. + * PID zero is also used by the scheduler in some cases. + * PID one is usually reserved for the init process. + * Also note, that negative PIDs may be used by kill() + * to send signals to process groups in some implementations. + * + * At the moment, getpid just returns an arbitrary number >= 2 + */ + + return 42; +} diff --git a/lib/posix/options/pthread.c b/lib/posix/options/pthread.c index 8e9e33ad86141..d9748c64637a7 100644 --- a/lib/posix/options/pthread.c +++ b/lib/posix/options/pthread.c @@ -188,22 +188,6 @@ int pthread_equal(pthread_t pt1, pthread_t pt2) return (pt1 == pt2); } -pid_t getpid(void) -{ - /* - * To maintain compatibility with some other POSIX operating systems, - * a PID of zero is used to indicate that the process exists in another namespace. - * PID zero is also used by the scheduler in some cases. - * PID one is usually reserved for the init process. - * Also note, that negative PIDs may be used by kill() - * to send signals to process groups in some implementations. - * - * At the moment, getpid just returns an arbitrary number >= 2 - */ - - return 42; -} - static inline void __z_pthread_cleanup_init(struct __pthread_cleanup *c, void (*routine)(void *arg), void *arg) { From 16409671738dfd0d9576c4b7cfe4cc23000f2549 Mon Sep 17 00:00:00 2001 From: Chris Friedt Date: Thu, 23 May 2024 13:51:34 -0400 Subject: [PATCH 1749/2849] doc: posix: clean up some Kconfig options Add links to POSIX-related Kconfig options that are related to POSIX Options and Option Groups. These include limits that might not have an associated standard name and related Kconfig variables in other subsystems. Signed-off-by: Chris Friedt --- doc/services/portability/posix/kconfig/index.rst | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/doc/services/portability/posix/kconfig/index.rst b/doc/services/portability/posix/kconfig/index.rst index d01cf549ed815..56574909eb13e 100644 --- a/doc/services/portability/posix/kconfig/index.rst +++ b/doc/services/portability/posix/kconfig/index.rst @@ -1,11 +1,13 @@ .. _posix_kconfig_options: -Configuration Options -********************* +Additional Configuration Options +******************************** -This is a non-exhaustive list of specific :ref:`kconfig` options relating to Zephyr's +Below is a non-exhaustive list of additional :ref:`kconfig` options relating to Zephyr's implementation of the POSIX API. +* :kconfig:option:`CONFIG_DYNAMIC_THREAD` +* :kconfig:option:`CONFIG_DYNAMIC_THREAD_POOL_SIZE` * :kconfig:option:`CONFIG_EVENTFD` * :kconfig:option:`CONFIG_EVENTFD_MAX` * :kconfig:option:`CONFIG_FDTABLE` @@ -17,8 +19,8 @@ implementation of the POSIX API. * :kconfig:option:`CONFIG_NET_SOCKETPAIR` * :kconfig:option:`CONFIG_NET_SOCKETS` * :kconfig:option:`CONFIG_NET_SOCKETS_POLL_MAX` -* :kconfig:option:`CONFIG_POSIX_API` * :kconfig:option:`CONFIG_ZVFS_OPEN_MAX` +* :kconfig:option:`CONFIG_POSIX_API` * :kconfig:option:`CONFIG_POSIX_OPEN_MAX` * :kconfig:option:`CONFIG_POSIX_PTHREAD_ATTR_GUARDSIZE_BITS` * :kconfig:option:`CONFIG_POSIX_PTHREAD_ATTR_GUARDSIZE_DEFAULT` @@ -35,3 +37,4 @@ implementation of the POSIX API. * :kconfig:option:`CONFIG_POSIX_SEM_NSEMS_MAX` * :kconfig:option:`CONFIG_POSIX_SEM_VALUE_MAX` * :kconfig:option:`CONFIG_TIMER_CREATE_WAIT` +* :kconfig:option:`CONFIG_THREAD_STACK_INFO` From 3949e893309641d33e15fdf61289606f30b00b22 Mon Sep 17 00:00:00 2001 From: Chris Friedt Date: Thu, 23 May 2024 13:56:35 -0400 Subject: [PATCH 1750/2849] posix: net: update for POSIX_NETWORKING Add a link to the Kconfig option CONFIG_POSIX_NETWORKING in the documentation. Additionally, add Kconfig options for other Network dependencies in an effort to make POSIX Kconfig options consistent with the specification. Signed-off-by: Chris Friedt --- doc/services/portability/posix/aep/index.rst | 4 +- .../portability/posix/conformance/index.rst | 4 +- .../portability/posix/option_groups/index.rst | 18 ++++++++ include/zephyr/posix/posix_features.h | 2 +- lib/posix/options/Kconfig.net | 42 ++++++++++++++++++- lib/posix/options/net.c | 18 +------- tests/posix/common/prj.conf | 1 + tests/posix/fs/prj.conf | 1 + tests/posix/net/prj.conf | 6 ++- tests/posix/pthread_pressure/prj.conf | 1 + 10 files changed, 72 insertions(+), 25 deletions(-) diff --git a/doc/services/portability/posix/aep/index.rst b/doc/services/portability/posix/aep/index.rst index 8075828e99a2d..b70ec23c92bd5 100644 --- a/doc/services/portability/posix/aep/index.rst +++ b/doc/services/portability/posix/aep/index.rst @@ -141,7 +141,7 @@ The *Dedicated Realtime System Profile* (PSE53) includes all features from PSE52 :widths: 50, 10, 50 :ref:`POSIX_MULTI_PROCESS`,, :kconfig:option:`CONFIG_POSIX_MULTI_PROCESS`:ref:`†` - :ref:`POSIX_NETWORKING `, yes, + :ref:`POSIX_NETWORKING `, yes, :kconfig:option:`CONFIG_POSIX_NETWORKING` :ref:`POSIX_PIPE `,, :ref:`POSIX_SIGNAL_JUMP `,, @@ -152,7 +152,7 @@ The *Dedicated Realtime System Profile* (PSE53) includes all features from PSE52 :ref:`_POSIX_CPUTIME `, 200809L, :kconfig:option:`CONFIG_POSIX_CPUTIME` _POSIX_PRIORITIZED_IO, -1, :ref:`_POSIX_PRIORITY_SCHEDULING `, -1, - _POSIX_RAW_SOCKETS, 200809L, :kconfig:option:`CONFIG_NET_SOCKETS_PACKET` + :ref:`_POSIX_RAW_SOCKETS `, 200809L, :kconfig:option:`CONFIG_POSIX_RAW_SOCKETS` _POSIX_SPAWN, -1, :ref:`†` _POSIX_SPORADIC_SERVER, -1, :ref:`†` diff --git a/doc/services/portability/posix/conformance/index.rst b/doc/services/portability/posix/conformance/index.rst index 81a2dfc90e475..fccff530a4bce 100644 --- a/doc/services/portability/posix/conformance/index.rst +++ b/doc/services/portability/posix/conformance/index.rst @@ -83,14 +83,14 @@ POSIX System Interfaces _POSIX_ADVISORY_INFO, -1, :ref:`_POSIX_CPUTIME`, 200809L, :kconfig:option:`CONFIG_POSIX_CPUTIME` :ref:`_POSIX_FSYNC`, 200809L, :kconfig:option:`CONFIG_POSIX_FSYNC` - _POSIX_IPV6, 200809L, :kconfig:option:`CONFIG_NET_IPV6` + :ref:`_POSIX_IPV6`, 200809L, :kconfig:option:`CONFIG_POSIX_IPV6` _POSIX_MEMLOCK, -1, _POSIX_MEMLOCK_RANGE, -1, :ref:`_POSIX_MESSAGE_PASSING`, 200809L, :kconfig:option:`CONFIG_POSIX_MESSAGE_PASSING` :ref:`_POSIX_MONOTONIC_CLOCK`, 200809L, :kconfig:option:`CONFIG_POSIX_MONOTONIC_CLOCK` _POSIX_PRIORITIZED_IO, -1, :ref:`_POSIX_PRIORITY_SCHEDULING`, 200809L, :kconfig:option:`CONFIG_POSIX_PRIORITY_SCHEDULING` - _POSIX_RAW_SOCKETS, 200809L, :kconfig:option:`CONFIG_NET_SOCKETS_PACKET` + :ref:`_POSIX_RAW_SOCKETS`, 200809L, :kconfig:option:`CONFIG_POSIX_RAW_SOCKETS` _POSIX_SHARED_MEMORY_OBJECTS, -1, _POSIX_SPAWN, -1, :ref:`†` _POSIX_SPORADIC_SERVER, -1, :ref:`†` diff --git a/doc/services/portability/posix/option_groups/index.rst b/doc/services/portability/posix/option_groups/index.rst index da025b52be426..d07498ce639d4 100644 --- a/doc/services/portability/posix/option_groups/index.rst +++ b/doc/services/portability/posix/option_groups/index.rst @@ -638,6 +638,15 @@ _POSIX_FSYNC fsync(),yes +.. _posix_option_ipv6: + +_POSIX_IPV6 ++++++++++++ + +Internet Protocol Version 6 is supported. + +For more information, please refer to :ref:`Networking `. + .. _posix_option_memlock: _POSIX_MEMLOCK @@ -709,6 +718,15 @@ _POSIX_PRIORITY_SCHEDULING sched_setscheduler(),yes (will fail with ``ENOSYS``:ref:`†`) sched_yield(),yes +.. _posix_option_raw_sockets: + +_POSIX_RAW_SOCKETS +++++++++++++++++++ + +Raw sockets are supported. + +For more information, please refer to :kconfig:option:`CONFIG_NET_SOCKETS_PACKET`. + .. _posix_option_reader_writer_locks: _POSIX_READER_WRITER_LOCKS diff --git a/include/zephyr/posix/posix_features.h b/include/zephyr/posix/posix_features.h index 0ff2f37158264..ccf5e314b9950 100644 --- a/include/zephyr/posix/posix_features.h +++ b/include/zephyr/posix/posix_features.h @@ -207,7 +207,7 @@ #define _POSIX_DELAYTIMER_MAX \ COND_CODE_1(CONFIG_POSIX_TIMERS, (CONFIG_POSIX_DELAYTIMER_MAX), (0)) #define _POSIX_HOST_NAME_MAX \ - COND_CODE_1(CONFIG_NET_HOSTNAME_MAX_LEN, (NET_HOSTNAME_MAX_LEN), (0)) + COND_CODE_1(CONFIG_POSIX_NETWORKING, (CONFIG_POSIX_HOST_NAME_MAX), (0)) #define _POSIX_LINK_MAX (8) #define _POSIX_LOGIN_NAME_MAX (9) #define _POSIX_MAX_CANON (255) diff --git a/lib/posix/options/Kconfig.net b/lib/posix/options/Kconfig.net index 5e2b363e167df..f63aaaf141152 100644 --- a/lib/posix/options/Kconfig.net +++ b/lib/posix/options/Kconfig.net @@ -2,10 +2,48 @@ # # SPDX-License-Identifier: Apache-2.0 -config POSIX_NETWORKING +menuconfig POSIX_NETWORKING bool "POSIX Networking API" - default y if POSIX_API depends on NETWORKING + select NET_HOSTNAME_ENABLE + select NET_HOSTNAME_DYNAMIC + select NET_INTERFACE_NAME + select NET_SOCKETPAIR + select NET_SOCKETS help Enable this option to support the POSIX networking API. This includes support for BSD Sockets. + + For additional details, please see + https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_subprofiles.html + +if POSIX_NETWORKING + +config POSIX_HOST_NAME_MAX + int + default NET_HOSTNAME_MAX_LEN + help + The maximum length of a host name as defined by POSIX. + + For additional details, please see + https://pubs.opengroup.org/onlinepubs/009695399/basedefs/limits.h.html + +config POSIX_IPV6 + bool "POSIX IPv6 support" + select NET_IPV6 + help + Enable this option to support the POSIX IPv6 API. + + For more information, please see + https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_port.html#tag_24_03_04 + +config POSIX_RAW_SOCKETS + bool "POSIX RAW socket support" + select NET_SOCKETS_PACKET + help + Enable this option to support the raw sockets. + + For more information, please see + https://pubs.opengroup.org/onlinepubs/9699919799.2008edition/xrat/V4_xsh_chap02.html#tag_22_02_10_18 + +endif # POSIX_NETWORKING diff --git a/lib/posix/options/net.c b/lib/posix/options/net.c index 618c630630ecd..84e4001a9b40d 100644 --- a/lib/posix/options/net.c +++ b/lib/posix/options/net.c @@ -100,11 +100,6 @@ char *if_indextoname(unsigned int ifindex, char *ifname) { int ret; - if (!IS_ENABLED(CONFIG_NET_INTERFACE_NAME)) { - errno = ENOTSUP; - return NULL; - } - ret = net_if_get_name(net_if_get_by_index(ifindex), ifname, IF_NAMESIZE); if (ret < 0) { errno = ENXIO; @@ -118,14 +113,14 @@ void if_freenameindex(struct if_nameindex *ptr) { size_t n; - if (ptr == NULL || !IS_ENABLED(CONFIG_NET_INTERFACE_NAME)) { + if (ptr == NULL) { return; } NET_IFACE_COUNT(&n); for (size_t i = 0; i < n; ++i) { - if (IS_ENABLED(CONFIG_NET_INTERFACE_NAME) && ptr[i].if_name != NULL) { + if (ptr[i].if_name != NULL) { free(ptr[i].if_name); } } @@ -139,11 +134,6 @@ struct if_nameindex *if_nameindex(void) char *name; struct if_nameindex *ni; - if (!IS_ENABLED(CONFIG_NET_INTERFACE_NAME)) { - errno = ENOTSUP; - return NULL; - } - /* FIXME: would be nice to use this without malloc */ NET_IFACE_COUNT(&n); ni = malloc((n + 1) * sizeof(*ni)); @@ -179,10 +169,6 @@ unsigned int if_nametoindex(const char *ifname) { int ret; - if (!IS_ENABLED(CONFIG_NET_INTERFACE_NAME)) { - return 0; - } - ret = net_if_get_by_name(ifname); if (ret < 0) { return 0; diff --git a/tests/posix/common/prj.conf b/tests/posix/common/prj.conf index ff61f29c7b5c7..51c709dee7bc6 100644 --- a/tests/posix/common/prj.conf +++ b/tests/posix/common/prj.conf @@ -1,6 +1,7 @@ CONFIG_POSIX_API=y CONFIG_POSIX_THREAD_THREADS_MAX=6 CONFIG_ZTEST=y +CONFIG_POSIX_NETWORKING=n CONFIG_POSIX_SEM_VALUE_MAX=32767 CONFIG_POSIX_MESSAGE_PASSING=y CONFIG_POSIX_PRIORITY_SCHEDULING=y diff --git a/tests/posix/fs/prj.conf b/tests/posix/fs/prj.conf index da73481ef4d1a..ce47ef9f097c9 100644 --- a/tests/posix/fs/prj.conf +++ b/tests/posix/fs/prj.conf @@ -4,5 +4,6 @@ CONFIG_FAT_FILESYSTEM_ELM=y CONFIG_POSIX_API=y CONFIG_POSIX_FILE_SYSTEM=y CONFIG_ZTEST=y +CONFIG_POSIX_NETWORKING=n CONFIG_MAIN_STACK_SIZE=4096 CONFIG_EVENTFD=n diff --git a/tests/posix/net/prj.conf b/tests/posix/net/prj.conf index 4831a9d150f5b..0b840d09dfdc4 100644 --- a/tests/posix/net/prj.conf +++ b/tests/posix/net/prj.conf @@ -1,4 +1,6 @@ CONFIG_ZTEST=y -CONFIG_NETWORKING=y -CONFIG_POSIX_NETWORKING=y CONFIG_NET_TEST=y +CONFIG_TEST_RANDOM_GENERATOR=y + +CONFIG_POSIX_API=y +CONFIG_POSIX_NETWORKING=y diff --git a/tests/posix/pthread_pressure/prj.conf b/tests/posix/pthread_pressure/prj.conf index ba9a5f8487a2a..e2b190b19feea 100644 --- a/tests/posix/pthread_pressure/prj.conf +++ b/tests/posix/pthread_pressure/prj.conf @@ -1,5 +1,6 @@ CONFIG_ZTEST=y CONFIG_POSIX_API=y +CONFIG_POSIX_NETWORKING=n ## Note: for benchmarking purposes, uncomment the Kconfig below # CONFIG_TEST_DURATION_S=60 From b003636b2b8283b08c6b1175bb2945fb47ae1f41 Mon Sep 17 00:00:00 2001 From: Chris Friedt Date: Fri, 24 May 2024 13:30:59 -0400 Subject: [PATCH 1751/2849] doc: posix: misc cleanup and add links to system interfaces memlock, memlock range, shared memory objects, and synchronized io were missing links. Also, vdisable is '\0' (not 0). Signed-off-by: Chris Friedt --- .../portability/posix/conformance/index.rst | 71 ++++++++++--------- 1 file changed, 36 insertions(+), 35 deletions(-) diff --git a/doc/services/portability/posix/conformance/index.rst b/doc/services/portability/posix/conformance/index.rst index fccff530a4bce..7de7fc26e3e9e 100644 --- a/doc/services/portability/posix/conformance/index.rst +++ b/doc/services/portability/posix/conformance/index.rst @@ -5,22 +5,6 @@ POSIX Conformance As per `IEEE 1003.1-2017`, this section details Zephyr's POSIX conformance. -.. _posix_undefined_behaviour: - -.. note:: - As per POSIX 1003.13, single process mode is supported directly by both PSE51 and PSE52 - profiles. While Zephyr includes support for many features found in PSE53, PSE53 itself requires - supporting multiple processes. Since supporting multiple processes is beyond the scope of - Zephyr's current design, some features requiring multi-process capabilities may exhibit - undefined behaviour, which we denote with the † (obelus) symbol. - -.. _posix_libc_provided: - -.. note:: - Features listed in various POSIX Options or Option Groups may be provided in whole or in part - by a conformant C library implementation. This includes (but is not limited to) POSIX - Extensions to the ISO C Standard (`CX`_). - .. _posix_system_interfaces: POSIX System Interfaces @@ -34,19 +18,7 @@ POSIX System Interfaces _POSIX_CHOWN_RESTRICTED, 0, _POSIX_NO_TRUNC, 0, - _POSIX_VDISABLE, 0, - -.. The following should be valued greater than zero in Zephyr, in order to be strictly conformant - with the POSIX specification. - -.. csv-table:: POSIX System Interfaces - :header: Symbol, Support, Remarks - :widths: 50, 10, 50 - - _POSIX_JOB_CONTROL, -1, :ref:`†` - _POSIX_REGEXP, -1, :ref:`†` - _POSIX_SAVED_IDS, -1, :ref:`†` - _POSIX_SHELL, -1, :ref:`†` + _POSIX_VDISABLE, ``'\0'``, .. TODO: POSIX_ASYNCHRONOUS_IO, and other interfaces below, are mandatory. That means that a strictly conforming application need not be modified in order to compile against Zephyr. @@ -76,6 +48,18 @@ POSIX System Interfaces :ref:`_POSIX_TIMERS`, 200809L, :kconfig:option:`CONFIG_POSIX_TIMERS` _POSIX2_C_BIND, 200809L, +.. The following should be valued greater than zero in Zephyr, in order to be strictly conformant + with the POSIX specification. + +.. csv-table:: POSIX System Interfaces (Unsupported) + :header: Symbol, Support, Remarks + :widths: 50, 10, 50 + + _POSIX_JOB_CONTROL, -1, :ref:`†` + _POSIX_REGEXP, -1, :ref:`†` + _POSIX_SAVED_IDS, -1, :ref:`†` + _POSIX_SHELL, -1, :ref:`†` + .. csv-table:: POSIX System Interfaces (Optional) :header: Symbol, Support, Remarks :widths: 50, 10, 50 @@ -84,14 +68,14 @@ POSIX System Interfaces :ref:`_POSIX_CPUTIME`, 200809L, :kconfig:option:`CONFIG_POSIX_CPUTIME` :ref:`_POSIX_FSYNC`, 200809L, :kconfig:option:`CONFIG_POSIX_FSYNC` :ref:`_POSIX_IPV6`, 200809L, :kconfig:option:`CONFIG_POSIX_IPV6` - _POSIX_MEMLOCK, -1, - _POSIX_MEMLOCK_RANGE, -1, + :ref:`_POSIX_MEMLOCK `, -1, + :ref:`_POSIX_MEMLOCK_RANGE `, -1, :ref:`_POSIX_MESSAGE_PASSING`, 200809L, :kconfig:option:`CONFIG_POSIX_MESSAGE_PASSING` :ref:`_POSIX_MONOTONIC_CLOCK`, 200809L, :kconfig:option:`CONFIG_POSIX_MONOTONIC_CLOCK` _POSIX_PRIORITIZED_IO, -1, :ref:`_POSIX_PRIORITY_SCHEDULING`, 200809L, :kconfig:option:`CONFIG_POSIX_PRIORITY_SCHEDULING` :ref:`_POSIX_RAW_SOCKETS`, 200809L, :kconfig:option:`CONFIG_POSIX_RAW_SOCKETS` - _POSIX_SHARED_MEMORY_OBJECTS, -1, + :ref:`_POSIX_SHARED_MEMORY_OBJECTS `, -1, _POSIX_SPAWN, -1, :ref:`†` _POSIX_SPORADIC_SERVER, -1, :ref:`†` :ref:`_POSIX_SYNCHRONIZED_IO `, -1, :kconfig:option:`CONFIG_POSIX_SYNCHRONIZED_IO` @@ -114,6 +98,7 @@ POSIX System Interfaces :ref:`_XOPEN_STREAMS`, 200809L, :kconfig:option:`CONFIG_XOPEN_STREAMS` _XOPEN_UNIX, -1, + POSIX Shell and Utilities ========================= @@ -141,10 +126,10 @@ Zephyr does not support a POSIX shell or utilities at this time. XSI Conformance ############### -XSI System Interfaces -===================== +X/Open System Interfaces +======================== -.. csv-table:: XSI System Interfaces +.. csv-table:: X/Open System Interfaces :header: Symbol, Support, Remarks :widths: 50, 10, 50 @@ -153,4 +138,20 @@ XSI System Interfaces :ref:`_POSIX_THREAD_ATTR_STACKSIZE`, 200809L, :kconfig:option:`CONFIG_POSIX_THREAD_ATTR_STACKSIZE` _POSIX_THREAD_PROCESS_SHARED, -1, +.. _posix_undefined_behaviour: + +.. note:: + Some features may exhibit undefined behaviour as they fall beyond the scope of Zephyr's current + design and capabilities. For example, multi-processing, ad-hoc memory-mapping, multiple users, + or regular expressions are features that are uncommon in low-footprint embedded systems. + Such undefined behaviour is denoted with the † (obelus) symbol. Additional details + :ref:`here `. + +.. _posix_libc_provided: + +.. note:: + Features listed in various POSIX Options or Option Groups may be provided in whole or in part + by a conformant C library implementation. This includes (but is not limited to) POSIX + Extensions to the ISO C Standard (`CX`_). + .. _CX: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap01.html From b3e36ad6e8b0f7ae163c18716dbdd27d6fc8cbf7 Mon Sep 17 00:00:00 2001 From: Chris Friedt Date: Tue, 28 May 2024 18:37:18 -0400 Subject: [PATCH 1752/2849] posix: eventfd: remove deprecated eventfd macros Remove the EFD_IN_USE and EFD_FLAGS_SET macros as they were not part of the public API. Rename the internal versions, accordingly. Signed-off-by: Chris Friedt --- include/zephyr/posix/sys/eventfd.h | 2 -- lib/posix/options/eventfd.c | 16 ++++++++-------- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/include/zephyr/posix/sys/eventfd.h b/include/zephyr/posix/sys/eventfd.h index 8f1443d7a9aac..5d8c48f6e21ff 100644 --- a/include/zephyr/posix/sys/eventfd.h +++ b/include/zephyr/posix/sys/eventfd.h @@ -16,10 +16,8 @@ extern "C" { #endif -#define EFD_IN_USE 0x1 __DEPRECATED_MACRO #define EFD_SEMAPHORE 0x2 #define EFD_NONBLOCK O_NONBLOCK -#define EFD_FLAGS_SET (EFD_SEMAPHORE | EFD_NONBLOCK) __DEPRECATED_MACRO typedef uint64_t eventfd_t; diff --git a/lib/posix/options/eventfd.c b/lib/posix/options/eventfd.c index 81b8f6d6dd810..60d327e4fd1f0 100644 --- a/lib/posix/options/eventfd.c +++ b/lib/posix/options/eventfd.c @@ -13,8 +13,8 @@ #include #include -#define EFD_IN_USE_INTERNAL 0x1 -#define EFD_FLAGS_SET_INTERNAL (EFD_SEMAPHORE | EFD_NONBLOCK) +#define EFD_IN_USE 0x1 +#define EFD_FLAGS_SET (EFD_SEMAPHORE | EFD_NONBLOCK) struct eventfd { struct k_poll_signal read_sig; @@ -33,7 +33,7 @@ static const struct fd_op_vtable eventfd_fd_vtable; static inline bool eventfd_is_in_use(struct eventfd *efd) { - return (efd->flags & EFD_IN_USE_INTERNAL) != 0; + return (efd->flags & EFD_IN_USE) != 0; } static inline bool eventfd_is_semaphore(struct eventfd *efd) @@ -235,7 +235,7 @@ static int eventfd_ioctl_op(void *obj, unsigned int request, va_list args) switch (request) { case F_GETFL: - ret = efd->flags & EFD_FLAGS_SET_INTERNAL; + ret = efd->flags & EFD_FLAGS_SET; break; case F_SETFL: { @@ -243,11 +243,11 @@ static int eventfd_ioctl_op(void *obj, unsigned int request, va_list args) flags = va_arg(args, int); - if (flags & ~EFD_FLAGS_SET_INTERNAL) { + if (flags & ~EFD_FLAGS_SET) { errno = EINVAL; ret = -1; } else { - int prev_flags = efd->flags & ~EFD_FLAGS_SET_INTERNAL; + int prev_flags = efd->flags & ~EFD_FLAGS_SET; efd->flags = flags | prev_flags; ret = 0; @@ -410,7 +410,7 @@ int eventfd(unsigned int initval, int flags) size_t offset; struct eventfd *efd = NULL; - if (flags & ~EFD_FLAGS_SET_INTERNAL) { + if (flags & ~EFD_FLAGS_SET) { errno = EINVAL; return -1; } @@ -428,7 +428,7 @@ int eventfd(unsigned int initval, int flags) return -1; } - efd->flags = EFD_IN_USE_INTERNAL | flags; + efd->flags = EFD_IN_USE | flags; efd->cnt = initval; k_poll_signal_init(&efd->write_sig); From 487a8756c32320f0f1fbe1fbe342849ef89e7440 Mon Sep 17 00:00:00 2001 From: Chris Friedt Date: Tue, 28 May 2024 19:39:06 -0400 Subject: [PATCH 1753/2849] posix: eventfd: fix dependency cycle between net and posix Until recently, the posix api was purely a consumer of the network subsystem. However, a dependency cycle was added as a stop-gap solution for challenges with the native platform. Specifically, 1. eventfd symbols conflict with those of the host 2. eventfd was excluded from native libc builds via cmake If any part of the posix were then to select the network subsystem (which is a legitimate use case, given that networking is a part of the posix api), we would get a build error due to the Kconfig dependency cycle. As usual, with dependency cycles, the cycle can be broken via a third, mutual dependency. What is the third mutual dependency? Naturally, it is ZVFS which was planned some time ago. ZVFS will be where we collect file-descriptor and FILE-pointer APIs so that we can ensure consistency for Zephyr users. This change deprecates EVENTFD_MAX in favour of ZVFS_EVENTFD_MAX. Signed-off-by: Chris Friedt --- .../portability/posix/kconfig/index.rst | 2 +- include/zephyr/posix/sys/eventfd.h | 11 +- include/zephyr/zvfs/eventfd.h | 66 +++ lib/os/CMakeLists.txt | 2 + lib/os/Kconfig | 1 + lib/os/zvfs/CMakeLists.txt | 4 + lib/os/zvfs/Kconfig | 36 ++ lib/os/zvfs/zvfs_eventfd.c | 485 ++++++++++++++++++ lib/posix/options/Kconfig.compat | 17 +- lib/posix/options/Kconfig.deprecated | 9 + lib/posix/options/eventfd.c | 471 +---------------- subsys/net/lib/sockets/sockets_service.c | 25 +- tests/net/lib/http_server/crime/prj.conf | 2 +- tests/net/lib/http_server/prototype/prj.conf | 2 +- tests/net/lib/http_server/tls/prj.conf | 2 +- tests/posix/eventfd/src/ioctl.c | 2 + 16 files changed, 628 insertions(+), 509 deletions(-) create mode 100644 include/zephyr/zvfs/eventfd.h create mode 100644 lib/os/zvfs/CMakeLists.txt create mode 100644 lib/os/zvfs/Kconfig create mode 100644 lib/os/zvfs/zvfs_eventfd.c diff --git a/doc/services/portability/posix/kconfig/index.rst b/doc/services/portability/posix/kconfig/index.rst index 56574909eb13e..7c7055326df2c 100644 --- a/doc/services/portability/posix/kconfig/index.rst +++ b/doc/services/portability/posix/kconfig/index.rst @@ -9,7 +9,6 @@ implementation of the POSIX API. * :kconfig:option:`CONFIG_DYNAMIC_THREAD` * :kconfig:option:`CONFIG_DYNAMIC_THREAD_POOL_SIZE` * :kconfig:option:`CONFIG_EVENTFD` -* :kconfig:option:`CONFIG_EVENTFD_MAX` * :kconfig:option:`CONFIG_FDTABLE` * :kconfig:option:`CONFIG_GETOPT_LONG` * :kconfig:option:`CONFIG_MAX_PTHREAD_SPINLOCK_COUNT` @@ -38,3 +37,4 @@ implementation of the POSIX API. * :kconfig:option:`CONFIG_POSIX_SEM_VALUE_MAX` * :kconfig:option:`CONFIG_TIMER_CREATE_WAIT` * :kconfig:option:`CONFIG_THREAD_STACK_INFO` +* :kconfig:option:`CONFIG_ZVFS_EVENTFD_MAX` diff --git a/include/zephyr/posix/sys/eventfd.h b/include/zephyr/posix/sys/eventfd.h index 5d8c48f6e21ff..35bef86d87e8c 100644 --- a/include/zephyr/posix/sys/eventfd.h +++ b/include/zephyr/posix/sys/eventfd.h @@ -7,19 +7,16 @@ #ifndef ZEPHYR_INCLUDE_POSIX_SYS_EVENTFD_H_ #define ZEPHYR_INCLUDE_POSIX_SYS_EVENTFD_H_ -#include - -#include -#include +#include #ifdef __cplusplus extern "C" { #endif -#define EFD_SEMAPHORE 0x2 -#define EFD_NONBLOCK O_NONBLOCK +#define EFD_SEMAPHORE ZVFS_EFD_SEMAPHORE +#define EFD_NONBLOCK ZVFS_EFD_NONBLOCK -typedef uint64_t eventfd_t; +typedef zvfs_eventfd_t eventfd_t; /** * @brief Create a file descriptor for event notification diff --git a/include/zephyr/zvfs/eventfd.h b/include/zephyr/zvfs/eventfd.h new file mode 100644 index 0000000000000..a5e1ebfa28675 --- /dev/null +++ b/include/zephyr/zvfs/eventfd.h @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2020 Tobias Svehagen + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_ZEPHYR_ZVFS_EVENTFD_H_ +#define ZEPHYR_INCLUDE_ZEPHYR_ZVFS_EVENTFD_H_ + +#include + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define ZVFS_EFD_SEMAPHORE 2 +#define ZVFS_EFD_NONBLOCK 0x4000 + +typedef uint64_t zvfs_eventfd_t; + +/** + * @brief Create a file descriptor for ZVFS event notification + * + * The returned file descriptor can be used with POSIX read/write calls or + * with the @ref zvfs_eventfd_read or @ref zvfs_eventfd_write functions. + * + * It also supports polling and by including an eventfd in a call to poll, + * it is possible to signal and wake the polling thread by simply writing to + * the eventfd. + * + * When using read() and write() on a ZVFS eventfd, the size must always be at + * least 8 bytes or the operation will fail with EINVAL. + * + * @return New ZVFS eventfd file descriptor on success, -1 on error + */ +int zvfs_eventfd(unsigned int initval, int flags); + +/** + * @brief Read from a ZVFS eventfd + * + * If call is successful, the value parameter will have the value 1 + * + * @param fd File descriptor + * @param value Pointer for storing the read value + * + * @return 0 on success, -1 on error + */ +int zvfs_eventfd_read(int fd, zvfs_eventfd_t *value); + +/** + * @brief Write to a ZVFS eventfd + * + * @param fd File descriptor + * @param value Value to write + * + * @return 0 on success, -1 on error + */ +int zvfs_eventfd_write(int fd, zvfs_eventfd_t value); + +#ifdef __cplusplus +} +#endif + +#endif /* ZEPHYR_INCLUDE_ZEPHYR_ZVFS_EVENTFD_H_ */ diff --git a/lib/os/CMakeLists.txt b/lib/os/CMakeLists.txt index 3a52bebab04b8..4ce50ad418292 100644 --- a/lib/os/CMakeLists.txt +++ b/lib/os/CMakeLists.txt @@ -40,3 +40,5 @@ zephyr_library_include_directories( ${ZEPHYR_BASE}/kernel/include ${ZEPHYR_BASE}/arch/${ARCH}/include ) + +add_subdirectory_ifdef(CONFIG_ZVFS zvfs) diff --git a/lib/os/Kconfig b/lib/os/Kconfig index 863f5e93b3ef7..fa52338e525f1 100644 --- a/lib/os/Kconfig +++ b/lib/os/Kconfig @@ -123,5 +123,6 @@ config POWEROFF Enable support for system power off. rsource "Kconfig.cbprintf" +rsource "zvfs/Kconfig" endmenu diff --git a/lib/os/zvfs/CMakeLists.txt b/lib/os/zvfs/CMakeLists.txt new file mode 100644 index 0000000000000..ca191a4d3ad7a --- /dev/null +++ b/lib/os/zvfs/CMakeLists.txt @@ -0,0 +1,4 @@ +# SPDX-License-Identifier: Apache-2.0 + +zephyr_library() +zephyr_library_sources_ifdef(CONFIG_ZVFS_EVENTFD zvfs_eventfd.c) diff --git a/lib/os/zvfs/Kconfig b/lib/os/zvfs/Kconfig new file mode 100644 index 0000000000000..7f50ff52befc2 --- /dev/null +++ b/lib/os/zvfs/Kconfig @@ -0,0 +1,36 @@ +# Copyright (c) 2020 Tobias Svehagen +# Copyright (c) 2023 Meta +# +# SPDX-License-Identifier: Apache-2.0 + +menuconfig ZVFS + bool "Zephyr virtual filesystem (ZVFS) support [EXPERIMENTAL]" + select FDTABLE + select EXPERIMENTAL + help + ZVFS is a central, Zephyr-native library that provides a common interoperable API for all + types of file descriptors such as those from the non-virtual FS, sockets, eventfds, FILE *'s + and more. It is designed to be used by all Zephyr subsystems that need to work with files. + +if ZVFS + +config ZVFS_EVENTFD + bool "ZVFS event file descriptor support" + select POLL + help + Enable support for ZVFS event file descriptors. An eventfd can + be used as an event wait/notify mechanism together with POSIX calls + like read, write and poll. + +if ZVFS_EVENTFD + +config ZVFS_EVENTFD_MAX + int "Maximum number of ZVFS eventfd's" + default 1 + range 1 4096 + help + The maximum number of supported event file descriptors. + +endif # ZVFS_EVENTFD + +endif # ZVFS diff --git a/lib/os/zvfs/zvfs_eventfd.c b/lib/os/zvfs/zvfs_eventfd.c new file mode 100644 index 0000000000000..069f4d680e931 --- /dev/null +++ b/lib/os/zvfs/zvfs_eventfd.c @@ -0,0 +1,485 @@ +/* + * Copyright (c) 2020 Tobias Svehagen + * Copyright (c) 2023, Meta + * Copyright (c) 2024, Tenstorrent AI ULC + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include +#include + +#define ZVFS_EFD_IN_USE 0x1 +#define ZVFS_EFD_FLAGS_SET (ZVFS_EFD_SEMAPHORE | ZVFS_EFD_NONBLOCK) + +struct zvfs_eventfd { + struct k_poll_signal read_sig; + struct k_poll_signal write_sig; + struct k_spinlock lock; + zvfs_eventfd_t cnt; + int flags; +}; + +static ssize_t zvfs_eventfd_rw_op(void *obj, void *buf, size_t sz, + int (*op)(struct zvfs_eventfd *efd, zvfs_eventfd_t *value)); + +SYS_BITARRAY_DEFINE_STATIC(efds_bitarray, CONFIG_ZVFS_EVENTFD_MAX); +static struct zvfs_eventfd efds[CONFIG_ZVFS_EVENTFD_MAX]; +static const struct fd_op_vtable zvfs_eventfd_fd_vtable; + +static inline bool zvfs_eventfd_is_in_use(struct zvfs_eventfd *efd) +{ + return (efd->flags & ZVFS_EFD_IN_USE) != 0; +} + +static inline bool zvfs_eventfd_is_semaphore(struct zvfs_eventfd *efd) +{ + return (efd->flags & ZVFS_EFD_SEMAPHORE) != 0; +} + +static inline bool zvfs_eventfd_is_blocking(struct zvfs_eventfd *efd) +{ + return (efd->flags & ZVFS_EFD_NONBLOCK) == 0; +} + +static int zvfs_eventfd_poll_prepare(struct zvfs_eventfd *efd, + struct zsock_pollfd *pfd, + struct k_poll_event **pev, + struct k_poll_event *pev_end) +{ + if (pfd->events & ZSOCK_POLLIN) { + if (*pev == pev_end) { + errno = ENOMEM; + return -1; + } + + (*pev)->obj = &efd->read_sig; + (*pev)->type = K_POLL_TYPE_SIGNAL; + (*pev)->mode = K_POLL_MODE_NOTIFY_ONLY; + (*pev)->state = K_POLL_STATE_NOT_READY; + (*pev)++; + } + + if (pfd->events & ZSOCK_POLLOUT) { + if (*pev == pev_end) { + errno = ENOMEM; + return -1; + } + + (*pev)->obj = &efd->write_sig; + (*pev)->type = K_POLL_TYPE_SIGNAL; + (*pev)->mode = K_POLL_MODE_NOTIFY_ONLY; + (*pev)->state = K_POLL_STATE_NOT_READY; + (*pev)++; + } + + return 0; +} + +static int zvfs_eventfd_poll_update(struct zvfs_eventfd *efd, + struct zsock_pollfd *pfd, + struct k_poll_event **pev) +{ + if (pfd->events & ZSOCK_POLLIN) { + pfd->revents |= ZSOCK_POLLIN * (efd->cnt > 0); + (*pev)++; + } + + if (pfd->events & ZSOCK_POLLOUT) { + pfd->revents |= ZSOCK_POLLOUT * (efd->cnt < UINT64_MAX - 1); + (*pev)++; + } + + return 0; +} + +static int zvfs_eventfd_read_locked(struct zvfs_eventfd *efd, zvfs_eventfd_t *value) +{ + if (!zvfs_eventfd_is_in_use(efd)) { + /* file descriptor has been closed */ + return -EBADF; + } + + if (efd->cnt == 0) { + /* would block / try again */ + return -EAGAIN; + } + + /* successful read */ + if (zvfs_eventfd_is_semaphore(efd)) { + *value = 1; + --efd->cnt; + } else { + *value = efd->cnt; + efd->cnt = 0; + } + + if (efd->cnt == 0) { + k_poll_signal_reset(&efd->read_sig); + } + + k_poll_signal_raise(&efd->write_sig, 0); + + return 0; +} + +static int zvfs_eventfd_write_locked(struct zvfs_eventfd *efd, zvfs_eventfd_t *value) +{ + zvfs_eventfd_t result; + + if (!zvfs_eventfd_is_in_use(efd)) { + /* file descriptor has been closed */ + return -EBADF; + } + + if (*value == UINT64_MAX) { + /* not a permitted value */ + return -EINVAL; + } + + if (u64_add_overflow(efd->cnt, *value, &result) || result == UINT64_MAX) { + /* would block / try again */ + return -EAGAIN; + } + + /* successful write */ + efd->cnt = result; + + if (efd->cnt == (UINT64_MAX - 1)) { + k_poll_signal_reset(&efd->write_sig); + } + + k_poll_signal_raise(&efd->read_sig, 0); + + return 0; +} + +static ssize_t zvfs_eventfd_read_op(void *obj, void *buf, size_t sz) +{ + return zvfs_eventfd_rw_op(obj, buf, sz, zvfs_eventfd_read_locked); +} + +static ssize_t zvfs_eventfd_write_op(void *obj, const void *buf, size_t sz) +{ + return zvfs_eventfd_rw_op(obj, (zvfs_eventfd_t *)buf, sz, zvfs_eventfd_write_locked); +} + +static int zvfs_eventfd_close_op(void *obj) +{ + int ret; + int err; + k_spinlock_key_t key; + struct k_mutex *lock = NULL; + struct k_condvar *cond = NULL; + struct zvfs_eventfd *efd = (struct zvfs_eventfd *)obj; + + if (k_is_in_isr()) { + /* not covered by the man page, but necessary in Zephyr */ + errno = EWOULDBLOCK; + return -1; + } + + err = (int)z_get_obj_lock_and_cond(obj, &zvfs_eventfd_fd_vtable, &lock, &cond); + __ASSERT((bool)err, "z_get_obj_lock_and_cond() failed"); + __ASSERT_NO_MSG(lock != NULL); + __ASSERT_NO_MSG(cond != NULL); + + err = k_mutex_lock(lock, K_FOREVER); + __ASSERT(err == 0, "k_mutex_lock() failed: %d", err); + + key = k_spin_lock(&efd->lock); + + if (!zvfs_eventfd_is_in_use(efd)) { + errno = EBADF; + ret = -1; + goto unlock; + } + + err = sys_bitarray_free(&efds_bitarray, 1, (struct zvfs_eventfd *)obj - efds); + __ASSERT(err == 0, "sys_bitarray_free() failed: %d", err); + + efd->flags = 0; + efd->cnt = 0; + + ret = 0; + +unlock: + k_spin_unlock(&efd->lock, key); + /* when closing an zvfs_eventfd, broadcast to all waiters */ + err = k_condvar_broadcast(cond); + __ASSERT(err == 0, "k_condvar_broadcast() failed: %d", err); + err = k_mutex_unlock(lock); + __ASSERT(err == 0, "k_mutex_unlock() failed: %d", err); + + return ret; +} + +static int zvfs_eventfd_ioctl_op(void *obj, unsigned int request, va_list args) +{ + int ret; + k_spinlock_key_t key; + struct zvfs_eventfd *efd = (struct zvfs_eventfd *)obj; + + /* note: zsock_poll_internal() has already taken the mutex */ + key = k_spin_lock(&efd->lock); + + if (!zvfs_eventfd_is_in_use(efd)) { + errno = EBADF; + ret = -1; + goto unlock; + } + + switch (request) { + case F_GETFL: + ret = efd->flags & ZVFS_EFD_FLAGS_SET; + break; + + case F_SETFL: { + int flags; + + flags = va_arg(args, int); + + if (flags & ~ZVFS_EFD_FLAGS_SET) { + errno = EINVAL; + ret = -1; + } else { + int prev_flags = efd->flags & ~ZVFS_EFD_FLAGS_SET; + + efd->flags = flags | prev_flags; + ret = 0; + } + } break; + + case ZFD_IOCTL_POLL_PREPARE: { + struct zsock_pollfd *pfd; + struct k_poll_event **pev; + struct k_poll_event *pev_end; + + pfd = va_arg(args, struct zsock_pollfd *); + pev = va_arg(args, struct k_poll_event **); + pev_end = va_arg(args, struct k_poll_event *); + + ret = zvfs_eventfd_poll_prepare(obj, pfd, pev, pev_end); + } break; + + case ZFD_IOCTL_POLL_UPDATE: { + struct zsock_pollfd *pfd; + struct k_poll_event **pev; + + pfd = va_arg(args, struct zsock_pollfd *); + pev = va_arg(args, struct k_poll_event **); + + ret = zvfs_eventfd_poll_update(obj, pfd, pev); + } break; + + default: + errno = EOPNOTSUPP; + ret = -1; + break; + } + +unlock: + k_spin_unlock(&efd->lock, key); + + return ret; +} + +static const struct fd_op_vtable zvfs_eventfd_fd_vtable = { + .read = zvfs_eventfd_read_op, + .write = zvfs_eventfd_write_op, + .close = zvfs_eventfd_close_op, + .ioctl = zvfs_eventfd_ioctl_op, +}; + +/* common to both zvfs_eventfd_read_op() and zvfs_eventfd_write_op() */ +static ssize_t zvfs_eventfd_rw_op(void *obj, void *buf, size_t sz, + int (*op)(struct zvfs_eventfd *efd, zvfs_eventfd_t *value)) +{ + int err; + ssize_t ret; + k_spinlock_key_t key; + struct zvfs_eventfd *efd = obj; + struct k_mutex *lock = NULL; + struct k_condvar *cond = NULL; + + if (sz < sizeof(zvfs_eventfd_t)) { + errno = EINVAL; + return -1; + } + + if (buf == NULL) { + errno = EFAULT; + return -1; + } + + key = k_spin_lock(&efd->lock); + + if (!zvfs_eventfd_is_blocking(efd)) { + /* + * Handle the non-blocking case entirely within this scope + */ + ret = op(efd, buf); + if (ret < 0) { + errno = -ret; + ret = -1; + } else { + ret = sizeof(zvfs_eventfd_t); + } + + goto unlock_spin; + } + + /* + * Handle the blocking case below + */ + __ASSERT_NO_MSG(zvfs_eventfd_is_blocking(efd)); + + if (k_is_in_isr()) { + /* not covered by the man page, but necessary in Zephyr */ + errno = EWOULDBLOCK; + ret = -1; + goto unlock_spin; + } + + err = (int)z_get_obj_lock_and_cond(obj, &zvfs_eventfd_fd_vtable, &lock, &cond); + __ASSERT((bool)err, "z_get_obj_lock_and_cond() failed"); + __ASSERT_NO_MSG(lock != NULL); + __ASSERT_NO_MSG(cond != NULL); + + /* do not hold a spinlock when taking a mutex */ + k_spin_unlock(&efd->lock, key); + err = k_mutex_lock(lock, K_FOREVER); + __ASSERT(err == 0, "k_mutex_lock() failed: %d", err); + + while (true) { + /* retake the spinlock */ + key = k_spin_lock(&efd->lock); + + ret = op(efd, buf); + switch (ret) { + case -EAGAIN: + /* not an error in blocking mode. break and try again */ + break; + case 0: + /* success! */ + ret = sizeof(zvfs_eventfd_t); + goto unlock_mutex; + default: + /* some other error */ + __ASSERT_NO_MSG(ret < 0); + errno = -ret; + ret = -1; + goto unlock_mutex; + } + + /* do not hold a spinlock when taking a mutex */ + k_spin_unlock(&efd->lock, key); + + /* wait for a write or close */ + err = k_condvar_wait(cond, lock, K_FOREVER); + __ASSERT(err == 0, "k_condvar_wait() failed: %d", err); + } + +unlock_mutex: + k_spin_unlock(&efd->lock, key); + /* only wake a single waiter */ + err = k_condvar_signal(cond); + __ASSERT(err == 0, "k_condvar_signal() failed: %d", err); + err = k_mutex_unlock(lock); + __ASSERT(err == 0, "k_mutex_unlock() failed: %d", err); + goto out; + +unlock_spin: + k_spin_unlock(&efd->lock, key); + +out: + return ret; +} + +/* + * Public-facing API + */ + +int zvfs_eventfd(unsigned int initval, int flags) +{ + int fd = 1; + size_t offset; + struct zvfs_eventfd *efd = NULL; + + if (flags & ~ZVFS_EFD_FLAGS_SET) { + errno = EINVAL; + return -1; + } + + if (sys_bitarray_alloc(&efds_bitarray, 1, &offset) < 0) { + errno = ENOMEM; + return -1; + } + + efd = &efds[offset]; + + fd = z_reserve_fd(); + if (fd < 0) { + sys_bitarray_free(&efds_bitarray, 1, offset); + return -1; + } + + efd->flags = ZVFS_EFD_IN_USE | flags; + efd->cnt = initval; + + k_poll_signal_init(&efd->write_sig); + k_poll_signal_init(&efd->read_sig); + + if (initval != 0) { + k_poll_signal_raise(&efd->read_sig, 0); + } + + k_poll_signal_raise(&efd->write_sig, 0); + + z_finalize_fd(fd, efd, &zvfs_eventfd_fd_vtable); + + return fd; +} + +int zvfs_eventfd_read(int fd, zvfs_eventfd_t *value) +{ + int ret; + void *obj; + + obj = z_get_fd_obj(fd, &zvfs_eventfd_fd_vtable, EBADF); + if (obj == NULL) { + return -1; + } + + ret = zvfs_eventfd_rw_op(obj, value, sizeof(zvfs_eventfd_t), zvfs_eventfd_read_locked); + __ASSERT_NO_MSG(ret == -1 || ret == sizeof(zvfs_eventfd_t)); + if (ret < 0) { + return -1; + } + + return 0; +} + +int zvfs_eventfd_write(int fd, zvfs_eventfd_t value) +{ + int ret; + void *obj; + + obj = z_get_fd_obj(fd, &zvfs_eventfd_fd_vtable, EBADF); + if (obj == NULL) { + return -1; + } + + ret = zvfs_eventfd_rw_op(obj, &value, sizeof(zvfs_eventfd_t), zvfs_eventfd_write_locked); + __ASSERT_NO_MSG(ret == -1 || ret == sizeof(zvfs_eventfd_t)); + if (ret < 0) { + return -1; + } + + return 0; +} diff --git a/lib/posix/options/Kconfig.compat b/lib/posix/options/Kconfig.compat index 680f12f1c1a44..f9ad9cee8d59f 100644 --- a/lib/posix/options/Kconfig.compat +++ b/lib/posix/options/Kconfig.compat @@ -5,26 +5,15 @@ menu "Miscellaneous POSIX-related options" -menuconfig EVENTFD +config EVENTFD bool "Support for eventfd" depends on !NATIVE_APPLICATION - select POLL - select FDTABLE + select ZVFS + select ZVFS_EVENTFD default y if POSIX_API help Enable support for event file descriptors, eventfd. An eventfd can be used as an event wait/notify mechanism together with POSIX calls like read, write and poll. -if EVENTFD - -config EVENTFD_MAX - int "Maximum number of eventfd's" - default 1 - range 1 4096 - help - The maximum number of supported event file descriptors. - -endif # EVENTFD - endmenu diff --git a/lib/posix/options/Kconfig.deprecated b/lib/posix/options/Kconfig.deprecated index 500783fd78ef9..3f39a701dc9ce 100644 --- a/lib/posix/options/Kconfig.deprecated +++ b/lib/posix/options/Kconfig.deprecated @@ -6,6 +6,15 @@ menu "Deprecated POSIX options" +config EVENTFD_MAX + int "Maximum number of eventfd's [DEPRECATED]" + default ZVFS_EVENTFD_MAX if ZVFS_EVENTFD + default 0 + help + This option is deprecated. + + Please use CONFIG_ZVFS_EVENTFD_MAX instead. + config FNMATCH bool "Support for fnmatch [DEPRECATED]" select DEPRECATED diff --git a/lib/posix/options/eventfd.c b/lib/posix/options/eventfd.c index 60d327e4fd1f0..b272bfa636fc2 100644 --- a/lib/posix/options/eventfd.c +++ b/lib/posix/options/eventfd.c @@ -1,484 +1,23 @@ /* - * Copyright (c) 2020 Tobias Svehagen - * Copyright (c) 2023, Meta + * Copyright (c) 2024, Tenstorrent AI ULC * * SPDX-License-Identifier: Apache-2.0 */ -#include -#include -#include #include -#include -#include -#include - -#define EFD_IN_USE 0x1 -#define EFD_FLAGS_SET (EFD_SEMAPHORE | EFD_NONBLOCK) - -struct eventfd { - struct k_poll_signal read_sig; - struct k_poll_signal write_sig; - struct k_spinlock lock; - eventfd_t cnt; - int flags; -}; - -static ssize_t eventfd_rw_op(void *obj, void *buf, size_t sz, - int (*op)(struct eventfd *efd, eventfd_t *value)); - -SYS_BITARRAY_DEFINE_STATIC(efds_bitarray, CONFIG_EVENTFD_MAX); -static struct eventfd efds[CONFIG_EVENTFD_MAX]; -static const struct fd_op_vtable eventfd_fd_vtable; - -static inline bool eventfd_is_in_use(struct eventfd *efd) -{ - return (efd->flags & EFD_IN_USE) != 0; -} - -static inline bool eventfd_is_semaphore(struct eventfd *efd) -{ - return (efd->flags & EFD_SEMAPHORE) != 0; -} - -static inline bool eventfd_is_blocking(struct eventfd *efd) -{ - return (efd->flags & EFD_NONBLOCK) == 0; -} - -static int eventfd_poll_prepare(struct eventfd *efd, - struct zsock_pollfd *pfd, - struct k_poll_event **pev, - struct k_poll_event *pev_end) -{ - if (pfd->events & ZSOCK_POLLIN) { - if (*pev == pev_end) { - errno = ENOMEM; - return -1; - } - - (*pev)->obj = &efd->read_sig; - (*pev)->type = K_POLL_TYPE_SIGNAL; - (*pev)->mode = K_POLL_MODE_NOTIFY_ONLY; - (*pev)->state = K_POLL_STATE_NOT_READY; - (*pev)++; - } - - if (pfd->events & ZSOCK_POLLOUT) { - if (*pev == pev_end) { - errno = ENOMEM; - return -1; - } - - (*pev)->obj = &efd->write_sig; - (*pev)->type = K_POLL_TYPE_SIGNAL; - (*pev)->mode = K_POLL_MODE_NOTIFY_ONLY; - (*pev)->state = K_POLL_STATE_NOT_READY; - (*pev)++; - } - - return 0; -} - -static int eventfd_poll_update(struct eventfd *efd, - struct zsock_pollfd *pfd, - struct k_poll_event **pev) -{ - if (pfd->events & ZSOCK_POLLIN) { - pfd->revents |= ZSOCK_POLLIN * (efd->cnt > 0); - (*pev)++; - } - - if (pfd->events & ZSOCK_POLLOUT) { - pfd->revents |= ZSOCK_POLLOUT * (efd->cnt < UINT64_MAX - 1); - (*pev)++; - } - - return 0; -} - -static int eventfd_read_locked(struct eventfd *efd, eventfd_t *value) -{ - if (!eventfd_is_in_use(efd)) { - /* file descriptor has been closed */ - return -EBADF; - } - - if (efd->cnt == 0) { - /* would block / try again */ - return -EAGAIN; - } - - /* successful read */ - if (eventfd_is_semaphore(efd)) { - *value = 1; - --efd->cnt; - } else { - *value = efd->cnt; - efd->cnt = 0; - } - - if (efd->cnt == 0) { - k_poll_signal_reset(&efd->read_sig); - } - - k_poll_signal_raise(&efd->write_sig, 0); - - return 0; -} - -static int eventfd_write_locked(struct eventfd *efd, eventfd_t *value) -{ - eventfd_t result; - - if (!eventfd_is_in_use(efd)) { - /* file descriptor has been closed */ - return -EBADF; - } - - if (*value == UINT64_MAX) { - /* not a permitted value */ - return -EINVAL; - } - - if (u64_add_overflow(efd->cnt, *value, &result) || result == UINT64_MAX) { - /* would block / try again */ - return -EAGAIN; - } - - /* successful write */ - efd->cnt = result; - - if (efd->cnt == (UINT64_MAX - 1)) { - k_poll_signal_reset(&efd->write_sig); - } - - k_poll_signal_raise(&efd->read_sig, 0); - - return 0; -} - -static ssize_t eventfd_read_op(void *obj, void *buf, size_t sz) -{ - return eventfd_rw_op(obj, buf, sz, eventfd_read_locked); -} - -static ssize_t eventfd_write_op(void *obj, const void *buf, size_t sz) -{ - return eventfd_rw_op(obj, (eventfd_t *)buf, sz, eventfd_write_locked); -} - -static int eventfd_close_op(void *obj) -{ - int ret; - int err; - k_spinlock_key_t key; - struct k_mutex *lock = NULL; - struct k_condvar *cond = NULL; - struct eventfd *efd = (struct eventfd *)obj; - - if (k_is_in_isr()) { - /* not covered by the man page, but necessary in Zephyr */ - errno = EWOULDBLOCK; - return -1; - } - - err = (int)z_get_obj_lock_and_cond(obj, &eventfd_fd_vtable, &lock, &cond); - __ASSERT((bool)err, "z_get_obj_lock_and_cond() failed"); - __ASSERT_NO_MSG(lock != NULL); - __ASSERT_NO_MSG(cond != NULL); - - err = k_mutex_lock(lock, K_FOREVER); - __ASSERT(err == 0, "k_mutex_lock() failed: %d", err); - - key = k_spin_lock(&efd->lock); - - if (!eventfd_is_in_use(efd)) { - errno = EBADF; - ret = -1; - goto unlock; - } - - err = sys_bitarray_free(&efds_bitarray, 1, (struct eventfd *)obj - efds); - __ASSERT(err == 0, "sys_bitarray_free() failed: %d", err); - - efd->flags = 0; - efd->cnt = 0; - - ret = 0; - -unlock: - k_spin_unlock(&efd->lock, key); - /* when closing an eventfd, broadcast to all waiters */ - err = k_condvar_broadcast(cond); - __ASSERT(err == 0, "k_condvar_broadcast() failed: %d", err); - err = k_mutex_unlock(lock); - __ASSERT(err == 0, "k_mutex_unlock() failed: %d", err); - - return ret; -} - -static int eventfd_ioctl_op(void *obj, unsigned int request, va_list args) -{ - int ret; - k_spinlock_key_t key; - struct eventfd *efd = (struct eventfd *)obj; - - /* note: zsock_poll_internal() has already taken the mutex */ - key = k_spin_lock(&efd->lock); - - if (!eventfd_is_in_use(efd)) { - errno = EBADF; - ret = -1; - goto unlock; - } - - switch (request) { - case F_GETFL: - ret = efd->flags & EFD_FLAGS_SET; - break; - - case F_SETFL: { - int flags; - - flags = va_arg(args, int); - - if (flags & ~EFD_FLAGS_SET) { - errno = EINVAL; - ret = -1; - } else { - int prev_flags = efd->flags & ~EFD_FLAGS_SET; - - efd->flags = flags | prev_flags; - ret = 0; - } - } break; - - case ZFD_IOCTL_POLL_PREPARE: { - struct zsock_pollfd *pfd; - struct k_poll_event **pev; - struct k_poll_event *pev_end; - - pfd = va_arg(args, struct zsock_pollfd *); - pev = va_arg(args, struct k_poll_event **); - pev_end = va_arg(args, struct k_poll_event *); - - ret = eventfd_poll_prepare(obj, pfd, pev, pev_end); - } break; - - case ZFD_IOCTL_POLL_UPDATE: { - struct zsock_pollfd *pfd; - struct k_poll_event **pev; - - pfd = va_arg(args, struct zsock_pollfd *); - pev = va_arg(args, struct k_poll_event **); - - ret = eventfd_poll_update(obj, pfd, pev); - } break; - - default: - errno = EOPNOTSUPP; - ret = -1; - break; - } - -unlock: - k_spin_unlock(&efd->lock, key); - - return ret; -} - -static const struct fd_op_vtable eventfd_fd_vtable = { - .read = eventfd_read_op, - .write = eventfd_write_op, - .close = eventfd_close_op, - .ioctl = eventfd_ioctl_op, -}; - -/* common to both eventfd_read_op() and eventfd_write_op() */ -static ssize_t eventfd_rw_op(void *obj, void *buf, size_t sz, - int (*op)(struct eventfd *efd, eventfd_t *value)) -{ - int err; - ssize_t ret; - k_spinlock_key_t key; - struct eventfd *efd = obj; - struct k_mutex *lock = NULL; - struct k_condvar *cond = NULL; - - if (sz < sizeof(eventfd_t)) { - errno = EINVAL; - return -1; - } - - if (buf == NULL) { - errno = EFAULT; - return -1; - } - - key = k_spin_lock(&efd->lock); - - if (!eventfd_is_blocking(efd)) { - /* - * Handle the non-blocking case entirely within this scope - */ - ret = op(efd, buf); - if (ret < 0) { - errno = -ret; - ret = -1; - } else { - ret = sizeof(eventfd_t); - } - - goto unlock_spin; - } - - /* - * Handle the blocking case below - */ - __ASSERT_NO_MSG(eventfd_is_blocking(efd)); - - if (k_is_in_isr()) { - /* not covered by the man page, but necessary in Zephyr */ - errno = EWOULDBLOCK; - ret = -1; - goto unlock_spin; - } - - err = (int)z_get_obj_lock_and_cond(obj, &eventfd_fd_vtable, &lock, &cond); - __ASSERT((bool)err, "z_get_obj_lock_and_cond() failed"); - __ASSERT_NO_MSG(lock != NULL); - __ASSERT_NO_MSG(cond != NULL); - - /* do not hold a spinlock when taking a mutex */ - k_spin_unlock(&efd->lock, key); - err = k_mutex_lock(lock, K_FOREVER); - __ASSERT(err == 0, "k_mutex_lock() failed: %d", err); - - while (true) { - /* retake the spinlock */ - key = k_spin_lock(&efd->lock); - - ret = op(efd, buf); - switch (ret) { - case -EAGAIN: - /* not an error in blocking mode. break and try again */ - break; - case 0: - /* success! */ - ret = sizeof(eventfd_t); - goto unlock_mutex; - default: - /* some other error */ - __ASSERT_NO_MSG(ret < 0); - errno = -ret; - ret = -1; - goto unlock_mutex; - } - - /* do not hold a spinlock when taking a mutex */ - k_spin_unlock(&efd->lock, key); - - /* wait for a write or close */ - err = k_condvar_wait(cond, lock, K_FOREVER); - __ASSERT(err == 0, "k_condvar_wait() failed: %d", err); - } - -unlock_mutex: - k_spin_unlock(&efd->lock, key); - /* only wake a single waiter */ - err = k_condvar_signal(cond); - __ASSERT(err == 0, "k_condvar_signal() failed: %d", err); - err = k_mutex_unlock(lock); - __ASSERT(err == 0, "k_mutex_unlock() failed: %d", err); - goto out; - -unlock_spin: - k_spin_unlock(&efd->lock, key); - -out: - return ret; -} - -/* - * Public-facing API - */ +#include int eventfd(unsigned int initval, int flags) { - int fd = 1; - size_t offset; - struct eventfd *efd = NULL; - - if (flags & ~EFD_FLAGS_SET) { - errno = EINVAL; - return -1; - } - - if (sys_bitarray_alloc(&efds_bitarray, 1, &offset) < 0) { - errno = ENOMEM; - return -1; - } - - efd = &efds[offset]; - - fd = z_reserve_fd(); - if (fd < 0) { - sys_bitarray_free(&efds_bitarray, 1, offset); - return -1; - } - - efd->flags = EFD_IN_USE | flags; - efd->cnt = initval; - - k_poll_signal_init(&efd->write_sig); - k_poll_signal_init(&efd->read_sig); - - if (initval != 0) { - k_poll_signal_raise(&efd->read_sig, 0); - } - - k_poll_signal_raise(&efd->write_sig, 0); - - z_finalize_fd(fd, efd, &eventfd_fd_vtable); - - return fd; + return zvfs_eventfd(initval, flags); } int eventfd_read(int fd, eventfd_t *value) { - int ret; - void *obj; - - obj = z_get_fd_obj(fd, &eventfd_fd_vtable, EBADF); - if (obj == NULL) { - return -1; - } - - ret = eventfd_rw_op(obj, value, sizeof(eventfd_t), eventfd_read_locked); - __ASSERT_NO_MSG(ret == -1 || ret == sizeof(eventfd_t)); - if (ret < 0) { - return -1; - } - - return 0; + return zvfs_eventfd_read(fd, value); } int eventfd_write(int fd, eventfd_t value) { - int ret; - void *obj; - - obj = z_get_fd_obj(fd, &eventfd_fd_vtable, EBADF); - if (obj == NULL) { - return -1; - } - - ret = eventfd_rw_op(obj, &value, sizeof(eventfd_t), eventfd_write_locked); - __ASSERT_NO_MSG(ret == -1 || ret == sizeof(eventfd_t)); - if (ret < 0) { - return -1; - } - - return 0; + return zvfs_eventfd_write(fd, value); } diff --git a/subsys/net/lib/sockets/sockets_service.c b/subsys/net/lib/sockets/sockets_service.c index 1c1d106240971..fc156b4070312 100644 --- a/subsys/net/lib/sockets/sockets_service.c +++ b/subsys/net/lib/sockets/sockets_service.c @@ -10,18 +10,7 @@ LOG_MODULE_REGISTER(net_sock_svc, CONFIG_NET_SOCKETS_LOG_LEVEL); #include #include #include -#include - -/* Next checks makes sure that we are not trying to use this library - * with eventfd if CONFIG_POSIX_API is not set and if using native_sim - * based board. The reason is that we should always use zephyr libc based - * eventfd implementation instead of host libc one. - */ -#if defined(CONFIG_NATIVE_LIBC) && defined(CONFIG_EVENTFD) -#error "The eventfd support CONFIG_EVENTFD will not work with host libc " - "so you need to enable CONFIG_POSIX_API in this case which will turn " - "off the host libc usage." -#endif +#include static int init_socket_service(void); static bool init_done; @@ -94,7 +83,7 @@ int z_impl_net_socket_service_register(const struct net_socket_service_desc *svc } /* Tell the thread to re-read the variables */ - eventfd_write(ctx.events[0].fd, 1); + zvfs_eventfd_write(ctx.events[0].fd, 1); ret = 0; out: @@ -191,7 +180,7 @@ static int trigger_work(struct zsock_pollfd *pev) static void socket_service_thread(void) { int ret, i, fd, count = 0; - eventfd_t value; + zvfs_eventfd_t value; STRUCT_SECTION_COUNT(net_socket_service_desc, &ret); if (ret == 0) { @@ -222,11 +211,11 @@ static void socket_service_thread(void) ctx.count = count + 1; - /* Create an eventfd that can be used to trigger events during polling */ - fd = eventfd(0, 0); + /* Create an zvfs_eventfd that can be used to trigger events during polling */ + fd = zvfs_eventfd(0, 0); if (fd < 0) { fd = -errno; - NET_ERR("eventfd failed (%d)", fd); + NET_ERR("zvfs_eventfd failed (%d)", fd); goto out; } @@ -264,7 +253,7 @@ static void socket_service_thread(void) } if (ret > 0 && ctx.events[0].revents) { - eventfd_read(ctx.events[0].fd, &value); + zvfs_eventfd_read(ctx.events[0].fd, &value); NET_DBG("Received restart event."); goto restart; } diff --git a/tests/net/lib/http_server/crime/prj.conf b/tests/net/lib/http_server/crime/prj.conf index a1f7ef3a8efe5..3ade5d7a2c71d 100644 --- a/tests/net/lib/http_server/crime/prj.conf +++ b/tests/net/lib/http_server/crime/prj.conf @@ -11,7 +11,7 @@ CONFIG_ZTEST_STACK_SIZE=1024 CONFIG_ZVFS_OPEN_MAX=10 CONFIG_REQUIRES_FULL_LIBC=y -CONFIG_EVENTFD_MAX=10 +CONFIG_ZVFS_EVENTFD_MAX=10 CONFIG_NET_MAX_CONTEXTS=10 CONFIG_NET_MAX_CONN=10 diff --git a/tests/net/lib/http_server/prototype/prj.conf b/tests/net/lib/http_server/prototype/prj.conf index 5e9ad2b1412ad..dc0c192140a3b 100644 --- a/tests/net/lib/http_server/prototype/prj.conf +++ b/tests/net/lib/http_server/prototype/prj.conf @@ -9,7 +9,7 @@ CONFIG_ENTROPY_GENERATOR=y CONFIG_TEST_RANDOM_GENERATOR=y CONFIG_ZVFS_OPEN_MAX=10 CONFIG_REQUIRES_FULL_LIBC=y -CONFIG_EVENTFD_MAX=10 +CONFIG_ZVFS_EVENTFD_MAX=10 CONFIG_NET_MAX_CONTEXTS=10 CONFIG_NET_MAX_CONN=10 diff --git a/tests/net/lib/http_server/tls/prj.conf b/tests/net/lib/http_server/tls/prj.conf index 63af22cbdf6a1..c84cfe7c6554e 100644 --- a/tests/net/lib/http_server/tls/prj.conf +++ b/tests/net/lib/http_server/tls/prj.conf @@ -41,7 +41,7 @@ CONFIG_ZVFS_OPEN_MAX=32 CONFIG_NET_SOCKETS_POLL_MAX=32 CONFIG_ZVFS_OPEN_MAX=32 CONFIG_REQUIRES_FULL_LIBC=y -CONFIG_EVENTFD_MAX=10 +CONFIG_ZVFS_EVENTFD_MAX=10 CONFIG_NET_MAX_CONTEXTS=10 CONFIG_NET_MAX_CONN=10 diff --git a/tests/posix/eventfd/src/ioctl.c b/tests/posix/eventfd/src/ioctl.c index 28c2ce59e4acf..2c534b16ec2a2 100644 --- a/tests/posix/eventfd/src/ioctl.c +++ b/tests/posix/eventfd/src/ioctl.c @@ -5,6 +5,8 @@ */ #include "_main.h" + +#include #include #define EFD_IN_USE_INTERNAL 0x1 From 0fa97326c7dbc9c85d94302713c597bd40d9ab3e Mon Sep 17 00:00:00 2001 From: Chris Friedt Date: Fri, 24 May 2024 15:05:36 -0400 Subject: [PATCH 1754/2849] posix: create kconfig options for pse51, pse52, pse53 Create Kconfig "shortcuts" for PSE51, PSE52, and PSE53. Signed-off-by: Chris Friedt --- doc/services/portability/posix/aep/index.rst | 6 +- .../portability/posix/overview/index.rst | 45 +++-- drivers/wifi/simplelink/Kconfig.simplelink | 1 + include/zephyr/posix/posix_features.h | 16 ++ lib/posix/options/Kconfig | 8 +- lib/posix/options/Kconfig.aio | 1 - lib/posix/options/Kconfig.barrier | 1 - lib/posix/options/Kconfig.c_lib_ext | 1 - lib/posix/options/Kconfig.compat | 1 - lib/posix/options/Kconfig.device_io | 1 - lib/posix/options/Kconfig.fd_mgmt | 1 - lib/posix/options/Kconfig.mem | 2 +- lib/posix/options/Kconfig.mqueue | 1 - lib/posix/options/Kconfig.proc1 | 1 - lib/posix/options/Kconfig.procN | 1 - lib/posix/options/Kconfig.profile | 186 ++++++++++++++++++ lib/posix/options/Kconfig.pthread | 8 - lib/posix/options/Kconfig.rwlock | 1 - lib/posix/options/Kconfig.sched | 1 - lib/posix/options/Kconfig.semaphore | 1 - lib/posix/options/Kconfig.signal | 2 - lib/posix/options/Kconfig.spinlock | 1 - lib/posix/options/Kconfig.timer | 6 - lib/posix/options/Kconfig.xsi | 4 - modules/thrift/CMakeLists.txt | 1 - modules/thrift/src/_stat.c | 20 -- .../shell/shell_module/overlay-usb.conf | 1 + samples/subsys/shell/shell_module/prj.conf | 1 + .../subsys/shell/shell_module/prj_getopt.conf | 1 + .../subsys/shell/shell_module/prj_login.conf | 1 + samples/subsys/shell/shell_module/sample.yaml | 5 + subsys/net/lib/sockets/Kconfig | 2 - tests/posix/common/prj.conf | 20 +- tests/posix/fs/prj.conf | 1 - tests/posix/headers/prj.conf | 16 +- tests/posix/headers/src/arpa_inet_h.c | 2 +- tests/posix/headers/src/net_if_h.c | 2 +- tests/posix/headers/src/netdb_h.c | 2 +- tests/posix/headers/src/poll_h.c | 2 +- tests/posix/headers/src/sys_select_h.c | 2 +- tests/posix/headers/src/sys_socket_h.c | 2 +- tests/posix/net/prj.conf | 1 + tests/posix/pthread_pressure/prj.conf | 2 +- 43 files changed, 286 insertions(+), 95 deletions(-) create mode 100644 lib/posix/options/Kconfig.profile delete mode 100644 modules/thrift/src/_stat.c diff --git a/doc/services/portability/posix/aep/index.rst b/doc/services/portability/posix/aep/index.rst index b70ec23c92bd5..3896d052184ff 100644 --- a/doc/services/portability/posix/aep/index.rst +++ b/doc/services/portability/posix/aep/index.rst @@ -42,7 +42,7 @@ The *Minimal Realtime System Profile* (PSE51) includes all of the :header: Symbol, Support, Remarks :widths: 50, 10, 50 - _POSIX_AEP_REALTIME_MINIMAL, -1, + _POSIX_AEP_REALTIME_MINIMAL, -1, :kconfig:option:`CONFIG_POSIX_AEP_REALTIME_MINIMAL` .. csv-table:: PSE51 Option Groups :header: Symbol, Support, Remarks @@ -94,7 +94,7 @@ The *Realtime Controller System Profile* (PSE52) includes all features from PSE5 :header: Symbol, Support, Remarks :widths: 50, 10, 50 - _POSIX_AEP_REALTIME_CONTROLLER, -1, + _POSIX_AEP_REALTIME_CONTROLLER, -1, :kconfig:option:`CONFIG_POSIX_AEP_REALTIME_CONTROLLER` .. csv-table:: PSE52 Option Groups :header: Symbol, Support, Remarks @@ -134,7 +134,7 @@ The *Dedicated Realtime System Profile* (PSE53) includes all features from PSE52 :header: Symbol, Support, Remarks :widths: 50, 10, 50 - _POSIX_AEP_REALTIME_DEDICATED, -1, + _POSIX_AEP_REALTIME_DEDICATED, -1, :kconfig:option:`CONFIG_POSIX_AEP_REALTIME_DEDICATED` .. csv-table:: PSE53 Option Groups :header: Symbol, Support, Remarks diff --git a/doc/services/portability/posix/overview/index.rst b/doc/services/portability/posix/overview/index.rst index 2df6d39bbf5be..6c352cf245433 100644 --- a/doc/services/portability/posix/overview/index.rst +++ b/doc/services/portability/posix/overview/index.rst @@ -122,22 +122,43 @@ Configuration Like most features in Zephyr, POSIX features are :ref:`highly configurable` but disabled by default. Users must -explicitly choose to enable POSIX options via :ref:`Kconfig` selection. Indeed, there are -:ref:`many Kconfig options in Zephyr` for the POSIX API to allow for -feature selection at various levels of granularity. +explicitly choose to enable POSIX options via :ref:`Kconfig` selection. -Alternatively, users may enable one of the Kconfig options below as a shortcut to enable multiple -:ref:`Option Groups`. +Subprofiles ++++++++++++ -* :kconfig:option:`CONFIG_POSIX_API` - Enables all implemented POSIX API Options and Option Groups +Enable one of the Kconfig options below to quickly configure a pre-defined +:ref:`POSIX subprofile `. -.. note:: - Since the POSIX environment in Zephyr is fully configurable via :ref:`Kconfig`, - configurations that require modifying features should not be made if strict compliance is - required (POSIX-1.2017, section 2.1.3.1). +* :kconfig:option:`CONFIG_POSIX_AEP_CHOICE_BASE` (:ref:`Base `) +* :kconfig:option:`CONFIG_POSIX_AEP_CHOICE_PSE51` (:ref:`PSE51 `) +* :kconfig:option:`CONFIG_POSIX_AEP_CHOICE_PSE52` (:ref:`PSE52 `) +* :kconfig:option:`CONFIG_POSIX_AEP_CHOICE_PSE53` (:ref:`PSE53 `) + +Additional POSIX :ref:`Options and Option Groups ` may be enabled as needed +via Kconfig (e.g. ``CONFIG_POSIX_C_LIB_EXT=y``). Further fine-tuning may be accomplished via +:ref:`additional POSIX-related Kconfig options `. + +Subprofiles, Options, and Option Groups should be considered the preferred way to configure POSIX +in Zephyr going forward. + +Legacy +++++++ + +Historically, Zephyr used :kconfig:option:`CONFIG_POSIX_API` to configure a set of POSIX features +that was overloaded and always increasing in size. + +* :kconfig:option:`CONFIG_POSIX_API` + +The option is now frozen, and can be considered equivalent to the following: + +* :kconfig:option:`CONFIG_POSIX_AEP_CHOICE_PSE51` +* :kconfig:option:`CONFIG_POSIX_FD_MGMT` +* :kconfig:option:`CONFIG_POSIX_MESSAGE_PASSING` +* :kconfig:option:`CONFIG_POSIX_NETWORKING` -.. - TODO: create Kconfig shortcuts for PSE51, PSE52, and PSE53 +However, :kconfig:option:`CONFIG_POSIX_API` should be considered legacy and should not be used for +new Zephyr applications. .. _IEEE: https://www.ieee.org/ .. _IEEE Computer Society: https://www.computer.org/ diff --git a/drivers/wifi/simplelink/Kconfig.simplelink b/drivers/wifi/simplelink/Kconfig.simplelink index f2c5ccacbab31..c325a50f2cd4e 100644 --- a/drivers/wifi/simplelink/Kconfig.simplelink +++ b/drivers/wifi/simplelink/Kconfig.simplelink @@ -9,6 +9,7 @@ menuconfig WIFI_SIMPLELINK select WIFI_OFFLOAD select NET_L2_WIFI_MGMT select FDTABLE + select POSIX_SEMAPHORES if WIFI_SIMPLELINK diff --git a/include/zephyr/posix/posix_features.h b/include/zephyr/posix/posix_features.h index ccf5e314b9950..ed948158e7f91 100644 --- a/include/zephyr/posix/posix_features.h +++ b/include/zephyr/posix/posix_features.h @@ -11,6 +11,22 @@ #include /* CONFIG_* */ #include /* COND_CODE_1() */ +/* + * POSIX Application Environment Profiles (AEP - IEEE Std 1003.13-2003) + */ + +#ifdef CONFIG_POSIX_AEP_REALTIME_MINIMAL +#define _POSIX_AEP_REALTIME_MINIMAL 200312L +#endif + +#ifdef CONFIG_POSIX_AEP_REALTIME_CONTROLLER +#define _POSIX_AEP_REALTIME_CONTROLLER 200312L +#endif + +#ifdef CONFIG_POSIX_AEP_REALTIME_DEDICATED +#define _POSIX_AEP_REALTIME_DEDICATED 200312L +#endif + /* * POSIX System Interfaces */ diff --git a/lib/posix/options/Kconfig b/lib/posix/options/Kconfig index ee5161da899b7..bdf0ed4901f05 100644 --- a/lib/posix/options/Kconfig +++ b/lib/posix/options/Kconfig @@ -6,13 +6,7 @@ menu "POSIX Options" -config POSIX_API - depends on !NATIVE_APPLICATION - bool "POSIX APIs" - select NATIVE_LIBC_INCOMPATIBLE - help - Enable mostly-standards-compliant implementations of - various POSIX (IEEE 1003.1) APIs. +rsource "Kconfig.profile" rsource "Kconfig.aio" rsource "Kconfig.barrier" diff --git a/lib/posix/options/Kconfig.aio b/lib/posix/options/Kconfig.aio index cf99ae1d30c52..43e681f39abc8 100644 --- a/lib/posix/options/Kconfig.aio +++ b/lib/posix/options/Kconfig.aio @@ -4,7 +4,6 @@ config POSIX_ASYNCHRONOUS_IO bool "POSIX asynchronous I/O [EXPERIMENTAL]" - default y if POSIX_API select EXPERIMENTAL help Enable this option for asynchronous I/O. This option is present for conformance purposes diff --git a/lib/posix/options/Kconfig.barrier b/lib/posix/options/Kconfig.barrier index 1a6b2e46410d3..b349d0376551b 100644 --- a/lib/posix/options/Kconfig.barrier +++ b/lib/posix/options/Kconfig.barrier @@ -6,7 +6,6 @@ menuconfig POSIX_BARRIERS bool "POSIX barriers" - default y if POSIX_API help Select 'y' here to enable POSIX barriers. diff --git a/lib/posix/options/Kconfig.c_lib_ext b/lib/posix/options/Kconfig.c_lib_ext index 8acfead9b342c..e8c55d8818b19 100644 --- a/lib/posix/options/Kconfig.c_lib_ext +++ b/lib/posix/options/Kconfig.c_lib_ext @@ -4,7 +4,6 @@ menuconfig POSIX_C_LIB_EXT bool "POSIX general C library extension" - default y if POSIX_API help Select 'y' here and Zephyr will provide an implementation of the POSIX_C_LIB_EXT Option Group, consisting of fnmatch(), getopt(), getsubopt(), optarg, opterr, optind, optopt, diff --git a/lib/posix/options/Kconfig.compat b/lib/posix/options/Kconfig.compat index f9ad9cee8d59f..a07c2b125795e 100644 --- a/lib/posix/options/Kconfig.compat +++ b/lib/posix/options/Kconfig.compat @@ -10,7 +10,6 @@ config EVENTFD depends on !NATIVE_APPLICATION select ZVFS select ZVFS_EVENTFD - default y if POSIX_API help Enable support for event file descriptors, eventfd. An eventfd can be used as an event wait/notify mechanism together with POSIX calls diff --git a/lib/posix/options/Kconfig.device_io b/lib/posix/options/Kconfig.device_io index a93b51f5be627..9cfbd453102bc 100644 --- a/lib/posix/options/Kconfig.device_io +++ b/lib/posix/options/Kconfig.device_io @@ -6,7 +6,6 @@ menu "POSIX device I/O" config POSIX_DEVICE_IO bool "POSIX device I/O [EXPERIMENTAL]" - default y if POSIX_API select FDTABLE select EXPERIMENTAL help diff --git a/lib/posix/options/Kconfig.fd_mgmt b/lib/posix/options/Kconfig.fd_mgmt index f1bacac36d69e..ca16539560148 100644 --- a/lib/posix/options/Kconfig.fd_mgmt +++ b/lib/posix/options/Kconfig.fd_mgmt @@ -4,7 +4,6 @@ menuconfig POSIX_FD_MGMT bool "POSIX file descriptor management [EXPERIMENTAL]" - default y if POSIX_API select EXPERIMENTAL help Select 'y' here and Zephyr will provide implementations for the POSIX_FD_MGMT Option Group. diff --git a/lib/posix/options/Kconfig.mem b/lib/posix/options/Kconfig.mem index ad3f0a94ec2d4..5a5783340919d 100644 --- a/lib/posix/options/Kconfig.mem +++ b/lib/posix/options/Kconfig.mem @@ -5,7 +5,7 @@ config POSIX_PAGE_SIZE_BITS int "Number of bits to use for PAGE_SIZE" range 6 16 - default 12 if POSIX_API + default 12 if POSIX_BASE_DEFINITIONS default 6 help Define PAGE_SIZE as BIT(n), where n is the value configured here. diff --git a/lib/posix/options/Kconfig.mqueue b/lib/posix/options/Kconfig.mqueue index 607885b21cf75..4a1e9925fdaf1 100644 --- a/lib/posix/options/Kconfig.mqueue +++ b/lib/posix/options/Kconfig.mqueue @@ -4,7 +4,6 @@ menuconfig POSIX_MESSAGE_PASSING bool "POSIX message queue support" - default y if POSIX_API help This enabled POSIX message queue related APIs. diff --git a/lib/posix/options/Kconfig.proc1 b/lib/posix/options/Kconfig.proc1 index ecdcec802e25e..9ab29048ca2bb 100644 --- a/lib/posix/options/Kconfig.proc1 +++ b/lib/posix/options/Kconfig.proc1 @@ -6,7 +6,6 @@ menuconfig POSIX_SINGLE_PROCESS bool "POSIX single process support" - default y if POSIX_API # imply COMMON_LIBC_MALLOC # for env.c help Select 'y' here to use confstr(), environ, errno, getenv(), setenv(), sysconf(), uname(), diff --git a/lib/posix/options/Kconfig.procN b/lib/posix/options/Kconfig.procN index 7cc248e1abee0..b3a467b88b9d3 100644 --- a/lib/posix/options/Kconfig.procN +++ b/lib/posix/options/Kconfig.procN @@ -4,7 +4,6 @@ menuconfig POSIX_MULTI_PROCESS bool "POSIX multi-process support [EXPERIMENTAL]" - default y if POSIX_API select EXPERIMENTAL help Support for multi-processing. diff --git a/lib/posix/options/Kconfig.profile b/lib/posix/options/Kconfig.profile new file mode 100644 index 0000000000000..b57e07fbc2828 --- /dev/null +++ b/lib/posix/options/Kconfig.profile @@ -0,0 +1,186 @@ +# Copyright (c) 2024 Tenstorrent +# +# SPDX-License-Identifier: Apache-2.0 + +config POSIX_API + bool "POSIX APIs" + depends on !NATIVE_APPLICATION + select NATIVE_LIBC_INCOMPATIBLE + select POSIX_BASE_DEFINITIONS # clock_gettime(), pthread_create(), sem_get(), etc + select POSIX_AEP_REALTIME_MINIMAL # CLOCK_MONOTONIC, pthread_attr_setstack(), etc + select POSIX_NETWORKING if NETWORKING # inet_ntoa(), socket(), etc + imply EVENTFD # eventfd(), eventfd_read(), eventfd_write() + imply POSIX_FD_MGMT # open(), close(), read(), write() + imply POSIX_MESSAGE_PASSING # mq_open(), etc + imply POSIX_MULTI_PROCESS # sleep(), getpid(), etc + help + This option enables the required POSIX System Interfaces (base definitions), all of PSE51, + and some features found in PSE52. + + Note: in the future, this option may be deprecated in favour of subprofiling options. + +choice POSIX_AEP_CHOICE + prompt "POSIX Subprofile" + default POSIX_AEP_CHOICE_NONE + help + This choice is intended to help users select the correct POSIX profile for their + application. Choices are based on IEEE 1003.13-2003 (now inactive / reserved) and + extrapolated to the more recent Subprofiling Option Groups in IEEE 1003.3-2017. + + For more information, please refer to + https://standards.ieee.org/ieee/1003.13/3322/ + https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_subprofiles.html + +config POSIX_AEP_CHOICE_NONE + bool "No pre-defined POSIX subprofile" + help + No pre-defined POSIX profile is selected. + +config POSIX_AEP_CHOICE_BASE + bool "Base definitions (system interfaces)" + depends on !NATIVE_APPLICATION + select NATIVE_LIBC_INCOMPATIBLE + select POSIX_BASE_DEFINITIONS + help + Only enable the base definitions required for all POSIX systems. + + For more information, please see + https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap02.html#tag_02_01_03_01 + +config POSIX_AEP_CHOICE_PSE51 + bool "Minimal Realtime System Profile (PSE51)" + depends on !NATIVE_APPLICATION + select NATIVE_LIBC_INCOMPATIBLE + select POSIX_BASE_DEFINITIONS + select POSIX_AEP_REALTIME_MINIMAL + help + PSE51 includes the POSIX Base Definitions (System Interfaces) as well as several Options and + Option Groups to facilitate device I/O, signals, mandatory configuration utilities, and + threading. + + For more information, please see + https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_subprofiles.html + +config POSIX_AEP_CHOICE_PSE52 + bool "Realtime Controller System Profile (PSE52)" + depends on !NATIVE_APPLICATION + select NATIVE_LIBC_INCOMPATIBLE + select POSIX_BASE_DEFINITIONS + select POSIX_AEP_REALTIME_MINIMAL + select POSIX_AEP_REALTIME_CONTROLLER + help + PSE52 includes the POSIX Base Definitions (System Interfaces) as well as all features of + PSE51. Additionally, it includes interfaces for file descriptor management, filesystem + support, support for message queues, and tracing. + + For more information, please see + https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_subprofiles.html + +config POSIX_AEP_CHOICE_PSE53 + bool "Dedicated Realtime System Profile (PSE53)" + depends on !NATIVE_APPLICATION + select NATIVE_LIBC_INCOMPATIBLE + select POSIX_BASE_DEFINITIONS + select POSIX_AEP_REALTIME_MINIMAL + select POSIX_AEP_REALTIME_CONTROLLER + select POSIX_AEP_REALTIME_DEDICATED + help + PSE53 includes the POSIX Base Definitions (System Interfaces) as well as all features of + PSE52. Additionally, it includes interfaces for POSIX multi-processing, networking, pipes, + and prioritized I/O. + + For more information, please see + https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_subprofiles.html + +# TODO: PSE54: Multi-purpose Realtime System Profile + +endchoice # POSIX_AEP_CHOICE + +# Base Definitions (System Interfaces) +config POSIX_BASE_DEFINITIONS + bool + select POSIX_ASYNCHRONOUS_IO + select POSIX_BARRIERS + select POSIX_CLOCK_SELECTION + # select POSIX_MAPPED_FILES + # select POSIX_MEMORY_PROTECTION + select POSIX_READER_WRITER_LOCKS + select POSIX_REALTIME_SIGNALS + select POSIX_SEMAPHORES + select POSIX_SPIN_LOCKS + select POSIX_THREAD_SAFE_FUNCTIONS + select POSIX_THREADS + select POSIX_TIMEOUTS + select POSIX_TIMERS + help + This option is not user configurable. It may be configured indirectly by selecting + CONFIG_POSIX_AEP_CHOICE_BASE=y. + + For more information, please see + https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap02.html#tag_02_01_03_01 + +config POSIX_AEP_REALTIME_MINIMAL + bool + # Option Groups + select POSIX_DEVICE_IO + select POSIX_SIGNALS + select POSIX_SINGLE_PROCESS + select XSI_THREADS_EXT + # Options + select POSIX_FSYNC + # select POSIX_MEMLOCK + # select POSIX_MEMLOCK_RANGE + select POSIX_MONOTONIC_CLOCK + # select POSIX_SHARED_MEMORY_OBJECTS + select POSIX_SYNCHRONIZED_IO + select POSIX_THREAD_ATTR_STACKADDR + select POSIX_THREAD_ATTR_STACKSIZE + select POSIX_THREAD_CPUTIME + select POSIX_THREAD_PRIO_INHERIT + select POSIX_THREAD_PRIO_PROTECT + select POSIX_THREAD_PRIORITY_SCHEDULING + # select POSIX_THREAD_SPORADIC_SERVER + help + This option is not user configurable. It may be configured indirectly by selecting + CONFIG_POSIX_AEP_CHOICE_PSE51=y. + + For more information, please see + https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_subprofiles.html + +config POSIX_AEP_REALTIME_CONTROLLER + bool + # Option Groups + select POSIX_FD_MGMT + select POSIX_FILE_SYSTEM + # Options + select POSIX_MESSAGE_PASSING + # select POSIX_TRACE + # select POSIX_TRACE_EVENT_FILTER + # select POSIX_TRACE_LOG + help + This option is not user configurable. It may be configured indirectly by selecting + CONFIG_POSIX_AEP_CHOICE_PSE52=y. + + For more information, please see + https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_subprofiles.html + +config POSIX_AEP_REALTIME_DEDICATED + bool + # Option Groups + select POSIX_MULTI_PROCESS + select POSIX_NETWORKING + # select POSIX_PIPE + # select POSIX_SIGNAL_JUMP + # Options + select POSIX_CPUTIME + # select POSIX_PRIORITIZED_IO + select POSIX_PRIORITY_SCHEDULING + select POSIX_RAW_SOCKETS + # select POSIX_SPAWN + # select POSIX_SPORADIC_SERVER + help + This option is not user configurable. It may be configured indirectly by selecting + CONFIG_POSIX_AEP_CHOICE_PSE53=y. + + For more information, please see + https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_subprofiles.html diff --git a/lib/posix/options/Kconfig.pthread b/lib/posix/options/Kconfig.pthread index 8c1b813c872e3..ec38286ff49a3 100644 --- a/lib/posix/options/Kconfig.pthread +++ b/lib/posix/options/Kconfig.pthread @@ -6,7 +6,6 @@ menuconfig POSIX_THREADS bool "POSIX thread support" - default y if POSIX_API help Select 'y' here to enable POSIX threads, mutexes, condition variables, and thread-specific storage. @@ -65,7 +64,6 @@ config PTHREAD_RECYCLER_DELAY_MS config POSIX_THREAD_ATTR_STACKADDR bool "Support getting and setting POSIX thread stack addresses" - default y help Enable this option to use pthread_attr_getstackaddr() and pthread_attr_setstackaddr(). @@ -80,7 +78,6 @@ config POSIX_THREAD_ATTR_STACKADDR config POSIX_THREAD_ATTR_STACKSIZE bool "Support getting and setting POSIX thread stack sizes" - default y help Enable this option to use pthread_attr_getstacksize() or pthread_attr_setstacksize(). @@ -90,7 +87,6 @@ config POSIX_THREAD_ATTR_STACKSIZE config POSIX_THREADS_EXT bool "Extended POSIX thread support" - default y help Enable this option to use pthread_attr_getguardsize(), pthread_attr_setguardsize(), pthread_mutexattr_gettype(), or pthread_mutexattr_settype(). @@ -100,7 +96,6 @@ config POSIX_THREADS_EXT config POSIX_THREAD_PRIORITY_SCHEDULING bool "Run POSIX threads with different priorities and schedulers" - default y help Enabling this option allows the application to configure different priorities and scheduling algorithms for different threads via functions such as pthread_setschedparam() @@ -145,7 +140,6 @@ config POSIX_PTHREAD_ATTR_GUARDSIZE_DEFAULT config POSIX_THREAD_PRIO_INHERIT bool "POSIX mutex priority inheritance" - default y help Select 'y' here to enable POSIX mutex priority inheritance. @@ -154,7 +148,6 @@ config POSIX_THREAD_PRIO_INHERIT config POSIX_THREAD_PRIO_PROTECT bool "POSIX mutex priority protection" - default y help Select 'y' here to enable POSIX mutex priority protection. @@ -163,7 +156,6 @@ config POSIX_THREAD_PRIO_PROTECT config POSIX_THREAD_SAFE_FUNCTIONS bool "POSIX thread-safe functions" - default y help Select 'y' here to enable POSIX thread-safe functions including asctime_r(), ctime_r(), flockfile(), ftrylockfile(), funlockfile(), getc_unlocked(), getchar_unlocked(), diff --git a/lib/posix/options/Kconfig.rwlock b/lib/posix/options/Kconfig.rwlock index ed19520725a68..8626b3bb1a40b 100644 --- a/lib/posix/options/Kconfig.rwlock +++ b/lib/posix/options/Kconfig.rwlock @@ -4,7 +4,6 @@ menuconfig POSIX_READER_WRITER_LOCKS bool "POSIX reader-writer locks" - default y if POSIX_API help Select 'y' here to enable POSIX reader-writer locks. diff --git a/lib/posix/options/Kconfig.sched b/lib/posix/options/Kconfig.sched index f8dbbf6931b2e..7e0dc70fca119 100644 --- a/lib/posix/options/Kconfig.sched +++ b/lib/posix/options/Kconfig.sched @@ -6,7 +6,6 @@ menu "POSIX scheduler options" config POSIX_PRIORITY_SCHEDULING bool "POSIX priority-based process scheduling [EXPERIMENTAL]" - default y if POSIX_API select EXPERIMENTAL help This enables POSIX scheduling APIs (_POSIX_PRIORITY_SCHEDULING). diff --git a/lib/posix/options/Kconfig.semaphore b/lib/posix/options/Kconfig.semaphore index 231565f3258a2..65bc2a686930b 100644 --- a/lib/posix/options/Kconfig.semaphore +++ b/lib/posix/options/Kconfig.semaphore @@ -4,7 +4,6 @@ menuconfig POSIX_SEMAPHORES bool "POSIX semaphore support" - default y if POSIX_API help Enable this option for POSIX semaphore support. diff --git a/lib/posix/options/Kconfig.signal b/lib/posix/options/Kconfig.signal index 81fcd6a696ce9..4507302e3f32d 100644 --- a/lib/posix/options/Kconfig.signal +++ b/lib/posix/options/Kconfig.signal @@ -6,7 +6,6 @@ menu "POSIX signals" config POSIX_REALTIME_SIGNALS bool "POSIX realtime signals [EXPERIMENTAL]" - default y if POSIX_API select EXPERIMENTAL help Enable support for POSIX realtime signals. @@ -24,7 +23,6 @@ endif # POSIX_REALTIME_SIGNALS config POSIX_SIGNALS bool "POSIX signals [EXPERIMENTAL]" - default y if POSIX_API select EXPERIMENTAL help Enable support for POSIX signals. diff --git a/lib/posix/options/Kconfig.spinlock b/lib/posix/options/Kconfig.spinlock index d5eb4a7028ae8..312a432ce38e9 100644 --- a/lib/posix/options/Kconfig.spinlock +++ b/lib/posix/options/Kconfig.spinlock @@ -4,7 +4,6 @@ menuconfig POSIX_SPIN_LOCKS bool "POSIX spin locks" - default y if POSIX_API help Select 'y' here to enable POSIX spin locks. diff --git a/lib/posix/options/Kconfig.timer b/lib/posix/options/Kconfig.timer index cd53379716a53..42eed40bce68d 100644 --- a/lib/posix/options/Kconfig.timer +++ b/lib/posix/options/Kconfig.timer @@ -5,7 +5,6 @@ menuconfig POSIX_TIMERS bool "POSIX timers, clocks, and sleep functions" - default y if POSIX_API help Select 'y' here and Zephyr will provide implementations of clock_getres(), clock_gettime(), clock_settime(), nanosleep(), timer_create(), timer_delete(), timer_getoverrun(), @@ -18,7 +17,6 @@ if POSIX_TIMERS config POSIX_THREAD_CPUTIME bool "POSIX per-thread CPU-time clocks" - default y help This enables CLOCK_THREAD_CPUTIME_ID. @@ -29,7 +27,6 @@ config POSIX_THREAD_CPUTIME config POSIX_MONOTONIC_CLOCK bool "POSIX Monotonic clock support" - default y help This enables CLOCK_MONOTONIC. @@ -39,7 +36,6 @@ config POSIX_MONOTONIC_CLOCK config POSIX_CPUTIME bool "POSIX per-process CPU-time clocks" - default y help This enables CLOCK_PROCESS_CPUTIME_ID. @@ -50,7 +46,6 @@ config POSIX_CPUTIME config POSIX_CLOCK_SELECTION bool "POSIX Clock selection" - default y help This enables POSIX clock selection. @@ -79,7 +74,6 @@ config POSIX_TIMER_MAX config POSIX_TIMEOUTS bool "Support timeouts for some blocking POSIX services" - default y help Enable mandatory timeouts for some blocking operations. diff --git a/lib/posix/options/Kconfig.xsi b/lib/posix/options/Kconfig.xsi index ac66838b89217..f8be61e245d5d 100644 --- a/lib/posix/options/Kconfig.xsi +++ b/lib/posix/options/Kconfig.xsi @@ -6,7 +6,6 @@ menu "X/Open system interfaces" config XSI_SINGLE_PROCESS bool "X/Open single process" - default y if POSIX_API depends on POSIX_SINGLE_PROCESS depends on POSIX_TIMERS help @@ -18,7 +17,6 @@ config XSI_SINGLE_PROCESS config XOPEN_STREAMS bool "X/Open streams" - default y if POSIX_API help This option provides support for the X/Open Streams interface, including functions such as fattach(), fdetach(), getmsg(), getpmsg(), putmsg(), and putpmsg(). @@ -28,7 +26,6 @@ config XOPEN_STREAMS config XSI_SYSTEM_LOGGING bool "X/Open system logging" - default y if POSIX_API help This option provides support for closelog(), openlog(), syslog(), setlogmask(), and vsyslog(). @@ -38,7 +35,6 @@ config XSI_SYSTEM_LOGGING config XSI_THREADS_EXT bool "X/Open threads extensions" - default y if POSIX_API help This option provides support for pthread_attr_getstack(), pthread_attr_setstack(), pthread_getconcurrency(), and pthread_setconcurrency(). diff --git a/modules/thrift/CMakeLists.txt b/modules/thrift/CMakeLists.txt index 468286c03e6c1..d26b6ef9c3ee4 100644 --- a/modules/thrift/CMakeLists.txt +++ b/modules/thrift/CMakeLists.txt @@ -12,7 +12,6 @@ zephyr_include_directories(include) zephyr_include_directories(${THRIFT_UPSTREAM}/lib/cpp/src) zephyr_library_sources( - src/_stat.c src/thrift/server/TFDServer.cpp ${THRIFT_UPSTREAM}/lib/cpp/src/thrift/protocol/TProtocol.cpp ${THRIFT_UPSTREAM}/lib/cpp/src/thrift/server/TConnectedClient.cpp diff --git a/modules/thrift/src/_stat.c b/modules/thrift/src/_stat.c deleted file mode 100644 index 688e1a53ceffb..0000000000000 --- a/modules/thrift/src/_stat.c +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright 2022 Meta - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include -#include - -#include - -int stat(const char *restrict path, struct stat *restrict buf) -{ - ARG_UNUSED(path); - ARG_UNUSED(buf); - - errno = ENOTSUP; - - return -1; -} diff --git a/samples/subsys/shell/shell_module/overlay-usb.conf b/samples/subsys/shell/shell_module/overlay-usb.conf index a9afb6499cf92..b92529f9cc612 100644 --- a/samples/subsys/shell/shell_module/overlay-usb.conf +++ b/samples/subsys/shell/shell_module/overlay-usb.conf @@ -6,6 +6,7 @@ CONFIG_USB_DEVICE_INITIALIZE_AT_BOOT=n # POSIX_TIMERS requires an embedded C library while the native USB driver is incompatible with it. # So let's disable it. Once USB_NATIVE_POSIX supports embedded C libraries this can be removed. +CONFIG_POSIX_API=n CONFIG_POSIX_TIMERS=n # DATE_SHELL requires POSIX_TIMERS CONFIG_DATE_SHELL=n diff --git a/samples/subsys/shell/shell_module/prj.conf b/samples/subsys/shell/shell_module/prj.conf index c6cc76bca402e..ff7c665b38155 100644 --- a/samples/subsys/shell/shell_module/prj.conf +++ b/samples/subsys/shell/shell_module/prj.conf @@ -9,6 +9,7 @@ CONFIG_THREAD_MONITOR=y CONFIG_BOOT_BANNER=n CONFIG_THREAD_NAME=y CONFIG_DEVICE_SHELL=y +CONFIG_POSIX_API=y CONFIG_POSIX_TIMERS=y CONFIG_DATE_SHELL=y CONFIG_THREAD_RUNTIME_STATS=y diff --git a/samples/subsys/shell/shell_module/prj_getopt.conf b/samples/subsys/shell/shell_module/prj_getopt.conf index e3c8ecbc805bb..8f04ab27d7c62 100644 --- a/samples/subsys/shell/shell_module/prj_getopt.conf +++ b/samples/subsys/shell/shell_module/prj_getopt.conf @@ -9,6 +9,7 @@ CONFIG_THREAD_MONITOR=y CONFIG_BOOT_BANNER=n CONFIG_THREAD_NAME=y CONFIG_DEVICE_SHELL=y +CONFIG_POSIX_API=y CONFIG_POSIX_TIMERS=y CONFIG_DATE_SHELL=y CONFIG_THREAD_RUNTIME_STATS=y diff --git a/samples/subsys/shell/shell_module/prj_login.conf b/samples/subsys/shell/shell_module/prj_login.conf index ff8e8a06c0df1..470a41044f82f 100644 --- a/samples/subsys/shell/shell_module/prj_login.conf +++ b/samples/subsys/shell/shell_module/prj_login.conf @@ -8,6 +8,7 @@ CONFIG_THREAD_MONITOR=y CONFIG_BOOT_BANNER=n CONFIG_THREAD_NAME=y CONFIG_DEVICE_SHELL=y +CONFIG_POSIX_API=y CONFIG_POSIX_TIMERS=y CONFIG_DATE_SHELL=y CONFIG_THREAD_RUNTIME_STATS=y diff --git a/samples/subsys/shell/shell_module/sample.yaml b/samples/subsys/shell/shell_module/sample.yaml index cfd6adb80de64..482e4a37875fa 100644 --- a/samples/subsys/shell/shell_module/sample.yaml +++ b/samples/subsys/shell/shell_module/sample.yaml @@ -1,5 +1,10 @@ sample: name: Shell Sample +common: + filter: not CONFIG_NATIVE_LIBC + platform_exclude: + - native_posix + - native_posix/native/64 tests: sample.shell.shell_module: filter: CONFIG_SERIAL and dt_chosen_enabled("zephyr,shell-uart") diff --git a/subsys/net/lib/sockets/Kconfig b/subsys/net/lib/sockets/Kconfig index 5805eb7e4c8cc..3f40f3a133af6 100644 --- a/subsys/net/lib/sockets/Kconfig +++ b/subsys/net/lib/sockets/Kconfig @@ -103,8 +103,6 @@ config NET_SOCKETS_SERVICE bool "Socket service support [EXPERIMENTAL]" select EXPERIMENTAL select EVENTFD - # We select here POSIX_API so that zephyr libc will be used for native_sim - select POSIX_API if BOARD_NATIVE_SIM help The socket service can monitor multiple sockets and save memory by only having one thread listening socket data. If data is received diff --git a/tests/posix/common/prj.conf b/tests/posix/common/prj.conf index 51c709dee7bc6..94f671badcfb6 100644 --- a/tests/posix/common/prj.conf +++ b/tests/posix/common/prj.conf @@ -1,7 +1,6 @@ CONFIG_POSIX_API=y CONFIG_POSIX_THREAD_THREADS_MAX=6 CONFIG_ZTEST=y -CONFIG_POSIX_NETWORKING=n CONFIG_POSIX_SEM_VALUE_MAX=32767 CONFIG_POSIX_MESSAGE_PASSING=y CONFIG_POSIX_PRIORITY_SCHEDULING=y @@ -10,3 +9,22 @@ CONFIG_THREAD_NAME=y CONFIG_DYNAMIC_THREAD=y CONFIG_THREAD_STACK_INFO=y CONFIG_DYNAMIC_THREAD_POOL_SIZE=6 + +# for fnmatch() +CONFIG_POSIX_C_LIB_EXT=y + +# for putmsg() +CONFIG_XOPEN_STREAMS=y + +# for sleep(), getpid() +CONFIG_POSIX_MULTI_PROCESS=y + +# for syslog() +CONFIG_XSI_SYSTEM_LOGGING=y + +# for sched_get_priority_min(), sched_get_priority_max() +CONFIG_POSIX_PRIORITY_SCHEDULING=y + +# for networking +CONFIG_NET_TEST=y +CONFIG_TEST_RANDOM_GENERATOR=y diff --git a/tests/posix/fs/prj.conf b/tests/posix/fs/prj.conf index ce47ef9f097c9..da73481ef4d1a 100644 --- a/tests/posix/fs/prj.conf +++ b/tests/posix/fs/prj.conf @@ -4,6 +4,5 @@ CONFIG_FAT_FILESYSTEM_ELM=y CONFIG_POSIX_API=y CONFIG_POSIX_FILE_SYSTEM=y CONFIG_ZTEST=y -CONFIG_POSIX_NETWORKING=n CONFIG_MAIN_STACK_SIZE=4096 CONFIG_EVENTFD=n diff --git a/tests/posix/headers/prj.conf b/tests/posix/headers/prj.conf index cfad8467f38eb..374baf4cbdfa6 100644 --- a/tests/posix/headers/prj.conf +++ b/tests/posix/headers/prj.conf @@ -2,20 +2,22 @@ CONFIG_POSIX_API=y CONFIG_ZTEST=y # for POSIX_FILESYSTEM -CONFIG_FILE_SYSTEM=y +CONFIG_POSIX_FILE_SYSTEM=y -# for select to work +# for networking things to work +CONFIG_NETWORKING=y +CONFIG_POSIX_NETWORKING=y CONFIG_NET_TEST=y CONFIG_TEST_RANDOM_GENERATOR=y -CONFIG_NET_SOCKETS=y -CONFIG_NETWORKING=y -# for socketpair to work -CONFIG_NET_SOCKETPAIR=y +# For e.g. sched_get_priority_max() +CONFIG_POSIX_PRIORITY_SCHEDULING=y + +# For putmsg(), etc +CONFIG_XOPEN_STREAMS=y # for when CONFIG_POSIX_API is not selected CONFIG_POSIX_THREADS=y -CONFIG_POSIX_FILE_SYSTEM=y CONFIG_POSIX_TIMERS=y CONFIG_POSIX_MESSAGE_PASSING=y CONFIG_EVENTFD=y diff --git a/tests/posix/headers/src/arpa_inet_h.c b/tests/posix/headers/src/arpa_inet_h.c index 06541e1cd7b60..1b3b90dc0de1b 100644 --- a/tests/posix/headers/src/arpa_inet_h.c +++ b/tests/posix/headers/src/arpa_inet_h.c @@ -24,7 +24,7 @@ ZTEST(posix_headers, test_arpa_inet_h) zassert_not_equal(-1, ntohl(0)); zassert_not_equal(-1, ntohs(0)); - if (IS_ENABLED(CONFIG_POSIX_API)) { + if (IS_ENABLED(CONFIG_POSIX_NETWORKING)) { /* zassert_not_null(inet_addr); */ /* not implemented */ /* zassert_not_null(inet_ntoa); */ /* not implemented */ zassert_not_null(inet_ntop); diff --git a/tests/posix/headers/src/net_if_h.c b/tests/posix/headers/src/net_if_h.c index bc88e992f68e0..3843d2b83d620 100644 --- a/tests/posix/headers/src/net_if_h.c +++ b/tests/posix/headers/src/net_if_h.c @@ -24,7 +24,7 @@ ZTEST(posix_headers, test_net_if_h) zassert_not_equal(-1, IF_NAMESIZE); - if (IS_ENABLED(CONFIG_POSIX_API)) { + if (IS_ENABLED(CONFIG_POSIX_NETWORKING)) { zassert_not_null(if_freenameindex); zassert_not_null(if_indextoname); zassert_not_null(if_nameindex); diff --git a/tests/posix/headers/src/netdb_h.c b/tests/posix/headers/src/netdb_h.c index 85e69fb7c55c9..9426c56b5a389 100644 --- a/tests/posix/headers/src/netdb_h.c +++ b/tests/posix/headers/src/netdb_h.c @@ -76,7 +76,7 @@ ZTEST(posix_headers, test_netdb_h) zassert_not_equal(-1, EAI_SYSTEM); zassert_not_equal(-1, EAI_OVERFLOW); - if (IS_ENABLED(CONFIG_POSIX_API)) { + if (IS_ENABLED(CONFIG_POSIX_NETWORKING)) { zassert_not_null(endhostent); zassert_not_null(endnetent); zassert_not_null(endprotoent); diff --git a/tests/posix/headers/src/poll_h.c b/tests/posix/headers/src/poll_h.c index ff4257939ddfe..f858ed070ca95 100644 --- a/tests/posix/headers/src/poll_h.c +++ b/tests/posix/headers/src/poll_h.c @@ -36,7 +36,7 @@ ZTEST(posix_headers, test_poll_h) zassert_not_equal(-1, POLLHUP); zassert_not_equal(-1, POLLNVAL); - if (IS_ENABLED(CONFIG_POSIX_API)) { + if (IS_ENABLED(CONFIG_POSIX_DEVICE_IO)) { zassert_not_null(poll); } } diff --git a/tests/posix/headers/src/sys_select_h.c b/tests/posix/headers/src/sys_select_h.c index 6ea986cbae268..5cca45419712d 100644 --- a/tests/posix/headers/src/sys_select_h.c +++ b/tests/posix/headers/src/sys_select_h.c @@ -27,7 +27,7 @@ ZTEST(posix_headers, test_sys_select_h) FD_SET(0, &fds); FD_ZERO(&fds); - if (IS_ENABLED(CONFIG_POSIX_API)) { + if (IS_ENABLED(CONFIG_POSIX_DEVICE_IO)) { /* zassert_not_null(pselect); */ /* not implemented */ zassert_not_null(select); } diff --git a/tests/posix/headers/src/sys_socket_h.c b/tests/posix/headers/src/sys_socket_h.c index 52ec01a21312d..843e6c16d7678 100644 --- a/tests/posix/headers/src/sys_socket_h.c +++ b/tests/posix/headers/src/sys_socket_h.c @@ -100,7 +100,7 @@ ZTEST(posix_headers, test_sys_socket_h) zassert_not_equal(-1, SHUT_RDWR); zassert_not_equal(-1, SHUT_WR); - if (IS_ENABLED(CONFIG_POSIX_API)) { + if (IS_ENABLED(CONFIG_POSIX_NETWORKING)) { zassert_not_null(accept); zassert_not_null(bind); zassert_not_null(connect); diff --git a/tests/posix/net/prj.conf b/tests/posix/net/prj.conf index 0b840d09dfdc4..1620a7010d7a6 100644 --- a/tests/posix/net/prj.conf +++ b/tests/posix/net/prj.conf @@ -4,3 +4,4 @@ CONFIG_TEST_RANDOM_GENERATOR=y CONFIG_POSIX_API=y CONFIG_POSIX_NETWORKING=y +CONFIG_NETWORKING=y diff --git a/tests/posix/pthread_pressure/prj.conf b/tests/posix/pthread_pressure/prj.conf index e2b190b19feea..4af4ae83e921e 100644 --- a/tests/posix/pthread_pressure/prj.conf +++ b/tests/posix/pthread_pressure/prj.conf @@ -1,6 +1,6 @@ CONFIG_ZTEST=y CONFIG_POSIX_API=y -CONFIG_POSIX_NETWORKING=n +CONFIG_POSIX_PRIORITY_SCHEDULING=y ## Note: for benchmarking purposes, uncomment the Kconfig below # CONFIG_TEST_DURATION_S=60 From fe1e7f8d378fd767a95bb1acc01283e4471c6a81 Mon Sep 17 00:00:00 2001 From: Chris Friedt Date: Sat, 25 May 2024 09:53:29 -0400 Subject: [PATCH 1755/2849] doc: release: posix: deprecate non-normative POSIX Kconfig Add release notes for the deprecation of a number of POSIX Kconfig options. These have been deprecated so that we can use more normative Kconfig variable identifiers, based on the Options and Option Groups of IEEE 1003.1-2017. To simplify migration, use python $ZEPHYR_BASE/scripts/utils/migrate_posix_kconfigs.py \ -r root_path Additionally, document the removal of PTHREAD_BARRIER_DEFINE(), EFD_IN_USE, EFD_FLAGS_SET, which were previously deprecated >= 2 release cycles before. Signed-off-by: Chris Friedt --- doc/releases/migration-guide-3.7.rst | 13 ++ doc/releases/release-notes-3.7.rst | 49 +++++++ .../portability/posix/conformance/index.rst | 2 +- lib/posix/options/signal.c | 1 + scripts/utils/migrate_posix_kconfigs.py | 137 ++++++++++++++++++ 5 files changed, 201 insertions(+), 1 deletion(-) create mode 100644 scripts/utils/migrate_posix_kconfigs.py diff --git a/doc/releases/migration-guide-3.7.rst b/doc/releases/migration-guide-3.7.rst index b7f2b3630eeb7..5fb4cfe135327 100644 --- a/doc/releases/migration-guide-3.7.rst +++ b/doc/releases/migration-guide-3.7.rst @@ -581,6 +581,19 @@ Modem * The ``CONFIG_MODEM_CHAT_LOG_BUFFER`` Kconfig option was renamed to :kconfig:option:`CONFIG_MODEM_CHAT_LOG_BUFFER_SIZE`. (:github:`70405`) +.. _zephyr_3.7_posix_api_migration: + +POSIX API +========= + +* The :ref:`POSIX API Kconfig deprecations ` may require + changes to Kconfig files (``prj.conf``, etc), as outlined in the release notes. A more automated + approach is available via the provided migration script. Simply run the following: + + .. code-block:: bash + + $ python ${ZEPHYR_BASE}/scripts/utils/migrate_posix_kconfigs.py -r root_path + Shell ===== diff --git a/doc/releases/release-notes-3.7.rst b/doc/releases/release-notes-3.7.rst index 159b75aaae92f..024922e924d76 100644 --- a/doc/releases/release-notes-3.7.rst +++ b/doc/releases/release-notes-3.7.rst @@ -62,6 +62,55 @@ 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. +.. _zephyr_3.7_posix_api_deprecations: + + * POSIX API + + * Deprecated :c:macro:`PTHREAD_BARRIER_DEFINE` has been removed. + * Deprecated :c:macro:`EFD_IN_USE` and :c:macro:`EFD_FLAGS_SET` have been removed. + + * In efforts to use Kconfig options that map directly to the Options and Option Groups in + IEEE 1003.1-2017, the following Kconfig options have been deprecated (replaced by): + + * :kconfig:option:`CONFIG_EVENTFD_MAX` (:kconfig:option:`CONFIG_ZVFS_EVENTFD_MAX`) + * :kconfig:option:`CONFIG_FNMATCH` (:kconfig:option:`CONFIG_POSIX_C_LIB_EXT`) + * :kconfig:option:`CONFIG_GETENTROPY` (:kconfig:option:`CONFIG_POSIX_C_LIB_EXT`) + * :kconfig:option:`CONFIG_GETOPT` (:kconfig:option:`CONFIG_POSIX_C_LIB_EXT`) +  * :kconfig:option:`CONFIG_MAX_PTHREAD_COUNT` (:kconfig:option:`CONFIG_POSIX_THREAD_THREADS_MAX`) + * :kconfig:option:`CONFIG_MAX_PTHREAD_KEY_COUNT` (:kconfig:option:`CONFIG_POSIX_THREAD_KEYS_MAX`) + * :kconfig:option:`CONFIG_MAX_TIMER_COUNT` (:kconfig:option:`CONFIG_POSIX_TIMER_MAX`) + * :kconfig:option:`CONFIG_POSIX_LIMITS_RTSIG_MAX` (:kconfig:option:`CONFIG_POSIX_RTSIG_MAX`) + * :kconfig:option:`CONFIG_POSIX_CLOCK` (:kconfig:option:`CONFIG_POSIX_CLOCK_SELECTION`, + :kconfig:option:`CONFIG_POSIX_CPUTIME`, :kconfig:option:`CONFIG_POSIX_MONOTONIC_CLOCK`, + :kconfig:option:`CONFIG_POSIX_TIMERS`, and :kconfig:option:`CONFIG_POSIX_TIMEOUTS`) + * :kconfig:option:`CONFIG_POSIX_CONFSTR` (:kconfig:option:`CONFIG_POSIX_SINGLE_PROCESS`) + * :kconfig:option:`CONFIG_POSIX_ENV` (:kconfig:option:`CONFIG_POSIX_SINGLE_PROCESS`) + * :kconfig:option:`CONFIG_POSIX_FS` (:kconfig:option:`CONFIG_POSIX_FILE_SYSTEM`) + * :kconfig:option:`CONFIG_POSIX_MAX_FDS` (:kconfig:option:`CONFIG_POSIX_OPEN_MAX` and + :kconfig:option:`CONFIG_ZVFS_OPEN_MAX`) + * :kconfig:option:`CONFIG_POSIX_MAX_OPEN_FILES` (:kconfig:option:`CONFIG_POSIX_OPEN_MAX` and + :kconfig:option:`CONFIG_ZVFS_OPEN_MAX`) + * :kconfig:option:`CONFIG_POSIX_MQUEUE` (:kconfig:option:`CONFIG_POSIX_MESSAGE_PASSING`) + * :kconfig:option:`CONFIG_POSIX_PUTMSG` (:kconfig:option:`CONFIG_XOPEN_STREAMS`) + * :kconfig:option:`CONFIG_POSIX_SIGNAL` (:kconfig:option:`CONFIG_POSIX_SIGNALS`) + * :kconfig:option:`CONFIG_POSIX_SYSCONF` (:kconfig:option:`CONFIG_POSIX_SINGLE_PROCESS`) + * :kconfig:option:`CONFIG_POSIX_SYSLOG` (:kconfig:option:`CONFIG_XSI_SYSTEM_LOGGING`) + * :kconfig:option:`CONFIG_POSIX_UNAME` (:kconfig:option:`CONFIG_POSIX_SINGLE_PROCESS`) + * :kconfig:option:`CONFIG_PTHREAD` (:kconfig:option:`CONFIG_POSIX_THREADS`) + * :kconfig:option:`CONFIG_PTHREAD_BARRIER` (:kconfig:option:`CONFIG_POSIX_BARRIERS`) + * :kconfig:option:`CONFIG_PTHREAD_COND` (:kconfig:option:`CONFIG_POSIX_THREADS`) + * :kconfig:option:`CONFIG_PTHREAD_IPC` (:kconfig:option:`CONFIG_POSIX_THREADS`) + * :kconfig:option:`CONFIG_PTHREAD_KEY` (:kconfig:option:`CONFIG_POSIX_THREADS`) + * :kconfig:option:`CONFIG_PTHREAD_MUTEX` (:kconfig:option:`CONFIG_POSIX_THREADS`) + * :kconfig:option:`CONFIG_PTHREAD_RWLOCK` (:kconfig:option:`CONFIG_POSIX_READER_WRITER_LOCKS`) + * :kconfig:option:`CONFIG_PTHREAD_SPINLOCK` (:kconfig:option:`CONFIG_POSIX_SPIN_LOCKS`) + * :kconfig:option:`CONFIG_SEM_NAMELEN_MAX` (:kconfig:option:`CONFIG_POSIX_SEM_NAMELEN_MAX`) + * :kconfig:option:`CONFIG_SEM_VALUE_MAX` (:kconfig:option:`CONFIG_POSIX_SEM_VALUE_MAX`) + * :kconfig:option:`CONFIG_TIMER` (:kconfig:option:`CONFIG_POSIX_TIMERS`) + * :kconfig:option:`CONFIG_TIMER_DELAYTIMER_MAX` (:kconfig:option:`CONFIG_POSIX_DELAYTIMER_MAX`) + + Please see the :ref:`POSIX API migration guide `. + * SPI * Deprecated :c:func:`spi_is_ready` API function has been removed. diff --git a/doc/services/portability/posix/conformance/index.rst b/doc/services/portability/posix/conformance/index.rst index 7de7fc26e3e9e..302bf4f6e71f3 100644 --- a/doc/services/portability/posix/conformance/index.rst +++ b/doc/services/portability/posix/conformance/index.rst @@ -39,7 +39,7 @@ POSIX System Interfaces _POSIX_MAPPED_FILES, -1, :ref:`†` _POSIX_MEMORY_PROTECTION, -1, :ref:`†` :ref:`_POSIX_READER_WRITER_LOCKS`, 200809L, :kconfig:option:`CONFIG_POSIX_READER_WRITER_LOCKS` - :ref:`_POSIX_REALTIME_SIGNALS`, -1, + :ref:`_POSIX_REALTIME_SIGNALS`, -1, :kconfig:option:`CONFIG_POSIX_REALTIME_SIGNALS` :ref:`_POSIX_SEMAPHORES`, 200809L, :kconfig:option:`CONFIG_POSIX_SEMAPHORES` :ref:`_POSIX_SPIN_LOCKS`, 200809L, :kconfig:option:`CONFIG_POSIX_SPIN_LOCKS` :ref:`_POSIX_THREAD_SAFE_FUNCTIONS`, -1, :kconfig:option:`CONFIG_POSIX_THREAD_SAFE_FUNCTIONS` diff --git a/lib/posix/options/signal.c b/lib/posix/options/signal.c index 362742063fc7f..d0674aea94b4d 100644 --- a/lib/posix/options/signal.c +++ b/lib/posix/options/signal.c @@ -8,6 +8,7 @@ #include #include +#include #include #define SIGNO_WORD_IDX(_signo) (signo / BITS_PER_LONG) diff --git a/scripts/utils/migrate_posix_kconfigs.py b/scripts/utils/migrate_posix_kconfigs.py new file mode 100644 index 0000000000000..ea8eed2d2f8e5 --- /dev/null +++ b/scripts/utils/migrate_posix_kconfigs.py @@ -0,0 +1,137 @@ +""" +Utility script to migrate Zephyr-based projects to normative POSIX Kconfig options. + +This script should be used for migrating from versions of Zephyr older than v3.7.0 to Zephyr +version v3.7.0 or later. + +Usage:: + + python $ZEPHYR_BASE/scripts/utils/migrate_posix_kconfigs.py -r root_path + +The utility will process c, cpp, h, hpp, rst, conf, CMakeLists.txt, +yml, yaml and Kconfig files. + + +Copyright (c) 2022 Nordic Semiconductor ASA +Copyright (c) 2024 Tenstorrent AI ULC +SPDX-License-Identifier: Apache-2.0 +""" + +import argparse +from pathlib import Path +import re +import sys + + +ZEPHYR_BASE = Path(__file__).parents[2] + +FILE_PATTERNS = ( + r".+\.c", r".+\.cpp", r".+\.hpp", r".+\.h", r".+\.rst", r".+\.conf", + r".+\.yml", r".+\.yaml", r"CMakeLists.txt", r"Kconfig(\..+)?" +) + +REPLACEMENTS = { + "EVENTFD_MAX": "ZVFS_EVENTFD_MAX", + "FNMATCH": "POSIX_C_LIB_EXT", + "GETENTROPY": "POSIX_C_LIB_EXT", + "GETOPT": "POSIX_C_LIB_EXT", + "MAX_PTHREAD_COUNT": "POSIX_THREAD_THREADS_MAX", + "MAX_PTHREAD_KEY_COUNT": "POSIX_THREAD_KEYS_MAX", + "MAX_TIMER_COUNT": "POSIX_TIMER_MAX", + "MSG_COUNT_MAX": "POSIX_MQ_OPEN_MAX", + "POSIX_CLOCK": "POSIX_TIMERS", + "POSIX_CONFSTR": "POSIX_SINGLE_PROCESS", + "POSIX_ENV": "POSIX_SINGLE_PROCESS", + "POSIX_FS": "POSIX_FILE_SYSTEM", + "POSIX_LIMITS_RTSIG_MAX": "POSIX_RTSIG_MAX", + "POSIX_MAX_FDS": "ZVFS_OPEN_MAX", + "POSIX_MAX_OPEN_FILES": "ZVFS_OPEN_MAX", + "POSIX_MQUEUE": "POSIX_MESSAGE_PASSING", + "POSIX_PUTMSG": "XOPEN_STREAMS", + "POSIX_SIGNAL": "POSIX_SIGNALS", + "POSIX_SYSCONF": "POSIX_SINGLE_PROCESS", + "POSIX_SYSLOG": "XSI_SYSTEM_LOGGING", + "POSIX_UNAME": "POSIX_SINGLE_PROCESS", + "PTHREAD": "POSIX_THREADS", + "PTHREAD_BARRIER": "POSIX_BARRIERS", + "PTHREAD_COND": "POSIX_THREADS", + "PTHREAD_IPC": "POSIX_THREADS", + "PTHREAD_KEY": "POSIX_THREADS", + "PTHREAD_MUTEX": "POSIX_THREADS", + "PTHREAD_RWLOCK": "POSIX_READER_WRITER_LOCKS", + "PTHREAD_SPINLOCK": "POSIX_SPIN_LOCKS", + "TIMER": "POSIX_TIMERS", + "TIMER_DELAYTIMER_MAX": "POSIX_DELAYTIMER_MAX", + "SEM_NAMELEN_MAX": "POSIX_SEM_NAME_MAX", + "SEM_VALUE_MAX": "POSIX_SEM_VALUE_MAX", +} + +MESSAGES = { + "POSIX_CLOCK": + "POSIX_CLOCK is a one-to-many replacement. If this simple substitution is not " + "sufficient, it's best to try a combination of POSIX_CLOCK_SELECTION, POSIX_CPUTIME, " + "POSIX_MONOTONIC_CLOCK, POSIX_TIMERS, and POSIX_TIMEOUTS.", + "POSIX_MAX_FDS": + "A read-only version of this symbol is POSIX_OPEN_MAX, which is of course, the standard " + "symbol. ZVFS_OPEN_MAX may be set by the user. Consider using POSIX_MAX_FDS if the " + "use-case is read-only.", +} + + +def process_file(path): + modified = False + output = [] + + try: + with open(path) as f: + lines = f.readlines() + + for line in lines: + longest = "" + length = 0 + for m in REPLACEMENTS: + if re.match(".*" + m + ".*", line) and len(m) > length: + length = len(m) + longest = m + + if length != 0: + modified = True + line = line.replace(longest, REPLACEMENTS[longest]) + msg = MESSAGES.get(longest) + if msg: + print( + f"Notice: {longest} -> {REPLACEMENTS[longest]}: {msg}") + + output.append(line) + + if modified is False: + return + + with open(path, "w") as f: + f.writelines(output) + + except UnicodeDecodeError: + print(f"Unable to read lines from {path}", file=sys.stderr) + except Exception as e: + print(f"Failed with exception {e}", e) + + +def process_tree(project): + for p in project.glob("**/*"): + for fp in FILE_PATTERNS: + cfp = re.compile(".+/" + fp + "$") + if re.match(cfp, str(p)) is not None: + process_file(p) + + +if __name__ == "__main__": + parser = argparse.ArgumentParser(allow_abbrev=False) + parser.add_argument( + "-r", + "--root", + type=Path, + required=True, + help="Zephyr-based project path") + args = parser.parse_args() + + process_tree(args.root) From f74a84b251cd21a71ce0c6f47019919c68730d27 Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Wed, 10 Apr 2024 19:39:11 +0000 Subject: [PATCH 1756/2849] xtensa: mmu: MMU re-initialization API With power managment is enabled, depending on the SoC power state used when idle, the MMU may lose context and may need to be re-initialized. When re-initializing the MMU, we must not re-create the page table because it may overwrite changes done during the execution, but we still need to set the asid and page table for the current context. Signed-off-by: Flavio Ceolin --- arch/xtensa/core/ptables.c | 18 ++++++++++++++++++ include/zephyr/arch/xtensa/xtensa_mmu.h | 10 ++++++++++ 2 files changed, 28 insertions(+) diff --git a/arch/xtensa/core/ptables.c b/arch/xtensa/core/ptables.c index f44e17ad6a953..3ae39c6c1f3a4 100644 --- a/arch/xtensa/core/ptables.c +++ b/arch/xtensa/core/ptables.c @@ -320,6 +320,24 @@ void xtensa_mmu_init(void) arch_xtensa_mmu_post_init(_current_cpu->id == 0); } +void xtensa_mmu_reinit(void) +{ + /* First initialize the hardware */ + xtensa_init_paging(xtensa_kernel_ptables); + +#ifdef CONFIG_USERSPACE + struct k_thread *thread = _current_cpu->current; + struct arch_mem_domain *domain = + &(thread->mem_domain_info.mem_domain->arch); + + + /* Set the page table for current context */ + xtensa_set_paging(domain->asid, domain->ptables); +#endif /* CONFIG_USERSPACE */ + + arch_xtensa_mmu_post_init(_current_cpu->id == 0); +} + #ifdef CONFIG_ARCH_HAS_RESERVED_PAGE_FRAMES /* Zephyr's linker scripts for Xtensa usually puts * something before z_mapped_start (aka .text), diff --git a/include/zephyr/arch/xtensa/xtensa_mmu.h b/include/zephyr/arch/xtensa/xtensa_mmu.h index d4deca40b311b..91da6a4f65688 100644 --- a/include/zephyr/arch/xtensa/xtensa_mmu.h +++ b/include/zephyr/arch/xtensa/xtensa_mmu.h @@ -123,6 +123,16 @@ extern int xtensa_soc_mmu_ranges_num; */ void xtensa_mmu_init(void); +/** + * @brief Re-initialize hardware MMU. + * + * This configures the MMU hardware when the cpu lost context and has + * re-started. + * + * It assumes that the page table is already created and accessible in memory. + */ +void xtensa_mmu_reinit(void); + /** * @brief Tell other processors to flush TLBs. * From 459517badcaacad9cf4d1781c43c4b34e62771ae Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Tue, 14 May 2024 17:54:14 +0000 Subject: [PATCH 1757/2849] drivers/flash/spi_nor: Fix DPD exit Incorrectly placed preprocessor conditions caused exit_dpd when there has been no instance of a device with dpd_wakeup_sequence parameter. Signed-off-by: Dominik Ermel Signed-off-by: Jan Tore Guggedal --- drivers/flash/spi_nor.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/flash/spi_nor.c b/drivers/flash/spi_nor.c index 1c46a9103ef57..36d7a664f70c2 100644 --- a/drivers/flash/spi_nor.c +++ b/drivers/flash/spi_nor.c @@ -515,13 +515,14 @@ static int enter_dpd(const struct device *const dev) static int exit_dpd(const struct device *const dev) { int ret = 0; +#if ANY_INST_HAS_DPD const struct spi_nor_config *cfg = dev->config; if (cfg->dpd_exist) { delay_until_exit_dpd_ok(dev); -#if ANY_INST_HAS_DPD_WAKEUP_SEQUENCE if (cfg->dpd_wakeup_sequence_exist) { +#if ANY_INST_HAS_DPD_WAKEUP_SEQUENCE /* Assert CSn and wait for tCRDP. * * Unfortunately the SPI API doesn't allow us to @@ -534,6 +535,7 @@ static int exit_dpd(const struct device *const dev) /* Deassert CSn and wait for tRDP */ k_sleep(K_MSEC(cfg->t_rdp_ms)); +#endif /* ANY_INST_HAS_DPD_WAKEUP_SEQUENCE */ } else { ret = spi_nor_cmd_write(dev, SPI_NOR_CMD_RDPD); @@ -545,8 +547,8 @@ static int exit_dpd(const struct device *const dev) } #endif /* T_EXIT_DPD */ } -#endif /* DPD_WAKEUP_SEQUENCE */ } +#endif /* ANY_INST_HAS_DPD */ return ret; } From 26d56eb0a5bd2c40c5b9cb98650997b5606a9cf8 Mon Sep 17 00:00:00 2001 From: Andrej Butok Date: Tue, 4 Jun 2024 15:47:48 +0200 Subject: [PATCH 1758/2849] boards: nxp: frdm_k22f: fix the flash size value - The MK22FN512VLH12 chip, installed on frdm_k22f, has 512 KB of Program Flash and 128KB SRAM according to the K22P121M120SF7RM.pdf manual (page 55). - Fix the flash size to 512KB (was 1MB). - Add nxp_k22fn512.dtsi with correct flash size value. Signed-off-by: Andrej Butok --- boards/nxp/frdm_k22f/doc/index.rst | 2 +- boards/nxp/frdm_k22f/frdm_k22f.dts | 3 ++- dts/arm/nxp/nxp_k22fn512.dtsi | 11 +++++++++++ 3 files changed, 14 insertions(+), 2 deletions(-) create mode 100644 dts/arm/nxp/nxp_k22fn512.dtsi diff --git a/boards/nxp/frdm_k22f/doc/index.rst b/boards/nxp/frdm_k22f/doc/index.rst index f0f98048561c7..b92fa508cd022 100644 --- a/boards/nxp/frdm_k22f/doc/index.rst +++ b/boards/nxp/frdm_k22f/doc/index.rst @@ -26,7 +26,7 @@ MCUs. Hardware ******** -- MK22FN512VLH12 (120 MHz, 1 MB flash memory, 256 KB RAM, low-power, +- MK22FN512VLH12 (120 MHz, 512 KB flash memory, 128 KB RAM, low-power, crystal-less USB, and 64 pin Low profile Quad Flat Package (LQFP)) - Dual role USB interface with micro-B USB connector - RGB LED diff --git a/boards/nxp/frdm_k22f/frdm_k22f.dts b/boards/nxp/frdm_k22f/frdm_k22f.dts index 587aaa65ee108..b3a085560fb15 100644 --- a/boards/nxp/frdm_k22f/frdm_k22f.dts +++ b/boards/nxp/frdm_k22f/frdm_k22f.dts @@ -1,12 +1,13 @@ /* * Copyright (c) 2018 Prevas A/S + * Copyright 2024 NXP * * SPDX-License-Identifier: Apache-2.0 */ /dts-v1/; -#include +#include #include #include "frdm_k22f-pinctrl.dtsi" #include diff --git a/dts/arm/nxp/nxp_k22fn512.dtsi b/dts/arm/nxp/nxp_k22fn512.dtsi new file mode 100644 index 0000000000000..76244b94d597b --- /dev/null +++ b/dts/arm/nxp/nxp_k22fn512.dtsi @@ -0,0 +1,11 @@ +/* + * Copyright 2024 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +&flash0 { + reg = <0 DT_SIZE_K(512)>; +}; From 5c308e0344a0743a796a224e51b34b7f94f7647d Mon Sep 17 00:00:00 2001 From: Yassine El Aissaoui Date: Tue, 4 Jun 2024 10:51:23 +0200 Subject: [PATCH 1759/2849] bluetooth: hci_nxp: move vendor specific setup to its dedicated place Some vendor specific setup was done inside the open() HCI function, those should be inside setup() function instead. Signed-off-by: Yassine El Aissaoui --- drivers/bluetooth/hci/Kconfig | 1 + drivers/bluetooth/hci/hci_nxp.c | 14 +++++++++++++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/drivers/bluetooth/hci/Kconfig b/drivers/bluetooth/hci/Kconfig index d00cb7315634a..282eda93e9720 100644 --- a/drivers/bluetooth/hci/Kconfig +++ b/drivers/bluetooth/hci/Kconfig @@ -112,6 +112,7 @@ config BT_DA1469X config BT_NXP bool "NXP HCI driver" + select BT_HCI_SETUP help NXP HCI bluetooth interface diff --git a/drivers/bluetooth/hci/hci_nxp.c b/drivers/bluetooth/hci/hci_nxp.c index 78016a794b5fd..293ba3cfff1ee 100644 --- a/drivers/bluetooth/hci/hci_nxp.c +++ b/drivers/bluetooth/hci/hci_nxp.c @@ -312,7 +312,18 @@ static int bt_nxp_open(void) LOG_ERR("HCI open failed"); break; } + } while (false); + + return ret; +} + +int bt_nxp_setup(const struct bt_hci_setup_params *params) +{ + ARG_UNUSED(params); + + int ret; + do { #if CONFIG_HCI_NXP_SET_CAL_DATA ret = bt_nxp_set_calibration_data(); if (ret < 0) { @@ -345,7 +356,7 @@ static int bt_nxp_open(void) LOG_ERR("Failed to configure controller autosleep"); break; } -#endif +#endif /* CONFIG_HCI_NXP_ENABLE_AUTO_SLEEP */ } while (false); return ret; @@ -373,6 +384,7 @@ static int bt_nxp_close(void) static const struct bt_hci_driver drv = { .name = "BT NXP", .open = bt_nxp_open, + .setup = bt_nxp_setup, .close = bt_nxp_close, .send = bt_nxp_send, .bus = BT_HCI_DRIVER_BUS_IPM, From 02dfda818d31372738140103833c1dbe14b0c048 Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Fri, 31 May 2024 20:56:34 +0200 Subject: [PATCH 1760/2849] fs: Fix MAX_FILE_NAME setting for LittleFS Fix MAX_FILE_NAME for LittleFS, which was set to 255, while currently allowed is 255. Fixes #72394 Signed-off-by: Dominik Ermel --- include/zephyr/fs/fs_interface.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/zephyr/fs/fs_interface.h b/include/zephyr/fs/fs_interface.h index 5db637635b954..9521ad88a87a5 100644 --- a/include/zephyr/fs/fs_interface.h +++ b/include/zephyr/fs/fs_interface.h @@ -34,7 +34,7 @@ extern "C" { #endif #if !defined(MAX_FILE_NAME) && defined(CONFIG_FILE_SYSTEM_LITTLEFS) -#define MAX_FILE_NAME 256 +#define MAX_FILE_NAME 255 #endif #if !defined(MAX_FILE_NAME) /* filesystem selection */ From c9a21363a12fe4a20d4b8c1b67148e7a0421a7e0 Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Fri, 31 May 2024 21:00:22 +0200 Subject: [PATCH 1761/2849] fs: Improved CONFIG_FILE_SYSTEM_MAX_FILE_NAME processing The processing of CONFIG_FILE_SYSTEM_MAX_FILE_NAME override for MAX_FILE_NAME has been improved to limit possibility to set it to value that is not allowed by any of the in-tree subsystems, when such subsystem is enabled. When no in-tree subsystem is allowed the value is still not limited. Signed-off-by: Dominik Ermel --- include/zephyr/fs/fs_interface.h | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/include/zephyr/fs/fs_interface.h b/include/zephyr/fs/fs_interface.h index 9521ad88a87a5..1f0d26ce5bc1e 100644 --- a/include/zephyr/fs/fs_interface.h +++ b/include/zephyr/fs/fs_interface.h @@ -13,10 +13,23 @@ extern "C" { #endif -#if defined(CONFIG_FILE_SYSTEM_MAX_FILE_NAME) && (CONFIG_FILE_SYSTEM_MAX_FILE_NAME - 0) > 0 +#if defined(CONFIG_FILE_SYSTEM_MAX_FILE_NAME) && (CONFIG_FILE_SYSTEM_MAX_FILE_NAME - 0) > 0 + +/* No in-tree file system supports name longer than 255 characters */ +#if (CONFIG_FILE_SYSTEM_LITTLEFS || CONFIG_FAT_FILESYSTEM_ELM || \ + CONFIG_FILE_SYSTEM_EXT2) && (CONFIG_FILE_SYSTEM_MAX_FILE_NAME > 255) +#error "Max allowed CONFIG_FILE_SYSTEM_MAX_FILE_NAME is 255 characters, when any in-tree FS enabled" +#endif + +/* Enabled FAT driver, without LFN, restricts name length to 12 characters */ +#if defined(CONFIG_FAT_FILESYSTEM_ELM) && !(CONFIG_FS_FATFS_LFN) && \ + (CONFIG_FILE_SYSTEM_MAX_FILE_NAME > 12) +#error "CONFIG_FILE_SYSTEM_MAX_FILE_NAME can not be > 12 if FAT is enabled without LFN" +#endif + #define MAX_FILE_NAME CONFIG_FILE_SYSTEM_MAX_FILE_NAME -#else /* CONFIG_FILE_SYSTEM_MAX_FILE_NAME */ +#else /* Select from enabled file systems */ #if defined(CONFIG_FAT_FILESYSTEM_ELM) From ed7a5f31c2a47606fe438eb9cf22363c2a411052 Mon Sep 17 00:00:00 2001 From: Peter Mitsis Date: Wed, 29 May 2024 11:44:10 -0400 Subject: [PATCH 1762/2849] kernel: Update CONFIG_PIPES Kconfig description Updates the CONFIG_PIPES Kconfig description to add a note that enabling it will cause a slight increase to the thread structure. This mirrors a similar comment in CONFIG_EVENTS. Signed-off-by: Peter Mitsis --- kernel/Kconfig | 3 +++ 1 file changed, 3 insertions(+) diff --git a/kernel/Kconfig b/kernel/Kconfig index c65ec351fcb3e..8b8def8b52e4f 100644 --- a/kernel/Kconfig +++ b/kernel/Kconfig @@ -704,6 +704,9 @@ config PIPES allows a thread to send a byte stream to another thread. Pipes can be used to synchronously transfer chunks of data in whole or in part. + Note that setting this option slightly increases the size of the + thread structure. + config KERNEL_MEM_POOL bool "Use Kernel Memory Pool" default y From 46e3cfa6653830a751d8f31fa9d07d25ea272a59 Mon Sep 17 00:00:00 2001 From: Peter Mitsis Date: Wed, 29 May 2024 11:46:28 -0400 Subject: [PATCH 1763/2849] doc: kernel: Fix pipes configuration option link Updates the pipes documentation to generate a link to CONFIG_PIPES Kconfig option description instead of merely listing the name of this option. Signed-off-by: Peter Mitsis --- doc/kernel/services/data_passing/pipes.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/kernel/services/data_passing/pipes.rst b/doc/kernel/services/data_passing/pipes.rst index bdeec48f0117b..c4cb571fc07ee 100644 --- a/doc/kernel/services/data_passing/pipes.rst +++ b/doc/kernel/services/data_passing/pipes.rst @@ -231,7 +231,7 @@ Configuration Options Related configuration options: -* CONFIG_PIPES +* :kconfig:option:`CONFIG_PIPES` API Reference ************* From 6a8674ce1218261ca2a8681e34b0defe410ba5d3 Mon Sep 17 00:00:00 2001 From: Sadik Ozer Date: Tue, 16 Jan 2024 13:35:15 +0300 Subject: [PATCH 1764/2849] soc: Add the MAX32680 SoC Add MAX32680 Kconfig and dts files Co-authored-by: Tahsin Mutlugun Signed-off-by: Sadik Ozer --- dts/arm/adi/max32/max32680-pinctrl.dtsi | 294 +++++++++++++++++++++++ dts/arm/adi/max32/max32680.dtsi | 59 +++++ soc/adi/max32/Kconfig | 3 + soc/adi/max32/Kconfig.defconfig.max32680 | 14 ++ soc/adi/max32/Kconfig.soc | 9 + soc/adi/max32/soc.yml | 3 + 6 files changed, 382 insertions(+) create mode 100644 dts/arm/adi/max32/max32680-pinctrl.dtsi create mode 100644 dts/arm/adi/max32/max32680.dtsi create mode 100644 soc/adi/max32/Kconfig.defconfig.max32680 diff --git a/dts/arm/adi/max32/max32680-pinctrl.dtsi b/dts/arm/adi/max32/max32680-pinctrl.dtsi new file mode 100644 index 0000000000000..525666cb14c9d --- /dev/null +++ b/dts/arm/adi/max32/max32680-pinctrl.dtsi @@ -0,0 +1,294 @@ +/* + * Copyright (c) 2024 Analog Devices, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +/ { + soc { + pinctrl: pin-controller@40008000 { + + /omit-if-no-ref/ uart0a_rx_p0_0: uart0a_rx_p0_0 { + pinmux = ; + }; + + /omit-if-no-ref/ uart0a_tx_p0_1: uart0a_tx_p0_1 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr0a_ioa_p0_2: tmr0a_ioa_p0_2 { + pinmux = ; + }; + + /omit-if-no-ref/ uart0b_cts_p0_2: uart0b_cts_p0_2 { + pinmux = ; + }; + + /omit-if-no-ref/ ext_clk_p0_3: ext_clk_p0_3 { + pinmux = ; + }; + + /omit-if-no-ref/ spi0a_ss0_p0_4: spi0a_ss0_p0_4 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr0b_ioan_p0_4: tmr0b_ioan_p0_4 { + pinmux = ; + }; + + /omit-if-no-ref/ spi0a_mosi_p0_5: spi0a_mosi_p0_5 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr0b_iobn_p0_5: tmr0b_iobn_p0_5 { + pinmux = ; + }; + + /omit-if-no-ref/ spi0a_miso_p0_6: spi0a_miso_p0_6 { + pinmux = ; + }; + + /omit-if-no-ref/ owm_io_p0_6: owm_io_p0_6 { + pinmux = ; + }; + + /omit-if-no-ref/ spi0a_sck_p0_7: spi0a_sck_p0_7 { + pinmux = ; + }; + + /omit-if-no-ref/ owm_pe_p0_7: owm_pe_p0_7 { + pinmux = ; + }; + + /omit-if-no-ref/ spi0a_sdio2_p0_8: spi0a_sdio2_p0_8 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr0b_ioa_p0_8: tmr0b_ioa_p0_8 { + pinmux = ; + }; + + /omit-if-no-ref/ spi0a_sdio3_p0_9: spi0a_sdio3_p0_9 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr0b_iob_p0_9: tmr0b_iob_p0_9 { + pinmux = ; + }; + + /omit-if-no-ref/ i2c0a_scl_p0_10: i2c0a_scl_p0_10 { + pinmux = ; + }; + + /omit-if-no-ref/ spi0b_ss2_p0_10: spi0b_ss2_p0_10 { + pinmux = ; + }; + + /omit-if-no-ref/ i2c0a_sda_p0_11: i2c0a_sda_p0_11 { + pinmux = ; + }; + + /omit-if-no-ref/ spi0b_ss1_p0_11: spi0b_ss1_p0_11 { + pinmux = ; + }; + + /omit-if-no-ref/ uart1a_rx_p0_12: uart1a_rx_p0_12 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr1b_ioa_p0_12: tmr1b_ioa_p0_12 { + pinmux = ; + }; + + /omit-if-no-ref/ uart1a_tx_p0_13: uart1a_tx_p0_13 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr1b_iobn_p0_13: tmr1b_iobn_p0_13 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr1a_ioa_p0_14: tmr1a_ioa_p0_14 { + pinmux = ; + }; + + /omit-if-no-ref/ uart1b_cts_p0_14: uart1b_cts_p0_14 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr1a_iob_p0_15: tmr1a_iob_p0_15 { + pinmux = ; + }; + + /omit-if-no-ref/ uart1b_rts_p0_15: uart1b_rts_p0_15 { + pinmux = ; + }; + + /omit-if-no-ref/ i2c1a_scl_p0_16: i2c1a_scl_p0_16 { + pinmux = ; + }; + + /omit-if-no-ref/ pt2_p0_16: pt2_p0_16 { + pinmux = ; + }; + + /omit-if-no-ref/ i2c1a_sda_p0_17: i2c1a_sda_p0_17 { + pinmux = ; + }; + + /omit-if-no-ref/ pt3_p0_17: pt3_p0_17 { + pinmux = ; + }; + + /omit-if-no-ref/ spi1a_sdio2_p0_24: spi1a_sdio2_p0_24 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr2b_ioa_p0_24: tmr2b_ioa_p0_24 { + pinmux = ; + }; + + /omit-if-no-ref/ adc0_rdy_p0_24: adc0_rdy_p0_24 { + pinmux = ; + }; + + /omit-if-no-ref/ spi1a_sdio3_p0_25: spi1a_sdio3_p0_25 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr2b_iob_p0_25: tmr2b_iob_p0_25 { + pinmux = ; + }; + + /omit-if-no-ref/ adc1_rdy_p0_25: adc1_rdy_p0_25 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr2a_ioa_p0_26: tmr2a_ioa_p0_26 { + pinmux = ; + }; + + /omit-if-no-ref/ spi1b_ss1_p0_26: spi1b_ss1_p0_26 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr2a_iob_p0_27: tmr2a_iob_p0_27 { + pinmux = ; + }; + + /omit-if-no-ref/ spi1b_ss2_p0_27: spi1b_ss2_p0_27 { + pinmux = ; + }; + + /omit-if-no-ref/ swdio_p0_28: swdio_p0_28 { + pinmux = ; + }; + + /omit-if-no-ref/ swclk_p0_29: swclk_p0_29 { + pinmux = ; + }; + + /omit-if-no-ref/ uart2a_rx_p1_0: uart2a_rx_p1_0 { + pinmux = ; + }; + + /omit-if-no-ref/ rv_tck_p1_0: rv_tck_p1_0 { + pinmux = ; + }; + + /omit-if-no-ref/ uart2a_tx_p1_1: uart2a_tx_p1_1 { + pinmux = ; + }; + + /omit-if-no-ref/ rv_tms_p1_1: rv_tms_p1_1 { + pinmux = ; + }; + + /omit-if-no-ref/ i2s0a_sck_p1_2: i2s0a_sck_p1_2 { + pinmux = ; + }; + + /omit-if-no-ref/ rv_tdi_p1_2: rv_tdi_p1_2 { + pinmux = ; + }; + + /omit-if-no-ref/ i2s0a_lrclk_p1_3: i2s0a_lrclk_p1_3 { + pinmux = ; + }; + + /omit-if-no-ref/ rv_tdo_p1_3: rv_tdo_p1_3 { + pinmux = ; + }; + + /omit-if-no-ref/ i2s0a_sdi_p1_4: i2s0a_sdi_p1_4 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr3b_ioa_p1_4: tmr3b_ioa_p1_4 { + pinmux = ; + }; + + /omit-if-no-ref/ i2s0a_sdo_p1_5: i2s0a_sdo_p1_5 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr3b_iob_p1_5: tmr3b_iob_p1_5 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr3a_ioa_p1_6: tmr3a_ioa_p1_6 { + pinmux = ; + }; + + /omit-if-no-ref/ ble_ant_ctrl2_p1_6: ble_ant_ctrl2_p1_6 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr3a_iob_p1_7: tmr3a_iob_p1_7 { + pinmux = ; + }; + + /omit-if-no-ref/ ble_ant_ctrl3_p1_7: ble_ant_ctrl3_p1_7 { + pinmux = ; + }; + + /omit-if-no-ref/ ain12_p2_4: ain12_p2_4 { + pinmux = ; + }; + + /omit-if-no-ref/ lptmr0b_ioa_p2_4: lptmr0b_ioa_p2_4 { + pinmux = ; + }; + + /omit-if-no-ref/ ain13_p2_5: ain13_p2_5 { + pinmux = ; + }; + + /omit-if-no-ref/ lptmr1b_ioa_p2_5: lptmr1b_ioa_p2_5 { + pinmux = ; + }; + + /omit-if-no-ref/ lptmr0_clk_p2_6: lptmr0_clk_p2_6 { + pinmux = ; + }; + + /omit-if-no-ref/ lpuartb_r_p2_6: lpuartb_r_p2_6 { + pinmux = ; + }; + + /omit-if-no-ref/ x_p2_6: x_p2_6 { + pinmux = ; + }; + + /omit-if-no-ref/ lptmr1_clk_p2_7: lptmr1_clk_p2_7 { + pinmux = ; + }; + + /omit-if-no-ref/ lpuartb_tx_p2_7: lpuartb_tx_p2_7 { + pinmux = ; + }; + }; + }; +}; diff --git a/dts/arm/adi/max32/max32680.dtsi b/dts/arm/adi/max32/max32680.dtsi new file mode 100644 index 0000000000000..47c883b50b2bd --- /dev/null +++ b/dts/arm/adi/max32/max32680.dtsi @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2024 Analog Devices, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +&pinctrl { + reg = <0x40008000 0x2400>; + + gpio2: gpio@40080400 { + reg = <0x40080400 0x200>; + compatible = "adi,max32-gpio"; + gpio-controller; + #gpio-cells = <2>; + interrupts = <26 0>; + clocks = <&gcr ADI_MAX32_CLOCK_BUS2 0>; + status = "disabled"; + }; + + gpio3: gpio@40080600 { + reg = <0x40080600 0x200>; + compatible = "adi,max32-gpio"; + gpio-controller; + #gpio-cells = <2>; + interrupts = <54 0>; + status = "disabled"; + }; +}; + +/ { + soc { + sram1: memory@20008000 { + compatible = "mmio-sram"; + reg = <0x20008000 DT_SIZE_K(32)>; + }; + + sram2: memory@20010000 { + compatible = "mmio-sram"; + reg = <0x20010000 DT_SIZE_K(48)>; + }; + + sram3: memory@2001c000 { + compatible = "mmio-sram"; + reg = <0x2001c000 DT_SIZE_K(16)>; + }; + + uart3: serial@40081400 { + compatible = "adi,max32-uart"; + reg = <0x40081400 0x1000>; + clocks = <&gcr ADI_MAX32_CLOCK_BUS2 4>; + clock-source = ; + interrupts = <88 0>; + status = "disabled"; + }; + }; +}; diff --git a/soc/adi/max32/Kconfig b/soc/adi/max32/Kconfig index 1be553aaead7f..9eb62daf6c38c 100644 --- a/soc/adi/max32/Kconfig +++ b/soc/adi/max32/Kconfig @@ -14,6 +14,9 @@ config SOC_FAMILY_MAX32 config SOC_MAX32655 select CPU_CORTEX_M4 +config SOC_MAX32680 + select CPU_CORTEX_M4 + config SOC_MAX32690 select CPU_CORTEX_M4 diff --git a/soc/adi/max32/Kconfig.defconfig.max32680 b/soc/adi/max32/Kconfig.defconfig.max32680 new file mode 100644 index 0000000000000..41e0674313de8 --- /dev/null +++ b/soc/adi/max32/Kconfig.defconfig.max32680 @@ -0,0 +1,14 @@ +# Analog Devices MAX32680 MCU + +# Copyright (c) 2024 Analog Devices, Inc. +# SPDX-License-Identifier: Apache-2.0 + +if SOC_MAX32680 + +config SYS_CLOCK_HW_CYCLES_PER_SEC + default $(dt_node_int_prop_int,/clocks/clk_ipo,clock-frequency) + +config NUM_IRQS + default 104 + +endif # SOC_MAX32680 diff --git a/soc/adi/max32/Kconfig.soc b/soc/adi/max32/Kconfig.soc index 1b373dfa2fed5..5d7baca5582fe 100644 --- a/soc/adi/max32/Kconfig.soc +++ b/soc/adi/max32/Kconfig.soc @@ -17,6 +17,14 @@ config SOC_MAX32655_M4 bool select SOC_MAX32655 +config SOC_MAX32680 + bool + select SOC_FAMILY_MAX32 + +config SOC_MAX32680_M4 + bool + select SOC_MAX32680 + config SOC_MAX32690 bool select SOC_FAMILY_MAX32 @@ -27,4 +35,5 @@ config SOC_MAX32690_M4 config SOC default "max32655" if SOC_MAX32655 + default "max32680" if SOC_MAX32680 default "max32690" if SOC_MAX32690 diff --git a/soc/adi/max32/soc.yml b/soc/adi/max32/soc.yml index 4f5bdbc4f89a1..5b2c70d086f97 100644 --- a/soc/adi/max32/soc.yml +++ b/soc/adi/max32/soc.yml @@ -7,6 +7,9 @@ family: - name: max32655 cpuclusters: - name: m4 + - name: max32680 + cpuclusters: + - name: m4 - name: max32690 cpuclusters: - name: m4 From 191b9ca0966bcf04ba49d9cca9ca2a1e86643295 Mon Sep 17 00:00:00 2001 From: Sadik Ozer Date: Tue, 16 Jan 2024 14:24:57 +0300 Subject: [PATCH 1765/2849] boards: Add MAX32680EVKit board Added MAX32680EVKit board For more information about this board please check https://www.analog.com/ Co-authored-by: Tahsin Mutlugun Signed-off-by: Sadik Ozer --- .../adi/max32680evkit/Kconfig.max32680evkit | 7 + boards/adi/max32680evkit/board.cmake | 7 + boards/adi/max32680evkit/board.yml | 8 + .../doc/img/max32680evkit_img1.jpg | Bin 0 -> 99637 bytes boards/adi/max32680evkit/doc/index.rst | 334 ++++++++++++++++++ .../max32680evkit_max32680_m4.dts | 80 +++++ .../max32680evkit_max32680_m4.yaml | 13 + .../max32680evkit_max32680_m4_defconfig | 13 + 8 files changed, 462 insertions(+) create mode 100644 boards/adi/max32680evkit/Kconfig.max32680evkit create mode 100644 boards/adi/max32680evkit/board.cmake create mode 100644 boards/adi/max32680evkit/board.yml create mode 100644 boards/adi/max32680evkit/doc/img/max32680evkit_img1.jpg create mode 100644 boards/adi/max32680evkit/doc/index.rst create mode 100644 boards/adi/max32680evkit/max32680evkit_max32680_m4.dts create mode 100644 boards/adi/max32680evkit/max32680evkit_max32680_m4.yaml create mode 100644 boards/adi/max32680evkit/max32680evkit_max32680_m4_defconfig diff --git a/boards/adi/max32680evkit/Kconfig.max32680evkit b/boards/adi/max32680evkit/Kconfig.max32680evkit new file mode 100644 index 0000000000000..ad5115590bd6b --- /dev/null +++ b/boards/adi/max32680evkit/Kconfig.max32680evkit @@ -0,0 +1,7 @@ +# MAX32680EVKIT boards configuration + +# Copyright (c) 2024 Analog Devices, Inc. +# SPDX-License-Identifier: Apache-2.0 + +config BOARD_MAX32680EVKIT + select SOC_MAX32680_M4 if BOARD_MAX32680EVKIT_MAX32680_M4 diff --git a/boards/adi/max32680evkit/board.cmake b/boards/adi/max32680evkit/board.cmake new file mode 100644 index 0000000000000..bd318bb200d32 --- /dev/null +++ b/boards/adi/max32680evkit/board.cmake @@ -0,0 +1,7 @@ +# Copyright (c) 2024 Analog Devices, Inc. +# SPDX-License-Identifier: Apache-2.0 + +board_runner_args(openocd --cmd-pre-init "source [find interface/cmsis-dap.cfg]") +board_runner_args(openocd --cmd-pre-init "source [find target/max32680.cfg]") + +include(${ZEPHYR_BASE}/boards/common/openocd.board.cmake) diff --git a/boards/adi/max32680evkit/board.yml b/boards/adi/max32680evkit/board.yml new file mode 100644 index 0000000000000..23b5102a97fdb --- /dev/null +++ b/boards/adi/max32680evkit/board.yml @@ -0,0 +1,8 @@ +# Copyright (c) 2024 Analog Devices, Inc. +# SPDX-License-Identifier: Apache-2.0 + +board: + name: max32680evkit + vendor: adi + socs: + - name: max32680 diff --git a/boards/adi/max32680evkit/doc/img/max32680evkit_img1.jpg b/boards/adi/max32680evkit/doc/img/max32680evkit_img1.jpg new file mode 100644 index 0000000000000000000000000000000000000000..c334dfe867ea73685f2cbf0d57f6f0d89658d984 GIT binary patch literal 99637 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 s7?XH?rxygt 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 z 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 + #include + #include + +/ { + model = "Analog Devices MAX32680EVKIT"; + compatible = "adi,max32680evkit"; + + chosen { + zephyr,console = &uart1; + zephyr,shell-uart = &uart1; + zephyr,sram = &sram2; + zephyr,flash = &flash0; + }; + + leds { + compatible = "gpio-leds"; + led1: led_1 { + gpios = <&gpio0 24 GPIO_ACTIVE_LOW>; + label = "Red LED"; + }; + led2: led_2 { + gpios = <&gpio0 25 GPIO_ACTIVE_LOW>; + label = "Blue LED"; + }; + }; + + buttons { + compatible = "gpio-keys"; + pb1: pb1 { + gpios = <&gpio0 26 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>; + label = "SW1"; + }; + pb2: pb2 { + gpios = <&gpio0 27 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>; + label = "SW2"; + }; + }; + + /* These aliases are provided for compatibility with samples */ + aliases { + led0 = &led1; + led1 = &led2; + sw0 = &pb1; + sw1 = &pb2; + }; +}; + +&uart1 { + pinctrl-0 = <&uart1a_tx_p0_13 &uart1a_rx_p0_12>; + pinctrl-names = "default"; + current-speed = <115200>; + data-bits = <8>; + parity = "none"; + status = "okay"; +}; + +&clk_ipo { + status = "okay"; +}; + +&gpio0 { + status = "okay"; +}; + +&gpio1 { + status = "okay"; +}; + +&gpio2 { + status = "okay"; +}; diff --git a/boards/adi/max32680evkit/max32680evkit_max32680_m4.yaml b/boards/adi/max32680evkit/max32680evkit_max32680_m4.yaml new file mode 100644 index 0000000000000..68e2baa65d733 --- /dev/null +++ b/boards/adi/max32680evkit/max32680evkit_max32680_m4.yaml @@ -0,0 +1,13 @@ +identifier: max32680evkit/max32680/m4 +name: max32680evkit m4 +type: mcu +arch: arm +toolchain: + - zephyr + - gnuarmemb + - xtools +supported: + - gpio + - serial +ram: 128 +flash: 512 diff --git a/boards/adi/max32680evkit/max32680evkit_max32680_m4_defconfig b/boards/adi/max32680evkit/max32680evkit_max32680_m4_defconfig new file mode 100644 index 0000000000000..a048ab2608ff0 --- /dev/null +++ b/boards/adi/max32680evkit/max32680evkit_max32680_m4_defconfig @@ -0,0 +1,13 @@ +# Copyright (c) 2024 Analog Devices, Inc. +# SPDX-License-Identifier: Apache-2.0 + +# Enable GPIO +CONFIG_GPIO=y + +# Console +CONFIG_CONSOLE=y +CONFIG_UART_CONSOLE=y + +# Enable UART +CONFIG_SERIAL=y +CONFIG_UART_INTERRUPT_DRIVEN=y From 859c733b016b4ed33bb7017a1efea11f77ac85dd Mon Sep 17 00:00:00 2001 From: Tahsin Mutlugun Date: Wed, 24 Jan 2024 11:38:30 +0300 Subject: [PATCH 1766/2849] tests: drivers: gpio: Enable gpio driver tests for MAX32680EVKIT Enable GPIO driver tests for MAX32680EVKIT. Signed-off-by: Tahsin Mutlugun --- .../boards/max32680evkit_max32680_m4.overlay | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 tests/drivers/gpio/gpio_basic_api/boards/max32680evkit_max32680_m4.overlay diff --git a/tests/drivers/gpio/gpio_basic_api/boards/max32680evkit_max32680_m4.overlay b/tests/drivers/gpio/gpio_basic_api/boards/max32680evkit_max32680_m4.overlay new file mode 100644 index 0000000000000..60a62c80bedac --- /dev/null +++ b/tests/drivers/gpio/gpio_basic_api/boards/max32680evkit_max32680_m4.overlay @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2024 Analog Devices, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + resources { + compatible = "test-gpio-basic-api"; + out-gpios = <&gpio2 6 0>; + in-gpios = <&gpio2 7 0>; + }; +}; From 8f5892a8304eeded579427c0cc231eb974cca8c4 Mon Sep 17 00:00:00 2001 From: Axel Le Bourhis Date: Thu, 16 May 2024 14:32:58 +0200 Subject: [PATCH 1767/2849] mcux: add Kconfig to configure NXP BLE monolithic feature The monolithic feature allows to link the binary blobs with the application during the build. Signed-off-by: Axel Le Bourhis Signed-off-by: Yassine El Aissaoui --- modules/Kconfig.mcux | 6 ++++++ west.yml | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/modules/Kconfig.mcux b/modules/Kconfig.mcux index 5d30250079fc6..4931c33568c52 100644 --- a/modules/Kconfig.mcux +++ b/modules/Kconfig.mcux @@ -375,6 +375,12 @@ config NXP_FW_LOADER The firmware loader is used to load firmwares to embedded tranceivers. It is needed to enable connectivity features. +config NXP_MONOLITHIC_BT + bool "BT firmware monolithic build" + help + If enabled, the BT firmware used by the device will be linked with the + application directly. + config NXP_RF_IMU bool "Include RF_IMU adapter for intercore messaging" select EVENTS diff --git a/west.yml b/west.yml index dad29b8d96156..3c16894fb60e4 100644 --- a/west.yml +++ b/west.yml @@ -198,7 +198,7 @@ manifest: groups: - hal - name: hal_nxp - revision: 5e84f1d2173e3c5057725d76f9dad6bfabad0b5f + revision: 88a7d079eed470ecc94010784931823a85ac3b39 path: modules/hal/nxp groups: - hal From ca53f5ee8e460832ba6ed198d42a36d275b91d95 Mon Sep 17 00:00:00 2001 From: Axel Le Bourhis Date: Thu, 16 May 2024 14:36:56 +0200 Subject: [PATCH 1768/2849] soc: rw6xx: Enable NXP_BLE_MONOLITHIC Enable monolithic build for all BLE apps. Signed-off-by: Axel Le Bourhis Signed-off-by: Yassine El Aissaoui --- soc/nxp/rw/CMakeLists.txt | 2 ++ soc/nxp/rw/Kconfig.defconfig | 3 +++ soc/nxp/rw/firmwares.ld | 10 ++++++++++ 3 files changed, 15 insertions(+) create mode 100644 soc/nxp/rw/firmwares.ld diff --git a/soc/nxp/rw/CMakeLists.txt b/soc/nxp/rw/CMakeLists.txt index 64b8bd4803ab0..b716ea5a21b30 100644 --- a/soc/nxp/rw/CMakeLists.txt +++ b/soc/nxp/rw/CMakeLists.txt @@ -18,4 +18,6 @@ set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/arm/cortex_m/scripts/li zephyr_include_directories(.) +zephyr_linker_sources(RODATA firmwares.ld) + zephyr_linker_sources(RAM_SECTIONS sections.ld) diff --git a/soc/nxp/rw/Kconfig.defconfig b/soc/nxp/rw/Kconfig.defconfig index 7f1ee72b9cf31..d00e99ed2619b 100644 --- a/soc/nxp/rw/Kconfig.defconfig +++ b/soc/nxp/rw/Kconfig.defconfig @@ -109,6 +109,9 @@ config HEAP_MEM_POOL_SIZE endif # BT +config NXP_MONOLITHIC_BT + default y if BT + config NXP_FW_LOADER default y if (BT || WIFI) diff --git a/soc/nxp/rw/firmwares.ld b/soc/nxp/rw/firmwares.ld new file mode 100644 index 0000000000000..428713251ca4e --- /dev/null +++ b/soc/nxp/rw/firmwares.ld @@ -0,0 +1,10 @@ +/* + * Copyright 2024 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#if defined(CONFIG_NXP_MONOLITHIC_BT) +. = ALIGN(4); +KEEP(*(.fw_cpu2_ble)) +#endif From bb6669418a0e7500e30678be4e86ca0d49cd57c5 Mon Sep 17 00:00:00 2001 From: Axel Le Bourhis Date: Thu, 16 May 2024 14:40:39 +0200 Subject: [PATCH 1769/2849] boards: rd_rw612_bga: flash size with monolithic feature When building with monolithic feature enabled, the firmwares binaries will be linked during the build with the application. This means we can remove the application size limit due to the firmware storage in flash not useful anymore. Signed-off-by: Axel Le Bourhis Signed-off-by: Yassine El Aissaoui --- boards/nxp/rd_rw612_bga/Kconfig.defconfig | 3 +++ 1 file changed, 3 insertions(+) diff --git a/boards/nxp/rd_rw612_bga/Kconfig.defconfig b/boards/nxp/rd_rw612_bga/Kconfig.defconfig index 376f96da2b332..88123b618997e 100644 --- a/boards/nxp/rd_rw612_bga/Kconfig.defconfig +++ b/boards/nxp/rd_rw612_bga/Kconfig.defconfig @@ -5,6 +5,9 @@ if BOARD_RD_RW612_BGA +config FLASH_LOAD_SIZE + default 0x400000 if !BOOTLOADER_MCUBOOT && !NXP_MONOLITHIC_BT + if LVGL # Enable DMA for LCDIC From ffa3f168ece53a600a3ea22b2e6defa32e11fd1f Mon Sep 17 00:00:00 2001 From: Yassine El Aissaoui Date: Mon, 27 May 2024 18:04:03 +0200 Subject: [PATCH 1770/2849] samples: tests: Create dedicated test section for rd_rw612_bga Monolithic build is enabled by default and it requires the presence of the binary blobs. CI will fail since it doesn't fetch them to the environment. To avoid this monolithic for BT app is disabled. Signed-off-by: Yassine El Aissaoui --- samples/bluetooth/central_ht/sample.yaml | 7 ++++++- samples/bluetooth/peripheral_ht/sample.yaml | 9 +++++++-- tests/bluetooth/tester/testcase.yaml | 9 ++++++++- 3 files changed, 21 insertions(+), 4 deletions(-) diff --git a/samples/bluetooth/central_ht/sample.yaml b/samples/bluetooth/central_ht/sample.yaml index f59d207a59fed..c598e33112cee 100644 --- a/samples/bluetooth/central_ht/sample.yaml +++ b/samples/bluetooth/central_ht/sample.yaml @@ -8,8 +8,13 @@ tests: - qemu_x86 - nrf51dk/nrf51822 - nrf52dk/nrf52832 - - rd_rw612_bga tags: bluetooth integration_platforms: - qemu_cortex_m3 + sample.bluetooth.central_ht.nxp: + # Disabling monolithic since CI environment doesn't use blobs + harness: bluetooth + platform_allow: - rd_rw612_bga + extra_configs: + - CONFIG_NXP_MONOLITHIC_BT=n diff --git a/samples/bluetooth/peripheral_ht/sample.yaml b/samples/bluetooth/peripheral_ht/sample.yaml index 4243914b57178..a87129f16627c 100644 --- a/samples/bluetooth/peripheral_ht/sample.yaml +++ b/samples/bluetooth/peripheral_ht/sample.yaml @@ -9,11 +9,9 @@ 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: @@ -25,3 +23,10 @@ tests: extra_args: SHIELD=frdm_kw41z integration_platforms: - mimxrt1020_evk + sample.bluetooth.peripheral_ht.nxp: + # Disabling monolithic since CI environment doesn't use blobs + harness: bluetooth + platform_allow: + - rd_rw612_bga + extra_configs: + - CONFIG_NXP_MONOLITHIC_BT=n diff --git a/tests/bluetooth/tester/testcase.yaml b/tests/bluetooth/tester/testcase.yaml index 43fa984a2ced9..8a8cb41b1b7ff 100644 --- a/tests/bluetooth/tester/testcase.yaml +++ b/tests/bluetooth/tester/testcase.yaml @@ -6,9 +6,16 @@ tests: - native_posix - native_sim - nrf52840dk/nrf52840 - - rd_rw612_bga tags: bluetooth harness: bluetooth + bluetooth.general.tester.nxp: + # Disabling monolithic since CI environment doesn't use blobs + build_only: true + harness: bluetooth + platform_allow: + - rd_rw612_bga + extra_configs: + - CONFIG_NXP_MONOLITHIC_BT=n bluetooth.general.tester_le_audio: build_only: true platform_allow: From cb85932488fd30e8de81d5a2ac427da80e342a1c Mon Sep 17 00:00:00 2001 From: Yassine El Aissaoui Date: Wed, 29 May 2024 18:01:47 +0200 Subject: [PATCH 1771/2849] boards: rd_rw612_bga: Update board documentation Add information about BLE. Signed-off-by: Yassine El Aissaoui --- boards/nxp/rd_rw612_bga/doc/index.rst | 32 +++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/boards/nxp/rd_rw612_bga/doc/index.rst b/boards/nxp/rd_rw612_bga/doc/index.rst index 42783abb9bbd8..233f8f691bb4e 100644 --- a/boards/nxp/rd_rw612_bga/doc/index.rst +++ b/boards/nxp/rd_rw612_bga/doc/index.rst @@ -66,6 +66,8 @@ Supported Features | PM | on-chip | power management; uses SoC Power | | | | Modes 1 and 2 | +-----------+------------+-----------------------------------+ +| BLE | on-chip | Bluetooth | ++-----------+------------+-----------------------------------+ The default configuration can be found in the defconfig file: @@ -73,6 +75,16 @@ The default configuration can be found in the defconfig file: Other hardware features are not currently supported +Fetch Binary Blobs +****************** + +To support Bluetooth, rd_rw612_bga requires fetching binary blobs, which can be +achieved by running the following command: + +.. code-block:: console + + west blobs fetch hal_nxp + Programming and Debugging ************************* @@ -134,6 +146,26 @@ should see the following message in the terminal: ***** Booting Zephyr OS zephyr-v3.6.0 ***** Hello World! rd_rw612_bga +Bluetooth +========= + +BLE functionality requires to fetch binary blobs, so make sure to follow +the ``Fetch Binary Blobs`` section first. + +Those binary blobs can be used in two different ways, depending if :kconfig:option:`CONFIG_NXP_MONOLITHIC_BT` +is enabled or not: + +- :kconfig:option:`CONFIG_NXP_MONOLITHIC_BT` is enabled (default): + +The required binary blob will be linked with the application image directly, forming +one single monolithic image. +The user has nothing else to do other than flashing the application to the board. + +- :kconfig:option:`CONFIG_NXP_MONOLITHIC_BT` is disabled: + +In this case, the BLE blob won't be linked with the application, so the user needs to manually +flash the BLE binary blob to the board at the address ``0x18540000``. +The binary blob will be located here: ``/modules/hal/nxp/zephyr/blobs/rw61x/rw61x_sb_ble_a2.bin`` Resources ========= From e01f422b02e69708b7dd1da010d266c23d852257 Mon Sep 17 00:00:00 2001 From: Sven Depoorter Date: Mon, 27 May 2024 16:07:28 +0200 Subject: [PATCH 1772/2849] drivers: display: ssd16xx: implement display_set_orientation API I chose this approach instead of software rotation because I need it for an ultra low power project. Rotation in steps of 0, 90, 180, 270 degrees is done by changing the data entry modes. This commit removes the orientation-flipped property as it is redundant. I made the assumption that the current driver implementation is right about controller X/Y versus display width/height. The display controller X parameter matches with the display height (dts) and display controller Y parameter matches with the display width (dts). It looks like display manufacturers choose to have it like this because a wider screen probably makes more sense. Tested on the reel_board with a 250x122 display (ssd1673 controller) and a custom PCB with a 200x200 display (ssd1681 controller). Also tested all orientations with various width/height dts overrides. Signed-off-by: Sven Depoorter --- drivers/display/ssd16xx.c | 149 +++++++++++++----- .../display/solomon,ssd16xx-common.yaml | 16 +- 2 files changed, 124 insertions(+), 41 deletions(-) diff --git a/drivers/display/ssd16xx.c b/drivers/display/ssd16xx.c index 53da2c33f4050..24cc580c8a090 100644 --- a/drivers/display/ssd16xx.c +++ b/drivers/display/ssd16xx.c @@ -66,6 +66,7 @@ struct ssd16xx_data { uint8_t scan_mode; bool blanking_on; enum ssd16xx_profile_type profile; + enum display_orientation orientation; }; struct ssd16xx_dt_array { @@ -100,7 +101,7 @@ struct ssd16xx_config { const struct ssd16xx_profile *profiles[SSD16XX_NUM_PROFILES]; - bool orientation; + uint16_t rotation; uint16_t height; uint16_t width; uint8_t tssv; @@ -380,42 +381,73 @@ static int ssd16xx_set_window(const struct device *dev, return -ENOTSUP; } - if ((y + desc->height) > panel_h) { - LOG_ERR("Buffer out of bounds (height)"); - return -EINVAL; - } + if (data->orientation == DISPLAY_ORIENTATION_NORMAL || + data->orientation == DISPLAY_ORIENTATION_ROTATED_180) { + if ((y + desc->height) > panel_h) { + LOG_ERR("Buffer out of bounds (height)"); + return -EINVAL; + } - if ((x + desc->width) > config->width) { - LOG_ERR("Buffer out of bounds (width)"); - return -EINVAL; - } + if ((x + desc->width) > config->width) { + LOG_ERR("Buffer out of bounds (width)"); + return -EINVAL; + } - if ((desc->height % EPD_PANEL_NUMOF_ROWS_PER_PAGE) != 0U) { - LOG_ERR("Buffer height not multiple of %d", - EPD_PANEL_NUMOF_ROWS_PER_PAGE); - return -EINVAL; - } + if ((desc->height % EPD_PANEL_NUMOF_ROWS_PER_PAGE) != 0U) { + LOG_ERR("Buffer height not multiple of %d", EPD_PANEL_NUMOF_ROWS_PER_PAGE); + return -EINVAL; + } - if ((y % EPD_PANEL_NUMOF_ROWS_PER_PAGE) != 0U) { - LOG_ERR("Y coordinate not multiple of %d", - EPD_PANEL_NUMOF_ROWS_PER_PAGE); - return -EINVAL; + if ((y % EPD_PANEL_NUMOF_ROWS_PER_PAGE) != 0U) { + LOG_ERR("Y coordinate not multiple of %d", EPD_PANEL_NUMOF_ROWS_PER_PAGE); + return -EINVAL; + } + } else { + if ((y + desc->height) > config->width) { + LOG_ERR("Buffer out of bounds (height)"); + return -EINVAL; + } + + if ((x + desc->width) > panel_h) { + LOG_ERR("Buffer out of bounds (width)"); + return -EINVAL; + } + + if ((desc->width % SSD16XX_PIXELS_PER_BYTE) != 0U) { + LOG_ERR("Buffer width not multiple of %d", SSD16XX_PIXELS_PER_BYTE); + return -EINVAL; + } + + if ((x % SSD16XX_PIXELS_PER_BYTE) != 0U) { + LOG_ERR("X coordinate not multiple of %d", SSD16XX_PIXELS_PER_BYTE); + return -EINVAL; + } } - switch (data->scan_mode) { - case SSD16XX_DATA_ENTRY_XIYDY: + switch (data->orientation) { + case DISPLAY_ORIENTATION_NORMAL: + x_start = (panel_h - 1 - y) / SSD16XX_PIXELS_PER_BYTE; + x_end = (panel_h - 1 - (y + desc->height - 1)) / SSD16XX_PIXELS_PER_BYTE; + y_start = x; + y_end = (x + desc->width - 1); + break; + case DISPLAY_ORIENTATION_ROTATED_90: + x_start = (panel_h - 1 - x) / SSD16XX_PIXELS_PER_BYTE; + x_end = (panel_h - 1 - (x + desc->width - 1)) / SSD16XX_PIXELS_PER_BYTE; + y_start = (config->width - 1 - y); + y_end = (config->width - 1 - (y + desc->height - 1)); + break; + case DISPLAY_ORIENTATION_ROTATED_180: x_start = y / SSD16XX_PIXELS_PER_BYTE; x_end = (y + desc->height - 1) / SSD16XX_PIXELS_PER_BYTE; y_start = (x + desc->width - 1); y_end = x; break; - - case SSD16XX_DATA_ENTRY_XDYIY: - x_start = (panel_h - 1 - y) / SSD16XX_PIXELS_PER_BYTE; - x_end = (panel_h - 1 - (y + desc->height - 1)) / - SSD16XX_PIXELS_PER_BYTE; - y_start = x; - y_end = (x + desc->width - 1); + case DISPLAY_ORIENTATION_ROTATED_270: + x_start = x / SSD16XX_PIXELS_PER_BYTE; + x_end = (x + desc->width - 1) / SSD16XX_PIXELS_PER_BYTE; + y_start = y; + y_end = (y + desc->height - 1); break; default: return -EINVAL; @@ -585,6 +617,7 @@ static void ssd16xx_get_capabilities(const struct device *dev, struct display_capabilities *caps) { const struct ssd16xx_config *config = dev->config; + struct ssd16xx_data *data = dev->data; memset(caps, 0, sizeof(struct display_capabilities)); caps->x_resolution = config->width; @@ -592,9 +625,14 @@ static void ssd16xx_get_capabilities(const struct device *dev, config->height % EPD_PANEL_NUMOF_ROWS_PER_PAGE; caps->supported_pixel_formats = PIXEL_FORMAT_MONO10; caps->current_pixel_format = PIXEL_FORMAT_MONO10; - caps->screen_info = SCREEN_INFO_MONO_VTILED | - SCREEN_INFO_MONO_MSB_FIRST | - SCREEN_INFO_EPD; + caps->screen_info = SCREEN_INFO_MONO_MSB_FIRST | SCREEN_INFO_EPD; + + if (data->orientation == DISPLAY_ORIENTATION_NORMAL || + data->orientation == DISPLAY_ORIENTATION_ROTATED_180) { + caps->screen_info |= SCREEN_INFO_MONO_VTILED; + } + + caps->current_orientation = data->orientation; } static int ssd16xx_set_pixel_format(const struct device *dev, @@ -608,6 +646,32 @@ static int ssd16xx_set_pixel_format(const struct device *dev, return -ENOTSUP; } +static int ssd16xx_set_orientation(const struct device *dev, + const enum display_orientation orientation) +{ + struct ssd16xx_data *data = dev->data; + int err; + + if (orientation == DISPLAY_ORIENTATION_NORMAL) { + data->scan_mode = SSD16XX_DATA_ENTRY_XDYIY; + } else if (orientation == DISPLAY_ORIENTATION_ROTATED_90) { + data->scan_mode = SSD16XX_DATA_ENTRY_XDYDX; + } else if (orientation == DISPLAY_ORIENTATION_ROTATED_180) { + data->scan_mode = SSD16XX_DATA_ENTRY_XIYDY; + } else if (orientation == DISPLAY_ORIENTATION_ROTATED_270) { + data->scan_mode = SSD16XX_DATA_ENTRY_XIYIX; + } + + err = ssd16xx_write_uint8(dev, SSD16XX_CMD_ENTRY_MODE, data->scan_mode); + if (err < 0) { + return err; + } + + data->orientation = orientation; + + return 0; +} + static int ssd16xx_clear_cntlr_mem(const struct device *dev, uint8_t ram_cmd) { const struct ssd16xx_config *config = dev->config; @@ -840,6 +904,7 @@ static int ssd16xx_controller_init(const struct device *dev) { const struct ssd16xx_config *config = dev->config; struct ssd16xx_data *data = dev->data; + enum display_orientation orientation; int err; LOG_DBG(""); @@ -860,12 +925,6 @@ static int ssd16xx_controller_init(const struct device *dev) k_msleep(SSD16XX_RESET_DELAY); - if (config->orientation == 1) { - data->scan_mode = SSD16XX_DATA_ENTRY_XIYDY; - } else { - data->scan_mode = SSD16XX_DATA_ENTRY_XDYIY; - } - err = ssd16xx_set_profile(dev, SSD16XX_PROFILE_FULL); if (err < 0) { return err; @@ -881,6 +940,21 @@ static int ssd16xx_controller_init(const struct device *dev) return err; } + if (config->rotation == 0U) { + orientation = DISPLAY_ORIENTATION_NORMAL; + } else if (config->rotation == 90U) { + orientation = DISPLAY_ORIENTATION_ROTATED_90; + } else if (config->rotation == 180U) { + orientation = DISPLAY_ORIENTATION_ROTATED_180; + } else { + orientation = DISPLAY_ORIENTATION_ROTATED_270; + } + + err = ssd16xx_set_orientation(dev, orientation); + if (err < 0) { + return err; + } + err = ssd16xx_update_display(dev); if (err < 0) { return err; @@ -954,6 +1028,7 @@ static struct display_driver_api ssd16xx_driver_api = { .read = ssd16xx_read, .get_capabilities = ssd16xx_get_capabilities, .set_pixel_format = ssd16xx_set_pixel_format, + .set_orientation = ssd16xx_set_orientation, }; #if DT_HAS_COMPAT_STATUS_OKAY(solomon_ssd1608) @@ -1070,7 +1145,7 @@ static struct ssd16xx_quirks quirks_solomon_ssd1681 = { .quirks = quirks_ptr, \ .height = DT_PROP(n, height), \ .width = DT_PROP(n, width), \ - .orientation = DT_PROP(n, orientation_flipped), \ + .rotation = DT_PROP(n, rotation), \ .tssv = DT_PROP_OR(n, tssv, 0), \ .softstart = SSD16XX_ASSIGN_ARRAY(n, softstart), \ .profiles = { \ diff --git a/dts/bindings/display/solomon,ssd16xx-common.yaml b/dts/bindings/display/solomon,ssd16xx-common.yaml index dd5b651e8feaf..34911dbc18b57 100644 --- a/dts/bindings/display/solomon,ssd16xx-common.yaml +++ b/dts/bindings/display/solomon,ssd16xx-common.yaml @@ -10,10 +10,6 @@ properties: type: uint8-array description: Booster soft start values - orientation-flipped: - type: boolean - description: Last column address is mapped to first segment - reset-gpios: type: phandle-array required: true @@ -49,6 +45,18 @@ properties: an external temperature sensor is connected to the controller. The value selects which sensor should be used. + rotation: + type: int + default: 0 + enum: + - 0 + - 90 + - 180 + - 270 + description: + Display rotation (CW) in degrees. + If not defined, rotation is off by default. + child-binding: description: | Child nodes describe refresh profiles. Each refresh profile From dda604c96f33ea88f552cc960c18299db837396d Mon Sep 17 00:00:00 2001 From: Sven Depoorter Date: Mon, 27 May 2024 16:25:42 +0200 Subject: [PATCH 1773/2849] drivers: display: ssd16xx: performance improvement The driver writes the scan entry mode to the display controller on each set_window call. Multiple calls to set_window can be needed to update a single frame buffer in the controller. There's a performance improvement by only setting the scan mode when the orientation is changed (set_orientation, see previous commit) and when the profile has changed. For the latter the scan_mode is lost on the controller due to a software reset. Signed-off-by: Sven Depoorter --- drivers/display/ssd16xx.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/drivers/display/ssd16xx.c b/drivers/display/ssd16xx.c index 24cc580c8a090..aa87b079a7175 100644 --- a/drivers/display/ssd16xx.c +++ b/drivers/display/ssd16xx.c @@ -453,12 +453,6 @@ static int ssd16xx_set_window(const struct device *dev, return -EINVAL; } - err = ssd16xx_write_cmd(dev, SSD16XX_CMD_ENTRY_MODE, - &data->scan_mode, sizeof(data->scan_mode)); - if (err < 0) { - return err; - } - err = ssd16xx_set_ram_param(dev, x_start, x_end, y_start, y_end); if (err < 0) { return err; @@ -895,6 +889,11 @@ static int ssd16xx_set_profile(const struct device *dev, } } + err = ssd16xx_write_uint8(dev, SSD16XX_CMD_ENTRY_MODE, data->scan_mode); + if (err < 0) { + return err; + } + data->profile = type; return 0; From cabeaf143613a2dba6b8616754d8394dfee20a62 Mon Sep 17 00:00:00 2001 From: Sven Depoorter Date: Wed, 29 May 2024 16:19:42 +0200 Subject: [PATCH 1774/2849] drivers: display: ili9xxx: add justification for default rotation To align with udpated ssd16xx bindings. Signed-off-by: Sven Depoorter --- dts/bindings/display/ilitek,ili9xxx-common.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/dts/bindings/display/ilitek,ili9xxx-common.yaml b/dts/bindings/display/ilitek,ili9xxx-common.yaml index 802250002d604..6a657399140e6 100644 --- a/dts/bindings/display/ilitek,ili9xxx-common.yaml +++ b/dts/bindings/display/ilitek,ili9xxx-common.yaml @@ -28,6 +28,7 @@ properties: - 270 description: Display rotation (CW) in degrees. + If not defined, rotation is off by default. display-inversion: type: boolean From 9751f78ce5ed42ef8feaba7ce2c9482131c2b2c7 Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Thu, 23 May 2024 10:43:08 -0700 Subject: [PATCH 1775/2849] doc: security-overview: Update cryptographic information Zephyr's transition to PSA Crypto API and demoting TinyCrypt. Lets not promote TinyCrypt in the overview. Signed-off-by: Flavio Ceolin --- doc/security/security-overview.rst | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/doc/security/security-overview.rst b/doc/security/security-overview.rst index 6ed15fa55ba89..53c956cbe53b5 100644 --- a/doc/security/security-overview.rst +++ b/doc/security/security-overview.rst @@ -122,14 +122,12 @@ Security Functionality The security functionality in Zephyr hinges mainly on the inclusion of cryptographic algorithms, and on its monolithic system design. -The cryptographic features are provided through a set of cryptographic -libraries. Applications can choose TinyCrypt2 or Mbed TLS based on their -needs. TinyCrypt2 supports key cryptographic algorithms required by the -connectivity stacks. TinyCrypt2, however, only provides a limited set of -algorithms. Mbed TLS supports a wider range of algorithms, but at the -cost of additional requirements such as malloc support. Applications can -choose the solution that matches their individual requirements. Future -work may include APIs to abstract the underlying crypto library choice. +The cryptographic features are provided through PSA Crypto, with +mbedTLS as the underlying implementation. Applications leverage PSA +Crypto APIs, ensuring a standardized and secure approach to +cryptographic operations. mbedTLS, as the implementation of PSA +Crypto, supports a wide range of cryptographic algorithms, making it +suitable for various application requirements. APIs for vendor specific cryptographic IPs in both hardware and software are planned, including secure key storage in the form of secure access From c1bcf3c72ff6530debd3041dd0def6e65973281d Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Thu, 23 May 2024 10:50:06 -0700 Subject: [PATCH 1776/2849] doc: crypto: Remove TinyCrypt from documentation TinyCrypt is being removed from Zephyr in favor of PSA Crypto. Signed-off-by: Flavio Ceolin --- doc/services/crypto/index.rst | 1 - doc/services/crypto/tinycrypt.rst | 325 ------------------------------ 2 files changed, 326 deletions(-) delete mode 100644 doc/services/crypto/tinycrypt.rst diff --git a/doc/services/crypto/index.rst b/doc/services/crypto/index.rst index 988366c2e62f9..652d209feb8b7 100644 --- a/doc/services/crypto/index.rst +++ b/doc/services/crypto/index.rst @@ -13,6 +13,5 @@ The following crypto libraries have been included: .. toctree:: :maxdepth: 1 - tinycrypt.rst random/index.rst api/index.rst diff --git a/doc/services/crypto/tinycrypt.rst b/doc/services/crypto/tinycrypt.rst deleted file mode 100644 index 1757ac350e7f5..0000000000000 --- a/doc/services/crypto/tinycrypt.rst +++ /dev/null @@ -1,325 +0,0 @@ -.. _tinycrypt: - -TinyCrypt Cryptographic Library -############################### - -Overview -******** -The TinyCrypt Library provides an implementation for targeting constrained devices -with a minimal set of standard cryptography primitives, as listed below. To better -serve applications targeting constrained devices, TinyCrypt implementations differ -from the standard specifications (see the Important Remarks section for some -important differences). Certain cryptographic primitives depend on other -primitives, as mentioned in the list below. - -Aside from the Important Remarks section below, valuable information on the usage, -security and technicalities of each cryptographic primitive are found in the -corresponding header file. - -* SHA-256: - - * Type of primitive: Hash function. - * Standard Specification: NIST FIPS PUB 180-4. - * Requires: -- - -* HMAC-SHA256: - - * Type of primitive: Message authentication code. - * Standard Specification: RFC 2104. - * Requires: SHA-256 - -* HMAC-PRNG: - - * Type of primitive: Pseudo-random number generator. - * Standard Specification: NIST SP 800-90A. - * Requires: SHA-256 and HMAC-SHA256. - -* AES-128: - - * Type of primitive: Block cipher. - * Standard Specification: NIST FIPS PUB 197. - * Requires: -- - -* AES-CBC mode: - - * Type of primitive: Encryption mode of operation. - * Standard Specification: NIST SP 800-38A. - * Requires: AES-128. - -* AES-CTR mode: - - * Type of primitive: Encryption mode of operation. - * Standard Specification: NIST SP 800-38A. - * Requires: AES-128. - -* AES-CMAC mode: - - * Type of primitive: Message authentication code. - * Standard Specification: NIST SP 800-38B. - * Requires: AES-128. - -* AES-CCM mode: - - * Type of primitive: Authenticated encryption. - * Standard Specification: NIST SP 800-38C. - * Requires: AES-128. - -* ECC-DH: - - * Type of primitive: Key exchange. - * Standard Specification: RFC 6090. - * Requires: ECC auxiliary functions (ecc.h/c). - -* ECC-DSA: - - * Type of primitive: Digital signature. - * Standard Specification: RFC 6090. - * Requires: ECC auxiliary functions (ecc.h/c). - -Design Goals -************ - -* Minimize the code size of each cryptographic primitive. This means minimize - the size of a board-independent implementation, as presented in TinyCrypt. - Note that various applications may require further features, optimizations with - respect to other metrics and countermeasures for particular threats. These - peculiarities would increase the code size and thus are not considered here. - -* Minimize the dependencies among the cryptographic primitives. This means - that it is unnecessary to build and allocate object code for more primitives - than the ones strictly required by the intended application. In other words, - one can select and compile only the primitives required by the application. - - -Important Remarks -***************** - -The cryptographic implementations in TinyCrypt library have some limitations. -Some of these limitations are inherent to the cryptographic primitives -themselves, while others are specific to TinyCrypt. Some of these limitations -are discussed in-depth below. - -General Remarks -*************** - -* TinyCrypt does **not** intend to be fully side-channel resistant. Due to the - variety of side-channel attacks, many of them making certain boards - vulnerable. In this sense, instead of penalizing all library users with - side-channel countermeasures such as increasing the overall code size, - TinyCrypt only implements certain generic timing-attack countermeasures. - -Specific Remarks -**************** - -* SHA-256: - - * The number of bits_hashed in the state is not checked for overflow. Note - however that this will only be a problem if you intend to hash more than - 2^64 bits, which is an extremely large window. - -* HMAC: - - * The HMAC verification process is assumed to be performed by the application. - This compares the computed tag with some given tag. - Note that conventional memory-comparison methods (such as memcmp function) - might be vulnerable to timing attacks; thus be sure to use a constant-time - memory comparison function (such as compare_constant_time - function provided in lib/utils.c). - -* HMAC-PRNG: - - * Before using HMAC-PRNG, you *must* find an entropy source to produce a seed. - PRNGs only stretch the seed into a seemingly random output of arbitrary - length. The security of the output is exactly equal to the - unpredictability of the seed. - - * NIST SP 800-90A requires three items as seed material in the initialization - step: entropy seed, personalization and a nonce (which is not implemented). - TinyCrypt requires the personalization byte array and automatically creates - the entropy seed using a mandatory call to the re-seed function. - -* AES-128: - - * The current implementation does not support other key-lengths (such as 256 - bits). Note that if you need AES-256, it doesn't sound as though your - application is running in a constrained environment. AES-256 requires keys - twice the size as for AES-128, and the key schedule is 40% larger. - -* CTR mode: - - * The AES-CTR mode limits the size of a data message they encrypt to 2^32 - blocks. If you need to encrypt larger data sets, your application would - need to replace the key after 2^32 block encryptions. - -* CBC mode: - - * TinyCrypt CBC decryption assumes that the iv and the ciphertext are - contiguous (as produced by TinyCrypt CBC encryption). This allows for a - very efficient decryption algorithm that would not otherwise be possible. - -* CMAC mode: - - * AES128-CMAC mode of operation offers 64 bits of security against collision - attacks. Note however that an external attacker cannot generate the tags - him/herself without knowing the MAC key. In this sense, to attack the - collision property of AES128-CMAC, an external attacker would need the - cooperation of the legal user to produce an exponentially high number of - tags (e.g. 2^64) to finally be able to look for collisions and benefit - from them. As an extra precaution, the current implementation allows to at - most 2^48 calls to tc_cmac_update function before re-calling tc_cmac_setup - (allowing a new key to be set), as suggested in Appendix B of SP 800-38B. - -* CCM mode: - - * There are a few tradeoffs for the selection of the parameters of CCM mode. - In special, there is a tradeoff between the maximum number of invocations - of CCM under a given key and the maximum payload length for those - invocations. Both things are related to the parameter 'q' of CCM mode. The - maximum number of invocations of CCM under a given key is determined by - the nonce size, which is: 15-q bytes. The maximum payload length for those - invocations is defined as 2^(8q) bytes. - - To achieve minimal code size, TinyCrypt CCM implementation fixes q = 2, - which is a quite reasonable choice for constrained applications. The - implications of this choice are: - - The nonce size is: 13 bytes. - - The maximum payload length is: 2^16 bytes = 65 KB. - - The mac size parameter is an important parameter to estimate the security - against collision attacks (that aim at finding different messages that - produce the same authentication tag). TinyCrypt CCM implementation - accepts any even integer between 4 and 16, as suggested in SP 800-38C. - - * TinyCrypt CCM implementation accepts associated data of any length between - 0 and (2^16 - 2^8) = 65280 bytes. - - * TinyCrypt CCM implementation accepts: - - * Both non-empty payload and associated data (it encrypts and - authenticates the payload and only authenticates the associated data); - - * Non-empty payload and empty associated data (it encrypts and - authenticates the payload); - - * Non-empty associated data and empty payload (it degenerates to an - authentication-only mode on the associated data). - - * RFC-3610, which also specifies CCM, presents a few relevant security - suggestions, such as: it is recommended for most applications to use a - mac size greater than 8. Besides, it is emphasized that the usage of the - same nonce for two different messages which are encrypted with the same - key obviously destroys the security properties of CCM mode. - -* ECC-DH and ECC-DSA: - - * TinyCrypt ECC implementation is based on nano-ecc (see - https://github.com/iSECPartners/nano-ecc) which in turn is based on - micro-ecc (see https://github.com/kmackay/micro-ecc). In the original - nano and micro-ecc documentation, there is an important remark about the - way integers are represented: - - "Integer representation: To reduce code size, all large integers are - represented using little-endian words - so the least significant word is - first. You can use the 'ecc_bytes2native()' and 'ecc_native2bytes()' - functions to convert between the native integer representation and the - standardized octet representation." - -Examples of Applications -************************ -It is possible to do useful cryptography with only the given small set of -primitives. With this list of primitives it becomes feasible to support a range -of cryptography usages: - - * Measurement of code, data structures, and other digital artifacts (SHA256); - - * Generate commitments (SHA256); - - * Construct keys (HMAC-SHA256); - - * Extract entropy from strings containing some randomness (HMAC-SHA256); - - * Construct random mappings (HMAC-SHA256); - - * Construct nonces and challenges (HMAC-PRNG); - - * Authenticate using a shared secret (HMAC-SHA256); - - * Create an authenticated, replay-protected session (HMAC-SHA256 + HMAC-PRNG); - - * Authenticated encryption (AES-128 + AES-CCM); - - * Key-exchange (EC-DH); - - * Digital signature (EC-DSA); - -Test Vectors -************ - -The library provides a test program for each cryptographic primitive (see 'test' -folder). Besides illustrating how to use the primitives, these tests evaluate -the correctness of the implementations by checking the results against -well-known publicly validated test vectors. - -For the case of the HMAC-PRNG, due to the necessity of performing an extensive -battery test to produce meaningful conclusions, we suggest the user to evaluate -the unpredictability of the implementation by using the NIST Statistical Test -Suite (see References). - -For the case of the EC-DH and EC-DSA implementations, most of the test vectors -were obtained from the site of the NIST Cryptographic Algorithm Validation -Program (CAVP), see References. - -References -********** - -* `NIST FIPS PUB 180-4 (SHA-256)`_ - -.. _NIST FIPS PUB 180-4 (SHA-256): - http://csrc.nist.gov/publications/fips/fips180-4/fips-180-4.pdf - -* `NIST FIPS PUB 197 (AES-128)`_ - -.. _NIST FIPS PUB 197 (AES-128): - http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf - -* `NIST SP800-90A (HMAC-PRNG)`_ - -.. _NIST SP800-90A (HMAC-PRNG): - http://csrc.nist.gov/publications/nistpubs/800-90A/SP800-90A.pdf - -* `NIST SP 800-38A (AES-CBC and AES-CTR)`_ - -.. _NIST SP 800-38A (AES-CBC and AES-CTR): - http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf - -* `NIST SP 800-38B (AES-CMAC)`_ - -.. _NIST SP 800-38B (AES-CMAC): - http://csrc.nist.gov/publications/nistpubs/800-38B/SP_800-38B.pdf - -* `NIST SP 800-38C (AES-CCM)`_ - -.. _NIST SP 800-38C (AES-CCM): - http://csrc.nist.gov/publications/nistpubs/800-38C/SP800-38C_updated-July20_2007.pdf - -* `NIST Statistical Test Suite`_ - -.. _NIST Statistical Test Suite: - http://csrc.nist.gov/groups/ST/toolkit/rng/documentation_software.html - -* `NIST Cryptographic Algorithm Validation Program (CAVP) site`_ - -.. _NIST Cryptographic Algorithm Validation Program (CAVP) site: - http://csrc.nist.gov/groups/STM/cavp/ - -* `RFC 2104 (HMAC-SHA256)`_ - -.. _RFC 2104 (HMAC-SHA256): - https://www.ietf.org/rfc/rfc2104.txt - -* `RFC 6090 (ECC-DH and ECC-DSA)`_ - -.. _RFC 6090 (ECC-DH and ECC-DSA): - https://www.ietf.org/rfc/rfc6090.txt From 1a6bdb2e3e3c29c2effb5704cf50d4fb53068f2f Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Thu, 23 May 2024 12:34:19 -0700 Subject: [PATCH 1777/2849] doc: crypto: Add PSA Crypto documentation Add PSA Crypto in the cryptographic services section. Signed-off-by: Flavio Ceolin --- doc/services/crypto/index.rst | 1 + doc/services/crypto/psa_crypto.rst | 181 +++++++++++++++++++++++++++++ 2 files changed, 182 insertions(+) create mode 100644 doc/services/crypto/psa_crypto.rst diff --git a/doc/services/crypto/index.rst b/doc/services/crypto/index.rst index 652d209feb8b7..2ac0f534208c1 100644 --- a/doc/services/crypto/index.rst +++ b/doc/services/crypto/index.rst @@ -13,5 +13,6 @@ The following crypto libraries have been included: .. toctree:: :maxdepth: 1 + psa_crypto.rst random/index.rst api/index.rst diff --git a/doc/services/crypto/psa_crypto.rst b/doc/services/crypto/psa_crypto.rst new file mode 100644 index 0000000000000..fe5360e996718 --- /dev/null +++ b/doc/services/crypto/psa_crypto.rst @@ -0,0 +1,181 @@ +.. _psa_crypto: + +PSA Crypto +########## + +Overview +******** + +The PSA (Platform Security Architecture) Crypto API offers a portable +programming interface for cryptographic operations and key storage +across a wide range of hardware. It is designed to be user-friendly +while still providing access to the low-level primitives essential for +modern cryptography. + +It is created and maintained by Arm. Arm developed the PSA as a +comprehensive security framework to address the increasing security +needs of connected devices. + +In Zephyr, the PSA Crypto API is implemented using Mbed TLS, an +open-source cryptographic library that provides the underlying +cryptographic functions. + +Design Goals +************ + +The interface is suitable for a vast range of devices: from +special-purpose cryptographic processors that process data with a +built-in key, to constrained devices running custom application code, +such as microcontrollers, and multi-application devices, such as +servers. It follows the principle of cryptographic agility. + +Algorithm Flexibility + The PSA Crypto API supports a wide range of cryptographic algorithms, + allowing developers to switch between different cryptographic + methods as needed. This flexibility is crucial for maintaining + security as new algorithms emerge and existing ones become obsolete. + +Key Management + The PSA Crypto API includes robust key management features that + support the creation, storage, and use of cryptographic keys in a + secure and flexible manner. It uses opaque key identifiers, which + allows for easy key replacement and updates without exposing key + material. + +Implementation Independence + The PSA Crypto API abstracts the underlying cryptographic library, + meaning that the specific implementation can be changed without + affecting the application code. This abstraction supports + cryptographic agility by enabling the use of different cryptographic + libraries or hardware accelerators as needed. + +Future-Proofing + By adhering to cryptographic agility, PSA Crypto ensures that + applications can quickly adapt to new cryptographic standards and + practices, enhancing long-term security and compliance. + +Examples of Applications +************************ + +Network Security (TLS) + The API provides all of the cryptographic primitives needed to establish TLS connections. + +Secure Storage + The API provides all primitives related to storage encryption, block + or file-based, with master encryption keys stored inside a key store. + +Network Credentials + The API provides network credential management inside a key store, + for example, for X.509-based authentication or pre-shared keys on + enterprise networks. + +Device Pairing + The API provides support for key agreement protocols that are often + used for secure pairing of devices over wireless channels. For + example, the pairing of an NFC token or a Bluetooth device might use + key agreement protocols upon first use. + +Secure Boot + The API provides primitives for use during firmware integrity and + authenticity validation, during a secure or trusted boot process. + +Attestation + The API provides primitives used in attestation + activities. Attestation is the ability for a device to sign an array + of bytes with a device private key and return the result to the + caller. There are several use cases; ranging from attestation of the + device state, to the ability to generate a key pair and prove that it + has been generated inside a secure key store. The API provides access + to the algorithms commonly used for attestation. + +Factory Provisioning + Most IoT devices receive a unique identity during the factory + provisioning process, or once they have been deployed to the + field. This API provides the APIs necessary for populating a device + with keys that represent that identity. + +Usage considerations +******************** + +Always check for errors + Most functions in the PSA Crypto API can return errors. All functions + that can fail have the return type ``psa_status_t``. A few functions + cannot fail, and thus, return void or some other type. + + If an error occurs, unless otherwise specified, the content of the + output parameters is undefined and must not be used. + + Some common causes of errors include: + + * In implementations where the keys are stored and processed in a + separate environment from the application, all functions that need + to access the cryptography processing environment might fail due + to an error in the communication between the two environments. + + * If an algorithm is implemented with a hardware accelerator, which + is logically separate from the application processor, the + accelerator might fail, even when the application processor keeps + running normally. + + * Most functions might fail due to a lack of resources. However, + some implementations guarantee that certain functions always have + sufficient memory. + + * All functions that access persistent keys might fail due to a + storage failure. + + * All functions that require randomness might fail due to a lack of + entropy. Implementations are encouraged to seed the random + generator with sufficient entropy during the execution of + ``psa_crypto_init()``. However, some security standards require + periodic reseeding from a hardware random generator, which can + fail. + +Shared memory and concurrency + Some environments allow applications to be multithreaded, while + others do not. In some environments, applications can share memory + with a different security context. In environments with + multithreaded applications or shared memory, applications must be + written carefully to avoid data corruption or leakage. This + specification requires the application to obey certain constraints. + + In general, the PSA Crypto API allows either one writer or any number of + simultaneous readers, on any given object. In other words, if two or + more calls access the same object concurrently, then the behavior is + only well-defined if all the calls are only reading from the object + and do not modify it. Read accesses include reading memory by input + parameters and reading keystore content by using a key. For more + details, refer to `Concurrent calls + `_ + + If an application shares memory with another security context, it + can pass shared memory blocks as input buffers or output buffers, + but not as non-buffer parameters. For more details, refer to + `Stability of parameters `_. + +Cleaning up after use + To minimize impact if the system is compromised, it is recommended + that applications wipe all sensitive data from memory when it is no + longer used. That way, only data that is currently in use can be + leaked, and past data is not compromised. + + Wiping sensitive data includes: + + * Clearing temporary buffers in the stack or on the heap. + + * Aborting operations if they will not be finished. + + * Destroying keys that are no longer used. + +References +********** + +* `PSA Crypto`_ + +.. _PSA Crypto: + https://arm-software.github.io/psa-api/crypto/ + +* `Mbed TLS`_ + +.. _Mbed TLS: + https://www.trustedfirmware.org/projects/mbed-tls/ From 94af630b2249babd70ec1177d4c48c35ef25a1bf Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Fri, 28 Jul 2023 10:23:25 -0700 Subject: [PATCH 1778/2849] pm: Deprecate PM_DEVICE_RUNTIME_EXCLUSIVE That is option has shown confusing on it is attempt to prevent system pm doing device power management. Lets address this problem properly. Signed-off-by: Flavio Ceolin --- doc/services/pm/device.rst | 6 ------ subsys/pm/Kconfig | 3 ++- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/doc/services/pm/device.rst b/doc/services/pm/device.rst index 055591c5f2c0b..d9b269b64d514 100644 --- a/doc/services/pm/device.rst +++ b/doc/services/pm/device.rst @@ -114,12 +114,6 @@ It is important to emphasize that this method has drawbacks (see above) and :kconfig:option:`CONFIG_PM_NEED_ALL_DEVICES_IDLE` is set and a device is marked as busy. -.. note:: - - This method of device power management is disabled when - :kconfig:option:`CONFIG_PM_DEVICE_RUNTIME_EXCLUSIVE` is set to ``y`` (that is - the default value when :kconfig:option:`CONFIG_PM_DEVICE_RUNTIME` is enabled) - .. note:: Devices are suspended only when the last active core is entering a low power diff --git a/subsys/pm/Kconfig b/subsys/pm/Kconfig index eda7569c917a3..5caf01f1375bf 100644 --- a/subsys/pm/Kconfig +++ b/subsys/pm/Kconfig @@ -123,8 +123,9 @@ config PM_DEVICE_RUNTIME config PM_DEVICE_RUNTIME_EXCLUSIVE depends on PM_DEVICE_RUNTIME - bool "Use only on Runtime Power Management on system suspend / resume" + bool "[DEPRECATED] Use only on Runtime Power Management on system suspend / resume" default y + select DEPRECATED help On system suspend / resume do not trigger the Device PM hooks but only rely on Runtime PM to manage the devices power states. From 2f99ff51ccd49c4baa6790f3bf2e27f359d643c1 Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Fri, 28 Jul 2023 13:39:52 -0700 Subject: [PATCH 1779/2849] pm: Disable device pm per power state Make it possible to disble device power management individually per power state. This allows targets tuning which states should (and which should not) trigger device power management. Signed-off-by: Flavio Ceolin --- dts/bindings/power/zephyr,power-state.yaml | 6 ++++++ include/zephyr/pm/state.h | 12 ++++++++++++ subsys/pm/pm.c | 3 ++- tests/subsys/pm/device_wakeup_api/src/main.c | 2 +- tests/subsys/pm/power_states_api/src/main.c | 4 ++-- 5 files changed, 23 insertions(+), 4 deletions(-) diff --git a/dts/bindings/power/zephyr,power-state.yaml b/dts/bindings/power/zephyr,power-state.yaml index 5c645306b58a1..4fe22d1c5dba0 100644 --- a/dts/bindings/power/zephyr,power-state.yaml +++ b/dts/bindings/power/zephyr,power-state.yaml @@ -31,3 +31,9 @@ properties: type: int description: | Worst case latency in microseconds required to exit the idle state. + zephyr,pm-device-disabled: + type: boolean + description: | + Disable system managed device power management for this state. When set, + the power management subsystem will not suspend devices before entering + this state. diff --git a/include/zephyr/pm/state.h b/include/zephyr/pm/state.h index cc3878794113d..e5866953f379a 100644 --- a/include/zephyr/pm/state.h +++ b/include/zephyr/pm/state.h @@ -134,12 +134,22 @@ struct pm_state_info { * substate-id = <2>; * min-residency-us = <20000>; * exit-latency-us = <200>; + * zephyr,pm-device-disabled; * }; * }; * @endcode */ uint8_t substate_id; + /** + * Whether or not this state triggers device power management. + * + * When this property is false the power management subsystem + * will suspend devices before entering this state and will + * properly resume them when leaving it. + */ + bool pm_device_disabled; + /** * Minimum residency duration in microseconds. It is the minimum * time for a given idle state to be worthwhile energywise. @@ -209,6 +219,7 @@ struct pm_state_info { .substate_id = DT_PROP_OR(node_id, substate_id, 0), \ .min_residency_us = DT_PROP_OR(node_id, min_residency_us, 0), \ .exit_latency_us = DT_PROP_OR(node_id, exit_latency_us, 0), \ + .pm_device_disabled = DT_PROP(node_id, zephyr_pm_device_disabled), \ } /** @@ -260,6 +271,7 @@ struct pm_state_info { * power-state-name = "suspend-to-ram"; * min-residency-us = <50000>; * exit-latency-us = <500>; + * zephyr,pm-device-disabled; * }; * }; * }; diff --git a/subsys/pm/pm.c b/subsys/pm/pm.c index 96ca35cdbe9d5..6f5cca1452fda 100644 --- a/subsys/pm/pm.c +++ b/subsys/pm/pm.c @@ -205,7 +205,8 @@ bool pm_system_suspend(int32_t ticks) #if defined(CONFIG_PM_DEVICE) && !defined(CONFIG_PM_DEVICE_RUNTIME_EXCLUSIVE) if (atomic_sub(&_cpus_active, 1) == 1) { - if (z_cpus_pm_state[id].state != PM_STATE_RUNTIME_IDLE) { + if ((z_cpus_pm_state[id].state != PM_STATE_RUNTIME_IDLE) && + !z_cpus_pm_state[id].pm_device_disabled) { if (pm_suspend_devices()) { pm_resume_devices(); z_cpus_pm_state[id].state = PM_STATE_ACTIVE; diff --git a/tests/subsys/pm/device_wakeup_api/src/main.c b/tests/subsys/pm/device_wakeup_api/src/main.c index cf8d7e2f3c313..6a45f3ffe796f 100644 --- a/tests/subsys/pm/device_wakeup_api/src/main.c +++ b/tests/subsys/pm/device_wakeup_api/src/main.c @@ -61,7 +61,7 @@ void pm_state_exit_post_ops(enum pm_state state, uint8_t substate_id) const struct pm_state_info *pm_policy_next_state(uint8_t cpu, int32_t ticks) { static const struct pm_state_info state = { - .state = PM_STATE_SUSPEND_TO_RAM + .state = PM_STATE_SUSPEND_TO_RAM, }; ARG_UNUSED(cpu); diff --git a/tests/subsys/pm/power_states_api/src/main.c b/tests/subsys/pm/power_states_api/src/main.c index 3699bc0d3ff5c..dac96e9e2993c 100644 --- a/tests/subsys/pm/power_states_api/src/main.c +++ b/tests/subsys/pm/power_states_api/src/main.c @@ -11,8 +11,8 @@ /* Last state has not declared a minimum residency, so it should be * set the default 0 value */ -static struct pm_state_info infos[] = {{PM_STATE_SUSPEND_TO_IDLE, 0, 10000, 100}, - {PM_STATE_SUSPEND_TO_RAM, 0, 50000, 500}, {PM_STATE_STANDBY, 0, 0}}; +static struct pm_state_info infos[] = {{PM_STATE_SUSPEND_TO_IDLE, 0, false, 10000, 100}, + {PM_STATE_SUSPEND_TO_RAM, 0, false, 50000, 500}, {PM_STATE_STANDBY, 0, false, 0}}; static enum pm_state states[] = {PM_STATE_SUSPEND_TO_IDLE, PM_STATE_SUSPEND_TO_RAM, PM_STATE_STANDBY}; static enum pm_state wrong_states[] = {PM_STATE_SUSPEND_TO_DISK, From c65be0cfb94dd021bcfb69a91d90dd8a08926c91 Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Fri, 28 Jul 2023 13:57:10 -0700 Subject: [PATCH 1780/2849] pm: Exclude device pm path when it is not needed Remove device pm path when there is no is no power state in DT with device pm enabled. This basically does the same thing that was done by PM_DEVICE_RUNTIME_EXCLUSIVE. Signed-off-by: Flavio Ceolin --- subsys/pm/pm.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/subsys/pm/pm.c b/subsys/pm/pm.c index 6f5cca1452fda..643a47bcffd8d 100644 --- a/subsys/pm/pm.c +++ b/subsys/pm/pm.c @@ -42,7 +42,14 @@ static struct pm_state_info z_cpus_pm_forced_state[] = { static struct k_spinlock pm_forced_state_lock; static struct k_spinlock pm_notifier_lock; -#ifdef CONFIG_PM_DEVICE +#define DT_PM_DEVICE_ENABLED(node_id) \ + COND_CODE_1(DT_PROP_OR(node_id, zephyr_pm_device_disabled, 0), \ + (), (1 +)) + +#define DT_PM_DEVICE_NEEDED \ + (DT_FOREACH_STATUS_OKAY(zephyr_power_state, DT_PM_DEVICE_ENABLED) 0) + +#if defined(CONFIG_PM_DEVICE) && DT_PM_DEVICE_NEEDED TYPE_SECTION_START_EXTERN(const struct device *, pm_device_slots); #if !defined(CONFIG_PM_DEVICE_RUNTIME_EXCLUSIVE) @@ -99,8 +106,7 @@ static void pm_resume_devices(void) num_susp = 0; } -#endif /* !CONFIG_PM_DEVICE_RUNTIME_EXCLUSIVE */ -#endif /* CONFIG_PM_DEVICE */ +#endif /* defined(CONFIG_PM_DEVICE) && DT_PM_DEVICE_NEEDED */ /* * Function called to notify when the system is entering / exiting a @@ -144,7 +150,7 @@ void pm_system_resume(void) * and it may schedule another thread. */ if (atomic_test_and_clear_bit(z_post_ops_required, id)) { -#if defined(CONFIG_PM_DEVICE) && !defined(CONFIG_PM_DEVICE_RUNTIME_EXCLUSIVE) +#if defined(CONFIG_PM_DEVICE) && DT_PM_DEVICE_NEEDED if (atomic_add(&_cpus_active, 1) == 0) { pm_resume_devices(); } @@ -203,7 +209,7 @@ bool pm_system_suspend(int32_t ticks) return false; } -#if defined(CONFIG_PM_DEVICE) && !defined(CONFIG_PM_DEVICE_RUNTIME_EXCLUSIVE) +#if defined(CONFIG_PM_DEVICE) && DT_PM_DEVICE_NEEDED if (atomic_sub(&_cpus_active, 1) == 1) { if ((z_cpus_pm_state[id].state != PM_STATE_RUNTIME_IDLE) && !z_cpus_pm_state[id].pm_device_disabled) { From 1c2e9880216a052fc3b64004a4b9586e48ac56e4 Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Tue, 16 Jan 2024 15:17:02 -0800 Subject: [PATCH 1781/2849] pm: device: De-couple device pm from system pm PM_DEVICE is not attached to system managed device power management. It is a very common use case targets with device runtime power management that don't want system device power management enabled. We introduce a new symbol (PM_DEVICE_SYSTEM_MANAGED) to explicit control whether or not system device power management should be globally enabled. Signed-off-by: Flavio Ceolin --- subsys/pm/CMakeLists.txt | 1 + subsys/pm/Kconfig | 23 +++++--- subsys/pm/device_system_managed.c | 89 +++++++++++++++++++++++++++++++ subsys/pm/device_system_managed.h | 22 ++++++++ subsys/pm/pm.c | 78 +++------------------------ 5 files changed, 137 insertions(+), 76 deletions(-) create mode 100644 subsys/pm/device_system_managed.c create mode 100644 subsys/pm/device_system_managed.h diff --git a/subsys/pm/CMakeLists.txt b/subsys/pm/CMakeLists.txt index a9aba72caca13..0e961abda7837 100644 --- a/subsys/pm/CMakeLists.txt +++ b/subsys/pm/CMakeLists.txt @@ -8,3 +8,4 @@ endif() zephyr_sources_ifdef(CONFIG_PM_DEVICE device.c) zephyr_sources_ifdef(CONFIG_PM_DEVICE_RUNTIME device_runtime.c) zephyr_sources_ifdef(CONFIG_PM_DEVICE_SHELL pm_shell.c) +zephyr_sources_ifdef(CONFIG_PM_DEVICE_SYSTEM_MANAGED device_system_managed.c) diff --git a/subsys/pm/Kconfig b/subsys/pm/Kconfig index 5caf01f1375bf..2b7ef998415db 100644 --- a/subsys/pm/Kconfig +++ b/subsys/pm/Kconfig @@ -78,12 +78,11 @@ config PM_DEVICE bool "Device Power Management" help This option enables the device power management interface. The - interface consists of hook functions implemented by device drivers - that get called by the power manager application when the system - is going to suspend state or resuming from suspend state. This allows - device drivers to do any necessary power management operations - like turning off device clocks and peripherals. The device drivers - may also save and restore states in these hook functions. + interface implemented by device drivers are called by the power + management subsystem. This allows device drivers to do any + necessary power management operations like turning off + device clocks and peripherals. Device drivers may also save + and restore states in these hook functions. if PM_DEVICE @@ -137,6 +136,18 @@ config PM_DEVICE_SHELL Enable the device power management shell, for triggering device power management events through the shell interface. +config PM_DEVICE_SYSTEM_MANAGED + bool "System-Managed Device Power Management" + default y if !PM_DEVICE_RUNTIME_EXCLUSIVE + default y if !PM_DEVICE_RUNTIME + help + This option enables the system-managed device power + management. The power management subsystem will suspend + devices before entering a low power state. Conversely, after + the core wakes up from low power mode all suspended devices + are resumed. + + endif # PM_DEVICE endmenu diff --git a/subsys/pm/device_system_managed.c b/subsys/pm/device_system_managed.c new file mode 100644 index 0000000000000..6507267d6a6d7 --- /dev/null +++ b/subsys/pm/device_system_managed.c @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2024 Intel Corporation. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +#include +LOG_MODULE_DECLARE(pm_device, CONFIG_PM_DEVICE_LOG_LEVEL); + +#define DT_PM_DEVICE_ENABLED(node_id) \ + COND_CODE_1(DT_PROP(node_id, zephyr_pm_device_disabled), \ + (), (1 +)) + +#define DT_PM_DEVICE_NEEDED \ + (DT_FOREACH_STATUS_OKAY(zephyr_power_state, DT_PM_DEVICE_ENABLED) 0) + +#if DT_PM_DEVICE_NEEDED +TYPE_SECTION_START_EXTERN(const struct device *, pm_device_slots); + +/* Number of devices successfully suspended. */ +static size_t num_susp; + +bool pm_suspend_devices(void) +{ + const struct device *devs; + size_t devc; + + devc = z_device_get_all_static(&devs); + + num_susp = 0; + + for (const struct device *dev = devs + devc - 1; dev >= devs; dev--) { + int ret; + + /* + * Ignore uninitialized devices, busy devices, wake up sources, and + * devices with runtime PM enabled. + */ + if (!device_is_ready(dev) || pm_device_is_busy(dev) || + pm_device_wakeup_is_enabled(dev) || + pm_device_runtime_is_enabled(dev)) { + continue; + } + + ret = pm_device_action_run(dev, PM_DEVICE_ACTION_SUSPEND); + /* ignore devices not supporting or already at the given state */ + if ((ret == -ENOSYS) || (ret == -ENOTSUP) || (ret == -EALREADY)) { + continue; + } else if (ret < 0) { + LOG_ERR("Device %s did not enter %s state (%d)", + dev->name, + pm_device_state_str(PM_DEVICE_STATE_SUSPENDED), + ret); + return false; + } + + TYPE_SECTION_START(pm_device_slots)[num_susp] = dev; + num_susp++; + } + + return true; +} + +void pm_resume_devices(void) +{ + for (int i = (num_susp - 1); i >= 0; i--) { + pm_device_action_run(TYPE_SECTION_START(pm_device_slots)[i], + PM_DEVICE_ACTION_RESUME); + } + + num_susp = 0; +} + +#else /* !DT_PM_DEVICE_NEEDED */ + +void pm_resume_devices(void) +{ +} + +bool pm_suspend_devices(void) +{ + return true; +} + +#endif diff --git a/subsys/pm/device_system_managed.h b/subsys/pm/device_system_managed.h new file mode 100644 index 0000000000000..6c2e9b930f2ff --- /dev/null +++ b/subsys/pm/device_system_managed.h @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2024 Intel Corporation. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_SUBSYS_PM_DEVICE_SYSTEM_MANAGED_H_ +#define ZEPHYR_SUBSYS_PM_DEVICE_SYSTEM_MANAGED_H_ + +#ifdef CONFIG_PM_DEVICE_SYSTEM_MANAGED + +bool pm_suspend_devices(void); +void pm_resume_devices(void); + +#else + +bool pm_resume_devices(void) { return true; } +void pm_suspend_devices(void) {} + +#endif /* CONFIG_PM_DEVICE_SYSTEM_MANAGED */ + +#endif /* ZEPHYR_SUBSYS_PM_DEVICE_SYSTEM_MANAGED_H_ */ diff --git a/subsys/pm/pm.c b/subsys/pm/pm.c index 643a47bcffd8d..25e60b68a6db1 100644 --- a/subsys/pm/pm.c +++ b/subsys/pm/pm.c @@ -18,6 +18,7 @@ #include #include "pm_stats.h" +#include "device_system_managed.h" #include LOG_MODULE_REGISTER(pm, CONFIG_PM_LOG_LEVEL); @@ -42,72 +43,6 @@ static struct pm_state_info z_cpus_pm_forced_state[] = { static struct k_spinlock pm_forced_state_lock; static struct k_spinlock pm_notifier_lock; -#define DT_PM_DEVICE_ENABLED(node_id) \ - COND_CODE_1(DT_PROP_OR(node_id, zephyr_pm_device_disabled, 0), \ - (), (1 +)) - -#define DT_PM_DEVICE_NEEDED \ - (DT_FOREACH_STATUS_OKAY(zephyr_power_state, DT_PM_DEVICE_ENABLED) 0) - -#if defined(CONFIG_PM_DEVICE) && DT_PM_DEVICE_NEEDED -TYPE_SECTION_START_EXTERN(const struct device *, pm_device_slots); - -#if !defined(CONFIG_PM_DEVICE_RUNTIME_EXCLUSIVE) -/* Number of devices successfully suspended. */ -static size_t num_susp; - -static int pm_suspend_devices(void) -{ - const struct device *devs; - size_t devc; - - devc = z_device_get_all_static(&devs); - - num_susp = 0; - - for (const struct device *dev = devs + devc - 1; dev >= devs; dev--) { - int ret; - - /* - * Ignore uninitialized devices, busy devices, wake up sources, and - * devices with runtime PM enabled. - */ - if (!device_is_ready(dev) || pm_device_is_busy(dev) || - pm_device_wakeup_is_enabled(dev) || - pm_device_runtime_is_enabled(dev)) { - continue; - } - - ret = pm_device_action_run(dev, PM_DEVICE_ACTION_SUSPEND); - /* ignore devices not supporting or already at the given state */ - if ((ret == -ENOSYS) || (ret == -ENOTSUP) || (ret == -EALREADY)) { - continue; - } else if (ret < 0) { - LOG_ERR("Device %s did not enter %s state (%d)", - dev->name, - pm_device_state_str(PM_DEVICE_STATE_SUSPENDED), - ret); - return ret; - } - - TYPE_SECTION_START(pm_device_slots)[num_susp] = dev; - num_susp++; - } - - return 0; -} - -static void pm_resume_devices(void) -{ - for (int i = (num_susp - 1); i >= 0; i--) { - pm_device_action_run(TYPE_SECTION_START(pm_device_slots)[i], - PM_DEVICE_ACTION_RESUME); - } - - num_susp = 0; -} -#endif /* defined(CONFIG_PM_DEVICE) && DT_PM_DEVICE_NEEDED */ - /* * Function called to notify when the system is entering / exiting a * power state @@ -150,9 +85,12 @@ void pm_system_resume(void) * and it may schedule another thread. */ if (atomic_test_and_clear_bit(z_post_ops_required, id)) { -#if defined(CONFIG_PM_DEVICE) && DT_PM_DEVICE_NEEDED +#ifdef CONFIG_PM_DEVICE_SYSTEM_MANAGED if (atomic_add(&_cpus_active, 1) == 0) { - pm_resume_devices(); + if ((z_cpus_pm_state[id].state != PM_STATE_RUNTIME_IDLE) && + !z_cpus_pm_state[id].pm_device_disabled) { + pm_resume_devices(); + } } #endif pm_state_exit_post_ops(z_cpus_pm_state[id].state, z_cpus_pm_state[id].substate_id); @@ -209,11 +147,11 @@ bool pm_system_suspend(int32_t ticks) return false; } -#if defined(CONFIG_PM_DEVICE) && DT_PM_DEVICE_NEEDED +#ifdef CONFIG_PM_DEVICE_SYSTEM_MANAGED if (atomic_sub(&_cpus_active, 1) == 1) { if ((z_cpus_pm_state[id].state != PM_STATE_RUNTIME_IDLE) && !z_cpus_pm_state[id].pm_device_disabled) { - if (pm_suspend_devices()) { + if (!pm_suspend_devices()) { pm_resume_devices(); z_cpus_pm_state[id].state = PM_STATE_ACTIVE; (void)atomic_add(&_cpus_active, 1); From 45e9c2eed34c12ee6cba4c2d783641c0b50fd26b Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Sat, 29 Jul 2023 13:07:24 -0700 Subject: [PATCH 1782/2849] tests: power_mgmt: Use DTS overlay for power state Define the power state needed in the test in DT. Signed-off-by: Flavio Ceolin --- .../pm/power_mgmt/boards/native_sim.overlay | 13 +++++++++++++ tests/subsys/pm/power_mgmt/src/main.c | 15 ++++++--------- 2 files changed, 19 insertions(+), 9 deletions(-) diff --git a/tests/subsys/pm/power_mgmt/boards/native_sim.overlay b/tests/subsys/pm/power_mgmt/boards/native_sim.overlay index a66ce9d00256a..a5eb7f26234cb 100644 --- a/tests/subsys/pm/power_mgmt/boards/native_sim.overlay +++ b/tests/subsys/pm/power_mgmt/boards/native_sim.overlay @@ -5,6 +5,15 @@ */ / { + cpus { + power-states { + state0: state0 { + compatible = "zephyr,power-state"; + power-state-name = "suspend-to-idle"; + }; + }; + }; + device_a: device_a { compatible = "test-device-pm"; }; @@ -25,3 +34,7 @@ compatible = "test-device-pm"; }; }; + +&cpu0 { + cpu-power-states = <&state0>; +}; diff --git a/tests/subsys/pm/power_mgmt/src/main.c b/tests/subsys/pm/power_mgmt/src/main.c index 10746b49021c2..f3a6904e2b2ed 100644 --- a/tests/subsys/pm/power_mgmt/src/main.c +++ b/tests/subsys/pm/power_mgmt/src/main.c @@ -229,9 +229,10 @@ void pm_state_exit_post_ops(enum pm_state state, uint8_t substate_id) /* Our PM policy handler */ const struct pm_state_info *pm_policy_next_state(uint8_t cpu, int32_t ticks) { - static struct pm_state_info info; + const struct pm_state_info *cpu_states; - ARG_UNUSED(cpu); + zassert_true(pm_state_cpu_get_all(cpu, &cpu_states) == 1, + "There is no power state defined"); /* make sure this is idle thread */ zassert_true(z_is_idle_thread_object(_current)); @@ -242,14 +243,10 @@ const struct pm_state_info *pm_policy_next_state(uint8_t cpu, int32_t ticks) if (enter_low_power) { enter_low_power = false; notify_app_entry = true; - info.state = PM_STATE_SUSPEND_TO_IDLE; - } else { - /* only test pm_policy_next_state() - * no PM operation done - */ - info.state = PM_STATE_ACTIVE; + return &cpu_states[0]; } - return &info; + + return NULL; } /* implement in application, called by idle thread */ From 7dcec56601b69de1da3e79722f8a68f3aedef24a Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Sat, 29 Jul 2023 13:12:47 -0700 Subject: [PATCH 1783/2849] tests: device_wakeup_api: Use DTS overlay for power state Define the power state needed in the test in DT. Signed-off-by: Flavio Ceolin --- .../pm/device_wakeup_api/boards/native_sim.overlay | 14 ++++++++++++++ tests/subsys/pm/device_wakeup_api/src/main.c | 9 ++++----- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/tests/subsys/pm/device_wakeup_api/boards/native_sim.overlay b/tests/subsys/pm/device_wakeup_api/boards/native_sim.overlay index 97fa7c3c71aa0..978899042e40a 100644 --- a/tests/subsys/pm/device_wakeup_api/boards/native_sim.overlay +++ b/tests/subsys/pm/device_wakeup_api/boards/native_sim.overlay @@ -3,9 +3,23 @@ * * SPDX-License-Identifier: Apache-2.0 */ +/ { + cpus { + power-states { + state0: state0 { + compatible = "zephyr,power-state"; + power-state-name = "suspend-to-ram"; + }; + }; + }; +}; &gpio0 { compatible = "zephyr,gpio-emul"; gpio-controller; wakeup-source; }; + +&cpu0 { + cpu-power-states = <&state0>; +}; diff --git a/tests/subsys/pm/device_wakeup_api/src/main.c b/tests/subsys/pm/device_wakeup_api/src/main.c index 6a45f3ffe796f..2486d3a586817 100644 --- a/tests/subsys/pm/device_wakeup_api/src/main.c +++ b/tests/subsys/pm/device_wakeup_api/src/main.c @@ -60,15 +60,14 @@ void pm_state_exit_post_ops(enum pm_state state, uint8_t substate_id) const struct pm_state_info *pm_policy_next_state(uint8_t cpu, int32_t ticks) { - static const struct pm_state_info state = { - .state = PM_STATE_SUSPEND_TO_RAM, - }; + const struct pm_state_info *cpu_states; - ARG_UNUSED(cpu); + zassert_true(pm_state_cpu_get_all(cpu, &cpu_states) == 1, + "There is no power state defined"); while (sleep_count < 3) { sleep_count++; - return &state; + return &cpu_states[0]; } return NULL; From dcf22a66dea0b9994252486379e503a076e6fd6e Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Thu, 3 Aug 2023 13:27:35 -0700 Subject: [PATCH 1784/2849] doc: pm: Update system device pm Add new information about new property to enable/disable device power management per power state. Signed-off-by: Flavio Ceolin --- doc/services/pm/device.rst | 36 +++++++++++++++++++++++++++++++++--- 1 file changed, 33 insertions(+), 3 deletions(-) diff --git a/doc/services/pm/device.rst b/doc/services/pm/device.rst index d9b269b64d514..e473fe3f4bfcf 100644 --- a/doc/services/pm/device.rst +++ b/doc/services/pm/device.rst @@ -72,16 +72,46 @@ For more information, see :ref:`pm-device-runtime`. System-Managed Device Power Management ====================================== +The system managed device power management (PM) framework is a method where +devices are suspended along with the system entering a CPU (or SoC) power state. +It can be enabled by setting :kconfig:option:`CONFIG_PM_DEVICE_SYSTEM_MANAGED`. When using this method, device power management is mostly done inside -:c:func:`pm_system_suspend()` along with entering a CPU or SOC power state. +:c:func:`pm_system_suspend()`. If a decision to enter a CPU lower power state is made, the power management -subsystem will suspend devices before changing state. The subsystem takes care -of suspending devices following their initialization order, ensuring that +subsystem will check if the selected low power state triggers device power +management and then suspend devices before changing state. The subsystem takes +care of suspending devices following their initialization order, ensuring that possible dependencies between them are satisfied. As soon as the CPU wakes up from a sleep state, devices are resumed in the opposite order that they were suspended. +The decision about suspending devices when entering a low power state is done based on the +state and if it has set the property ``zephyr,pm-device-disabled``. Here is +an example of a target with two low power states with only one triggering device power +management: + +.. code-block:: devicetree + + /* Node in a DTS file */ + cpus { + power-states { + state0: state0 { + compatible = "zephyr,power-state"; + power-state-name = "standby"; + min-residency-us = <5000>; + exit-latency-us = <240>; + zephyr,pm-device-disabled; + }; + state1: state1 { + compatible = "zephyr,power-state"; + power-state-name = "suspend-to-ram"; + min-residency-us = <8000>; + exit-latency-us = <360>; + }; + }; + }; + .. note:: When using :ref:`pm-system`, device transitions can be run from the idle thread. From 1359eb93089290ed19e5ee5d35b17980498ed434 Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Sun, 28 Jan 2024 18:49:55 +0000 Subject: [PATCH 1785/2849] tests: power_mgmt: Add test for PM_DEVICE_SYSTEM_MANAGED Add a new test that disables PM_DEVICE_SYSTEM_MANAGED, since this option is enabled by default. Signed-off-by: Flavio Ceolin --- tests/subsys/pm/power_mgmt/no-device-pm.conf | 7 +++++++ tests/subsys/pm/power_mgmt/src/main.c | 15 ++++++++++++++- tests/subsys/pm/power_mgmt/testcase.yaml | 10 +++++++--- 3 files changed, 28 insertions(+), 4 deletions(-) create mode 100644 tests/subsys/pm/power_mgmt/no-device-pm.conf diff --git a/tests/subsys/pm/power_mgmt/no-device-pm.conf b/tests/subsys/pm/power_mgmt/no-device-pm.conf new file mode 100644 index 0000000000000..862c4f8fa2cf8 --- /dev/null +++ b/tests/subsys/pm/power_mgmt/no-device-pm.conf @@ -0,0 +1,7 @@ +CONFIG_ZTEST=y +CONFIG_PM=y +CONFIG_PM_DEVICE=y +CONFIG_PM_DEVICE_RUNTIME=y +CONFIG_PM_POLICY_CUSTOM=y +CONFIG_PM_DEVICE_SYSTEM_MANAGED=n +CONFIG_MP_MAX_NUM_CPUS=1 diff --git a/tests/subsys/pm/power_mgmt/src/main.c b/tests/subsys/pm/power_mgmt/src/main.c index f3a6904e2b2ed..c93a1d43e84cc 100644 --- a/tests/subsys/pm/power_mgmt/src/main.c +++ b/tests/subsys/pm/power_mgmt/src/main.c @@ -177,6 +177,18 @@ void pm_state_set(enum pm_state state, uint8_t substate_id) enum pm_device_state device_power_state; +#ifndef CONFIG_PM_DEVICE_SYSTEM_MANAGED + /* Devices shouldn't have changed state because system managed + * device power management is not enabled. + **/ + pm_device_state_get(device_a, &device_power_state); + zassert_true(device_power_state == PM_DEVICE_STATE_ACTIVE, + NULL); + + pm_device_state_get(device_c, &device_power_state); + zassert_true(device_power_state == PM_DEVICE_STATE_ACTIVE, + NULL); +#else /* If testing device order this function does not need to anything */ if (testing_device_order) { return; @@ -213,6 +225,7 @@ void pm_state_set(enum pm_state state, uint8_t substate_id) */ zassert_false(state == PM_STATE_ACTIVE, "Entering low power state with a wrong parameter"); +#endif } void pm_state_exit_post_ops(enum pm_state state, uint8_t substate_id) @@ -261,7 +274,7 @@ static void notify_pm_state_entry(enum pm_state state) zassert_equal(state, PM_STATE_SUSPEND_TO_IDLE); pm_device_state_get(device_dummy, &device_power_state); - if (testing_device_runtime) { + if (testing_device_runtime || !IS_ENABLED(CONFIG_PM_DEVICE_SYSTEM_MANAGED)) { /* If device runtime is enable, the device should still be * active */ diff --git a/tests/subsys/pm/power_mgmt/testcase.yaml b/tests/subsys/pm/power_mgmt/testcase.yaml index b51b282ea5549..8c4a1c92e3d83 100644 --- a/tests/subsys/pm/power_mgmt/testcase.yaml +++ b/tests/subsys/pm/power_mgmt/testcase.yaml @@ -1,4 +1,8 @@ +common: + platform_allow: native_sim + tags: pm tests: - pm.system: - platform_allow: native_sim - tags: pm + pm.system: {} + pm.system.no.device.pm: + extra_args: + - OVERLAY_CONFIG="no-device-pm.conf" From 2dfacadd041a5256d877cfa37c5119f573bbbf5a Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Fri, 22 Mar 2024 11:47:25 -0700 Subject: [PATCH 1786/2849] tests: pm: Replace depracated build option Replace the usage of CONFIG_PM_DEVICE_RUNTIME_EXCLUSIVE with CONFIG_PM_DEVICE_SYSTEM_MANAGED. Signed-off-by: Flavio Ceolin --- samples/boards/stm32/power_mgmt/adc/prj.conf | 2 +- samples/boards/stm32/power_mgmt/blinky/prj.conf | 2 +- samples/boards/stm32/power_mgmt/serial_wakeup/prj.conf | 2 +- samples/boards/stm32/power_mgmt/suspend_to_ram/prj.conf | 2 +- tests/subsys/pm/power_mgmt/prj.conf | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/samples/boards/stm32/power_mgmt/adc/prj.conf b/samples/boards/stm32/power_mgmt/adc/prj.conf index c5359fe02387d..6c9650f1dfb2b 100644 --- a/samples/boards/stm32/power_mgmt/adc/prj.conf +++ b/samples/boards/stm32/power_mgmt/adc/prj.conf @@ -1,6 +1,6 @@ CONFIG_PM=y CONFIG_PM_DEVICE=y CONFIG_PM_DEVICE_RUNTIME=y -CONFIG_PM_DEVICE_RUNTIME_EXCLUSIVE=n +CONFIG_PM_DEVICE_SYSTEM_MANAGED=y CONFIG_ADC=y #CONFIG_DEBUG=y diff --git a/samples/boards/stm32/power_mgmt/blinky/prj.conf b/samples/boards/stm32/power_mgmt/blinky/prj.conf index fa60e82b4f0a4..6888f24a03f9a 100644 --- a/samples/boards/stm32/power_mgmt/blinky/prj.conf +++ b/samples/boards/stm32/power_mgmt/blinky/prj.conf @@ -1,5 +1,5 @@ CONFIG_PM=y CONFIG_PM_DEVICE=y CONFIG_PM_DEVICE_RUNTIME=y -CONFIG_PM_DEVICE_RUNTIME_EXCLUSIVE=n +CONFIG_PM_DEVICE_SYSTEM_MANAGED=y CONFIG_ASSERT=y diff --git a/samples/boards/stm32/power_mgmt/serial_wakeup/prj.conf b/samples/boards/stm32/power_mgmt/serial_wakeup/prj.conf index ca1e6cf73a9df..526010f5d162d 100644 --- a/samples/boards/stm32/power_mgmt/serial_wakeup/prj.conf +++ b/samples/boards/stm32/power_mgmt/serial_wakeup/prj.conf @@ -1,7 +1,7 @@ CONFIG_PM=y CONFIG_PM_DEVICE=y CONFIG_PM_DEVICE_RUNTIME=y -CONFIG_PM_DEVICE_RUNTIME_EXCLUSIVE=y +CONFIG_PM_DEVICE_SYSTEM_MANAGED=n CONFIG_SHELL=y diff --git a/samples/boards/stm32/power_mgmt/suspend_to_ram/prj.conf b/samples/boards/stm32/power_mgmt/suspend_to_ram/prj.conf index 78963168c5a81..ce43f3f936fb5 100644 --- a/samples/boards/stm32/power_mgmt/suspend_to_ram/prj.conf +++ b/samples/boards/stm32/power_mgmt/suspend_to_ram/prj.conf @@ -1,7 +1,7 @@ CONFIG_PM=y CONFIG_PM_DEVICE=y CONFIG_PM_DEVICE_RUNTIME=y -CONFIG_PM_DEVICE_RUNTIME_EXCLUSIVE=n +CONFIG_PM_DEVICE_SYSTEM_MANAGED=y CONFIG_PM_S2RAM=y CONFIG_ADC=y CONFIG_ENTROPY_GENERATOR=y diff --git a/tests/subsys/pm/power_mgmt/prj.conf b/tests/subsys/pm/power_mgmt/prj.conf index 81edc8f7e26d1..8c6a19ef3afc7 100644 --- a/tests/subsys/pm/power_mgmt/prj.conf +++ b/tests/subsys/pm/power_mgmt/prj.conf @@ -4,4 +4,4 @@ CONFIG_PM_DEVICE=y CONFIG_PM_DEVICE_RUNTIME=y CONFIG_PM_POLICY_CUSTOM=y CONFIG_MP_MAX_NUM_CPUS=1 -CONFIG_PM_DEVICE_RUNTIME_EXCLUSIVE=n +CONFIG_PM_DEVICE_SYSTEM_MANAGED=y From 4ffefed23a74c720a0a0e5517fb8341bae327f19 Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Fri, 19 Apr 2024 14:16:15 -0700 Subject: [PATCH 1787/2849] tests: power_mgmt: Test system-managed disabled per state Check that a power state that has system-managed device power management disabled does not trigger device power management when the system sleeps. Signed-off-by: Flavio Ceolin --- .../pm/power_mgmt/boards/native_sim.overlay | 7 ++++++- tests/subsys/pm/power_mgmt/src/main.c | 15 ++++++++++++--- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/tests/subsys/pm/power_mgmt/boards/native_sim.overlay b/tests/subsys/pm/power_mgmt/boards/native_sim.overlay index a5eb7f26234cb..eee1b914540fb 100644 --- a/tests/subsys/pm/power_mgmt/boards/native_sim.overlay +++ b/tests/subsys/pm/power_mgmt/boards/native_sim.overlay @@ -11,6 +11,11 @@ compatible = "zephyr,power-state"; power-state-name = "suspend-to-idle"; }; + state1: state1 { + compatible = "zephyr,power-state"; + power-state-name = "standby"; + zephyr,pm-device-disabled; + }; }; }; @@ -36,5 +41,5 @@ }; &cpu0 { - cpu-power-states = <&state0>; + cpu-power-states = <&state0 &state1>; }; diff --git a/tests/subsys/pm/power_mgmt/src/main.c b/tests/subsys/pm/power_mgmt/src/main.c index c93a1d43e84cc..3c75e44587fc7 100644 --- a/tests/subsys/pm/power_mgmt/src/main.c +++ b/tests/subsys/pm/power_mgmt/src/main.c @@ -199,6 +199,12 @@ void pm_state_set(enum pm_state state, uint8_t substate_id) set_pm = true; zassert_equal(state, forced_state, NULL); testing_force_state = false; + + /* We have forced a state that does not trigger device power management. + * The device should still be active. + */ + pm_device_state_get(device_c, &device_power_state); + zassert_true(device_power_state == PM_DEVICE_STATE_ACTIVE); } /* at this point, notify_pm_state_entry() implemented in @@ -244,7 +250,7 @@ const struct pm_state_info *pm_policy_next_state(uint8_t cpu, int32_t ticks) { const struct pm_state_info *cpu_states; - zassert_true(pm_state_cpu_get_all(cpu, &cpu_states) == 1, + zassert_true(pm_state_cpu_get_all(cpu, &cpu_states) == 2, "There is no power state defined"); /* make sure this is idle thread */ @@ -457,8 +463,11 @@ ZTEST(power_management_1cpu, test_empty_states) ZTEST(power_management_1cpu, test_force_state) { - forced_state = PM_STATE_STANDBY; - bool ret = pm_state_force(0, &(struct pm_state_info) {forced_state, 0, 0}); + const struct pm_state_info *cpu_states; + + pm_state_cpu_get_all(0, &cpu_states); + forced_state = cpu_states[1].state; + bool ret = pm_state_force(0, &cpu_states[1]); zassert_equal(ret, true, "Error in force state"); From 69360d2f386ce808caeb715819c4ab1b717571c1 Mon Sep 17 00:00:00 2001 From: Chekhov Ma Date: Thu, 9 May 2024 16:20:51 +0800 Subject: [PATCH 1788/2849] soc: imx93: enable flexcan driver - Add flexcan dts node and pinctrl. Signed-off-by: Chekhov Ma --- dts/arm64/nxp/nxp_mimx93_a55.dtsi | 24 ++++++++++++++++++++++++ soc/nxp/imx/imx9/a55/mmu_regions.c | 3 +++ 2 files changed, 27 insertions(+) diff --git a/dts/arm64/nxp/nxp_mimx93_a55.dtsi b/dts/arm64/nxp/nxp_mimx93_a55.dtsi index defcb2dc32687..387c0187261d1 100644 --- a/dts/arm64/nxp/nxp_mimx93_a55.dtsi +++ b/dts/arm64/nxp/nxp_mimx93_a55.dtsi @@ -322,6 +322,30 @@ #size-cells = <0>; }; + flexcan1: can@443a0000 { + compatible = "nxp,flexcan-fd", "nxp,flexcan"; + reg = <0x443a0000 DT_SIZE_K(64)>; + interrupt-parent= <&gic>; + interrupts = , + ; + interrupt-names = "common", "error"; + clocks = <&ccm IMX_CCM_CAN1_CLK 0x68 14>; + clk-source = <0>; + status = "disabled"; + }; + + flexcan2: can@425b0000 { + compatible = "nxp,flexcan-fd", "nxp,flexcan"; + reg = <0x425b0000 DT_SIZE_K(64)>; + interrupt-parent= <&gic>; + interrupts = , + ; + interrupt-names = "common", "error"; + clocks = <&ccm IMX_CCM_CAN1_CLK 0x68 14>; + clk-source = <0>; + status = "disabled"; + }; + edma4: dma@42000000 { compatible = "nxp,edma"; reg = <0x42000000 (DT_SIZE_K(64) * 32)>; diff --git a/soc/nxp/imx/imx9/a55/mmu_regions.c b/soc/nxp/imx/imx9/a55/mmu_regions.c index 4305d8ff7e23e..98f26abb4ab3d 100644 --- a/soc/nxp/imx/imx9/a55/mmu_regions.c +++ b/soc/nxp/imx/imx9/a55/mmu_regions.c @@ -38,6 +38,9 @@ static const struct arm_mmu_region mmu_regions[] = { MMU_REGION_DT_COMPAT_FOREACH_FLAT_ENTRY(nxp_kinetis_lpuart, (MT_DEVICE_nGnRnE | MT_P_RW_U_NA | MT_NS)) + MMU_REGION_DT_COMPAT_FOREACH_FLAT_ENTRY(nxp_flexcan, + (MT_DEVICE_nGnRnE | MT_P_RW_U_NA | MT_NS)) + #if CONFIG_SOF MMU_REGION_FLAT_ENTRY("MU2_A", DT_REG_ADDR(DT_NODELABEL(mu2_a)), From 07f132b1b50ac803ab775a578a0890c1e46b4ed8 Mon Sep 17 00:00:00 2001 From: Chekhov Ma Date: Fri, 24 May 2024 13:56:16 +0800 Subject: [PATCH 1789/2849] boards: imx93_evk: enable flexcan driver Add pinctrl for flexcan2 Add EXP_SEL gpio hog for board mux selection during boot. Add TJA1057 CAN PHY driver. Update supported features in board document Signed-off-by: Chekhov Ma --- boards/nxp/imx93_evk/Kconfig.defconfig | 14 ++++++++++++ boards/nxp/imx93_evk/doc/index.rst | 8 +++++++ boards/nxp/imx93_evk/imx93_evk-pinctrl.dtsi | 18 +++++++++++++++ .../nxp/imx93_evk/imx93_evk_mimx9352_a55.dts | 22 +++++++++++++++++-- .../nxp/imx93_evk/imx93_evk_mimx9352_a55.yaml | 1 + 5 files changed, 61 insertions(+), 2 deletions(-) create mode 100644 boards/nxp/imx93_evk/Kconfig.defconfig diff --git a/boards/nxp/imx93_evk/Kconfig.defconfig b/boards/nxp/imx93_evk/Kconfig.defconfig new file mode 100644 index 0000000000000..556fd451cfcb1 --- /dev/null +++ b/boards/nxp/imx93_evk/Kconfig.defconfig @@ -0,0 +1,14 @@ +# MIMX93 EVK board defconfig + +# Copyright 2024 NXP +# SPDX-License-Identifier: Apache-2.0 + +if BOARD_IMX93_EVK_MIMX9352_A55 + +if CAN +# CAN Phy must be enabled after mfd0 gpio expander is ready +config CAN_TRANSCEIVER_INIT_PRIORITY + default 75 +endif + +endif # BOARD_IMX93_EVK_MIMX9352_A55 diff --git a/boards/nxp/imx93_evk/doc/index.rst b/boards/nxp/imx93_evk/doc/index.rst index 0fdeb237ec27c..2c1f742efa41a 100644 --- a/boards/nxp/imx93_evk/doc/index.rst +++ b/boards/nxp/imx93_evk/doc/index.rst @@ -58,8 +58,16 @@ features: +-----------+------------+-------------------------------------+ | ARM TIMER | on-chip | system clock | +-----------+------------+-------------------------------------+ +| GPIO | on-chip | gpio | ++-----------+------------+-------------------------------------+ | UART | on-chip | serial port | +-----------+------------+-------------------------------------+ +| I2C | on-chip | i2c | ++-----------+------------+-------------------------------------+ +| SPI | on-chip | spi | ++-----------+------------+-------------------------------------+ +| CAN | on-chip | can | ++-----------+------------+-------------------------------------+ Devices ======== diff --git a/boards/nxp/imx93_evk/imx93_evk-pinctrl.dtsi b/boards/nxp/imx93_evk/imx93_evk-pinctrl.dtsi index 31e35907f86d6..5f19f1f63a479 100644 --- a/boards/nxp/imx93_evk/imx93_evk-pinctrl.dtsi +++ b/boards/nxp/imx93_evk/imx93_evk-pinctrl.dtsi @@ -83,4 +83,22 @@ }; }; + flexcan1_default: flexcan1_default { + group0 { + pinmux = <&iomuxc1_sai1_txd0_can_tx_can1_tx>, + <&iomuxc1_sai1_txc_can_rx_can1_rx>; + slew-rate = "slightly_fast"; + drive-strength = "x5"; + }; + }; + + flexcan2_default: flexcan2_default { + group0 { + pinmux = <&iomuxc1_gpio_io25_can_tx_can2_tx>, + <&iomuxc1_gpio_io27_can_rx_can2_rx>; + slew-rate = "slightly_fast"; + drive-strength = "x5"; + }; + }; + }; diff --git a/boards/nxp/imx93_evk/imx93_evk_mimx9352_a55.dts b/boards/nxp/imx93_evk/imx93_evk_mimx9352_a55.dts index cd025a547e717..f68fb2094661c 100644 --- a/boards/nxp/imx93_evk/imx93_evk_mimx9352_a55.dts +++ b/boards/nxp/imx93_evk/imx93_evk_mimx9352_a55.dts @@ -17,6 +17,7 @@ zephyr,console = &lpuart2; zephyr,shell-uart = &lpuart2; zephyr,sram = &sram0; + zephyr,canbus = &flexcan2; }; cpus { @@ -64,6 +65,14 @@ gpios = <&gpio2 24 GPIO_ACTIVE_LOW>; }; }; + + can_phy0: can-phy0 { + compatible = "nxp,tja1057", "can-transceiver-gpio"; + max-bitrate = <8000000>; + standby-gpios = <&gpio_exp0 8 GPIO_ACTIVE_HIGH>; + #phy-cells = <0>; + status = "okay"; + }; }; &lpuart1 { @@ -91,7 +100,7 @@ }; &lpi2c2 { - status = "disabled"; + status = "okay"; clock-frequency = ; pinctrl-0 = <&i2c2_default>; pinctrl-names = "default"; @@ -99,7 +108,7 @@ mfd0:adp5585@34 { compatible = "adi,adp5585"; reg = <0x34>; - status = "disabled"; + status = "okay"; gpio_exp0: adp5585_gpio { compatible = "adi,adp5585-gpio"; @@ -146,3 +155,12 @@ &gpio4{ status = "okay"; }; + +&flexcan2 { + pinctrl-0 = <&flexcan2_default>; + pinctrl-names = "default"; + bus-speed = <125000>; + bus-speed-data = <1000000>; + phys = <&can_phy0>; + status = "okay"; +}; diff --git a/boards/nxp/imx93_evk/imx93_evk_mimx9352_a55.yaml b/boards/nxp/imx93_evk/imx93_evk_mimx9352_a55.yaml index 3a045828f8423..d40b613b39185 100644 --- a/boards/nxp/imx93_evk/imx93_evk_mimx9352_a55.yaml +++ b/boards/nxp/imx93_evk/imx93_evk_mimx9352_a55.yaml @@ -17,6 +17,7 @@ supported: - uart - i2c - spi + - can testing: ignore_tags: - net From a7d55cfa13ffe8c2eebd04a14ee715635fd54dda Mon Sep 17 00:00:00 2001 From: Henrik Brix Andersen Date: Wed, 29 May 2024 17:30:14 +0000 Subject: [PATCH 1790/2849] twister: harness: pytest: list available fixtures in device config Pass the list of supported twister fixtures for a given platform to pytest via DeviceConfig. This allows for the pytest suites to use knowledge of the fixtures for test suite configuration. Signed-off-by: Henrik Brix Andersen --- .../pytest-twister-harness/src/twister_harness/plugin.py | 4 ++++ .../src/twister_harness/twister_harness_config.py | 2 ++ scripts/pylib/twister/twisterlib/harness.py | 7 +++++++ .../twister/pytest_integration/test_harness_pytest.py | 5 ++++- scripts/tests/twister/test_harness.py | 3 +++ 5 files changed, 20 insertions(+), 1 deletion(-) 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 60537608357a1..e484cb8bb43ca 100644 --- a/scripts/pylib/pytest-twister-harness/src/twister_harness/plugin.py +++ b/scripts/pylib/pytest-twister-harness/src/twister_harness/plugin.py @@ -117,6 +117,10 @@ def pytest_addoption(parser: pytest.Parser): choices=('function', 'class', 'module', 'package', 'session'), help='The scope for which `dut` and `shell` fixtures are shared.' ) + twister_harness_group.addoption( + '--twister-fixture', action='append', dest='fixtures', metavar='FIXTURE', default=[], + help='Twister fixture supported by this platform. May be given multiple times.' + ) def pytest_configure(config: pytest.Config): 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 08087a97387c1..a4b0b7497775d 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 @@ -33,6 +33,7 @@ class DeviceConfig: pre_script: Path | None = None post_script: Path | None = None post_flash_script: Path | None = None + fixtures: list[str] = None app_build_dir: Path | None = None def __post_init__(self): @@ -77,6 +78,7 @@ def create(cls, config: pytest.Config) -> TwisterHarnessConfig: pre_script=_cast_to_path(config.option.pre_script), post_script=_cast_to_path(config.option.post_script), post_flash_script=_cast_to_path(config.option.post_flash_script), + fixtures=config.option.fixtures, ) devices.append(device_from_cli) diff --git a/scripts/pylib/twister/twisterlib/harness.py b/scripts/pylib/twister/twisterlib/harness.py index 8f4f47a7f082d..dc800a038d5c9 100644 --- a/scripts/pylib/twister/twisterlib/harness.py +++ b/scripts/pylib/twister/twisterlib/harness.py @@ -353,6 +353,10 @@ def generate_command(self): else: raise PytestHarnessException(f'Support for handler {handler.type_str} not implemented yet') + if handler.type_str != 'device': + for fixture in handler.options.fixture: + command.append(f'--twister-fixture={fixture}') + if handler.options.pytest_args: command.extend(handler.options.pytest_args) if pytest_args_yaml: @@ -410,6 +414,9 @@ def _generate_parameters_for_hardware(self, handler: Handler): if hardware.flash_before: command.append(f'--flash-before={hardware.flash_before}') + for fixture in hardware.fixtures: + command.append(f'--twister-fixture={fixture}') + return command def run_command(self, cmd, timeout): diff --git a/scripts/tests/twister/pytest_integration/test_harness_pytest.py b/scripts/tests/twister/pytest_integration/test_harness_pytest.py index befd384be37b1..898f7e5ababde 100644 --- a/scripts/tests/twister/pytest_integration/test_harness_pytest.py +++ b/scripts/tests/twister/pytest_integration/test_harness_pytest.py @@ -25,6 +25,7 @@ def testinstance() -> TestInstance: testinstance.handler = mock.Mock() testinstance.handler.options = mock.Mock() testinstance.handler.options.verbose = 1 + testinstance.handler.options.fixture = ['fixture1:option1', 'fixture2'] testinstance.handler.options.pytest_args = None testinstance.handler.type_str = 'native' return testinstance @@ -41,7 +42,9 @@ def test_pytest_command(testinstance: TestInstance, device_type): 'samples/hello/pytest', f'--build-dir={testinstance.build_dir}', f'--junit-xml={testinstance.build_dir}/report.xml', - f'--device-type={device_type}' + f'--device-type={device_type}', + '--twister-fixture=fixture1:option1', + '--twister-fixture=fixture2' ] command = pytest_harness.generate_command() diff --git a/scripts/tests/twister/test_harness.py b/scripts/tests/twister/test_harness.py index 6a92a4ffba0c1..019559843d316 100644 --- a/scripts/tests/twister/test_harness.py +++ b/scripts/tests/twister/test_harness.py @@ -345,6 +345,7 @@ def test_pytest__generate_parameters_for_hardware(tmp_path, pty_value, hardware_ hardware.baud = 115200 hardware.runner = "runner" hardware.runner_params = ["--runner-param1", "runner-param2"] + hardware.fixtures = ['fixture1:option1', 'fixture2'] options = handler.options options.west_flash = "args" @@ -386,6 +387,8 @@ def test_pytest__generate_parameters_for_hardware(tmp_path, pty_value, hardware_ assert '--pre-script=pre_script' in command assert '--post-flash-script=post_flash_script' in command assert '--post-script=post_script' in command + assert '--twister-fixture=fixture1:option1' in command + assert '--twister-fixture=fixture2' in command def test__update_command_with_env_dependencies(): From 3eb3c330960d92fef2c69295e816676c81624951 Mon Sep 17 00:00:00 2001 From: Henrik Brix Andersen Date: Wed, 29 May 2024 18:10:32 +0000 Subject: [PATCH 1791/2849] scripts: twister: allow fixtures to contain extra configuration Allow twister fixtures to contain extra information, which can be used for test suite configuration. The extra information can be appended to existing fixtures separated by a colon (i.e. :). This is especially useful for the pytest harness, where a fixture of a given type may need to refer to an instance of a particular piece of host hardware needed by the pytest suite (e.g. a network interface, a UART, or a CAN interface connected to the device under test). Signed-off-by: Henrik Brix Andersen --- doc/develop/test/twister.rst | 4 ++++ scripts/pylib/twister/twisterlib/handlers.py | 2 +- scripts/pylib/twister/twisterlib/testinstance.py | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/doc/develop/test/twister.rst b/doc/develop/test/twister.rst index 3be0132b05cd7..4773a3e3466e2 100644 --- a/doc/develop/test/twister.rst +++ b/doc/develop/test/twister.rst @@ -1082,6 +1082,10 @@ can be used multiple times and all given fixtures will be appended as a list. An given fixtures will be assigned to all boards, this means that all boards set by current twister command can run those testcases which request the same fixtures. +Some fixtures allow for configuration strings to be appended, separated from the +fixture name by a ``:``. Only the fixture name is matched against the fixtures +requested by testcases. + Notes +++++ diff --git a/scripts/pylib/twister/twisterlib/handlers.py b/scripts/pylib/twister/twisterlib/handlers.py index 3a3c8de4cb37e..4a9ed97ea2dbd 100755 --- a/scripts/pylib/twister/twisterlib/handlers.py +++ b/scripts/pylib/twister/twisterlib/handlers.py @@ -456,7 +456,7 @@ def device_is_available(self, instance): dut_found = False for d in self.duts: - if fixture and fixture not in d.fixtures: + if fixture and fixture not in map(lambda f: f.split(sep=':')[0], d.fixtures): continue if d.platform != device or (d.serial is None and d.serial_pty is None): continue diff --git a/scripts/pylib/twister/twisterlib/testinstance.py b/scripts/pylib/twister/twisterlib/testinstance.py index fb0fc1d909b48..b7a46fd5008ac 100644 --- a/scripts/pylib/twister/twisterlib/testinstance.py +++ b/scripts/pylib/twister/twisterlib/testinstance.py @@ -180,7 +180,7 @@ def testsuite_runnable(testsuite, fixtures): # command-line, then we need to run the test, not just build it. fixture = testsuite.harness_config.get('fixture') if fixture: - can_run = fixture in fixtures + can_run = fixture in map(lambda f: f.split(sep=':')[0], fixtures) return can_run From afb2791ccf9ab8e2366dbd881d9abf82dc578c82 Mon Sep 17 00:00:00 2001 From: Henrik Brix Andersen Date: Sat, 1 Jun 2024 21:24:59 +0000 Subject: [PATCH 1792/2849] tests: drivers: can: host: allow specifying context along with fixture Allow specifying the python-can configuration context to use along with the "can" fixture. This opens up for specifying board-specific contexts in the twister hardware map file. Signed-off-by: Henrik Brix Andersen --- tests/drivers/can/host/README.rst | 19 +++++++++++++------ tests/drivers/can/host/pytest/conftest.py | 9 ++++++++- 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/tests/drivers/can/host/README.rst b/tests/drivers/can/host/README.rst index b6a3fcef5c81e..7f8b15936afce 100644 --- a/tests/drivers/can/host/README.rst +++ b/tests/drivers/can/host/README.rst @@ -28,10 +28,17 @@ The Zephyr end of the CAN fixture can be configured as follows: The host end of the CAN fixture can be configured through python-can. Available configuration options depend on the type of host CAN adapter used. The python-can library provides a lot of -flexibility for configuration as decribed in the `python-can configuration`_ page. By default, the -python-can configuration context is not specified, causing python-can to use the default -configuration context. The context can be overridden using the ``--can-context`` test suite argument -(see examples below). +flexibility for configuration as decribed in the `python-can configuration`_ page, all centered +around the concept of a configuration "context. The configuration context for this test suite can be +configured as follows: + +* By default, the python-can configuration context is not specified, causing python-can to use the + default configuration context. +* A specific configuration context can be provided along with the ``can`` fixture separated by a + ``:`` (i.e. specify fixture ``can:zcan0`` to use the ``zcan0`` python-can configuration context). +* The configuration context can be overridden using the ``--can-context`` test suite argument + (i.e. run ``twister`` with the ``--pytest-args=--can-context=zcan0`` argument to use the ``zcan0`` + python-can configuration context). Building and Running ******************** @@ -65,7 +72,7 @@ be launched using Twister: .. code-block:: shell - west twister -v -p native_sim/native/64 -X can -T tests/drivers/can/host/ --pytest-args=--can-context=zcan0 + west twister -v -p native_sim/native/64 -X can:zcan0 -T tests/drivers/can/host/ After the test suite has completed, the virtual SocketCAN interface can be removed again: @@ -107,7 +114,7 @@ Twister. Below is an example for running on the :ref:`lpcxpresso55s36`: .. code-block:: shell - west twister -v -p lpcxpresso55s36/lpc55s36 --device-testing --device-serial /dev/ttyACM0 -X can -T tests/drivers/can/host/ --pytest-args=--can-context=can0 + west twister -v -p lpcxpresso55s36/lpc55s36 --device-testing --device-serial /dev/ttyACM0 -X can:can0 -T tests/drivers/can/host/ After the test suite has completed, the SocketCAN interface can be brought down again: diff --git a/tests/drivers/can/host/pytest/conftest.py b/tests/drivers/can/host/pytest/conftest.py index f7ffe763a69f8..691e39fc497f8 100644 --- a/tests/drivers/can/host/pytest/conftest.py +++ b/tests/drivers/can/host/pytest/conftest.py @@ -23,9 +23,16 @@ def pytest_addoption(parser) -> None: help='Configuration context to use for python-can (default: None)') @pytest.fixture(name='context', scope='session') -def fixture_context(request) -> str: +def fixture_context(request, dut: DeviceAdapter) -> str: """Return the name of the python-can configuration context to use.""" ctx = request.config.getoption('--can-context') + + if ctx is None: + for fixture in dut.device_config.fixtures: + if fixture.startswith('can:'): + ctx = fixture.split(sep=':', maxsplit=1)[1] + break + logger.info('using python-can configuration context "%s"', ctx) return ctx From 9ff5221d236bc727f70009ff41997c689c6e78bf Mon Sep 17 00:00:00 2001 From: Peter Mitsis Date: Fri, 1 Mar 2024 14:44:26 -0500 Subject: [PATCH 1793/2849] kernel: Update IPI usage in k_thread_priority_set() 1. The flagging of IPIs is moved out of k_thread_priority_set() into z_thread_prio_set(). This allows for an IPI to be done for a thread that had its priority bumped due to the handling of priority inheritance from a mutex. 2. k_thread_priority_set()'s check for sched_locked only applies to non-SMP builds that are using the old arch_swap() framework to switch between threads. Incidentally, nearly all calls to flag_ipi() are now performed with sched_spinlock being locked. The only exception is in slice_timeout(). Signed-off-by: Peter Mitsis --- kernel/sched.c | 48 +++++++++++++++++++++++++++++++++++------------- 1 file changed, 35 insertions(+), 13 deletions(-) diff --git a/kernel/sched.c b/kernel/sched.c index 506ad57a141b2..c17efeaf6ef6b 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -348,11 +348,11 @@ static void update_cache(int preempt_ok) #endif /* CONFIG_SMP */ } -static bool thread_active_elsewhere(struct k_thread *thread) +static struct _cpu *thread_active_elsewhere(struct k_thread *thread) { - /* True if the thread is currently running on another CPU. - * There are more scalable designs to answer this question in - * constant time, but this is fine for now. + /* Returns pointer to _cpu if the thread is currently running on + * another CPU. There are more scalable designs to answer this + * question in constant time, but this is fine for now. */ #ifdef CONFIG_SMP int currcpu = _current_cpu->id; @@ -362,12 +362,12 @@ static bool thread_active_elsewhere(struct k_thread *thread) for (int i = 0; i < num_cpus; i++) { if ((i != currcpu) && (_kernel.cpus[i].current == thread)) { - return true; + return &_kernel.cpus[i]; } } #endif /* CONFIG_SMP */ ARG_UNUSED(thread); - return false; + return NULL; } static void ready_thread(struct k_thread *thread) @@ -390,7 +390,7 @@ static void ready_thread(struct k_thread *thread) void z_ready_thread_locked(struct k_thread *thread) { - if (!thread_active_elsewhere(thread)) { + if (thread_active_elsewhere(thread) == NULL) { ready_thread(thread); } } @@ -398,7 +398,7 @@ void z_ready_thread_locked(struct k_thread *thread) void z_ready_thread(struct k_thread *thread) { K_SPINLOCK(&_sched_spinlock) { - if (!thread_active_elsewhere(thread)) { + if (thread_active_elsewhere(thread) == NULL) { ready_thread(thread); } } @@ -466,7 +466,10 @@ static void z_thread_halt(struct k_thread *thread, k_spinlock_key_t key, * halt itself in the IPI. Otherwise it's unscheduled, so we * can clean it up directly. */ - if (thread_active_elsewhere(thread)) { + + struct _cpu *cpu = thread_active_elsewhere(thread); + + if (cpu != NULL) { thread->base.thread_state |= (terminate ? _THREAD_ABORTING : _THREAD_SUSPENDING); #if defined(CONFIG_SMP) && defined(CONFIG_SCHED_IPI_SUPPORTED) @@ -731,19 +734,38 @@ void z_unpend_thread(struct k_thread *thread) bool z_thread_prio_set(struct k_thread *thread, int prio) { bool need_sched = 0; + int old_prio = thread->base.prio; K_SPINLOCK(&_sched_spinlock) { need_sched = z_is_thread_ready(thread); if (need_sched) { - /* Don't requeue on SMP if it's the running thread */ if (!IS_ENABLED(CONFIG_SMP) || z_is_thread_queued(thread)) { dequeue_thread(thread); thread->base.prio = prio; queue_thread(thread); + + if (old_prio > prio) { + flag_ipi(); + } } else { + /* + * This is a running thread on SMP. Update its + * priority, but do not requeue it. An IPI is + * needed if the priority is both being lowered + * and it is running on another CPU. + */ + thread->base.prio = prio; + + struct _cpu *cpu; + + cpu = thread_active_elsewhere(thread); + if ((cpu != NULL) && (old_prio < prio)) { + flag_ipi(); + } } + update_cache(1); } else { thread->base.prio = prio; @@ -1006,8 +1028,8 @@ 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) && (IS_ENABLED(CONFIG_SMP) || + (_current->base.sched_locked == 0U))) { z_reschedule_unlocked(); } } @@ -1219,7 +1241,7 @@ void z_impl_k_wakeup(k_tid_t thread) z_mark_thread_as_not_suspended(thread); - if (!thread_active_elsewhere(thread)) { + if (thread_active_elsewhere(thread) == NULL) { ready_thread(thread); } From d8a4c8a90c725d141219e889af921b56a551f9f0 Mon Sep 17 00:00:00 2001 From: Peter Mitsis Date: Fri, 16 Feb 2024 13:54:47 -0500 Subject: [PATCH 1794/2849] kernel: Add CONFIG_IPI_OPTIMIZE The CONFIG_IPI_OPTIMIZE configuration option allows for the flagging and subsequent signaling of IPIs to be optimized. It does this by making each bit in the kernel's pending_ipi field a flag that indicates whether the corresponding CPU might need an IPI to trigger the scheduling of a new thread on that CPU. When a new thread is made ready, we compare that thread against each of the threads currently executing on the other CPUs. If there is a chance that that thread should preempt the thread on the other CPU then we flag that an IPI is needed for that CPU. That is, a clear bit indicates that the CPU absolutely will not need to reschedule, while a set bit indicates that the target CPU must make that determination for itself. Signed-off-by: Peter Mitsis --- include/zephyr/kernel_structs.h | 4 +-- kernel/Kconfig.smp | 18 +++++++++++ kernel/include/ipi.h | 16 ++++++++-- kernel/ipi.c | 53 ++++++++++++++++++++++++++++++--- kernel/sched.c | 7 +++-- kernel/timeslicing.c | 7 ++--- 6 files changed, 90 insertions(+), 15 deletions(-) diff --git a/include/zephyr/kernel_structs.h b/include/zephyr/kernel_structs.h index baa2046f07c8e..cf7daff9a6cf7 100644 --- a/include/zephyr/kernel_structs.h +++ b/include/zephyr/kernel_structs.h @@ -240,8 +240,8 @@ struct z_kernel { #endif #if defined(CONFIG_SMP) && defined(CONFIG_SCHED_IPI_SUPPORTED) - /* Need to signal an IPI at the next scheduling point */ - bool pending_ipi; + /* Identify CPUs to send IPIs to at the next scheduling point */ + atomic_t pending_ipi; #endif }; diff --git a/kernel/Kconfig.smp b/kernel/Kconfig.smp index 22279270b19f0..04fc01801b3c2 100644 --- a/kernel/Kconfig.smp +++ b/kernel/Kconfig.smp @@ -73,6 +73,24 @@ config TRACE_SCHED_IPI depends on SCHED_IPI_SUPPORTED depends on MP_MAX_NUM_CPUS>1 +config IPI_OPTIMIZE + bool "Optimize IPI delivery" + default n + depends on SCHED_IPI_SUPPORTED && MP_MAX_NUM_CPUS>1 + help + When selected, the kernel will attempt to determine the minimum + set of CPUs that need an IPI to trigger a reschedule in response to + a thread newly made ready for execution. This increases the + computation required at every scheduler operation by a value that is + O(N) in the number of CPUs, and in exchange reduces the number of + interrupts delivered. Which to choose is going to depend on + application behavior. If the architecture also supports directing + IPIs to specific CPUs then this has the potential to signficantly + reduce the number of IPIs (and consequently ISRs) processed by the + system as the number of CPUs increases. If not, the only benefit + would be to not issue any IPIs if the newly readied thread is of + lower priority than all the threads currently executing on other CPUs. + config KERNEL_COHERENCE bool "Place all shared data into coherent memory" depends on ARCH_HAS_COHERENCE diff --git a/kernel/include/ipi.h b/kernel/include/ipi.h index 77105cac16834..b353a676d4624 100644 --- a/kernel/include/ipi.h +++ b/kernel/include/ipi.h @@ -7,13 +7,25 @@ #ifndef ZEPHYR_KERNEL_INCLUDE_IPI_H_ #define ZEPHYR_KERNEL_INCLUDE_IPI_H_ +#include +#include +#include + +#define IPI_ALL_CPUS_MASK ((1 << CONFIG_MP_MAX_NUM_CPUS) - 1) + +#define IPI_CPU_MASK(cpu_id) \ + (IS_ENABLED(CONFIG_IPI_OPTIMIZE) ? BIT(cpu_id) : IPI_ALL_CPUS_MASK) + + /* defined in ipi.c when CONFIG_SMP=y */ #ifdef CONFIG_SMP -void flag_ipi(void); +void flag_ipi(uint32_t ipi_mask); void signal_pending_ipi(void); +atomic_val_t ipi_mask_create(struct k_thread *thread); #else -#define flag_ipi() do { } while (false) +#define flag_ipi(ipi_mask) do { } while (false) #define signal_pending_ipi() do { } while (false) #endif /* CONFIG_SMP */ + #endif /* ZEPHYR_KERNEL_INCLUDE_IPI_H_ */ diff --git a/kernel/ipi.c b/kernel/ipi.c index 99693c0ecbfcf..9985c9485c20b 100644 --- a/kernel/ipi.c +++ b/kernel/ipi.c @@ -13,15 +13,58 @@ extern void z_trace_sched_ipi(void); #endif -void flag_ipi(void) +void flag_ipi(uint32_t ipi_mask) { #if defined(CONFIG_SCHED_IPI_SUPPORTED) if (arch_num_cpus() > 1) { - _kernel.pending_ipi = true; + atomic_or(&_kernel.pending_ipi, (atomic_val_t)ipi_mask); } #endif /* CONFIG_SCHED_IPI_SUPPORTED */ } +/* Create a bitmask of CPUs that need an IPI. Note: sched_spinlock is held. */ +atomic_val_t ipi_mask_create(struct k_thread *thread) +{ + if (!IS_ENABLED(CONFIG_IPI_OPTIMIZE)) { + return (CONFIG_MP_MAX_NUM_CPUS > 1) ? IPI_ALL_CPUS_MASK : 0; + } + + uint32_t ipi_mask = 0; + uint32_t num_cpus = (uint32_t)arch_num_cpus(); + uint32_t id = _current_cpu->id; + struct k_thread *cpu_thread; + bool executable_on_cpu = true; + + for (uint32_t i = 0; i < num_cpus; i++) { + if (id == i) { + continue; + } + + /* + * An IPI absolutely does not need to be sent if ... + * 1. the CPU is not active, or + * 2. can not execute on the target CPU + * ... and might not need to be sent if ... + * 3. the target CPU's active thread is not preemptible, or + * 4. the target CPU's active thread has a higher priority + * (Items 3 & 4 may be overridden by a metaIRQ thread) + */ + +#if defined(CONFIG_SCHED_CPU_MASK) + executable_on_cpu = ((thread->base.cpu_mask & BIT(i)) != 0); +#endif + + cpu_thread = _kernel.cpus[i].current; + if ((cpu_thread != NULL) && + (((z_sched_prio_cmp(cpu_thread, thread) < 0) && + (thread_is_preemptible(cpu_thread))) || + thread_is_metairq(thread)) && executable_on_cpu) { + ipi_mask |= BIT(i); + } + } + + return (atomic_val_t)ipi_mask; +} void signal_pending_ipi(void) { @@ -34,8 +77,10 @@ void signal_pending_ipi(void) */ #if defined(CONFIG_SCHED_IPI_SUPPORTED) if (arch_num_cpus() > 1) { - if (_kernel.pending_ipi) { - _kernel.pending_ipi = false; + uint32_t cpu_bitmap; + + cpu_bitmap = (uint32_t)atomic_clear(&_kernel.pending_ipi); + if (cpu_bitmap != 0) { arch_sched_ipi(); } } diff --git a/kernel/sched.c b/kernel/sched.c index c17efeaf6ef6b..34b256c22a820 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -384,7 +384,8 @@ static void ready_thread(struct k_thread *thread) queue_thread(thread); update_cache(0); - flag_ipi(); + + flag_ipi(ipi_mask_create(thread)); } } @@ -746,7 +747,7 @@ bool z_thread_prio_set(struct k_thread *thread, int prio) queue_thread(thread); if (old_prio > prio) { - flag_ipi(); + flag_ipi(ipi_mask_create(thread)); } } else { /* @@ -762,7 +763,7 @@ bool z_thread_prio_set(struct k_thread *thread, int prio) cpu = thread_active_elsewhere(thread); if ((cpu != NULL) && (old_prio < prio)) { - flag_ipi(); + flag_ipi(IPI_CPU_MASK(cpu->id)); } } diff --git a/kernel/timeslicing.c b/kernel/timeslicing.c index 07ae497c7f91e..be91d9606f51e 100644 --- a/kernel/timeslicing.c +++ b/kernel/timeslicing.c @@ -58,11 +58,10 @@ static void slice_timeout(struct _timeout *timeout) slice_expired[cpu] = true; /* We need an IPI if we just handled a timeslice expiration - * for a different CPU. Ideally this would be able to target - * the specific core, but that's not part of the API yet. + * for a different CPU. */ - if (IS_ENABLED(CONFIG_SMP) && cpu != _current_cpu->id) { - flag_ipi(); + if (cpu != _current_cpu->id) { + flag_ipi(IPI_CPU_MASK(cpu)); } } From 0bcdae2c62f8e08d6e00ff7e34580e26e9ed43aa Mon Sep 17 00:00:00 2001 From: Peter Mitsis Date: Mon, 4 Mar 2024 10:52:24 -0500 Subject: [PATCH 1795/2849] kernel: Add CONFIG_ARCH_HAS_DIRECTED_IPIS Platforms that support IPIs allow them to be broadcast via the new arch_sched_broadcast_ipi() routine (replacing arch_sched_ipi()). Those that also allow IPIs to be directed to specific CPUs may use arch_sched_directed_ipi() to do so. As the kernel has the capability to track which CPUs may need an IPI (see CONFIG_IPI_OPTIMIZE), this commit updates the signalling of tracked IPIs to use the directed version if supported; otherwise they continue to use the broadcast version. Platforms that allow directed IPIs may see a significant reduction in the number of IPI related ISRs when CONFIG_IPI_OPTIMIZE is enabled and the number of CPUs increases. These platforms can be identified by the Kconfig option CONFIG_ARCH_HAS_DIRECTED_IPIS. Signed-off-by: Peter Mitsis --- arch/Kconfig | 11 ++++++++++ arch/arc/core/smp.c | 19 +++++++++++------ arch/arc/include/kernel_arch_func.h | 2 -- arch/arm/core/cortex_a_r/Kconfig | 1 + arch/arm/core/cortex_a_r/smp.c | 17 +++++++++++---- arch/arm64/core/smp.c | 19 ++++++++++++----- arch/riscv/core/smp.c | 11 ++++++++-- arch/x86/core/intel64/smp.c | 2 +- doc/kernel/services/smp/smp.rst | 18 +++++++++------- include/zephyr/arch/arch_interface.h | 12 +++++++++-- kernel/Kconfig.smp | 11 +++++----- kernel/ipi.c | 6 +++++- kernel/sched.c | 6 +++++- soc/espressif/esp32/esp32-mp.c | 10 ++++++++- soc/intel/intel_adsp/ace/multiprocessing.c | 23 ++++++++++++++------- soc/intel/intel_adsp/cavs/multiprocessing.c | 16 ++++++++++++-- tests/kernel/smp/src/main.c | 10 ++++----- 17 files changed, 141 insertions(+), 53 deletions(-) diff --git a/arch/Kconfig b/arch/Kconfig index f3e4f14dfbc89..f1295eec38e87 100644 --- a/arch/Kconfig +++ b/arch/Kconfig @@ -24,6 +24,7 @@ config ARC imply XIP select ARCH_HAS_THREAD_LOCAL_STORAGE select ARCH_SUPPORTS_ROM_START + select ARCH_HAS_DIRECTED_IPIS help ARC architecture @@ -50,6 +51,7 @@ config ARM64 select USE_SWITCH_SUPPORTED select IRQ_OFFLOAD_NESTED if IRQ_OFFLOAD select BARRIER_OPERATIONS_ARCH + select ARCH_HAS_DIRECTED_IPIS help ARM64 (AArch64) architecture @@ -115,6 +117,7 @@ config RISCV select USE_SWITCH_SUPPORTED select USE_SWITCH select SCHED_IPI_SUPPORTED if SMP + select ARCH_HAS_DIRECTED_IPIS select BARRIER_OPERATIONS_BUILTIN imply XIP help @@ -129,6 +132,7 @@ config XTENSA select ARCH_HAS_CODE_DATA_RELOCATION select ARCH_HAS_TIMING_FUNCTIONS select ARCH_MEM_DOMAIN_DATA if USERSPACE + select ARCH_HAS_DIRECTED_IPIS help Xtensa architecture @@ -746,6 +750,13 @@ config ARCH_HAS_RESERVED_PAGE_FRAMES memory mappings. The architecture will need to implement arch_reserved_pages_update(). +config ARCH_HAS_DIRECTED_IPIS + bool + help + This hidden configuration should be selected by the architecture if + it has an implementation for arch_sched_directed_ipi() which allows + for IPIs to be directed to specific CPUs. + config CPU_HAS_DCACHE bool help diff --git a/arch/arc/core/smp.c b/arch/arc/core/smp.c index 9f8ee38a4a105..aa12623db8014 100644 --- a/arch/arc/core/smp.c +++ b/arch/arc/core/smp.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -130,21 +131,27 @@ static void sched_ipi_handler(const void *unused) z_sched_ipi(); } -/* arch implementation of sched_ipi */ -void arch_sched_ipi(void) +void arch_sched_directed_ipi(uint32_t cpu_bitmap) { - uint32_t i; + unsigned int i; + unsigned int num_cpus = arch_num_cpus(); - /* broadcast sched_ipi request to other cores + /* Send sched_ipi request to other cores * if the target is current core, hardware will ignore it */ - unsigned int num_cpus = arch_num_cpus(); for (i = 0U; i < num_cpus; i++) { - z_arc_connect_ici_generate(i); + if ((cpu_bitmap & BIT(i)) != 0) { + z_arc_connect_ici_generate(i); + } } } +void arch_sched_broadcast_ipi(void) +{ + arch_sched_directed_ipi(IPI_ALL_CPUS_MASK); +} + int arch_smp_init(void) { struct arc_connect_bcr bcr; diff --git a/arch/arc/include/kernel_arch_func.h b/arch/arc/include/kernel_arch_func.h index 65a497e02d078..ca382a274f4b1 100644 --- a/arch/arc/include/kernel_arch_func.h +++ b/arch/arc/include/kernel_arch_func.h @@ -64,8 +64,6 @@ extern void z_arc_userspace_enter(k_thread_entry_t user_entry, void *p1, extern void z_arc_fatal_error(unsigned int reason, const struct arch_esf *esf); -extern void arch_sched_ipi(void); - extern void z_arc_switch(void *switch_to, void **switched_from); static inline void arch_switch(void *switch_to, void **switched_from) diff --git a/arch/arm/core/cortex_a_r/Kconfig b/arch/arm/core/cortex_a_r/Kconfig index 3ec57cc408e1b..4095a277c6138 100644 --- a/arch/arm/core/cortex_a_r/Kconfig +++ b/arch/arm/core/cortex_a_r/Kconfig @@ -131,6 +131,7 @@ config AARCH32_ARMV8_R bool select ATOMIC_OPERATIONS_BUILTIN select SCHED_IPI_SUPPORTED if SMP + select ARCH_HAS_DIRECTED_IPIS help This option signifies the use of an ARMv8-R AArch32 processor implementation. diff --git a/arch/arm/core/cortex_a_r/smp.c b/arch/arm/core/cortex_a_r/smp.c index 9e06730f91396..379b7663d016b 100644 --- a/arch/arm/core/cortex_a_r/smp.c +++ b/arch/arm/core/cortex_a_r/smp.c @@ -7,6 +7,7 @@ #include #include #include +#include #include "boot.h" #include "zephyr/cache.h" #include "zephyr/kernel/thread_stack.h" @@ -210,7 +211,7 @@ void arch_secondary_cpu_init(void) #ifdef CONFIG_SMP -static void broadcast_ipi(unsigned int ipi) +static void send_ipi(unsigned int ipi, uint32_t cpu_bitmap) { uint32_t mpidr = MPIDR_TO_CORE(GET_MPIDR()); @@ -220,6 +221,10 @@ static void broadcast_ipi(unsigned int ipi) unsigned int num_cpus = arch_num_cpus(); for (int i = 0; i < num_cpus; i++) { + if ((cpu_bitmap & BIT(i)) == 0) { + continue; + } + uint32_t target_mpidr = cpu_map[i]; uint8_t aff0; @@ -239,10 +244,14 @@ void sched_ipi_handler(const void *unused) z_sched_ipi(); } -/* arch implementation of sched_ipi */ -void arch_sched_ipi(void) +void arch_sched_broadcast_ipi(void) +{ + send_ipi(SGI_SCHED_IPI, IPI_ALL_CPUS_MASK); +} + +void arch_sched_directed_ipi(uint32_t cpu_bitmap) { - broadcast_ipi(SGI_SCHED_IPI); + send_ipi(SGI_SCHED_IPI, cpu_bitmap); } int arch_smp_init(void) diff --git a/arch/arm64/core/smp.c b/arch/arm64/core/smp.c index 8777c400766fc..31dfcf337e421 100644 --- a/arch/arm64/core/smp.c +++ b/arch/arm64/core/smp.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -180,7 +181,7 @@ void arch_secondary_cpu_init(int cpu_num) #ifdef CONFIG_SMP -static void broadcast_ipi(unsigned int ipi) +static void send_ipi(unsigned int ipi, uint32_t cpu_bitmap) { uint64_t mpidr = MPIDR_TO_CORE(GET_MPIDR()); @@ -190,6 +191,10 @@ static void broadcast_ipi(unsigned int ipi) unsigned int num_cpus = arch_num_cpus(); for (int i = 0; i < num_cpus; i++) { + if ((cpu_bitmap & BIT(i)) == 0) { + continue; + } + uint64_t target_mpidr = cpu_map[i]; uint8_t aff0; @@ -209,10 +214,14 @@ void sched_ipi_handler(const void *unused) z_sched_ipi(); } -/* arch implementation of sched_ipi */ -void arch_sched_ipi(void) +void arch_sched_broadcast_ipi(void) +{ + send_ipi(SGI_SCHED_IPI, IPI_ALL_CPUS_MASK); +} + +void arch_sched_directed_ipi(uint32_t cpu_bitmap) { - broadcast_ipi(SGI_SCHED_IPI); + send_ipi(SGI_SCHED_IPI, cpu_bitmap); } #ifdef CONFIG_USERSPACE @@ -232,7 +241,7 @@ void mem_cfg_ipi_handler(const void *unused) void z_arm64_mem_cfg_ipi(void) { - broadcast_ipi(SGI_MMCFG_IPI); + send_ipi(SGI_MMCFG_IPI, IPI_ALL_CPUS_MASK); } #endif diff --git a/arch/riscv/core/smp.c b/arch/riscv/core/smp.c index 68147f8880a65..b5b94aac25cf0 100644 --- a/arch/riscv/core/smp.c +++ b/arch/riscv/core/smp.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -86,14 +87,15 @@ static atomic_val_t cpu_pending_ipi[CONFIG_MP_MAX_NUM_CPUS]; #define IPI_SCHED 0 #define IPI_FPU_FLUSH 1 -void arch_sched_ipi(void) +void arch_sched_directed_ipi(uint32_t cpu_bitmap) { unsigned int key = arch_irq_lock(); unsigned int id = _current_cpu->id; unsigned int num_cpus = arch_num_cpus(); for (unsigned int i = 0; i < num_cpus; i++) { - if (i != id && _kernel.cpus[i].arch.online) { + if ((i != id) && _kernel.cpus[i].arch.online && + ((cpu_bitmap & BIT(i)) != 0)) { atomic_set_bit(&cpu_pending_ipi[i], IPI_SCHED); MSIP(_kernel.cpus[i].arch.hartid) = 1; } @@ -102,6 +104,11 @@ void arch_sched_ipi(void) arch_irq_unlock(key); } +void arch_sched_broadcast_ipi(void) +{ + arch_sched_directed_ipi(IPI_ALL_CPUS_MASK); +} + #ifdef CONFIG_FPU_SHARING void arch_flush_fpu_ipi(unsigned int cpu) { diff --git a/arch/x86/core/intel64/smp.c b/arch/x86/core/intel64/smp.c index a73ba9c8f38c3..b0232f2198413 100644 --- a/arch/x86/core/intel64/smp.c +++ b/arch/x86/core/intel64/smp.c @@ -34,7 +34,7 @@ int arch_smp_init(void) * it is not clear exactly how/where/why to abstract this, as it * assumes the use of a local APIC (but there's no other mechanism). */ -void arch_sched_ipi(void) +void arch_sched_broadcast_ipi(void) { z_loapic_ipi(0, LOAPIC_ICR_IPI_OTHERS, CONFIG_SCHED_IPI_VECTOR); } diff --git a/doc/kernel/services/smp/smp.rst b/doc/kernel/services/smp/smp.rst index ca1e0149ad55e..4b178432bd559 100644 --- a/doc/kernel/services/smp/smp.rst +++ b/doc/kernel/services/smp/smp.rst @@ -180,13 +180,17 @@ handle the newly-runnable load. So where possible, Zephyr SMP architectures should implement an interprocessor interrupt. The current framework is very simple: the -architecture provides a :c:func:`arch_sched_ipi` call, which when invoked -will flag an interrupt on all CPUs (except the current one, though -that is allowed behavior) which will then invoke the :c:func:`z_sched_ipi` -function implemented in the scheduler. The expectation is that these -APIs will evolve over time to encompass more functionality -(e.g. cross-CPU calls), and that the scheduler-specific calls here -will be implemented in terms of a more general framework. +architecture provides at least a :c:func:`arch_sched_broadcast_ipi` call, +which when invoked will flag an interrupt on all CPUs (except the current one, +though that is allowed behavior). If the architecture supports directed IPIs +(see :kconfig:option:`CONFIG_ARCH_HAS_DIRECTED_IPIS`), then the +architecture also provides a :c:func:`arch_sched_directed_ipi` call, which +when invoked will flag an interrupt on the specified CPUs. When an interrupt is +flagged on the CPUs, the :c:func:`z_sched_ipi` function implmented in the +scheduler will get invoked on those CPUs. The expectation is that these +APIs will evolve over time to encompass more functionality (e.g. cross-CPU +calls), and that the scheduler-specific calls here will be implemented in +terms of a more general framework. Note that not all SMP architectures will have a usable IPI mechanism (either missing, or just undocumented/unimplemented). In those cases diff --git a/include/zephyr/arch/arch_interface.h b/include/zephyr/arch/arch_interface.h index 797a60bbaa58c..d7c33e511ce50 100644 --- a/include/zephyr/arch/arch_interface.h +++ b/include/zephyr/arch/arch_interface.h @@ -494,10 +494,18 @@ static inline uint32_t arch_proc_id(void); /** * Broadcast an interrupt to all CPUs * - * This will invoke z_sched_ipi() on other CPUs in the system. + * This will invoke z_sched_ipi() on all other CPUs in the system. */ -void arch_sched_ipi(void); +void arch_sched_broadcast_ipi(void); +/** + * Direct IPIs to the specified CPUs + * + * This will invoke z_sched_ipi() on the CPUs identified by @a cpu_bitmap. + * + * @param cpu_bitmap A bitmap indicating which CPUs need the IPI + */ +void arch_sched_directed_ipi(uint32_t cpu_bitmap); int arch_smp_init(void); diff --git a/kernel/Kconfig.smp b/kernel/Kconfig.smp index 04fc01801b3c2..da83d1624e060 100644 --- a/kernel/Kconfig.smp +++ b/kernel/Kconfig.smp @@ -56,12 +56,11 @@ config MP_MAX_NUM_CPUS config SCHED_IPI_SUPPORTED bool help - True if the architecture supports a call to - arch_sched_ipi() to broadcast an interrupt that will call - z_sched_ipi() on other CPUs in the system. Required for - k_thread_abort() to operate with reasonable latency - (otherwise we might have to wait for the other thread to - take an interrupt, which can be arbitrarily far in the + True if the architecture supports a call to arch_sched_broadcast_ipi() + to broadcast an interrupt that will call z_sched_ipi() on other CPUs + in the system. Required for k_thread_abort() to operate with + reasonable latency (otherwise we might have to wait for the other + thread to take an interrupt, which can be arbitrarily far in the future). config TRACE_SCHED_IPI diff --git a/kernel/ipi.c b/kernel/ipi.c index 9985c9485c20b..ee01c4594251c 100644 --- a/kernel/ipi.c +++ b/kernel/ipi.c @@ -81,7 +81,11 @@ void signal_pending_ipi(void) cpu_bitmap = (uint32_t)atomic_clear(&_kernel.pending_ipi); if (cpu_bitmap != 0) { - arch_sched_ipi(); +#ifdef CONFIG_ARCH_HAS_DIRECTED_IPIS + arch_sched_directed_ipi(cpu_bitmap); +#else + arch_sched_broadcast_ipi(); +#endif } } #endif /* CONFIG_SCHED_IPI_SUPPORTED */ diff --git a/kernel/sched.c b/kernel/sched.c index 34b256c22a820..67e5645bc6f24 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -474,7 +474,11 @@ static void z_thread_halt(struct k_thread *thread, k_spinlock_key_t key, thread->base.thread_state |= (terminate ? _THREAD_ABORTING : _THREAD_SUSPENDING); #if defined(CONFIG_SMP) && defined(CONFIG_SCHED_IPI_SUPPORTED) - arch_sched_ipi(); +#ifdef CONFIG_ARCH_HAS_DIRECTED_IPIS + arch_sched_directed_ipi(IPI_CPU_MASK(cpu->id)); +#else + arch_sched_broadcast_ipi(); +#endif #endif if (arch_is_in_isr()) { thread_halt_spin(thread, key); diff --git a/soc/espressif/esp32/esp32-mp.c b/soc/espressif/esp32/esp32-mp.c index c380df6c8b77a..ca2de23e1e8b8 100644 --- a/soc/espressif/esp32/esp32-mp.c +++ b/soc/espressif/esp32/esp32-mp.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -290,10 +291,12 @@ void arch_cpu_start(int cpu_num, k_thread_stack_t *stack, int sz, smp_log("ESP32: APPCPU initialized"); } -void arch_sched_ipi(void) +void arch_sched_directed_ipi(uint32_t cpu_bitmap) { const int core_id = esp_core_id(); + ARG_UNUSED(cpu_bitmap); + if (core_id == 0) { DPORT_WRITE_PERI_REG(DPORT_CPU_INTR_FROM_CPU_0_REG, DPORT_CPU_INTR_FROM_CPU_0); } else { @@ -301,6 +304,11 @@ void arch_sched_ipi(void) } } +void arch_sched_broadcast_ipi(void) +{ + arch_sched_directed_ipi(IPI_ALL_CPUS_MASK); +} + IRAM_ATTR bool arch_cpu_active(int cpu_num) { return cpus_active[cpu_num]; diff --git a/soc/intel/intel_adsp/ace/multiprocessing.c b/soc/intel/intel_adsp/ace/multiprocessing.c index 68b8693a520d4..1c9b3fa3d3225 100644 --- a/soc/intel/intel_adsp/ace/multiprocessing.c +++ b/soc/intel/intel_adsp/ace/multiprocessing.c @@ -21,6 +21,7 @@ #include #include #include +#include #define CORE_POWER_CHECK_NUM 128 @@ -209,7 +210,7 @@ void soc_mp_startup(uint32_t cpu) #ifndef CONFIG_XTENSA_MMU ALWAYS_INLINE #endif -static void send_ipi(uint32_t msg) +static void send_ipi(uint32_t msg, uint32_t cpu_bitmap) { uint32_t curr = arch_proc_id(); @@ -217,24 +218,30 @@ static void send_ipi(uint32_t msg) unsigned int num_cpus = arch_num_cpus(); for (int core = 0; core < num_cpus; core++) { - if (core != curr && soc_cpus_active[core]) { + if ((core != curr) && soc_cpus_active[core] && + ((cpu_bitmap & BIT(core)) != 0)) { IDC[core].agents[1].ipc.idr = msg | INTEL_ADSP_IPC_BUSY; } } } -void arch_sched_ipi(void) -{ - send_ipi(0); -} - #if defined(CONFIG_XTENSA_MMU) && (CONFIG_MP_MAX_NUM_CPUS > 1) void xtensa_mmu_tlb_ipi(void) { - send_ipi(IPI_TLB_FLUSH); + send_ipi(IPI_TLB_FLUSH, IPI_ALL_CPUS_MASK); } #endif +void arch_sched_broadcast_ipi(void) +{ + send_ipi(0, IPI_ALL_CPUS_MASK); +} + +void arch_sched_directed_ipi(uint32_t cpu_bitmap) +{ + send_ipi(0, cpu_bitmap); +} + #if CONFIG_MP_MAX_NUM_CPUS > 1 int soc_adsp_halt_cpu(int id) { diff --git a/soc/intel/intel_adsp/cavs/multiprocessing.c b/soc/intel/intel_adsp/cavs/multiprocessing.c index 2a38f20355da0..d87cd435e5759 100644 --- a/soc/intel/intel_adsp/cavs/multiprocessing.c +++ b/soc/intel/intel_adsp/cavs/multiprocessing.c @@ -8,6 +8,7 @@ #include #include #include +#include /* IDC power up message to the ROM firmware. This isn't documented * anywhere, it's basically just a magic number (except the high bit, @@ -121,18 +122,29 @@ void soc_start_core(int cpu_num) IDC[curr_cpu].core[cpu_num].itc = IDC_MSG_POWER_UP; } -void arch_sched_ipi(void) +static void send_ipi(uint32_t cpu_bitmap) { uint32_t curr = arch_proc_id(); unsigned int num_cpus = arch_num_cpus(); for (int c = 0; c < num_cpus; c++) { - if (c != curr && soc_cpus_active[c]) { + if ((c != curr) && soc_cpus_active[c] && + ((cpu_bitmap & BIT(c)) != 0)) { IDC[curr].core[c].itc = BIT(31); } } } +void arch_sched_broadcast_ipi(void) +{ + send_ipi(IPI_ALL_CPUS_MASK); +} + +void arch_sched_directed_ipi(uint32_t cpu_bitmap) +{ + send_ipi(cpu_bitmap); +} + void idc_isr(const void *param) { ARG_UNUSED(param); diff --git a/tests/kernel/smp/src/main.c b/tests/kernel/smp/src/main.c index f73a1dfdbbb6e..7f556793e670c 100644 --- a/tests/kernel/smp/src/main.c +++ b/tests/kernel/smp/src/main.c @@ -695,8 +695,8 @@ void z_trace_sched_ipi(void) * - To verify architecture layer provides a mechanism to issue an interprocessor * interrupt to all other CPUs in the system that calls the scheduler IPI. * We simply add a hook in z_sched_ipi(), in order to check if it has been - * called once in another CPU except the caller, when arch_sched_ipi() is - * called. + * called once in another CPU except the caller, when arch_sched_broadcast_ipi() + * is called. * * Testing techniques: * - Interface testing, function and block box testing, @@ -711,7 +711,7 @@ void z_trace_sched_ipi(void) * * Test Procedure: * -# In main thread, given a global variable sched_ipi_has_called equaled zero. - * -# Call arch_sched_ipi() then sleep for 100ms. + * -# Call arch_sched_broadcast_ipi() then sleep for 100ms. * -# In z_sched_ipi() handler, increment the sched_ipi_has_called. * -# In main thread, check the sched_ipi_has_called is not equaled to zero. * -# Repeat step 1 to 4 for 3 times. @@ -727,7 +727,7 @@ void z_trace_sched_ipi(void) * - This test using for the platform that support SMP, in our current scenario * , only x86_64 and arc supported. * - * @see arch_sched_ipi() + * @see arch_sched_broadcast_ipi() */ #ifdef CONFIG_SCHED_IPI_SUPPORTED ZTEST(smp, test_smp_ipi) @@ -741,7 +741,7 @@ ZTEST(smp, test_smp_ipi) for (int i = 0; i < 3 ; i++) { /* issue a sched ipi to tell other CPU to run thread */ sched_ipi_has_called = 0; - arch_sched_ipi(); + arch_sched_broadcast_ipi(); /* Need to wait longer than we think, loaded CI * systems need to wait for host scheduling to run the From 1753a0dabee33d704f8291e3451647f0d7beb1dc Mon Sep 17 00:00:00 2001 From: Peter Mitsis Date: Mon, 4 Mar 2024 16:01:49 -0500 Subject: [PATCH 1796/2849] manifest: optional: Update revision for arch_sched_ipi() Updates the sof revision. This is needed for it to pick up a change to the arch_sched_ipi() which has been renamed to arch_sched_broadcast_ipi(). Signed-off-by: Peter Mitsis --- submanifests/optional.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/submanifests/optional.yaml b/submanifests/optional.yaml index 35f5d93116769..a6a9048d17f4e 100644 --- a/submanifests/optional.yaml +++ b/submanifests/optional.yaml @@ -34,7 +34,7 @@ manifest: groups: - optional - name: sof - revision: a44758883f3f6cfb6c67b19bc76fcb01f77ca50b + revision: 3f1716b0da7a48358bc265586b90b2252745c14c path: modules/audio/sof remote: upstream groups: From 48285cb6b88173ddf6d8ad619b39c4f3cc35f177 Mon Sep 17 00:00:00 2001 From: Peter Mitsis Date: Thu, 28 Mar 2024 10:57:49 -0400 Subject: [PATCH 1797/2849] tests: Add IPI_OPTIMIZE tests Adds several tests to verify that IPIs can be appropriately targeted to specific CPUs. Signed-off-by: Peter Mitsis --- tests/kernel/ipi_optimize/CMakeLists.txt | 12 + .../qemu_cortex_a53_qemu_cortex_a53_smp.conf | 4 + ...emu_cortex_a53_qemu_cortex_a53_smp.overlay | 19 + tests/kernel/ipi_optimize/prj.conf | 5 + tests/kernel/ipi_optimize/src/main.c | 475 ++++++++++++++++++ tests/kernel/ipi_optimize/testcase.yaml | 6 + 6 files changed, 521 insertions(+) create mode 100644 tests/kernel/ipi_optimize/CMakeLists.txt create mode 100644 tests/kernel/ipi_optimize/boards/qemu_cortex_a53_qemu_cortex_a53_smp.conf create mode 100644 tests/kernel/ipi_optimize/boards/qemu_cortex_a53_qemu_cortex_a53_smp.overlay create mode 100644 tests/kernel/ipi_optimize/prj.conf create mode 100644 tests/kernel/ipi_optimize/src/main.c create mode 100644 tests/kernel/ipi_optimize/testcase.yaml diff --git a/tests/kernel/ipi_optimize/CMakeLists.txt b/tests/kernel/ipi_optimize/CMakeLists.txt new file mode 100644 index 0000000000000..f32de519289c3 --- /dev/null +++ b/tests/kernel/ipi_optimize/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) + +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/ipi_optimize/boards/qemu_cortex_a53_qemu_cortex_a53_smp.conf b/tests/kernel/ipi_optimize/boards/qemu_cortex_a53_qemu_cortex_a53_smp.conf new file mode 100644 index 0000000000000..f0ee34b467edd --- /dev/null +++ b/tests/kernel/ipi_optimize/boards/qemu_cortex_a53_qemu_cortex_a53_smp.conf @@ -0,0 +1,4 @@ +# Copyright (c) 2022 Carlo Caione +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_MP_MAX_NUM_CPUS=4 diff --git a/tests/kernel/ipi_optimize/boards/qemu_cortex_a53_qemu_cortex_a53_smp.overlay b/tests/kernel/ipi_optimize/boards/qemu_cortex_a53_qemu_cortex_a53_smp.overlay new file mode 100644 index 0000000000000..5bb497069dd8f --- /dev/null +++ b/tests/kernel/ipi_optimize/boards/qemu_cortex_a53_qemu_cortex_a53_smp.overlay @@ -0,0 +1,19 @@ +/* Copyright 2022 Carlo Caione + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + cpus { + cpu@2 { + device_type = "cpu"; + compatible = "arm,cortex-a53"; + reg = <2>; + }; + + cpu@3 { + device_type = "cpu"; + compatible = "arm,cortex-a53"; + reg = <3>; + }; + }; +}; diff --git a/tests/kernel/ipi_optimize/prj.conf b/tests/kernel/ipi_optimize/prj.conf new file mode 100644 index 0000000000000..f337c89ff5bb4 --- /dev/null +++ b/tests/kernel/ipi_optimize/prj.conf @@ -0,0 +1,5 @@ +CONFIG_ZTEST=y +CONFIG_SMP=y +CONFIG_TRACE_SCHED_IPI=y +CONFIG_IPI_OPTIMIZE=y +CONFIG_SYS_CLOCK_TICKS_PER_SEC=50 diff --git a/tests/kernel/ipi_optimize/src/main.c b/tests/kernel/ipi_optimize/src/main.c new file mode 100644 index 0000000000000..029b79b6d3a85 --- /dev/null +++ b/tests/kernel/ipi_optimize/src/main.c @@ -0,0 +1,475 @@ +/* + * Copyright (c) 2024 Intel Corporation. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include + +#define STACK_SIZE (1024 + CONFIG_TEST_EXTRA_STACK_SIZE) + +#define NUM_THREADS (CONFIG_MP_MAX_NUM_CPUS - 1) + +#define DELAY_FOR_IPIS 200 + +static struct k_thread thread[NUM_THREADS]; +static struct k_thread alt_thread; + +static bool alt_thread_created; + +static K_THREAD_STACK_ARRAY_DEFINE(stack, NUM_THREADS, STACK_SIZE); +static K_THREAD_STACK_DEFINE(alt_stack, STACK_SIZE); + +static uint32_t ipi_count[CONFIG_MP_MAX_NUM_CPUS]; +static struct k_spinlock ipilock; +static atomic_t busy_started; +static volatile bool alt_thread_done; + +static K_SEM_DEFINE(sem, 0, 1); + +void z_trace_sched_ipi(void) +{ + k_spinlock_key_t key; + + key = k_spin_lock(&ipilock); + ipi_count[_current_cpu->id]++; + k_spin_unlock(&ipilock, key); +} + +static void clear_ipi_counts(void) +{ + k_spinlock_key_t key; + + key = k_spin_lock(&ipilock); + memset(ipi_count, 0, sizeof(ipi_count)); + k_spin_unlock(&ipilock, key); +} + +static void get_ipi_counts(uint32_t *set, size_t n_elem) +{ + k_spinlock_key_t key; + + key = k_spin_lock(&ipilock); + memcpy(set, ipi_count, n_elem * sizeof(*set)); + k_spin_unlock(&ipilock, key); +} + +static void busy_thread_entry(void *p1, void *p2, void *p3) +{ + int key; + uint32_t id; + + key = arch_irq_lock(); + id = _current_cpu->id; + arch_irq_unlock(key); + + atomic_or(&busy_started, BIT(id)); + + while (1) { + } +} + +static bool wait_until_busy_threads_ready(uint32_t id) +{ + uint32_t all; + uint32_t value; + unsigned int i; + + all = IPI_ALL_CPUS_MASK ^ BIT(id); + for (i = 0; i < 10; i++) { + k_busy_wait(1000); + + value = (uint32_t)atomic_get(&busy_started); + if (value == all) { + break; + } + } + + return (i < 10); +} + +static void pending_thread_entry(void *p1, void *p2, void *p3) +{ + int key; + + k_sem_take(&sem, K_FOREVER); + + while (!alt_thread_done) { + key = arch_irq_lock(); + arch_spin_relax(); + arch_irq_unlock(key); + } +} + +static void alt_thread_create(int priority, const char *desc) +{ + k_thread_create(&alt_thread, alt_stack, STACK_SIZE, + pending_thread_entry, NULL, NULL, NULL, + priority, 0, K_NO_WAIT); + alt_thread_created = true; + + /* Verify alt_thread is pending */ + + k_busy_wait(10000); + zassert_true(z_is_thread_pending(&alt_thread), + "%s priority thread has not pended.\n", desc); +} + +uint32_t busy_threads_create(int priority) +{ + unsigned int i; + uint32_t id; + int key; + + atomic_clear(&busy_started); + + for (i = 0; i < NUM_THREADS; i++) { + k_thread_create(&thread[i], stack[i], STACK_SIZE, + busy_thread_entry, NULL, NULL, NULL, + priority, 0, K_NO_WAIT); + } + + /* Align to tick boundary to minimize probability of timer ISRs */ + + k_sleep(K_TICKS(1)); + key = arch_irq_lock(); + id = _current_cpu->id; + arch_irq_unlock(key); + + /* + * Spin until all busy threads are ready. It is assumed that as this + * thread and the busy threads are cooperative that they will not be + * rescheduled to execute on a different CPU. + */ + + zassert_true(wait_until_busy_threads_ready(id), + "1 or more 'busy threads' not ready.\n"); + + return id; +} + +void busy_threads_priority_set(int priority, int delta) +{ + unsigned int i; + + for (i = 0; i < NUM_THREADS; i++) { + k_thread_priority_set(&thread[i], priority); + priority += delta; + } +} + +/** + * Verify that arch_sched_broadcast_ipi() broadcasts IPIs as expected. + */ +ZTEST(ipi, test_arch_sched_broadcast_ipi) +{ + uint32_t set[CONFIG_MP_MAX_NUM_CPUS]; + uint32_t id; + int priority; + unsigned int j; + + priority = k_thread_priority_get(k_current_get()); + + id = busy_threads_create(priority - 1); + + /* Broadcast the IPI. All other CPUs ought to receive and process it */ + + clear_ipi_counts(); + arch_sched_broadcast_ipi(); + k_busy_wait(DELAY_FOR_IPIS); + get_ipi_counts(set, CONFIG_MP_MAX_NUM_CPUS); + + for (j = 0; j < CONFIG_MP_MAX_NUM_CPUS; j++) { + if (id == j) { + zassert_true(set[j] == 0, + "Broadcast-Expected 0, got %u\n", + set[j]); + } else { + zassert_true(set[j] == 1, + "Broadcast-Expected 1, got %u\n", + set[j]); + } + } +} + +#ifdef CONFIG_ARCH_HAS_DIRECTED_IPIS +/** + * Verify that arch_sched_directed_ipi() directs IPIs as expected. + */ +ZTEST(ipi, test_arch_sched_directed_ipi) +{ + uint32_t set[CONFIG_MP_MAX_NUM_CPUS]; + uint32_t id; + int priority; + unsigned int j; + + priority = k_thread_priority_get(k_current_get()); + + id = busy_threads_create(priority - 1); + + /* + * Send an IPI to each CPU, one at a time. Verify that only the + * targeted CPU received the IPI. + */ + for (unsigned int i = 0; i < CONFIG_MP_MAX_NUM_CPUS; i++) { + if (i == id) { + continue; + } + + clear_ipi_counts(); + arch_sched_directed_ipi(BIT(i)); + k_busy_wait(DELAY_FOR_IPIS); + get_ipi_counts(set, CONFIG_MP_MAX_NUM_CPUS); + + for (j = 0; j < CONFIG_MP_MAX_NUM_CPUS; j++) { + if (i == j) { + zassert_true(set[j] == 1, + "Direct-Expected 1, got %u\n", + set[j]); + } else { + zassert_true(set[j] == 0, + "Direct-Expected 0, got %u\n", + set[j]); + } + } + } +} +#endif + +/** + * Verify that waking a thread whose priority is lower than any other + * currently executing thread does not result in any IPIs being sent. + */ +ZTEST(ipi, test_low_thread_wakes_no_ipis) +{ + uint32_t set[CONFIG_MP_MAX_NUM_CPUS]; + uint32_t id; + int priority; + unsigned int i; + + priority = k_thread_priority_get(k_current_get()); + atomic_clear(&busy_started); + + alt_thread_create(5, "Low"); + + id = busy_threads_create(priority - 1); + + /* + * Lower the priority of the busy threads now that we know that they + * have started. As this is expected to generate IPIs, busy wait for + * some small amount of time to give them time to be processed. + */ + + busy_threads_priority_set(0, 0); + k_busy_wait(DELAY_FOR_IPIS); + + /* + * Low priority thread is pended. Current thread is cooperative. + * Other CPUs are executing preemptible threads @ priority 0. + */ + + clear_ipi_counts(); + k_sem_give(&sem); + k_busy_wait(DELAY_FOR_IPIS); + get_ipi_counts(set, CONFIG_MP_MAX_NUM_CPUS); + + zassert_true(z_is_thread_ready(&alt_thread), + "Low priority thread is not ready.\n"); + + alt_thread_done = true; + + for (i = 0; i < CONFIG_MP_MAX_NUM_CPUS; i++) { + zassert_true(set[i] == 0, + "CPU %u unexpectedly received IPI.\n", i); + } +} + +/** + * Verify that waking a thread whose priority is higher than all currently + * executing threads results in the proper IPIs being sent and processed. + */ +ZTEST(ipi, test_high_thread_wakes_some_ipis) +{ + uint32_t set[CONFIG_MP_MAX_NUM_CPUS]; + uint32_t id; + int priority; + unsigned int i; + + priority = k_thread_priority_get(k_current_get()); + atomic_clear(&busy_started); + + alt_thread_create(priority - 1 - NUM_THREADS, "High"); + + id = busy_threads_create(priority - 1); + + /* + * Lower the priority of the busy threads now that we know that they + * have started and are busy waiting. As this is expected to generate + * IPIs, busy wait for some small amount of time to give them time to + * be processed. + */ + + busy_threads_priority_set(0, 1); + k_busy_wait(DELAY_FOR_IPIS); + + /* + * High priority thread is pended. Current thread is cooperative. + * Other CPUs are executing preemptible threads. + */ + + clear_ipi_counts(); + k_sem_give(&sem); + k_busy_wait(DELAY_FOR_IPIS); + get_ipi_counts(set, CONFIG_MP_MAX_NUM_CPUS); + + zassert_true(z_is_thread_ready(&alt_thread), + "High priority thread is not ready.\n"); + + alt_thread_done = true; + + for (i = 0; i < CONFIG_MP_MAX_NUM_CPUS; i++) { + if (i == id) { + continue; + } + + zassert_true(set[i] == 1, "CPU%u got %u IPIs", i, set[i]); + } + + zassert_true(set[id] == 0, "Current CPU got %u IPI(s).\n", set[id]); +} + +/** + * Verify that lowering the priority of an active thread results in an IPI. + * If directed IPIs are enabled, then only the CPU executing that active + * thread ought to receive the IPI. Otherwise if IPIs are broadcast, then all + * other CPUs save the current CPU ought to receive IPIs. + */ +ZTEST(ipi, test_thread_priority_set_lower) +{ + uint32_t set[CONFIG_MP_MAX_NUM_CPUS]; + uint32_t id; + int priority; + unsigned int i; + + priority = k_thread_priority_get(k_current_get()); + + id = busy_threads_create(priority - 1); + + clear_ipi_counts(); + k_thread_priority_set(&thread[0], priority); + k_busy_wait(DELAY_FOR_IPIS); + get_ipi_counts(set, CONFIG_MP_MAX_NUM_CPUS); + + for (i = 0; i < CONFIG_MP_MAX_NUM_CPUS; i++) { + if (i == id) { + continue; + } + +#ifdef CONFIG_ARCH_HAS_DIRECTED_IPIS + unsigned int j; + + for (j = 0; j < NUM_THREADS; j++) { + if (_kernel.cpus[i].current == &thread[j]) { + break; + } + } + + zassert_true(j < NUM_THREADS, + "CPU%u not executing expected thread\n", i); + + if (j == 0) { + zassert_true(set[i] == 1, "CPU%u got %u IPIs.\n", + i, set[i]); + } else { + zassert_true(set[i] == 0, "CPU%u got %u IPI(s).\n", + i, set[i]); + } +#else + zassert_true(set[i] == 1, "CPU%u got %u IPIs", i, set[i]); +#endif + } + + zassert_true(set[id] == 0, "Current CPU got %u IPI(s).\n", set[id]); +} + +/* + * Verify that IPIs are not sent to CPUs that are executing cooperative + * threads. + */ +ZTEST(ipi, test_thread_coop_no_ipis) +{ + uint32_t set[CONFIG_MP_MAX_NUM_CPUS]; + uint32_t id; + int priority; + unsigned int i; + + priority = k_thread_priority_get(k_current_get()); + atomic_clear(&busy_started); + + alt_thread_create(priority - 1 - NUM_THREADS, "High"); + + id = busy_threads_create(priority - 1); + + /* + * High priority thread is pended. Current thread is cooperative. + * Other CPUs are executing lower priority cooperative threads. + */ + + clear_ipi_counts(); + k_sem_give(&sem); + k_busy_wait(DELAY_FOR_IPIS); + get_ipi_counts(set, CONFIG_MP_MAX_NUM_CPUS); + + zassert_true(z_is_thread_ready(&alt_thread), + "High priority thread is not ready.\n"); + + alt_thread_done = true; + + for (i = 0; i < CONFIG_MP_MAX_NUM_CPUS; i++) { + zassert_true(set[i] == 0, "CPU%u got %u IPIs", i, set[i]); + } +} + +static void *ipi_tests_setup(void) +{ + /* + * Sleep a bit to guarantee that all CPUs enter an idle thread + * from which they can exit correctly to run the test. + */ + + k_sleep(K_MSEC(20)); + + return NULL; +} + +static void cleanup_threads(void *fixture) +{ + unsigned int i; + + ARG_UNUSED(fixture); + + /* + * Ensure that spawned busy threads are aborted before + * proceeding to the next test. + */ + + for (i = 0; i < NUM_THREADS; i++) { + k_thread_abort(&thread[i]); + } + + /* Ensure alt_thread ,if it was created, also gets aborted */ + + if (alt_thread_created) { + k_thread_abort(&alt_thread); + } + alt_thread_created = false; + + alt_thread_done = false; +} + +ZTEST_SUITE(ipi, NULL, ipi_tests_setup, NULL, cleanup_threads, NULL); diff --git a/tests/kernel/ipi_optimize/testcase.yaml b/tests/kernel/ipi_optimize/testcase.yaml new file mode 100644 index 0000000000000..49227a720cbac --- /dev/null +++ b/tests/kernel/ipi_optimize/testcase.yaml @@ -0,0 +1,6 @@ +tests: + kernel.ipi_optimize.smp: + tags: + - kernel + - smp + filter: (CONFIG_MP_MAX_NUM_CPUS > 1) From ee92645e9ceb9f8ea2c5389bb5a665dc777edd26 Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Tue, 4 Jun 2024 12:01:48 -0700 Subject: [PATCH 1798/2849] doc: relnotes/3.7: Add info about CVE-2024-3332 Information about CVE-2024-3332 in release notes. 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 024922e924d76..4cdaedb5a8197 100644 --- a/doc/releases/release-notes-3.7.rst +++ b/doc/releases/release-notes-3.7.rst @@ -31,6 +31,8 @@ https://docs.zephyrproject.org/latest/security/vulnerabilities.html * CVE-2024-3077 `Zephyr project bug tracker GHSA-gmfv-4vfh-2mh8 `_ +* CVE-2024-3332 Under embargo until 2024-07-01 + * CVE-2024-4785: Under embargo until 2024-08-07 API Changes From 0b3d7eb3e7bb15c840fdea7808be81a33d3cae25 Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Tue, 4 Jun 2024 12:03:48 -0700 Subject: [PATCH 1799/2849] doc: vulnerabilities: Info about CVE-2024-3332 Add an entry for CVE-2024-3332. 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 77f39e79ea1f2..5cd2e300ad7db 100644 --- a/doc/security/vulnerabilities.rst +++ b/doc/security/vulnerabilities.rst @@ -1717,6 +1717,11 @@ This has been fixed in main for v3.7.0 - `PR 69396 fix for main `_ +CVE-2024-3332 +------------- + +Under embargo until 2024-07-01 + CVE-2024-4785 ------------- From 9d9576b442cedeee985e2482bec31ac4f9282597 Mon Sep 17 00:00:00 2001 From: Yong Cong Sin Date: Thu, 30 May 2024 23:44:04 +0800 Subject: [PATCH 1800/2849] subsys/debug: relocate gdbstub stuff into its folder Move the gdbstub files into the gdbstub folder, and relocated its Kconfig as well. Signed-off-by: Yong Cong Sin --- subsys/debug/CMakeLists.txt | 9 +--- subsys/debug/Kconfig | 43 +------------------ subsys/debug/gdbstub/CMakeLists.txt | 11 +++++ subsys/debug/gdbstub/Kconfig | 45 ++++++++++++++++++++ subsys/debug/{ => gdbstub}/gdbstub.c | 0 subsys/debug/{ => gdbstub}/gdbstub_backend.h | 0 6 files changed, 59 insertions(+), 49 deletions(-) create mode 100644 subsys/debug/gdbstub/CMakeLists.txt create mode 100644 subsys/debug/gdbstub/Kconfig rename subsys/debug/{ => gdbstub}/gdbstub.c (100%) rename subsys/debug/{ => gdbstub}/gdbstub_backend.h (100%) diff --git a/subsys/debug/CMakeLists.txt b/subsys/debug/CMakeLists.txt index 200e3bcb38662..2e855563b0d91 100644 --- a/subsys/debug/CMakeLists.txt +++ b/subsys/debug/CMakeLists.txt @@ -20,14 +20,9 @@ add_subdirectory_ifdef( coredump ) -zephyr_sources_ifdef( +add_subdirectory_ifdef( CONFIG_GDBSTUB - gdbstub.c - ) - -zephyr_sources_ifdef( - CONFIG_GDBSTUB_SERIAL_BACKEND - gdbstub/gdbstub_backend_serial.c + gdbstub ) zephyr_sources_ifdef( diff --git a/subsys/debug/Kconfig b/subsys/debug/Kconfig index dc9da0efc3081..db27f1e2b26fa 100644 --- a/subsys/debug/Kconfig +++ b/subsys/debug/Kconfig @@ -422,48 +422,7 @@ config DEBUG_THREAD_INFO rsource "coredump/Kconfig" endmenu -config GDBSTUB - bool "GDB remote serial protocol support [EXPERIMENTAL]" - depends on ARCH_HAS_GDBSTUB - select UART_USE_RUNTIME_CONFIGURE - select EXPERIMENTAL - help - This option enable support the target using GDB, or any other - application that supports GDB protocol. - -if GDBSTUB - -choice - prompt "GDB backend" - -config GDBSTUB_SERIAL_BACKEND - bool "Use serial backend" - depends on SERIAL - help - Use serial as backend for GDB - -config GDBSTUB_CUSTOM_BACKEND - bool "Use a custom backend" - help - Use a custom backend for GDB - -endchoice - -config GDBSTUB_BUF_SZ - int "GDB backend send/receive buffer size (in bytes)" - default 256 - help - This specifies the size (in bytes) of the send/receive buffer - for GDB backend. This needs to be big enough to hold one - full GDB packet at a time. - -config GDBSTUB_TRACE - bool "GDB backend extra logging" - help - Enable extra debug logging for the GDB backend, including - breakpoint interrupts and remote commands it receives. - -endif +rsource "gdbstub/Kconfig" config SEGGER_DEBUGMON bool "Use Segger's J-Link debug monitor implementation" diff --git a/subsys/debug/gdbstub/CMakeLists.txt b/subsys/debug/gdbstub/CMakeLists.txt new file mode 100644 index 0000000000000..1f5220558bc0c --- /dev/null +++ b/subsys/debug/gdbstub/CMakeLists.txt @@ -0,0 +1,11 @@ +# Copyright (c) 2020 Intel Corporation. +# SPDX-License-Identifier: Apache-2.0 + +zephyr_sources( + gdbstub.c + ) + +zephyr_sources_ifdef( + CONFIG_GDBSTUB_SERIAL_BACKEND + gdbstub_backend_serial.c + ) diff --git a/subsys/debug/gdbstub/Kconfig b/subsys/debug/gdbstub/Kconfig new file mode 100644 index 0000000000000..358643a589b8e --- /dev/null +++ b/subsys/debug/gdbstub/Kconfig @@ -0,0 +1,45 @@ +# Copyright (c) 2020 Intel Corporation. +# SPDX-License-Identifier: Apache-2.0 + +menuconfig GDBSTUB + bool "GDB remote serial protocol support [EXPERIMENTAL]" + depends on ARCH_HAS_GDBSTUB + select UART_USE_RUNTIME_CONFIGURE + select EXPERIMENTAL + help + This option enable support the target using GDB, or any other + application that supports GDB protocol. + +if GDBSTUB + +choice + prompt "GDB backend" + +config GDBSTUB_SERIAL_BACKEND + bool "Use serial backend" + depends on SERIAL + help + Use serial as backend for GDB + +config GDBSTUB_CUSTOM_BACKEND + bool "Use a custom backend" + help + Use a custom backend for GDB + +endchoice + +config GDBSTUB_BUF_SZ + int "GDB backend send/receive buffer size (in bytes)" + default 256 + help + This specifies the size (in bytes) of the send/receive buffer + for GDB backend. This needs to be big enough to hold one + full GDB packet at a time. + +config GDBSTUB_TRACE + bool "GDB backend extra logging" + help + Enable extra debug logging for the GDB backend, including + breakpoint interrupts and remote commands it receives. + +endif # GDBSTUB diff --git a/subsys/debug/gdbstub.c b/subsys/debug/gdbstub/gdbstub.c similarity index 100% rename from subsys/debug/gdbstub.c rename to subsys/debug/gdbstub/gdbstub.c diff --git a/subsys/debug/gdbstub_backend.h b/subsys/debug/gdbstub/gdbstub_backend.h similarity index 100% rename from subsys/debug/gdbstub_backend.h rename to subsys/debug/gdbstub/gdbstub_backend.h From 3cb2c04fc1dd364e964058c02356e13efa43d501 Mon Sep 17 00:00:00 2001 From: Yong Cong Sin Date: Thu, 30 May 2024 23:47:04 +0800 Subject: [PATCH 1801/2849] subsys/debug: relocate symtab Kconfig Move the symtab Kcofig into the symtab folder. Signed-off-by: Yong Cong Sin --- subsys/debug/Kconfig | 11 +---------- subsys/debug/symtab/Kconfig | 12 ++++++++++++ 2 files changed, 13 insertions(+), 10 deletions(-) create mode 100644 subsys/debug/symtab/Kconfig diff --git a/subsys/debug/Kconfig b/subsys/debug/Kconfig index db27f1e2b26fa..d8922ce99eab7 100644 --- a/subsys/debug/Kconfig +++ b/subsys/debug/Kconfig @@ -369,16 +369,6 @@ 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 @@ -420,6 +410,7 @@ config DEBUG_THREAD_INFO for debugger RTOS plugins to determine the state of running threads. rsource "coredump/Kconfig" +rsource "symtab/Kconfig" endmenu rsource "gdbstub/Kconfig" diff --git a/subsys/debug/symtab/Kconfig b/subsys/debug/symtab/Kconfig new file mode 100644 index 0000000000000..8094c2dc07767 --- /dev/null +++ b/subsys/debug/symtab/Kconfig @@ -0,0 +1,12 @@ +# Copyright (c) 2024 Meta Platforms +# SPDX-License-Identifier: Apache-2.0 + +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. From c74445d6943b09b150dd730fa942b07e2756c23b Mon Sep 17 00:00:00 2001 From: Stephanos Ioannidis Date: Sat, 1 Jun 2024 09:58:17 +0900 Subject: [PATCH 1802/2849] ci: doc-build: Reduce parallel job count to 14 This commit reduces the parallel job count for building the documentation from the default value of 16 (i.e. `-j auto` aka. the vCPU count) to 14 because the total available RAM in the runners is 32GiB and each sphinx-build process may use more than 2GiB of RAM, which can lead to out-of-memory conditions. Note that the HTML doc build process was parallelised prior to this change in spite of the lack of `-j auto` in the CI workflow because the default `SPHINXOPTS` includes `-j auto` and only `SPHINXOPTS_EXTRA` was specified -- this commit explicitly adds the `SPHINXOPTS` for it with the default value specified in doc/CMakeLists.txt to make the job count configurable while ensuring the previous behaviour is preserved. Signed-off-by: Stephanos Ioannidis --- .github/workflows/doc-build.yml | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/.github/workflows/doc-build.yml b/.github/workflows/doc-build.yml index e55b4bea247bc..d7c1edd6a6591 100644 --- a/.github/workflows/doc-build.yml +++ b/.github/workflows/doc-build.yml @@ -18,6 +18,9 @@ env: # so we fetch that through pip. CMAKE_VERSION: 3.20.5 DOXYGEN_VERSION: 1.9.6 + # Job count is set to 2 less than the vCPU count of 16 because the total available RAM is 32GiB + # and each sphinx-build process may use more than 2GiB of RAM. + JOB_COUNT: 14 jobs: doc-file-check: @@ -132,7 +135,11 @@ jobs: else DOC_TARGET="html" fi - DOC_TAG=${DOC_TAG} SPHINXOPTS_EXTRA="-q -t publish" make -C doc ${DOC_TARGET} + + DOC_TAG=${DOC_TAG} \ + SPHINXOPTS="-j ${JOB_COUNT} -W --keep-going -T" \ + SPHINXOPTS_EXTRA="-q -t publish" \ + make -C doc ${DOC_TARGET} # API documentation coverage python3 -m coverxygen --xml-dir doc/_build/html/doxygen/xml/ --src-dir include/ --output doc-coverage.info @@ -245,7 +252,10 @@ jobs: DOC_TAG="development" fi - DOC_TAG=${DOC_TAG} SPHINXOPTS="-q -j auto" LATEXMKOPTS="-quiet -halt-on-error" make -C doc pdf + DOC_TAG=${DOC_TAG} \ + SPHINXOPTS="-q -j ${JOB_COUNT}" \ + LATEXMKOPTS="-quiet -halt-on-error" \ + make -C doc pdf - name: upload-build if: always() From c3d7b1c978f8b462dcbdda998dbaefa981b3d089 Mon Sep 17 00:00:00 2001 From: Sven Ginka Date: Sat, 1 Jun 2024 18:57:52 +0200 Subject: [PATCH 1803/2849] soc: atmel: sam: Add invalidate d-cache at z_arm_platform_init Before that fix, the SOC was unable to boot properly. Starting turned directly into z_arm_usage_fault(). Fixes zephyrproject-rtos#73485 Signed-off-by: Sven Ginka --- soc/atmel/sam/same70/soc.c | 1 + soc/atmel/sam/samv71/soc.c | 1 + 2 files changed, 2 insertions(+) diff --git a/soc/atmel/sam/same70/soc.c b/soc/atmel/sam/same70/soc.c index ba3a44e875af8..4db92e8cebfbc 100644 --- a/soc/atmel/sam/same70/soc.c +++ b/soc/atmel/sam/same70/soc.c @@ -122,6 +122,7 @@ void z_arm_platform_init(void) * sys_cache*-functions can enable them, if requested by the * configuration. */ + SCB_InvalidateDCache(); SCB_DisableDCache(); /* diff --git a/soc/atmel/sam/samv71/soc.c b/soc/atmel/sam/samv71/soc.c index c1b58bc126e81..e5129e30e80d2 100644 --- a/soc/atmel/sam/samv71/soc.c +++ b/soc/atmel/sam/samv71/soc.c @@ -119,6 +119,7 @@ void z_arm_platform_init(void) * sys_cache*-functions can enable them, if requested by the * configuration. */ + SCB_InvalidateDCache(); SCB_DisableDCache(); /* From b8f7ae5a4ce9eab650723317e1453f3687509939 Mon Sep 17 00:00:00 2001 From: Stephanos Ioannidis Date: Sat, 1 Jun 2024 16:17:36 +0900 Subject: [PATCH 1804/2849] ci: Switch to CI image v0.26.13 This commit updates the CI workflows to use the CI image v0.26.13, which includes Zephyr SDK 0.16.8. Signed-off-by: Stephanos Ioannidis --- .github/workflows/bsim-tests.yaml | 2 +- .github/workflows/clang.yaml | 2 +- .github/workflows/codecov.yaml | 2 +- .github/workflows/errno.yml | 2 +- .github/workflows/footprint-tracking.yml | 2 +- .github/workflows/twister.yaml | 4 ++-- .github/workflows/twister_tests_blackbox.yml | 2 +- 7 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/bsim-tests.yaml b/.github/workflows/bsim-tests.yaml index 52d384e92fdf3..d75e759499d4c 100644 --- a/.github/workflows/bsim-tests.yaml +++ b/.github/workflows/bsim-tests.yaml @@ -34,7 +34,7 @@ jobs: runs-on: group: zephyr-runner-v2-linux-x64-4xlarge container: - image: ghcr.io/zephyrproject-rtos/ci-repo-cache:v0.26.11.20240324 + image: ghcr.io/zephyrproject-rtos/ci-repo-cache:v0.26.13.20240601 options: '--entrypoint /bin/bash' env: ZEPHYR_TOOLCHAIN_VARIANT: zephyr diff --git a/.github/workflows/clang.yaml b/.github/workflows/clang.yaml index 77a36a0c9317e..95d68acf47a49 100644 --- a/.github/workflows/clang.yaml +++ b/.github/workflows/clang.yaml @@ -12,7 +12,7 @@ jobs: runs-on: group: zephyr-runner-v2-linux-x64-4xlarge container: - image: ghcr.io/zephyrproject-rtos/ci-repo-cache:v0.26.11.20240324 + image: ghcr.io/zephyrproject-rtos/ci-repo-cache:v0.26.13.20240601 options: '--entrypoint /bin/bash' strategy: fail-fast: false diff --git a/.github/workflows/codecov.yaml b/.github/workflows/codecov.yaml index 19c50aba9b4b9..8bf4d2289ebd3 100644 --- a/.github/workflows/codecov.yaml +++ b/.github/workflows/codecov.yaml @@ -14,7 +14,7 @@ jobs: runs-on: group: zephyr-runner-v2-linux-x64-4xlarge container: - image: ghcr.io/zephyrproject-rtos/ci-repo-cache:v0.26.11.20240324 + image: ghcr.io/zephyrproject-rtos/ci-repo-cache:v0.26.13.20240601 options: '--entrypoint /bin/bash' strategy: fail-fast: false diff --git a/.github/workflows/errno.yml b/.github/workflows/errno.yml index 593fe916deb69..b1f7e6f4e6250 100644 --- a/.github/workflows/errno.yml +++ b/.github/workflows/errno.yml @@ -10,7 +10,7 @@ jobs: check-errno: runs-on: ubuntu-22.04 container: - image: ghcr.io/zephyrproject-rtos/ci:v0.26.11 + image: ghcr.io/zephyrproject-rtos/ci:v0.26.13 steps: - name: Apply container owner mismatch workaround diff --git a/.github/workflows/footprint-tracking.yml b/.github/workflows/footprint-tracking.yml index ede9f52602eed..5b39c94a9c009 100644 --- a/.github/workflows/footprint-tracking.yml +++ b/.github/workflows/footprint-tracking.yml @@ -26,7 +26,7 @@ jobs: group: zephyr-runner-v2-linux-x64-4xlarge if: github.repository_owner == 'zephyrproject-rtos' container: - image: ghcr.io/zephyrproject-rtos/ci-repo-cache:v0.26.11.20240324 + image: ghcr.io/zephyrproject-rtos/ci-repo-cache:v0.26.13.20240601 options: '--entrypoint /bin/bash' strategy: fail-fast: false diff --git a/.github/workflows/twister.yaml b/.github/workflows/twister.yaml index 40f9fe04c2dde..c2e44c830d05d 100644 --- a/.github/workflows/twister.yaml +++ b/.github/workflows/twister.yaml @@ -25,7 +25,7 @@ jobs: runs-on: group: zephyr-runner-v2-linux-x64-4xlarge container: - image: ghcr.io/zephyrproject-rtos/ci-repo-cache:v0.26.11.20240324 + image: ghcr.io/zephyrproject-rtos/ci-repo-cache:v0.26.13.20240601 options: '--entrypoint /bin/bash' outputs: subset: ${{ steps.output-services.outputs.subset }} @@ -129,7 +129,7 @@ jobs: needs: twister-build-prep if: needs.twister-build-prep.outputs.size != 0 container: - image: ghcr.io/zephyrproject-rtos/ci-repo-cache:v0.26.11.20240324 + image: ghcr.io/zephyrproject-rtos/ci-repo-cache:v0.26.13.20240601 options: '--entrypoint /bin/bash' strategy: fail-fast: false diff --git a/.github/workflows/twister_tests_blackbox.yml b/.github/workflows/twister_tests_blackbox.yml index edec21e28d393..1176afc729907 100644 --- a/.github/workflows/twister_tests_blackbox.yml +++ b/.github/workflows/twister_tests_blackbox.yml @@ -24,7 +24,7 @@ jobs: python-version: ['3.10', '3.11', '3.12'] os: [ubuntu-22.04] container: - image: ghcr.io/zephyrproject-rtos/ci:v0.26.11 + image: ghcr.io/zephyrproject-rtos/ci:v0.26.13 steps: - name: Apply Container Owner Mismatch Workaround From 7975db44b201f25f57a0943176c3239ea8220fd8 Mon Sep 17 00:00:00 2001 From: Stephanos Ioannidis Date: Sat, 1 Jun 2024 16:18:51 +0900 Subject: [PATCH 1805/2849] SDK_VERSION: Use Zephyr SDK 0.16.8 This commit updates SDK_VERSION to point to the Zephyr SDK 0.16.8 release. Signed-off-by: Stephanos Ioannidis --- SDK_VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SDK_VERSION b/SDK_VERSION index e35e56114f44c..74aaa3f38cfe8 100644 --- a/SDK_VERSION +++ b/SDK_VERSION @@ -1 +1 @@ -0.16.5-1 +0.16.8 From d07b13dbc203be8066e9f840edf917dd8969ce00 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Chru=C5=9Bci=C5=84ski?= Date: Wed, 29 May 2024 16:13:31 +0200 Subject: [PATCH 1806/2849] drivers: serial: nrfx_uarte: Allow use of legacy shim on RISCV cores MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Legacy shim takes less flash so it should be a first choice on cores with less code memory (like RISCV cores on nrf54h20). Adding new instances support to the legacy shim. Signed-off-by: Krzysztof Chruściński --- drivers/serial/Kconfig.nrfx | 3 +- drivers/serial/Kconfig.nrfx_uart_instance | 1 + drivers/serial/uart_nrfx_uarte.c | 71 +++++++++++------------ 3 files changed, 38 insertions(+), 37 deletions(-) diff --git a/drivers/serial/Kconfig.nrfx b/drivers/serial/Kconfig.nrfx index 158731404e63e..930dd00e3d869 100644 --- a/drivers/serial/Kconfig.nrfx +++ b/drivers/serial/Kconfig.nrfx @@ -31,7 +31,8 @@ config UART_NRFX_UARTE config UART_NRFX_UARTE_LEGACY_SHIM bool "Legacy UARTE shim" depends on UART_NRFX_UARTE - depends on !SOC_SERIES_NRF54LX && !SOC_SERIES_NRF54HX + depends on !SOC_SERIES_NRF54LX + depends on RISCV || !SOC_SERIES_NRF54HX # New shim takes more ROM. Until it is fixed use legacy shim. default y diff --git a/drivers/serial/Kconfig.nrfx_uart_instance b/drivers/serial/Kconfig.nrfx_uart_instance index 71b25dbeba07f..7f135d2f997c5 100644 --- a/drivers/serial/Kconfig.nrfx_uart_instance +++ b/drivers/serial/Kconfig.nrfx_uart_instance @@ -54,6 +54,7 @@ config UART_$(nrfx_uart_num)_NRF_HW_ASYNC depends on HAS_HW_NRF_UARTE$(nrfx_uart_num) depends on UART_ASYNC_API depends on UART_NRFX_UARTE_LEGACY_SHIM + depends on HAS_HW_NRF_PPI || HAS_HW_NRF_DPPIC select NRFX_PPI if HAS_HW_NRF_PPI select NRFX_DPPI if HAS_HW_NRF_DPPIC help diff --git a/drivers/serial/uart_nrfx_uarte.c b/drivers/serial/uart_nrfx_uarte.c index cc2c9b90594d8..d2b36017051b7 100644 --- a/drivers/serial/uart_nrfx_uarte.c +++ b/drivers/serial/uart_nrfx_uarte.c @@ -25,12 +25,12 @@ LOG_MODULE_REGISTER(uart_nrfx_uarte, CONFIG_UART_LOG_LEVEL); #include /* Generalize PPI or DPPI channel management */ -#if defined(CONFIG_HAS_HW_NRF_PPI) +#if defined(PPI_PRESENT) #include #define gppi_channel_t nrf_ppi_channel_t #define gppi_channel_alloc nrfx_ppi_channel_alloc #define gppi_channel_enable nrfx_ppi_channel_enable -#elif defined(CONFIG_HAS_HW_NRF_DPPIC) +#elif defined(DPPI_PRESENT) #include #define gppi_channel_t uint8_t #define gppi_channel_alloc nrfx_dppi_channel_alloc @@ -39,39 +39,49 @@ LOG_MODULE_REGISTER(uart_nrfx_uarte, CONFIG_UART_LOG_LEVEL); #error "No PPI or DPPI" #endif +/* Execute macro f(x) for all instances. */ +#define UARTE_FOR_EACH_INSTANCE(f, sep, off_code) \ + NRFX_FOREACH_PRESENT(UARTE, f, sep, off_code, _) -#if (defined(CONFIG_HAS_HW_NRF_UARTE0) && \ - defined(CONFIG_UART_0_INTERRUPT_DRIVEN)) || \ - (defined(CONFIG_HAS_HW_NRF_UARTE1) && \ - defined(CONFIG_UART_1_INTERRUPT_DRIVEN)) || \ - (defined(CONFIG_HAS_HW_NRF_UARTE2) && \ - defined(CONFIG_UART_2_INTERRUPT_DRIVEN)) || \ - (defined(CONFIG_HAS_HW_NRF_UARTE3) && \ - defined(CONFIG_UART_3_INTERRUPT_DRIVEN)) +/* Determine if any instance is using interrupt driven API. */ +#define IS_INT_DRIVEN(unused, prefix, i, _) \ + (IS_ENABLED(CONFIG_HAS_HW_NRF_UARTE##prefix##i) && \ + IS_ENABLED(CONFIG_UART_##prefix##i##_INTERRUPT_DRIVEN)) + +#if UARTE_FOR_EACH_INSTANCE(IS_INT_DRIVEN, (||), (0)) #define UARTE_INTERRUPT_DRIVEN 1 #endif -#if (defined(CONFIG_HAS_HW_NRF_UARTE0) && !defined(CONFIG_UART_0_ASYNC)) || \ - (defined(CONFIG_HAS_HW_NRF_UARTE1) && !defined(CONFIG_UART_1_ASYNC)) || \ - (defined(CONFIG_HAS_HW_NRF_UARTE2) && !defined(CONFIG_UART_2_ASYNC)) || \ - (defined(CONFIG_HAS_HW_NRF_UARTE3) && !defined(CONFIG_UART_3_ASYNC)) +/* Determine if any instance is not using asynchronous API. */ +#define IS_NOT_ASYNC(unused, prefix, i, _) \ + (IS_ENABLED(CONFIG_HAS_HW_NRF_UARTE##prefix##i) && \ + !IS_ENABLED(CONFIG_UART_##prefix##i##_ASYNC)) + +#if UARTE_FOR_EACH_INSTANCE(IS_NOT_ASYNC, (||), (0)) #define UARTE_ANY_NONE_ASYNC 1 #endif -#if (defined(CONFIG_HAS_HW_NRF_UARTE0) && defined(CONFIG_UART_0_ASYNC)) || \ - (defined(CONFIG_HAS_HW_NRF_UARTE1) && defined(CONFIG_UART_1_ASYNC)) || \ - (defined(CONFIG_HAS_HW_NRF_UARTE2) && defined(CONFIG_UART_2_ASYNC)) || \ - (defined(CONFIG_HAS_HW_NRF_UARTE3) && defined(CONFIG_UART_3_ASYNC)) +/* Determine if any instance is using asynchronous API. */ +#define IS_ASYNC(unused, prefix, i, _) \ + (IS_ENABLED(CONFIG_HAS_HW_NRF_UARTE##prefix##i) && \ + IS_ENABLED(CONFIG_UART_##prefix##i##_ASYNC)) + +#if UARTE_FOR_EACH_INSTANCE(IS_ASYNC, (||), (0)) #define UARTE_ANY_ASYNC 1 #endif -#if defined(CONFIG_UART_0_NRF_HW_ASYNC) || defined(CONFIG_UART_1_NRF_HW_ASYNC) || \ - defined(CONFIG_UART_2_NRF_HW_ASYNC) || defined(CONFIG_UART_3_NRF_HW_ASYNC) +/* Determine if any instance is using asynchronous API with HW byte counting. */ +#define IS_HW_ASYNC(unused, prefix, i, _) IS_ENABLED(CONFIG_UART_##prefix##i##_NRF_HW_ASYNC) + +#if UARTE_FOR_EACH_INSTANCE(IS_HW_ASYNC, (||), (0)) #define UARTE_HW_ASYNC 1 #endif -#if defined(CONFIG_UART_0_ENHANCED_POLL_OUT) || defined(CONFIG_UART_1_ENHANCED_POLL_OUT) || \ - defined(CONFIG_UART_2_ENHANCED_POLL_OUT) || defined(CONFIG_UART_3_ENHANCED_POLL_OUT) +/* Determine if any instance is using enhanced poll_out feature. */ +#define IS_ENHANCED_POLL_OUT(unused, prefix, i, _) \ + IS_ENABLED(CONFIG_UART_##prefix##i##_ENHANCED_POLL_OUT) + +#if UARTE_FOR_EACH_INSTANCE(IS_ENHANCED_POLL_OUT, (||), (0)) #define UARTE_ENHANCED_POLL_OUT 1 #endif @@ -2074,18 +2084,7 @@ static int uarte_nrfx_pm_action(const struct device *dev, DT_PHANDLE(UARTE(idx), memory_regions)))))), \ ()) -#ifdef CONFIG_HAS_HW_NRF_UARTE0 -UART_NRF_UARTE_DEVICE(0); -#endif +#define COND_UART_NRF_UARTE_DEVICE(unused, prefix, i, _) \ + IF_ENABLED(CONFIG_HAS_HW_NRF_UARTE##prefix##i, (UART_NRF_UARTE_DEVICE(prefix##i);)) -#ifdef CONFIG_HAS_HW_NRF_UARTE1 -UART_NRF_UARTE_DEVICE(1); -#endif - -#ifdef CONFIG_HAS_HW_NRF_UARTE2 -UART_NRF_UARTE_DEVICE(2); -#endif - -#ifdef CONFIG_HAS_HW_NRF_UARTE3 -UART_NRF_UARTE_DEVICE(3); -#endif +UARTE_FOR_EACH_INSTANCE(COND_UART_NRF_UARTE_DEVICE, (), ()) From 955dbf47f8ca8c0151807df88eefa9b1c910852b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Karol=20Laso=C5=84czyk?= Date: Fri, 31 May 2024 12:26:45 +0200 Subject: [PATCH 1807/2849] tests: nordic: Enable I2C tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add i2c to supported peripheral to enable i2c testing. Signed-off-by: Karol Lasończyk --- boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpuapp.yaml | 1 + tests/boards/nrf/i2c/i2c_slave/testcase.yaml | 7 ++++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpuapp.yaml b/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpuapp.yaml index 85d28db349467..b0dff4bb9f783 100644 --- a/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpuapp.yaml +++ b/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpuapp.yaml @@ -15,6 +15,7 @@ supported: - can - counter - gpio + - i2c - pwm - spi - watchdog diff --git a/tests/boards/nrf/i2c/i2c_slave/testcase.yaml b/tests/boards/nrf/i2c/i2c_slave/testcase.yaml index 1309b60146ec6..818502b689087 100644 --- a/tests/boards/nrf/i2c/i2c_slave/testcase.yaml +++ b/tests/boards/nrf/i2c/i2c_slave/testcase.yaml @@ -5,8 +5,13 @@ tests: harness: ztest harness_config: fixture: i2c_loopback - platform_allow: nrf52840dk/nrf52840 nrf5340dk/nrf5340/cpuapp nrf54l15pdk/nrf54l15/cpuapp + platform_allow: + - nrf52840dk/nrf52840 + - nrf5340dk/nrf5340/cpuapp + - nrf54l15pdk/nrf54l15/cpuapp + - nrf54h20dk/nrf54h20/cpuapp integration_platforms: - nrf52840dk/nrf52840 - nrf5340dk/nrf5340/cpuapp - nrf54l15pdk/nrf54l15/cpuapp + - nrf54h20dk/nrf54h20/cpuapp From 87dbd81168c9e705098b842e0cc0d9f739f377e7 Mon Sep 17 00:00:00 2001 From: Valerio Setti Date: Tue, 28 May 2024 15:47:37 +0200 Subject: [PATCH 1808/2849] tfm: do not enable all PSA features by default when BUILD_WITH_TFM Do not enable all PSA features by default when BUILD_WITH_TFM Signed-off-by: Valerio Setti --- modules/trusted-firmware-m/Kconfig.tfm | 1 - samples/tfm_integration/psa_crypto/prj.conf | 5 +++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/modules/trusted-firmware-m/Kconfig.tfm b/modules/trusted-firmware-m/Kconfig.tfm index 5e8511947cfff..b90390f3d043e 100644 --- a/modules/trusted-firmware-m/Kconfig.tfm +++ b/modules/trusted-firmware-m/Kconfig.tfm @@ -33,7 +33,6 @@ 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 diff --git a/samples/tfm_integration/psa_crypto/prj.conf b/samples/tfm_integration/psa_crypto/prj.conf index dde93b26bd28f..0abda9534232f 100644 --- a/samples/tfm_integration/psa_crypto/prj.conf +++ b/samples/tfm_integration/psa_crypto/prj.conf @@ -29,6 +29,11 @@ CONFIG_MBEDTLS_USER_CONFIG_ENABLE=y CONFIG_MBEDTLS_USER_CONFIG_FILE="config_mbedtls.h" CONFIG_MBEDTLS_PSA_CRYPTO_C=y +CONFIG_PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY=y +CONFIG_PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_BASIC=y +CONFIG_PSA_WANT_ECC_SECP_R1_256=y +CONFIG_PSA_WANT_ALG_ECDSA=y +CONFIG_PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY=y CONFIG_MBEDTLS_ENTROPY_ENABLED=y CONFIG_MBEDTLS_ECP_C=y CONFIG_MBEDTLS_ECP_DP_SECP256R1_ENABLED=y From 246e614ac340e2cc535b07fd67500a3de3e34a22 Mon Sep 17 00:00:00 2001 From: Daniel Kampert Date: Mon, 27 May 2024 13:39:49 +0200 Subject: [PATCH 1809/2849] drivers: rtc: rtc_mc146818: Patch incorrect field comparisons Minutes and hour values are incorrectly compared with MAX_SEC. Compare minutes and hour to MAX_MIN and MAX_HOUR respectively. Signed-off-by: Daniel Kampert --- drivers/rtc/rtc_mc146818.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/rtc/rtc_mc146818.c b/drivers/rtc/rtc_mc146818.c index 15d36c623b094..66257cf8d7461 100644 --- a/drivers/rtc/rtc_mc146818.c +++ b/drivers/rtc/rtc_mc146818.c @@ -377,13 +377,13 @@ static int rtc_mc146818_alarm_get_time(const struct device *dev, uint16_t id, ui } value = rtc_read(RTC_ALARM_MIN); - if (value <= MAX_SEC) { + if (value <= MAX_MIN) { timeptr->tm_min = value; (*mask) |= RTC_ALARM_TIME_MASK_MINUTE; } value = rtc_read(RTC_ALARM_HOUR); - if (value <= MAX_SEC) { + if (value <= MAX_HOUR) { timeptr->tm_hour = value; (*mask) |= RTC_ALARM_TIME_MASK_HOUR; } From 5f4d330db66e6e6daba7db8f7223f3bef02ef830 Mon Sep 17 00:00:00 2001 From: Lukasz Mrugala Date: Tue, 30 Apr 2024 14:17:47 +0000 Subject: [PATCH 1810/2849] scripts: twister: Do not report filtered test instances by default Filtered testcases are removed by default from Twister tests. Older functionality is preserved via a new Twister flag: --report-filtered. Old tests were adjusted and a new test for that flag added. Signed-off-by: Lukasz Mrugala --- .../pylib/twister/twisterlib/environment.py | 2 + scripts/pylib/twister/twisterlib/reports.py | 2 + scripts/tests/twister_blackbox/test_report.py | 60 ++++++++++++++++--- scripts/tests/twister_blackbox/test_runner.py | 8 +-- 4 files changed, 61 insertions(+), 11 deletions(-) diff --git a/scripts/pylib/twister/twisterlib/environment.py b/scripts/pylib/twister/twisterlib/environment.py index 85b7cdb371e10..3d818e4e96446 100644 --- a/scripts/pylib/twister/twisterlib/environment.py +++ b/scripts/pylib/twister/twisterlib/environment.py @@ -547,6 +547,8 @@ def add_parse_arguments(parser = None): parser.add_argument("--overflow-as-errors", action="store_true", help="Treat RAM/SRAM overflows as errors.") + parser.add_argument("--report-filtered", action="store_true", + help="Include filtered tests in the reports.") parser.add_argument("-P", "--exclude-platform", action="append", default=[], help="""Exclude platforms and do not build or run any tests diff --git a/scripts/pylib/twister/twisterlib/reports.py b/scripts/pylib/twister/twisterlib/reports.py index 48c9df082c486..4bc352e4f1d97 100644 --- a/scripts/pylib/twister/twisterlib/reports.py +++ b/scripts/pylib/twister/twisterlib/reports.py @@ -259,6 +259,8 @@ def json_report(self, filename, version="NA", platform=None): for instance in self.instances.values(): if platform and platform != instance.platform.name: continue + if instance.status == "filtered" and not self.env.options.report_filtered: + continue suite = {} handler_log = os.path.join(instance.build_dir, "handler.log") pytest_log = os.path.join(instance.build_dir, "twister_harness.log") diff --git a/scripts/tests/twister_blackbox/test_report.py b/scripts/tests/twister_blackbox/test_report.py index e116bea3da1eb..5b30394ef601b 100644 --- a/scripts/tests/twister_blackbox/test_report.py +++ b/scripts/tests/twister_blackbox/test_report.py @@ -344,14 +344,25 @@ def test_log_file(self, capfd, test_path, test_platforms, out_path, file_name): assert str(sys_exit.value) == '0' @pytest.mark.parametrize( - 'test_path, expected_testcase_count', - [(os.path.join(TEST_DATA, 'tests', 'dummy'), 6),], - ids=['dummy tests'] + 'test_path, flags, expected_testcase_counts', + [ + ( + os.path.join(TEST_DATA, 'tests', 'dummy'), + ['--detailed-skipped-report'], + {'qemu_x86': 5, 'frdm_k64f': 1} + ), + ( + os.path.join(TEST_DATA, 'tests', 'dummy'), + ['--detailed-skipped-report', '--report-filtered'], + {'qemu_x86': 6, 'frdm_k64f': 6} + ), + ], + ids=['dummy tests', 'dummy tests with filtered'] ) - def test_detailed_skipped_report(self, out_path, test_path, expected_testcase_count): + def test_detailed_skipped_report(self, out_path, test_path, flags, expected_testcase_counts): test_platforms = ['qemu_x86', 'frdm_k64f'] args = ['-i', '--outdir', out_path, '-T', test_path] + \ - ['--detailed-skipped-report'] + \ + flags + \ [val for pair in zip( ['-p'] * len(test_platforms), test_platforms ) for val in pair] @@ -367,12 +378,47 @@ def test_detailed_skipped_report(self, out_path, test_path, expected_testcase_co for ts in xml_data.iter('testsuite'): testsuite_counter += 1 # Without the tested flag, filtered testcases would be missing from the report - assert len(list(ts.iter('testcase'))) == expected_testcase_count, \ - 'Not all expected testcases appear in the report.' + testcase_count = len(list(ts.iter('testcase'))) + expected_tc_count = expected_testcase_counts[ts.get('name')] + assert testcase_count == expected_tc_count, \ + f'Not all expected testcases appear in the report.' \ + f' (In {ts.get("name")}, expected {expected_tc_count}, got {testcase_count}.)' assert testsuite_counter == len(test_platforms), \ 'Some platforms are missing from the XML report.' + @pytest.mark.parametrize( + 'test_path, report_filtered, expected_filtered_count', + [ + (os.path.join(TEST_DATA, 'tests', 'dummy'), False, 0), + (os.path.join(TEST_DATA, 'tests', 'dummy'), True, 4), + ], + ids=['no filtered', 'with filtered'] + ) + def test_report_filtered(self, out_path, test_path, report_filtered, expected_filtered_count): + test_platforms = ['qemu_x86', 'frdm_k64f'] + args = ['-i', '--outdir', out_path, '-T', test_path] + \ + (['--report-filtered'] if report_filtered else []) + \ + [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) == '0' + + with open(os.path.join(out_path, 'twister.json')) as f: + j = json.load(f) + + testsuites = j.get('testsuites') + assert testsuites, 'No testsuites found.' + statuses = [testsuite.get('status') for testsuite in testsuites] + filtered_status_count = statuses.count("filtered") + assert filtered_status_count == expected_filtered_count, \ + f'Expected {expected_filtered_count} filtered statuses, got {filtered_status_count}.' + def test_enable_size_report(self, out_path): test_platforms = ['qemu_x86', 'frdm_k64f'] path = os.path.join(TEST_DATA, 'tests', 'dummy', 'device', 'group') diff --git a/scripts/tests/twister_blackbox/test_runner.py b/scripts/tests/twister_blackbox/test_runner.py index 97e36d8b8a633..c93b93eb74e7e 100644 --- a/scripts/tests/twister_blackbox/test_runner.py +++ b/scripts/tests/twister_blackbox/test_runner.py @@ -45,15 +45,15 @@ class TestRunner: ['qemu_x86', 'qemu_x86_64', 'frdm_k64f'], { 'selected_test_scenarios': 3, - 'selected_test_instances': 9, - 'skipped_configurations': 3, - 'skipped_by_static_filter': 3, + 'selected_test_instances': 6, + 'skipped_configurations': 0, + 'skipped_by_static_filter': 0, 'skipped_at_runtime': 0, 'passed_configurations': 4, 'failed_configurations': 0, 'errored_configurations': 0, 'executed_test_cases': 8, - 'skipped_test_cases': 5, + 'skipped_test_cases': 0, 'platform_count': 0, 'executed_on_platform': 4, 'only_built': 2 From a4fdd915d5350f27afe6b3435d248075eb86dc49 Mon Sep 17 00:00:00 2001 From: Kai Vehmanen Date: Tue, 4 Jun 2024 18:10:54 +0300 Subject: [PATCH 1811/2849] drivers: dma: intel_adsp_hda: change L1 exit defaults DMA_INTEL_ADSP_HDA_TIMING_L1_EXIT should be set by default for both Intel ACE15 and ACE20 platforms. Signed-off-by: Kai Vehmanen --- drivers/dma/Kconfig.intel_adsp_hda | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/dma/Kconfig.intel_adsp_hda b/drivers/dma/Kconfig.intel_adsp_hda index 20ced567cb084..3761470fc95e7 100644 --- a/drivers/dma/Kconfig.intel_adsp_hda +++ b/drivers/dma/Kconfig.intel_adsp_hda @@ -45,6 +45,7 @@ config DMA_INTEL_ADSP_HDA config DMA_INTEL_ADSP_HDA_TIMING_L1_EXIT bool "Intel ADSP HDA Host L1 Exit Interrupt" default y if SOC_INTEL_ACE15_MTPM + default y if SOC_INTEL_ACE20_LNL depends on DMA_INTEL_ADSP_HDA_HOST_IN || DMA_INTEL_ADSP_HDA_HOST_OUT help Intel ADSP HDA Host Interrupt for L1 exit. From 9360b6e1aa76003f849a062ed4fe6515cacd2f82 Mon Sep 17 00:00:00 2001 From: Valerio Setti Date: Thu, 23 May 2024 15:03:19 +0200 Subject: [PATCH 1812/2849] mbedtls: remove unused kconfigs for Blowfish, ARC4 and MD4 As of Mbed TLS 3.6 (which is the currently used version in Zephyr) Blowfish, ARC4 and MD4 are no more supported so existing kconfigs have no effect at all. Moreover they are not even used anywhere in Zephyr. This commit just removes them all and it also updates the migration guide document. Signed-off-by: Valerio Setti --- doc/releases/migration-guide-3.7.rst | 3 +++ modules/mbedtls/Kconfig.tls-generic | 12 ------------ modules/mbedtls/configs/config-tls-generic.h | 12 ------------ 3 files changed, 3 insertions(+), 24 deletions(-) diff --git a/doc/releases/migration-guide-3.7.rst b/doc/releases/migration-guide-3.7.rst index 5fb4cfe135327..b18522722e1b1 100644 --- a/doc/releases/migration-guide-3.7.rst +++ b/doc/releases/migration-guide-3.7.rst @@ -98,6 +98,9 @@ Mbed TLS of other Kconfig options which are now named `CONFIG_MBEDTLS_SHA*`. * The `CONFIG_MBEDTLS_MAC_ALL_ENABLED` Kconfig option has been removed. Its equivalent is the combination of :kconfig:option:`CONFIG_MBEDTLS_HASH_ALL_ENABLED` and :kconfig:option:`CONFIG_MBEDTLS_CMAC`. +* The Kconfig options ``CONFIG_MBEDTLS_MAC_MD4_ENABLED``, ``CONFIG_MBEDTLS_CIPHER_ARC4_ENABLED`` + and ``CONFIG_MBEDTLS_CIPHER_BLOWFISH_ENABLED`` were removed because they are no more supported + in Mbed TLS. (:github:`73222`) MCUboot ======= diff --git a/modules/mbedtls/Kconfig.tls-generic b/modules/mbedtls/Kconfig.tls-generic index 3cf98bdd3278c..7a7105287a505 100644 --- a/modules/mbedtls/Kconfig.tls-generic +++ b/modules/mbedtls/Kconfig.tls-generic @@ -215,9 +215,7 @@ config MBEDTLS_CIPHER_ALL_ENABLED select MBEDTLS_CIPHER_AES_ENABLED select MBEDTLS_CIPHER_CAMELLIA_ENABLED select MBEDTLS_CIPHER_DES_ENABLED - select MBEDTLS_CIPHER_ARC4_ENABLED select MBEDTLS_CIPHER_CHACHA20_ENABLED - select MBEDTLS_CIPHER_BLOWFISH_ENABLED select MBEDTLS_CIPHER_CCM_ENABLED select MBEDTLS_CIPHER_GCM_ENABLED select MBEDTLS_CIPHER_MODE_XTS_ENABLED @@ -269,15 +267,9 @@ config MBEDTLS_CIPHER_CAMELLIA_ENABLED config MBEDTLS_CIPHER_DES_ENABLED bool "DES block cipher" -config MBEDTLS_CIPHER_ARC4_ENABLED - bool "ARC4 stream cipher" - config MBEDTLS_CIPHER_CHACHA20_ENABLED bool "ChaCha20 stream cipher" -config MBEDTLS_CIPHER_BLOWFISH_ENABLED - bool "Blowfish block cipher" - if MBEDTLS_SOME_AEAD_CIPHER_ENABLED config MBEDTLS_CIPHER_CCM_ENABLED @@ -312,7 +304,6 @@ comment "Supported hash algorithms" config MBEDTLS_HASH_ALL_ENABLED bool "All available MAC methods" - select MBEDTLS_MD4 select MBEDTLS_MD5 select MBEDTLS_SHA1 select MBEDTLS_SHA224 @@ -321,9 +312,6 @@ config MBEDTLS_HASH_ALL_ENABLED select MBEDTLS_SHA512 select MBEDTLS_POLY1305 -config MBEDTLS_MD4 - bool "MD4 hash algorithm" - config MBEDTLS_MD5 bool "MD5 hash algorithm" diff --git a/modules/mbedtls/configs/config-tls-generic.h b/modules/mbedtls/configs/config-tls-generic.h index 8c19e30e5c072..850b27d80d671 100644 --- a/modules/mbedtls/configs/config-tls-generic.h +++ b/modules/mbedtls/configs/config-tls-generic.h @@ -163,18 +163,10 @@ #define MBEDTLS_DES_C #endif -#if defined(CONFIG_MBEDTLS_CIPHER_ARC4_ENABLED) -#define MBEDTLS_ARC4_C -#endif - #if defined(CONFIG_MBEDTLS_CIPHER_CHACHA20_ENABLED) #define MBEDTLS_CHACHA20_C #endif -#if defined(CONFIG_MBEDTLS_CIPHER_BLOWFISH_ENABLED) -#define MBEDTLS_BLOWFISH_C -#endif - #if defined(CONFIG_MBEDTLS_CIPHER_CCM_ENABLED) #define MBEDTLS_CCM_C #endif @@ -273,10 +265,6 @@ /* Supported hash algorithms */ -#if defined(CONFIG_MBEDTLS_MD4) -#define MBEDTLS_MD4_C -#endif - #if defined(CONFIG_MBEDTLS_MD5) #define MBEDTLS_MD5_C #endif From 5a4fa06c6793fd4a62fa79872cb1073f7d9e192a Mon Sep 17 00:00:00 2001 From: Piotr Kosycarz Date: Tue, 14 May 2024 13:52:34 +0200 Subject: [PATCH 1813/2849] samples: basic: fade_led: add testing base on console output Extend automated testing on HW by veryfing console output. Signed-off-by: Piotr Kosycarz --- samples/basic/fade_led/sample.yaml | 9 ++++++++- samples/basic/fade_led/src/main.c | 1 + 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/samples/basic/fade_led/sample.yaml b/samples/basic/fade_led/sample.yaml index eae1afefe5b48..603c572147191 100644 --- a/samples/basic/fade_led/sample.yaml +++ b/samples/basic/fade_led/sample.yaml @@ -6,7 +6,14 @@ tests: - drivers - pwm depends_on: pwm - harness: led filter: dt_alias_exists("pwm-led0") and dt_compat_enabled("pwm-leds") integration_platforms: - nrf51dk/nrf51822 + harness: console + harness_config: + type: multi_line + ordered: true + regex: + - "PWM-based LED fade" + - "Using pulse width [0-9]+%" + - "Using pulse width [0-9]+%" diff --git a/samples/basic/fade_led/src/main.c b/samples/basic/fade_led/src/main.c index ab7b2aca0328f..c6a49a13a1222 100644 --- a/samples/basic/fade_led/src/main.c +++ b/samples/basic/fade_led/src/main.c @@ -40,6 +40,7 @@ int main(void) printk("Error %d: failed to set pulse width\n", ret); return 0; } + printk("Using pulse width %d%%\n", 100 * pulse_width / pwm_led0.period); if (dir) { pulse_width += step; From 90986e7e22f42a45e25da84ef3e293f4171f9886 Mon Sep 17 00:00:00 2001 From: Declan Snyder Date: Mon, 3 Jun 2024 20:03:34 -0500 Subject: [PATCH 1814/2849] drivers: mcux_lptmr_timer: Fix compat string error Fix error due to compatible string changing in DT and forgetting to update this driver with the change. Also make the counter symbol hidden. Signed-off-by: Declan Snyder --- drivers/counter/Kconfig.mcux_lptmr | 2 +- drivers/timer/Kconfig.mcux_lptmr | 13 ++++++++++++- drivers/timer/mcux_lptmr_timer.c | 5 +++++ 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/drivers/counter/Kconfig.mcux_lptmr b/drivers/counter/Kconfig.mcux_lptmr index d6847a3ffbb4b..af961c790e1d4 100644 --- a/drivers/counter/Kconfig.mcux_lptmr +++ b/drivers/counter/Kconfig.mcux_lptmr @@ -12,7 +12,7 @@ config COUNTER_MCUX_LPTMR Enable support for the MCUX Low Power Timer (LPTMR). config COUNTER_MCUX_KINETIS_LPTMR - bool "Deprecated DT compatible" + bool default y depends on DT_HAS_NXP_KINETIS_LPTMR_ENABLED select DEPRECATED diff --git a/drivers/timer/Kconfig.mcux_lptmr b/drivers/timer/Kconfig.mcux_lptmr index 8879cb3b558c4..6182611f744db 100644 --- a/drivers/timer/Kconfig.mcux_lptmr +++ b/drivers/timer/Kconfig.mcux_lptmr @@ -6,7 +6,8 @@ config MCUX_LPTMR_TIMER bool "MCUX LPTMR timer" default y - depends on DT_HAS_NXP_KINETIS_LPTMR_ENABLED + depends on DT_HAS_NXP_KINETIS_LPTMR_ENABLED || \ + MCUX_KINETIS_LPTMR depends on !COUNTER_MCUX_LPTMR depends on PM select SYSTEM_TIMER_HAS_DISABLE_SUPPORT @@ -14,3 +15,13 @@ config MCUX_LPTMR_TIMER This module implements a kernel device driver for the NXP MCUX Low Power Timer (LPTMR) and provides the standard "system clock driver" interfaces. + +config MCUX_KINETIS_LPTMR + bool + default y + depends on DT_HAS_NXP_KINETIS_LPTMR_ENABLED + select DEPRECATED + help + The compatible string "nxp,kinetis-lptmr" should + be swiched to "nxp,lptmr" in DT. The former will + be removed eventually. diff --git a/drivers/timer/mcux_lptmr_timer.c b/drivers/timer/mcux_lptmr_timer.c index e91c11112ff9c..930058f4ea40a 100644 --- a/drivers/timer/mcux_lptmr_timer.c +++ b/drivers/timer/mcux_lptmr_timer.c @@ -4,7 +4,12 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include +#if DT_HAS_COMPAT_STATUS_OKAY(nxp_kinetis_lptmr) #define DT_DRV_COMPAT nxp_kinetis_lptmr +#else +#define DT_DRV_COMPAT nxp_lptmr +#endif #include #include From 02d71a135c3179964194943d03e1221e0c94625b Mon Sep 17 00:00:00 2001 From: Ayush Singh Date: Fri, 31 May 2024 23:09:01 +0530 Subject: [PATCH 1815/2849] drivers: cc13xx_cc26xx: pwm: Fix building blinky_pwm - Add channel, flags to pwm-cells - Replace __ASSERT_UNREACHABLE with CODE_UNREACHABLE Signed-off-by: Ayush Singh --- drivers/pwm/pwm_cc13xx_cc26xx_timer.c | 4 ++-- dts/arm/ti/cc13xx_cc26xx.dtsi | 8 ++++---- dts/bindings/pwm/ti,cc13xx-cc26xx-timer-pwm.yaml | 4 +++- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/drivers/pwm/pwm_cc13xx_cc26xx_timer.c b/drivers/pwm/pwm_cc13xx_cc26xx_timer.c index 4855c134aa626..9edb19b647fd8 100644 --- a/drivers/pwm/pwm_cc13xx_cc26xx_timer.c +++ b/drivers/pwm/pwm_cc13xx_cc26xx_timer.c @@ -140,7 +140,7 @@ static int get_timer_inst_number(const struct pwm_cc13xx_cc26xx_config *config) case GPT3_BASE: return 3; default: - __ASSERT_UNREACHABLE; + CODE_UNREACHABLE; } } #else @@ -156,7 +156,7 @@ static int get_timer_peripheral(const struct pwm_cc13xx_cc26xx_config *config) case GPT3_BASE: return PRCM_PERIPH_TIMER3; default: - __ASSERT_UNREACHABLE; + CODE_UNREACHABLE; } } #endif /* CONFIG_PM */ diff --git a/dts/arm/ti/cc13xx_cc26xx.dtsi b/dts/arm/ti/cc13xx_cc26xx.dtsi index 5c67e9df3f4e9..3cdf6b5d57892 100644 --- a/dts/arm/ti/cc13xx_cc26xx.dtsi +++ b/dts/arm/ti/cc13xx_cc26xx.dtsi @@ -105,7 +105,7 @@ pwm0: pwm { compatible = "ti,cc13xx-cc26xx-timer-pwm"; - #pwm-cells = <1>; + #pwm-cells = <3>; status = "disabled"; }; }; @@ -119,7 +119,7 @@ pwm1: pwm { compatible = "ti,cc13xx-cc26xx-timer-pwm"; - #pwm-cells = <1>; + #pwm-cells = <3>; status = "disabled"; }; }; @@ -133,7 +133,7 @@ pwm2: pwm { compatible = "ti,cc13xx-cc26xx-timer-pwm"; - #pwm-cells = <1>; + #pwm-cells = <3>; status = "disabled"; }; }; @@ -147,7 +147,7 @@ pwm3: pwm { compatible = "ti,cc13xx-cc26xx-timer-pwm"; - #pwm-cells = <1>; + #pwm-cells = <3>; status = "disabled"; }; }; diff --git a/dts/bindings/pwm/ti,cc13xx-cc26xx-timer-pwm.yaml b/dts/bindings/pwm/ti,cc13xx-cc26xx-timer-pwm.yaml index c63fc7ac1d78f..bc33465b1188e 100644 --- a/dts/bindings/pwm/ti,cc13xx-cc26xx-timer-pwm.yaml +++ b/dts/bindings/pwm/ti,cc13xx-cc26xx-timer-pwm.yaml @@ -69,4 +69,6 @@ properties: required: true pwm-cells: -- period + - channel + - period + - flags From d9e2b0c70763ce9c5368f345881ea1e558d8a77c Mon Sep 17 00:00:00 2001 From: Ayush Singh Date: Fri, 31 May 2024 23:10:11 +0530 Subject: [PATCH 1816/2849] samples: blinky_pwm: add overlay for bcf - Add and test pwm for beagleconnect freedom Signed-off-by: Ayush Singh --- .../boards/beagleconnect_freedom.overlay | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 samples/basic/blinky_pwm/boards/beagleconnect_freedom.overlay diff --git a/samples/basic/blinky_pwm/boards/beagleconnect_freedom.overlay b/samples/basic/blinky_pwm/boards/beagleconnect_freedom.overlay new file mode 100644 index 0000000000000..1d8f708c712bf --- /dev/null +++ b/samples/basic/blinky_pwm/boards/beagleconnect_freedom.overlay @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2024 Ayush Singh + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + aliases { + pwm-led0 = &pwm_led0; + }; + + pwmleds { + compatible = "pwm-leds"; + pwm_led0: pwm_led_0 { + pwms = <&pwm0 0 255>; + label = "PWM MB1"; + }; + }; +}; + +&pinctrl { + pwm0_default: pwm0_default { + pinmux = <17 IOC_PORT_MCU_PORT_EVENT1>; + bias-disable; + drive-strength = <8>; + }; +}; + +&gpt0 { + status = "okay"; +}; + +&pwm0 { + status = "okay"; + pinctrl-0 = <&pwm0_default>; + pinctrl-names = "default"; +}; From 12142f72ec71acbabdf019907f3a9e5d24a3e99b Mon Sep 17 00:00:00 2001 From: Nikodem Kastelik Date: Wed, 29 May 2024 14:26:29 +0200 Subject: [PATCH 1817/2849] arch: arm: core: mpu: allow non-ARM memory attributes Memory region defined in devicetree can have attributes that are not intended to be parsed by MPU library, but might be valid for other components. Signed-off-by: Nikodem Kastelik --- arch/arm/core/mpu/arm_mpu.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/arch/arm/core/mpu/arm_mpu.c b/arch/arm/core/mpu/arm_mpu.c index 52ad585b79c13..fe5d86c822da5 100644 --- a/arch/arm/core/mpu/arm_mpu.c +++ b/arch/arm/core/mpu/arm_mpu.c @@ -130,12 +130,10 @@ static int mpu_configure_regions_from_dt(uint8_t *reg_index) break; #endif default: - /* Either the specified `ATTR_MPU_*` attribute does not - * exists or the `REGION_*_ATTR` macro is not defined - * for that attribute. + /* Attribute other than ARM-specific is set. + * This region should not be configured in MPU. */ - LOG_ERR("Invalid attribute for the region\n"); - return -EINVAL; + continue; } #if defined(CONFIG_ARMV7_R) region_conf.size = size_to_mpu_rasr_size(region[idx].dt_size); From 8b8c0a7bf0cc95c36854373f46fe7bd6b1b72e98 Mon Sep 17 00:00:00 2001 From: Nikodem Kastelik Date: Wed, 29 May 2024 14:31:38 +0200 Subject: [PATCH 1818/2849] boards: nrf54h20dk: add ram21 memory region This memory region is used for not only but also DMA transfers of the fast peripherals. Signed-off-by: Nikodem Kastelik --- .../nrf54h20dk_nrf54h20-memory_map.dtsi | 22 +++++++++++++++++++ .../nrf54h20dk/nrf54h20dk_nrf54h20_cpuapp.dts | 8 +++++++ 2 files changed, 30 insertions(+) diff --git a/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20-memory_map.dtsi b/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20-memory_map.dtsi index 7e4f859753c32..834448f33e4cc 100644 --- a/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20-memory_map.dtsi +++ b/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20-memory_map.dtsi @@ -3,6 +3,7 @@ * * SPDX-License-Identifier: Apache-2.0 */ +#include / { reserved-memory { @@ -92,6 +93,27 @@ }; }; + ram21_region: memory@2f890000 { + compatible = "nordic,owned-memory"; + status = "disabled"; + reg = <0x2f890000 DT_SIZE_K(64)>; + perm-read; + perm-write; + perm-secure; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0x2f890000 0x10000>; + + dma_fast_region: memory@8000 { + compatible = "zephyr,memory-region"; + reg = <0x8000 DT_SIZE_K(16)>; + status = "disabled"; + #memory-region-cells = <0>; + zephyr,memory-region = "DMA_RAM21"; + zephyr,memory-attr = <( DT_MEM_CACHEABLE )>; + }; + }; + cpuppr_ram3x_region: memory@2fc00000 { compatible = "nordic,owned-memory"; reg = <0x2fc00000 DT_SIZE_K(64)>; diff --git a/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpuapp.dts b/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpuapp.dts index 2c5d61a27e8bb..2b071c8703887 100644 --- a/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpuapp.dts +++ b/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpuapp.dts @@ -108,6 +108,10 @@ status = "okay"; }; +&ram21_region { + status = "okay"; +}; + &cpuapp_bellboard { status = "okay"; interrupts = <96 NRF_DEFAULT_IRQ_PRIORITY>; @@ -156,6 +160,10 @@ ipc0: &cpuapp_cpurad_ipc { status = "okay"; }; +&dma_fast_region { + status = "okay"; +}; + &cpuapp_rx_partitions { status = "okay"; }; From 41ad1f3ddbf9cfe726e01e38071d19b136e53228 Mon Sep 17 00:00:00 2001 From: Nikodem Kastelik Date: Wed, 29 May 2024 14:35:32 +0200 Subject: [PATCH 1819/2849] drivers: pinctrl: nrf: use CLOCKPIN for slow SPIM MOSI Fast SPIM instances must not have CLOCKPIN setting applied to MOSI. Signed-off-by: Nikodem Kastelik --- drivers/pinctrl/pinctrl_nrf.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/pinctrl/pinctrl_nrf.c b/drivers/pinctrl/pinctrl_nrf.c index 4c2acee81b58a..17193c160cad1 100644 --- a/drivers/pinctrl/pinctrl_nrf.c +++ b/drivers/pinctrl/pinctrl_nrf.c @@ -162,7 +162,10 @@ int pinctrl_configure_pins(const pinctrl_soc_pin_t *pins, uint8_t pin_cnt, dir = NRF_GPIO_PIN_DIR_OUTPUT; input = NRF_GPIO_PIN_INPUT_DISCONNECT; #if NRF_GPIO_HAS_CLOCKPIN && defined(NRF_SPIM_CLOCKPIN_MOSI_NEEDED) - clockpin = true; + /* CLOCKPIN setting must not be applied to SPIM12x instances. */ + if (!NRF_SPIM_IS_320MHZ_SPIM((void *)reg)) { + clockpin = true; + } #endif break; case NRF_FUN_SPIM_MISO: From 77e875a0b7cfb6bcecf91b8199111f9202134a4f Mon Sep 17 00:00:00 2001 From: Nikodem Kastelik Date: Wed, 29 May 2024 14:37:51 +0200 Subject: [PATCH 1820/2849] tests: drivers: spi_controller_peripheral: improve async test case In test cases checking async API, use async API for both controller and peripheral devices. Signed-off-by: Nikodem Kastelik --- .../spi/spi_controller_peripheral/src/main.c | 28 +++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/tests/drivers/spi/spi_controller_peripheral/src/main.c b/tests/drivers/spi/spi_controller_peripheral/src/main.c index dfcd83e6558bc..75e5a4d2ea3d7 100644 --- a/tests/drivers/spi/spi_controller_peripheral/src/main.c +++ b/tests/drivers/spi/spi_controller_peripheral/src/main.c @@ -35,6 +35,10 @@ static struct k_poll_signal async_sig = K_POLL_SIGNAL_INITIALIZER(async_sig); static struct k_poll_event async_evt = K_POLL_EVENT_INITIALIZER(K_POLL_TYPE_SIGNAL, K_POLL_MODE_NOTIFY_ONLY, &async_sig); +static struct k_poll_signal async_sig_spim = K_POLL_SIGNAL_INITIALIZER(async_sig_spim); +static struct k_poll_event async_evt_spim = + K_POLL_EVENT_INITIALIZER(K_POLL_TYPE_SIGNAL, K_POLL_MODE_NOTIFY_ONLY, &async_sig_spim); + #define MEMORY_SECTION(node) \ COND_CODE_1(DT_NODE_HAS_PROP(node, memory_regions), \ (__attribute__((__section__( \ @@ -55,6 +59,7 @@ struct test_data { struct spi_buf_set *stx_set; struct spi_buf_set *srx_set; struct spi_buf bufs[8]; + bool async; }; static struct test_data tdata; @@ -85,8 +90,26 @@ static void work_handler(struct k_work *work) struct test_data *td = CONTAINER_OF(dwork, struct test_data, test_work); int rv; - rv = spi_transceive_dt(&spim, td->mtx_set, td->mrx_set); - if (rv == 0) { + if (!td->async) { + rv = spi_transceive_dt(&spim, td->mtx_set, td->mrx_set); + if (rv == 0) { + k_sem_give(&td->sem); + } + } else { + rv = spi_transceive_signal(spim.bus, &spim.config, td->mtx_set, td->mrx_set, + &async_sig_spim); + zassert_equal(rv, 0); + + rv = k_poll(&async_evt_spim, 1, K_MSEC(200)); + zassert_false(rv, "one or more events are not ready"); + + rv = async_evt_spim.signal->result; + zassert_equal(rv, 0); + + /* Reinitializing for next call */ + async_evt_spim.signal->signaled = 0U; + async_evt_spim.state = K_POLL_STATE_NOT_READY; + k_sem_give(&td->sem); } } @@ -181,6 +204,7 @@ static void run_test(bool m_same_size, bool s_same_size, bool async) int periph_rv; int srx_len; + tdata.async = async; rv = k_work_schedule(&tdata.test_work, K_MSEC(10)); zassert_equal(rv, 1); From 7080f0f83f9aea1052de28d8009c09279bee9c8c Mon Sep 17 00:00:00 2001 From: Nikodem Kastelik Date: Wed, 29 May 2024 15:02:04 +0200 Subject: [PATCH 1821/2849] drivers: spi: nrf: fix async cs deactivation Chip Select signal must be deactivated only after transaction is finalized. In async case this means it cannot be done from `transceive` call context, as this context is left as soon as transfer is initialized. Signed-off-by: Nikodem Kastelik --- drivers/spi/spi_nrfx_spim.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/spi/spi_nrfx_spim.c b/drivers/spi/spi_nrfx_spim.c index 08012b389c55b..0dc3fc7a37098 100644 --- a/drivers/spi/spi_nrfx_spim.c +++ b/drivers/spi/spi_nrfx_spim.c @@ -298,6 +298,8 @@ static void finish_transaction(const struct device *dev, int error) spi_context_complete(ctx, dev, error); dev_data->busy = false; + + spi_context_cs_control(&dev_data->ctx, false); } static void transfer_next_chunk(const struct device *dev) @@ -468,8 +470,6 @@ static int transceive(const struct device *dev, anomaly_58_workaround_clear(dev_data); #endif } - - spi_context_cs_control(&dev_data->ctx, false); } spi_context_release(&dev_data->ctx, error); From dd91c89d2f3e84344db390cc8b8b5cbe9e0fb937 Mon Sep 17 00:00:00 2001 From: Nikodem Kastelik Date: Thu, 30 May 2024 23:11:11 +0200 Subject: [PATCH 1822/2849] manifest: update hal_nordic revision Updated hal_nordic revision brings update to nrfx SPIM driver, allowing external configuration of ENABLE register needed to mitigate SPI bus glitches when using CTRLSEL pins. Signed-off-by: Nikodem Kastelik --- west.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/west.yml b/west.yml index 3c16894fb60e4..238e3a6316406 100644 --- a/west.yml +++ b/west.yml @@ -188,7 +188,7 @@ manifest: groups: - hal - name: hal_nordic - revision: fc02d66798f691b66bd6b0236e63082a9c498bbf + revision: f311735c1a16169ef228f1c50fefb4c8632ae69c path: modules/hal/nordic groups: - hal From fc0718ed46661f4af478385380dc666d8647b795 Mon Sep 17 00:00:00 2001 From: Nikodem Kastelik Date: Wed, 29 May 2024 15:14:46 +0200 Subject: [PATCH 1823/2849] drivers: spi: nrf: add support for spim12x instances SPIM12x instances can perform DMA only from memory region that is cacheable by default. SPIM12x instances pins are configured via CTRLSEL mechanism, which prevents the GPIO registers from ensuring correct bus state when peripheral does not drive the bus lines. External configuration of SPIM12x ENABLE register fixes this issue. Signed-off-by: Nikodem Kastelik --- drivers/spi/spi_nrfx_spim.c | 59 ++++++++++++++++++++++++++++++++++--- 1 file changed, 55 insertions(+), 4 deletions(-) diff --git a/drivers/spi/spi_nrfx_spim.c b/drivers/spi/spi_nrfx_spim.c index 0dc3fc7a37098..e1ce774af5229 100644 --- a/drivers/spi/spi_nrfx_spim.c +++ b/drivers/spi/spi_nrfx_spim.c @@ -5,8 +5,10 @@ */ #include +#include #include #include +#include #include #ifdef CONFIG_SOC_NRF52832_ALLOW_SPIM_DESPITE_PAN_58 #include @@ -64,10 +66,28 @@ struct spi_nrfx_config { #endif uint32_t wake_pin; nrfx_gpiote_t wake_gpiote; +#ifdef CONFIG_DCACHE + uint32_t mem_attr; +#endif }; static void event_handler(const nrfx_spim_evt_t *p_event, void *p_context); +static inline void finalize_spi_transaction(const struct device *dev, bool deactivate_cs) +{ + struct spi_nrfx_data *dev_data = dev->data; + const struct spi_nrfx_config *dev_config = dev->config; + void *reg = dev_config->spim.p_reg; + + if (deactivate_cs) { + spi_context_cs_control(&dev_data->ctx, false); + } + + if (NRF_SPIM_IS_320MHZ_SPIM(reg) && !(dev_data->ctx.config->operation & SPI_HOLD_ON_CS)) { + nrfy_spim_disable(reg); + } +} + static inline uint32_t get_nrf_spim_frequency(uint32_t frequency) { /* Get the highest supported frequency not exceeding the requested one. @@ -193,7 +213,7 @@ static int configure(const struct device *dev, } result = nrfx_spim_init(&dev_config->spim, &config, - event_handler, dev_data); + event_handler, (void *)dev); if (result != NRFX_SUCCESS) { LOG_ERR("Failed to initialize nrfx driver: %08x", result); return -EIO; @@ -299,7 +319,7 @@ static void finish_transaction(const struct device *dev, int error) spi_context_complete(ctx, dev, error); dev_data->busy = false; - spi_context_cs_control(&dev_data->ctx, false); + finalize_spi_transaction(dev, true); } static void transfer_next_chunk(const struct device *dev) @@ -330,6 +350,11 @@ static void transfer_next_chunk(const struct device *dev) } memcpy(dev_data->tx_buffer, tx_buf, chunk_len); +#ifdef CONFIG_DCACHE + if (dev_config->mem_attr & DT_MEM_CACHEABLE) { + sys_cache_data_flush_range(dev_data->tx_buffer, chunk_len); + } +#endif tx_buf = dev_data->tx_buffer; } @@ -379,7 +404,11 @@ static void transfer_next_chunk(const struct device *dev) static void event_handler(const nrfx_spim_evt_t *p_event, void *p_context) { - struct spi_nrfx_data *dev_data = p_context; + const struct device *dev = p_context; + struct spi_nrfx_data *dev_data = dev->data; +#ifdef CONFIG_DCACHE + const struct spi_nrfx_config *dev_config = dev->config; +#endif if (p_event->type == NRFX_SPIM_EVENT_DONE) { /* Chunk length is set to 0 when a transaction is aborted @@ -397,6 +426,11 @@ static void event_handler(const nrfx_spim_evt_t *p_event, void *p_context) if (spi_context_rx_buf_on(&dev_data->ctx) && p_event->xfer_desc.p_rx_buffer != NULL && p_event->xfer_desc.p_rx_buffer != dev_data->ctx.rx_buf) { +#ifdef CONFIG_DCACHE + if (dev_config->mem_attr & DT_MEM_CACHEABLE) { + sys_cache_data_invd_range(dev_data->rx_buffer, dev_data->chunk_len); + } +#endif (void)memcpy(dev_data->ctx.rx_buf, dev_data->rx_buffer, dev_data->chunk_len); @@ -419,6 +453,7 @@ static int transceive(const struct device *dev, { struct spi_nrfx_data *dev_data = dev->data; const struct spi_nrfx_config *dev_config = dev->config; + void *reg = dev_config->spim.p_reg; int error; spi_context_lock(&dev_data->ctx, asynchronous, cb, userdata, spi_cfg); @@ -441,6 +476,9 @@ static int transceive(const struct device *dev, } spi_context_buffers_setup(&dev_data->ctx, tx_bufs, rx_bufs, 1); + if (NRF_SPIM_IS_320MHZ_SPIM(reg)) { + nrfy_spim_enable(reg); + } spi_context_cs_control(&dev_data->ctx, true); transfer_next_chunk(dev); @@ -469,6 +507,8 @@ static int transceive(const struct device *dev, #ifdef CONFIG_SOC_NRF52832_ALLOW_SPIM_DESPITE_PAN_58 anomaly_58_workaround_clear(dev_data); #endif + } else if (error) { + finalize_spi_transaction(dev, true); } } @@ -511,6 +551,7 @@ static int spi_nrfx_release(const struct device *dev, } spi_context_unlock_unconditionally(&dev_data->ctx); + finalize_spi_transaction(dev, false); return 0; } @@ -612,6 +653,7 @@ static int spi_nrfx_init(const struct device *dev) #define SPIM(idx) DT_NODELABEL(spi##idx) #define SPIM_PROP(idx, prop) DT_PROP(SPIM(idx), prop) #define SPIM_HAS_PROP(idx, prop) DT_NODE_HAS_PROP(SPIM(idx), prop) +#define SPIM_MEM_REGION(idx) DT_PHANDLE(SPIM(idx), memory_regions) #define SPI_NRFX_SPIM_EXTENDED_CONFIG(idx) \ IF_ENABLED(NRFX_SPIM_EXTENDED_ENABLED, \ @@ -621,6 +663,13 @@ static int spi_nrfx_init(const struct device *dev) ()) \ )) +#define SPIM_GET_MEM_ATTR(idx) \ + COND_CODE_1(SPIM_HAS_PROP(idx, memory_regions), \ + (COND_CODE_1(DT_NODE_HAS_PROP(SPIM_MEM_REGION(idx), zephyr_memory_attr), \ + (DT_PROP(SPIM_MEM_REGION(idx), zephyr_memory_attr)), \ + (0))), \ + (0)) + #define SPI_NRFX_SPIM_DEFINE(idx) \ NRF_DT_CHECK_NODE_HAS_PINCTRL_SLEEP(SPIM(idx)); \ static void irq_connect##idx(void) \ @@ -669,6 +718,8 @@ static int spi_nrfx_init(const struct device *dev) .wake_pin = NRF_DT_GPIOS_TO_PSEL_OR(SPIM(idx), wake_gpios, \ WAKE_PIN_NOT_USED), \ .wake_gpiote = WAKE_GPIOTE_INSTANCE(SPIM(idx)), \ + IF_ENABLED(CONFIG_DCACHE, \ + (.mem_attr = SPIM_GET_MEM_ATTR(idx),)) \ }; \ BUILD_ASSERT(!SPIM_HAS_PROP(idx, wake_gpios) || \ !(DT_GPIO_FLAGS(SPIM(idx), wake_gpios) & GPIO_ACTIVE_LOW),\ @@ -685,7 +736,7 @@ static int spi_nrfx_init(const struct device *dev) #define SPIM_MEMORY_SECTION(idx) \ COND_CODE_1(SPIM_HAS_PROP(idx, memory_regions), \ (__attribute__((__section__(LINKER_DT_NODE_REGION_NAME( \ - DT_PHANDLE(SPIM(idx), memory_regions)))))), \ + SPIM_MEM_REGION(idx)))))), \ ()) #ifdef CONFIG_HAS_HW_NRF_SPIM0 From b1506dfda88747098184ccaf9c2bd5a26bead17a Mon Sep 17 00:00:00 2001 From: Nikodem Kastelik Date: Tue, 4 Jun 2024 09:42:01 +0200 Subject: [PATCH 1824/2849] boards: nordic: nrf54h20: cpuppr: add SPI to supported features SPI is now supported on nRF54H20 PPR CPU. Signed-off-by: Nikodem Kastelik --- boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpuppr.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpuppr.yaml b/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpuppr.yaml index 190d835f58090..af81ae6e28edf 100644 --- a/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpuppr.yaml +++ b/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpuppr.yaml @@ -12,3 +12,4 @@ flash: 62 supported: - gpio - pwm + - spi From 23b4706e47843dec33f5885011f5f95818a270d9 Mon Sep 17 00:00:00 2001 From: Nikodem Kastelik Date: Wed, 29 May 2024 15:31:35 +0200 Subject: [PATCH 1825/2849] tests: drivers: spi: nordic: add fast SPI to overlays SPIM12x have more capabilities than SPIM13x, so it should be tested separately. Signed-off-by: Nikodem Kastelik --- .../boards/nrf54h20dk_nrf54h20_common.dtsi | 3 +- .../boards/nrf54h20dk_nrf54h20_cpuapp.overlay | 2 +- .../nrf54h20dk_nrf54h20_cpuapp_fast.overlay | 75 ++++++++++++++++ .../boards/nrf54h20dk_nrf54h20_cpurad.overlay | 2 +- .../spi_controller_peripheral/testcase.yaml | 21 ++++- .../nrf54h20dk_nrf54h20_cpuapp_fast.overlay | 75 ++++++++++++++++ .../boards/nrf54h20dk_nrf54h20_cpuppr.overlay | 85 +++++++++++++++++++ ...rf54h20dk_nrf54h20_cpuppr_launcher.overlay | 23 +++++ tests/drivers/spi/spi_error_cases/src/main.c | 12 --- .../drivers/spi/spi_error_cases/testcase.yaml | 23 +++-- .../nrf54h20dk_nrf54h20_cpuapp_fast.overlay | 43 ++++++++++ tests/drivers/spi/spi_loopback/testcase.yaml | 4 + 12 files changed, 346 insertions(+), 22 deletions(-) create mode 100644 tests/drivers/spi/spi_controller_peripheral/boards/nrf54h20dk_nrf54h20_cpuapp_fast.overlay create mode 100644 tests/drivers/spi/spi_error_cases/boards/nrf54h20dk_nrf54h20_cpuapp_fast.overlay create mode 100644 tests/drivers/spi/spi_error_cases/boards/nrf54h20dk_nrf54h20_cpuppr.overlay create mode 100644 tests/drivers/spi/spi_error_cases/boards/nrf54h20dk_nrf54h20_cpuppr_launcher.overlay create mode 100644 tests/drivers/spi/spi_loopback/boards/nrf54h20dk_nrf54h20_cpuapp_fast.overlay diff --git a/tests/drivers/spi/spi_controller_peripheral/boards/nrf54h20dk_nrf54h20_common.dtsi b/tests/drivers/spi/spi_controller_peripheral/boards/nrf54h20dk_nrf54h20_common.dtsi index 359a5ef600da5..f968e4351a8dc 100644 --- a/tests/drivers/spi/spi_controller_peripheral/boards/nrf54h20dk_nrf54h20_common.dtsi +++ b/tests/drivers/spi/spi_controller_peripheral/boards/nrf54h20dk_nrf54h20_common.dtsi @@ -52,7 +52,7 @@ owned-channels = <7>; }; -dut_spi: &spi130 { +&spi130 { compatible = "nordic,nrf-spim"; status = "okay"; pinctrl-0 = <&spi130_default_alt>; @@ -63,6 +63,7 @@ dut_spi: &spi130 { dut_spi_dt: test-spi-dev@0 { compatible = "vnd,spi-device"; reg = <0>; + spi-max-frequency = ; }; }; diff --git a/tests/drivers/spi/spi_controller_peripheral/boards/nrf54h20dk_nrf54h20_cpuapp.overlay b/tests/drivers/spi/spi_controller_peripheral/boards/nrf54h20dk_nrf54h20_cpuapp.overlay index ff337ebdec483..83fd7a89eb906 100644 --- a/tests/drivers/spi/spi_controller_peripheral/boards/nrf54h20dk_nrf54h20_cpuapp.overlay +++ b/tests/drivers/spi/spi_controller_peripheral/boards/nrf54h20dk_nrf54h20_cpuapp.overlay @@ -5,7 +5,7 @@ */ #include "nrf54h20dk_nrf54h20_common.dtsi" -&dut_spi { +&spi130 { memory-regions = <&cpuapp_dma_region>; }; diff --git a/tests/drivers/spi/spi_controller_peripheral/boards/nrf54h20dk_nrf54h20_cpuapp_fast.overlay b/tests/drivers/spi/spi_controller_peripheral/boards/nrf54h20dk_nrf54h20_cpuapp_fast.overlay new file mode 100644 index 0000000000000..0523426db4580 --- /dev/null +++ b/tests/drivers/spi/spi_controller_peripheral/boards/nrf54h20dk_nrf54h20_cpuapp_fast.overlay @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&pinctrl { + spi121_default_alt: spi121_default_alt { + group1 { + psels = , + , + ; + }; + }; + + spi121_sleep_alt: spi121_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"; +}; + +&spi121 { + compatible = "nordic,nrf-spim"; + status = "okay"; + pinctrl-0 = <&spi121_default_alt>; + pinctrl-1 = <&spi121_sleep_alt>; + pinctrl-names = "default", "sleep"; + overrun-character = <0x00>; + memory-regions = <&dma_fast_region>; + cs-gpios = <&gpio0 10 GPIO_ACTIVE_LOW>; + dut_spi_dt: test-spi-dev@0 { + compatible = "vnd,spi-device"; + reg = <0>; + spi-max-frequency = ; + }; +}; + +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"; + memory-regions = <&cpuapp_dma_region>; + /delete-property/rx-delay-supported; + /delete-property/rx-delay; +}; diff --git a/tests/drivers/spi/spi_controller_peripheral/boards/nrf54h20dk_nrf54h20_cpurad.overlay b/tests/drivers/spi/spi_controller_peripheral/boards/nrf54h20dk_nrf54h20_cpurad.overlay index 936bd5b15d541..84edfb2b6f1f6 100644 --- a/tests/drivers/spi/spi_controller_peripheral/boards/nrf54h20dk_nrf54h20_cpurad.overlay +++ b/tests/drivers/spi/spi_controller_peripheral/boards/nrf54h20dk_nrf54h20_cpurad.overlay @@ -5,7 +5,7 @@ */ #include "nrf54h20dk_nrf54h20_common.dtsi" -&dut_spi { +&spi130 { memory-regions = <&cpurad_dma_region>; }; diff --git a/tests/drivers/spi/spi_controller_peripheral/testcase.yaml b/tests/drivers/spi/spi_controller_peripheral/testcase.yaml index 2c6f8974fcc2e..18dfb9db1cdc0 100644 --- a/tests/drivers/spi/spi_controller_peripheral/testcase.yaml +++ b/tests/drivers/spi/spi_controller_peripheral/testcase.yaml @@ -7,36 +7,53 @@ common: platform_allow: | nrf52840dk/nrf52840 nrf54l15pdk/nrf54l15/cpuapp nrf54h20dk/nrf54h20/cpuapp nrf54h20dk/nrf54h20/cpurad - integration_platforms: - - nrf52840dk/nrf52840 tests: drivers.spi.spi_mode0: extra_configs: - CONFIG_TESTED_SPI_MODE=0 extra_args: EXTRA_DTC_OVERLAY_FILE="boards/250khz.overlay" + integration_platforms: + - nrf52840dk/nrf52840 drivers.spi.spi_mode1: extra_configs: - CONFIG_TESTED_SPI_MODE=1 extra_args: EXTRA_DTC_OVERLAY_FILE="boards/500khz.overlay" + integration_platforms: + - nrf52840dk/nrf52840 drivers.spi.spi_mode2: extra_configs: - CONFIG_TESTED_SPI_MODE=2 extra_args: EXTRA_DTC_OVERLAY_FILE="boards/1mhz.overlay" + integration_platforms: + - nrf52840dk/nrf52840 drivers.spi.spi_mode3: extra_configs: - CONFIG_TESTED_SPI_MODE=3 extra_args: EXTRA_DTC_OVERLAY_FILE="boards/2mhz.overlay" + integration_platforms: + - nrf52840dk/nrf52840 drivers.spi.spi_4MHz: extra_configs: - CONFIG_TESTED_SPI_MODE=2 extra_args: EXTRA_DTC_OVERLAY_FILE="boards/4mhz.overlay" + integration_platforms: + - nrf52840dk/nrf52840 drivers.spi.spi_8MHz: extra_configs: - CONFIG_TESTED_SPI_MODE=1 extra_args: EXTRA_DTC_OVERLAY_FILE="boards/8mhz.overlay" + integration_platforms: + - nrf52840dk/nrf52840 + + drivers.spi.spi_fast: + extra_args: DTC_OVERLAY_FILE="boards/nrf54h20dk_nrf54h20_cpuapp_fast.overlay" + platform_exclude: + - nrf52840dk/nrf52840 + - nrf54l15pdk/nrf54l15/cpuapp + - nrf54h20dk/nrf54h20/cpurad diff --git a/tests/drivers/spi/spi_error_cases/boards/nrf54h20dk_nrf54h20_cpuapp_fast.overlay b/tests/drivers/spi/spi_error_cases/boards/nrf54h20dk_nrf54h20_cpuapp_fast.overlay new file mode 100644 index 0000000000000..0523426db4580 --- /dev/null +++ b/tests/drivers/spi/spi_error_cases/boards/nrf54h20dk_nrf54h20_cpuapp_fast.overlay @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&pinctrl { + spi121_default_alt: spi121_default_alt { + group1 { + psels = , + , + ; + }; + }; + + spi121_sleep_alt: spi121_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"; +}; + +&spi121 { + compatible = "nordic,nrf-spim"; + status = "okay"; + pinctrl-0 = <&spi121_default_alt>; + pinctrl-1 = <&spi121_sleep_alt>; + pinctrl-names = "default", "sleep"; + overrun-character = <0x00>; + memory-regions = <&dma_fast_region>; + cs-gpios = <&gpio0 10 GPIO_ACTIVE_LOW>; + dut_spi_dt: test-spi-dev@0 { + compatible = "vnd,spi-device"; + reg = <0>; + spi-max-frequency = ; + }; +}; + +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"; + memory-regions = <&cpuapp_dma_region>; + /delete-property/rx-delay-supported; + /delete-property/rx-delay; +}; diff --git a/tests/drivers/spi/spi_error_cases/boards/nrf54h20dk_nrf54h20_cpuppr.overlay b/tests/drivers/spi/spi_error_cases/boards/nrf54h20dk_nrf54h20_cpuppr.overlay new file mode 100644 index 0000000000000..191d76e0bf9c5 --- /dev/null +++ b/tests/drivers/spi/spi_error_cases/boards/nrf54h20dk_nrf54h20_cpuppr.overlay @@ -0,0 +1,85 @@ +/* + * 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>; +}; + +&cpuapp_dma_region { + status = "okay"; +}; + +&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>; + }; + memory-regions = <&cpuapp_dma_region>; +}; + +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"; + memory-regions = <&cpuapp_dma_region>; + /delete-property/rx-delay-supported; + /delete-property/rx-delay; +}; diff --git a/tests/drivers/spi/spi_error_cases/boards/nrf54h20dk_nrf54h20_cpuppr_launcher.overlay b/tests/drivers/spi/spi_error_cases/boards/nrf54h20dk_nrf54h20_cpuppr_launcher.overlay new file mode 100644 index 0000000000000..6e30d17315519 --- /dev/null +++ b/tests/drivers/spi/spi_error_cases/boards/nrf54h20dk_nrf54h20_cpuppr_launcher.overlay @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&spi130 { + status = "reserved"; + interrupt-parent = <&cpuppr_clic>; +}; + +&spi131 { + status = "reserved"; + interrupt-parent = <&cpuppr_clic>; +}; + +&shared_ram3x_region { + status = "okay"; +}; + +&gpio0 { + status = "reserved"; +}; diff --git a/tests/drivers/spi/spi_error_cases/src/main.c b/tests/drivers/spi/spi_error_cases/src/main.c index 699383e7a171f..4ebca6f1c2e12 100644 --- a/tests/drivers/spi/spi_error_cases/src/main.c +++ b/tests/drivers/spi/spi_error_cases/src/main.c @@ -176,18 +176,6 @@ ZTEST(spi_error_cases, test_unsupported_frequency) zassert_equal(rv, -EINVAL, "Got %d instead", rv); } -ZTEST(spi_error_cases, test_CS_unsupported_on_slave) -{ - int slave_rv; - struct spi_config spis_config_invalid = spis_config; - struct gpio_dt_spec test_gpio = { DEVICE_DT_GET(DT_NODELABEL(gpio0)), 10, GPIO_ACTIVE_LOW }; - - spis_config_invalid.cs.gpio = test_gpio; - - slave_rv = spi_transceive(spis_dev, &spis_config_invalid, tdata.stx_set, tdata.srx_set); - zassert_equal(slave_rv, -EINVAL, "Got %d instead", slave_rv); -} - ZTEST(spi_error_cases, test_spis_scattered_tx_buf_not_supported) { int slave_rv; diff --git a/tests/drivers/spi/spi_error_cases/testcase.yaml b/tests/drivers/spi/spi_error_cases/testcase.yaml index 5f4cfc703930c..ba046ee0292d1 100644 --- a/tests/drivers/spi/spi_error_cases/testcase.yaml +++ b/tests/drivers/spi/spi_error_cases/testcase.yaml @@ -1,13 +1,26 @@ +common: + depends_on: spi + tags: drivers spi + harness: ztest + harness_config: + fixture: gpio_spi_loopback tests: drivers.spi.spi_error_cases: - depends_on: spi - tags: drivers spi - harness: ztest - harness_config: - fixture: gpio_spi_loopback platform_allow: - nrf52840dk/nrf52840 - nrf54l15pdk/nrf54l15/cpuapp - nrf54h20dk/nrf54h20/cpuapp integration_platforms: - nrf52840dk/nrf52840 + drivers.spi.spi_error_cases.fast: + extra_args: DTC_OVERLAY_FILE="boards/nrf54h20dk_nrf54h20_cpuapp_fast.overlay" + platform_allow: + - nrf54h20dk/nrf54h20/cpuapp + drivers.spi.spi_error_cases.nrf54h20_cpuppr: + platform_allow: nrf54h20dk/nrf54h20/cpuppr + sysbuild: true + extra_args: + - vpr_launcher_DTC_OVERLAY_FILE="../../../tests/drivers/spi/spi_error_cases/boards/nrf54h20dk_nrf54h20_cpuppr_launcher.overlay" + - SB_CONFIG_VPR_LAUNCHER=y + # Disable asserts to fit in limited code memory + - CONFIG_ASSERT=n diff --git a/tests/drivers/spi/spi_loopback/boards/nrf54h20dk_nrf54h20_cpuapp_fast.overlay b/tests/drivers/spi/spi_loopback/boards/nrf54h20dk_nrf54h20_cpuapp_fast.overlay new file mode 100644 index 0000000000000..d6c3c972afd33 --- /dev/null +++ b/tests/drivers/spi/spi_loopback/boards/nrf54h20dk_nrf54h20_cpuapp_fast.overlay @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&pinctrl { + spi120_default: spi120_default { + group1 { + psels = , + , + ; + }; + }; + + spi120_sleep: spi120_sleep { + group1 { + psels = , + , + ; + low-power-enable; + }; + }; +}; + +&spi120 { + status = "okay"; + pinctrl-0 = <&spi120_default>; + pinctrl-1 = <&spi120_sleep>; + pinctrl-names = "default", "sleep"; + overrun-character = <0x00>; + memory-regions = <&dma_fast_region>; + slow@0 { + compatible = "test-spi-loopback-slow"; + reg = <0>; + spi-max-frequency = ; + }; + fast@0 { + compatible = "test-spi-loopback-fast"; + reg = <0>; + spi-max-frequency = ; + }; +}; diff --git a/tests/drivers/spi/spi_loopback/testcase.yaml b/tests/drivers/spi/spi_loopback/testcase.yaml index 6c419bab03062..4a858b481c8b8 100644 --- a/tests/drivers/spi/spi_loopback/testcase.yaml +++ b/tests/drivers/spi/spi_loopback/testcase.yaml @@ -169,3 +169,7 @@ tests: filter: CONFIG_DT_HAS_NXP_FLEXIO_ENABLED and CONFIG_DT_HAS_NXP_FLEXIO_SPI_ENABLED platform_allow: mimxrt1064_evk + drivers.spi.nrf_fast: + extra_args: DTC_OVERLAY_FILE="boards/nrf54h20dk_nrf54h20_cpuapp_fast.overlay" + platform_allow: + - nrf54h20dk/nrf54h20/cpuapp From 695e704b5dc30ae1863373cc8f31f62219710051 Mon Sep 17 00:00:00 2001 From: Henrik Brix Andersen Date: Sat, 1 Jun 2024 22:28:09 +0000 Subject: [PATCH 1826/2849] dts: bindings: can: rename bus-speed/bus-speed-data properties Deprecate the CAN controller bus-speed/bus-speed-data properties and rename them to bitrate/bitrate-data to match the terminology used in other CAN devicetree properties and the CAN subsystem API. Signed-off-by: Henrik Brix Andersen --- doc/hardware/peripherals/can/shell.rst | 2 +- doc/releases/migration-guide-3.7.rst | 8 ++++++-- drivers/can/Kconfig | 4 ++-- dts/bindings/can/can-controller.yaml | 8 ++++++++ dts/bindings/can/can-fd-controller.yaml | 8 ++++++++ include/zephyr/drivers/can.h | 7 ++++--- samples/modules/canopennode/src/main.c | 5 +++-- tests/drivers/can/host/README.rst | 2 +- 8 files changed, 33 insertions(+), 11 deletions(-) diff --git a/doc/hardware/peripherals/can/shell.rst b/doc/hardware/peripherals/can/shell.rst index ed36379c55ffe..0457203438d7e 100644 --- a/doc/hardware/peripherals/can/shell.rst +++ b/doc/hardware/peripherals/can/shell.rst @@ -101,7 +101,7 @@ stopping the processing of CAN frames. .. note:: The CAN controller mode and timing can only be changed while the CAN controller is stopped, which is the initial setting upon boot-up. The initial CAN controller mode is set to ``normal`` and the - initial timing is set according to the ``bus-speed``, ``sample-point``, ``bus-speed-data``, and + initial timing is set according to the ``bitrate``, ``sample-point``, ``bitrate-data``, and ``sample-point-data`` :ref:`devicetree` properties. Timing diff --git a/doc/releases/migration-guide-3.7.rst b/doc/releases/migration-guide-3.7.rst index b18522722e1b1..ce86715258151 100644 --- a/doc/releases/migration-guide-3.7.rst +++ b/doc/releases/migration-guide-3.7.rst @@ -247,8 +247,9 @@ Controller Area Network (CAN) ============================= * Removed the following deprecated CAN controller devicetree properties. Out-of-tree boards using - these properties need to switch to using the ``bus-speed``, ``sample-point``, ``bus-speed-data``, - and ``sample-point-data`` devicetree properties for specifying the initial CAN bitrate: + these properties can switch to using the ``bitrate``, ``sample-point``, ``bitrate-data``, and + ``sample-point-data`` devicetree properties (or rely on :kconfig:option:`CAN_DEFAULT_BITRATE` and + :kconfig:option:`CAN_DEFAULT_BITRATE_DATA`) for specifying the initial CAN bitrate: * ``sjw`` * ``prop-seg`` @@ -259,6 +260,9 @@ Controller Area Network (CAN) * ``phase-seg1-data`` * ``phase-seg1-data`` + The ``bus-speed`` and ``bus-speed-data`` CAN controller devicetree properties have been + deprecated. + (:github:`68714`) * Support for manual bus-off recovery was reworked (:github:`69460`): diff --git a/drivers/can/Kconfig b/drivers/can/Kconfig index df1bf5f7f6c57..5aa956353dc21 100644 --- a/drivers/can/Kconfig +++ b/drivers/can/Kconfig @@ -28,7 +28,7 @@ config CAN_DEFAULT_BITRATE default 125000 help Default initial CAN bitrate in bits/s. This can be overridden per CAN controller using the - "bus-speed" devicetree property. + "bitrate" devicetree property. config CAN_DEFAULT_BITRATE_DATA int "Default CAN data phase bitrate" @@ -36,7 +36,7 @@ config CAN_DEFAULT_BITRATE_DATA 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. + using the "bitrate-data" devicetree property. config CAN_SHELL bool "CAN shell" diff --git a/dts/bindings/can/can-controller.yaml b/dts/bindings/can/can-controller.yaml index 55322b50a21e9..e2825b6e6763b 100644 --- a/dts/bindings/can/can-controller.yaml +++ b/dts/bindings/can/can-controller.yaml @@ -4,6 +4,14 @@ include: base.yaml properties: bus-speed: + type: int + deprecated: true + description: | + Deprecated. This property has been renamed to bitrate. + + Initial bitrate in bit/s. If this is unset, the initial bitrate is set to + CONFIG_CAN_DEFAULT_BITRATE. + bitrate: type: int description: | Initial bitrate in bit/s. If this is unset, the initial bitrate is set to diff --git a/dts/bindings/can/can-fd-controller.yaml b/dts/bindings/can/can-fd-controller.yaml index 9efc7823f94fd..ea357b832240e 100644 --- a/dts/bindings/can/can-fd-controller.yaml +++ b/dts/bindings/can/can-fd-controller.yaml @@ -4,6 +4,14 @@ include: can-controller.yaml properties: bus-speed-data: + type: int + deprecated: true + description: | + Deprecated. This property has been renamed to bitrate-data. + + Initial data phase bitrate in bit/s. If this is unset, the initial data phase bitrate is set + to CONFIG_CAN_DEFAULT_BITRATE_DATA. + bitrate-data: type: int description: | Initial data phase bitrate in bit/s. If this is unset, the initial data phase bitrate is set diff --git a/include/zephyr/drivers/can.h b/include/zephyr/drivers/can.h index bf3af29ede29e..8dbf7c89e48e9 100644 --- a/include/zephyr/drivers/can.h +++ b/include/zephyr/drivers/can.h @@ -374,11 +374,12 @@ 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_OR(node_id, bus_speed, CONFIG_CAN_DEFAULT_BITRATE), \ + .bus_speed = DT_PROP_OR(node_id, bitrate, \ + 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, \ - CONFIG_CAN_DEFAULT_BITRATE_DATA), \ + (.bus_speed_data = DT_PROP_OR(node_id, bitrate_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 60c3ebaa6dfe6..e741f569466ae 100644 --- a/samples/modules/canopennode/src/main.c +++ b/samples/modules/canopennode/src/main.c @@ -15,8 +15,9 @@ LOG_MODULE_REGISTER(app); #define CAN_INTERFACE DEVICE_DT_GET(DT_CHOSEN(zephyr_canbus)) -#define CAN_BITRATE (DT_PROP_OR(DT_CHOSEN(zephyr_canbus), bus_speed, \ - CONFIG_CAN_DEFAULT_BITRATE) / 1000) +#define CAN_BITRATE (DT_PROP_OR(DT_CHOSEN(zephyr_canbus), 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}); diff --git a/tests/drivers/can/host/README.rst b/tests/drivers/can/host/README.rst index 7f8b15936afce..bc1dca4d73c05 100644 --- a/tests/drivers/can/host/README.rst +++ b/tests/drivers/can/host/README.rst @@ -22,7 +22,7 @@ The Zephyr end of the CAN fixture can be configured as follows: * The CAN controller to be used is set using the ``zephyr,canbus`` chosen devicetree node. * The CAN bitrates are set using :kconfig:option:`CONFIG_CAN_DEFAULT_BITRATE` and :kconfig:option:`CONFIG_CAN_DEFAULT_BITRATE_DATA`, but can be overridden on a board level using - the ``bus-speed`` and ``bus-speed-data`` CAN controller devicetree properties if needed. Default + the ``bitrate`` and ``bitrate-data`` CAN controller devicetree properties if needed. Default bitrates are 125 kbits/s for the arbitration phase/CAN classic and 1 Mbit/s for the CAN FD data phase when using bitrate switching (BRS). From 68096cedaec816f7bfa46604a59a419bf21d4880 Mon Sep 17 00:00:00 2001 From: Henrik Brix Andersen Date: Mon, 3 Jun 2024 13:52:55 +0200 Subject: [PATCH 1827/2849] drivers: can: rename struct can_driver_config fields Rename the "bus_speed" and "bus_speed_data" fields of struct can_driver_config to "bitrate" and "bitrate_data" to match the corresponding devicetree properties and the terminology used in the rest of the CAN subsystem API. Signed-off-by: Henrik Brix Andersen --- doc/releases/release-notes-3.7.rst | 2 ++ drivers/can/can_mcan.c | 4 ++-- drivers/can/can_mcp2515.c | 2 +- drivers/can/can_mcp251xfd.c | 4 ++-- drivers/can/can_mcux_flexcan.c | 4 ++-- drivers/can/can_nxp_s32_canxl.c | 8 ++++---- drivers/can/can_rcar.c | 2 +- drivers/can/can_sja1000.c | 2 +- drivers/can/can_stm32_bxcan.c | 2 +- drivers/can/can_xmc4xxx.c | 2 +- include/zephyr/drivers/can.h | 8 ++++---- 11 files changed, 21 insertions(+), 19 deletions(-) diff --git a/doc/releases/release-notes-3.7.rst b/doc/releases/release-notes-3.7.rst index 4cdaedb5a8197..dda728bad3750 100644 --- a/doc/releases/release-notes-3.7.rst +++ b/doc/releases/release-notes-3.7.rst @@ -265,6 +265,8 @@ Drivers and Sensors * Updated the CAN timing functions to take the minimum supported bitrate into consideration when validating the bitrate. * Made the ``sample-point`` and ``sample-point-data`` devicetree properties optional. + * Renamed the ``bus_speed`` and ``bus_speed_data`` fields of :c:struct:`can_driver_config` to + ``bitrate`` and ``bitrate_data``. * Charger diff --git a/drivers/can/can_mcan.c b/drivers/can/can_mcan.c index 56ac2225b89a3..c4a94d49cfaa4 100644 --- a/drivers/can/can_mcan.c +++ b/drivers/can/can_mcan.c @@ -1466,7 +1466,7 @@ int can_mcan_init(const struct device *dev) return err; } - err = can_calc_timing(dev, &timing, config->common.bus_speed, + err = can_calc_timing(dev, &timing, config->common.bitrate, config->common.sample_point); if (err == -EINVAL) { LOG_ERR("Can't find timing for given param"); @@ -1477,7 +1477,7 @@ int can_mcan_init(const struct device *dev) timing.phase_seg2); LOG_DBG("Sample-point err : %d", err); #ifdef CONFIG_CAN_FD_MODE - err = can_calc_timing_data(dev, &timing_data, config->common.bus_speed_data, + err = can_calc_timing_data(dev, &timing_data, config->common.bitrate_data, config->common.sample_point_data); if (err == -EINVAL) { LOG_ERR("Can't find timing for given dataphase param"); diff --git a/drivers/can/can_mcp2515.c b/drivers/can/can_mcp2515.c index b7720a7ab47ae..791f548cec5b4 100644 --- a/drivers/can/can_mcp2515.c +++ b/drivers/can/can_mcp2515.c @@ -972,7 +972,7 @@ static int mcp2515_init(const struct device *dev) (void)memset(dev_data->filter, 0, sizeof(dev_data->filter)); dev_data->old_state = CAN_STATE_ERROR_ACTIVE; - ret = can_calc_timing(dev, &timing, dev_cfg->common.bus_speed, + ret = can_calc_timing(dev, &timing, dev_cfg->common.bitrate, dev_cfg->common.sample_point); if (ret == -EINVAL) { LOG_ERR("Can't find timing for given param"); diff --git a/drivers/can/can_mcp251xfd.c b/drivers/can/can_mcp251xfd.c index 8e1fef06168ee..ae347296eeb3a 100644 --- a/drivers/can/can_mcp251xfd.c +++ b/drivers/can/can_mcp251xfd.c @@ -1576,7 +1576,7 @@ static int mcp251xfd_init(const struct device *dev) goto done; } - ret = can_calc_timing(dev, &timing, dev_cfg->common.bus_speed, + ret = can_calc_timing(dev, &timing, dev_cfg->common.bitrate, dev_cfg->common.sample_point); if (ret < 0) { LOG_ERR("Can't find timing for given param"); @@ -1588,7 +1588,7 @@ static int mcp251xfd_init(const struct device *dev) LOG_DBG("Sample-point err : %d", ret); #if defined(CONFIG_CAN_FD_MODE) - ret = can_calc_timing_data(dev, &timing_data, dev_cfg->common.bus_speed_data, + ret = can_calc_timing_data(dev, &timing_data, dev_cfg->common.bitrate_data, dev_cfg->common.sample_point_data); if (ret < 0) { LOG_ERR("Can't find data timing for given param"); diff --git a/drivers/can/can_mcux_flexcan.c b/drivers/can/can_mcux_flexcan.c index c4109c89c610d..562d02650aa27 100644 --- a/drivers/can/can_mcux_flexcan.c +++ b/drivers/can/can_mcux_flexcan.c @@ -1139,7 +1139,7 @@ static int mcux_flexcan_init(const struct device *dev) k_sem_init(&data->tx_allocs_sem, MCUX_FLEXCAN_MAX_TX, MCUX_FLEXCAN_MAX_TX); - err = can_calc_timing(dev, &data->timing, config->common.bus_speed, + err = can_calc_timing(dev, &data->timing, config->common.bitrate, config->common.sample_point); if (err == -EINVAL) { LOG_ERR("Can't find timing for given param"); @@ -1160,7 +1160,7 @@ static int mcux_flexcan_init(const struct device *dev) #ifdef CONFIG_CAN_MCUX_FLEXCAN_FD if (config->flexcan_fd) { err = can_calc_timing_data(dev, &data->timing_data, - config->common.bus_speed_data, + config->common.bitrate_data, config->common.sample_point_data); if (err == -EINVAL) { LOG_ERR("Can't find timing for given param"); diff --git a/drivers/can/can_nxp_s32_canxl.c b/drivers/can/can_nxp_s32_canxl.c index 9d1e2626ab010..94e75c04f9b23 100644 --- a/drivers/can/can_nxp_s32_canxl.c +++ b/drivers/can/can_nxp_s32_canxl.c @@ -931,7 +931,7 @@ static int can_nxp_s32_init(const struct device *dev) IP_MC_RGM->PRST_0[0].PRST_0 &= ~(MC_RGM_PRST_0_PERIPH_16_RST_MASK | MC_RGM_PRST_0_PERIPH_24_RST_MASK); - err = can_calc_timing(dev, &data->timing, config->common.bus_speed, + err = can_calc_timing(dev, &data->timing, config->common.bitrate, config->common.sample_point); if (err == -EINVAL) { LOG_ERR("Can't find timing for given param"); @@ -942,11 +942,11 @@ static int can_nxp_s32_init(const struct device *dev) LOG_WRN("Sample-point error : %d", err); } - LOG_DBG("Setting CAN bitrate %d:", config->common.bus_speed); + LOG_DBG("Setting CAN bitrate %d:", config->common.bitrate); nxp_s32_zcan_timing_to_canxl_timing(&data->timing, &config->can_cfg->bitrate); #ifdef CAN_NXP_S32_FD_MODE - err = can_calc_timing_data(dev, &data->timing_data, config->common.bus_speed_data, + err = can_calc_timing_data(dev, &data->timing_data, config->common.bitrate_data, config->common.sample_point_data); if (err == -EINVAL) { LOG_ERR("Can't find timing data for given param"); @@ -957,7 +957,7 @@ static int can_nxp_s32_init(const struct device *dev) LOG_WRN("Sample-point-data err : %d", err); } - LOG_DBG("Setting CAN FD bitrate %d:", config->common.bus_speed_data); + LOG_DBG("Setting CAN FD bitrate %d:", config->common.bitrate_data); nxp_s32_zcan_timing_to_canxl_timing(&data->timing_data, &config->can_cfg->Fd_bitrate); #endif diff --git a/drivers/can/can_rcar.c b/drivers/can/can_rcar.c index d1607a6797a93..23bd82896cbe8 100644 --- a/drivers/can/can_rcar.c +++ b/drivers/can/can_rcar.c @@ -1075,7 +1075,7 @@ static int can_rcar_init(const struct device *dev) return ret; } - ret = can_calc_timing(dev, &timing, config->common.bus_speed, + ret = can_calc_timing(dev, &timing, config->common.bitrate, config->common.sample_point); if (ret == -EINVAL) { LOG_ERR("Can't find timing for given param"); diff --git a/drivers/can/can_sja1000.c b/drivers/can/can_sja1000.c index 871f0fdb00ddd..758715bb44303 100644 --- a/drivers/can/can_sja1000.c +++ b/drivers/can/can_sja1000.c @@ -781,7 +781,7 @@ int can_sja1000_init(const struct device *dev) can_sja1000_write_reg(dev, CAN_SJA1000_AMR2, 0xFF); can_sja1000_write_reg(dev, CAN_SJA1000_AMR3, 0xFF); - err = can_calc_timing(dev, &timing, config->common.bus_speed, + err = can_calc_timing(dev, &timing, config->common.bitrate, config->common.sample_point); if (err == -EINVAL) { LOG_ERR("bitrate/sample point cannot be met (err %d)", err); diff --git a/drivers/can/can_stm32_bxcan.c b/drivers/can/can_stm32_bxcan.c index c21099c04b3a0..5c3e44dfd0c3c 100644 --- a/drivers/can/can_stm32_bxcan.c +++ b/drivers/can/can_stm32_bxcan.c @@ -659,7 +659,7 @@ static int can_stm32_init(const struct device *dev) /* Enable automatic bus-off recovery */ can->MCR |= CAN_MCR_ABOM; - ret = can_calc_timing(dev, &timing, cfg->common.bus_speed, + ret = can_calc_timing(dev, &timing, cfg->common.bitrate, cfg->common.sample_point); if (ret == -EINVAL) { LOG_ERR("Can't find timing for given param"); diff --git a/drivers/can/can_xmc4xxx.c b/drivers/can/can_xmc4xxx.c index 8eddf05b96ea9..2704ef1b44edb 100644 --- a/drivers/can/can_xmc4xxx.c +++ b/drivers/can/can_xmc4xxx.c @@ -869,7 +869,7 @@ static int can_xmc4xxx_init(const struct device *dev) } #endif - ret = can_calc_timing(dev, &timing, dev_cfg->common.bus_speed, + ret = can_calc_timing(dev, &timing, dev_cfg->common.bitrate, dev_cfg->common.sample_point); if (ret < 0) { return ret; diff --git a/include/zephyr/drivers/can.h b/include/zephyr/drivers/can.h index 8dbf7c89e48e9..9dee92ddd69fc 100644 --- a/include/zephyr/drivers/can.h +++ b/include/zephyr/drivers/can.h @@ -351,14 +351,14 @@ struct can_driver_config { /** The maximum bitrate supported by the CAN controller/transceiver combination. */ uint32_t max_bitrate; /** Initial CAN classic/CAN FD arbitration phase bitrate. */ - uint32_t bus_speed; + uint32_t bitrate; /** Initial CAN classic/CAN FD arbitration phase sample point in permille. */ uint16_t sample_point; #ifdef CONFIG_CAN_FD_MODE /** Initial CAN FD data phase sample point in permille. */ uint16_t sample_point_data; /** Initial CAN FD data phase bitrate. */ - uint32_t bus_speed_data; + uint32_t bitrate_data; #endif /* CONFIG_CAN_FD_MODE */ }; @@ -374,11 +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_OR(node_id, bitrate, \ + .bitrate = DT_PROP_OR(node_id, bitrate, \ 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, bitrate_data, \ + (.bitrate_data = DT_PROP_OR(node_id, bitrate_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),)) \ } From d3081e2f30fd17a1e737db378d1b1e3cecf53fb2 Mon Sep 17 00:00:00 2001 From: Seppo Takalo Date: Mon, 3 Jun 2024 13:22:13 +0300 Subject: [PATCH 1828/2849] net: lwm2m: On write, use server selected block size When we receive CoAP packets, it is in input buffer that is size of NET_IPV6_MTU. So in reality, we can handle bigger Block-Wise writes than CONFIG_LWM2M_COAP_BLOCK_SIZE. So if parsing of CoAP packet has passed, continue with the same block-size instead of going to default. Signed-off-by: Seppo Takalo --- subsys/net/lib/lwm2m/lwm2m_message_handling.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/subsys/net/lib/lwm2m/lwm2m_message_handling.c b/subsys/net/lib/lwm2m/lwm2m_message_handling.c index b9457565fc953..427912977e9e2 100644 --- a/subsys/net/lib/lwm2m/lwm2m_message_handling.c +++ b/subsys/net/lib/lwm2m/lwm2m_message_handling.c @@ -2066,6 +2066,10 @@ static int parse_write_op(struct lwm2m_message *msg, uint16_t format) free_block_ctx(block_ctx); r = init_block_ctx(&msg->path, &block_ctx); + /* If we have already parsed the packet, we can handle the block size + * given by the server. + */ + block_ctx->ctx.block_size = block_size; } if (r < 0) { From 72715531e400bcaa08564399af3c7c9de7f5d167 Mon Sep 17 00:00:00 2001 From: Henrik Brix Andersen Date: Wed, 5 Jun 2024 17:32:37 +0000 Subject: [PATCH 1829/2849] boards: nxp: imx93_evk: remove deprecated CAN controller properties Remove the deprecated CAN controller properties "bus-speed" and "bus-speed-data" and rely on the Kconfig defaults. Signed-off-by: Henrik Brix Andersen --- boards/nxp/imx93_evk/imx93_evk_mimx9352_a55.dts | 2 -- 1 file changed, 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 f68fb2094661c..46cd1aa6ae790 100644 --- a/boards/nxp/imx93_evk/imx93_evk_mimx9352_a55.dts +++ b/boards/nxp/imx93_evk/imx93_evk_mimx9352_a55.dts @@ -159,8 +159,6 @@ &flexcan2 { pinctrl-0 = <&flexcan2_default>; pinctrl-names = "default"; - bus-speed = <125000>; - bus-speed-data = <1000000>; phys = <&can_phy0>; status = "okay"; }; From 285969c98c1103dc67e963add859df0885e75409 Mon Sep 17 00:00:00 2001 From: Ioannis Damigos Date: Mon, 27 May 2024 12:54:46 +0300 Subject: [PATCH 1830/2849] scripts/kconfig: Introduce dt_node_ph_prop_path function Introduce dt_node_ph_prop_path function. It takes a node 'path' and a phandle property name and returns the path to the pointed-to node. Signed-off-by: Ioannis Damigos --- scripts/kconfig/kconfigfunctions.py | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/scripts/kconfig/kconfigfunctions.py b/scripts/kconfig/kconfigfunctions.py index 58fcf9c6a1886..94cb46d3f6b5c 100644 --- a/scripts/kconfig/kconfigfunctions.py +++ b/scripts/kconfig/kconfigfunctions.py @@ -657,6 +657,32 @@ def dt_node_ph_array_prop(kconf, name, path, prop, index, cell, unit=None): if name == "dt_node_ph_array_prop_hex": return hex(_node_ph_array_prop(node, prop, index, cell, unit)) +def dt_node_ph_prop_path(kconf, name, path, prop): + """ + This function takes a 'path' and a property name ('prop') and + looks for an EDT node at that path. If it finds an EDT node, + it will look to see if that node has a property called 'prop' + and if that 'prop' is an phandle type. Then it will return the + path to the pointed-to node, or an empty string if there is + no such node. + """ + if doc_mode or edt is None: + return "" + + try: + node = edt.get_node(path) + except edtlib.EDTError: + return "" + + if prop not in node.props: + return "" + if node.props[prop].type != "phandle": + return "" + + phandle = node.props[prop].val + + return phandle.path if phandle else "" + def dt_node_str_prop_equals(kconf, _, path, prop, val): """ This function takes a 'path' and property name ('prop') looks for an EDT @@ -920,6 +946,7 @@ def substring(kconf, _, string, start, stop=None): "dt_node_array_prop_hex": (dt_node_array_prop, 3, 4), "dt_node_ph_array_prop_int": (dt_node_ph_array_prop, 4, 5), "dt_node_ph_array_prop_hex": (dt_node_ph_array_prop, 4, 5), + "dt_node_ph_prop_path": (dt_node_ph_prop_path, 2, 2), "dt_node_str_prop_equals": (dt_node_str_prop_equals, 3, 3), "dt_nodelabel_has_compat": (dt_nodelabel_has_compat, 2, 2), "dt_node_has_compat": (dt_node_has_compat, 2, 2), From 9c8fd3745c29f423527bfa971240fbedb55acb3b Mon Sep 17 00:00:00 2001 From: Ioannis Damigos Date: Mon, 3 Jun 2024 11:32:50 +0300 Subject: [PATCH 1831/2849] kconfigfunctions.py: Fix used-before-assignment error with pylint 3.2 CI reports error: kconfigfunctions.py:143:11: E0601: Using variable 'edtlib' before assignment (used-before-assignment) Initialize edtlib to none when there is no edt. Signed-off-by: Ioannis Damigos --- scripts/kconfig/kconfigfunctions.py | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/kconfig/kconfigfunctions.py b/scripts/kconfig/kconfigfunctions.py index 94cb46d3f6b5c..75b964e0f72ac 100644 --- a/scripts/kconfig/kconfigfunctions.py +++ b/scripts/kconfig/kconfigfunctions.py @@ -29,6 +29,7 @@ edtlib = inspect.getmodule(edt) else: edt = None + edtlib = None def _warn(kconf, msg): From e414acfabcc6d948d83136f32971b49b8349f9e6 Mon Sep 17 00:00:00 2001 From: Frode van der Meeren Date: Mon, 27 May 2024 16:51:50 +0200 Subject: [PATCH 1832/2849] Bluetooth: Tester: Adjust bap ext adv options This change removes the BT_LE_PER_ADV_OPT_USE_TX_POWER option for extended advertisement in BLE Audio PTS tests. The Broadcaster setup options was hardcoded to include the BT_LE_PER_ADV_OPT_USE_TX_POWER option. This causes incompabilities for any controller not support it, and since the option is not required for the audio tests it should not be used here. signed-off-by: Frode van der Meeren --- tests/bluetooth/tester/src/btp_bap_broadcast.c | 2 +- tests/bluetooth/tester/src/btp_cap.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/bluetooth/tester/src/btp_bap_broadcast.c b/tests/bluetooth/tester/src/btp_bap_broadcast.c index 75b2ed716e86e..f213475d055b0 100644 --- a/tests/bluetooth/tester/src/btp_bap_broadcast.c +++ b/tests/bluetooth/tester/src/btp_bap_broadcast.c @@ -360,7 +360,7 @@ uint8_t btp_bap_broadcast_source_setup(const void *cmd, uint16_t cmd_len, err = tester_gap_padv_configure(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_USE_TX_POWER)); + BT_LE_PER_ADV_OPT_NONE)); if (err != 0) { LOG_DBG("Failed to configure periodic advertising: %d", err); diff --git a/tests/bluetooth/tester/src/btp_cap.c b/tests/bluetooth/tester/src/btp_cap.c index 58d34bd06511a..7a46a19dc88b9 100644 --- a/tests/bluetooth/tester/src/btp_cap.c +++ b/tests/bluetooth/tester/src/btp_cap.c @@ -569,7 +569,7 @@ static int cap_broadcast_source_adv_setup(struct btp_bap_broadcast_local_source err = tester_gap_padv_configure(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_USE_TX_POWER)); + BT_LE_PER_ADV_OPT_NONE)); if (err != 0) { LOG_DBG("Failed to configure periodic advertising: %d", err); From 8bae146a6049e231d3fd5a617819951e41e3f6ad Mon Sep 17 00:00:00 2001 From: Abderrahmane Jarmouni Date: Tue, 21 May 2024 02:31:38 +0200 Subject: [PATCH 1833/2849] dts: bindings: power: stm32 pwr peripheral & wake-up pins Add DT binding for stm32 PWR peripheral that controlls wake-up pins. This binding primarily introduces wake-up pins configuration in a unifed way that takes into consideration the variations between STM32 SoC series & facilitates the association of GPIO pins with their corresponding wake-up pins. Signed-off-by: Abderrahmane Jarmouni --- dts/bindings/power/st,stm32-pwr.yaml | 67 ++++++++++++++++++++ include/zephyr/dt-bindings/power/stm32_pwr.h | 28 ++++++++ 2 files changed, 95 insertions(+) create mode 100644 dts/bindings/power/st,stm32-pwr.yaml create mode 100644 include/zephyr/dt-bindings/power/stm32_pwr.h diff --git a/dts/bindings/power/st,stm32-pwr.yaml b/dts/bindings/power/st,stm32-pwr.yaml new file mode 100644 index 0000000000000..84b67104dac7d --- /dev/null +++ b/dts/bindings/power/st,stm32-pwr.yaml @@ -0,0 +1,67 @@ +# Copyright (c) 2023 STMicroelectronics +# SPDX-License-Identifier: Apache-2.0 + +description: STM32 power controller + +compatible: "st,stm32-pwr" + +include: base.yaml + +properties: + reg: + required: true + + wkup-pins-nb: + type: int + description: | + Max nbr of system wake-up pins. + For example wkup-pins-nb = <8>; on the stm32u5 + + wkup-pin-srcs: + type: int + description: | + Number of wake-up GPIO sources to select from for each wake-up pin. + If not specified, that means there is only 1 GPIO source for each + wake-up pin. + + For example, each wake-up pin on STM32U5 is associated with + 4 wake-up sources, 3 of them correspond to GPIOs. + + wkup-pins-pol: + type: boolean + description: | + True if SoC has a wake-up pins polarity config register + + wkup-pins-pupd: + type: boolean + description: | + True if SoC has pull-up/down config register(s) for GPIO ports + that are associated with wake-up pins. + + "#address-cells": + const: 1 + + "#size-cells": + const: 0 + +child-binding: + description: | + STM32 wake-up pin node. + + All nodes using this binding must be named "wkup-pin@[index]" + index starts from 1 + + properties: + reg: + type: array + required: true + description: Wake-up pin identifier, same as "index" in node name + + wkup-gpios: + type: phandle-array + description: | + Specifies the GPIOs, if any, that are associated with the wake-up pin. + + For example, for GPIO B2 associated with wakeup source 1 on wake-up + pin 1 on STM32U5 SoCs: + wkup-gpios = <&gpiob 2 STM32_PWR_WKUP_PIN_SRC_1>, <...>; diff --git a/include/zephyr/dt-bindings/power/stm32_pwr.h b/include/zephyr/dt-bindings/power/stm32_pwr.h new file mode 100644 index 0000000000000..8c7962f14ada8 --- /dev/null +++ b/include/zephyr/dt-bindings/power/stm32_pwr.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2023 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_POWER_STM32_PWR_H_ +#define ZEPHYR_INCLUDE_DT_BINDINGS_POWER_STM32_PWR_H_ + +/** + * @brief STM32 power controller + * @{ + */ + +/** + * @name flags for wake-up pins sources + * @{ + */ + +#define STM32_PWR_WKUP_PIN_SRC_0 0 +#define STM32_PWR_WKUP_PIN_SRC_1 1 +#define STM32_PWR_WKUP_PIN_SRC_2 (1 << 2) + +/** @} */ + +/** @} */ + +#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_POWER_STM32_PWR_H_ */ From ede21b54d033edb5daddf8c55d7a9017e3469777 Mon Sep 17 00:00:00 2001 From: Abderrahmane Jarmouni Date: Sun, 31 Dec 2023 17:29:58 +0100 Subject: [PATCH 1834/2849] dts: arm: st: add pwr peripheral & wake-up pins nodes Add devicetree node of stm32 PWR peripheral that controlls wake-up pins. The new node includes child nodes for wake-up pins configuration. We only add these nodes for STM32 SoC series that support Poweroff. Signed-off-by: Abderrahmane Jarmouni --- dts/arm/st/l4/stm32l4.dtsi | 34 ++++++++++++++++ dts/arm/st/l4/stm32l4r5Xi.dtsi | 23 +++++++++++ dts/arm/st/u5/stm32u5.dtsi | 71 ++++++++++++++++++++++++++++++++++ dts/arm/st/wb/stm32wb.dtsi | 24 ++++++++++++ dts/arm/st/wb/stm32wb55Xg.dtsi | 18 +++++++++ dts/arm/st/wl/stm32wl.dtsi | 29 ++++++++++++++ 6 files changed, 199 insertions(+) diff --git a/dts/arm/st/l4/stm32l4.dtsi b/dts/arm/st/l4/stm32l4.dtsi index e6e87879b95a4..03e7734f75942 100644 --- a/dts/arm/st/l4/stm32l4.dtsi +++ b/dts/arm/st/l4/stm32l4.dtsi @@ -17,6 +17,7 @@ #include #include #include +#include #include / { @@ -469,6 +470,39 @@ <&rcc STM32_SRC_MSI CLK48_SEL(3)>; status = "disabled"; }; + + pwr: power@40007000 { + compatible = "st,stm32-pwr"; + reg = <0x40007000 0x400>; /* PWR register bank */ + status = "disabled"; + + wkup-pins-nb = <5>; /* 5 system wake-up pins */ + wkup-pins-pol; + wkup-pins-pupd; + + #address-cells = <1>; + #size-cells = <0>; + + wkup-pin@1 { + reg = <0x1>; + }; + + wkup-pin@2 { + reg = <0x2>; + }; + + wkup-pin@3 { + reg = <0x3>; + }; + + wkup-pin@4 { + reg = <0x4>; + }; + + wkup-pin@5 { + reg = <0x5>; + }; + }; }; die_temp: dietemp { diff --git a/dts/arm/st/l4/stm32l4r5Xi.dtsi b/dts/arm/st/l4/stm32l4r5Xi.dtsi index 9154d8820f8be..5da6f035e7693 100644 --- a/dts/arm/st/l4/stm32l4r5Xi.dtsi +++ b/dts/arm/st/l4/stm32l4r5Xi.dtsi @@ -1,5 +1,6 @@ /* * Copyright (c) 2018 Pushpal Sidhu + * Copyright (c) 2024 STMicroelectronics * * SPDX-License-Identifier: Apache-2.0 */ @@ -16,3 +17,25 @@ }; }; }; + +&pwr { + wkup-pin@1 { + wkup-gpios = <&gpioa 0 STM32_PWR_WKUP_PIN_SRC_0>; + }; + + wkup-pin@2 { + wkup-gpios = <&gpioc 13 STM32_PWR_WKUP_PIN_SRC_0>; + }; + + wkup-pin@3 { + wkup-gpios = <&gpioe 6 STM32_PWR_WKUP_PIN_SRC_0>; + }; + + wkup-pin@4 { + wkup-gpios = <&gpioa 2 STM32_PWR_WKUP_PIN_SRC_0>; + }; + + wkup-pin@5 { + wkup-gpios = <&gpioc 5 STM32_PWR_WKUP_PIN_SRC_0>; + }; +}; diff --git a/dts/arm/st/u5/stm32u5.dtsi b/dts/arm/st/u5/stm32u5.dtsi index 642431a52ecae..4a7f2a1fe4387 100644 --- a/dts/arm/st/u5/stm32u5.dtsi +++ b/dts/arm/st/u5/stm32u5.dtsi @@ -19,6 +19,7 @@ #include #include #include +#include #include / { @@ -841,6 +842,76 @@ }; }; + pwr: power@46020800 { + compatible = "st,stm32-pwr"; + reg = <0x46020800 0x400>; /* PWR register bank */ + status = "disabled"; + + wkup-pins-nb = <8>; /* 8 system wake-up pins */ + wkup-pin-srcs = <3>; /* 3 gpio sources associated with each wkup pin */ + wkup-pins-pol; + wkup-pins-pupd; + + #address-cells = <1>; + #size-cells = <0>; + + wkup-pin@1 { + reg = <0x1>; + wkup-gpios = <&gpioa 0 STM32_PWR_WKUP_PIN_SRC_0>, + <&gpiob 2 STM32_PWR_WKUP_PIN_SRC_1>, + <&gpioe 4 STM32_PWR_WKUP_PIN_SRC_2>; + }; + + wkup-pin@2 { + reg = <0x2>; + wkup-gpios = <&gpioa 4 STM32_PWR_WKUP_PIN_SRC_0>, + <&gpioc 13 STM32_PWR_WKUP_PIN_SRC_1>, + <&gpioe 5 STM32_PWR_WKUP_PIN_SRC_2>; + }; + + wkup-pin@3 { + reg = <0x3>; + wkup-gpios = <&gpioe 6 STM32_PWR_WKUP_PIN_SRC_0>, + <&gpioa 1 STM32_PWR_WKUP_PIN_SRC_1>, + <&gpiob 6 STM32_PWR_WKUP_PIN_SRC_2>; + }; + + wkup-pin@4 { + reg = <0x4>; + wkup-gpios = <&gpioa 2 STM32_PWR_WKUP_PIN_SRC_0>, + <&gpiob 1 STM32_PWR_WKUP_PIN_SRC_1>, + <&gpiob 7 STM32_PWR_WKUP_PIN_SRC_2>; + }; + + wkup-pin@5 { + reg = <0x5>; + wkup-gpios = <&gpioc 5 STM32_PWR_WKUP_PIN_SRC_0>, + <&gpioa 3 STM32_PWR_WKUP_PIN_SRC_1>, + <&gpiob 8 STM32_PWR_WKUP_PIN_SRC_2>; + }; + + wkup-pin@6 { + reg = <0x6>; + wkup-gpios = <&gpiob 5 STM32_PWR_WKUP_PIN_SRC_0>, + <&gpioa 5 STM32_PWR_WKUP_PIN_SRC_1>, + <&gpioe 7 STM32_PWR_WKUP_PIN_SRC_2>; + }; + + wkup-pin@7 { + reg = <0x7>; + wkup-gpios = <&gpiob 15 STM32_PWR_WKUP_PIN_SRC_0>, + <&gpioa 6 STM32_PWR_WKUP_PIN_SRC_1>, + <&gpioe 8 STM32_PWR_WKUP_PIN_SRC_2>; + }; + + wkup-pin@8 { + reg = <0x8>; + wkup-gpios = <&gpiof 2 STM32_PWR_WKUP_PIN_SRC_0>, + <&gpioa 7 STM32_PWR_WKUP_PIN_SRC_1>, + <&gpiob 10 STM32_PWR_WKUP_PIN_SRC_2>; + }; + }; + }; swj_port: swj_port { diff --git a/dts/arm/st/wb/stm32wb.dtsi b/dts/arm/st/wb/stm32wb.dtsi index acd8d3c0fd89f..a972f3ef9c6d6 100644 --- a/dts/arm/st/wb/stm32wb.dtsi +++ b/dts/arm/st/wb/stm32wb.dtsi @@ -16,6 +16,7 @@ #include #include #include +#include #include / { @@ -512,6 +513,29 @@ interrupts = <51 0>; status = "disabled"; }; + + pwr: power@58000400 { + compatible = "st,stm32-pwr"; + reg = <0x58000400 0x400>; /* PWR register bank */ + status = "disabled"; + + wkup-pins-nb = <5>; /* 5 system wake-up pins */ + wkup-pins-pol; + wkup-pins-pupd; + + #address-cells = <1>; + #size-cells = <0>; + + wkup-pin@1 { + reg = <0x1>; + wkup-gpios = <&gpioa 0 STM32_PWR_WKUP_PIN_SRC_0>; + }; + + wkup-pin@4 { + reg = <0x4>; + wkup-gpios = <&gpioa 2 STM32_PWR_WKUP_PIN_SRC_0>; + }; + }; }; die_temp: dietemp { diff --git a/dts/arm/st/wb/stm32wb55Xg.dtsi b/dts/arm/st/wb/stm32wb55Xg.dtsi index 91592e8778df3..c3a7d391e7752 100644 --- a/dts/arm/st/wb/stm32wb55Xg.dtsi +++ b/dts/arm/st/wb/stm32wb55Xg.dtsi @@ -1,5 +1,6 @@ /* * Copyright (c) 2018 Linaro Limited + * Copyright (c) 2024 STMicroelectronics * * SPDX-License-Identifier: Apache-2.0 */ @@ -19,3 +20,20 @@ }; }; }; + +&pwr { + wkup-pin@2 { + reg = <0x2>; + wkup-gpios = <&gpioc 13 STM32_PWR_WKUP_PIN_SRC_0>; + }; + + wkup-pin@3 { + reg = <0x3>; + wkup-gpios = <&gpioc 12 STM32_PWR_WKUP_PIN_SRC_0>; + }; + + wkup-pin@5 { + reg = <0x5>; + wkup-gpios = <&gpioc 5 STM32_PWR_WKUP_PIN_SRC_0>; + }; +}; diff --git a/dts/arm/st/wl/stm32wl.dtsi b/dts/arm/st/wl/stm32wl.dtsi index 9ef2a41969a67..fae199c6f6302 100644 --- a/dts/arm/st/wl/stm32wl.dtsi +++ b/dts/arm/st/wl/stm32wl.dtsi @@ -15,6 +15,7 @@ #include #include #include +#include #include / { @@ -498,6 +499,34 @@ dma-requests= <38>; status = "disabled"; }; + + pwr: power@58000400 { + compatible = "st,stm32-pwr"; + reg = <0x58000400 0x400>; /* PWR register bank */ + status = "disabled"; + + wkup-pins-nb = <3>; /* 3 system wake-up pins */ + wkup-pins-pol; + wkup-pins-pupd; + + #address-cells = <1>; + #size-cells = <0>; + + wkup-pin@1 { + reg = <0x1>; + wkup-gpios = <&gpioa 0 STM32_PWR_WKUP_PIN_SRC_0>; + }; + + wkup-pin@2 { + reg = <0x2>; + wkup-gpios = <&gpioc 13 STM32_PWR_WKUP_PIN_SRC_0>; + }; + + wkup-pin@3 { + reg = <0x3>; + wkup-gpios = <&gpiob 3 STM32_PWR_WKUP_PIN_SRC_0>; + }; + }; }; die_temp: dietemp { From ae17e480360e0762084e45d8b904af2339eb971e Mon Sep 17 00:00:00 2001 From: Abderrahmane Jarmouni Date: Tue, 21 May 2024 02:33:10 +0200 Subject: [PATCH 1835/2849] soc: st: stm32: common: introduce a wake-up pins driver Implement GPIO pins configuration as sources for STM32 PWR wake-up pins behind the scenes exclusively from devicetree information for all series using the public stm32_pwr_wkup_pin_cfg_gpio() function. Introduce macros for parsing & storing DT wake-up pins config in C structs. Introduce user-configurable STM32_WKUP_PINS Kconfig flag. Signed-off-by: Abderrahmane Jarmouni --- soc/st/stm32/Kconfig | 6 + soc/st/stm32/common/CMakeLists.txt | 4 + soc/st/stm32/common/stm32_wkup_pins.c | 348 ++++++++++++++++++++++++++ soc/st/stm32/common/stm32_wkup_pins.h | 86 +++++++ 4 files changed, 444 insertions(+) create mode 100644 soc/st/stm32/common/stm32_wkup_pins.c create mode 100644 soc/st/stm32/common/stm32_wkup_pins.h diff --git a/soc/st/stm32/Kconfig b/soc/st/stm32/Kconfig index 5b299239b8405..9c2d29ca202ec 100644 --- a/soc/st/stm32/Kconfig +++ b/soc/st/stm32/Kconfig @@ -50,6 +50,12 @@ config SWJ_ANALOG_PRIORITY config STM32_FLASH_PREFETCH bool "Flash prefetch buffer" +config STM32_WKUP_PINS + bool "STM32 PWR Wake-up Pins" + depends on DT_HAS_ST_STM32_PWR_ENABLED + help + Enable support for STM32 PWR wake-up pins. + choice POWER_SUPPLY_CHOICE prompt "STM32 power supply configuration" default POWER_SUPPLY_LDO diff --git a/soc/st/stm32/common/CMakeLists.txt b/soc/st/stm32/common/CMakeLists.txt index 0df733452e204..3ff3d1f5d6f64 100644 --- a/soc/st/stm32/common/CMakeLists.txt +++ b/soc/st/stm32/common/CMakeLists.txt @@ -15,3 +15,7 @@ zephyr_linker_sources_ifdef(CONFIG_STM32_BACKUP_SRAM SECTIONS stm32_backup_sram. if (NOT CONFIG_DEBUG AND CONFIG_PM) zephyr_sources_ifdef(CONFIG_DT_HAS_SWJ_CONNECTOR_ENABLED pm_debug_swj.c) endif() + +if (CONFIG_STM32_WKUP_PINS) + zephyr_sources(stm32_wkup_pins.c) +endif() diff --git a/soc/st/stm32/common/stm32_wkup_pins.c b/soc/st/stm32/common/stm32_wkup_pins.c new file mode 100644 index 0000000000000..23a2d2a80f00d --- /dev/null +++ b/soc/st/stm32/common/stm32_wkup_pins.c @@ -0,0 +1,348 @@ +/* + * Copyright (c) 2024 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +#include "stm32_wkup_pins.h" + +#include + +LOG_MODULE_DECLARE(soc, CONFIG_SOC_LOG_LEVEL); + +#define DT_DRV_COMPAT st_stm32_pwr + +#define STM32_PWR_NODE DT_NODELABEL(pwr) + +#define PWR_STM32_MAX_NB_WKUP_PINS DT_INST_PROP(0, wkup_pins_nb) + +#define PWR_STM32_WKUP_PIN_SRCS_NB DT_INST_PROP_OR(0, wkup_pin_srcs, 1) + +#define PWR_STM32_WKUP_PINS_POLARITY DT_INST_PROP_OR(0, wkup_pins_pol, 0) + +#define PWR_STM32_WKUP_PINS_PUPD_CFG DT_INST_PROP_OR(0, wkup_pins_pupd, 0) + +/** @cond INTERNAL_HIDDEN */ + +/** + * @brief flags for wake-up pin polarity configuration + * @{ + */ + +/* detection of wake-up event on the high level : rising edge */ +#define STM32_PWR_WKUP_PIN_P_RISING 0 +/* detection of wake-up event on the low level : falling edge */ +#define STM32_PWR_WKUP_PIN_P_FALLING 1 + +/** @} */ + +/** + * @brief flags for configuration of pull-ups & pull-downs of GPIO ports + * that are associated with wake-up pins + * @{ + */ + +#define STM32_PWR_WKUP_PIN_NOPULL 0 +#define STM32_PWR_WKUP_PIN_PULLUP 1 +#define STM32_PWR_WKUP_PIN_PULLDOWN (1 << 2) + +/** @} */ + +/** + * @brief Structure for storing the devicetree configuration of a wake-up pin. + */ +struct wkup_pin_dt_cfg_t { + /* starts from 1 */ + uint32_t wkup_pin_id; + /* GPIO pin(s) associated with wake-up pin */ + struct gpio_dt_spec gpios_cfgs[PWR_STM32_WKUP_PIN_SRCS_NB]; +}; + +#define WKUP_PIN_NODE_LABEL(i) wkup_pin_##i + +#define WKUP_PIN_NODE_ID_BY_IDX(idx) DT_CHILD(STM32_PWR_NODE, WKUP_PIN_NODE_LABEL(idx)) + +static const struct gpio_dt_spec empty_gpio = {.port = NULL, .pin = 0, .dt_flags = 0}; + +/* cell_idx starts from 0 */ +#define WKUP_PIN_GPIOS_CFG_DT_BY_IDX(cell_idx, node_id) \ + GPIO_DT_SPEC_GET_BY_IDX_OR(node_id, wkup_gpios, cell_idx, empty_gpio) + +#define NB_DEF(i, _) i + +/** + * @brief Get wake-up pin configuration from a given devicetree node. + * + * This returns a static initializer for a struct wkup_pin_dt_cfg_t + * filled with data from a given devicetree node. + * + * @param node_id Devicetree node identifier. + * + * @return Static initializer for a wkup_pin_dt_cfg_t structure. + */ +#define WKUP_PIN_CFG_DT(node_id) \ + { \ + .wkup_pin_id = DT_REG_ADDR(node_id), \ + .gpios_cfgs = \ + { \ + FOR_EACH_FIXED_ARG(WKUP_PIN_GPIOS_CFG_DT_BY_IDX, (,), node_id, \ + LISTIFY(PWR_STM32_WKUP_PIN_SRCS_NB, NB_DEF, (,))) \ + } \ + } + +/* wkup_pin idx starts from 1 */ +#define WKUP_PIN_CFG_DT_BY_IDX(idx) WKUP_PIN_CFG_DT(WKUP_PIN_NODE_ID_BY_IDX(idx)) + +#define PWR_STM32_WKUP_PIN_DEF(i, _) LL_PWR_WAKEUP_PIN##i + +#define WKUP_PIN_CFG_DT_COMMA(wkup_pin_id) WKUP_PIN_CFG_DT(wkup_pin_id), + +/** @endcond */ + +/** + * @brief Structure for passing the runtime configuration of a given wake-up pin. + */ +struct wkup_pin_cfg_t { + uint32_t wkup_pin_id; +#if PWR_STM32_WKUP_PINS_POLARITY + bool polarity; /* True if detection on the low level : falling edge */ +#endif /* PWR_STM32_WKUP_PINS_POLARITY */ +#if PWR_STM32_WKUP_PINS_PUPD_CFG + uint32_t pupd_cfg; /* pull-up/down config of GPIO port associated w/ this wkup pin */ + uint32_t ll_gpio_port; /* GPIO port associated with this wake-up pin */ + uint32_t ll_gpio_pin; /* GPIO pin associated with this wake-up pin */ +#endif /* PWR_STM32_WKUP_PINS_PUPD_CFG */ + uint32_t src_selection; /* The source signal to use with this wake-up pin */ +}; + +/** + * @brief LookUp Table to store LL_PWR_WAKEUP_PINx for each wake-up pin. + */ +static const uint32_t table_wakeup_pins[PWR_STM32_MAX_NB_WKUP_PINS + 1] = { + LISTIFY(PWR_STM32_MAX_NB_WKUP_PINS, PWR_STM32_WKUP_PIN_DEF, (,))}; + +static struct wkup_pin_dt_cfg_t wkup_pins_cfgs[] = { + DT_FOREACH_CHILD(STM32_PWR_NODE, WKUP_PIN_CFG_DT_COMMA)}; + +#if PWR_STM32_WKUP_PINS_PUPD_CFG + +/** + * @brief Array containing pointers to each GPIO port. + * + * Entry will be NULL if the GPIO port is not enabled. + * Also used to get GPIO port index from device ptr, so having + * NULL entries for unused GPIO ports is desired. + */ +static const struct device *const gpio_ports[] = { + DEVICE_DT_GET_OR_NULL(DT_NODELABEL(gpioa)), + DEVICE_DT_GET_OR_NULL(DT_NODELABEL(gpiob)), + DEVICE_DT_GET_OR_NULL(DT_NODELABEL(gpioc)), + DEVICE_DT_GET_OR_NULL(DT_NODELABEL(gpiod)), + DEVICE_DT_GET_OR_NULL(DT_NODELABEL(gpioe)), + DEVICE_DT_GET_OR_NULL(DT_NODELABEL(gpiof)), + DEVICE_DT_GET_OR_NULL(DT_NODELABEL(gpiog)), + DEVICE_DT_GET_OR_NULL(DT_NODELABEL(gpioh)), + DEVICE_DT_GET_OR_NULL(DT_NODELABEL(gpioi)), + DEVICE_DT_GET_OR_NULL(DT_NODELABEL(gpioj)), + DEVICE_DT_GET_OR_NULL(DT_NODELABEL(gpiok)), +}; + +/* Number of GPIO ports. */ +static const size_t gpio_ports_cnt = ARRAY_SIZE(gpio_ports); + +/** + * @brief LookUp Table to store LL_PWR_GPIO_x of each GPIO port. + */ +static const uint32_t table_ll_pwr_gpio_ports[] = { +#ifdef CONFIG_SOC_SERIES_STM32U5X + (uint32_t)LL_PWR_GPIO_PORTA, (uint32_t)LL_PWR_GPIO_PORTB, (uint32_t)LL_PWR_GPIO_PORTC, + (uint32_t)LL_PWR_GPIO_PORTD, (uint32_t)LL_PWR_GPIO_PORTE, (uint32_t)LL_PWR_GPIO_PORTF, + (uint32_t)LL_PWR_GPIO_PORTG, (uint32_t)LL_PWR_GPIO_PORTH, (uint32_t)LL_PWR_GPIO_PORTI, + (uint32_t)LL_PWR_GPIO_PORTJ +#else + LL_PWR_GPIO_A, LL_PWR_GPIO_B, LL_PWR_GPIO_C, LL_PWR_GPIO_D, LL_PWR_GPIO_E, + LL_PWR_GPIO_F, LL_PWR_GPIO_G, LL_PWR_GPIO_H, LL_PWR_GPIO_I, LL_PWR_GPIO_J +#endif /* CONFIG_SOC_SERIES_STM32U5X */ +}; + +static const size_t pwr_ll_gpio_ports_cnt = ARRAY_SIZE(table_ll_pwr_gpio_ports); + +#endif /* PWR_STM32_WKUP_PINS_PUPD_CFG */ + +/** + * @brief Configure & enable a wake-up pin. + * + * @param wakeup_pin_cfg wake-up pin runtime configuration. + * + */ +static void wkup_pin_setup(const struct wkup_pin_cfg_t *wakeup_pin_cfg) +{ + uint32_t wkup_pin_index = wakeup_pin_cfg->wkup_pin_id; + +#if PWR_STM32_WKUP_PINS_POLARITY + /* Set wake-up pin polarity */ + if (wakeup_pin_cfg->polarity == STM32_PWR_WKUP_PIN_P_FALLING) { + LL_PWR_SetWakeUpPinPolarityLow(table_wakeup_pins[wkup_pin_index]); + } else { + LL_PWR_SetWakeUpPinPolarityHigh(table_wakeup_pins[wkup_pin_index]); + } +#endif /* PWR_STM32_WKUP_PINS_POLARITY */ + +#if PWR_STM32_WKUP_PINS_PUPD_CFG + if (wakeup_pin_cfg->pupd_cfg == STM32_PWR_WKUP_PIN_NOPULL) { + LL_PWR_DisableGPIOPullUp(wakeup_pin_cfg->ll_gpio_port, + (1u << wakeup_pin_cfg->ll_gpio_pin)); + LL_PWR_DisableGPIOPullDown(wakeup_pin_cfg->ll_gpio_port, + (1u << wakeup_pin_cfg->ll_gpio_pin)); + + } else if ((wakeup_pin_cfg->pupd_cfg == STM32_PWR_WKUP_PIN_PULLUP) && + wakeup_pin_cfg->ll_gpio_port) { + LL_PWR_EnableGPIOPullUp(wakeup_pin_cfg->ll_gpio_port, + (1u << wakeup_pin_cfg->ll_gpio_pin)); + + } else if ((wakeup_pin_cfg->pupd_cfg == STM32_PWR_WKUP_PIN_PULLDOWN) && + wakeup_pin_cfg->ll_gpio_port) { + LL_PWR_EnableGPIOPullDown(wakeup_pin_cfg->ll_gpio_port, + (1u << wakeup_pin_cfg->ll_gpio_pin)); + } +#endif /* PWR_STM32_WKUP_PINS_PUPD_CFG */ + +#if defined(CONFIG_SOC_SERIES_STM32U5X) || defined(CONFIG_SOC_SERIES_STM32WBAX) + /* Select the proper wake-up signal source */ + if (wakeup_pin_cfg->src_selection & STM32_PWR_WKUP_PIN_SRC_0) { + LL_PWR_SetWakeUpPinSignal0Selection(table_wakeup_pins[wkup_pin_index]); + } else if (wakeup_pin_cfg->src_selection & STM32_PWR_WKUP_PIN_SRC_1) { + LL_PWR_SetWakeUpPinSignal1Selection(table_wakeup_pins[wkup_pin_index]); + } else if (wakeup_pin_cfg->src_selection & STM32_PWR_WKUP_PIN_SRC_2) { + LL_PWR_SetWakeUpPinSignal2Selection(table_wakeup_pins[wkup_pin_index]); + } else { + LL_PWR_SetWakeUpPinSignal3Selection(table_wakeup_pins[wkup_pin_index]); + } +#endif /* CONFIG_SOC_SERIES_STM32U5X or CONFIG_SOC_SERIES_STM32WBAX */ + + LL_PWR_EnableWakeUpPin(table_wakeup_pins[wkup_pin_index]); +} + +/** + * @brief Exported function to configure a given GPIO pin as a source for wake-up pins + * + * @param gpio Container for GPIO pin information specified in devicetree + * + * @return 0 on success, -EINVAL if said GPIO pin is not associated with any wake-up pin. + */ +int stm32_pwr_wkup_pin_cfg_gpio(const struct gpio_dt_spec *gpio) +{ + struct wkup_pin_cfg_t wakeup_pin_cfg; + struct wkup_pin_dt_cfg_t *wkup_pin_dt_cfg; + struct gpio_dt_spec *wkup_pin_gpio_cfg; + bool found_gpio = false; + int i; + int j; + + UNUSED(empty_gpio); + + /* Look for a wake-up pin that has this GPIO pin as a source, if any */ + for (i = 0; i < PWR_STM32_MAX_NB_WKUP_PINS; i++) { + wkup_pin_dt_cfg = &(wkup_pins_cfgs[i]); + for (j = 0; j < PWR_STM32_WKUP_PIN_SRCS_NB; j++) { + wkup_pin_gpio_cfg = &(wkup_pin_dt_cfg->gpios_cfgs[j]); + if (wkup_pin_gpio_cfg->port == gpio->port) { + if (wkup_pin_gpio_cfg->pin == gpio->pin) { + found_gpio = true; + break; + } + } + } + if (found_gpio) { + break; + }; + } + + if (!found_gpio) { + LOG_DBG("Couldn't find a wake-up event correspending to GPIO %s pin %d\n", + gpio->port->name, gpio->pin); + LOG_DBG("=> It cannot be used as a wake-up source\n"); + return -EINVAL; + } + + wakeup_pin_cfg.wkup_pin_id = wkup_pin_dt_cfg->wkup_pin_id; + +/* Each wake-up pin on STM32U5 is associated with 4 wkup srcs, 3 of them correspond to GPIOs. */ +#if defined(CONFIG_SOC_SERIES_STM32U5X) || defined(CONFIG_SOC_SERIES_STM32WBAX) + wakeup_pin_cfg.src_selection = wkup_pin_gpio_cfg->dt_flags & + (STM32_PWR_WKUP_PIN_SRC_0 | + STM32_PWR_WKUP_PIN_SRC_1 | + STM32_PWR_WKUP_PIN_SRC_2); +#else + wakeup_pin_cfg.src_selection = 0; +#endif /* CONFIG_SOC_SERIES_STM32U5X or CONFIG_SOC_SERIES_STM32WBAX */ + +#if PWR_STM32_WKUP_PINS_POLARITY + /* + * get polarity config from GPIO flags specified in device "gpios" property + */ + if (gpio->dt_flags & GPIO_ACTIVE_LOW) { + wakeup_pin_cfg.polarity = STM32_PWR_WKUP_PIN_P_FALLING; + } else { + wakeup_pin_cfg.polarity = STM32_PWR_WKUP_PIN_P_RISING; + } +#endif /* PWR_STM32_WKUP_PINS_POLARITY */ + +#if PWR_STM32_WKUP_PINS_PUPD_CFG + wakeup_pin_cfg.ll_gpio_port = 0; + for (i = 0; i < gpio_ports_cnt; i++) { + if ((gpio_ports[i] == gpio->port) && (i < pwr_ll_gpio_ports_cnt)) { + wakeup_pin_cfg.ll_gpio_port = table_ll_pwr_gpio_ports[i]; + break; + } + } + + wakeup_pin_cfg.ll_gpio_pin = gpio->pin; + + /* + * Get pull-up/down config, if any, from GPIO flags specified in device "gpios" property + */ + if (gpio->dt_flags & GPIO_PULL_UP) { + wakeup_pin_cfg.pupd_cfg = STM32_PWR_WKUP_PIN_PULLUP; + } else if (gpio->dt_flags & GPIO_PULL_DOWN) { + wakeup_pin_cfg.pupd_cfg = STM32_PWR_WKUP_PIN_PULLDOWN; + } else { + wakeup_pin_cfg.pupd_cfg = STM32_PWR_WKUP_PIN_NOPULL; + } +#endif /* PWR_STM32_WKUP_PINS_PUPD_CFG */ + + wkup_pin_setup(&wakeup_pin_cfg); + + return 0; +} + +/** + * @brief Exported function to activate pull-ups/pull-downs configuration of GPIO ports + * associated with wake-up pins. + */ +void stm32_pwr_wkup_pin_cfg_pupd(void) +{ +#if PWR_STM32_WKUP_PINS_PUPD_CFG +#ifdef CONFIG_SOC_SERIES_STM32U5X + LL_PWR_EnablePUPDConfig(); +#else + LL_PWR_EnablePUPDCfg(); +#endif /* CONFIG_SOC_SERIES_STM32U5X */ +#else + return; +#endif /* PWR_STM32_WKUP_PINS_PUPD_CFG */ +} diff --git a/soc/st/stm32/common/stm32_wkup_pins.h b/soc/st/stm32/common/stm32_wkup_pins.h new file mode 100644 index 0000000000000..c8ea75f7eb58a --- /dev/null +++ b/soc/st/stm32/common/stm32_wkup_pins.h @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2024 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * STM32 SoC specific definitions for wake-up pins configuration + */ + +#ifndef ZEPHYR_SOC_ST_STM32_COMMON_STM32_WKUP_PINS_H_ +#define ZEPHYR_SOC_ST_STM32_COMMON_STM32_WKUP_PINS_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/* Some stm32 devices do not have all the LL_PWR_WAKEUP_PINx */ +#define LL_PWR_WAKEUP_PIN0 0 +#ifndef LL_PWR_WAKEUP_PIN3 +#define LL_PWR_WAKEUP_PIN3 0 +#endif /* LL_PWR_WAKEUP_PIN3 */ +#ifndef LL_PWR_WAKEUP_PIN5 +#define LL_PWR_WAKEUP_PIN5 0 +#endif /* LL_PWR_WAKEUP_PIN5 */ +#ifndef LL_PWR_WAKEUP_PIN6 +#define LL_PWR_WAKEUP_PIN6 0 +#endif /* LL_PWR_WAKEUP_PIN6 */ +#ifndef LL_PWR_WAKEUP_PIN7 +#define LL_PWR_WAKEUP_PIN7 0 +#endif /* LL_PWR_WAKEUP_PIN7 */ +#ifndef LL_PWR_WAKEUP_PIN8 +#define LL_PWR_WAKEUP_PIN8 0 +#endif /* LL_PWR_WAKEUP_PIN8 */ + +/* Some stm32 devices do not have all the LL_PWR_GPIO_X */ +#ifndef LL_PWR_GPIO_A +#define LL_PWR_GPIO_A 0 +#endif /* LL_PWR_GPIO_A */ +#ifndef LL_PWR_GPIO_B +#define LL_PWR_GPIO_B 0 +#endif /* LL_PWR_WGPIO_B */ +#ifndef LL_PWR_GPIO_C +#define LL_PWR_GPIO_C 0 +#endif /* LL_PWR_GPIO_C */ +#ifndef LL_PWR_GPIO_D +#define LL_PWR_GPIO_D 0 +#endif /* LL_PWR_GPIO_D */ +#ifndef LL_PWR_GPIO_E +#define LL_PWR_GPIO_E 0 +#endif /* LL_PWR_GPIO_E */ +#ifndef LL_PWR_GPIO_F +#define LL_PWR_GPIO_F 0 +#endif /* LL_PWR_GPIO_F */ +#ifndef LL_PWR_GPIO_G +#define LL_PWR_GPIO_G 0 +#endif /* LL_PWR_GPIO_G */ +#ifndef LL_PWR_GPIO_H +#define LL_PWR_GPIO_H 0 +#endif /* LL_PWR_GPIO_H */ +#ifndef LL_PWR_GPIO_I +#define LL_PWR_GPIO_I 0 +#endif /* LL_PWR_GPIO_I */ +#ifndef LL_PWR_GPIO_J +#define LL_PWR_GPIO_J 0 +#endif /* LL_PWR_GPIO_J */ + +/* Some STM32U5 SoCs do not have all the LL_PWR_GPIO_PORTX */ +#if defined(CONFIG_SOC_SERIES_STM32U5X) +#ifndef LL_PWR_GPIO_PORTF +#define LL_PWR_GPIO_PORTF 0 +#endif /* LL_PWR_GPIO_PORTF */ +#ifndef LL_PWR_GPIO_PORTI +#define LL_PWR_GPIO_PORTI 0 +#endif /* LL_PWR_GPIO_PORTI */ +#ifndef LL_PWR_GPIO_PORTJ +#define LL_PWR_GPIO_PORTJ 0 +#endif /* LL_PWR_GPIO_PORTJ */ +#endif /* CONFIG_SOC_SERIES_STM32U5X */ + +#ifdef __cplusplus +} +#endif + +#endif /* ZEPHYR_SOC_ST_STM32_COMMON_STM32_WKUP_PINS_H_ */ From 559c72d7a63446975d582162f8d460fa29438518 Mon Sep 17 00:00:00 2001 From: Abderrahmane Jarmouni Date: Tue, 21 May 2024 01:31:33 +0200 Subject: [PATCH 1836/2849] include: drivers: misc: introduce stm32 wkup pins public cfg API Introduce public functions for GPIO pins configuration as sources for STM32 PWR wake-up pins, in stm32 drivers & routines such gpio_stm32 & poweroff. Signed-off-by: Abderrahmane Jarmouni --- include/zephyr/drivers/misc/README | 4 ++ .../misc/stm32_wkup_pins/stm32_wkup_pins.h | 40 +++++++++++++++++++ 2 files changed, 44 insertions(+) create mode 100644 include/zephyr/drivers/misc/stm32_wkup_pins/stm32_wkup_pins.h diff --git a/include/zephyr/drivers/misc/README b/include/zephyr/drivers/misc/README index 17a18102f3678..a820cf6340875 100644 --- a/include/zephyr/drivers/misc/README +++ b/include/zephyr/drivers/misc/README @@ -15,3 +15,7 @@ This directory contains header files of the Miscellaneous Drivers. layer graphic operations like widgets, shapes, fonts, text, or bitmaps rendering. These operations are controlled by a vendor-specific API designed for this device. + +* STM32 Wake-up Pins + STM32 wake-up pins are part of the Power Control (PWR) peripheral. + They can be used to wake-up the system from Poweroff through GPIO pins. diff --git a/include/zephyr/drivers/misc/stm32_wkup_pins/stm32_wkup_pins.h b/include/zephyr/drivers/misc/stm32_wkup_pins/stm32_wkup_pins.h new file mode 100644 index 0000000000000..f5b48552e2789 --- /dev/null +++ b/include/zephyr/drivers/misc/stm32_wkup_pins/stm32_wkup_pins.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2024 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * @brief Public APIs for STM32 PWR wake-up pins configuration + */ + +#ifndef ZEPHYR_DRIVERS_MISC_STM32_WKUP_PINS_H_ +#define ZEPHYR_DRIVERS_MISC_STM32_WKUP_PINS_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Configure a GPIO pin as a source for STM32 PWR wake-up pins + * + * @param gpio Container for GPIO pin information specified in devicetree + * + * @return 0 on success, -EINVAL on invalid values + */ +int stm32_pwr_wkup_pin_cfg_gpio(const struct gpio_dt_spec *gpio); + +/** + * @brief Enable or Disable pull-up and pull-down configuration for + * GPIO Ports that are associated with STM32 PWR wake-up pins + */ +void stm32_pwr_wkup_pin_cfg_pupd(void); + +#ifdef __cplusplus +} +#endif + +#endif /* ZEPHYR_DRIVERS_MISC_STM32_WKUP_PINS_H_ */ From efc209b47ffd1b7ee55999beef1d87d296e41534 Mon Sep 17 00:00:00 2001 From: Abderrahmane Jarmouni Date: Tue, 21 May 2024 01:35:31 +0200 Subject: [PATCH 1837/2849] drivers: gpio: stm32: support wkup pins configuration Introduce a custom STM32_GPIO_WKUP GPIO flag. Use the newly introduced stm32_pwr_wkup_pin_cfg_gpio() public function to configure GPIO pins, that have the STM32_GPIO_WKUP flag in DT, as sources for STM32 PWR wake-up pins, on the condition that there is a wake-up pin that corresponds to each of them. These GPIO pins can then be used to power on the system after Poweroff like a reset pin. Signed-off-by: Abderrahmane Jarmouni --- drivers/gpio/gpio_stm32.c | 25 ++++++++++++++++ include/zephyr/dt-bindings/gpio/stm32-gpio.h | 31 ++++++++++++++++++++ 2 files changed, 56 insertions(+) create mode 100644 include/zephyr/dt-bindings/gpio/stm32-gpio.h diff --git a/drivers/gpio/gpio_stm32.c b/drivers/gpio/gpio_stm32.c index d835c3454ccb8..2c3a9fc6ca202 100644 --- a/drivers/gpio/gpio_stm32.c +++ b/drivers/gpio/gpio_stm32.c @@ -22,11 +22,17 @@ #include #include #include +#include +#include #include "stm32_hsem.h" #include "gpio_stm32.h" #include +#include + +LOG_MODULE_REGISTER(stm32, CONFIG_GPIO_LOG_LEVEL); + /** * @brief Common GPIO driver for STM32 MCUs. */ @@ -541,6 +547,25 @@ static int gpio_stm32_config(const struct device *dev, gpio_stm32_configure_raw(dev, pin, pincfg, 0); +#ifdef CONFIG_STM32_WKUP_PINS + if (flags & STM32_GPIO_WKUP) { +#ifdef CONFIG_POWEROFF + struct gpio_dt_spec gpio_dt_cfg = { + .port = dev, + .pin = pin, + .dt_flags = (gpio_dt_flags_t)flags, + }; + + if (stm32_pwr_wkup_pin_cfg_gpio((const struct gpio_dt_spec *)&gpio_dt_cfg)) { + LOG_ERR("Could not configure GPIO %s pin %d as a wake-up source", + gpio_dt_cfg.port->name, gpio_dt_cfg.pin); + } +#else + LOG_DBG("STM32_GPIO_WKUP flag has no effect when CONFIG_POWEROFF=n"); +#endif /* CONFIG_POWEROFF */ + } +#endif /* CONFIG_STM32_WKUP_PINS */ + /* Release clock only if pin is disconnected */ if (((flags & GPIO_OUTPUT) == 0) && ((flags & GPIO_INPUT) == 0)) { err = pm_device_runtime_put(dev); diff --git a/include/zephyr/dt-bindings/gpio/stm32-gpio.h b/include/zephyr/dt-bindings/gpio/stm32-gpio.h new file mode 100644 index 0000000000000..f9a3a4b60af6c --- /dev/null +++ b/include/zephyr/dt-bindings/gpio/stm32-gpio.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2024 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_GPIO_STM32_GPIO_H_ +#define ZEPHYR_INCLUDE_DT_BINDINGS_GPIO_STM32_GPIO_H_ + +/** + * @brief STM32 GPIO specific flags + * + * The driver flags are encoded in the 8 upper bits of @ref gpio_dt_flags_t as + * follows: + * + * - Bit 8: Configure a GPIO pin to power on the system after Poweroff. + * + * @ingroup gpio_interface + * @{ + */ + +/** + * Configures a GPIO pin to power on the system after Poweroff. + * This flag is reserved to GPIO pins that are associated with wake-up pins + * in STM32 PWR devicetree node, through the property "wkup-gpios". + */ +#define STM32_GPIO_WKUP (1 << 8) + +/** @} */ + +#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_GPIO_STM32_GPIO_H_ */ From 323fcf94f966a340b118cf925318dd34a4f5c94d Mon Sep 17 00:00:00 2001 From: Abderrahmane Jarmouni Date: Tue, 21 May 2024 02:47:57 +0200 Subject: [PATCH 1838/2849] soc: st: stm32: complete wkup pins cfg before poweroff Complete wake-up pins configuration before powering off the system when the CONFIG_STM32_WKUP_PINS flag is enabled. Signed-off-by: Abderrahmane Jarmouni --- soc/st/stm32/stm32l4x/poweroff.c | 9 +++++++++ soc/st/stm32/stm32u5x/poweroff.c | 9 +++++++++ soc/st/stm32/stm32wbx/poweroff.c | 7 +++++++ soc/st/stm32/stm32wlx/poweroff.c | 9 +++++++++ 4 files changed, 34 insertions(+) diff --git a/soc/st/stm32/stm32l4x/poweroff.c b/soc/st/stm32/stm32l4x/poweroff.c index b5260dc33cdfb..0b5a9effdd8f2 100644 --- a/soc/st/stm32/stm32l4x/poweroff.c +++ b/soc/st/stm32/stm32l4x/poweroff.c @@ -1,11 +1,14 @@ /* * Copyright (c) 2023 Nordic Semiconductor ASA + * Copyright (c) 2024 STMicroelectronics + * * SPDX-License-Identifier: Apache-2.0 */ #include #include #include +#include #include #include @@ -13,6 +16,12 @@ void z_sys_poweroff(void) { +#ifdef CONFIG_STM32_WKUP_PINS + stm32_pwr_wkup_pin_cfg_pupd(); + + LL_PWR_ClearFlag_WU(); +#endif /* CONFIG_STM32_WKUP_PINS */ + LL_PWR_SetPowerMode(LL_PWR_MODE_SHUTDOWN); LL_LPM_EnableDeepSleep(); LL_DBGMCU_DisableDBGStandbyMode(); diff --git a/soc/st/stm32/stm32u5x/poweroff.c b/soc/st/stm32/stm32u5x/poweroff.c index 191230be5235d..1b2e26c0395c8 100644 --- a/soc/st/stm32/stm32u5x/poweroff.c +++ b/soc/st/stm32/stm32u5x/poweroff.c @@ -1,17 +1,26 @@ /* * Copyright (c) 2023 Nordic Semiconductor ASA + * Copyright (c) 2024 STMicroelectronics + * * SPDX-License-Identifier: Apache-2.0 */ #include #include #include +#include #include #include void z_sys_poweroff(void) { +#ifdef CONFIG_STM32_WKUP_PINS + stm32_pwr_wkup_pin_cfg_pupd(); + + LL_PWR_ClearFlag_WU(); +#endif /* CONFIG_STM32_WKUP_PINS */ + LL_PWR_SetPowerMode(LL_PWR_SHUTDOWN_MODE); LL_LPM_EnableDeepSleep(); diff --git a/soc/st/stm32/stm32wbx/poweroff.c b/soc/st/stm32/stm32wbx/poweroff.c index d95aa24fc0c05..e4319762e8262 100644 --- a/soc/st/stm32/stm32wbx/poweroff.c +++ b/soc/st/stm32/stm32wbx/poweroff.c @@ -1,18 +1,25 @@ /* * Copyright (c) 2023 Nordic Semiconductor ASA + * Copyright (c) 2024 STMicroelectronics + * * SPDX-License-Identifier: Apache-2.0 */ #include #include #include +#include #include #include void z_sys_poweroff(void) { +#ifdef CONFIG_STM32_WKUP_PINS + stm32_pwr_wkup_pin_cfg_pupd(); + LL_PWR_ClearFlag_WU(); +#endif /* CONFIG_STM32_WKUP_PINS */ LL_PWR_SetPowerMode(LL_PWR_MODE_SHUTDOWN); LL_LPM_EnableDeepSleep(); diff --git a/soc/st/stm32/stm32wlx/poweroff.c b/soc/st/stm32/stm32wlx/poweroff.c index 05d516393ea96..e4319762e8262 100644 --- a/soc/st/stm32/stm32wlx/poweroff.c +++ b/soc/st/stm32/stm32wlx/poweroff.c @@ -1,17 +1,26 @@ /* * Copyright (c) 2023 Nordic Semiconductor ASA + * Copyright (c) 2024 STMicroelectronics + * * SPDX-License-Identifier: Apache-2.0 */ #include #include #include +#include #include #include void z_sys_poweroff(void) { +#ifdef CONFIG_STM32_WKUP_PINS + stm32_pwr_wkup_pin_cfg_pupd(); + + LL_PWR_ClearFlag_WU(); +#endif /* CONFIG_STM32_WKUP_PINS */ + LL_PWR_SetPowerMode(LL_PWR_MODE_SHUTDOWN); LL_LPM_EnableDeepSleep(); From 80180188b124713f3d0b5d406d539206cee8873d Mon Sep 17 00:00:00 2001 From: Abderrahmane Jarmouni Date: Mon, 13 May 2024 15:05:49 +0200 Subject: [PATCH 1839/2849] samples: boards: stm32: exit Poweroff using wkup pins & gpios This sample demonstrates how gpio pins can be used to power on the system after a Poweroff, just like a reset pin. The user only needs to add the STM32_GPIO_WKUP flag to the gpio pin in "gpios" property of a DT device such a button or a sensor. The samples Powers off the system after a delay then the user can power it on with the user button that has the STM32_GPIO_WKUP flag in DT. Only works on STM32 boards that support Zephyr POWEROFF (U5, WL, WB, & L4 SoC series), & also have a user button whose GPIO pin is associated with a wake-up pin (see PWR node in SoC dtsi file). Signed-off-by: Abderrahmane Jarmouni --- .../stm32/power_mgmt/wkup_pins/CMakeLists.txt | 7 +++ .../stm32/power_mgmt/wkup_pins/README.rst | 38 +++++++++++++++ .../wkup_pins/boards/nucleo_l4r5zi.overlay | 21 +++++++++ .../wkup_pins/boards/nucleo_u575zi_q.overlay | 21 +++++++++ .../wkup_pins/boards/nucleo_u5a5zj_q.overlay | 21 +++++++++ .../wkup_pins/boards/nucleo_wl55jc.overlay | 21 +++++++++ .../stm32/power_mgmt/wkup_pins/prj.conf | 7 +++ .../stm32/power_mgmt/wkup_pins/sample.yaml | 12 +++++ .../stm32/power_mgmt/wkup_pins/src/main.c | 46 +++++++++++++++++++ 9 files changed, 194 insertions(+) create mode 100644 samples/boards/stm32/power_mgmt/wkup_pins/CMakeLists.txt create mode 100644 samples/boards/stm32/power_mgmt/wkup_pins/README.rst create mode 100644 samples/boards/stm32/power_mgmt/wkup_pins/boards/nucleo_l4r5zi.overlay create mode 100644 samples/boards/stm32/power_mgmt/wkup_pins/boards/nucleo_u575zi_q.overlay create mode 100644 samples/boards/stm32/power_mgmt/wkup_pins/boards/nucleo_u5a5zj_q.overlay create mode 100644 samples/boards/stm32/power_mgmt/wkup_pins/boards/nucleo_wl55jc.overlay create mode 100644 samples/boards/stm32/power_mgmt/wkup_pins/prj.conf create mode 100644 samples/boards/stm32/power_mgmt/wkup_pins/sample.yaml create mode 100644 samples/boards/stm32/power_mgmt/wkup_pins/src/main.c diff --git a/samples/boards/stm32/power_mgmt/wkup_pins/CMakeLists.txt b/samples/boards/stm32/power_mgmt/wkup_pins/CMakeLists.txt new file mode 100644 index 0000000000000..f0d58364d27aa --- /dev/null +++ b/samples/boards/stm32/power_mgmt/wkup_pins/CMakeLists.txt @@ -0,0 +1,7 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(stm32_wkup_pins) + +target_sources(app PRIVATE src/main.c) diff --git a/samples/boards/stm32/power_mgmt/wkup_pins/README.rst b/samples/boards/stm32/power_mgmt/wkup_pins/README.rst new file mode 100644 index 0000000000000..3592ca0da55ee --- /dev/null +++ b/samples/boards/stm32/power_mgmt/wkup_pins/README.rst @@ -0,0 +1,38 @@ +.. _gpio-as-a-wkup-pin-src-sample: + +GPIO As A Wake-up Pin Source +############################ + +Overview +******** + +This sample is a minimum application to demonstrate using a wake-up pin with a GPIO as +a source to power on an STM32 SoC after Poweroff. + +The system will power off automatically ``WAIT_TIME_US`` us after boot. +Press the user button designated in boards's devicetree overlay as "wkup-src" to power it on again. + +.. _gpio-as-a-wkup-pin-src-sample-requirements: + +Requirements +************ + +The SoC should support POWEROFF functionality & have a wake-up pin that corresponds +to the GPIO pin of a user button. +To support another board, add an overlay in boards folder. +Make sure that wake-up pins are configured in SoC dtsi file. + +Building and Running +******************** + +Build and flash wkup_pins as follows, changing ``nucleo_u5a5zj_q`` for your board: + +.. zephyr-app-commands:: + :zephyr-app: samples/boards/stm32/power_mgmt/wkup_pins + :board: nucleo_u5a5zj_q + :goals: build flash + :compact: + +After flashing, the LED in ON. +The LED will be turned off when the system is powered off. +Press the user button to power on the system again. diff --git a/samples/boards/stm32/power_mgmt/wkup_pins/boards/nucleo_l4r5zi.overlay b/samples/boards/stm32/power_mgmt/wkup_pins/boards/nucleo_l4r5zi.overlay new file mode 100644 index 0000000000000..1dbe5efeec802 --- /dev/null +++ b/samples/boards/stm32/power_mgmt/wkup_pins/boards/nucleo_l4r5zi.overlay @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2024 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +/ { + aliases { + wkup-src = &user_button; + }; +}; + +&user_button { + gpios = <&gpioc 13 (GPIO_ACTIVE_HIGH | STM32_GPIO_WKUP)>; +}; + +&pwr { + status = "okay"; +}; diff --git a/samples/boards/stm32/power_mgmt/wkup_pins/boards/nucleo_u575zi_q.overlay b/samples/boards/stm32/power_mgmt/wkup_pins/boards/nucleo_u575zi_q.overlay new file mode 100644 index 0000000000000..1dbe5efeec802 --- /dev/null +++ b/samples/boards/stm32/power_mgmt/wkup_pins/boards/nucleo_u575zi_q.overlay @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2024 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +/ { + aliases { + wkup-src = &user_button; + }; +}; + +&user_button { + gpios = <&gpioc 13 (GPIO_ACTIVE_HIGH | STM32_GPIO_WKUP)>; +}; + +&pwr { + status = "okay"; +}; diff --git a/samples/boards/stm32/power_mgmt/wkup_pins/boards/nucleo_u5a5zj_q.overlay b/samples/boards/stm32/power_mgmt/wkup_pins/boards/nucleo_u5a5zj_q.overlay new file mode 100644 index 0000000000000..1dbe5efeec802 --- /dev/null +++ b/samples/boards/stm32/power_mgmt/wkup_pins/boards/nucleo_u5a5zj_q.overlay @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2024 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +/ { + aliases { + wkup-src = &user_button; + }; +}; + +&user_button { + gpios = <&gpioc 13 (GPIO_ACTIVE_HIGH | STM32_GPIO_WKUP)>; +}; + +&pwr { + status = "okay"; +}; diff --git a/samples/boards/stm32/power_mgmt/wkup_pins/boards/nucleo_wl55jc.overlay b/samples/boards/stm32/power_mgmt/wkup_pins/boards/nucleo_wl55jc.overlay new file mode 100644 index 0000000000000..7182d8a10affb --- /dev/null +++ b/samples/boards/stm32/power_mgmt/wkup_pins/boards/nucleo_wl55jc.overlay @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2024 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +/ { + aliases { + wkup-src = &user_button_1; + }; +}; + +&user_button_1 { + gpios = <&gpioa 0 (GPIO_ACTIVE_LOW | GPIO_PULL_UP | STM32_GPIO_WKUP)>; +}; + +&pwr { + status = "okay"; +}; diff --git a/samples/boards/stm32/power_mgmt/wkup_pins/prj.conf b/samples/boards/stm32/power_mgmt/wkup_pins/prj.conf new file mode 100644 index 0000000000000..1c68aa590c2de --- /dev/null +++ b/samples/boards/stm32/power_mgmt/wkup_pins/prj.conf @@ -0,0 +1,7 @@ +CONFIG_POWEROFF=y +CONFIG_STM32_WKUP_PINS=y +CONFIG_INPUT=y +CONFIG_INPUT_GPIO_KEYS=y +CONFIG_PM=n +CONFIG_PM_DEVICE=n +CONFIG_PM_DEVICE_RUNTIME=n diff --git a/samples/boards/stm32/power_mgmt/wkup_pins/sample.yaml b/samples/boards/stm32/power_mgmt/wkup_pins/sample.yaml new file mode 100644 index 0000000000000..1fb3ead82e729 --- /dev/null +++ b/samples/boards/stm32/power_mgmt/wkup_pins/sample.yaml @@ -0,0 +1,12 @@ +sample: + name: GPIO As A Wake-up Pin Source +tests: + sample.boards.stm32.power_mgmt.wkup_pins: + build_only: true + filter: dt_enabled_alias_with_parent_compat("wkup-src", + "gpio-keys") and dt_compat_enabled("st,stm32-pwr") + platform_allow: + - nucleo_l4r5zi + - nucleo_u575zi_q + - nucleo_u5a5zj_q + - nucleo_wl55jc diff --git a/samples/boards/stm32/power_mgmt/wkup_pins/src/main.c b/samples/boards/stm32/power_mgmt/wkup_pins/src/main.c new file mode 100644 index 0000000000000..cd7d672cdf685 --- /dev/null +++ b/samples/boards/stm32/power_mgmt/wkup_pins/src/main.c @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2024 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include + +#define WAIT_TIME_US 4000000 + +#define WKUP_SRC_NODE DT_ALIAS(wkup_src) +#if !DT_NODE_HAS_STATUS(WKUP_SRC_NODE, okay) +#error "Unsupported board: wkup_src devicetree alias is not defined" +#endif + +static const struct gpio_dt_spec button = GPIO_DT_SPEC_GET(WKUP_SRC_NODE, gpios); + +static const struct gpio_dt_spec led = GPIO_DT_SPEC_GET(DT_ALIAS(led0), gpios); + +int main(void) +{ + __ASSERT_NO_MSG(gpio_is_ready_dt(&button)); + printk("\nWake-up button set up at %s pin %d\n", button.port->name, button.pin); + + __ASSERT_NO_MSG(gpio_is_ready_dt(&led)); + gpio_pin_configure_dt(&led, GPIO_OUTPUT_ACTIVE); + gpio_pin_set(led.port, led.pin, 1); + + printk("Device is ready\n"); + + printk("Will wait %ds before powering the system off\n", (WAIT_TIME_US / 1000000)); + k_busy_wait(WAIT_TIME_US); + + printk("Powering off\n"); + printk("Press the user button to power the system on\n\n"); + + sys_poweroff(); + /* Will remain powered off until wake-up or reset button is pressed */ + + return 0; +} From 9a869ef33ad2c03ebec2c7b63db6fd8b3ba2a82e Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Fri, 31 May 2024 14:54:29 -0700 Subject: [PATCH 1840/2849] arc: pm: Don't use deprecated function Use pm_system_resume instead of z_pm_save_idle_exit Signed-off-by: Flavio Ceolin --- arch/arc/core/isr_wrapper.S | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arc/core/isr_wrapper.S b/arch/arc/core/isr_wrapper.S index 3471e4d73498d..4b486ed926da5 100644 --- a/arch/arc/core/isr_wrapper.S +++ b/arch/arc/core/isr_wrapper.S @@ -26,7 +26,7 @@ GTEXT(_isr_wrapper) GTEXT(_isr_demux) #if defined(CONFIG_PM) -GTEXT(z_pm_save_idle_exit) +GTEXT(pm_system_resume) #endif /* @@ -253,7 +253,7 @@ rirq_path: st 0, [r1, _kernel_offset_to_idle] /* zero idle duration */ PUSHR blink - jl z_pm_save_idle_exit + jl pm_system_resume POPR blink _skip_pm_save_idle_exit: From a3de27fce99e2b9be327a0f727b8376728a8e8c5 Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Fri, 31 May 2024 14:56:03 -0700 Subject: [PATCH 1841/2849] x86: pm: Don't use deprecated function Use pm_system_resume instead of z_pm_save_idle_exit Signed-off-by: Flavio Ceolin --- arch/x86/core/ia32/intstub.S | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/x86/core/ia32/intstub.S b/arch/x86/core/ia32/intstub.S index 0dc08c67c245d..4cd5c0bee9040 100644 --- a/arch/x86/core/ia32/intstub.S +++ b/arch/x86/core/ia32/intstub.S @@ -33,7 +33,7 @@ GTEXT(arch_swap) #ifdef CONFIG_PM - GTEXT(z_pm_save_idle_exit) + GTEXT(pm_system_resume) #endif /** @@ -314,13 +314,13 @@ handle_idle: movl $0, _kernel_offset_to_idle(%ecx) /* - * Beware that a timer driver's z_pm_save_idle_exit() implementation might + * Beware that a timer driver's pm_system_resume() implementation might * expect that interrupts are disabled when invoked. This ensures that * the calculation and programming of the device for the next timer * deadline is not interrupted. */ - call z_pm_save_idle_exit + call pm_system_resume popl %edx popl %eax jmp alreadyOnIntStack From 64b1ac831b37e082057cffadf84e0c17e5dfa924 Mon Sep 17 00:00:00 2001 From: Flavio Ceolin Date: Fri, 31 May 2024 14:56:57 -0700 Subject: [PATCH 1842/2849] arm: pm: Don't use deprecated function Use pm_system_resume instead of z_pm_save_idle_exit Signed-off-by: Flavio Ceolin --- arch/arm/core/cortex_a_r/isr_wrapper.S | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/arm/core/cortex_a_r/isr_wrapper.S b/arch/arm/core/cortex_a_r/isr_wrapper.S index 0cd30e0a34313..56fd111ea3fe4 100644 --- a/arch/arm/core/cortex_a_r/isr_wrapper.S +++ b/arch/arm/core/cortex_a_r/isr_wrapper.S @@ -156,7 +156,7 @@ _vfp_not_enabled: * idle, this ensures that the calculation and programming of the * device for the next timer deadline is not interrupted. For * non-tickless idle, this ensures that the clearing of the kernel idle - * state is not interrupted. In each case, z_pm_save_idle_exit + * state is not interrupted. In each case, pm_system_resume * is called with interrupts disabled. */ @@ -170,7 +170,7 @@ _vfp_not_enabled: movs r1, #0 /* clear kernel idle state */ str r1, [r2, #_kernel_offset_to_idle] - bl z_pm_save_idle_exit + bl pm_system_resume _idle_state_cleared: #endif /* CONFIG_PM */ @@ -269,7 +269,7 @@ SECTION_FUNC(TEXT, _isr_wrapper) * idle, this ensures that the calculation and programming of the * device for the next timer deadline is not interrupted. For * non-tickless idle, this ensures that the clearing of the kernel idle - * state is not interrupted. In each case, z_pm_save_idle_exit + * state is not interrupted. In each case, pm_system_resume * is called with interrupts disabled. */ @@ -283,7 +283,7 @@ SECTION_FUNC(TEXT, _isr_wrapper) movs r1, #0 /* clear kernel idle state */ str r1, [r2, #_kernel_offset_to_idle] - bl z_pm_save_idle_exit + bl pm_system_resume _idle_state_cleared: #endif /* CONFIG_PM */ From eb49f1ba31b7eb1836854f94cbc2d25a03d9d27e Mon Sep 17 00:00:00 2001 From: IBEN EL HADJ MESSAOUD Marwa Date: Fri, 31 May 2024 23:27:11 +0200 Subject: [PATCH 1843/2849] dts: arm: st: add stm32h533Xe support Provide support for STM32H533XE family support Signed-off-by: IBEN EL HADJ MESSAOUD Marwa --- dts/arm/st/h5/stm32h533.dtsi | 12 ++++++++++++ dts/arm/st/h5/stm32h533Xe.dtsi | 35 ++++++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+) create mode 100644 dts/arm/st/h5/stm32h533.dtsi create mode 100644 dts/arm/st/h5/stm32h533Xe.dtsi diff --git a/dts/arm/st/h5/stm32h533.dtsi b/dts/arm/st/h5/stm32h533.dtsi new file mode 100644 index 0000000000000..80c2767e71273 --- /dev/null +++ b/dts/arm/st/h5/stm32h533.dtsi @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2024 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include + +/ { + soc { + compatible = "st,stm32h533", "st,stm32h5", "simple-bus"; + }; +}; diff --git a/dts/arm/st/h5/stm32h533Xe.dtsi b/dts/arm/st/h5/stm32h533Xe.dtsi new file mode 100644 index 0000000000000..7b3b530f6a7ef --- /dev/null +++ b/dts/arm/st/h5/stm32h533Xe.dtsi @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2024 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#include + +/ { + sram1: memory@20000000 { + compatible = "zephyr,memory-region", "mmio-sram"; + reg = <0x20000000 DT_SIZE_K(128)>; + zephyr,memory-region = "SRAM1"; + }; + + sram2: memory@20040000 { + compatible = "zephyr,memory-region", "mmio-sram"; + reg = <0x20040000 DT_SIZE_K(80)>; + zephyr,memory-region = "SRAM2"; + }; + + sram3: memory@20050000 { + compatible = "zephyr,memory-region", "mmio-sram"; + reg = <0x20050000 DT_SIZE_K(64)>; + zephyr,memory-region = "SRAM3"; + }; + + soc { + flash-controller@40022000 { + flash0: flash@8000000 { + reg = <0x08000000 DT_SIZE_K(512)>; + }; + }; + }; +}; From 198cee44d5f489a973b5ea460df691f5fd796eee Mon Sep 17 00:00:00 2001 From: IBEN EL HADJ MESSAOUD Marwa Date: Mon, 3 Jun 2024 09:40:44 +0200 Subject: [PATCH 1844/2849] dts: arm: st: h5: Add node gpiof Add the node gpiof to the stm32h5 dtsi file. Signed-off-by: IBEN EL HADJ MESSAOUD Marwa --- dts/arm/st/h5/stm32h533.dtsi | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/dts/arm/st/h5/stm32h533.dtsi b/dts/arm/st/h5/stm32h533.dtsi index 80c2767e71273..bd781b87cd9cd 100644 --- a/dts/arm/st/h5/stm32h533.dtsi +++ b/dts/arm/st/h5/stm32h533.dtsi @@ -8,5 +8,13 @@ / { soc { compatible = "st,stm32h533", "st,stm32h5", "simple-bus"; + + gpiof: gpio@42021400 { + compatible = "st,stm32-gpio"; + gpio-controller; + #gpio-cells = <2>; + reg = <0x42021400 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_AHB2 0x00000080>; + }; }; }; From 413eb8ad1d4f23c88e573d93eaa789f85dc61064 Mon Sep 17 00:00:00 2001 From: IBEN EL HADJ MESSAOUD Marwa Date: Tue, 4 Jun 2024 10:55:25 +0200 Subject: [PATCH 1845/2849] tests: drivers: rtc: rtc_api: Add nucleo_h533re Adds necessary overlay nucleo_h533re in rtc_api test case to enables the board. Signed-off-by: IBEN EL HADJ MESSAOUD Marwa --- tests/drivers/rtc/rtc_api/boards/nucleo_h533re.conf | 2 ++ .../drivers/rtc/rtc_api/boards/nucleo_h533re.overlay | 11 +++++++++++ 2 files changed, 13 insertions(+) create mode 100644 tests/drivers/rtc/rtc_api/boards/nucleo_h533re.conf create mode 100644 tests/drivers/rtc/rtc_api/boards/nucleo_h533re.overlay diff --git a/tests/drivers/rtc/rtc_api/boards/nucleo_h533re.conf b/tests/drivers/rtc/rtc_api/boards/nucleo_h533re.conf new file mode 100644 index 0000000000000..8c6c114ee41fa --- /dev/null +++ b/tests/drivers/rtc/rtc_api/boards/nucleo_h533re.conf @@ -0,0 +1,2 @@ +CONFIG_RTC_CALIBRATION=y +CONFIG_RTC_ALARM=y diff --git a/tests/drivers/rtc/rtc_api/boards/nucleo_h533re.overlay b/tests/drivers/rtc/rtc_api/boards/nucleo_h533re.overlay new file mode 100644 index 0000000000000..0ed5c08c87f20 --- /dev/null +++ b/tests/drivers/rtc/rtc_api/boards/nucleo_h533re.overlay @@ -0,0 +1,11 @@ + /* + * Copyright (c) 2024 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + aliases { + rtc = &rtc; + }; +}; From 44a5198a99e2ae2ada1a832c7600810f050986a4 Mon Sep 17 00:00:00 2001 From: IBEN EL HADJ MESSAOUD Marwa Date: Sat, 1 Jun 2024 01:01:53 +0200 Subject: [PATCH 1846/2849] boards: st: add stm32h533re board support Add board support for stm32h533re Signed-off-by: IBEN EL HADJ MESSAOUD Marwa --- boards/st/nucleo_h533re/Kconfig.nucleo_h533re | 5 + .../nucleo_h533re/arduino_r3_connector.dtsi | 38 +++ boards/st/nucleo_h533re/board.cmake | 11 + boards/st/nucleo_h533re/board.yml | 5 + .../nucleo_h533re/doc/img/nucleo_h533re.jpg | Bin 0 -> 90356 bytes boards/st/nucleo_h533re/doc/index.rst | 306 ++++++++++++++++++ boards/st/nucleo_h533re/nucleo_h533re.dts | 137 ++++++++ boards/st/nucleo_h533re/nucleo_h533re.yaml | 17 + .../st/nucleo_h533re/nucleo_h533re_defconfig | 16 + .../st/nucleo_h533re/st_morpho_connector.dtsi | 65 ++++ 10 files changed, 600 insertions(+) create mode 100644 boards/st/nucleo_h533re/Kconfig.nucleo_h533re create mode 100644 boards/st/nucleo_h533re/arduino_r3_connector.dtsi create mode 100644 boards/st/nucleo_h533re/board.cmake create mode 100644 boards/st/nucleo_h533re/board.yml create mode 100644 boards/st/nucleo_h533re/doc/img/nucleo_h533re.jpg create mode 100644 boards/st/nucleo_h533re/doc/index.rst create mode 100644 boards/st/nucleo_h533re/nucleo_h533re.dts create mode 100644 boards/st/nucleo_h533re/nucleo_h533re.yaml create mode 100644 boards/st/nucleo_h533re/nucleo_h533re_defconfig create mode 100644 boards/st/nucleo_h533re/st_morpho_connector.dtsi diff --git a/boards/st/nucleo_h533re/Kconfig.nucleo_h533re b/boards/st/nucleo_h533re/Kconfig.nucleo_h533re new file mode 100644 index 0000000000000..3d48952fb5896 --- /dev/null +++ b/boards/st/nucleo_h533re/Kconfig.nucleo_h533re @@ -0,0 +1,5 @@ +# Copyright (c) 2024 STMicroelectronics +# SPDX-License-Identifier: Apache-2.0 + +config BOARD_NUCLEO_H533RE + select SOC_STM32H533XX diff --git a/boards/st/nucleo_h533re/arduino_r3_connector.dtsi b/boards/st/nucleo_h533re/arduino_r3_connector.dtsi new file mode 100644 index 0000000000000..15bb1aab0bf5e --- /dev/null +++ b/boards/st/nucleo_h533re/arduino_r3_connector.dtsi @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2024 STMicroelectronics + * + * 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 &gpioa 0 0>, /* A0 */ + <1 0 &gpioa 1 0>, /* A1 */ + <2 0 &gpiob 1 0>, /* A2 */ + <3 0 &gpiob 0 0>, /* A3 */ + <4 0 &gpioc 1 0>, /* A4 */ + <5 0 &gpioc 0 0>, /* A5 */ + <6 0 &gpiob 15 0>, /* D0 */ + <7 0 &gpiob 14 0>, /* D1 */ + <8 0 &gpioc 8 0>, /* D2 */ + <9 0 &gpiob 3 0>, /* D3 */ + <10 0 &gpiob 5 0>, /* D4 */ + <11 0 &gpiob 4 0>, /* D5 */ + <12 0 &gpiob 10 0>, /* D6 */ + <13 0 &gpioa 8 0>, /* D7 */ + <14 0 &gpioc 7 0>, /* D8 */ + <15 0 &gpioc 6 0>, /* D9 */ + <16 0 &gpioc 9 0>, /* D10 */ + <17 0 &gpioa 7 0>, /* D11 */ + <18 0 &gpioa 6 0>, /* D12 */ + <19 0 &gpioa 5 0>, /* D13 */ + <20 0 &gpiob 7 0>, /* D14 */ + <21 0 &gpiob 6 0>; /* D15 */ + }; +}; + +arduino_serial: &usart1 {}; diff --git a/boards/st/nucleo_h533re/board.cmake b/boards/st/nucleo_h533re/board.cmake new file mode 100644 index 0000000000000..cec3a36c40362 --- /dev/null +++ b/boards/st/nucleo_h533re/board.cmake @@ -0,0 +1,11 @@ +# SPDX-License-Identifier: Apache-2.0 + +board_runner_args(stm32cubeprogrammer "--erase" "--port=swd" "--reset-mode=hw") + +board_runner_args(pyocd "--target=stm32h533retx") + +board_runner_args(jlink "--device=STM32H533RE" "--reset-after-load") + +include(${ZEPHYR_BASE}/boards/common/stm32cubeprogrammer.board.cmake) +include(${ZEPHYR_BASE}/boards/common/pyocd.board.cmake) +include(${ZEPHYR_BASE}/boards/common/jlink.board.cmake) diff --git a/boards/st/nucleo_h533re/board.yml b/boards/st/nucleo_h533re/board.yml new file mode 100644 index 0000000000000..4b633011b714a --- /dev/null +++ b/boards/st/nucleo_h533re/board.yml @@ -0,0 +1,5 @@ +board: + name: nucleo_h533re + vendor: st + socs: + - name: stm32h533xx diff --git a/boards/st/nucleo_h533re/doc/img/nucleo_h533re.jpg b/boards/st/nucleo_h533re/doc/img/nucleo_h533re.jpg new file mode 100644 index 0000000000000000000000000000000000000000..aed4a9752f909c8ad9d88c29de883c7c159e7e37 GIT binary patch literal 90356 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